{"_id":"@bookingcare/ai","_rev":"8-e9b56296630cff62481f9367e38ce5f0","name":"@bookingcare/ai","dist-tags":{"latest":"0.5.2"},"versions":{"0.1.3":{"name":"@bookingcare/ai","version":"0.1.3","license":"MIT","_id":"@bookingcare/ai@0.1.3","maintainers":[{"name":"nampham1106","email":"nampham11062002@gmail.com"}],"dist":{"shasum":"510398ceeacdbede4848a87111c8bdde9a54917b","tarball":"https://registry.npmjs.org/@bookingcare/ai/-/ai-0.1.3.tgz","fileCount":62,"integrity":"sha512-/Gt6Ku6nYq3kB87h6bq1RJYB+K8Q8n0k/mJ3FNAQt69D6/pTA2lsaQiq1vJ80cLt7GiIv7sQ5XtXCPkoXPdyGA==","signatures":[{"sig":"MEQCID/h/A77LNOntmlo3yMnQhXkWPg8jeZ8HbtR8syPQkvJAiBbTQvJ6JXrIgmJXvMLbXlu01xJKWF39jYP225r0GRE7Q==","keyid":"SHA256:DhQ8wR5APBvFHLF/+Tc+AYvPOdTpcIDqOhxsBHRwC7U"}],"unpackedSize":84266},"main":"./dist/index.js","type":"module","_from":"file:bookingcare-ai-0.1.3.tgz","types":"./dist/index.d.ts","exports":{".":{"types":"./dist/index.d.ts","default":"./dist/index.js"},"./azure-openai":{"types":"./dist/providers/azure-openai.d.ts","default":"./dist/providers/azure-openai.js"}},"scripts":{"dev":"tsc --watch","build":"tsc","clean":"rm -rf dist *.tsbuildinfo","type-check":"tsc --noEmit","generate-models":"tsx scripts/generate-models.ts"},"_npmUser":{"name":"nampham1106","email":"nampham11062002@gmail.com"},"_resolved":"/tmp/7972b2256045e3e3522d7dc612a8cd58/bookingcare-ai-0.1.3.tgz","_integrity":"sha512-/Gt6Ku6nYq3kB87h6bq1RJYB+K8Q8n0k/mJ3FNAQt69D6/pTA2lsaQiq1vJ80cLt7GiIv7sQ5XtXCPkoXPdyGA==","_npmVersion":"10.9.7","description":"Unified LLM API with automatic model discovery, provider configuration, token and cost tracking, and context persistence","directories":{},"_nodeVersion":"22.22.2","dependencies":{"openai":"^6.37.0","partial-json":"^0.1.7","@sinclair/typebox":"^0.34.49"},"_hasShrinkwrap":false,"devDependencies":{"vitest":"^4.1.5","typescript":"^5.8.0","@types/node":"^25.6.2","@repo/tsconfig":"^0.1.3"},"_npmOperationalInternal":{"tmp":"tmp/ai_0.1.3_1778482628248_0.6247614069744207","host":"s3://npm-registry-packages-npm-production"}},"0.2.0":{"name":"@bookingcare/ai","version":"0.2.0","license":"MIT","_id":"@bookingcare/ai@0.2.0","maintainers":[{"name":"nampham1106","email":"nampham11062002@gmail.com"}],"dist":{"shasum":"1ee2e73259311c7db111a3ef94d7805d8aebdad9","tarball":"https://registry.npmjs.org/@bookingcare/ai/-/ai-0.2.0.tgz","fileCount":70,"integrity":"sha512-Y/c4KqgXB5iHtIZ+7cai7TmqlSOndZBQFSH0ey5+ptuBmC7oH/g0fKTmpkJQAwlFvJFYjNJSMvFPQOs2XoeG9A==","signatures":[{"sig":"MEUCIDPqaxa/FpgS35JxGLfyHAAjszV6rGlvsy1Msa4uYHNuAiEAqDi81rUcEuG5z2IkfwoqnwZY+q00d4JBGnKFwWgUE/M=","keyid":"SHA256:DhQ8wR5APBvFHLF/+Tc+AYvPOdTpcIDqOhxsBHRwC7U"}],"unpackedSize":109254},"main":"./dist/index.js","type":"module","types":"./dist/index.d.ts","exports":{".":{"types":"./dist/index.d.ts","default":"./dist/index.js"},"./azure-openai":{"types":"./dist/providers/azure-openai.d.ts","default":"./dist/providers/azure-openai.js"}},"gitHead":"44a011df3231d727f84fe8ab93f8d8f06801de38","scripts":{"dev":"tsc --watch","build":"tsc","clean":"rm -rf dist *.tsbuildinfo","type-check":"tsc --noEmit","generate-models":"tsx scripts/generate-models.ts"},"_npmUser":{"name":"nampham1106","email":"nampham11062002@gmail.com"},"_npmVersion":"10.9.7","description":"Unified LLM API with automatic model discovery, provider configuration, token and cost tracking, and context persistence","directories":{},"_nodeVersion":"22.22.2","dependencies":{"openai":"^6.37.0","partial-json":"^0.1.7","@sinclair/typebox":"^0.34.49"},"_hasShrinkwrap":false,"devDependencies":{"vitest":"^4.1.5","typescript":"^5.8.0","@types/node":"^25.6.2","@bookingcare/tsconfig":"workspace:*"},"_npmOperationalInternal":{"tmp":"tmp/ai_0.2.0_1778654715898_0.284830447212719","host":"s3://npm-registry-packages-npm-production"}},"0.3.0":{"name":"@bookingcare/ai","version":"0.3.0","license":"MIT","_id":"@bookingcare/ai@0.3.0","maintainers":[{"name":"nampham1106","email":"nampham11062002@gmail.com"}],"dist":{"shasum":"e64a5a53ebebcb6db7d270e894a434e9ae5a105f","tarball":"https://registry.npmjs.org/@bookingcare/ai/-/ai-0.3.0.tgz","fileCount":74,"integrity":"sha512-bdgNs3kIV9oy4ffQAbWl3w35tKpSednqAUYAdf4QthMc9tm2h+FvnwU+qP/rusyKRN4hc47LyBdVgr+QsyJj8w==","signatures":[{"sig":"MEUCIQCaTGqWoS2Th3/KZsj+M43ELmchtdhDyJrgatMWESZC1gIgURfU12LGFxaduV0gXL6v2VHRfFhkx6Tmu9pXAI4vQ+Y=","keyid":"SHA256:DhQ8wR5APBvFHLF/+Tc+AYvPOdTpcIDqOhxsBHRwC7U"}],"unpackedSize":124892},"main":"./dist/index.js","type":"module","types":"./dist/index.d.ts","exports":{".":{"types":"./dist/index.d.ts","default":"./dist/index.js"},"./azure-openai":{"types":"./dist/providers/azure-openai.d.ts","default":"./dist/providers/azure-openai.js"}},"gitHead":"aae37561b3c77dd32db84fe0e6d0946166756019","scripts":{"dev":"tsc -p tsconfig.build.json --watch","build":"tsc -p tsconfig.build.json","clean":"rm -rf dist *.tsbuildinfo","type-check":"tsc --noEmit","generate-models":"tsx scripts/generate-models.ts"},"_npmUser":{"name":"nampham1106","email":"nampham11062002@gmail.com"},"_npmVersion":"10.9.7","description":"Unified LLM API with automatic model discovery, provider configuration, token and cost tracking, and context persistence","directories":{},"_nodeVersion":"22.22.2","dependencies":{"openai":"^6.37.0","partial-json":"^0.1.7","@sinclair/typebox":"^0.34.49"},"_hasShrinkwrap":false,"devDependencies":{"vitest":"^4.1.5","typescript":"^5.8.0","@types/node":"^25.6.2","@bookingcare/tsconfig":"workspace:*"},"_npmOperationalInternal":{"tmp":"tmp/ai_0.3.0_1779040411632_0.2599206544480883","host":"s3://npm-registry-packages-npm-production"}},"0.4.0":{"name":"@bookingcare/ai","version":"0.4.0","license":"MIT","_id":"@bookingcare/ai@0.4.0","maintainers":[{"name":"nampham1106","email":"nampham11062002@gmail.com"}],"dist":{"shasum":"6193aa0067294b60a14e48673f48f8e9835da23d","tarball":"https://registry.npmjs.org/@bookingcare/ai/-/ai-0.4.0.tgz","fileCount":74,"integrity":"sha512-R4eRJoC6WsT5G5TDutgEK986ewD9rn7j5oEhHlBCMq8HHCd3nZtAqltHiWxyS1MRnv2+s6X0rEqJm/Fy/GZRjg==","signatures":[{"sig":"MEUCIQC3KzI8ROz2EjY8qa/L85QP8hn38++v/ZTwaS2uoDOScwIgdXq38Niy1jXhK/5dLLpk42N5lWq0zxEY1TLzdGIP/tQ=","keyid":"SHA256:DhQ8wR5APBvFHLF/+Tc+AYvPOdTpcIDqOhxsBHRwC7U"}],"unpackedSize":124887},"main":"./dist/index.js","type":"module","types":"./dist/index.d.ts","exports":{".":{"types":"./dist/index.d.ts","default":"./dist/index.js"},"./azure-openai":{"types":"./dist/providers/azure-openai.d.ts","default":"./dist/providers/azure-openai.js"}},"gitHead":"bec368663b0eb9c5de989cf8053b35d9271cbea4","scripts":{"dev":"tsc -p tsconfig.build.json --watch","build":"tsc -p tsconfig.build.json","clean":"rm -rf dist *.tsbuildinfo","type-check":"tsc --noEmit","generate-models":"tsx scripts/generate-models.ts"},"_npmUser":{"name":"nampham1106","email":"nampham11062002@gmail.com"},"_npmVersion":"10.9.7","description":"Unified LLM API with automatic model discovery, provider configuration, token and cost tracking, and context persistence","directories":{},"_nodeVersion":"22.22.2","dependencies":{"openai":"^6.37.0","partial-json":"^0.1.7","@sinclair/typebox":"^0.34.49"},"_hasShrinkwrap":false,"devDependencies":{"vitest":"^4.1.5","typescript":"^5.8.0","@types/node":"^25.6.2","@bookingcare/tsconfig":"^0.4.0"},"_npmOperationalInternal":{"tmp":"tmp/ai_0.4.0_1779089409402_0.3255092009480991","host":"s3://npm-registry-packages-npm-production"}},"0.4.1":{"name":"@bookingcare/ai","version":"0.4.1","license":"MIT","_id":"@bookingcare/ai@0.4.1","maintainers":[{"name":"nampham1106","email":"nampham11062002@gmail.com"}],"dist":{"shasum":"9e9d0689ecebc625d59b80794d2e874f852e5e58","tarball":"https://registry.npmjs.org/@bookingcare/ai/-/ai-0.4.1.tgz","fileCount":74,"integrity":"sha512-7kWcddO9+Xuv/sYdx4JZOxz+lxVirZkbg3Aagy1JpqrAlSSa/PIeQ5V6VKzBXzFHnT98fu0aERP48zRpeRVlvA==","signatures":[{"sig":"MEYCIQDNWrgLGbE9KZmID38mFg1C/W9YK0h3ahXpiJgC/6OOeAIhAKGfzI+QD+XilW4jwyew5F9PBLKowiOSsKspkRKw74jd","keyid":"SHA256:DhQ8wR5APBvFHLF/+Tc+AYvPOdTpcIDqOhxsBHRwC7U"}],"unpackedSize":117367},"main":"./dist/index.js","type":"module","types":"./dist/index.d.ts","exports":{".":{"types":"./dist/index.d.ts","default":"./dist/index.js"},"./azure-openai":{"types":"./dist/providers/azure-openai.d.ts","default":"./dist/providers/azure-openai.js"}},"gitHead":"2801a0f6c25f83ab7e2f395fb7961d230da65948","scripts":{"dev":"tsc -p tsconfig.build.json --watch","build":"tsc -p tsconfig.build.json","clean":"rm -rf dist *.tsbuildinfo","type-check":"tsc --noEmit","generate-models":"tsx scripts/generate-models.ts"},"_npmUser":{"name":"nampham1106","email":"nampham11062002@gmail.com"},"_npmVersion":"10.9.7","description":"Unified LLM API with automatic model discovery, provider configuration, token and cost tracking, and context persistence","directories":{},"_nodeVersion":"22.22.2","dependencies":{"openai":"^6.37.0","partial-json":"^0.1.7","@sinclair/typebox":"^0.34.49"},"_hasShrinkwrap":false,"devDependencies":{"vitest":"^4.1.5","typescript":"^5.8.0","@types/node":"^25.6.2","@bookingcare/tsconfig":"^0.4.1"},"_npmOperationalInternal":{"tmp":"tmp/ai_0.4.1_1779101837258_0.33714350211674793","host":"s3://npm-registry-packages-npm-production"}},"0.5.0":{"name":"@bookingcare/ai","version":"0.5.0","license":"MIT","_id":"@bookingcare/ai@0.5.0","maintainers":[{"name":"nampham1106","email":"nampham11062002@gmail.com"}],"dist":{"shasum":"a23ecb083d47706a67c0621072588ef8b58d3ee2","tarball":"https://registry.npmjs.org/@bookingcare/ai/-/ai-0.5.0.tgz","fileCount":58,"integrity":"sha512-zRGP5nolOT/OI+KOzo6+DS+b1wrQWFMtL5SMhi3u0WaNOnbXLlvpoO3BJyKOuhys2ZHtEpXe8T+tUsIViMxJeg==","signatures":[{"sig":"MEUCIQC7CHQZULSRNn7QIjpMk6cF/aWK5ffSGl8Oc73hpHJwkwIgIfwew0FBkRCEJpcvx1xfEh3D8Ul3kKn7tW6Fms0TE70=","keyid":"SHA256:DhQ8wR5APBvFHLF/+Tc+AYvPOdTpcIDqOhxsBHRwC7U"}],"unpackedSize":119329},"main":"./dist/index.js","type":"module","types":"./dist/index.d.ts","exports":{".":{"types":"./dist/index.d.ts","default":"./dist/index.js"},"./azure-openai":{"types":"./dist/providers/azure-openai.d.ts","default":"./dist/providers/azure-openai.js"}},"gitHead":"e835c6d211bffee87278c12b69e12cd67b71d9e5","scripts":{"dev":"tsc -p tsconfig.build.json --watch","build":"tsc -p tsconfig.build.json","clean":"rm -rf dist *.tsbuildinfo","type-check":"tsc --noEmit","generate-models":"tsx scripts/generate-models.ts"},"_npmUser":{"name":"nampham1106","email":"nampham11062002@gmail.com"},"_npmVersion":"10.9.7","description":"Unified LLM API with automatic model discovery, provider configuration, token and cost tracking, and context persistence","directories":{},"_nodeVersion":"22.22.2","dependencies":{"openai":"^6.37.0","partial-json":"^0.1.7","@sinclair/typebox":"^0.34.49"},"_hasShrinkwrap":false,"devDependencies":{"vitest":"^4.1.5","typescript":"^5.8.0","@types/node":"^25.6.2","@bookingcare/tsconfig":"^0.5.0"},"_npmOperationalInternal":{"tmp":"tmp/ai_0.5.0_1780549368516_0.03999775616911494","host":"s3://npm-registry-packages-npm-production"}},"0.5.1":{"name":"@bookingcare/ai","version":"0.5.1","license":"MIT","_id":"@bookingcare/ai@0.5.1","maintainers":[{"name":"nampham1106","email":"nampham11062002@gmail.com"}],"dist":{"shasum":"7587692862d7326bb3d92a7c8e45297747fc40d0","tarball":"https://registry.npmjs.org/@bookingcare/ai/-/ai-0.5.1.tgz","fileCount":62,"integrity":"sha512-i658/GYtZB3KOVxINjRYrjpZ7bJL9u/BBj2lbeT3YVsVCtuoRbsF82VRTYD2qSIbY1/nefwnqVLFLksIMO7hTg==","signatures":[{"sig":"MEQCIBvPUc791j1gLm9e6ORdxqbde3dkTK7bEMhSti1UCMuLAiBAzLiCB7w0ZwIMp6+rraqhTNh5D/PpZLSifwADRYZGeg==","keyid":"SHA256:DhQ8wR5APBvFHLF/+Tc+AYvPOdTpcIDqOhxsBHRwC7U"}],"unpackedSize":162884},"main":"./dist/index.js","type":"module","types":"./dist/index.d.ts","exports":{".":{"types":"./dist/index.d.ts","default":"./dist/index.js"},"./azure-openai":{"types":"./dist/providers/azure-openai.d.ts","default":"./dist/providers/azure-openai.js"},"./azure-openai-responses":{"types":"./dist/providers/azure-openai-responses.d.ts","default":"./dist/providers/azure-openai-responses.js"}},"gitHead":"a1f48034cf8bd8b097d1eeb9d04ebf55882a5f61","scripts":{"dev":"tsc -p tsconfig.build.json --watch","build":"tsc -p tsconfig.build.json","clean":"rm -rf dist *.tsbuildinfo","type-check":"tsc --noEmit","generate-models":"tsx scripts/generate-models.ts"},"_npmUser":{"name":"nampham1106","email":"nampham11062002@gmail.com"},"_npmVersion":"10.9.7","description":"Unified LLM API with automatic model discovery, provider configuration, token and cost tracking, and context persistence","directories":{},"_nodeVersion":"22.22.2","dependencies":{"openai":"^6.37.0","partial-json":"^0.1.7","@sinclair/typebox":"^0.34.49"},"_hasShrinkwrap":false,"devDependencies":{"vitest":"^4.1.5","typescript":"^5.8.0","@types/node":"^25.6.2","@bookingcare/tsconfig":"^0.5.1"},"_npmOperationalInternal":{"tmp":"tmp/ai_0.5.1_1781576853599_0.864113744976096","host":"s3://npm-registry-packages-npm-production"}},"0.5.2":{"name":"@bookingcare/ai","version":"0.5.2","description":"Unified LLM API with automatic model discovery, provider configuration, token and cost tracking, and context persistence","license":"MIT","type":"module","main":"./dist/index.js","types":"./dist/index.d.ts","exports":{".":{"types":"./dist/index.d.ts","default":"./dist/index.js"},"./azure-openai":{"types":"./dist/providers/azure-openai.d.ts","default":"./dist/providers/azure-openai.js"},"./azure-openai-responses":{"types":"./dist/providers/azure-openai-responses.d.ts","default":"./dist/providers/azure-openai-responses.js"}},"scripts":{"build":"tsc -p tsconfig.build.json","dev":"tsc -p tsconfig.build.json --watch","clean":"rm -rf dist *.tsbuildinfo","type-check":"tsc --noEmit","generate-models":"tsx scripts/generate-models.ts"},"devDependencies":{"@bookingcare/tsconfig":"^0.5.2","@types/node":"^25.6.2","typescript":"^5.8.0","vitest":"^4.1.5"},"dependencies":{"@sinclair/typebox":"^0.34.49","openai":"^6.37.0","partial-json":"^0.1.7"},"_id":"@bookingcare/ai@0.5.2","gitHead":"f25fe7a5cb6290c989bbc3d12a0fe2dda849c131","_nodeVersion":"22.22.2","_npmVersion":"10.9.7","dist":{"integrity":"sha512-5zsagG8ic0xI36dkD3dWKjhTM4PvBceSZvc382WExA7NpO/E9JHaXCOge2e1DC4LlB4XtVDcXH3mK9s00FPCeA==","shasum":"ea4e17db802cd495c0dfce1fb9569c4e6c083e5b","tarball":"https://registry.npmjs.org/@bookingcare/ai/-/ai-0.5.2.tgz","fileCount":62,"unpackedSize":164055,"signatures":[{"keyid":"SHA256:DhQ8wR5APBvFHLF/+Tc+AYvPOdTpcIDqOhxsBHRwC7U","sig":"MEYCIQDtqQ6VP1X0HDIE9hYu08rQJNynT26wI5rf/txJVk8sRQIhAOdfYf3BQbQqSVbPxmLhYPjRHcaMwtj1rMi+URD4NYcI"}]},"_npmUser":{"name":"nampham1106","email":"nampham11062002@gmail.com"},"directories":{},"maintainers":[{"name":"nampham1106","email":"nampham11062002@gmail.com"}],"_npmOperationalInternal":{"host":"s3://npm-registry-packages-npm-production","tmp":"tmp/ai_0.5.2_1783160119665_0.4800240251281074"},"_hasShrinkwrap":false}},"time":{"created":"2026-05-11T06:57:08.160Z","modified":"2026-07-04T10:15:19.931Z","0.1.3":"2026-05-11T06:57:08.407Z","0.2.0":"2026-05-13T06:45:16.050Z","0.3.0":"2026-05-17T17:53:31.769Z","0.4.0":"2026-05-18T07:30:09.544Z","0.4.1":"2026-05-18T10:57:17.405Z","0.5.0":"2026-06-04T05:02:48.707Z","0.5.1":"2026-06-16T02:27:33.732Z","0.5.2":"2026-07-04T10:15:19.811Z"},"license":"MIT","description":"Unified LLM API with automatic model discovery, provider configuration, token and cost tracking, and context persistence","maintainers":[{"name":"nampham1106","email":"nampham11062002@gmail.com"}],"readme":"# @bookingcare/ai\n\nUnified LLM API with automatic model discovery, provider configuration, token and cost tracking, and simple context persistence and hand-off to other models mid-session.\n\n**Note:** This library only includes models that support tool calling (function calling), as this is essential for agentic workflows.\n\n## Installation\n\n```bash\npnpm add @bookingcare/ai\n```\n\n## Quick Start\n\n```typescript\nimport { getModel, complete, stream, collectStream } from \"@bookingcare/ai\";\nimport type { Context } from \"@bookingcare/ai\";\n\nconst model = getModel(\"gpt-5.4-nano\")!;\n\nconst context: Context = {\n  messages: [\n    { role: \"system\", content: \"You are a helpful assistant.\" },\n    { role: \"user\", content: \"Hello!\", timestamp: Date.now() },\n  ],\n};\n\n// Option 1: Collect the full result at once\nconst result = await complete(model, context);\nconsole.log(result.text);\nconsole.log(result.usage); // { inputTokens: 20, outputTokens: 5 }\nconsole.log(result.cost); // { input: 0.000004, output: 0.000006, total: 0.00001 }\n\n// Option 2: Stream events as they arrive\nconst eventStream = stream(model, context);\nfor await (const event of eventStream) {\n  if (event.type === \"text_delta\") process.stdout.write(event.delta);\n}\n\n// Option 3: Stream then collect\nconst result2 = await collectStream(stream(model, context), model);\n\n// Option 4: Await the final message directly\nconst eventStream2 = stream(model, context);\nconst finalMessage = await eventStream2.result();\n```\n\n## Architecture: Model-Context-Options\n\nAll streaming functions follow a 3-argument pattern:\n\n```typescript\nfunction stream<TApi extends Api>(\n  model: Model<TApi>, // typed model object from the registry\n  context: Context, // { messages, tools? }\n  options?: StreamOptions, // transport-level: temperature, maxTokens, signal, etc.\n): AssistantMessageEventStream;\n```\n\n- **Model** — carries API type, provider, base URL, pricing, and compat overrides. The provider is resolved from `model.api` via the API registry.\n- **Context** — content-level: `{ messages: Message[]; tools?: Tool[] }`. Separates what is being asked from how it is transported.\n- **StreamOptions** — transport-level control: `temperature`, `maxTokens`, `topP`, `stopSequences`, `signal`, `apiKey`, `transport`, `cacheRetention`, `sessionId`, `onPayload`, `onResponse`, `headers`, `timeoutMs`, `maxRetries`, `maxRetryDelayMs`, `reasoningEffort`, `metadata`.\n\nProviders implement `StreamFunction<TApi, TOptions>` — a typed function `(model, context, options?) => AssistantMessageEventStream` that encodes all errors into the stream.\n\n## Streaming vs Collecting\n\nThere are two families of functions:\n\n| Function                                   | Returns                       | Description                                  |\n| ------------------------------------------ | ----------------------------- | -------------------------------------------- |\n| `stream(model, context, options?)`         | `AssistantMessageEventStream` | Stream events in real time                   |\n| `streamSimple(model, context, options?)`   | `AssistantMessageEventStream` | Stream a simple completion                   |\n| `complete(model, context, options?)`       | `Promise<StreamResult>`       | Collect full result (wraps `stream`)         |\n| `completeSimple(model, context, options?)` | `Promise<StreamResult>`       | Collect simple result (wraps `streamSimple`) |\n| `collectStream(eventStream, model?)`       | `Promise<StreamResult>`       | Consume any stream into a result             |\n\n`complete` and `completeSimple` are convenience wrappers that combine streaming and collection in a single call.\n\n## Event Stream\n\nThe `stream()` function returns an `AssistantMessageEventStream` — a push-based async iterable that emits structured `AssistantMessageEvent` events. Every event carries a `partial` field with the current state of the `AssistantMessage` being built, enabling live state inspection.\n\n### Event Protocol\n\nStreams emit `start` before partial updates, then terminate with either `done` (success) or `error`:\n\n| Event            | Fields                                | Description                                     |\n| ---------------- | ------------------------------------- | ----------------------------------------------- |\n| `start`          | `partial`                             | Stream started, first partial message           |\n| `text_start`     | `contentIndex`, `partial`             | Text content block started                      |\n| `text_delta`     | `contentIndex`, `delta`, `partial`    | Text fragment                                   |\n| `text_end`       | `contentIndex`, `content`, `partial`  | Text content block completed                    |\n| `thinking_start` | `contentIndex`, `partial`             | Thinking block started                          |\n| `thinking_delta` | `contentIndex`, `delta`, `partial`    | Thinking fragment                               |\n| `thinking_end`   | `contentIndex`, `content`, `partial`  | Thinking block completed                        |\n| `toolcall_start` | `contentIndex`, `partial`             | Tool call started                               |\n| `toolcall_delta` | `contentIndex`, `delta`, `partial`    | Tool call argument fragment                     |\n| `toolcall_end`   | `contentIndex`, `toolCall`, `partial` | Tool call completed with full `ToolCall` object |\n| `done`           | `reason`, `message`                   | Stream completed successfully                   |\n| `error`          | `reason`, `error`                     | Stream ended with error                         |\n\n### EventStream API\n\nThe `AssistantMessageEventStream` extends the generic `EventStream<T, R>` class:\n\n```typescript\nconst eventStream = stream(model, context);\n\n// Iterate events as they arrive\nfor await (const event of eventStream) {\n  if (event.type === \"text_delta\") process.stdout.write(event.delta);\n}\n\n// Or await the final AssistantMessage directly\nconst message = await eventStream.result();\n```\n\n## Tool Calling\n\n```typescript\nimport { getModel, complete, type Context } from \"@bookingcare/ai\";\n\nconst model = getModel(\"gpt-5.4-nano\")!;\n\nconst context: Context = {\n  messages: [{ role: \"user\", content: \"What's the weather in Tokyo?\", timestamp: Date.now() }],\n  tools: [\n    {\n      name: \"get_weather\",\n      description: \"Get the current weather in a city\",\n      parameters: {\n        type: \"object\",\n        properties: {\n          city: { type: \"string\", description: \"City name\" },\n        },\n        required: [\"city\"],\n      },\n    },\n  ],\n};\n\nconst result = await complete(model, context);\n\nif (result.stopReason === \"toolUse\") {\n  const call = result.toolCalls[0];\n  console.log(call.name); // \"get_weather\"\n  console.log(call.arguments); // '{\"city\":\"Tokyo\"}'\n}\n```\n\n### Typed Tool Definitions\n\nUse the `tool()` helper with TypeBox schemas for end-to-end type safety:\n\n```typescript\nimport { Type, Static, tool } from \"@bookingcare/ai\";\n\nconst GetWeatherParams = Type.Object({\n  city: Type.String({ description: \"City name\" }),\n  unit: Type.Optional(Type.Union([Type.Literal(\"celsius\"), Type.Literal(\"fahrenheit\")])),\n});\n\nconst getWeather = tool({\n  name: \"get_weather\",\n  description: \"Get the current weather in a city\",\n  parameters: GetWeatherParams,\n});\n\ntype WeatherArgs = Static<typeof getWeather.parameters>;\n// { city: string; unit?: \"celsius\" | \"fahrenheit\" }\n```\n\n## Conversation & Model Hand-off\n\n```typescript\nimport { getModel, Conversation, stream } from \"@bookingcare/ai\";\n\nconst model = getModel(\"gpt-5.4-nano\")!;\n\nconst conv = new Conversation();\nconv.addSystemMessage(\"You are a helpful assistant.\");\nconv.addUserMessage(\"Explain quantum computing briefly.\");\n\n// First turn\nconst events1 = stream(model, conv.toContext());\nawait conv.addAssistantResponse(events1, model);\n\n// Second turn\nconv.addUserMessage(\"Summarize that in one sentence.\");\nconst events2 = stream(model, conv.toContext());\nawait conv.addAssistantResponse(events2, model);\n\n// Track accumulated usage and cost\nconsole.log(conv.totalUsage);\nconsole.log(conv.getTotalCost(model));\n\n// Add tool results\nconv.addToolResult(\"call_123\", \"get_weather\", [{ type: \"text\", text: \"Sunny, 22\\u00B0C\" }]);\n\n// Persist conversation\nconst json = conv.toJSON();\nconst restored = Conversation.fromJSON(json);\n```\n\n## Model Discovery\n\n```typescript\nimport { listModels, getModel, getModelsByProvider } from \"@bookingcare/ai\";\n\n// All models\nconst models = listModels();\n\n// Look up a specific model (returns undefined if not found)\nconst model = getModel(\"gpt-5.4-nano\");\n\n// Filter by provider\nconst azureModels = getModelsByProvider(\"azure-openai\");\n```\n\n## Providers\n\nProviders implement the `ApiProvider<TApi, TOptions>` interface and register via `registerApiProvider()`. Each provider declares:\n\n- `api` — the API type string (e.g. `\"azure-openai-completions\"`)\n- `stream` — a `StreamFunction<TApi, TOptions>` for streaming completions\n- `streamSimple` — a `StreamFunction<TApi, SimpleStreamOptions>` for simple completions\n\nThe `StreamFunction` contract guarantees that all errors are encoded into the returned stream (never thrown), with `stopReason: \"error\" | \"aborted\"` and an `errorMessage`.\n\n### Azure OpenAI\n\nConfigure via environment variables:\n\n```bash\nAZURE_OPENAI_ENDPOINT=https://your-resource.openai.azure.com\nAZURE_OPENAI_API_KEY=your-api-key\nAZURE_OPENAI_API_VERSION=2024-12-01-preview  # optional for Chat Completions\n```\n\nThe model name in `getModel()` maps to your Azure deployment name. Create deployments named `gpt-5.4`, `gpt-5.4-mini`, `gpt-5.4-nano`, etc. to match the model registry.\n\nGPT-5.4 models use Azure OpenAI Responses API by default. For reasoning models, pass `reasoningEffort` to control `reasoning.effort` (`\"low\"`, `\"medium\"`, `\"high\"`, etc.) and `reasoningSummary: \"auto\"` to stream reasoning summaries as `thinking_delta` events. Raw reasoning tokens are not emitted by the API; they are counted as output tokens in usage and exposed as `usage.reasoningTokens` when the provider reports them.\n\n#### Supported Models\n\n| Model        | Context Window | Max Output | Vision | Reasoning | Price (in/out per 1M tokens) |\n| ------------ | -------------- | ---------- | ------ | --------- | ---------------------------- |\n| gpt-5.4      | 1,050,000      | 128,000    | Yes    | Yes       | $2.50 / $15.00               |\n| gpt-5.4-mini | 400,000        | 128,000    | Yes    | Yes       | $0.75 / $4.50                |\n| gpt-5.4-nano | 400,000        | 128,000    | Yes    | Yes       | $0.20 / $1.25                |\n\n`gpt-5.4` pricing uses Azure's standard Global rate for prompts under 272k input tokens; Azure applies higher long-context rates above that threshold.\n\n## Content Type Guards\n\nUtility functions for narrowing content types:\n\n```typescript\nimport { isTextContent, isImageContent, isToolCall } from \"@bookingcare/ai\";\n\n// Check content parts\nif (isTextContent(part)) {\n  console.log(part.text);\n}\n\n// Check tool calls\nif (isToolCall(someValue)) {\n  console.log(someValue.name, someValue.arguments);\n}\n```\n\n## API Reference\n\n### `stream(model, context, options?): AssistantMessageEventStream`\n\nStart a streaming completion. Provider auto-detected from the model's API type.\n\n### `streamSimple(model, context, options?): AssistantMessageEventStream`\n\nStream a simple completion. Same signature as `stream()`.\n\n### `complete(model, context, options?): Promise<StreamResult>`\n\nGenerate a completion, collecting the full result. Convenience wrapper around `stream` + `collectStream`.\n\n### `completeSimple(model, context, options?): Promise<StreamResult>`\n\nGenerate a simple completion, collecting the full result. Convenience wrapper around `streamSimple` + `collectStream`.\n\n### `collectStream(eventStream, model?): Promise<StreamResult>`\n\nConsume a stream into a single result with text, tool calls, usage, and optional cost. Cost is calculated only when a `model` is provided.\n\n### `Conversation`\n\nManages message history, tracks usage, supports serialization and model hand-off. Use `toContext(tools?)` to get a `Context` object for passing to `stream()`.\n\n### `tool(def): Tool<TParams>`\n\nDefine a tool with a TypeBox schema for type-safe parameters.\n\n### `calculateCost(usage, model): Cost`\n\nCalculate cost from token usage and model pricing.\n\n### `getModel(id): Model | undefined`\n\nLook up a model by ID.\n\n### `listModels(): Model[]`\n\nList all registered models.\n\n### `getModelsByProvider(provider): Model[]`\n\nList models filtered by provider name.\n\n### `registerApiProvider(provider, sourceId?): void`\n\nRegister a typed API provider. `provider` must be an `ApiProvider<TApi, TOptions>` with `api`, `stream`, and `streamSimple` fields. Optional `sourceId` enables batch removal via `unregisterApiProviders()`.\n\n### `getApiProvider(api): ApiProviderInternal | undefined`\n\nLook up a registered provider by API type.\n\n### `getApiProviders(): ApiProviderInternal[]`\n\nList all registered API providers.\n\n### `unregisterApiProviders(sourceId): void`\n\nRemove all providers registered with the given `sourceId`.\n\n### `clearApiProviders(): void`\n\nRemove all registered providers.\n\n### `isTextContent(content): boolean`\n\nType guard for `TextContent`.\n\n### `isImageContent(content): boolean`\n\nType guard for `ImageContent`.\n\n### `isToolCall(value): boolean`\n\nType guard for `ToolCall`.\n\n### `EventStream<T, R>`\n\nGeneric push-based async iterable with a typed final result. Call `push()` to emit events, `end()` to close, and `result()` to await the final value.\n\n### `AssistantMessageEventStream`\n\nExtends `EventStream<AssistantMessageEvent, AssistantMessage>`. The standard return type for all streaming functions.\n\n### `createAssistantMessageEventStream(): AssistantMessageEventStream`\n\nFactory function to create a new event stream instance.\n","readmeFilename":"README.md"}