{"_id":"@caesura-io/openai","_rev":"4-02519eb2e584cfa324a5e59cbb6136c7","name":"@caesura-io/openai","dist-tags":{"latest":"0.3.0"},"versions":{"0.1.0":{"name":"@caesura-io/openai","version":"0.1.0","keywords":["caesura","ai","llm","recommendations","openai"],"author":{"name":"Caesura"},"license":"Apache-2.0","_id":"@caesura-io/openai@0.1.0","maintainers":[{"name":"oleksandr_caesura","email":"oleksandr@caesura.io"}],"homepage":"https://github.com/caesura-io/sdk-js/tree/main/packages/openai#readme","bugs":{"url":"https://github.com/caesura-io/sdk-js/issues"},"dist":{"shasum":"f6e1d5bf2fe821781cb7030d3e3940c001e772fe","tarball":"https://registry.npmjs.org/@caesura-io/openai/-/openai-0.1.0.tgz","fileCount":8,"integrity":"sha512-/wA/t0WKuN6WCDcht2yHtrNzIAG9VuNLjrcQ5Nj1KRaROBGzeEV8oCxujgrW8PZVnDvjM2MBXTsZp680A1is0w==","signatures":[{"sig":"MEQCIHMLRJA5Eg8N8yufRqcFxnvsPAhBF2Vpi8u6szz6EhcmAiBOqgUskUK4FRAUMiITEi3savPnq2hiiXiWUKox6Dq6CQ==","keyid":"SHA256:DhQ8wR5APBvFHLF/+Tc+AYvPOdTpcIDqOhxsBHRwC7U"}],"unpackedSize":89741},"main":"./dist/index.cjs","type":"module","types":"./dist/index.d.ts","module":"./dist/index.js","exports":{".":{"types":"./dist/index.d.ts","import":"./dist/index.js","require":"./dist/index.cjs"}},"gitHead":"a6d191d7c094e78cd0a6df5abbac989529262a83","scripts":{"dev":"tsup --watch","test":"vitest run","build":"tsup","typecheck":"tsc --noEmit","test:watch":"vitest"},"_npmUser":{"name":"oleksandr_caesura","email":"oleksandr@caesura.io"},"repository":{"url":"git+https://github.com/caesura-io/sdk-js.git","type":"git","directory":"packages/openai"},"_npmVersion":"11.17.0","description":"Transparent proxy wrapper for the official OpenAI SDK to inject Caesura recommendations.","directories":{},"sideEffects":false,"_nodeVersion":"20.20.0","dependencies":{"@caesura-io/core":"workspace:*"},"publishConfig":{"access":"public","provenance":true},"_hasShrinkwrap":false,"devDependencies":{"tsup":"^8.3.0","openai":"^4.77.0","vitest":"^2.1.2","typescript":"^5.6.2"},"peerDependencies":{"openai":">=4.77.0"},"_npmOperationalInternal":{"tmp":"tmp/openai_0.1.0_1782811302297_0.050857994360800074","host":"s3://npm-registry-packages-npm-production"}},"0.2.0":{"name":"@caesura-io/openai","version":"0.2.0","keywords":["caesura","ai","llm","recommendations","openai"],"author":{"name":"Caesura"},"license":"Apache-2.0","_id":"@caesura-io/openai@0.2.0","maintainers":[{"name":"oleksandr_caesura","email":"oleksandr@caesura.io"}],"homepage":"https://github.com/caesura-io/sdk-js/tree/main/packages/openai#readme","bugs":{"url":"https://github.com/caesura-io/sdk-js/issues"},"dist":{"shasum":"314616ecc9d241d11be692c1fcac852330f90d70","tarball":"https://registry.npmjs.org/@caesura-io/openai/-/openai-0.2.0.tgz","fileCount":9,"integrity":"sha512-K071jdTJH5F6Ue6DRNFSJP4zqBnDBvb5rtxUOxQ634hB9E5MmWp4NFBUlMGLfmhiKPFofR/ug/3iJJ7YamHevw==","signatures":[{"sig":"MEUCIQD1SykFEO6n2ybfBAT4+i1loSPXPepNl8BN10q2T+8c3wIgIOmMjE6axihEXbfPy93HLg9GShcNIvABDu8GUUc6bec=","keyid":"SHA256:DhQ8wR5APBvFHLF/+Tc+AYvPOdTpcIDqOhxsBHRwC7U"}],"attestations":{"url":"https://registry.npmjs.org/-/npm/v1/attestations/@caesura-io%2fopenai@0.2.0","provenance":{"predicateType":"https://slsa.dev/provenance/v1"}},"unpackedSize":101076},"main":"./dist/index.cjs","type":"module","_from":"file:caesura-io-openai-0.2.0.tgz","types":"./dist/index.d.ts","module":"./dist/index.js","exports":{".":{"types":"./dist/index.d.ts","import":"./dist/index.js","require":"./dist/index.cjs"}},"scripts":{"dev":"tsup --watch","test":"vitest run","build":"tsup","typecheck":"tsc --noEmit","test:watch":"vitest"},"_npmUser":{"name":"GitHub Actions","email":"npm-oidc-no-reply@github.com","trustedPublisher":{"id":"github","oidcConfigId":"oidc:84dfb7fb-4a84-47cf-9d91-8ec9dc791c6f"}},"_resolved":"/tmp/a22c802797d44ceb70a71180e2c98250/caesura-io-openai-0.2.0.tgz","_integrity":"sha512-K071jdTJH5F6Ue6DRNFSJP4zqBnDBvb5rtxUOxQ634hB9E5MmWp4NFBUlMGLfmhiKPFofR/ug/3iJJ7YamHevw==","repository":{"url":"git+https://github.com/caesura-io/sdk-js.git","type":"git","directory":"packages/openai"},"_npmVersion":"11.18.0","description":"Transparent proxy wrapper for the official OpenAI SDK to inject Caesura recommendations.","directories":{},"sideEffects":false,"_nodeVersion":"22.23.0","dependencies":{"@caesura-io/core":"0.2.0"},"publishConfig":{"access":"public","provenance":true},"_hasShrinkwrap":false,"devDependencies":{"tsup":"^8.3.0","openai":"^4.77.0","vitest":"^2.1.2","typescript":"^5.6.2"},"peerDependencies":{"openai":">=4.77.0"},"_npmOperationalInternal":{"tmp":"tmp/openai_0.2.0_1782813854772_0.054939105337802996","host":"s3://npm-registry-packages-npm-production"}},"0.2.1":{"name":"@caesura-io/openai","version":"0.2.1","keywords":["caesura","ai","llm","recommendations","openai"],"author":{"name":"Caesura"},"license":"Apache-2.0","_id":"@caesura-io/openai@0.2.1","maintainers":[{"name":"oleksandr_caesura","email":"oleksandr@caesura.io"}],"homepage":"https://github.com/caesura-io/sdk-js/tree/main/packages/openai#readme","bugs":{"url":"https://github.com/caesura-io/sdk-js/issues"},"dist":{"shasum":"fea4c0c8129f7c9d97c6a2252c25671ea87535a0","tarball":"https://registry.npmjs.org/@caesura-io/openai/-/openai-0.2.1.tgz","fileCount":9,"integrity":"sha512-enf5b6/Xsxh3iG0VwotL9dqJhWkDYTJguIEaOGIycvv4z7/OkPLMMj16+113qFZSlkyN++Dc3lX/pEHrTwWz4A==","signatures":[{"sig":"MEUCIQCsrsRQY1F6TQxr3sspb2tT3JMESgi7A/w4Qvhzv7vlmAIgZe0K6WexCVCUMCt92lte9QQQlljHlEztZYVHCiH+dZg=","keyid":"SHA256:DhQ8wR5APBvFHLF/+Tc+AYvPOdTpcIDqOhxsBHRwC7U"}],"attestations":{"url":"https://registry.npmjs.org/-/npm/v1/attestations/@caesura-io%2fopenai@0.2.1","provenance":{"predicateType":"https://slsa.dev/provenance/v1"}},"unpackedSize":101024},"main":"./dist/index.cjs","type":"module","_from":"file:caesura-io-openai-0.2.1.tgz","types":"./dist/index.d.ts","module":"./dist/index.js","exports":{".":{"types":"./dist/index.d.ts","import":"./dist/index.js","require":"./dist/index.cjs"}},"scripts":{"dev":"tsup --watch","test":"vitest run","build":"tsup","typecheck":"tsc --noEmit","test:watch":"vitest"},"_npmUser":{"name":"GitHub Actions","email":"npm-oidc-no-reply@github.com","trustedPublisher":{"id":"github","oidcConfigId":"oidc:84dfb7fb-4a84-47cf-9d91-8ec9dc791c6f"}},"_resolved":"/tmp/e15aab256b0bf7a712bfc711f50908db/caesura-io-openai-0.2.1.tgz","_integrity":"sha512-enf5b6/Xsxh3iG0VwotL9dqJhWkDYTJguIEaOGIycvv4z7/OkPLMMj16+113qFZSlkyN++Dc3lX/pEHrTwWz4A==","repository":{"url":"git+https://github.com/caesura-io/sdk-js.git","type":"git","directory":"packages/openai"},"_npmVersion":"11.18.0","description":"Transparent proxy wrapper for the official OpenAI SDK to inject Caesura recommendations.","directories":{},"sideEffects":false,"_nodeVersion":"22.23.0","dependencies":{"@caesura-io/core":"0.2.0"},"publishConfig":{"access":"public","provenance":true},"_hasShrinkwrap":false,"devDependencies":{"tsup":"^8.3.0","openai":"^4.77.0","vitest":"^2.1.2","typescript":"^5.6.2"},"peerDependencies":{"openai":">=4.77.0"},"_npmOperationalInternal":{"tmp":"tmp/openai_0.2.1_1782815338590_0.8849875062123032","host":"s3://npm-registry-packages-npm-production"}},"0.3.0":{"_id":"@caesura-io/openai@0.3.0","bugs":{"url":"https://github.com/caesura-io/sdk-js/issues"},"dist":{"shasum":"270424def4631793b22050bbd84fcaf0f7f9dedc","tarball":"https://registry.npmjs.org/@caesura-io/openai/-/openai-0.3.0.tgz","fileCount":9,"integrity":"sha512-CZEjCypBZRk0/tTWzuKVgPYvAatGZ5EcK7tPne1C7QD2S733ThP5qwAx7JZtY9Jci1FBvg91tYV6LrMwXkbiHw==","signatures":[{"sig":"MEUCIQCSOi2plV1oP21cDILrTuD3tPa/0fHVQ5ByDxF84Y1RPQIgLt+kZkmyxVZLs1nce+dv48djLxDg/3eMeSZaFg9mUR0=","keyid":"SHA256:DhQ8wR5APBvFHLF/+Tc+AYvPOdTpcIDqOhxsBHRwC7U"},{"keyid":"SHA256:DhQ8wR5APBvFHLF/+Tc+AYvPOdTpcIDqOhxsBHRwC7U","sig":"MEYCIQDkjDnGRRmgLa38v9jOXrsjgifdJHm/qrXQmvhj/r1G/QIhAMkG220czcn5egdxaJw7LxhLIfsFEF+g3HWiWynxDs1a"}],"attestations":{"url":"https://registry.npmjs.org/-/npm/v1/attestations/@caesura-io%2fopenai@0.3.0","provenance":{"predicateType":"https://slsa.dev/provenance/v1"}},"unpackedSize":119889},"main":"./dist/index.cjs","name":"@caesura-io/openai","type":"module","_from":"file:caesura-io-openai-0.3.0.tgz","types":"./dist/index.d.ts","author":{"name":"CaesuraO"},"module":"./dist/index.js","exports":{".":{"import":{"types":"./dist/index.d.ts","default":"./dist/index.js"},"require":{"types":"./dist/index.d.cts","default":"./dist/index.cjs"}}},"license":"Apache-2.0","scripts":{"dev":"tsup --watch","test":"vitest run","build":"tsup","typecheck":"tsc --noEmit","test:watch":"vitest"},"version":"0.3.0","_npmUser":{"name":"GitHub Actions","email":"npm-oidc-no-reply@github.com","trustedPublisher":{"id":"github","oidcConfigId":"84dfb7fb-4a84-47cf-9d91-8ec9dc791c6f"}},"homepage":"https://github.com/caesura-io/sdk-js/tree/main/packages/openai#readme","keywords":["caesura","ai","llm","recommendations","openai"],"_resolved":"/tmp/262e9f755bbcec06b273e4e0d9f5fa35/caesura-io-openai-0.3.0.tgz","_integrity":"sha512-CZEjCypBZRk0/tTWzuKVgPYvAatGZ5EcK7tPne1C7QD2S733ThP5qwAx7JZtY9Jci1FBvg91tYV6LrMwXkbiHw==","repository":{"url":"git+https://github.com/caesura-io/sdk-js.git","type":"git","directory":"packages/openai"},"_npmVersion":"11.21.0","description":"Transparent proxy wrapper for the official OpenAI SDK to inject CaesuraO recommendations.","directories":{},"maintainers":[{"name":"oleksandr_caesura","email":"oleksandr@caesura.io"}],"sideEffects":false,"_nodeVersion":"22.23.3","dependencies":{"@caesura-io/core":"0.3.0"},"publishConfig":{"access":"public","provenance":true},"_hasShrinkwrap":false,"devDependencies":{"tsup":"^8.3.0","openai":"^4.87.3","vitest":"^2.1.2","typescript":"^5.6.2"},"peerDependencies":{"openai":">=4.87.3 <8"},"_npmOperationalInternal":{"host":"s3://npm-registry-packages-npm-production","tmp":"tmp/openai_0.3.0_1790973627500_0.1402000080874668"}}},"time":{"created":"2026-06-30T09:21:42.008Z","modified":"2026-10-02T20:40:27.933Z","0.1.0":"2026-06-30T09:21:42.421Z","0.2.0":"2026-06-30T10:04:14.921Z","0.2.1":"2026-06-30T10:28:58.742Z","0.3.0":"2026-10-02T20:40:27.580Z"},"bugs":{"url":"https://github.com/caesura-io/sdk-js/issues"},"author":{"name":"CaesuraO"},"license":"Apache-2.0","homepage":"https://github.com/caesura-io/sdk-js/tree/main/packages/openai#readme","keywords":["caesura","ai","llm","recommendations","openai"],"repository":{"url":"git+https://github.com/caesura-io/sdk-js.git","type":"git","directory":"packages/openai"},"description":"Transparent proxy wrapper for the official OpenAI SDK to inject CaesuraO recommendations.","maintainers":[{"name":"oleksandr_caesura","email":"oleksandr@caesura.io"}],"readme":"# @caesura-io/openai\n\nAsynchronous, non-blocking recommendation injection for the official [OpenAI Node SDK](https://github.com/openai/openai-node).\n\nCaesuraO listens to your agent's dialogue and pushes short, real-time recommendations (\"analysis\") into the model's context without blocking the conversation. It plugs in as a transparent proxy wrapper around the OpenAI client.\n\n> **Status:** early development. API is not yet stable.\n\n## Install\n\n```bash\nnpm i @caesura-io/openai openai\n```\n\n## Quick start\n\nWrap your existing `OpenAI` client with `createCaesura`. Every call to `responses.create` or `chat.completions.create` is automatically intercepted. All other methods and nested resources pass through untouched.\n\n### Chat Completions\n\n```diff\n import OpenAI from 'openai';\n+import { createCaesura } from '@caesura-io/openai';\n\n-const client = new OpenAI();\n+const client = createCaesura(new OpenAI(), {\n+  autoCreateConversation: true,\n+  // apiKey auto-read from CAESURA_API_KEY if omitted\n+});\n\n const completion = await client.chat.completions.create({\n   model: 'gpt-5.4-mini',\n   messages: conversation,\n+}, {\n+  caesura: { conversationId: sessionId },\n });\n```\n\n### Responses API\n\n```diff\n import OpenAI from 'openai';\n+import { createCaesura } from '@caesura-io/openai';\n\n-const client = new OpenAI();\n+const client = createCaesura(new OpenAI(), {\n+  autoCreateConversation: true,\n+});\n\n const response = await client.responses.create({\n   model: 'gpt-5.4-mini',\n   input: 'Hello agent!',\n+}, {\n+  caesura: { conversationId: sessionId },\n });\n```\n\n## Conversations and persistence\n\n`baseUrl` defaults to `https://api.caesurao.com`. Your account determines the environment;\nmost applications do not need a URL override. `CAESURA_API_KEY` remains unchanged.\n\n`persist` defaults to `true`. Persistence requires a backend conversation ID:\na local label or generated UUID alone does not create a conversation. Choose one of these approaches:\n\n- **Explicit creation (default):** create once, save the returned ID, and reuse it on every turn.\n- **Automatic creation:** set `autoCreateConversation: true` and pass a stable, unique local session label.\n  The SDK creates a backend conversation before its first analysis and reuses it, including after analysis failures.\n  Overlapping observations share the same creation. Empty dialogue and `persist: false` skip creation.\n\nAutomatic creation defaults to `false`. Its local-label mapping is stored in memory by default and\nis lost on eviction, clearing, or restart; use explicit IDs for durable reuse. Use a distinct ID or label\nfor each independent conversation.\n\nIf neither a per-call nor configured ID is supplied, JS uses the shared `\"default\"` session.\nA client serving multiple users must supply distinct IDs or labels.\nCreation failures from `createConversation()` reject its promise;\nautomatic failures go to `onError` and leave the model call running.\n\n```ts\nconst client = createCaesura(new OpenAI(), {});\nconst conversationId = await client.createConversation({\n  name: 'Support session',\n});\n// Save conversationId; reuse it on subsequent calls.\nawait client.responses.create(\n  { model: 'gpt-5.4-mini', input: 'Hello!' },\n  { caesura: { conversationId } },\n);\n```\n\n`createConversation({ name?, calendarId?, eventId? })` calls `POST /api/conversation`\nand returns a validated backend ID string. Set `persist: false` to analyze without backend storage.\nOrdinary SDK analysis requests omit `notifyIntegrations` and do not override the backend's default `callType`.\n\n## Analysis and limits\n\nResponses are preserved as returned: JSON objects, arrays, strings, numbers, booleans, or null,\nand plain text. `{analysis}` renders the complete value; `{analysis.field}` reads the exact object key.\nZero and false are valid guidance. Empty values are not buffered. Only boolean `isSame` or `is_same`\nmetadata suppresses duplicates; deduplication depends on the backend returning that signal.\n\nOnly user and assistant text is analyzed. System/developer instructions, tool metadata/results,\nand reasoning items are excluded. Tool results remain adjacent to their assistant tool calls.\nThe skill prompt stays in system/developer instructions, independently of the analysis injection role.\n\n`send.maxMessages` (default `10`) and `send.maxInputChars` cap the actual outgoing analysis request,\nincluding prior analyses. Newest dialogue has priority; history uses the remaining budget.\nZero disables analysis. `inject.keepLast: 0` disables recommendation injection while retaining history.\nNegative limits are rejected. Model input and caller-owned messages are preserved.\n\n## Reusing injected history\n\nPreviously emitted guidance is tracked per stored conversation by provider role\nand exact rendered text, including older merged blocks. Before analysis and\ninjection, recognized anonymous text-only guidance messages are removed from reused\nhistory; only currently eligible guidance is inserted again. This avoids duplicate\ninjections and removes expired guidance or guidance excluded by `keepLast`.\nNamed messages, explicit speaker indices, tool calls, and multimodal content are\npreserved. Messages with a different provider role are not mistaken for guidance.\nKeep application dialogue separate from injected requests when possible; an\nanonymous message with the same role and exact text as prior SDK guidance is\nindistinguishable after serialization.\n\n## Credit Usage Reporting\n\nYou can request credit-usage metadata on every analyze call and receive the reported value via the `onCreditUsage` callback.\n\n```diff\n+import { createCaesura, createCreditMeter } from '@caesura-io/openai';\n import OpenAI from 'openai';\n+\n+const meter = createCreditMeter();\n\n-const client = new OpenAI();\n+const client = createCaesura(new OpenAI(), {\n+  autoCreateConversation: true,\n+  onCreditUsage: meter.record,\n+});\n\n+// Query credit metrics later\n+console.log('total credits consumed:', meter.total());\n+console.log('credits by conversation:', meter.breakdown());\n+console.log('retained credit events:', meter.events());\n```\n\n> [!NOTE]\n> In `async` mode (default), the `onCreditUsage` callback fires out-of-band as soon as the asynchronous analyze call completes, decoupled from the synchronous OpenAI request resolution.\n\n## Backend message roles and persistence\n\nEvery analysis request sets `currentUser` to `speakerNames.agent` (default `\"Agent\"`).\nThis identifies the guidance recipient even on customer turns; per-message name\noverrides affect only the message, not `currentUser`.\n\n`/api/analyze` uses `speakerRole` for the analysis prompt: both customer and agent\n**dialogue** are sent as `\"user\"`, with identity preserved by `speakerName` and\n`speakerIndex` (`1` for customer, `0` for agent). Explicit indices survive copying\nand trimming. Previous CaesuraO analyses use `\"assistant\"` with index `-1`. JSON-formatted agent dialogue is\nstill dialogue; its content is never used to reclassify it as an analysis.\n\nThe backend persists the last outbound message as the current utterance. The SDK\nkeeps that dialogue message last, even if repeated text matches an earlier\nanalysis anchor. Retained analyses stay before it and use only the remaining\nmessage/character budget. These backend adaptations do not change the original\nroles or messages sent to the model provider.\n\nAnalyses are anchored to the dialogue prefix through the analyzed turn, including\nspeaker names and indices, before SDK send limits are applied. Repeated dialogue\ntherefore keeps its original analysis order, including with\n`placement: \"after-last-analyzed\"`. Pass growing dialogue history to retain those\npositions. If callers edit or remove earlier history, unmatched analyses use the\nlatest-context fallback instead of attaching to another identical utterance.\nBackground analysis snapshots the collected dialogue before awaiting work.\nThe prefix fingerprint uses FNV-1a/64 over UTF-16 code units; it is local occurrence\nmetadata, not a security hash or a backend field.\n\nSimilarity calculation and duplicate suppression are separate: `calculateSimilarities`\ndefaults to `true`, while `similarityThreshold` is omitted unless you configure it.\nCalculating similarities alone does not enable threshold suppression. The SDK forwards\nboth options unchanged and buffers no new guidance when the backend returns boolean\n`isSame: true`; it retains previous guidance and still sends subsequent dialogue turns\nfor analysis and persistence, subject to the configured cadence and in-flight guard.\n\n## Live persistence regression\n\nWith `CAESURA_API_KEY` configured, build the local core and opt into the live test:\n\n```sh\npnpm --filter @caesura-io/core build\nCAESURA_LIVE_TEST=1 pnpm --filter @caesura-io/openai exec vitest run src/persistence.live.test.ts\n```\n\nThis creates one test conversation and runs four real analyses using local SDK sources.\nIt alternates Customer/Agent dialogue with identical text, switches between Responses\nand Chat Completions in background mode, then fetches the conversation and verifies\ntext, names, and indices `[1, 0, 1, 0]`. It awaits each background analysis before sending\nthe next test turn. OpenAI model calls are stubbed; the default suite uses deterministic\nduplicate responses to test guidance retention without backend calls.\n\nSupported OpenAI versions: `>=4.87.3 <8`. CI checks the minimum and newest\nrelease of each supported major with packed declarations and both APIs.\n\n## Text budgets and migration\n\nText parts concatenate without added separators. Character limits count Unicode\ncode points. Newest dialogue takes priority, with a suffix of the oldest retained\nmessage using any remaining space. Whole analyses then use the remaining budget\nnewest-first, stopping when the next analysis cannot fit. Missing-anchor analyses\ncollapse to one latest leading context entry before budgeting. Objects and arrays\nuse compact Unicode-preserving JSON. Provider input remains unchanged.\n\nSee the [migration notes](https://github.com/caesura-io/sdk-js/blob/main/MIGRATION.md)\nfor persistence defaults, default sessions, arbitrary analysis types, and examples.\n","readmeFilename":"README.md"}