{"_id":"@damsarabi/llm-intent-router","_rev":"3-ee986b00abf1e2d1890f36e1edd428f7","name":"@damsarabi/llm-intent-router","dist-tags":{"latest":"1.1.4"},"versions":{"1.1.2":{"name":"@damsarabi/llm-intent-router","version":"1.1.2","keywords":["llm","intent","router","zod","typescript"],"author":"","license":"ISC","_id":"@damsarabi/llm-intent-router@1.1.2","maintainers":[{"name":"damsarabi","email":"sam.darabi@gmail.com"}],"homepage":"https://github.com/damsarabi/llm-intent-router#readme","bugs":{"url":"https://github.com/damsarabi/llm-intent-router/issues"},"dist":{"shasum":"7647e5a35e9b4d11c1a19a3ebca104920d1f7f90","tarball":"https://registry.npmjs.org/@damsarabi/llm-intent-router/-/llm-intent-router-1.1.2.tgz","fileCount":45,"integrity":"sha512-z2oURITWVP4fmcuZHIBhEBZb3GiQ7Sg4H/jlE2wp0vDLtAyiV7/c8PcLn1Q/sSGgv/ROO67lAEcLxjXaSGtCNA==","signatures":[{"sig":"MEUCIQCbXaCw06GuNUJNZXqnY1a1hFXd4HLKtGUc3mm+PDw0FAIgX0eALFebWvIGl0jzj+K1kA+UKiw9afkOTbIQv3Favsw=","keyid":"SHA256:DhQ8wR5APBvFHLF/+Tc+AYvPOdTpcIDqOhxsBHRwC7U"}],"unpackedSize":266297},"main":"dist/index.js","types":"dist/index.d.ts","module":"dist/index.mjs","exports":{".":{"types":"./dist/index.d.ts","import":"./dist/index.mjs","require":"./dist/index.js"}},"gitHead":"14a195d4694c7feeff3d8d613469d714836c12ba","scripts":{"dev":"tsup --watch","test":"vitest run","build":"tsup","test:coverage":"vitest run --coverage"},"_npmUser":{"name":"damsarabi","email":"sam.darabi@gmail.com"},"repository":{"url":"git+https://github.com/damsarabi/llm-intent-router.git","type":"git"},"_npmVersion":"10.8.2","description":"A middleware router for processing and routing LLM JSON intents with Zod validation","directories":{},"_nodeVersion":"20.20.2","dependencies":{"ms":"^2.1.3","mz":"^2.7.0","cac":"^6.7.14","ufo":"^1.6.4","fdir":"^6.5.0","mlly":"^1.8.2","acorn":"^8.17.0","debug":"^4.4.3","pathe":"^2.0.3","joycon":"^3.1.1","rollup":"^4.62.2","confbox":"^0.1.8","consola":"^3.4.2","esbuild":"^0.27.7","pirates":"^4.0.7","sucrase":"^3.35.1","thenify":"^3.3.1","chokidar":"^4.0.3","readdirp":"^4.1.2","tinyexec":"^0.3.2","commander":"^4.1.1","lilconfig":"^3.1.3","picomatch":"^4.0.5","pkg-types":"^1.3.1","tree-kill":"^1.2.2","picocolors":"^1.1.1","source-map":"^0.7.6","tinyglobby":"^0.2.17","any-promise":"^1.3.0","thenify-all":"^1.6.0","magic-string":"^0.30.21","resolve-from":"^5.0.0","undici-types":"^6.21.0","load-tsconfig":"^0.2.5","object-assign":"^4.1.1","bundle-require":"^5.1.0","lines-and-columns":"^1.2.4","postcss-load-config":"^6.0.1","ts-interface-checker":"^0.1.13","fix-dts-default-cjs-exports":"^1.0.1"},"publishConfig":{"access":"public"},"_hasShrinkwrap":false,"devDependencies":{"tsx":"^4.23.13","zod":"^3.25.76","tsup":"^8.5.1","dotenv":"^17.4.2","vitest":"^4.1.10","typescript":"^5.9.3","@types/node":"^20.19.43","@changesets/cli":"^2.31.1","@vitest/coverage-v8":"^4.1.10","@google/generative-ai":"^0.24.1"},"peerDependencies":{"zod":"^3.0.0"},"_npmOperationalInternal":{"tmp":"tmp/llm-intent-router_1.1.2_1789106236725_0.4134980772829613","host":"s3://npm-registry-packages-npm-production"}},"1.1.3":{"name":"@damsarabi/llm-intent-router","version":"1.1.3","keywords":["llm","intent","router","zod","typescript"],"author":"","license":"ISC","_id":"@damsarabi/llm-intent-router@1.1.3","maintainers":[{"name":"damsarabi","email":"sam.darabi@gmail.com"}],"homepage":"https://github.com/damsarabi/llm-intent-router#readme","bugs":{"url":"https://github.com/damsarabi/llm-intent-router/issues"},"dist":{"shasum":"cff24a3a9cb1bfdcc347019bd885e0ed1ac06378","tarball":"https://registry.npmjs.org/@damsarabi/llm-intent-router/-/llm-intent-router-1.1.3.tgz","fileCount":45,"integrity":"sha512-9bqg/pF+npl1yOKLOiucp/10SkRl6EuUU+cAeVcA+6OFlPHGKX7q+7ZeyE1Xkj1ZanuoMwV1QrqHd5GOQUC/vQ==","signatures":[{"sig":"MEUCIQDHyS1+1KOQkHCJk3NbbyLlVlTsLpDVtFQ0ixJj8AdmVgIgMYUE6oEmIaCFQwSVMerC/ZzyG7VZ62yJRC5rEQ3yDM4=","keyid":"SHA256:DhQ8wR5APBvFHLF/+Tc+AYvPOdTpcIDqOhxsBHRwC7U"}],"unpackedSize":266297},"main":"dist/index.js","types":"dist/index.d.ts","module":"dist/index.mjs","exports":{".":{"types":"./dist/index.d.ts","import":"./dist/index.mjs","require":"./dist/index.js"}},"gitHead":"b069146d9bc3010330699c2cee7f50b08daaf20a","scripts":{"dev":"tsup --watch","test":"vitest run","build":"tsup","test:coverage":"vitest run --coverage"},"_npmUser":{"name":"damsarabi","email":"sam.darabi@gmail.com"},"repository":{"url":"git+https://github.com/damsarabi/llm-intent-router.git","type":"git"},"_npmVersion":"10.8.2","description":"A middleware router for processing and routing LLM JSON intents with Zod validation","directories":{},"_nodeVersion":"20.20.2","dependencies":{"ms":"^2.1.3","mz":"^2.7.0","cac":"^6.7.14","ufo":"^1.6.4","fdir":"^6.5.0","mlly":"^1.8.2","acorn":"^8.17.0","debug":"^4.4.3","pathe":"^2.0.3","joycon":"^3.1.1","rollup":"^4.62.2","confbox":"^0.1.8","consola":"^3.4.2","esbuild":"^0.27.7","pirates":"^4.0.7","sucrase":"^3.35.1","thenify":"^3.3.1","chokidar":"^4.0.3","readdirp":"^4.1.2","tinyexec":"^0.3.2","commander":"^4.1.1","lilconfig":"^3.1.3","picomatch":"^4.0.5","pkg-types":"^1.3.1","tree-kill":"^1.2.2","picocolors":"^1.1.1","source-map":"^0.7.6","tinyglobby":"^0.2.17","any-promise":"^1.3.0","thenify-all":"^1.6.0","magic-string":"^0.30.21","resolve-from":"^5.0.0","undici-types":"^6.21.0","load-tsconfig":"^0.2.5","object-assign":"^4.1.1","bundle-require":"^5.1.0","lines-and-columns":"^1.2.4","postcss-load-config":"^6.0.1","ts-interface-checker":"^0.1.13","fix-dts-default-cjs-exports":"^1.0.1"},"publishConfig":{"access":"public"},"_hasShrinkwrap":false,"devDependencies":{"tsx":"^4.23.13","zod":"^3.25.76","tsup":"^8.5.1","dotenv":"^17.4.2","vitest":"^4.1.10","typescript":"^5.9.3","@types/node":"^20.19.43","@changesets/cli":"^2.31.1","@vitest/coverage-v8":"^4.1.10","@google/generative-ai":"^0.24.1"},"peerDependencies":{"zod":"^3.0.0"},"_npmOperationalInternal":{"tmp":"tmp/llm-intent-router_1.1.3_1789106542995_0.09066057656936644","host":"s3://npm-registry-packages-npm-production"}},"1.1.4":{"name":"@damsarabi/llm-intent-router","version":"1.1.4","description":"A middleware router for processing and routing LLM JSON intents with Zod validation","publishConfig":{"access":"public"},"main":"dist/index.js","module":"dist/index.mjs","types":"dist/index.d.ts","exports":{".":{"types":"./dist/index.d.ts","import":"./dist/index.mjs","require":"./dist/index.js"}},"scripts":{"build":"tsup","dev":"tsup --watch","test":"vitest run","test:coverage":"vitest run --coverage"},"peerDependencies":{"zod":"^3.0.0"},"devDependencies":{"@changesets/cli":"^2.31.1","@google/generative-ai":"^0.24.1","@types/node":"^20.19.43","@vitest/coverage-v8":"^4.1.10","dotenv":"^17.4.2","tsup":"^8.5.1","tsx":"^4.23.13","typescript":"^5.9.3","vitest":"^4.1.10","zod":"^3.25.76"},"keywords":["llm","intent","router","zod","typescript"],"author":"","license":"ISC","dependencies":{"acorn":"^8.17.0","any-promise":"^1.3.0","bundle-require":"^5.1.0","cac":"^6.7.14","chokidar":"^4.0.3","commander":"^4.1.1","confbox":"^0.1.8","consola":"^3.4.2","debug":"^4.4.3","esbuild":"^0.27.7","fdir":"^6.5.0","fix-dts-default-cjs-exports":"^1.0.1","joycon":"^3.1.1","lilconfig":"^3.1.3","lines-and-columns":"^1.2.4","load-tsconfig":"^0.2.5","magic-string":"^0.30.21","mlly":"^1.8.2","ms":"^2.1.3","mz":"^2.7.0","object-assign":"^4.1.1","pathe":"^2.0.3","picocolors":"^1.1.1","picomatch":"^4.0.5","pirates":"^4.0.7","pkg-types":"^1.3.1","postcss-load-config":"^6.0.1","readdirp":"^4.1.2","resolve-from":"^5.0.0","rollup":"^4.62.2","source-map":"^0.7.6","sucrase":"^3.35.1","thenify":"^3.3.1","thenify-all":"^1.6.0","tinyexec":"^0.3.2","tinyglobby":"^0.2.17","tree-kill":"^1.2.2","ts-interface-checker":"^0.1.13","ufo":"^1.6.4","undici-types":"^6.21.0"},"repository":{"type":"git","url":"git+https://github.com/damsarabi/llm-intent-router.git"},"bugs":{"url":"https://github.com/damsarabi/llm-intent-router/issues"},"homepage":"https://github.com/damsarabi/llm-intent-router#readme","_id":"@damsarabi/llm-intent-router@1.1.4","gitHead":"f55e3ba101276e95749bc869a71254f94d81dc93","_nodeVersion":"20.20.2","_npmVersion":"10.8.2","dist":{"integrity":"sha512-GptorvnDP8S1Iduj2f9Ih4/fEho8Ys5RP0u6eQyDB54IjUiCqUteO1FFvLtYQ3eY6vOeaTM2DW/+NsqYUphwOw==","shasum":"12ad0ad56e2bda44e0d6af8b9b992c4b72922d05","tarball":"https://registry.npmjs.org/@damsarabi/llm-intent-router/-/llm-intent-router-1.1.4.tgz","fileCount":46,"unpackedSize":266625,"signatures":[{"keyid":"SHA256:DhQ8wR5APBvFHLF/+Tc+AYvPOdTpcIDqOhxsBHRwC7U","sig":"MEUCIQCTZ+7ZICTBWQ/pGHAx8jI3etCVA90vla8Rcxt0CH3wIgIgG7rXqnJ23nONDQQxdreRqf/h9OQGDlKP9ESdXqOdErw="}]},"_npmUser":{"name":"damsarabi","email":"sam.darabi@gmail.com"},"directories":{},"maintainers":[{"name":"damsarabi","email":"sam.darabi@gmail.com"}],"_npmOperationalInternal":{"host":"s3://npm-registry-packages-npm-production","tmp":"tmp/llm-intent-router_1.1.4_1789107177667_0.4091897755794398"},"_hasShrinkwrap":false}},"time":{"created":"2026-09-11T05:57:16.502Z","modified":"2026-09-11T06:12:57.988Z","1.1.2":"2026-09-11T05:57:16.864Z","1.1.3":"2026-09-11T06:02:23.173Z","1.1.4":"2026-09-11T06:12:57.820Z"},"bugs":{"url":"https://github.com/damsarabi/llm-intent-router/issues"},"license":"ISC","homepage":"https://github.com/damsarabi/llm-intent-router#readme","keywords":["llm","intent","router","zod","typescript"],"repository":{"type":"git","url":"git+https://github.com/damsarabi/llm-intent-router.git"},"description":"A middleware router for processing and routing LLM JSON intents with Zod validation","maintainers":[{"name":"damsarabi","email":"sam.darabi@gmail.com"}],"readme":"# llm-intent-router\n\n[![npm version](https://img.shields.io/npm/v/@damsarabi/llm-intent-router.svg)](https://www.npmjs.com/package/@damsarabi/llm-intent-router)\n[![codecov](https://codecov.io/gh/damsarabi/llm-intent-router/branch/main/graph/badge.svg)](https://codecov.io/gh/damsarabi/llm-intent-router)\n[![License: MIT](https://img.shields.io/badge/License-MIT-yellow.svg)](https://opensource.org/licenses/MIT)\n[![Build Status](https://github.com/damsarabi/llm-intent-router/actions/workflows/ci.yml/badge.svg)](https://github.com/damsarabi/llm-intent-router/actions)\n\n**Deterministic state routing for unpredictable LLM outputs.**\n\nStop piping raw LLM text into your application state. `llm-intent-router` is a lightweight, framework-agnostic middleware that safely translates non-deterministic AI text into strictly typed, Zod-validated execution callbacks.\n\n## The Problem\n\nWiring Generative AI into traditional UI state (React, Zustand, Redux) is notoriously fragile:\n1. **Markdown Formatting:** Even in JSON mode, models often wrap responses in Markdown (e.g., ````json ... ````). \n2. **Hallucinations:** LLMs hallucinate object properties or return invalid enum values.\n3. **Fatal Crashes:** Passing a raw `JSON.parse(aiOutput)` directly to your global store will eventually crash your application.\n\n## The Solution\n\n`llm-intent-router` acts as a safety barrier and orchestration engine between your AI and your application code. It operates in two phases:\n\n### Phase 1: The Orchestrator (Multi-Agent Routing)\nInstead of piping all user input into an expensive, slow model, you can use the `ClassifierAgent` to do a cheap, fast binary check: *Is this just a chat, or an actionable command?* \nIf it's a command, the `Orchestrator` takes over, using greedy decoding (`temperature: 0`) to force the LLM to output predictable JSON.\n\n### Phase 2: The Intent Router (Validation & Repair)\nOnce the LLM outputs JSON, the Router:\n- **Sanitizes** strings by stripping Markdown code blocks.\n- **Parses** the payload (gracefully handling both single JSON objects and arrays/batches).\n- **Validates** the LLM's payload against your strict `zod` schemas.\n- **Auto-Repairs:** If Zod validation fails, the Orchestrator automatically feeds the exact Zod error back to the LLM so it can fix its own hallucination.\n- **Routes** the validated data to your execution callback, entirely typed and safe.\n\n## Installation\n\n```bash\nnpm install llm-intent-router zod\n```\n\n## Quick Start\n\n```typescript\nimport { IntentRouter } from 'llm-intent-router';\nimport { z } from 'zod';\n\n// 1. Define your strict UI schemas\nconst schemas = {\n  TOGGLE_THEME: z.object({\n    theme: z.enum(['dark', 'light']),\n  }),\n  FILTER_TABLE: z.object({\n    region: z.string(),\n    minRevenue: z.number().optional(),\n  }),\n};\n\n// 2. Initialize the router\nconst router = new IntentRouter({\n  schemas,\n  onExecute: (intent, payload) => {\n    // 🟢 SAFE: 'payload' is strictly typed based on the matched intent.\n    // Perfect place to dispatch to Zustand, Redux, or Context.\n    console.log(`Executing ${intent}:`, payload);\n  },\n  onError: (error, rawItem) => {\n    // 🔴 CAUGHT: The LLM hallucinated, or parsing failed. \n    // State remains protected.\n    console.error('LLM Validation Failed:', error.message);\n  },\n});\n\n// 3. Process raw AI responses (even messy ones)\nconst messyAiResponse = `\nHere is your data:\n\\`\\`\\`json\n[\n  { \"intent\": \"TOGGLE_THEME\", \"payload\": { \"theme\": \"dark\" } },\n  { \"intent\": \"FILTER_TABLE\", \"payload\": { \"region\": \"North America\" } }\n]\n\\`\\`\\`\n`;\n\n// Automatically strips markdown, validates payloads, and fires onExecute twice.\nrouter.process(messyAiResponse);\n```\n\n## Advanced: Batch Execution\n\nThe router natively supports batch execution. If the LLM returns an array of intent objects, `llm-intent-router` will parse the array and sequentially fire the `onExecute` callback for every valid intent in the batch.\n\n## Advanced: The Orchestrator (Auto-Repair)\n\nIf you want the library to handle the actual LLM API calls, you can use the `Orchestrator`. It wraps your LLM SDK and automatically feeds Zod validation errors back to the model for self-correction.\n\n```typescript\nimport { Orchestrator, ClassifierAgent } from 'llm-intent-router';\n\n// Fast lane classification (e.g. Gemini Flash Lite)\nconst classifier = new ClassifierAgent(myFastLLMProvider);\nconst intentType = await classifier.classify(userInput, { systemPrompt: '...' });\n\nif (intentType === 'COMMAND') {\n  // Slow lane execution (e.g. Gemini Pro)\n  const orchestrator = new Orchestrator({\n    provider: myHeavyLLMProvider,\n    router: myIntentRouter,\n    maxRetries: 2, // If it hallucinates, it gets 2 chances to fix it!\n    systemPrompt: 'You are a strict JSON command engine.'\n  });\n\n  await orchestrator.execute(userInput); // Validates and executes safely\n}\n```\n\n## 🧪 Production Evals (Promptfoo)\n\nA routing engine is only as good as its tests. `llm-intent-router` ships with a production-grade [Promptfoo](https://promptfoo.dev) evaluation suite in the `evals/` directory.\n\nThe suite mathematically proves the router's resilience across 4 dimensions:\n1. **Dual-Routing Accuracy:** Proving the classifier accurately separates conversational chat from actionable commands.\n2. **Schema Adherence:** Proving the generator outputs valid JSON matching complex Zod expectations.\n3. **Resilience & Fallback:** Proving the system degrades gracefully when required data (like an `orderId`) is missing from the user's prompt.\n4. **Batch Execution:** Proving the router can execute multiple distinct intents from a single prompt.\n\nTo run the evals:\n```bash\nnpm install -g promptfoo\ncd evals\npromptfoo eval\npromptfoo view\n```\n\n## License\n\nMIT\n","readmeFilename":"README.md"}