{"_id":"@countly/ai-sdk-llamaindex","_rev":"4-ce5ebe7496ef0e0796ddab9660ad1af8","name":"@countly/ai-sdk-llamaindex","dist-tags":{"latest":"0.0.6"},"versions":{"0.0.3":{"name":"@countly/ai-sdk-llamaindex","version":"0.0.3","_id":"@countly/ai-sdk-llamaindex@0.0.3","maintainers":[{"name":"mksglu","email":"code.bm.ksglu@gmail.com"}],"dist":{"shasum":"8e2405d421dd0d8387322338a257d79060db9413","tarball":"https://registry.npmjs.org/@countly/ai-sdk-llamaindex/-/ai-sdk-llamaindex-0.0.3.tgz","fileCount":10,"integrity":"sha512-8AtvPCrVOQK8DjjayULwWq5Zm7Rl5dmRc47CebQSydTflvxr1DPhQIbu+IX+ohWWNbgF1SCyH47JKqApK7zbfA==","signatures":[{"sig":"MEUCIQCwoL43V7E0+HZuekYHF8FvdVTHFHKAQJCgdlCiixET2gIgcBQE8FJl75QuVeLNeCIFOpslKZk/ry8jlh6CiCdY+yc=","keyid":"SHA256:DhQ8wR5APBvFHLF/+Tc+AYvPOdTpcIDqOhxsBHRwC7U"}],"unpackedSize":23782},"type":"module","_from":"file:countly-ai-sdk-llamaindex-0.0.3.tgz","exports":{".":{"types":"./dist/index.d.ts","import":"./dist/index.js"}},"scripts":{"dev":"tsc --project tsconfig.build.json --watch","lint":"tsc --noEmit","test":"vitest run","build":"tsc --project tsconfig.build.json"},"_npmUser":{"name":"mksglu","email":"code.bm.ksglu@gmail.com"},"_resolved":"/private/var/folders/df/nbmn_hp51n177rvbz8zh44sh0000gn/T/c0088682439e83416a94870c4d2b8e2e/countly-ai-sdk-llamaindex-0.0.3.tgz","_integrity":"sha512-8AtvPCrVOQK8DjjayULwWq5Zm7Rl5dmRc47CebQSydTflvxr1DPhQIbu+IX+ohWWNbgF1SCyH47JKqApK7zbfA==","_npmVersion":"11.12.1","description":"Countly AI observability adapter for LlamaIndex","directories":{},"_nodeVersion":"24.15.0","dependencies":{"@countly/ai-sdk-core":"0.0.3"},"publishConfig":{"access":"public"},"_hasShrinkwrap":false,"devDependencies":{"typescript":"^5.8.3","@countly/ai-sdk-tsconfig":"0.0.0"},"peerDependencies":{"llamaindex":">=0.8.0"},"peerDependenciesMeta":{"llamaindex":{"optional":false}},"_npmOperationalInternal":{"tmp":"tmp/ai-sdk-llamaindex_0.0.3_1783443618915_0.9447297893780402","host":"s3://npm-registry-packages-npm-production"}},"0.0.4":{"name":"@countly/ai-sdk-llamaindex","version":"0.0.4","_id":"@countly/ai-sdk-llamaindex@0.0.4","maintainers":[{"name":"mksglu","email":"code.bm.ksglu@gmail.com"}],"dist":{"shasum":"0e834dabf906d9199687fcd667d5ec54556f9a0c","tarball":"https://registry.npmjs.org/@countly/ai-sdk-llamaindex/-/ai-sdk-llamaindex-0.0.4.tgz","fileCount":10,"integrity":"sha512-KIpEpYnbkWP1kUNQCDz40iuC/+XE9EUTmg9y3bNFA6pb5y3vGISdycIO321DC9PgLLEzZMqjcDQtrpzIswMFAA==","signatures":[{"sig":"MEUCIQDp/h0XZNB+VPiiNAHV5UJ02p/9ApTJOlytIVJVuF39mQIgUlVg1AwhyKVVOgKLnSS6mqVeKZi3FCDQiXOELz41y1s=","keyid":"SHA256:DhQ8wR5APBvFHLF/+Tc+AYvPOdTpcIDqOhxsBHRwC7U"}],"unpackedSize":29113},"type":"module","_from":"file:countly-ai-sdk-llamaindex-0.0.4.tgz","exports":{".":{"types":"./dist/index.d.ts","import":"./dist/index.js"}},"scripts":{"dev":"tsc --project tsconfig.build.json --watch","lint":"tsc --noEmit","test":"vitest run","build":"tsc --project tsconfig.build.json"},"_npmUser":{"name":"mksglu","email":"code.bm.ksglu@gmail.com"},"_resolved":"/private/var/folders/df/nbmn_hp51n177rvbz8zh44sh0000gn/T/94e09c5b674655ed5d34d7e1f426de99/countly-ai-sdk-llamaindex-0.0.4.tgz","_integrity":"sha512-KIpEpYnbkWP1kUNQCDz40iuC/+XE9EUTmg9y3bNFA6pb5y3vGISdycIO321DC9PgLLEzZMqjcDQtrpzIswMFAA==","_npmVersion":"10.8.2","description":"Countly AI observability adapter for LlamaIndex","directories":{},"_nodeVersion":"20.19.2","dependencies":{"@countly/ai-sdk-core":"0.0.4"},"publishConfig":{"access":"public"},"_hasShrinkwrap":false,"devDependencies":{"typescript":"^5.8.3","@countly/ai-sdk-tsconfig":"0.0.0"},"peerDependencies":{"llamaindex":">=0.8.0"},"peerDependenciesMeta":{"llamaindex":{"optional":false}},"_npmOperationalInternal":{"tmp":"tmp/ai-sdk-llamaindex_0.0.4_1784147101064_0.5029450165930145","host":"s3://npm-registry-packages-npm-production"}},"0.0.5":{"name":"@countly/ai-sdk-llamaindex","version":"0.0.5","_id":"@countly/ai-sdk-llamaindex@0.0.5","maintainers":[{"name":"mksglu","email":"code.bm.ksglu@gmail.com"}],"dist":{"shasum":"439f361c1cfee4b98b64e0423235a063daf9b85c","tarball":"https://registry.npmjs.org/@countly/ai-sdk-llamaindex/-/ai-sdk-llamaindex-0.0.5.tgz","fileCount":10,"integrity":"sha512-ChtUZ6eAzlRlj5fEpEwCGzatKjRRN3DeWRS1sGaawLc6qk4yUvTUdPxVcGGnqbw18Ls5oPmUKf6FQSj4ggrxpg==","signatures":[{"sig":"MEYCIQDvkVGQZDT1OWUKxWk/hpDzgfTh7qS+03drViBnH50ffAIhAJWLhBUAzYwVArZD3Q2CMBPRdfyK9q4AEwraa/qcA0jd","keyid":"SHA256:DhQ8wR5APBvFHLF/+Tc+AYvPOdTpcIDqOhxsBHRwC7U"}],"unpackedSize":29113},"type":"module","_from":"file:countly-ai-sdk-llamaindex-0.0.5.tgz","exports":{".":{"types":"./dist/index.d.ts","import":"./dist/index.js"}},"scripts":{"dev":"tsc --project tsconfig.build.json --watch","lint":"tsc --noEmit","test":"vitest run","build":"tsc --project tsconfig.build.json"},"_npmUser":{"name":"mksglu","email":"code.bm.ksglu@gmail.com"},"_resolved":"/private/var/folders/df/nbmn_hp51n177rvbz8zh44sh0000gn/T/cb5b9f4a902e7ac46ab06595488a643b/countly-ai-sdk-llamaindex-0.0.5.tgz","_integrity":"sha512-ChtUZ6eAzlRlj5fEpEwCGzatKjRRN3DeWRS1sGaawLc6qk4yUvTUdPxVcGGnqbw18Ls5oPmUKf6FQSj4ggrxpg==","_npmVersion":"10.8.2","description":"Countly AI observability adapter for LlamaIndex","directories":{},"_nodeVersion":"20.19.2","dependencies":{"@countly/ai-sdk-core":"0.0.5"},"publishConfig":{"access":"public"},"_hasShrinkwrap":false,"devDependencies":{"typescript":"^5.8.3","@countly/ai-sdk-tsconfig":"0.0.0"},"peerDependencies":{"llamaindex":">=0.8.0"},"peerDependenciesMeta":{"llamaindex":{"optional":false}},"_npmOperationalInternal":{"tmp":"tmp/ai-sdk-llamaindex_0.0.5_1784810342509_0.1931829529887652","host":"s3://npm-registry-packages-npm-production"}},"0.0.6":{"name":"@countly/ai-sdk-llamaindex","version":"0.0.6","description":"Countly AI observability adapter for LlamaIndex","type":"module","main":"./dist/index.js","types":"./dist/index.d.ts","exports":{".":{"types":"./dist/index.d.ts","import":"./dist/index.js","require":"./dist/index.js","default":"./dist/index.js"},"./package.json":"./package.json"},"engines":{"node":"^20.19.0 || >=22.12.0"},"publishConfig":{"access":"public"},"dependencies":{"@countly/ai-sdk-core":"0.0.6"},"peerDependencies":{"llamaindex":">=0.8.0"},"peerDependenciesMeta":{"llamaindex":{"optional":false}},"devDependencies":{"typescript":"^5.8.3","@countly/ai-sdk-tsconfig":"0.0.0"},"scripts":{"build":"tsc --project tsconfig.build.json","dev":"tsc --project tsconfig.build.json --watch","lint":"tsc --noEmit","test":"vitest run"},"_id":"@countly/ai-sdk-llamaindex@0.0.6","_integrity":"sha512-rF+bm99+YOkX9QJUMgat5wVuUN5RFwAmCAOZFVALUpPjQhMjnx8QJQtGx59z8SuK5GMBrDgGTl43o55YgGlArQ==","_resolved":"/private/var/folders/df/nbmn_hp51n177rvbz8zh44sh0000gn/T/5791f56263059fa128f2591f43b635e9/countly-ai-sdk-llamaindex-0.0.6.tgz","_from":"file:countly-ai-sdk-llamaindex-0.0.6.tgz","_nodeVersion":"20.19.2","_npmVersion":"10.8.2","dist":{"integrity":"sha512-rF+bm99+YOkX9QJUMgat5wVuUN5RFwAmCAOZFVALUpPjQhMjnx8QJQtGx59z8SuK5GMBrDgGTl43o55YgGlArQ==","shasum":"108a4223821fe4d3bef8b32931fd7e5d7cf1ad0e","tarball":"https://registry.npmjs.org/@countly/ai-sdk-llamaindex/-/ai-sdk-llamaindex-0.0.6.tgz","fileCount":10,"unpackedSize":80236,"signatures":[{"keyid":"SHA256:DhQ8wR5APBvFHLF/+Tc+AYvPOdTpcIDqOhxsBHRwC7U","sig":"MEUCIQCrP+V5URHwBVoK4mX1OGZ3/VMrTYnlsTB+GCvAmmCCWwIgc5bNMYjvId3/f2ew4GsdZtQ4OFXhNaWtgvQv+JyBFzQ="}]},"_npmUser":{"name":"mksglu","email":"code.bm.ksglu@gmail.com"},"directories":{},"maintainers":[{"name":"mksglu","email":"code.bm.ksglu@gmail.com"}],"_npmOperationalInternal":{"host":"s3://npm-registry-packages-npm-production","tmp":"tmp/ai-sdk-llamaindex_0.0.6_1785687689661_0.07875771228372841"},"_hasShrinkwrap":false}},"time":{"created":"2026-07-07T17:00:18.720Z","modified":"2026-08-02T16:21:29.971Z","0.0.3":"2026-07-07T17:00:19.111Z","0.0.4":"2026-07-15T20:25:01.282Z","0.0.5":"2026-07-23T12:39:02.653Z","0.0.6":"2026-08-02T16:21:29.813Z"},"description":"Countly AI observability adapter for LlamaIndex","maintainers":[{"name":"mksglu","email":"code.bm.ksglu@gmail.com"}],"readme":"# @countly/ai-sdk-llamaindex\n\n> Countly AI observability adapter for [LlamaIndex.TS](https://github.com/run-llama/LlamaIndexTS).\n\nPart of the [Countly AI SDK](https://github.com/Countly/countly-ai-sdk) — provider-agnostic LLM observability for every AI stack.\n\n## Install\n\n```bash\nnpm install @countly/ai-sdk-llamaindex\n```\n\n`@countly/ai-sdk-core` is pulled in automatically.\n\n## Peer dependency\n\n```\nllamaindex >= 0.8.0\n```\n\n## Quick Start\n\n```typescript\nimport { Settings } from \"llamaindex\";\nimport { CountlyLlamaIndexTracer } from \"@countly/ai-sdk-llamaindex\";\nimport { AsyncLocalStorage } from \"node:async_hooks\";\n\nconst userStore = new AsyncLocalStorage<{ userId: string }>();\n\napp.use((req, res, next) => {\n  userStore.run({ userId: req.user.id }, next);\n});\n\nconst tracer = new CountlyLlamaIndexTracer({\n  appKey: \"YOUR_APP_KEY\",\n  url: \"https://your-countly-server.com\",\n  getDeviceId: () => userStore.getStore()?.userId,\n});\n\n// Attach to LlamaIndex's callback manager\ntracer.register(Settings.callbackManager);\n```\n\nThe tracer listens to `llm-start`, `llm-stream`, `llm-end`, `llm-tool-call`, and `llm-tool-result` events on the dispatcher.\n\n## What's captured\n\n- One `[CLY]_llm_interaction` row per generation — latency, time to first token, tokens, cost, model, endpoint class\n- Streamed calls too: for a stream, LlamaIndex hands `llm-end` an **array of chunks** instead of the provider response, and the model and token counts are recovered from it\n- Provider-native token shapes: OpenAI, Anthropic (both cache buckets), Gemini (`thoughtsTokenCount` as reasoning), Cohere (`meta.tokens`)\n- Tool call lifecycle (name, `call_id`, arguments, observed status, latency), attributed to the generation that requested it\n- Concurrent call tracking\n- Per-user aggregation\n\nNothing is invented: a count the provider did not report is **omitted** and the row carries `usage_state: \"not_reported\"`; a dimension we could not read carries `\"unknown\"`.\n\n## Errors\n\nLlamaIndex has no error event — when `LLM.chat()` throws, `llm-end` is never dispatched — so a failed call is invisible to any callback listener. Hand the throw over explicitly, or the error rate reads as a perfect 0:\n\n```typescript\ntry {\n  const response = await queryEngine.query({ query });\n}\ncatch (err) {\n  tracer.recordError(err); // emits a status:\"error\" interaction + a crash report\n  throw err;\n}\n```\n\nWith a single call in flight the failure is attributed to it, so its latency and prompt survive. Pass `recordError(err, { id })` when you have the LlamaIndex call id, or `{ model, provider }` when the failure happened before any call started.\n\n## Known limitations\n\n- **Turn grouping.** LlamaIndex mints a fresh uuid per `chat()` and exposes no turn identity, so without `getPromptId` every generation is its own `run_id` (and `generation_index` is always 0). Supply `getPromptId` to group an agent loop's generations into one run.\n- **Tool failures.** `@llamaindex/core` dispatches `llm-tool-result` only when the tool *returns*; a tool that throws produces no event. Such a call is still reported, with `status: \"unknown\"` — never a fabricated success — at the next generation or on `shutdown()`.\n- **Endpoint.** `api_host_type`/`api_host` are read off the LLM instance behind the event. A provider class that exposes its `baseURL` under an unrecognized name reports `api_host_type: \"unknown\"` rather than a guess.\n\n## Flush before shutdown\n\n```typescript\nawait tracer.flush();    // send buffered events\nawait tracer.shutdown(); // flush + stop the transport\ntracer.unregister(Settings.callbackManager); // detach handlers\n```\n\n## Feedback\n\nUser feedback (thumbs up/down, ratings, comments) is not auto-collected — wire it from your UI. Capture the `prompt_id` of each tracked interaction via the `onPrompt` callback, then record feedback against it with `createFeedbackTracker` (re-exported from this package, so no extra install is needed):\n\n```typescript\nimport { Settings } from \"llamaindex\";\nimport { CountlyLlamaIndexTracer, createFeedbackTracker, type PromptInfo } from \"@countly/ai-sdk-llamaindex\";\n\nconst countly = { appKey: \"YOUR_APP_KEY\", url: \"https://your-countly-server.com\" };\n\nlet lastPrompt: PromptInfo | undefined;\nconst tracer = new CountlyLlamaIndexTracer({\n  ...countly,\n  onPrompt: (info) => { lastPrompt = info; }, // fires after every tracked LLM call\n});\ntracer.register(Settings.callbackManager);\n\nconst feedback = createFeedbackTracker(countly, { sdk_adapter: \"llamaindex\" });\n\nconst response = await queryEngine.query({ query: \"Explain quantum computing\" });\n\n// ...later, when the user rates the answer:\nfeedback.track({\n  prompt_id: lastPrompt!.prompt_id,\n  rating: \"thumbs_up\", // or \"thumbs_down\", or any custom string\n  score: 0.9, // optional 0-1 numeric score\n  category: \"helpful\", // optional: hallucination, irrelevant, harmful, ...\n  comment: \"Great answer\", // optional free-form text\n  deviceId: user.id, // attribute to the same user as the interaction\n});\n```\n\nEach `track()` call emits a `[CLY]_llm_interaction_feedback` event whose `prompt_id` links back to the run (`PromptInfo.prompt_id` is the turn's `run_id`; pass `PromptInfo.event_id` plus `run_id` instead to rate one specific generation) — powering prompt → feedback funnels and per-model satisfaction breakdowns in Countly. In a real app, store `prompt_id` alongside the rendered message (or return it to your client) and read it back when the user rates the answer. Feedback is batched like interaction events; call `feedback.flush()` to send immediately, or `feedback.shutdown()` on process exit.\n\n### Caller-supplied `prompt_id`\n\nInstead of reading an id back through `onPrompt`, you can stamp your own on each turn via `getPromptId`. Return the correlation key you already track for the request (e.g. a message id or trace id) and the tracer uses it verbatim as the turn's `run_id`; return `undefined` and each LLM call becomes its own run. This lets you correlate feedback without a read-back round-trip — and it is the only way to group an agent loop's generations into one run:\n\n```typescript\nconst tracer = new CountlyLlamaIndexTracer({\n  ...countly,\n  getPromptId: () => currentRequest.id, // your own id → becomes the event's prompt_id\n});\ntracer.register(Settings.callbackManager);\n\n// ...later, correlate feedback directly against the same id you supplied:\nfeedback.track({ prompt_id: currentRequest.id, rating: \"thumbs_up\" });\n```\n\n`getPromptId` is called once per interaction. It is the wrapped-client equivalent of the request-context prompt id used by other Countly AI adapters, so a non-empty return value becomes the `run_id` of the `[CLY]_llm_interaction` event and of every tool event scoped to that run.\n\n## Full documentation\n\nSee the [Countly AI SDK repository](https://github.com/Countly/countly-ai-sdk) for the **schema v2 wire contract** (one row per generation, RULE A dimensions, RULE B measures with their `usage_state` / `cost_priced` markers, and the common envelope), the [adapter capability matrix](https://github.com/Countly/countly-ai-sdk/blob/main/docs/capability-matrix.md), observability levels (0/1/2), cost calculation, privacy controls, and Countly plugin integration (Drill, Funnels, Cohorts, APM, Crash Analytics).\n\n## License\n\nMIT\n","readmeFilename":"README.md"}