{"_id":"@diabolicallabs/llm-client","_rev":"37-bc0970fd02cd2c74010bd1b184031167","name":"@diabolicallabs/llm-client","dist-tags":{"latest":"6.9.0"},"versions":{"0.1.0":{"name":"@diabolicallabs/llm-client","version":"0.1.0","author":{"url":"https://deeismail.com","name":"Diana Ismail","email":"diana@deeismail.com"},"license":"UNLICENSED","_id":"@diabolicallabs/llm-client@0.1.0","maintainers":[{"name":"shackled78","email":"shackled78@gmail.com"}],"homepage":"https://github.com/mannism/dlabs-toolkit#readme","bugs":{"url":"https://github.com/mannism/dlabs-toolkit/issues"},"dist":{"shasum":"e184b529a7e42259f8a257ab22c5a3bc7e4aad22","tarball":"https://registry.npmjs.org/@diabolicallabs/llm-client/-/llm-client-0.1.0.tgz","fileCount":5,"integrity":"sha512-ZxdPRUkDMVkprLPwfenrOx8j+TJ4k+RYZ6afsNEfKEWAcNTJFdDBtSwEQhv8iVTQfbvtGAFbuYBzBD1NTQAdhw==","signatures":[{"sig":"MEQCIEdVjUDJAQqX0dXaeLEzVyXfEfAQMxuikiHzf5Vd9a0XAiAEVWSPxiifBMDiGeGa1NmKBF8cVTCd5VmVtkl9po3Ddw==","keyid":"SHA256:DhQ8wR5APBvFHLF/+Tc+AYvPOdTpcIDqOhxsBHRwC7U"}],"unpackedSize":109482},"main":"./dist/index.js","type":"module","_from":"file:diabolicallabs-llm-client-0.1.0.tgz","types":"./dist/index.d.ts","engines":{"node":">=20"},"exports":{".":{"types":"./dist/index.d.ts","import":"./dist/index.js"}},"scripts":{"lint":"biome check ./src && eslint ./src","test":"vitest run","build":"tsup","typecheck":"tsc --noEmit","test:watch":"vitest"},"_npmUser":{"name":"shackled78","email":"shackled78@gmail.com"},"_resolved":"/tmp/6eccfe8e83e4baf8272852ecee9f22f9/diabolicallabs-llm-client-0.1.0.tgz","publisher":"Diabolical Labs","_integrity":"sha512-ZxdPRUkDMVkprLPwfenrOx8j+TJ4k+RYZ6afsNEfKEWAcNTJFdDBtSwEQhv8iVTQfbvtGAFbuYBzBD1NTQAdhw==","repository":{"url":"git+https://github.com/mannism/dlabs-toolkit.git","type":"git","directory":"packages/llm-client"},"_npmVersion":"10.8.2","description":"Unified LLM API for Anthropic, OpenAI, Google, and DeepSeek. Streaming, retry/backoff, structured output, token normalization. © Diabolical Labs","directories":{},"_nodeVersion":"20.20.2","dependencies":{"zod":"^4.4.3","openai":"^6.36.0","@google/genai":"^1.52.0","@anthropic-ai/sdk":"^0.94.0"},"_hasShrinkwrap":false,"devDependencies":{"tsup":"^8.3.5","vitest":"^4.1.5","@types/node":"^25.6.0","@vitest/coverage-v8":"^4.1.5"},"_npmOperationalInternal":{"tmp":"tmp/llm-client_0.1.0_1778050952999_0.325427461293305","host":"s3://npm-registry-packages-npm-production"}},"0.1.1":{"name":"@diabolicallabs/llm-client","version":"0.1.1","author":{"url":"https://deeismail.com","name":"Diana Ismail","email":"diana@deeismail.com"},"license":"MIT","_id":"@diabolicallabs/llm-client@0.1.1","maintainers":[{"name":"shackled78","email":"shackled78@gmail.com"}],"homepage":"https://github.com/mannism/dlabs-toolkit#readme","bugs":{"url":"https://github.com/mannism/dlabs-toolkit/issues"},"dist":{"shasum":"87570ae52f07ac7927fb8aef65e66d895302c585","tarball":"https://registry.npmjs.org/@diabolicallabs/llm-client/-/llm-client-0.1.1.tgz","fileCount":6,"integrity":"sha512-BVT24bZ13d9mgkpzrMIrmiOes5aofrAWCJu2K0sFcfUbt1naM2XHFlLk9eFM/0Wys6J+vZ6QQDUwdDG21TUf6g==","signatures":[{"sig":"MEQCICFrEKUu7gm4sZp9pap6lWsfTJug8Wzza/Q5mnYdkgY5AiAgJbGDMGqNtiDsJoxFQAzmX3LkL2cdE3kn2XY7OOeSjQ==","keyid":"SHA256:DhQ8wR5APBvFHLF/+Tc+AYvPOdTpcIDqOhxsBHRwC7U"}],"unpackedSize":110434},"main":"./dist/index.js","type":"module","_from":"file:diabolicallabs-llm-client-0.1.1.tgz","types":"./dist/index.d.ts","engines":{"node":">=20"},"exports":{".":{"types":"./dist/index.d.ts","import":"./dist/index.js"}},"scripts":{"lint":"biome check ./src && eslint ./src","test":"vitest run","build":"tsup","typecheck":"tsc --noEmit","test:watch":"vitest"},"_npmUser":{"name":"shackled78","email":"shackled78@gmail.com"},"_resolved":"/tmp/5613c59363c42b220bf0460b4b183ec3/diabolicallabs-llm-client-0.1.1.tgz","publisher":"Diabolical Labs","_integrity":"sha512-BVT24bZ13d9mgkpzrMIrmiOes5aofrAWCJu2K0sFcfUbt1naM2XHFlLk9eFM/0Wys6J+vZ6QQDUwdDG21TUf6g==","repository":{"url":"git+https://github.com/mannism/dlabs-toolkit.git","type":"git","directory":"packages/llm-client"},"_npmVersion":"10.8.2","description":"Unified LLM API for Anthropic, OpenAI, Google, and DeepSeek. Streaming, retry/backoff, structured output, token normalization. © Diabolical Labs","directories":{},"_nodeVersion":"20.20.2","dependencies":{"zod":"^4.4.3","openai":"^6.36.0","@google/genai":"^1.52.0","@anthropic-ai/sdk":"^0.94.0"},"_hasShrinkwrap":false,"devDependencies":{"tsup":"^8.3.5","vitest":"^4.1.5","@types/node":"^25.6.0","@vitest/coverage-v8":"^4.1.5"},"_npmOperationalInternal":{"tmp":"tmp/llm-client_0.1.1_1778059932039_0.9791519505417567","host":"s3://npm-registry-packages-npm-production"}},"0.2.0":{"name":"@diabolicallabs/llm-client","version":"0.2.0","author":{"url":"https://deeismail.com","name":"Diana Ismail","email":"diana@deeismail.com"},"license":"MIT","_id":"@diabolicallabs/llm-client@0.2.0","maintainers":[{"name":"shackled78","email":"shackled78@gmail.com"}],"homepage":"https://github.com/mannism/dlabs-toolkit#readme","bugs":{"url":"https://github.com/mannism/dlabs-toolkit/issues"},"dist":{"shasum":"d942fefd17b19d5a9c29a82f813df40ff90574b7","tarball":"https://registry.npmjs.org/@diabolicallabs/llm-client/-/llm-client-0.2.0.tgz","fileCount":6,"integrity":"sha512-vl5EyUI6ssR0l7hUoaCkx4QTWbvx36olODVk1SPN43jFK0jHr6TgwU4uoCTNpCLnLg8Nuvyc0wL7o9WTaD1ZjQ==","signatures":[{"sig":"MEUCID/d1y7Vy2vfl4ri+id7G6jF5lP23QvZSZNjRebeZs3ZAiEAntfRQ3Rtux6gjMggOOkOhMEsK8HGIBMlMJucjDfELz4=","keyid":"SHA256:DhQ8wR5APBvFHLF/+Tc+AYvPOdTpcIDqOhxsBHRwC7U"}],"unpackedSize":137314},"main":"./dist/index.js","type":"module","_from":"file:diabolicallabs-llm-client-0.2.0.tgz","types":"./dist/index.d.ts","engines":{"node":">=20"},"exports":{".":{"types":"./dist/index.d.ts","import":"./dist/index.js"}},"scripts":{"lint":"biome check ./src && eslint ./src","test":"vitest run","build":"tsup","typecheck":"tsc --noEmit","test:watch":"vitest"},"_npmUser":{"name":"shackled78","email":"shackled78@gmail.com"},"_resolved":"/tmp/ec89268547d0a0fe08d7333a29e802bc/diabolicallabs-llm-client-0.2.0.tgz","publisher":"Diabolical Labs","_integrity":"sha512-vl5EyUI6ssR0l7hUoaCkx4QTWbvx36olODVk1SPN43jFK0jHr6TgwU4uoCTNpCLnLg8Nuvyc0wL7o9WTaD1ZjQ==","repository":{"url":"git+https://github.com/mannism/dlabs-toolkit.git","type":"git","directory":"packages/llm-client"},"_npmVersion":"10.8.2","description":"Unified LLM API for Anthropic, OpenAI, Google, and DeepSeek. Streaming, retry/backoff, structured output, token normalization. © Diabolical Labs","directories":{},"_nodeVersion":"20.20.2","dependencies":{"zod":"^4.4.3","openai":"^6.36.0","@google/genai":"^1.52.0","@anthropic-ai/sdk":"^0.94.0"},"_hasShrinkwrap":false,"devDependencies":{"tsup":"^8.3.5","vitest":"^4.1.5","@types/node":"^25.6.0","@vitest/coverage-v8":"^4.1.5"},"_npmOperationalInternal":{"tmp":"tmp/llm-client_0.2.0_1778244870311_0.049342951533093427","host":"s3://npm-registry-packages-npm-production"}},"0.3.0":{"name":"@diabolicallabs/llm-client","version":"0.3.0","author":{"url":"https://deeismail.com","name":"Diana Ismail","email":"diana@deeismail.com"},"license":"MIT","_id":"@diabolicallabs/llm-client@0.3.0","maintainers":[{"name":"shackled78","email":"shackled78@gmail.com"}],"homepage":"https://github.com/mannism/dlabs-toolkit#readme","bugs":{"url":"https://github.com/mannism/dlabs-toolkit/issues"},"dist":{"shasum":"e50a09149ad23df2a38171472abe40a07d785de4","tarball":"https://registry.npmjs.org/@diabolicallabs/llm-client/-/llm-client-0.3.0.tgz","fileCount":6,"integrity":"sha512-fnyhxIKgB343/diPY5w7zj36vsGQ4V/NvpKwynwH1Rved3UBtUC7jz+7nC5MleG/leIzUTV3Vunyjsr6fNO3eQ==","signatures":[{"sig":"MEUCICA7xW9yldM57R8kVr3PmQJk6oGmzlysY+c9fxXTOPWUAiEAuBzD/5NNSPHg2RaQjB/lxvzdDsfC67rIawfQb09IInE=","keyid":"SHA256:DhQ8wR5APBvFHLF/+Tc+AYvPOdTpcIDqOhxsBHRwC7U"}],"unpackedSize":183798},"main":"./dist/index.js","type":"module","_from":"file:diabolicallabs-llm-client-0.3.0.tgz","types":"./dist/index.d.ts","engines":{"node":">=20"},"exports":{".":{"types":"./dist/index.d.ts","import":"./dist/index.js"}},"scripts":{"lint":"biome check ./src && eslint ./src","test":"vitest run","build":"tsup","typecheck":"tsc --noEmit","test:watch":"vitest"},"_npmUser":{"name":"shackled78","email":"shackled78@gmail.com"},"_resolved":"/tmp/1d962239113aef33fa593a4b9e45920a/diabolicallabs-llm-client-0.3.0.tgz","publisher":"Diabolical Labs","_integrity":"sha512-fnyhxIKgB343/diPY5w7zj36vsGQ4V/NvpKwynwH1Rved3UBtUC7jz+7nC5MleG/leIzUTV3Vunyjsr6fNO3eQ==","repository":{"url":"git+https://github.com/mannism/dlabs-toolkit.git","type":"git","directory":"packages/llm-client"},"_npmVersion":"10.8.2","description":"Unified LLM API for Anthropic, OpenAI, Google, and DeepSeek. Streaming, retry/backoff, structured output, token normalization. © Diabolical Labs","directories":{},"_nodeVersion":"20.20.2","dependencies":{"zod":"^4.4.3","openai":"^6.36.0","@google/genai":"^1.52.0","@anthropic-ai/sdk":"^0.94.0"},"_hasShrinkwrap":false,"devDependencies":{"tsup":"^8.3.5","vitest":"^4.1.5","@types/node":"^25.6.0","@vitest/coverage-v8":"^4.1.5"},"_npmOperationalInternal":{"tmp":"tmp/llm-client_0.3.0_1778376158605_0.02436692908059368","host":"s3://npm-registry-packages-npm-production"}},"0.4.0":{"name":"@diabolicallabs/llm-client","version":"0.4.0","author":{"url":"https://deeismail.com","name":"Diana Ismail","email":"diana@deeismail.com"},"license":"MIT","_id":"@diabolicallabs/llm-client@0.4.0","maintainers":[{"name":"shackled78","email":"shackled78@gmail.com"}],"homepage":"https://github.com/mannism/dlabs-toolkit#readme","bugs":{"url":"https://github.com/mannism/dlabs-toolkit/issues"},"dist":{"shasum":"b479a9a46b646a728f647b900980b56c8e15375d","tarball":"https://registry.npmjs.org/@diabolicallabs/llm-client/-/llm-client-0.4.0.tgz","fileCount":6,"integrity":"sha512-8SfpC+R6HDZfCkRQDeh3NRqDWPCdBiDxXzXEvlsWLwIqrNUCY1Nd9WpTvhy8341Un+cE9j5FkBkmClFnKTC3Vw==","signatures":[{"sig":"MEUCIQC2dlT0vx6AK8JN2babRTP4gmn5q3F0aQYttK4xYsX7HAIgZmbZbIB1Vb6GEiQB2LzF+hTA/cOZpDPt5pRgx29nEMo=","keyid":"SHA256:DhQ8wR5APBvFHLF/+Tc+AYvPOdTpcIDqOhxsBHRwC7U"}],"unpackedSize":237800},"main":"./dist/index.js","type":"module","_from":"file:diabolicallabs-llm-client-0.4.0.tgz","types":"./dist/index.d.ts","engines":{"node":">=20"},"exports":{".":{"types":"./dist/index.d.ts","import":"./dist/index.js"}},"scripts":{"lint":"biome check ./src && eslint ./src","test":"vitest run","build":"tsup","typecheck":"tsc --noEmit","test:watch":"vitest"},"_npmUser":{"name":"shackled78","email":"shackled78@gmail.com"},"_resolved":"/tmp/628c383b1243d12446b89aa5cbf92ccd/diabolicallabs-llm-client-0.4.0.tgz","publisher":"Diabolical Labs","_integrity":"sha512-8SfpC+R6HDZfCkRQDeh3NRqDWPCdBiDxXzXEvlsWLwIqrNUCY1Nd9WpTvhy8341Un+cE9j5FkBkmClFnKTC3Vw==","repository":{"url":"git+https://github.com/mannism/dlabs-toolkit.git","type":"git","directory":"packages/llm-client"},"_npmVersion":"10.8.2","description":"Unified LLM API for Anthropic, OpenAI, Google, and DeepSeek. Streaming, retry/backoff, structured output, token normalization. © Diabolical Labs","directories":{},"_nodeVersion":"20.20.2","dependencies":{"zod":"^4.4.3","openai":"^6.36.0","@google/genai":"^1.52.0","@anthropic-ai/sdk":"^0.94.0"},"_hasShrinkwrap":false,"devDependencies":{"tsup":"^8.3.5","vitest":"^4.1.5","@types/node":"^25.6.0","@vitest/coverage-v8":"^4.1.5"},"_npmOperationalInternal":{"tmp":"tmp/llm-client_0.4.0_1778380520152_0.5791671265426537","host":"s3://npm-registry-packages-npm-production"}},"0.4.1":{"name":"@diabolicallabs/llm-client","version":"0.4.1","author":{"url":"https://deeismail.com","name":"Diana Ismail","email":"diana@deeismail.com"},"license":"MIT","_id":"@diabolicallabs/llm-client@0.4.1","maintainers":[{"name":"shackled78","email":"shackled78@gmail.com"}],"homepage":"https://github.com/mannism/dlabs-toolkit#readme","bugs":{"url":"https://github.com/mannism/dlabs-toolkit/issues"},"dist":{"shasum":"e8dd17e3b7928f3336e84fa0cc81bdd0f12879fd","tarball":"https://registry.npmjs.org/@diabolicallabs/llm-client/-/llm-client-0.4.1.tgz","fileCount":6,"integrity":"sha512-wB81EQsm16s3J4n3DlEMGIf83E9hGK66UR6Ag3MO1+7fvPrFJz95ILhNcGOLVmBrFtsfYvuTLMJ2HbrKMr1shw==","signatures":[{"sig":"MEQCIGfM3GjcV9jVgFw++OkaFNKpUDQmz7X6paLLHrGucTjMAiARGLvEloJOGh3cAmQO36FhrgCRIQ6tV3WkqF/0jAvExg==","keyid":"SHA256:DhQ8wR5APBvFHLF/+Tc+AYvPOdTpcIDqOhxsBHRwC7U"}],"unpackedSize":237910},"main":"./dist/index.js","type":"module","_from":"file:diabolicallabs-llm-client-0.4.1.tgz","types":"./dist/index.d.ts","engines":{"node":">=20"},"exports":{".":{"types":"./dist/index.d.ts","import":"./dist/index.js"}},"scripts":{"lint":"biome check ./src && eslint ./src","test":"vitest run","build":"tsup","typecheck":"tsc --noEmit","test:watch":"vitest"},"_npmUser":{"name":"shackled78","email":"shackled78@gmail.com"},"_resolved":"/tmp/fe88f75e4d9d394e11b46bdc7c4ccc86/diabolicallabs-llm-client-0.4.1.tgz","publisher":"Diabolical Labs","_integrity":"sha512-wB81EQsm16s3J4n3DlEMGIf83E9hGK66UR6Ag3MO1+7fvPrFJz95ILhNcGOLVmBrFtsfYvuTLMJ2HbrKMr1shw==","repository":{"url":"git+https://github.com/mannism/dlabs-toolkit.git","type":"git","directory":"packages/llm-client"},"_npmVersion":"10.8.2","description":"Unified LLM API for Anthropic, OpenAI, Google, and DeepSeek. Streaming, retry/backoff, structured output, token normalization. © Diabolical Labs","directories":{},"_nodeVersion":"20.20.2","dependencies":{"zod":"^4.4.3","openai":"^6.36.0","@google/genai":"^1.52.0","@anthropic-ai/sdk":"^0.94.0"},"_hasShrinkwrap":false,"devDependencies":{"tsup":"^8.3.5","vitest":"^4.1.5","@types/node":"^25.6.0","@vitest/coverage-v8":"^4.1.5"},"_npmOperationalInternal":{"tmp":"tmp/llm-client_0.4.1_1778430691224_0.7339166463009921","host":"s3://npm-registry-packages-npm-production"}},"0.4.2":{"name":"@diabolicallabs/llm-client","version":"0.4.2","author":{"url":"https://deeismail.com","name":"Diana Ismail","email":"diana@deeismail.com"},"license":"MIT","_id":"@diabolicallabs/llm-client@0.4.2","maintainers":[{"name":"shackled78","email":"shackled78@gmail.com"}],"homepage":"https://github.com/mannism/dlabs-toolkit#readme","bugs":{"url":"https://github.com/mannism/dlabs-toolkit/issues"},"dist":{"shasum":"6a12ddc02a9aebc8064a158cddc455b9d63f3e67","tarball":"https://registry.npmjs.org/@diabolicallabs/llm-client/-/llm-client-0.4.2.tgz","fileCount":6,"integrity":"sha512-7cTLlWvTG27bjWGmAws/4Os2nfSY8ceyq/IyRoWwC1t10XPRgRgNg6zSKD8z9QFkmL4qBKZ3a8rn+n2IMh2xsw==","signatures":[{"sig":"MEYCIQC7nTg+zCjZhSNcGgJlwE6f+ThuzGSdO/gVUXxlRpzgOQIhAN098i/GmjMQgWgQMHK4v8o34+4GFjvMYuZHK82AAUnx","keyid":"SHA256:DhQ8wR5APBvFHLF/+Tc+AYvPOdTpcIDqOhxsBHRwC7U"}],"unpackedSize":243189},"main":"./dist/index.js","type":"module","_from":"file:diabolicallabs-llm-client-0.4.2.tgz","types":"./dist/index.d.ts","engines":{"node":">=20"},"exports":{".":{"types":"./dist/index.d.ts","import":"./dist/index.js"}},"scripts":{"lint":"biome check ./src && eslint ./src","test":"vitest run","build":"tsup","typecheck":"tsc --noEmit","test:watch":"vitest"},"_npmUser":{"name":"shackled78","email":"shackled78@gmail.com"},"_resolved":"/tmp/55cc31fce744e43119bc347f2733aced/diabolicallabs-llm-client-0.4.2.tgz","publisher":"Diabolical Labs","_integrity":"sha512-7cTLlWvTG27bjWGmAws/4Os2nfSY8ceyq/IyRoWwC1t10XPRgRgNg6zSKD8z9QFkmL4qBKZ3a8rn+n2IMh2xsw==","repository":{"url":"git+https://github.com/mannism/dlabs-toolkit.git","type":"git","directory":"packages/llm-client"},"_npmVersion":"10.8.2","description":"Unified LLM API for Anthropic, OpenAI, Google, and DeepSeek. Streaming, retry/backoff, structured output, token normalization. © Diabolical Labs","directories":{},"_nodeVersion":"20.20.2","dependencies":{"zod":"^4.4.3","openai":"^6.36.0","@google/genai":"^1.52.0","@anthropic-ai/sdk":"^0.94.0"},"_hasShrinkwrap":false,"devDependencies":{"tsup":"^8.3.5","vitest":"^4.1.5","@types/node":"^25.6.0","@vitest/coverage-v8":"^4.1.5"},"_npmOperationalInternal":{"tmp":"tmp/llm-client_0.4.2_1778436296489_0.8421579802169217","host":"s3://npm-registry-packages-npm-production"}},"0.4.3":{"name":"@diabolicallabs/llm-client","version":"0.4.3","author":{"url":"https://deeismail.com","name":"Diana Ismail","email":"diana@deeismail.com"},"license":"MIT","_id":"@diabolicallabs/llm-client@0.4.3","maintainers":[{"name":"shackled78","email":"shackled78@gmail.com"}],"homepage":"https://github.com/mannism/dlabs-toolkit#readme","bugs":{"url":"https://github.com/mannism/dlabs-toolkit/issues"},"dist":{"shasum":"b36ec2bc5ee1e1334244331feeb9bc94f53ccfd1","tarball":"https://registry.npmjs.org/@diabolicallabs/llm-client/-/llm-client-0.4.3.tgz","fileCount":6,"integrity":"sha512-p+49L3woD1ussO1JtZI7cxhJx9I5hn9s+GjHrhxH/aaPCwlLr9HL+zgWes0Vcwi4pWxZzP6uYoAI/mqa+AKh9Q==","signatures":[{"sig":"MEQCIEzTxRV2cKxt+YYc2Q6edR4eWb+13CLA+92QE6fjBSG2AiAXim7vz8ExGeJGleox4M1y/A7L2bCPfsVq2o2MEjwB7g==","keyid":"SHA256:DhQ8wR5APBvFHLF/+Tc+AYvPOdTpcIDqOhxsBHRwC7U"}],"unpackedSize":253675},"main":"./dist/index.js","type":"module","_from":"file:diabolicallabs-llm-client-0.4.3.tgz","types":"./dist/index.d.ts","engines":{"node":">=20"},"exports":{".":{"types":"./dist/index.d.ts","import":"./dist/index.js"}},"scripts":{"lint":"biome check ./src && eslint ./src","test":"vitest run","build":"tsup","typecheck":"tsc --noEmit","test:watch":"vitest"},"_npmUser":{"name":"shackled78","email":"shackled78@gmail.com"},"_resolved":"/tmp/71e606475f4f68cc9371a096440a8d43/diabolicallabs-llm-client-0.4.3.tgz","publisher":"Diabolical Labs","_integrity":"sha512-p+49L3woD1ussO1JtZI7cxhJx9I5hn9s+GjHrhxH/aaPCwlLr9HL+zgWes0Vcwi4pWxZzP6uYoAI/mqa+AKh9Q==","repository":{"url":"git+https://github.com/mannism/dlabs-toolkit.git","type":"git","directory":"packages/llm-client"},"_npmVersion":"10.8.2","description":"Unified LLM API for Anthropic, OpenAI, Google, and DeepSeek. Streaming, retry/backoff, structured output, token normalization. © Diabolical Labs","directories":{},"_nodeVersion":"20.20.2","dependencies":{"zod":"^4.4.3","openai":"^6.36.0","@google/genai":"^1.52.0","@anthropic-ai/sdk":"^0.94.0"},"_hasShrinkwrap":false,"devDependencies":{"tsup":"^8.3.5","vitest":"^4.1.5","@types/node":"^25.6.0","@vitest/coverage-v8":"^4.1.5"},"_npmOperationalInternal":{"tmp":"tmp/llm-client_0.4.3_1778464110626_0.8178656561617106","host":"s3://npm-registry-packages-npm-production"}},"0.4.4":{"name":"@diabolicallabs/llm-client","version":"0.4.4","author":{"url":"https://deeismail.com","name":"Diana Ismail","email":"diana@deeismail.com"},"license":"MIT","_id":"@diabolicallabs/llm-client@0.4.4","maintainers":[{"name":"shackled78","email":"shackled78@gmail.com"}],"homepage":"https://github.com/mannism/dlabs-toolkit#readme","bugs":{"url":"https://github.com/mannism/dlabs-toolkit/issues"},"dist":{"shasum":"45f4923a6d9e1f3e874d2431db2b996234fc24e0","tarball":"https://registry.npmjs.org/@diabolicallabs/llm-client/-/llm-client-0.4.4.tgz","fileCount":6,"integrity":"sha512-ETnMMhoE/eXP1bcSV//P8picKhjyU1m0UPmmrTB9EZunQljs8Qd9LnrfF2Ss5NEsImqJK5MdaIC1KVlrqevLPA==","signatures":[{"sig":"MEQCIBdi8lpaSb7lzsYrpL2RA0JaRy+STDg1uZcpRD+IEUT2AiAX+af8pS/CO0/GO+pDxcuhQoHtgPkdn/UD5JgfVaAlkw==","keyid":"SHA256:DhQ8wR5APBvFHLF/+Tc+AYvPOdTpcIDqOhxsBHRwC7U"}],"unpackedSize":260707},"main":"./dist/index.js","type":"module","_from":"file:diabolicallabs-llm-client-0.4.4.tgz","types":"./dist/index.d.ts","engines":{"node":">=20"},"exports":{".":{"types":"./dist/index.d.ts","import":"./dist/index.js"}},"scripts":{"lint":"biome check ./src && eslint ./src","test":"vitest run","build":"tsup","typecheck":"tsc --noEmit","test:watch":"vitest"},"_npmUser":{"name":"shackled78","email":"shackled78@gmail.com"},"_resolved":"/tmp/bd9c632bfe06de8cf07895780f90f0fb/diabolicallabs-llm-client-0.4.4.tgz","publisher":"Diabolical Labs","_integrity":"sha512-ETnMMhoE/eXP1bcSV//P8picKhjyU1m0UPmmrTB9EZunQljs8Qd9LnrfF2Ss5NEsImqJK5MdaIC1KVlrqevLPA==","repository":{"url":"git+https://github.com/mannism/dlabs-toolkit.git","type":"git","directory":"packages/llm-client"},"_npmVersion":"10.8.2","description":"Unified LLM API for Anthropic, OpenAI, Google, and DeepSeek. Streaming, retry/backoff, structured output, token normalization. © Diabolical Labs","directories":{},"_nodeVersion":"20.20.2","dependencies":{"zod":"^4.4.3","openai":"^6.36.0","@google/genai":"^1.52.0","@anthropic-ai/sdk":"^0.94.0"},"_hasShrinkwrap":false,"devDependencies":{"tsup":"^8.3.5","vitest":"^4.1.5","@types/node":"^25.6.0","@vitest/coverage-v8":"^4.1.5"},"_npmOperationalInternal":{"tmp":"tmp/llm-client_0.4.4_1778475476416_0.6510327802490787","host":"s3://npm-registry-packages-npm-production"}},"1.0.0":{"name":"@diabolicallabs/llm-client","version":"1.0.0","author":{"url":"https://deeismail.com","name":"Diana Ismail","email":"diana@deeismail.com"},"license":"MIT","_id":"@diabolicallabs/llm-client@1.0.0","maintainers":[{"name":"shackled78","email":"shackled78@gmail.com"}],"homepage":"https://github.com/mannism/dlabs-toolkit#readme","bugs":{"url":"https://github.com/mannism/dlabs-toolkit/issues"},"dist":{"shasum":"47e0164c158c4765227e8f7140f576f01113e6fb","tarball":"https://registry.npmjs.org/@diabolicallabs/llm-client/-/llm-client-1.0.0.tgz","fileCount":6,"integrity":"sha512-6rq2aHj3iRgBqQJwEeE2eQr5OboRE47wgzqT/OYrCBiVzX+ZIbITvOV5e48zazrZ6arrZTNLvPOhZtwyodjSEw==","signatures":[{"sig":"MEUCIGA/xJMzPTbRHEmtfpQkvMOM+1PdwLkyhlwFdT7AItsKAiEAmxCKSNHEVaAtNcfvcgqPl8m74p4MPaHnEsIUcUev5Kk=","keyid":"SHA256:DhQ8wR5APBvFHLF/+Tc+AYvPOdTpcIDqOhxsBHRwC7U"}],"unpackedSize":340559},"main":"./dist/index.js","type":"module","_from":"file:diabolicallabs-llm-client-1.0.0.tgz","types":"./dist/index.d.ts","engines":{"node":">=20"},"exports":{".":{"types":"./dist/index.d.ts","import":"./dist/index.js"}},"scripts":{"lint":"biome check ./src && eslint ./src","test":"vitest run","build":"tsup","typecheck":"tsc --noEmit","test:watch":"vitest"},"_npmUser":{"name":"shackled78","email":"shackled78@gmail.com"},"_resolved":"/tmp/c0d0f4fdfb582007c7b1fb10558ef6bf/diabolicallabs-llm-client-1.0.0.tgz","publisher":"Diabolical Labs","_integrity":"sha512-6rq2aHj3iRgBqQJwEeE2eQr5OboRE47wgzqT/OYrCBiVzX+ZIbITvOV5e48zazrZ6arrZTNLvPOhZtwyodjSEw==","repository":{"url":"git+https://github.com/mannism/dlabs-toolkit.git","type":"git","directory":"packages/llm-client"},"_npmVersion":"10.8.2","description":"Unified LLM API for Anthropic, OpenAI, Google, and DeepSeek. Streaming, retry/backoff, structured output, token normalization. © Diabolical Labs","directories":{},"_nodeVersion":"20.20.2","dependencies":{"zod":"^4.4.3","openai":"^6.37.0","@google/genai":"^2.2.0","@anthropic-ai/sdk":"^0.95.2"},"_hasShrinkwrap":false,"devDependencies":{"tsup":"^8.3.5","vitest":"^4.1.5","@types/node":"^25.6.2","@vitest/coverage-v8":"^4.1.5"},"_npmOperationalInternal":{"tmp":"tmp/llm-client_1.0.0_1778673188087_0.12106286964369017","host":"s3://npm-registry-packages-npm-production"}},"1.1.0":{"name":"@diabolicallabs/llm-client","version":"1.1.0","author":{"url":"https://deeismail.com","name":"Diana Ismail","email":"diana@deeismail.com"},"license":"MIT","_id":"@diabolicallabs/llm-client@1.1.0","maintainers":[{"name":"shackled78","email":"shackled78@gmail.com"}],"homepage":"https://github.com/mannism/dlabs-toolkit#readme","bugs":{"url":"https://github.com/mannism/dlabs-toolkit/issues"},"dist":{"shasum":"b969c7a4bcc58254d3a46c965e7a910fdc8b4a83","tarball":"https://registry.npmjs.org/@diabolicallabs/llm-client/-/llm-client-1.1.0.tgz","fileCount":6,"integrity":"sha512-2WiUktGWqRk4slhfauqt5IVza3nyrMj7bl6l+HO+/vClod7S8bzjqMLOSGeMBl3s3J89ENTRxbzFIws1OKdoIA==","signatures":[{"sig":"MEQCIHbhPh3tsLo3Qvh603pSrnay7b6WkKgaGx0RCRHFnFZ4AiAp5cLFjIKge5Bmp6d5AAT1wCMAQBw0vOzhXNfGqHfeBg==","keyid":"SHA256:DhQ8wR5APBvFHLF/+Tc+AYvPOdTpcIDqOhxsBHRwC7U"}],"unpackedSize":356959},"main":"./dist/index.js","type":"module","_from":"file:diabolicallabs-llm-client-1.1.0.tgz","types":"./dist/index.d.ts","engines":{"node":">=20"},"exports":{".":{"types":"./dist/index.d.ts","import":"./dist/index.js"}},"scripts":{"lint":"biome check ./src && eslint ./src","test":"vitest run","build":"tsup","typecheck":"tsc --noEmit","test:watch":"vitest"},"_npmUser":{"name":"shackled78","email":"shackled78@gmail.com"},"_resolved":"/tmp/c4599554bff381a6751c10c5152d8061/diabolicallabs-llm-client-1.1.0.tgz","publisher":"Diabolical Labs","_integrity":"sha512-2WiUktGWqRk4slhfauqt5IVza3nyrMj7bl6l+HO+/vClod7S8bzjqMLOSGeMBl3s3J89ENTRxbzFIws1OKdoIA==","repository":{"url":"git+https://github.com/mannism/dlabs-toolkit.git","type":"git","directory":"packages/llm-client"},"_npmVersion":"10.8.2","description":"Unified LLM API for Anthropic, OpenAI, Google, and DeepSeek. Streaming, retry/backoff, structured output, token normalization. © Diabolical Labs","directories":{},"_nodeVersion":"20.20.2","dependencies":{"zod":"^4.4.3","openai":"^6.37.0","@google/genai":"^2.2.0","@anthropic-ai/sdk":"^0.95.2"},"_hasShrinkwrap":false,"devDependencies":{"tsup":"^8.3.5","vitest":"^4.1.5","@types/node":"^25.6.2","@vitest/coverage-v8":"^4.1.5","@diabolicallabs/llm-pricing":"0.1.0"},"peerDependencies":{"@diabolicallabs/llm-pricing":"^0.1.0"},"peerDependenciesMeta":{"@diabolicallabs/llm-pricing":{"optional":true}},"_npmOperationalInternal":{"tmp":"tmp/llm-client_1.1.0_1778675962761_0.45409874164768205","host":"s3://npm-registry-packages-npm-production"}},"1.2.0":{"name":"@diabolicallabs/llm-client","version":"1.2.0","author":{"url":"https://deeismail.com","name":"Diana Ismail","email":"diana@deeismail.com"},"license":"MIT","_id":"@diabolicallabs/llm-client@1.2.0","maintainers":[{"name":"shackled78","email":"shackled78@gmail.com"}],"homepage":"https://github.com/mannism/dlabs-toolkit#readme","bugs":{"url":"https://github.com/mannism/dlabs-toolkit/issues"},"dist":{"shasum":"e0b3a63a14dda6f2ea330558554e69a0ba46abdc","tarball":"https://registry.npmjs.org/@diabolicallabs/llm-client/-/llm-client-1.2.0.tgz","fileCount":9,"integrity":"sha512-mjG4GJgm06CZADd+7KBZn3R8Lgyw3IxISQnsUixV/twYxgNsVgAi82cyzZeIV7uw7ZtLl9wB0IoP2XAO0MUwmg==","signatures":[{"sig":"MEQCIGFWM1wrLrU0fR8rniVSS6LiJWRJWbMKYSItNKRor0EzAiBNvDHpI2VPtT6D55X3f48JxwPCNyxDk/m7U9FKAfAVEw==","keyid":"SHA256:DhQ8wR5APBvFHLF/+Tc+AYvPOdTpcIDqOhxsBHRwC7U"}],"unpackedSize":422666},"main":"./dist/index.js","type":"module","_from":"file:diabolicallabs-llm-client-1.2.0.tgz","types":"./dist/index.d.ts","engines":{"node":">=20"},"exports":{".":{"types":"./dist/index.d.ts","import":"./dist/index.js"},"./pool":{"types":"./dist/pool/index.d.ts","import":"./dist/pool/index.js"}},"scripts":{"lint":"biome check ./src && eslint ./src","test":"vitest run","build":"tsup","typecheck":"tsc --noEmit","test:watch":"vitest"},"_npmUser":{"name":"shackled78","email":"shackled78@gmail.com"},"_resolved":"/tmp/ec317739d08642f432d435c8e0645bcf/diabolicallabs-llm-client-1.2.0.tgz","publisher":"Diabolical Labs","_integrity":"sha512-mjG4GJgm06CZADd+7KBZn3R8Lgyw3IxISQnsUixV/twYxgNsVgAi82cyzZeIV7uw7ZtLl9wB0IoP2XAO0MUwmg==","repository":{"url":"git+https://github.com/mannism/dlabs-toolkit.git","type":"git","directory":"packages/llm-client"},"_npmVersion":"10.8.2","description":"Unified LLM API for Anthropic, OpenAI, Google, and DeepSeek. Streaming, retry/backoff, structured output, token normalization. © Diabolical Labs","directories":{},"_nodeVersion":"20.20.2","dependencies":{"zod":"^4.4.3","openai":"^6.37.0","@google/genai":"^2.2.0","@anthropic-ai/sdk":"^0.95.2"},"_hasShrinkwrap":false,"devDependencies":{"tsup":"^8.3.5","vitest":"^4.1.5","@types/node":"^25.6.2","@vitest/coverage-v8":"^4.1.5","@diabolicallabs/llm-pricing":"0.1.0"},"peerDependencies":{"@diabolicallabs/llm-pricing":"^0.1.0"},"peerDependenciesMeta":{"@diabolicallabs/llm-pricing":{"optional":true}},"_npmOperationalInternal":{"tmp":"tmp/llm-client_1.2.0_1778679018055_0.7488263007497213","host":"s3://npm-registry-packages-npm-production"}},"1.3.0":{"name":"@diabolicallabs/llm-client","version":"1.3.0","author":{"url":"https://deeismail.com","name":"Diana Ismail","email":"diana@deeismail.com"},"license":"MIT","_id":"@diabolicallabs/llm-client@1.3.0","maintainers":[{"name":"shackled78","email":"shackled78@gmail.com"}],"homepage":"https://github.com/mannism/dlabs-toolkit#readme","bugs":{"url":"https://github.com/mannism/dlabs-toolkit/issues"},"dist":{"shasum":"f0ad2b2311935eebf3146d2d0102065014c04e3a","tarball":"https://registry.npmjs.org/@diabolicallabs/llm-client/-/llm-client-1.3.0.tgz","fileCount":9,"integrity":"sha512-D2S0SSRmhk0Nrz70QCsnJ3nUUIiUQSdyXUy+kr2T3yILy1ORHM5C5bG0EgCUOTDKzNv2lNBSk+ANK+toN/Wxkg==","signatures":[{"sig":"MEUCIQCBOeh2voEy8z/8YWdtDS6mVzufMs5VObCdPo4d/E4kbgIgEW409enHXLRTcj9X8mYD6o8JawBA/4ttflsYXIovZg0=","keyid":"SHA256:DhQ8wR5APBvFHLF/+Tc+AYvPOdTpcIDqOhxsBHRwC7U"}],"unpackedSize":465550},"main":"./dist/index.js","type":"module","_from":"file:diabolicallabs-llm-client-1.3.0.tgz","types":"./dist/index.d.ts","engines":{"node":">=20"},"exports":{".":{"types":"./dist/index.d.ts","import":"./dist/index.js"},"./pool":{"types":"./dist/pool/index.d.ts","import":"./dist/pool/index.js"}},"scripts":{"lint":"biome check ./src && eslint ./src","test":"vitest run","build":"tsup","typecheck":"tsc --noEmit","test:watch":"vitest"},"_npmUser":{"name":"shackled78","email":"shackled78@gmail.com"},"_resolved":"/tmp/d790a1775aea9b6b84f13840eed673b7/diabolicallabs-llm-client-1.3.0.tgz","publisher":"Diabolical Labs","_integrity":"sha512-D2S0SSRmhk0Nrz70QCsnJ3nUUIiUQSdyXUy+kr2T3yILy1ORHM5C5bG0EgCUOTDKzNv2lNBSk+ANK+toN/Wxkg==","repository":{"url":"git+https://github.com/mannism/dlabs-toolkit.git","type":"git","directory":"packages/llm-client"},"_npmVersion":"10.8.2","description":"Unified LLM API for Anthropic, OpenAI, Google, and DeepSeek. Streaming, retry/backoff, structured output, token normalization. © Diabolical Labs","directories":{},"_nodeVersion":"20.20.2","dependencies":{"zod":"^4.4.3","openai":"^6.37.0","@google/genai":"^2.2.0","@anthropic-ai/sdk":"^0.95.2"},"_hasShrinkwrap":false,"devDependencies":{"tsup":"^8.3.5","vitest":"^4.1.5","@types/node":"^25.6.2","@vitest/coverage-v8":"^4.1.5","@diabolicallabs/llm-pricing":"0.1.0"},"peerDependencies":{"@diabolicallabs/llm-pricing":"^0.1.0"},"peerDependenciesMeta":{"@diabolicallabs/llm-pricing":{"optional":true}},"_npmOperationalInternal":{"tmp":"tmp/llm-client_1.3.0_1778682321778_0.7743885200668774","host":"s3://npm-registry-packages-npm-production"}},"1.4.0":{"name":"@diabolicallabs/llm-client","version":"1.4.0","author":{"url":"https://deeismail.com","name":"Diana Ismail","email":"diana@deeismail.com"},"license":"MIT","_id":"@diabolicallabs/llm-client@1.4.0","maintainers":[{"name":"shackled78","email":"shackled78@gmail.com"}],"homepage":"https://github.com/mannism/dlabs-toolkit#readme","bugs":{"url":"https://github.com/mannism/dlabs-toolkit/issues"},"dist":{"shasum":"1c0722ecf00385cbbaedd73f08469c8c6d77d63f","tarball":"https://registry.npmjs.org/@diabolicallabs/llm-client/-/llm-client-1.4.0.tgz","fileCount":9,"integrity":"sha512-Rl7Fz3AdIg4bJ4dOK7+NAVoGmjcDOkeNwF5VWaeUPBneDgBPWqDIf9qbXB1NhOTRnyzEch6XwP0JeCoX09RkhA==","signatures":[{"sig":"MEUCIAUiqJEqdPgtq7D8qq0mJV8oHQgfCx1kmWjJlBOmuBxHAiEAtW15YHOmCRzwD4xIQ70u80rhQv8rOwC0ppCnsFVoW2A=","keyid":"SHA256:DhQ8wR5APBvFHLF/+Tc+AYvPOdTpcIDqOhxsBHRwC7U"}],"unpackedSize":527070},"main":"./dist/index.js","type":"module","_from":"file:diabolicallabs-llm-client-1.4.0.tgz","types":"./dist/index.d.ts","engines":{"node":">=20"},"exports":{".":{"types":"./dist/index.d.ts","import":"./dist/index.js"},"./pool":{"types":"./dist/pool/index.d.ts","import":"./dist/pool/index.js"}},"scripts":{"lint":"biome check ./src && eslint ./src","test":"vitest run","build":"tsup","typecheck":"tsc --noEmit","test:watch":"vitest"},"_npmUser":{"name":"shackled78","email":"shackled78@gmail.com"},"_resolved":"/tmp/dc79fa9e8bcdebfcf542b0dfb5ec97a5/diabolicallabs-llm-client-1.4.0.tgz","publisher":"Diabolical Labs","_integrity":"sha512-Rl7Fz3AdIg4bJ4dOK7+NAVoGmjcDOkeNwF5VWaeUPBneDgBPWqDIf9qbXB1NhOTRnyzEch6XwP0JeCoX09RkhA==","repository":{"url":"git+https://github.com/mannism/dlabs-toolkit.git","type":"git","directory":"packages/llm-client"},"_npmVersion":"10.8.2","description":"Unified LLM API for Anthropic, OpenAI, Google, and DeepSeek. Streaming, retry/backoff, structured output, token normalization. © Diabolical Labs","directories":{},"_nodeVersion":"20.20.2","dependencies":{"zod":"^4.4.3","openai":"^6.37.0","@google/genai":"^2.2.0","@anthropic-ai/sdk":"^0.95.2"},"_hasShrinkwrap":false,"devDependencies":{"tsup":"^8.3.5","vitest":"^4.1.5","@types/node":"^25.6.2","@vitest/coverage-v8":"^4.1.5","@diabolicallabs/llm-pricing":"0.1.0"},"peerDependencies":{"@diabolicallabs/llm-pricing":"^0.1.0"},"peerDependenciesMeta":{"@diabolicallabs/llm-pricing":{"optional":true}},"_npmOperationalInternal":{"tmp":"tmp/llm-client_1.4.0_1778685673361_0.33574025380714967","host":"s3://npm-registry-packages-npm-production"}},"1.5.0":{"name":"@diabolicallabs/llm-client","version":"1.5.0","author":{"url":"https://deeismail.com","name":"Diana Ismail","email":"diana@deeismail.com"},"license":"MIT","_id":"@diabolicallabs/llm-client@1.5.0","maintainers":[{"name":"shackled78","email":"shackled78@gmail.com"}],"homepage":"https://github.com/mannism/dlabs-toolkit#readme","bugs":{"url":"https://github.com/mannism/dlabs-toolkit/issues"},"dist":{"shasum":"181b9875e6392157aeab7657b95f4bb7a4ab55f3","tarball":"https://registry.npmjs.org/@diabolicallabs/llm-client/-/llm-client-1.5.0.tgz","fileCount":9,"integrity":"sha512-E405O+g1YjVM1xBWGNxpFdw9+bpt/93lk7sMUu3mEhj38vQtV2dax/O3SoSm5RjZJBcvS7rDpoRa7CwJySs9qw==","signatures":[{"sig":"MEUCIHszgc5X4h4a55uRU7Wu88+Tg61ShUng24CU9JsrodjlAiEA9xDTH9Zw8gw6VS9rkqu/UvCuerKQIH/NBwy/5oGenmg=","keyid":"SHA256:DhQ8wR5APBvFHLF/+Tc+AYvPOdTpcIDqOhxsBHRwC7U"}],"unpackedSize":570791},"main":"./dist/index.js","type":"module","_from":"file:diabolicallabs-llm-client-1.5.0.tgz","types":"./dist/index.d.ts","engines":{"node":">=20"},"exports":{".":{"types":"./dist/index.d.ts","import":"./dist/index.js"},"./pool":{"types":"./dist/pool/index.d.ts","import":"./dist/pool/index.js"}},"scripts":{"lint":"biome check ./src && eslint ./src","test":"vitest run","build":"tsup","typecheck":"tsc --noEmit","test:watch":"vitest"},"_npmUser":{"name":"shackled78","email":"shackled78@gmail.com"},"_resolved":"/tmp/f5390a769f7170f944ba2b284140a74a/diabolicallabs-llm-client-1.5.0.tgz","publisher":"Diabolical Labs","_integrity":"sha512-E405O+g1YjVM1xBWGNxpFdw9+bpt/93lk7sMUu3mEhj38vQtV2dax/O3SoSm5RjZJBcvS7rDpoRa7CwJySs9qw==","repository":{"url":"git+https://github.com/mannism/dlabs-toolkit.git","type":"git","directory":"packages/llm-client"},"_npmVersion":"10.8.2","description":"Unified LLM API for Anthropic, OpenAI, Google, and DeepSeek. Streaming, retry/backoff, structured output, token normalization. © Diabolical Labs","directories":{},"_nodeVersion":"20.20.2","dependencies":{"zod":"^4.4.3","openai":"^6.37.0","@google/genai":"^2.2.0","@anthropic-ai/sdk":"^0.95.2"},"_hasShrinkwrap":false,"devDependencies":{"tsup":"^8.3.5","vitest":"^4.1.5","@types/node":"^25.6.2","@vitest/coverage-v8":"^4.1.5","@diabolicallabs/llm-pricing":"0.1.0"},"peerDependencies":{"@diabolicallabs/llm-pricing":"^0.1.0"},"peerDependenciesMeta":{"@diabolicallabs/llm-pricing":{"optional":true}},"_npmOperationalInternal":{"tmp":"tmp/llm-client_1.5.0_1778692479128_0.9458148995836662","host":"s3://npm-registry-packages-npm-production"}},"1.6.0":{"name":"@diabolicallabs/llm-client","version":"1.6.0","author":{"url":"https://deeismail.com","name":"Diana Ismail","email":"diana@deeismail.com"},"license":"MIT","_id":"@diabolicallabs/llm-client@1.6.0","maintainers":[{"name":"shackled78","email":"shackled78@gmail.com"}],"homepage":"https://github.com/mannism/dlabs-toolkit#readme","bugs":{"url":"https://github.com/mannism/dlabs-toolkit/issues"},"dist":{"shasum":"211eb259468e6bfbccbbb3c4f4cabc02d24a4713","tarball":"https://registry.npmjs.org/@diabolicallabs/llm-client/-/llm-client-1.6.0.tgz","fileCount":9,"integrity":"sha512-fdP82Q1C7CUPC3gsns+KofvOOicSpnTfHrshUB+4IsMt2nC1fHils8Gm62GU930He1vRCNAqiqbL5iPoB2Gufw==","signatures":[{"sig":"MEYCIQCcOmkhixM4AbKgT3JF4lsE5PzJzwehwRtQAV7uCaAV5gIhAJh3JsZLGawAtAvIL/ZKj5EO19/sPwLdXTMP9NFNSCrp","keyid":"SHA256:DhQ8wR5APBvFHLF/+Tc+AYvPOdTpcIDqOhxsBHRwC7U"}],"unpackedSize":576964},"main":"./dist/index.js","type":"module","_from":"file:diabolicallabs-llm-client-1.6.0.tgz","types":"./dist/index.d.ts","engines":{"node":">=20"},"exports":{".":{"types":"./dist/index.d.ts","import":"./dist/index.js"},"./pool":{"types":"./dist/pool/index.d.ts","import":"./dist/pool/index.js"}},"scripts":{"lint":"biome check ./src && eslint ./src","test":"vitest run","build":"tsup","typecheck":"tsc --noEmit","test:watch":"vitest"},"_npmUser":{"name":"shackled78","email":"shackled78@gmail.com"},"_resolved":"/tmp/c07bbd93ffa369434342b49c6514a3b1/diabolicallabs-llm-client-1.6.0.tgz","publisher":"Diabolical Labs","_integrity":"sha512-fdP82Q1C7CUPC3gsns+KofvOOicSpnTfHrshUB+4IsMt2nC1fHils8Gm62GU930He1vRCNAqiqbL5iPoB2Gufw==","repository":{"url":"git+https://github.com/mannism/dlabs-toolkit.git","type":"git","directory":"packages/llm-client"},"_npmVersion":"10.8.2","description":"Unified LLM API for Anthropic, OpenAI, Google, and DeepSeek. Streaming, retry/backoff, structured output, token normalization. © Diabolical Labs","directories":{},"_nodeVersion":"20.20.2","dependencies":{"zod":"^4.4.3","openai":"^6.37.0","@google/genai":"^2.2.0","@anthropic-ai/sdk":"^0.95.2"},"_hasShrinkwrap":false,"devDependencies":{"tsup":"^8.3.5","vitest":"^4.1.5","@types/node":"^25.6.2","@vitest/coverage-v8":"^4.1.5","@diabolicallabs/llm-pricing":"0.1.0"},"peerDependencies":{"@diabolicallabs/llm-pricing":"^0.1.0"},"peerDependenciesMeta":{"@diabolicallabs/llm-pricing":{"optional":true}},"_npmOperationalInternal":{"tmp":"tmp/llm-client_1.6.0_1778718141021_0.13597332483094915","host":"s3://npm-registry-packages-npm-production"}},"1.7.0":{"name":"@diabolicallabs/llm-client","version":"1.7.0","author":{"url":"https://deeismail.com","name":"Diana Ismail","email":"diana@deeismail.com"},"license":"MIT","_id":"@diabolicallabs/llm-client@1.7.0","maintainers":[{"name":"shackled78","email":"shackled78@gmail.com"}],"homepage":"https://github.com/mannism/dlabs-toolkit#readme","bugs":{"url":"https://github.com/mannism/dlabs-toolkit/issues"},"dist":{"shasum":"c69e70c1d0bc18634b54d7bab3664206b87e1de9","tarball":"https://registry.npmjs.org/@diabolicallabs/llm-client/-/llm-client-1.7.0.tgz","fileCount":9,"integrity":"sha512-yX43UIIrs/e1hqyCo/UQ624ptwPkuAFNGYMTEiHYEG00BbjVZg5qhyemOFlUWjqKY5WO57O216xdLeNO5bgA0A==","signatures":[{"sig":"MEQCICON6bz2ZK3iNydTLjc/30BniUxMC/qRLKhQJuZ5bWp2AiAAlPboMoLC8O44hL5IYzGg6NwCV2H0PmwXm0LIpIpeAA==","keyid":"SHA256:DhQ8wR5APBvFHLF/+Tc+AYvPOdTpcIDqOhxsBHRwC7U"}],"unpackedSize":588549},"main":"./dist/index.js","type":"module","_from":"file:diabolicallabs-llm-client-1.7.0.tgz","types":"./dist/index.d.ts","engines":{"node":">=20"},"exports":{".":{"types":"./dist/index.d.ts","import":"./dist/index.js"},"./pool":{"types":"./dist/pool/index.d.ts","import":"./dist/pool/index.js"}},"scripts":{"lint":"biome check ./src && eslint ./src","test":"vitest run","build":"tsup","typecheck":"tsc --noEmit","test:watch":"vitest"},"_npmUser":{"name":"shackled78","email":"shackled78@gmail.com"},"_resolved":"/tmp/4a24659b34739b7c7d03192f70044378/diabolicallabs-llm-client-1.7.0.tgz","publisher":"Diabolical Labs","_integrity":"sha512-yX43UIIrs/e1hqyCo/UQ624ptwPkuAFNGYMTEiHYEG00BbjVZg5qhyemOFlUWjqKY5WO57O216xdLeNO5bgA0A==","repository":{"url":"git+https://github.com/mannism/dlabs-toolkit.git","type":"git","directory":"packages/llm-client"},"_npmVersion":"10.8.2","description":"Unified LLM API for Anthropic, OpenAI, Google, and DeepSeek. Streaming, retry/backoff, structured output, token normalization. © Diabolical Labs","directories":{},"_nodeVersion":"20.20.2","dependencies":{"zod":"^4.4.3","openai":"^6.37.0","@google/genai":"^2.2.0","@anthropic-ai/sdk":"^0.95.2"},"_hasShrinkwrap":false,"devDependencies":{"tsup":"^8.3.5","vitest":"^4.1.5","@types/node":"^25.6.2","@vitest/coverage-v8":"^4.1.5","@diabolicallabs/llm-pricing":"0.2.0"},"peerDependencies":{"@diabolicallabs/llm-pricing":"^0.2.0"},"peerDependenciesMeta":{"@diabolicallabs/llm-pricing":{"optional":true}},"_npmOperationalInternal":{"tmp":"tmp/llm-client_1.7.0_1778749878023_0.44027384173051076","host":"s3://npm-registry-packages-npm-production"}},"2.0.0":{"name":"@diabolicallabs/llm-client","version":"2.0.0","author":{"url":"https://deeismail.com","name":"Diana Ismail","email":"diana@deeismail.com"},"license":"MIT","_id":"@diabolicallabs/llm-client@2.0.0","maintainers":[{"name":"shackled78","email":"shackled78@gmail.com"}],"homepage":"https://github.com/mannism/dlabs-toolkit#readme","bugs":{"url":"https://github.com/mannism/dlabs-toolkit/issues"},"dist":{"shasum":"422855349ef07f6349edbe74b9e22bb5e5c0e03e","tarball":"https://registry.npmjs.org/@diabolicallabs/llm-client/-/llm-client-2.0.0.tgz","fileCount":9,"integrity":"sha512-tY2G5bdUctZ6npZsH8wITvzs0+O4NvWwpYnZzlMiWD6ZZWzP5q8V3FHj8AtZnQgJXQbUnq6xsKvm+4zp8nqbMQ==","signatures":[{"sig":"MEUCIQDCS6VWRHVxwYWPosnwGVHEZ0iPGX8PbqiVE+VqD8DBJAIgbT54uynFZAUkZCEod1dkIdnSzTCb4e90xvYL4kmJ/GQ=","keyid":"SHA256:DhQ8wR5APBvFHLF/+Tc+AYvPOdTpcIDqOhxsBHRwC7U"}],"unpackedSize":588549},"main":"./dist/index.js","type":"module","_from":"file:diabolicallabs-llm-client-2.0.0.tgz","types":"./dist/index.d.ts","engines":{"node":">=20"},"exports":{".":{"types":"./dist/index.d.ts","import":"./dist/index.js"},"./pool":{"types":"./dist/pool/index.d.ts","import":"./dist/pool/index.js"}},"scripts":{"lint":"biome check ./src && eslint ./src","test":"vitest run","build":"tsup","typecheck":"tsc --noEmit","test:watch":"vitest"},"_npmUser":{"name":"shackled78","email":"shackled78@gmail.com"},"_resolved":"/tmp/bb027be3f2694cb01ffdde1ab6e3a349/diabolicallabs-llm-client-2.0.0.tgz","publisher":"Diabolical Labs","_integrity":"sha512-tY2G5bdUctZ6npZsH8wITvzs0+O4NvWwpYnZzlMiWD6ZZWzP5q8V3FHj8AtZnQgJXQbUnq6xsKvm+4zp8nqbMQ==","repository":{"url":"git+https://github.com/mannism/dlabs-toolkit.git","type":"git","directory":"packages/llm-client"},"_npmVersion":"10.8.2","description":"Unified LLM API for Anthropic, OpenAI, Google, and DeepSeek. Streaming, retry/backoff, structured output, token normalization. © Diabolical Labs","directories":{},"_nodeVersion":"20.20.2","dependencies":{"zod":"^4.4.3","openai":"^6.37.0","@google/genai":"^2.2.0","@anthropic-ai/sdk":"^0.95.2"},"_hasShrinkwrap":false,"devDependencies":{"tsup":"^8.3.5","vitest":"^4.1.5","@types/node":"^25.6.2","@vitest/coverage-v8":"^4.1.5","@diabolicallabs/llm-pricing":"0.3.0"},"peerDependencies":{"@diabolicallabs/llm-pricing":"^0.3.0"},"peerDependenciesMeta":{"@diabolicallabs/llm-pricing":{"optional":true}},"_npmOperationalInternal":{"tmp":"tmp/llm-client_2.0.0_1779037443931_0.30474385141088733","host":"s3://npm-registry-packages-npm-production"}},"3.0.0":{"name":"@diabolicallabs/llm-client","version":"3.0.0","author":{"url":"https://deeismail.com","name":"Diana Ismail","email":"diana@deeismail.com"},"license":"MIT","_id":"@diabolicallabs/llm-client@3.0.0","maintainers":[{"name":"shackled78","email":"shackled78@gmail.com"}],"homepage":"https://github.com/mannism/dlabs-toolkit#readme","bugs":{"url":"https://github.com/mannism/dlabs-toolkit/issues"},"dist":{"shasum":"f1a50bbeb9f52469bc4e05744a85af145e10f526","tarball":"https://registry.npmjs.org/@diabolicallabs/llm-client/-/llm-client-3.0.0.tgz","fileCount":9,"integrity":"sha512-P3kNexznz4JFgpQNWR35RQMTM0SfUWFHy6gD1dPOtuGaqZ/CaLgqBdiMsZDJzwZssRaVIa7uugywvWbvdZBX6Q==","signatures":[{"sig":"MEUCIQDuiQJxu6Z9ipnPrXN4tGESJpjOewnHocyIiFrQV0beIQIgaXyBSu/H23x9iZ3jSYrMAcP588W7z/x33oVl1odcq3I=","keyid":"SHA256:DhQ8wR5APBvFHLF/+Tc+AYvPOdTpcIDqOhxsBHRwC7U"}],"unpackedSize":588549},"main":"./dist/index.js","type":"module","_from":"file:diabolicallabs-llm-client-3.0.0.tgz","types":"./dist/index.d.ts","engines":{"node":">=20"},"exports":{".":{"types":"./dist/index.d.ts","import":"./dist/index.js"},"./pool":{"types":"./dist/pool/index.d.ts","import":"./dist/pool/index.js"}},"scripts":{"lint":"biome check ./src && eslint ./src","test":"vitest run","build":"tsup","typecheck":"tsc --noEmit","test:watch":"vitest"},"_npmUser":{"name":"shackled78","email":"shackled78@gmail.com"},"_resolved":"/tmp/c9bf2f0c368817bb2f9b0d09699b4fd4/diabolicallabs-llm-client-3.0.0.tgz","publisher":"Diabolical Labs","_integrity":"sha512-P3kNexznz4JFgpQNWR35RQMTM0SfUWFHy6gD1dPOtuGaqZ/CaLgqBdiMsZDJzwZssRaVIa7uugywvWbvdZBX6Q==","repository":{"url":"git+https://github.com/mannism/dlabs-toolkit.git","type":"git","directory":"packages/llm-client"},"_npmVersion":"10.8.2","description":"Unified LLM API for Anthropic, OpenAI, Google, and DeepSeek. Streaming, retry/backoff, structured output, token normalization. © Diabolical Labs","directories":{},"_nodeVersion":"20.20.2","dependencies":{"zod":"^4.4.3","openai":"^6.37.0","@google/genai":"^2.2.0","@anthropic-ai/sdk":"^0.95.2"},"_hasShrinkwrap":false,"devDependencies":{"tsup":"^8.3.5","vitest":"^4.1.5","@types/node":"^25.6.2","@vitest/coverage-v8":"^4.1.5","@diabolicallabs/llm-pricing":"0.4.0"},"peerDependencies":{"@diabolicallabs/llm-pricing":"^0.4.0"},"peerDependenciesMeta":{"@diabolicallabs/llm-pricing":{"optional":true}},"_npmOperationalInternal":{"tmp":"tmp/llm-client_3.0.0_1779111738299_0.56752101810599","host":"s3://npm-registry-packages-npm-production"}},"3.0.1":{"name":"@diabolicallabs/llm-client","version":"3.0.1","author":{"url":"https://deeismail.com","name":"Diana Ismail","email":"diana@deeismail.com"},"license":"MIT","_id":"@diabolicallabs/llm-client@3.0.1","maintainers":[{"name":"shackled78","email":"shackled78@gmail.com"}],"homepage":"https://github.com/mannism/dlabs-toolkit#readme","bugs":{"url":"https://github.com/mannism/dlabs-toolkit/issues"},"dist":{"shasum":"95e04948521f2d30956b2b6037f23b098ab4ec1f","tarball":"https://registry.npmjs.org/@diabolicallabs/llm-client/-/llm-client-3.0.1.tgz","fileCount":9,"integrity":"sha512-6Z5MT34Cf8F0XfZrAbeKfdxC4ff7G4SDhFwMrP0OdIZGQwMnGF2loWF1CBSTuArg1ERoYpV2oH5ujv3pxCYK4g==","signatures":[{"sig":"MEUCIQD40UWJCCKxJ1ECXJzDYL5Mau7CkOhcKC9MWiKdfGhhdQIgPJY8iTBXVONHv/QaJphkWVGthF8ZFPL8t4c00/ypU0I=","keyid":"SHA256:DhQ8wR5APBvFHLF/+Tc+AYvPOdTpcIDqOhxsBHRwC7U"}],"unpackedSize":588549},"main":"./dist/index.js","type":"module","_from":"file:diabolicallabs-llm-client-3.0.1.tgz","types":"./dist/index.d.ts","engines":{"node":">=20"},"exports":{".":{"types":"./dist/index.d.ts","import":"./dist/index.js"},"./pool":{"types":"./dist/pool/index.d.ts","import":"./dist/pool/index.js"}},"scripts":{"lint":"biome check ./src && eslint ./src","test":"vitest run","build":"tsup","typecheck":"tsc --noEmit","test:watch":"vitest"},"_npmUser":{"name":"shackled78","email":"shackled78@gmail.com"},"_resolved":"/tmp/5fe735efc9c504338e0e8a8e5f48574b/diabolicallabs-llm-client-3.0.1.tgz","publisher":"Diabolical Labs","_integrity":"sha512-6Z5MT34Cf8F0XfZrAbeKfdxC4ff7G4SDhFwMrP0OdIZGQwMnGF2loWF1CBSTuArg1ERoYpV2oH5ujv3pxCYK4g==","repository":{"url":"git+https://github.com/mannism/dlabs-toolkit.git","type":"git","directory":"packages/llm-client"},"_npmVersion":"10.8.2","description":"Unified LLM API for Anthropic, OpenAI, Google, and DeepSeek. Streaming, retry/backoff, structured output, token normalization. © Diabolical Labs","directories":{},"_nodeVersion":"20.20.2","dependencies":{"zod":"^4.4.3","openai":"^6.37.0","@google/genai":"^2.2.0","@anthropic-ai/sdk":"^0.95.2"},"_hasShrinkwrap":false,"devDependencies":{"tsup":"^8.3.5","vitest":"^4.1.5","@types/node":"^25.6.2","@vitest/coverage-v8":"^4.1.5","@diabolicallabs/llm-pricing":"1.0.0"},"peerDependencies":{"@diabolicallabs/llm-pricing":"^1.0.0"},"peerDependenciesMeta":{"@diabolicallabs/llm-pricing":{"optional":true}},"_npmOperationalInternal":{"tmp":"tmp/llm-client_3.0.1_1779114020020_0.43881257746532776","host":"s3://npm-registry-packages-npm-production"}},"4.0.0":{"name":"@diabolicallabs/llm-client","version":"4.0.0","author":{"url":"https://deeismail.com","name":"Diana Ismail","email":"diana@deeismail.com"},"license":"MIT","_id":"@diabolicallabs/llm-client@4.0.0","maintainers":[{"name":"shackled78","email":"shackled78@gmail.com"}],"homepage":"https://github.com/mannism/dlabs-toolkit#readme","bugs":{"url":"https://github.com/mannism/dlabs-toolkit/issues"},"dist":{"shasum":"b5628f621cc5e64123ec690af2ecdd863b7173ef","tarball":"https://registry.npmjs.org/@diabolicallabs/llm-client/-/llm-client-4.0.0.tgz","fileCount":9,"integrity":"sha512-OqnC60hvP12hR9wrDKpSOB32T4t1r98WW0vnuphAItbmeSrTFJKf4KbqGnRk5zp/+KEeLaMyH+JxWTTe/xdBnA==","signatures":[{"sig":"MEYCIQDxxj/zR1RC/q8OK0Fe+qXmReHxTf6J5LAN9ge1Q5//LgIhAL7h+Trkvoufa17U5u/t3f8uF85cjEudAlmgjKCwr44+","keyid":"SHA256:DhQ8wR5APBvFHLF/+Tc+AYvPOdTpcIDqOhxsBHRwC7U"}],"unpackedSize":588549},"main":"./dist/index.js","type":"module","_from":"file:diabolicallabs-llm-client-4.0.0.tgz","types":"./dist/index.d.ts","engines":{"node":">=20"},"exports":{".":{"types":"./dist/index.d.ts","import":"./dist/index.js"},"./pool":{"types":"./dist/pool/index.d.ts","import":"./dist/pool/index.js"}},"scripts":{"lint":"biome check ./src && eslint ./src","test":"vitest run","build":"tsup","typecheck":"tsc --noEmit","test:watch":"vitest"},"_npmUser":{"name":"shackled78","email":"shackled78@gmail.com"},"_resolved":"/tmp/ff300ab70ec06d7d4031e2477d8d5700/diabolicallabs-llm-client-4.0.0.tgz","publisher":"Diabolical Labs","_integrity":"sha512-OqnC60hvP12hR9wrDKpSOB32T4t1r98WW0vnuphAItbmeSrTFJKf4KbqGnRk5zp/+KEeLaMyH+JxWTTe/xdBnA==","repository":{"url":"git+https://github.com/mannism/dlabs-toolkit.git","type":"git","directory":"packages/llm-client"},"_npmVersion":"10.8.2","description":"Unified LLM API for Anthropic, OpenAI, Google, and DeepSeek. Streaming, retry/backoff, structured output, token normalization. © Diabolical Labs","directories":{},"_nodeVersion":"20.20.2","dependencies":{"zod":"^4.4.3","openai":"^6.37.0","@google/genai":"^2.2.0","@anthropic-ai/sdk":"^0.95.2"},"_hasShrinkwrap":false,"devDependencies":{"tsup":"^8.3.5","vitest":"^4.1.5","@types/node":"^25.6.2","@vitest/coverage-v8":"^4.1.5","@diabolicallabs/llm-pricing":"1.1.0"},"peerDependencies":{"@diabolicallabs/llm-pricing":"^1.1.0"},"peerDependenciesMeta":{"@diabolicallabs/llm-pricing":{"optional":true}},"_npmOperationalInternal":{"tmp":"tmp/llm-client_4.0.0_1779160794150_0.9951268400945645","host":"s3://npm-registry-packages-npm-production"}},"4.1.0":{"name":"@diabolicallabs/llm-client","version":"4.1.0","author":{"url":"https://deeismail.com","name":"Diana Ismail","email":"diana@deeismail.com"},"license":"MIT","_id":"@diabolicallabs/llm-client@4.1.0","maintainers":[{"name":"shackled78","email":"shackled78@gmail.com"}],"homepage":"https://github.com/mannism/dlabs-toolkit#readme","bugs":{"url":"https://github.com/mannism/dlabs-toolkit/issues"},"dist":{"shasum":"71bd711cabf67740babed28a60f491ce8b972fd6","tarball":"https://registry.npmjs.org/@diabolicallabs/llm-client/-/llm-client-4.1.0.tgz","fileCount":9,"integrity":"sha512-Jb0goRP1NZuknzaqCX3IHDS05Pi+pSrtKDVgPw6ucDOOJ2UUdHhTjVSDRdI+BjiE7q6Rmcvmj5xMsxkY2RxXwA==","signatures":[{"sig":"MEUCIQCg1HlohncUcYJLUqbFtHmmnmC7v1cyu+tpH+r/2CddKgIgKK/iolQqYVGDDC8YvFhvP8OHvqVI7CPxAPiKVnNUOQM=","keyid":"SHA256:DhQ8wR5APBvFHLF/+Tc+AYvPOdTpcIDqOhxsBHRwC7U"}],"unpackedSize":599905},"main":"./dist/index.js","type":"module","_from":"file:diabolicallabs-llm-client-4.1.0.tgz","types":"./dist/index.d.ts","engines":{"node":">=20"},"exports":{".":{"types":"./dist/index.d.ts","import":"./dist/index.js"},"./pool":{"types":"./dist/pool/index.d.ts","import":"./dist/pool/index.js"}},"scripts":{"lint":"biome check ./src && eslint ./src","test":"vitest run","build":"tsup","typecheck":"tsc --noEmit","test:watch":"vitest"},"_npmUser":{"name":"shackled78","email":"shackled78@gmail.com"},"_resolved":"/tmp/9e26538dc80740a33c9cc6079048ba1c/diabolicallabs-llm-client-4.1.0.tgz","publisher":"Diabolical Labs","_integrity":"sha512-Jb0goRP1NZuknzaqCX3IHDS05Pi+pSrtKDVgPw6ucDOOJ2UUdHhTjVSDRdI+BjiE7q6Rmcvmj5xMsxkY2RxXwA==","repository":{"url":"git+https://github.com/mannism/dlabs-toolkit.git","type":"git","directory":"packages/llm-client"},"_npmVersion":"10.8.2","description":"Unified LLM API for Anthropic, OpenAI, Google, and DeepSeek. Streaming, retry/backoff, structured output, token normalization. © Diabolical Labs","directories":{},"_nodeVersion":"20.20.2","dependencies":{"zod":"^4.4.3","openai":"^6.37.0","@google/genai":"^2.2.0","@anthropic-ai/sdk":"^0.95.2"},"_hasShrinkwrap":false,"devDependencies":{"tsup":"^8.3.5","vitest":"^4.1.5","@types/node":"^25.6.2","@vitest/coverage-v8":"^4.1.5","@diabolicallabs/llm-pricing":"1.1.0"},"peerDependencies":{"@diabolicallabs/llm-pricing":"^1.1.0"},"peerDependenciesMeta":{"@diabolicallabs/llm-pricing":{"optional":true}},"_npmOperationalInternal":{"tmp":"tmp/llm-client_4.1.0_1779193863732_0.6116404269644318","host":"s3://npm-registry-packages-npm-production"}},"4.2.0":{"name":"@diabolicallabs/llm-client","version":"4.2.0","author":{"url":"https://deeismail.com","name":"Diana Ismail","email":"diana@deeismail.com"},"license":"MIT","_id":"@diabolicallabs/llm-client@4.2.0","maintainers":[{"name":"shackled78","email":"shackled78@gmail.com"}],"homepage":"https://github.com/mannism/dlabs-toolkit#readme","bugs":{"url":"https://github.com/mannism/dlabs-toolkit/issues"},"dist":{"shasum":"31784ec7280927955fdf2da8933d81dd035465b0","tarball":"https://registry.npmjs.org/@diabolicallabs/llm-client/-/llm-client-4.2.0.tgz","fileCount":9,"integrity":"sha512-CsBEdCgmVnTy3ZQ4VH7BeC34x7nNugcphfs0eEQ0Y9Ki+q7T07tbfvTU6vR6MP4ZDBXXoNPJVhdHmJ/aMLXt3w==","signatures":[{"sig":"MEQCIDZ5u7OpM1OFbpLaI1OQXJcB8Pni+J/jzRT+DoZuDhhQAiAB5TJ/KRd2HbXF7pA5zgnHl22IhapTwz4XVPd3O8qrZA==","keyid":"SHA256:DhQ8wR5APBvFHLF/+Tc+AYvPOdTpcIDqOhxsBHRwC7U"}],"unpackedSize":646977},"main":"./dist/index.js","type":"module","_from":"file:diabolicallabs-llm-client-4.2.0.tgz","types":"./dist/index.d.ts","engines":{"node":">=20"},"exports":{".":{"types":"./dist/index.d.ts","import":"./dist/index.js"},"./pool":{"types":"./dist/pool/index.d.ts","import":"./dist/pool/index.js"}},"scripts":{"lint":"biome check ./src && eslint ./src","test":"vitest run","build":"tsup","typecheck":"tsc --noEmit","test:watch":"vitest"},"_npmUser":{"name":"shackled78","email":"shackled78@gmail.com"},"_resolved":"/tmp/3a3cce73f24f7f025c90a41f08da5e4d/diabolicallabs-llm-client-4.2.0.tgz","publisher":"Diabolical Labs","_integrity":"sha512-CsBEdCgmVnTy3ZQ4VH7BeC34x7nNugcphfs0eEQ0Y9Ki+q7T07tbfvTU6vR6MP4ZDBXXoNPJVhdHmJ/aMLXt3w==","repository":{"url":"git+https://github.com/mannism/dlabs-toolkit.git","type":"git","directory":"packages/llm-client"},"_npmVersion":"10.8.2","description":"Unified LLM API for Anthropic, OpenAI, Google, and DeepSeek. Streaming, retry/backoff, structured output, token normalization. © Diabolical Labs","directories":{},"_nodeVersion":"20.20.2","dependencies":{"zod":"^4.4.3","openai":"^6.39.1","@google/genai":"^2.7.0","@anthropic-ai/sdk":"^0.100.1"},"_hasShrinkwrap":false,"devDependencies":{"tsup":"^8.3.5","vitest":"^4.1.8","@types/node":"^25.9.1","@vitest/coverage-v8":"^4.1.8","@diabolicallabs/llm-pricing":"1.1.0"},"peerDependencies":{"@diabolicallabs/llm-pricing":"^1.1.0"},"peerDependenciesMeta":{"@diabolicallabs/llm-pricing":{"optional":true}},"_npmOperationalInternal":{"tmp":"tmp/llm-client_4.2.0_1780734306720_0.1165396682534443","host":"s3://npm-registry-packages-npm-production"}},"5.0.0":{"name":"@diabolicallabs/llm-client","version":"5.0.0","author":{"url":"https://deeismail.com","name":"Diana Ismail","email":"diana@deeismail.com"},"license":"MIT","_id":"@diabolicallabs/llm-client@5.0.0","maintainers":[{"name":"shackled78","email":"shackled78@gmail.com"}],"homepage":"https://github.com/mannism/dlabs-toolkit#readme","bugs":{"url":"https://github.com/mannism/dlabs-toolkit/issues"},"dist":{"shasum":"0d9cd5d3b81279809073f805a3b5b7c39f0970d2","tarball":"https://registry.npmjs.org/@diabolicallabs/llm-client/-/llm-client-5.0.0.tgz","fileCount":9,"integrity":"sha512-pTVT8YRKNwerMowDIbJxGuiUfbZ8FU1tE61sAuYh6mOOuTHs0ZfmlzLXxAyTafCdJHPx7YHw7UJxvq9umJIp6A==","signatures":[{"sig":"MEYCIQDwIk1FRrZvqARMx7fcbCPozXAnG8r/gU9aLNt1O28DIQIhAOYJyxSEDNmckxHVx40r0CJf0Hj5fMt07UiJzq2RYOtY","keyid":"SHA256:DhQ8wR5APBvFHLF/+Tc+AYvPOdTpcIDqOhxsBHRwC7U"}],"unpackedSize":658615},"main":"./dist/index.js","type":"module","_from":"file:diabolicallabs-llm-client-5.0.0.tgz","types":"./dist/index.d.ts","engines":{"node":">=20"},"exports":{".":{"types":"./dist/index.d.ts","import":"./dist/index.js"},"./pool":{"types":"./dist/pool/index.d.ts","import":"./dist/pool/index.js"}},"scripts":{"lint":"biome check ./src && eslint ./src","test":"vitest run","build":"tsup","typecheck":"tsc --noEmit","test:watch":"vitest"},"_npmUser":{"name":"shackled78","email":"shackled78@gmail.com"},"_resolved":"/tmp/f7fb55b10312dfe31a37f687c25a74f5/diabolicallabs-llm-client-5.0.0.tgz","publisher":"Diabolical Labs","_integrity":"sha512-pTVT8YRKNwerMowDIbJxGuiUfbZ8FU1tE61sAuYh6mOOuTHs0ZfmlzLXxAyTafCdJHPx7YHw7UJxvq9umJIp6A==","repository":{"url":"git+https://github.com/mannism/dlabs-toolkit.git","type":"git","directory":"packages/llm-client"},"_npmVersion":"10.8.2","description":"Unified LLM API for Anthropic, OpenAI, Google, and DeepSeek. Streaming, retry/backoff, structured output, token normalization. © Diabolical Labs","directories":{},"_nodeVersion":"20.20.2","dependencies":{"zod":"^4.4.3","openai":"^6.39.1","@google/genai":"^2.7.0","@anthropic-ai/sdk":"^0.100.1"},"_hasShrinkwrap":false,"devDependencies":{"tsup":"^8.3.5","vitest":"^4.1.8","@types/node":"^25.9.1","@vitest/coverage-v8":"^4.1.8","@diabolicallabs/llm-pricing":"1.1.0"},"peerDependencies":{"@diabolicallabs/llm-pricing":"^1.1.0"},"peerDependenciesMeta":{"@diabolicallabs/llm-pricing":{"optional":true}},"_npmOperationalInternal":{"tmp":"tmp/llm-client_5.0.0_1780845683741_0.22553989941425723","host":"s3://npm-registry-packages-npm-production"}},"5.1.0":{"name":"@diabolicallabs/llm-client","version":"5.1.0","author":{"url":"https://deeismail.com","name":"Diana Ismail","email":"diana@deeismail.com"},"license":"MIT","_id":"@diabolicallabs/llm-client@5.1.0","maintainers":[{"name":"shackled78","email":"shackled78@gmail.com"}],"homepage":"https://github.com/mannism/dlabs-toolkit#readme","bugs":{"url":"https://github.com/mannism/dlabs-toolkit/issues"},"dist":{"shasum":"9c6cc3829ab6f6af74641f9125cfda2d59e94c14","tarball":"https://registry.npmjs.org/@diabolicallabs/llm-client/-/llm-client-5.1.0.tgz","fileCount":9,"integrity":"sha512-SVwxdI2qgTDoyV2YD6tKUe9SBg0d2PoSJmVrtRJjayPe+PlHMB5CdflTa0hrjAyxTHcz8YvNQx+DJqiymJwfqw==","signatures":[{"sig":"MEQCIEmiAVdpFEj3pUROTBrBRj4SjToDW9IdhANhJZNCNZ3RAiAeB8pEp1biro8BC8RkWzNTyHkWu6mpAH+jGw414zjOPQ==","keyid":"SHA256:DhQ8wR5APBvFHLF/+Tc+AYvPOdTpcIDqOhxsBHRwC7U"}],"unpackedSize":747119},"main":"./dist/index.js","type":"module","_from":"file:diabolicallabs-llm-client-5.1.0.tgz","types":"./dist/index.d.ts","engines":{"node":">=20"},"exports":{".":{"types":"./dist/index.d.ts","import":"./dist/index.js"},"./pool":{"types":"./dist/pool/index.d.ts","import":"./dist/pool/index.js"}},"scripts":{"lint":"biome check ./src && eslint ./src","test":"vitest run","build":"tsup","typecheck":"tsc --noEmit","test:watch":"vitest"},"_npmUser":{"name":"shackled78","email":"shackled78@gmail.com"},"_resolved":"/tmp/62d69dd6e4d787ac7cc35d12f12f80b5/diabolicallabs-llm-client-5.1.0.tgz","publisher":"Diabolical Labs","_integrity":"sha512-SVwxdI2qgTDoyV2YD6tKUe9SBg0d2PoSJmVrtRJjayPe+PlHMB5CdflTa0hrjAyxTHcz8YvNQx+DJqiymJwfqw==","repository":{"url":"git+https://github.com/mannism/dlabs-toolkit.git","type":"git","directory":"packages/llm-client"},"_npmVersion":"10.8.2","description":"Unified LLM API for Anthropic, OpenAI, Google, and DeepSeek. Streaming, retry/backoff, structured output, token normalization. © Diabolical Labs","directories":{},"_nodeVersion":"20.20.2","dependencies":{"zod":"^4.4.3","openai":"^6.39.1","@google/genai":"^2.7.0","@anthropic-ai/sdk":"^0.100.1"},"_hasShrinkwrap":false,"devDependencies":{"tsup":"^8.3.5","vitest":"^4.1.8","@types/node":"^25.9.1","@vitest/coverage-v8":"^4.1.8","@diabolicallabs/llm-pricing":"1.1.0"},"peerDependencies":{"@diabolicallabs/llm-pricing":"^1.1.0"},"peerDependenciesMeta":{"@diabolicallabs/llm-pricing":{"optional":true}},"_npmOperationalInternal":{"tmp":"tmp/llm-client_5.1.0_1781600115328_0.8003824269857642","host":"s3://npm-registry-packages-npm-production"}},"5.2.0":{"name":"@diabolicallabs/llm-client","version":"5.2.0","author":{"url":"https://deeismail.com","name":"Diana Ismail","email":"diana@deeismail.com"},"license":"MIT","_id":"@diabolicallabs/llm-client@5.2.0","maintainers":[{"name":"shackled78","email":"shackled78@gmail.com"}],"homepage":"https://github.com/mannism/dlabs-toolkit#readme","bugs":{"url":"https://github.com/mannism/dlabs-toolkit/issues"},"dist":{"shasum":"12675d1946734011957b83fc97dcdd7a8085eff6","tarball":"https://registry.npmjs.org/@diabolicallabs/llm-client/-/llm-client-5.2.0.tgz","fileCount":9,"integrity":"sha512-Qq4Zh4TSHU39NeE3lrkcOXPNoRNwFtKdEHS3RoNFYCWoJLX38zQpQoDJBfZbT8ndOwr9wpV/TgvxWwffOKp0EA==","signatures":[{"sig":"MEYCIQCsU1GZ2z/3Zgi6sme2NNbGXWTjeH+ggxViex9+qzDcvAIhAJgWAVkgjGMvh4O+U1Na/8YMglByT+kt7S7aojhOORiY","keyid":"SHA256:DhQ8wR5APBvFHLF/+Tc+AYvPOdTpcIDqOhxsBHRwC7U"}],"unpackedSize":749685},"main":"./dist/index.js","type":"module","_from":"file:diabolicallabs-llm-client-5.2.0.tgz","types":"./dist/index.d.ts","engines":{"node":">=20"},"exports":{".":{"types":"./dist/index.d.ts","import":"./dist/index.js"},"./pool":{"types":"./dist/pool/index.d.ts","import":"./dist/pool/index.js"}},"scripts":{"lint":"biome check ./src && eslint ./src","test":"vitest run","build":"tsup","typecheck":"tsc --noEmit","test:watch":"vitest"},"_npmUser":{"name":"shackled78","email":"shackled78@gmail.com"},"_resolved":"/tmp/34ab527ce804ddac523871d5d5114e83/diabolicallabs-llm-client-5.2.0.tgz","publisher":"Diabolical Labs","_integrity":"sha512-Qq4Zh4TSHU39NeE3lrkcOXPNoRNwFtKdEHS3RoNFYCWoJLX38zQpQoDJBfZbT8ndOwr9wpV/TgvxWwffOKp0EA==","repository":{"url":"git+https://github.com/mannism/dlabs-toolkit.git","type":"git","directory":"packages/llm-client"},"_npmVersion":"10.8.2","description":"Unified LLM API for Anthropic, OpenAI, Google, and DeepSeek. Streaming, retry/backoff, structured output, token normalization. © Diabolical Labs","directories":{},"_nodeVersion":"20.20.2","dependencies":{"zod":"^4.4.3","openai":"^6.39.1","@google/genai":"^2.7.0","@anthropic-ai/sdk":"^0.100.1"},"_hasShrinkwrap":false,"devDependencies":{"tsup":"^8.3.5","vitest":"^4.1.8","@types/node":"^25.9.1","@vitest/coverage-v8":"^4.1.8","@diabolicallabs/llm-pricing":"1.1.0"},"peerDependencies":{"@diabolicallabs/llm-pricing":"^1.1.0"},"peerDependenciesMeta":{"@diabolicallabs/llm-pricing":{"optional":true}},"_npmOperationalInternal":{"tmp":"tmp/llm-client_5.2.0_1781629838671_0.684643159659396","host":"s3://npm-registry-packages-npm-production"}},"6.0.0":{"name":"@diabolicallabs/llm-client","version":"6.0.0","author":{"url":"https://deeismail.com","name":"Diana Ismail","email":"diana@deeismail.com"},"license":"MIT","_id":"@diabolicallabs/llm-client@6.0.0","maintainers":[{"name":"shackled78","email":"shackled78@gmail.com"}],"homepage":"https://github.com/mannism/dlabs-toolkit#readme","bugs":{"url":"https://github.com/mannism/dlabs-toolkit/issues"},"dist":{"shasum":"16cd4b643c34d1f97e0e4de738412d238d469e38","tarball":"https://registry.npmjs.org/@diabolicallabs/llm-client/-/llm-client-6.0.0.tgz","fileCount":9,"integrity":"sha512-ye2znDMz/PYXwj6/DOVAZZiO1n2pGrCFBojV9rvkHbsRmIH314NU6kUOUiKOC343DacWFuFYREHacL/OvNqvEA==","signatures":[{"sig":"MEUCIBJ8J9jPlqc/q1m2khJubvEnll5ilZUHmgDRyYf30fqqAiEAp/XS9PMhIfBuJiyH/DQb4cX6PWDnzbDBwyKzi/bITlA=","keyid":"SHA256:DhQ8wR5APBvFHLF/+Tc+AYvPOdTpcIDqOhxsBHRwC7U"}],"unpackedSize":749685},"main":"./dist/index.js","type":"module","_from":"file:diabolicallabs-llm-client-6.0.0.tgz","types":"./dist/index.d.ts","engines":{"node":">=20"},"exports":{".":{"types":"./dist/index.d.ts","import":"./dist/index.js"},"./pool":{"types":"./dist/pool/index.d.ts","import":"./dist/pool/index.js"}},"scripts":{"lint":"biome check ./src && eslint ./src","test":"vitest run","build":"tsup","typecheck":"tsc --noEmit","test:watch":"vitest"},"_npmUser":{"name":"shackled78","email":"shackled78@gmail.com"},"_resolved":"/tmp/21ec93f3603436d37309fd5a291ea482/diabolicallabs-llm-client-6.0.0.tgz","publisher":"Diabolical Labs","_integrity":"sha512-ye2znDMz/PYXwj6/DOVAZZiO1n2pGrCFBojV9rvkHbsRmIH314NU6kUOUiKOC343DacWFuFYREHacL/OvNqvEA==","repository":{"url":"git+https://github.com/mannism/dlabs-toolkit.git","type":"git","directory":"packages/llm-client"},"_npmVersion":"10.8.2","description":"Unified LLM API for Anthropic, OpenAI, Google, and DeepSeek. Streaming, retry/backoff, structured output, token normalization. © Diabolical Labs","directories":{},"_nodeVersion":"20.20.2","dependencies":{"zod":"^4.4.3","openai":"^6.42.0","@google/genai":"^2.8.0","@anthropic-ai/sdk":"^0.104.2"},"_hasShrinkwrap":false,"devDependencies":{"tsup":"^8.3.5","vitest":"^4.1.9","@types/node":"^25.9.3","@vitest/coverage-v8":"^4.1.9","@diabolicallabs/llm-pricing":"1.2.0"},"peerDependencies":{"@diabolicallabs/llm-pricing":"^1.2.0"},"peerDependenciesMeta":{"@diabolicallabs/llm-pricing":{"optional":true}},"_npmOperationalInternal":{"tmp":"tmp/llm-client_6.0.0_1781634084528_0.33549135049487133","host":"s3://npm-registry-packages-npm-production"}},"6.1.0":{"name":"@diabolicallabs/llm-client","version":"6.1.0","author":{"url":"https://deeismail.com","name":"Diana Ismail","email":"diana@deeismail.com"},"license":"MIT","_id":"@diabolicallabs/llm-client@6.1.0","maintainers":[{"name":"shackled78","email":"shackled78@gmail.com"}],"homepage":"https://github.com/mannism/dlabs-toolkit#readme","bugs":{"url":"https://github.com/mannism/dlabs-toolkit/issues"},"dist":{"shasum":"6a26c9cc6dfa9bcd3044c22ea55590a45bffcb18","tarball":"https://registry.npmjs.org/@diabolicallabs/llm-client/-/llm-client-6.1.0.tgz","fileCount":9,"integrity":"sha512-LsDHvvGNE/81a3+AWddrRJl45RC++vH6mUKOrlSMbkYpEmodD4f4avvlQPImJixJurEg9dHrh4kWUHTNg3s0RA==","signatures":[{"sig":"MEQCIDZUgFX6bveXqhlolnNEgNIsuVcohy8ha/oU4L8c1xm7AiA0VbiCZrwvYiphu3+ZSqBW8t5sNJdsbmDLV3bVIpVsUg==","keyid":"SHA256:DhQ8wR5APBvFHLF/+Tc+AYvPOdTpcIDqOhxsBHRwC7U"}],"unpackedSize":749767},"main":"./dist/index.js","type":"module","_from":"file:diabolicallabs-llm-client-6.1.0.tgz","types":"./dist/index.d.ts","engines":{"node":">=22.12.0"},"exports":{".":{"types":"./dist/index.d.ts","import":"./dist/index.js","require":"./dist/index.js"},"./pool":{"types":"./dist/pool/index.d.ts","import":"./dist/pool/index.js","require":"./dist/pool/index.js"}},"scripts":{"lint":"biome check ./src && eslint ./src","test":"vitest run","build":"tsup","typecheck":"tsc --noEmit","test:watch":"vitest"},"_npmUser":{"name":"shackled78","email":"shackled78@gmail.com"},"_resolved":"/tmp/8d1bd42ba156f5b59d455ea870370896/diabolicallabs-llm-client-6.1.0.tgz","publisher":"Diabolical Labs","_integrity":"sha512-LsDHvvGNE/81a3+AWddrRJl45RC++vH6mUKOrlSMbkYpEmodD4f4avvlQPImJixJurEg9dHrh4kWUHTNg3s0RA==","repository":{"url":"git+https://github.com/mannism/dlabs-toolkit.git","type":"git","directory":"packages/llm-client"},"_npmVersion":"10.8.2","description":"Unified LLM API for Anthropic, OpenAI, Google, and DeepSeek. Streaming, retry/backoff, structured output, token normalization. © Diabolical Labs","directories":{},"_nodeVersion":"20.20.2","dependencies":{"zod":"^4.4.3","openai":"^6.42.0","@google/genai":"^2.8.0","@anthropic-ai/sdk":"^0.104.2"},"_hasShrinkwrap":false,"devDependencies":{"tsup":"^8.3.5","vitest":"^4.1.9","@types/node":"^25.9.3","@vitest/coverage-v8":"^4.1.9","@diabolicallabs/llm-pricing":"1.2.0"},"peerDependencies":{"@diabolicallabs/llm-pricing":"^1.0.0"},"peerDependenciesMeta":{"@diabolicallabs/llm-pricing":{"optional":true}},"_npmOperationalInternal":{"tmp":"tmp/llm-client_6.1.0_1781705085949_0.7203675164781589","host":"s3://npm-registry-packages-npm-production"}},"6.2.0":{"name":"@diabolicallabs/llm-client","version":"6.2.0","author":{"url":"https://deeismail.com","name":"Diana Ismail","email":"diana@deeismail.com"},"license":"MIT","_id":"@diabolicallabs/llm-client@6.2.0","maintainers":[{"name":"shackled78","email":"shackled78@gmail.com"}],"homepage":"https://github.com/mannism/dlabs-toolkit#readme","bugs":{"url":"https://github.com/mannism/dlabs-toolkit/issues"},"dist":{"shasum":"7b44bf07f79ed835bb7d4a1e2ff73e5d6b6a0a36","tarball":"https://registry.npmjs.org/@diabolicallabs/llm-client/-/llm-client-6.2.0.tgz","fileCount":9,"integrity":"sha512-aUgzkhE55/ObOS8coOzuqR63QdSRHk+kJj9Ar7k8iHsY3jmmumUEKQAkhTi6KbsBBZ+wTh8tJF1EBfJm3d+4Iw==","signatures":[{"sig":"MEYCIQC6YlmDl/u3fCiRiFzWCN7ezTYzAdzgnqEnPDNAFjelagIhANTARyCuJXGr/cvyuy2IAk6sLpVaR0yISEHraEI1wJJ4","keyid":"SHA256:DhQ8wR5APBvFHLF/+Tc+AYvPOdTpcIDqOhxsBHRwC7U"}],"unpackedSize":749969},"main":"./dist/index.js","type":"module","_from":"file:diabolicallabs-llm-client-6.2.0.tgz","types":"./dist/index.d.ts","engines":{"node":">=22.12.0"},"exports":{".":{"types":"./dist/index.d.ts","import":"./dist/index.js","require":"./dist/index.js"},"./pool":{"types":"./dist/pool/index.d.ts","import":"./dist/pool/index.js","require":"./dist/pool/index.js"}},"scripts":{"lint":"biome check ./src && eslint ./src","test":"vitest run","build":"tsup","typecheck":"tsc --noEmit","test:watch":"vitest"},"_npmUser":{"name":"shackled78","email":"shackled78@gmail.com"},"_resolved":"/tmp/decc7d1821be805102241f1122e1dbb1/diabolicallabs-llm-client-6.2.0.tgz","publisher":"Diabolical Labs","_integrity":"sha512-aUgzkhE55/ObOS8coOzuqR63QdSRHk+kJj9Ar7k8iHsY3jmmumUEKQAkhTi6KbsBBZ+wTh8tJF1EBfJm3d+4Iw==","repository":{"url":"git+https://github.com/mannism/dlabs-toolkit.git","type":"git","directory":"packages/llm-client"},"_npmVersion":"10.8.2","description":"Unified LLM API for Anthropic, OpenAI, Google, and DeepSeek. Streaming, retry/backoff, structured output, token normalization. © Diabolical Labs","directories":{},"_nodeVersion":"20.20.2","dependencies":{"zod":"^4.4.3","openai":"^6.42.0","@google/genai":"^2.8.0","@anthropic-ai/sdk":"^0.104.2"},"_hasShrinkwrap":false,"devDependencies":{"tsup":"^8.3.5","vitest":"^4.1.9","@types/node":"^25.9.3","@vitest/coverage-v8":"^4.1.9","@diabolicallabs/llm-pricing":"1.2.0"},"peerDependencies":{"@diabolicallabs/llm-pricing":"^1.0.0"},"peerDependenciesMeta":{"@diabolicallabs/llm-pricing":{"optional":true}},"_npmOperationalInternal":{"tmp":"tmp/llm-client_6.2.0_1781835454501_0.15720342467863535","host":"s3://npm-registry-packages-npm-production"}},"6.3.0":{"name":"@diabolicallabs/llm-client","version":"6.3.0","author":{"url":"https://deeismail.com","name":"Diana Ismail","email":"diana@deeismail.com"},"license":"MIT","_id":"@diabolicallabs/llm-client@6.3.0","maintainers":[{"name":"shackled78","email":"shackled78@gmail.com"}],"homepage":"https://github.com/mannism/dlabs-toolkit#readme","bugs":{"url":"https://github.com/mannism/dlabs-toolkit/issues"},"dist":{"shasum":"42e3fc5e2e13f762653ea8e0d68df747a186d6c7","tarball":"https://registry.npmjs.org/@diabolicallabs/llm-client/-/llm-client-6.3.0.tgz","fileCount":9,"integrity":"sha512-hvBPElFtQdMOM+qTQR4SJqPi4xcyWF9GStPe//uJgLtI8cLs10KNt9scOS0CfI4P9dDtijwyCLKoyRVZ2PO3BQ==","signatures":[{"sig":"MEUCIQCzNa0RxHm70K1umVpsZRM7zPL2O7BL4ENmwK8ZdVcb/QIgBIRqtFb/9MGLXC3AaMOb93bsNmRZjfUN7rLHRmmhv9c=","keyid":"SHA256:DhQ8wR5APBvFHLF/+Tc+AYvPOdTpcIDqOhxsBHRwC7U"}],"unpackedSize":795438},"main":"./dist/index.js","type":"module","_from":"file:diabolicallabs-llm-client-6.3.0.tgz","types":"./dist/index.d.ts","engines":{"node":">=22.12.0"},"exports":{".":{"types":"./dist/index.d.ts","import":"./dist/index.js","require":"./dist/index.js"},"./pool":{"types":"./dist/pool/index.d.ts","import":"./dist/pool/index.js","require":"./dist/pool/index.js"}},"scripts":{"lint":"biome check ./src && eslint ./src","test":"vitest run","build":"tsup","typecheck":"tsc --noEmit","test:watch":"vitest"},"_npmUser":{"name":"shackled78","email":"shackled78@gmail.com"},"_resolved":"/tmp/414abd5aa6b5649be3413abaebaaa16a/diabolicallabs-llm-client-6.3.0.tgz","publisher":"Diabolical Labs","_integrity":"sha512-hvBPElFtQdMOM+qTQR4SJqPi4xcyWF9GStPe//uJgLtI8cLs10KNt9scOS0CfI4P9dDtijwyCLKoyRVZ2PO3BQ==","repository":{"url":"git+https://github.com/mannism/dlabs-toolkit.git","type":"git","directory":"packages/llm-client"},"_npmVersion":"10.8.2","description":"Unified LLM API for Anthropic, OpenAI, Google, and DeepSeek. Streaming, retry/backoff, structured output, token normalization. © Diabolical Labs","directories":{},"_nodeVersion":"20.20.2","dependencies":{"zod":"^4.4.3","openai":"^6.49.0","@google/genai":"^2.13.0","@anthropic-ai/sdk":"^0.115.0"},"_hasShrinkwrap":false,"devDependencies":{"tsup":"^8.3.5","vitest":"^4.1.10","@types/node":"^26.1.1","@vitest/coverage-v8":"^4.1.10","@diabolicallabs/llm-pricing":"1.3.0"},"peerDependencies":{"@diabolicallabs/llm-pricing":"^1.0.0"},"peerDependenciesMeta":{"@diabolicallabs/llm-pricing":{"optional":true}},"_npmOperationalInternal":{"tmp":"tmp/llm-client_6.3.0_1785278788454_0.2348677984884988","host":"s3://npm-registry-packages-npm-production"}},"6.4.0":{"name":"@diabolicallabs/llm-client","version":"6.4.0","author":{"url":"https://deeismail.com","name":"Diana Ismail","email":"diana@deeismail.com"},"license":"MIT","_id":"@diabolicallabs/llm-client@6.4.0","maintainers":[{"name":"shackled78","email":"shackled78@gmail.com"}],"homepage":"https://github.com/mannism/dlabs-toolkit#readme","bugs":{"url":"https://github.com/mannism/dlabs-toolkit/issues"},"dist":{"shasum":"f3429e9e7574537d83c847ca35ad1c1ef47a8d5e","tarball":"https://registry.npmjs.org/@diabolicallabs/llm-client/-/llm-client-6.4.0.tgz","fileCount":9,"integrity":"sha512-SpaSgPyXIBU5v5UviB0J2geOxD3Y44yogRNwVE0TpS2yjpntMXN/q0ZOux6tURmGCchvVnKOnGxARBfBNIVIGQ==","signatures":[{"sig":"MEQCIFJ2mMsU53jpWAAUCxu3Tf2wnmRfNoWkqmo/fy+noB0+AiATDeADyhh60tMaGC2reU729OgaEKw2OB1bbLWh/FSLeg==","keyid":"SHA256:DhQ8wR5APBvFHLF/+Tc+AYvPOdTpcIDqOhxsBHRwC7U"}],"unpackedSize":803769},"main":"./dist/index.js","type":"module","_from":"file:diabolicallabs-llm-client-6.4.0.tgz","types":"./dist/index.d.ts","engines":{"node":">=22.12.0"},"exports":{".":{"types":"./dist/index.d.ts","import":"./dist/index.js","require":"./dist/index.js"},"./pool":{"types":"./dist/pool/index.d.ts","import":"./dist/pool/index.js","require":"./dist/pool/index.js"}},"scripts":{"lint":"biome check ./src && eslint ./src","test":"vitest run","build":"tsup","typecheck":"tsc --noEmit","test:watch":"vitest"},"_npmUser":{"name":"shackled78","email":"shackled78@gmail.com"},"_resolved":"/tmp/3a813fdb43732c2fcc445d7efe843cd3/diabolicallabs-llm-client-6.4.0.tgz","publisher":"Diabolical Labs","_integrity":"sha512-SpaSgPyXIBU5v5UviB0J2geOxD3Y44yogRNwVE0TpS2yjpntMXN/q0ZOux6tURmGCchvVnKOnGxARBfBNIVIGQ==","repository":{"url":"git+https://github.com/mannism/dlabs-toolkit.git","type":"git","directory":"packages/llm-client"},"_npmVersion":"10.8.2","description":"Unified LLM API for Anthropic, OpenAI, Google, and DeepSeek. Streaming, retry/backoff, structured output, token normalization. © Diabolical Labs","directories":{},"_nodeVersion":"20.20.2","dependencies":{"zod":"^4.4.3","openai":"^7.4.0","@google/genai":"^2.15.0","@anthropic-ai/sdk":"^0.115.0"},"_hasShrinkwrap":false,"devDependencies":{"tsup":"^8.3.5","vitest":"^4.1.10","@types/node":"^26.1.2","@vitest/coverage-v8":"^4.1.10","@diabolicallabs/llm-pricing":"1.3.0"},"peerDependencies":{"@diabolicallabs/llm-pricing":"^1.0.0"},"peerDependenciesMeta":{"@diabolicallabs/llm-pricing":{"optional":true}},"_npmOperationalInternal":{"tmp":"tmp/llm-client_6.4.0_1786199665836_0.6167288202823249","host":"s3://npm-registry-packages-npm-production"}},"6.5.0":{"name":"@diabolicallabs/llm-client","version":"6.5.0","author":{"url":"https://deeismail.com","name":"Diana Ismail","email":"diana@deeismail.com"},"license":"MIT","_id":"@diabolicallabs/llm-client@6.5.0","maintainers":[{"name":"shackled78","email":"shackled78@gmail.com"}],"homepage":"https://github.com/mannism/dlabs-toolkit#readme","bugs":{"url":"https://github.com/mannism/dlabs-toolkit/issues"},"dist":{"shasum":"12988652917bb4a9d2b5b7060bf0871b37bbbf00","tarball":"https://registry.npmjs.org/@diabolicallabs/llm-client/-/llm-client-6.5.0.tgz","fileCount":9,"integrity":"sha512-IhfCOANr0CWSoGaypBWrvDDTwFwRl+mngQ0rfo5N7u5bE1o+Lx1gfBjV22aP2zDpsjZW2OxObxKkDT+TwOGQIQ==","signatures":[{"sig":"MEYCIQDJQ1K763xuDp1uVSu8lLLozyTWul2tAVqubEXrFO9H9AIhAM9PFZHK7VK2H4B5x9J+VxxS6sdVtttKrSz3qhCXI4xS","keyid":"SHA256:DhQ8wR5APBvFHLF/+Tc+AYvPOdTpcIDqOhxsBHRwC7U"}],"unpackedSize":809496},"main":"./dist/index.js","type":"module","_from":"file:diabolicallabs-llm-client-6.5.0.tgz","types":"./dist/index.d.ts","engines":{"node":">=22.12.0"},"exports":{".":{"types":"./dist/index.d.ts","import":"./dist/index.js","require":"./dist/index.js"},"./pool":{"types":"./dist/pool/index.d.ts","import":"./dist/pool/index.js","require":"./dist/pool/index.js"}},"scripts":{"lint":"biome check ./src && eslint ./src","test":"vitest run","build":"tsup","typecheck":"tsc --noEmit","test:watch":"vitest"},"_npmUser":{"name":"shackled78","email":"shackled78@gmail.com"},"_resolved":"/tmp/73f71bb37f8bf33fda971c074423c26a/diabolicallabs-llm-client-6.5.0.tgz","publisher":"Diabolical Labs","_integrity":"sha512-IhfCOANr0CWSoGaypBWrvDDTwFwRl+mngQ0rfo5N7u5bE1o+Lx1gfBjV22aP2zDpsjZW2OxObxKkDT+TwOGQIQ==","repository":{"url":"git+https://github.com/mannism/dlabs-toolkit.git","type":"git","directory":"packages/llm-client"},"_npmVersion":"10.8.2","description":"Unified LLM API for Anthropic, OpenAI, Google, and DeepSeek. Streaming, retry/backoff, structured output, token normalization. © Diabolical Labs","directories":{},"_nodeVersion":"20.20.2","dependencies":{"zod":"^4.4.3","openai":"^7.4.0","@google/genai":"^2.15.0","@anthropic-ai/sdk":"^0.115.0"},"_hasShrinkwrap":false,"devDependencies":{"tsup":"^8.3.5","vitest":"^4.1.10","@types/node":"^26.1.2","@vitest/coverage-v8":"^4.1.10","@diabolicallabs/llm-pricing":"1.3.0"},"peerDependencies":{"@diabolicallabs/llm-pricing":"^1.0.0"},"peerDependenciesMeta":{"@diabolicallabs/llm-pricing":{"optional":true}},"_npmOperationalInternal":{"tmp":"tmp/llm-client_6.5.0_1786201290725_0.0004798719328773515","host":"s3://npm-registry-packages-npm-production"}},"6.5.1":{"name":"@diabolicallabs/llm-client","version":"6.5.1","author":{"url":"https://deeismail.com","name":"Diana Ismail","email":"diana@deeismail.com"},"license":"MIT","_id":"@diabolicallabs/llm-client@6.5.1","maintainers":[{"name":"shackled78","email":"shackled78@gmail.com"}],"homepage":"https://github.com/mannism/dlabs-toolkit#readme","bugs":{"url":"https://github.com/mannism/dlabs-toolkit/issues"},"dist":{"shasum":"40cff9ed7be6d3be9c1ccf514c0bb6c5b75bc968","tarball":"https://registry.npmjs.org/@diabolicallabs/llm-client/-/llm-client-6.5.1.tgz","fileCount":9,"integrity":"sha512-z8WrQkXNfFuXcrWQrCiW4dWVL+9V5nuUpEnr2SvthuLVtrRCETaGksf44WCQl2ljW+ZyQcfKOTGZIba6J/0lsQ==","signatures":[{"sig":"MEUCIEvstQ72N2xpZFBX3BjM19p8cLIDMECqNMPNyxRaAY4bAiEAsfyiD/9ANSuO4kFJrGz3jWOc79ovpSQWzIUSb8qrZEo=","keyid":"SHA256:DhQ8wR5APBvFHLF/+Tc+AYvPOdTpcIDqOhxsBHRwC7U"}],"unpackedSize":811613},"main":"./dist/index.js","type":"module","_from":"file:diabolicallabs-llm-client-6.5.1.tgz","types":"./dist/index.d.ts","engines":{"node":">=22.12.0"},"exports":{".":{"types":"./dist/index.d.ts","import":"./dist/index.js","require":"./dist/index.js"},"./pool":{"types":"./dist/pool/index.d.ts","import":"./dist/pool/index.js","require":"./dist/pool/index.js"}},"scripts":{"lint":"biome check ./src && eslint ./src","test":"vitest run","build":"tsup","typecheck":"tsc --noEmit","test:watch":"vitest"},"_npmUser":{"name":"shackled78","email":"shackled78@gmail.com"},"_resolved":"/tmp/5466c85ae7b55f7d174a7a0db2f509cc/diabolicallabs-llm-client-6.5.1.tgz","publisher":"Diabolical Labs","_integrity":"sha512-z8WrQkXNfFuXcrWQrCiW4dWVL+9V5nuUpEnr2SvthuLVtrRCETaGksf44WCQl2ljW+ZyQcfKOTGZIba6J/0lsQ==","repository":{"url":"git+https://github.com/mannism/dlabs-toolkit.git","type":"git","directory":"packages/llm-client"},"_npmVersion":"10.8.2","description":"Unified LLM API for Anthropic, OpenAI, Google, and DeepSeek. Streaming, retry/backoff, structured output, token normalization. © Diabolical Labs","directories":{},"_nodeVersion":"20.20.2","dependencies":{"zod":"^4.4.3","openai":"^7.4.0","@google/genai":"^2.17.0","@anthropic-ai/sdk":"^0.115.0"},"_hasShrinkwrap":false,"devDependencies":{"tsup":"^8.3.5","vitest":"^4.1.10","@types/node":"^26.2.0","@vitest/coverage-v8":"^4.1.10","@diabolicallabs/llm-pricing":"1.4.2"},"peerDependencies":{"@diabolicallabs/llm-pricing":"^1.0.0"},"peerDependenciesMeta":{"@diabolicallabs/llm-pricing":{"optional":true}},"_npmOperationalInternal":{"tmp":"tmp/llm-client_6.5.1_1787038887682_0.847744021834345","host":"s3://npm-registry-packages-npm-production"}},"6.6.0":{"name":"@diabolicallabs/llm-client","version":"6.6.0","author":{"url":"https://deeismail.com","name":"Diana Ismail","email":"diana@deeismail.com"},"license":"MIT","_id":"@diabolicallabs/llm-client@6.6.0","maintainers":[{"name":"shackled78","email":"shackled78@gmail.com"}],"homepage":"https://github.com/mannism/dlabs-toolkit#readme","bugs":{"url":"https://github.com/mannism/dlabs-toolkit/issues"},"dist":{"shasum":"bb93cecee87ab3b7c8a3cb747fd1254699ba8bd3","tarball":"https://registry.npmjs.org/@diabolicallabs/llm-client/-/llm-client-6.6.0.tgz","fileCount":9,"integrity":"sha512-lz+GvNEACTBOF4w4cOymr6MFYfIv/G/l6ILUoJCBqmDFBkcksYY00xVwJrXOGJyv3EsGpZyGSIbeZiecSnt0+Q==","signatures":[{"sig":"MEYCIQDaWJLY/rlo2CEER8sk2tT7mByZ6YCOEKvBqscMScjHxwIhANZC+zboPCPrPBIUZnNEmJaegoXeN8ZNgvmXHcGkziRt","keyid":"SHA256:DhQ8wR5APBvFHLF/+Tc+AYvPOdTpcIDqOhxsBHRwC7U"}],"unpackedSize":817875},"main":"./dist/index.js","type":"module","_from":"file:diabolicallabs-llm-client-6.6.0.tgz","types":"./dist/index.d.ts","engines":{"node":">=22.12.0"},"exports":{".":{"types":"./dist/index.d.ts","import":"./dist/index.js","require":"./dist/index.js"},"./pool":{"types":"./dist/pool/index.d.ts","import":"./dist/pool/index.js","require":"./dist/pool/index.js"}},"scripts":{"lint":"biome check ./src && eslint ./src","test":"vitest run","build":"tsup","typecheck":"tsc --noEmit","test:watch":"vitest"},"_npmUser":{"name":"shackled78","email":"shackled78@gmail.com"},"_resolved":"/tmp/1c0563b5e3900428fd9837731b8a72b3/diabolicallabs-llm-client-6.6.0.tgz","publisher":"Diabolical Labs","_integrity":"sha512-lz+GvNEACTBOF4w4cOymr6MFYfIv/G/l6ILUoJCBqmDFBkcksYY00xVwJrXOGJyv3EsGpZyGSIbeZiecSnt0+Q==","repository":{"url":"git+https://github.com/mannism/dlabs-toolkit.git","type":"git","directory":"packages/llm-client"},"_npmVersion":"10.8.2","description":"Unified LLM API for Anthropic, OpenAI, Google, and DeepSeek. Streaming, retry/backoff, structured output, token normalization. © Diabolical Labs","directories":{},"_nodeVersion":"20.20.2","dependencies":{"zod":"^4.4.3","openai":"^7.4.0","@google/genai":"^2.17.0","@anthropic-ai/sdk":"^0.115.0"},"_hasShrinkwrap":false,"devDependencies":{"tsup":"^8.3.5","vitest":"^4.1.10","@types/node":"^26.2.0","@vitest/coverage-v8":"^4.1.10","@diabolicallabs/llm-pricing":"1.4.3"},"peerDependencies":{"@diabolicallabs/llm-pricing":"^1.0.0"},"peerDependenciesMeta":{"@diabolicallabs/llm-pricing":{"optional":true}},"_npmOperationalInternal":{"tmp":"tmp/llm-client_6.6.0_1787121292684_0.7328236539209727","host":"s3://npm-registry-packages-npm-production"}},"6.7.0":{"name":"@diabolicallabs/llm-client","version":"6.7.0","author":{"url":"https://deeismail.com","name":"Diana Ismail","email":"diana@deeismail.com"},"license":"MIT","_id":"@diabolicallabs/llm-client@6.7.0","maintainers":[{"name":"shackled78","email":"shackled78@gmail.com"}],"homepage":"https://github.com/mannism/dlabs-toolkit#readme","bugs":{"url":"https://github.com/mannism/dlabs-toolkit/issues"},"dist":{"shasum":"6c170e728933ffd38f464b457a1fdb42fb4c8f9f","tarball":"https://registry.npmjs.org/@diabolicallabs/llm-client/-/llm-client-6.7.0.tgz","fileCount":9,"integrity":"sha512-cBeFuAhFalJVtcLUI1GxYcYLkWBgBVShdIuk44uEXlAPXa7EFCpBmnXbz4L8GALjqlp83RM3VvmsVrikgnvq5A==","signatures":[{"sig":"MEUCIQCGDHRHybgL22KrRRO8sjLbfmcXXn/7Vqfmf+bg8Bm7igIgTywWk6obmuQKvMF2j+Nlot4B88iMQHJryo2TQOehznY=","keyid":"SHA256:DhQ8wR5APBvFHLF/+Tc+AYvPOdTpcIDqOhxsBHRwC7U"}],"unpackedSize":851465},"main":"./dist/index.js","type":"module","_from":"file:diabolicallabs-llm-client-6.7.0.tgz","types":"./dist/index.d.ts","engines":{"node":">=22.12.0"},"exports":{".":{"types":"./dist/index.d.ts","import":"./dist/index.js","require":"./dist/index.js"},"./pool":{"types":"./dist/pool/index.d.ts","import":"./dist/pool/index.js","require":"./dist/pool/index.js"}},"scripts":{"lint":"biome check ./src && eslint ./src","test":"vitest run","build":"tsup","typecheck":"tsc --noEmit","test:watch":"vitest"},"_npmUser":{"name":"shackled78","email":"shackled78@gmail.com"},"_resolved":"/tmp/4132de83c657f326ce412e74959465a0/diabolicallabs-llm-client-6.7.0.tgz","publisher":"Diabolical Labs","_integrity":"sha512-cBeFuAhFalJVtcLUI1GxYcYLkWBgBVShdIuk44uEXlAPXa7EFCpBmnXbz4L8GALjqlp83RM3VvmsVrikgnvq5A==","repository":{"url":"git+https://github.com/mannism/dlabs-toolkit.git","type":"git","directory":"packages/llm-client"},"_npmVersion":"10.8.2","description":"Unified LLM API for Anthropic, OpenAI, Google, and DeepSeek. Streaming, retry/backoff, structured output, token normalization. © Diabolical Labs","directories":{},"_nodeVersion":"20.20.2","dependencies":{"zod":"^4.4.3","openai":"^7.4.0","@google/genai":"^2.17.0","@anthropic-ai/sdk":"^0.115.0"},"_hasShrinkwrap":false,"devDependencies":{"tsup":"^8.3.5","vitest":"^4.1.10","@types/node":"^26.2.0","@vitest/coverage-v8":"^4.1.10","@diabolicallabs/llm-pricing":"1.5.0"},"peerDependencies":{"@diabolicallabs/llm-pricing":"^1.0.0"},"peerDependenciesMeta":{"@diabolicallabs/llm-pricing":{"optional":true}},"_npmOperationalInternal":{"tmp":"tmp/llm-client_6.7.0_1788592393521_0.3304229562287959","host":"s3://npm-registry-packages-npm-production"}},"6.8.0":{"name":"@diabolicallabs/llm-client","version":"6.8.0","author":{"url":"https://deeismail.com","name":"Diana Ismail","email":"diana@deeismail.com"},"license":"MIT","_id":"@diabolicallabs/llm-client@6.8.0","maintainers":[{"name":"shackled78","email":"shackled78@gmail.com"}],"homepage":"https://github.com/mannism/dlabs-toolkit#readme","bugs":{"url":"https://github.com/mannism/dlabs-toolkit/issues"},"dist":{"shasum":"99b183da3cf7580db6730e744ded1d7161d09b0a","tarball":"https://registry.npmjs.org/@diabolicallabs/llm-client/-/llm-client-6.8.0.tgz","fileCount":9,"integrity":"sha512-cr/qSYNemTsQEtzw/7d3XjIVTKl2Aq+sKLIEQciwHglQ3FIaNPMepUQ6UEOKoW5ix9NEDRw01YuDIFeb7KXERg==","signatures":[{"sig":"MEYCIQDOZm8784lNGPt6zaJXfW9Oyc1YqCUKgerTvfaaiIAG+gIhAL3Amk9VwUH8UDt5EHJqPRthPwq9sqjLcDF3gmHBO8Bu","keyid":"SHA256:DhQ8wR5APBvFHLF/+Tc+AYvPOdTpcIDqOhxsBHRwC7U"}],"unpackedSize":855852},"main":"./dist/index.js","type":"module","_from":"file:diabolicallabs-llm-client-6.8.0.tgz","types":"./dist/index.d.ts","engines":{"node":">=22.12.0"},"exports":{".":{"types":"./dist/index.d.ts","import":"./dist/index.js","require":"./dist/index.js"},"./pool":{"types":"./dist/pool/index.d.ts","import":"./dist/pool/index.js","require":"./dist/pool/index.js"}},"scripts":{"lint":"biome check ./src && eslint ./src","test":"vitest run","build":"tsup","typecheck":"tsc --noEmit","test:watch":"vitest"},"_npmUser":{"name":"shackled78","email":"shackled78@gmail.com"},"_resolved":"/tmp/f64a1b4c21613ee6e30616dc1e7ab707/diabolicallabs-llm-client-6.8.0.tgz","publisher":"Diabolical Labs","_integrity":"sha512-cr/qSYNemTsQEtzw/7d3XjIVTKl2Aq+sKLIEQciwHglQ3FIaNPMepUQ6UEOKoW5ix9NEDRw01YuDIFeb7KXERg==","repository":{"url":"git+https://github.com/mannism/dlabs-toolkit.git","type":"git","directory":"packages/llm-client"},"_npmVersion":"10.8.2","description":"Unified LLM API for Anthropic, OpenAI, Google, and DeepSeek. Streaming, retry/backoff, structured output, token normalization. © Diabolical Labs","directories":{},"_nodeVersion":"20.20.2","dependencies":{"zod":"^4.4.3","openai":"^7.4.0","@google/genai":"^2.17.0","@anthropic-ai/sdk":"^0.115.0"},"_hasShrinkwrap":false,"devDependencies":{"tsup":"^8.3.5","vitest":"^4.1.10","@types/node":"^26.2.0","@vitest/coverage-v8":"^4.1.10","@diabolicallabs/llm-pricing":"1.6.0"},"peerDependencies":{"@diabolicallabs/llm-pricing":"^1.0.0"},"peerDependenciesMeta":{"@diabolicallabs/llm-pricing":{"optional":true}},"_npmOperationalInternal":{"tmp":"tmp/llm-client_6.8.0_1788595257100_0.3800318343933906","host":"s3://npm-registry-packages-npm-production"}},"6.9.0":{"_id":"@diabolicallabs/llm-client@6.9.0","bugs":{"url":"https://github.com/mannism/dlabs-toolkit/issues"},"dist":{"shasum":"2d914449529f7fc08d38e2ba6093c61f4acf157e","tarball":"https://registry.npmjs.org/@diabolicallabs/llm-client/-/llm-client-6.9.0.tgz","fileCount":9,"integrity":"sha512-eiecaKVcTeGqgh/H91I5EVDKAczhuSS/RtwQ/ZzVEJbqH5SWaAdoblO51Pm+TDQZTJBklyT5stzbsXV7er9fvQ==","signatures":[{"sig":"MEYCIQD7GKB0+bNDYO881bMB6d0GgzGrV77qSQZW9jZLmg8TsQIhAKulIqxLMLk4FksZeDcS9CsB5kXYTuF38/CYKNuEfqV4","keyid":"SHA256:DhQ8wR5APBvFHLF/+Tc+AYvPOdTpcIDqOhxsBHRwC7U"},{"keyid":"SHA256:DhQ8wR5APBvFHLF/+Tc+AYvPOdTpcIDqOhxsBHRwC7U","sig":"MEYCIQCmYC+Q09vC75sxkgQNa739w95gW4kc3SnqM5Y2uDYCzAIhAKbJh3fugSLG4OB7cM8ODk6JMzTLsgWiwHY8IB1PQcJE"}],"unpackedSize":876186},"main":"./dist/index.js","name":"@diabolicallabs/llm-client","type":"module","_from":"file:diabolicallabs-llm-client-6.9.0.tgz","types":"./dist/index.d.ts","author":{"url":"https://deeismail.com","name":"Diana Ismail","email":"diana@deeismail.com"},"engines":{"node":">=22.12.0"},"exports":{".":{"types":"./dist/index.d.ts","import":"./dist/index.js","require":"./dist/index.js"},"./pool":{"types":"./dist/pool/index.d.ts","import":"./dist/pool/index.js","require":"./dist/pool/index.js"}},"license":"MIT","scripts":{"lint":"biome check ./src && eslint ./src","test":"vitest run","build":"tsup","typecheck":"tsc --noEmit","test:watch":"vitest"},"version":"6.9.0","_npmUser":{"name":"shackled78","email":"shackled78@gmail.com"},"homepage":"https://github.com/mannism/dlabs-toolkit#readme","_resolved":"/tmp/4eae977998bf105e37401bb0a369b014/diabolicallabs-llm-client-6.9.0.tgz","publisher":"Diabolical Labs","_integrity":"sha512-eiecaKVcTeGqgh/H91I5EVDKAczhuSS/RtwQ/ZzVEJbqH5SWaAdoblO51Pm+TDQZTJBklyT5stzbsXV7er9fvQ==","repository":{"url":"git+https://github.com/mannism/dlabs-toolkit.git","type":"git","directory":"packages/llm-client"},"_npmVersion":"10.9.8","description":"Unified LLM API for Anthropic, OpenAI, Google, and DeepSeek. Streaming, retry/backoff, structured output, token normalization. © Diabolical Labs","directories":{},"maintainers":[{"name":"shackled78","email":"shackled78@gmail.com"}],"_nodeVersion":"22.23.2","dependencies":{"zod":"^4.6.2","openai":"^7.15.0","@google/genai":"^2.22.0","@anthropic-ai/sdk":"^0.125.0"},"_hasShrinkwrap":false,"devDependencies":{"tsup":"^8.3.5","vitest":"^5.0.0","@types/node":"^26.5.1","@vitest/coverage-v8":"^5.0.0","@diabolicallabs/llm-pricing":"1.6.0"},"peerDependencies":{"@diabolicallabs/llm-pricing":"^1.0.0"},"peerDependenciesMeta":{"@diabolicallabs/llm-pricing":{"optional":true}},"_npmOperationalInternal":{"host":"s3://npm-registry-packages-npm-production","tmp":"tmp/llm-client_6.9.0_1789397136644_0.9675203944006636"}}},"time":{"created":"2026-05-06T07:02:32.880Z","modified":"2026-09-14T14:45:36.985Z","0.1.0":"2026-05-06T07:02:33.165Z","0.1.1":"2026-05-06T09:32:12.189Z","0.2.0":"2026-05-08T12:54:30.443Z","0.3.0":"2026-05-10T01:22:38.755Z","0.4.0":"2026-05-10T02:35:20.305Z","0.4.1":"2026-05-10T16:31:31.364Z","0.4.2":"2026-05-10T18:04:56.630Z","0.4.3":"2026-05-11T01:48:30.783Z","0.4.4":"2026-05-11T04:57:56.595Z","1.0.0":"2026-05-13T11:53:08.253Z","1.1.0":"2026-05-13T12:39:22.979Z","1.2.0":"2026-05-13T13:30:18.259Z","1.3.0":"2026-05-13T14:25:21.925Z","1.4.0":"2026-05-13T15:21:13.600Z","1.5.0":"2026-05-13T17:14:39.366Z","1.6.0":"2026-05-14T00:22:21.205Z","1.7.0":"2026-05-14T09:11:18.166Z","2.0.0":"2026-05-17T17:04:04.114Z","3.0.0":"2026-05-18T13:42:18.450Z","3.0.1":"2026-05-18T14:20:20.257Z","4.0.0":"2026-05-19T03:19:54.327Z","4.1.0":"2026-05-19T12:31:03.899Z","4.2.0":"2026-06-06T08:25:06.960Z","5.0.0":"2026-06-07T15:21:23.934Z","5.1.0":"2026-06-16T08:55:15.510Z","5.2.0":"2026-06-16T17:10:38.860Z","6.0.0":"2026-06-16T18:21:24.772Z","6.1.0":"2026-06-17T14:04:46.119Z","6.2.0":"2026-06-19T02:17:34.706Z","6.3.0":"2026-07-28T22:46:28.685Z","6.4.0":"2026-08-08T14:34:25.991Z","6.5.0":"2026-08-08T15:01:30.896Z","6.5.1":"2026-08-18T07:41:27.823Z","6.6.0":"2026-08-19T06:34:52.853Z","6.7.0":"2026-09-05T07:13:13.662Z","6.8.0":"2026-09-05T08:00:57.257Z","6.9.0":"2026-09-14T14:45:36.752Z"},"bugs":{"url":"https://github.com/mannism/dlabs-toolkit/issues"},"author":{"url":"https://deeismail.com","name":"Diana Ismail","email":"diana@deeismail.com"},"license":"MIT","homepage":"https://github.com/mannism/dlabs-toolkit#readme","repository":{"url":"git+https://github.com/mannism/dlabs-toolkit.git","type":"git","directory":"packages/llm-client"},"description":"Unified LLM API for Anthropic, OpenAI, Google, and DeepSeek. Streaming, retry/backoff, structured output, token normalization. © Diabolical Labs","maintainers":[{"name":"shackled78","email":"shackled78@gmail.com"}],"readme":"# @diabolicallabs/llm-client\n\nUnified LLM API across Anthropic, OpenAI, Google Gemini, DeepSeek, and Perplexity. Single interface for completion, streaming, structured output, and native tool calling. All provider errors are normalized into a consistent `LlmError` shape. © Diabolical Labs\n\n## Status\n\n**v6.9.0.** All five providers fully implemented. See [MIGRATION.md](./MIGRATION.md) for breaking changes from v0.x.\n\nHighlights:\n- **v6.9.0** — Gemini `structured()` (and its prompt-mode fallback) now classifies empty/whitespace-only responses by `candidates[0].finishReason` / `promptFeedback.blockReason` before attempting `JSON.parse`, instead of always throwing a generic `structured_parse_failed`. New error kinds `max_tokens` (MAX_TOKENS finish reason) and `empty_response` (any other empty-text case, including an all-thought-parts response where the SDK's `.text` getter skips `thought: true` parts); `SAFETY`/`blockReason` map to the existing `content_filter` kind. `structured_parse_failed` is now reserved for genuinely non-empty, unparseable text. `LlmStructuredResponse.stopReason` (`'end_turn' | 'max_tokens' | 'content_filter'`, optional) is populated by Gemini on successful parses so callers can detect truncation even when JSON.parse still succeeded.\n- **v6.3.0** — Reasoning-effort passthrough: `reasoningEffort` on `LlmCallOptions` (Anthropic, OpenAI, Gemini — Perplexity/DeepSeek reject), `LlmUsage.reasoningTokens`, and a `reasoningEffort` dialect tag on `ModelCapabilities`. See [Reasoning-effort passthrough](#reasoning-effort-passthrough-v630).\n- **v5.1.0** — Files API: `LlmFilesApi` namespace on every `LlmClient` (`files.upload()`, `files.refresh()`, `files.waitForActive()`, `files.delete()`). New `{ type: 'file', ref: LlmFileRef }` content block for passing uploaded files in messages. Gemini supports video, large images, and PDFs via the Files API; OpenAI supports PDFs; Anthropic supports PDFs and images via the Files beta. Error kinds map to the existing taxonomy (`bad_request` for provider/state mismatches, `network`/`server_error` for SDK failures, `timeout` for waitForActive deadline exceeded). Cross-provider refs throw `bad_request` before any SDK call.\n- **v5.0.0** — **Breaking.** `LlmTool.inputSchema` now requires an `LlmToolSchema` discriminated union (`{ kind: 'zod', schema }` or `{ kind: 'jsonSchema', schema, validate? }`). The legacy `{ parse: fn }` shape throws `LlmError({ kind: 'tool_schema_invalid' })` at runtime. `LlmToolSchema` is exported from the package root. New `tool_schema_invalid` error kind added. See [Tool calling](#tool-calling-v100) for migration examples.\n- **v1.7.0** — `createClient()` is now `async`. `pricing.remoteUrl` config option fetches a remote `PricingTable` on init (stale-while-revalidate cache, 24h default TTL). `pricing.cacheTtlMs` controls the TTL. Structured `pricing_source` log on every `createClient()` with pricing config. Requires `@diabolicallabs/llm-pricing@^0.2.0`.\n- **v1.6.0** — `LlmAfterCallContext` now carries `usage?: LlmUsage` for all 5 call types. Non-streaming paths mirror `response.usage`; `stream()` captures from the terminal chunk; `streamStructured()` from the `done` event. The v1.5.0 caveat (\"usage not surfaced for streaming in afterCall\") is removed. `agent-sdk` v2.0.0 uses this to complete its architecture migration.\n- **v1.5.0** — Pre-call hooks API (`hooks?: LlmHooks` on `createClient`). `beforeCall` for request mutation and short-circuit caching; `afterCall` for custom logging and observability. Fires on all 5 call types. Cross-reference: [`@diabolicallabs/agent-sdk`](../agent-sdk/README.md) uses hooks internally.\n- **v1.4.0** — Provider capability matrix (`getModelCapabilities()`), linked AbortController helper (`linkedAbortController()`), response IDs on all response types (`id` + `idSource`).\n- **v1.3.0** — Streaming structured output (`streamStructured()`) — token streaming + Zod-validated final object. OpenAI, Anthropic, DeepSeek supported; Gemini and Perplexity throw pre-call.\n- **v1.2.0** — Configurable retry strategy (exponential/linear/fixed/decorrelated), provider failover via `model: string[]`, `Retry-After` header support.\n- **v1.1.0** — Per-response cost computation via `@diabolicallabs/llm-pricing`; concurrency pool at `@diabolicallabs/llm-client/pool`.\n- **v1.0.0** — Native tool calling (`withTools()`), expanded `LlmErrorKind` taxonomy, OpenAI Responses API migration.\n\n## Install\n\n```bash\npnpm add @diabolicallabs/llm-client\n```\n\nPublic on npmjs.com — no `.npmrc` config required.\n\n## Usage\n\n```typescript\nimport { createClient, createClientFromEnv } from '@diabolicallabs/llm-client';\n\n// From explicit config — createClient() is async (v1.7.0+)\nconst client = await createClient({\n  provider: 'anthropic',\n  model: 'claude-sonnet-4-6',\n  apiKey: process.env.ANTHROPIC_API_KEY!,\n});\n\n// From environment variables — also async\nconst client = await createClientFromEnv('anthropic', 'claude-sonnet-4-6');\n\n// Non-streaming completion\nconst response = await client.complete([\n  { role: 'user', content: 'Hello' },\n]);\nconsole.log(response.content, response.usage);\n\n// Streaming\nfor await (const chunk of client.stream([{ role: 'user', content: 'Hello' }])) {\n  process.stdout.write(chunk.token);\n}\n\n// Structured output — Zod 4 schema triggers strict native mode automatically\nimport { z } from 'zod';\nconst schema = z.object({ name: z.string(), score: z.number() });\nconst result = await client.structured(messages, schema);\n// result.data is typed as { name: string; score: number }\n// result.model and result.id are populated (v0.4.0+)\n```\n\n## Strict structured outputs (v0.4.0)\n\nPass a **Zod 4** schema to `structured()` and the toolkit automatically routes to the strictest native path available for each provider. No opt-in flag required.\n\n```typescript\nimport { z } from 'zod';\nconst schema = z.object({\n  topic: z.string(),\n  bullets: z.array(z.string()),\n});\n\nconst result = await client.structured(messages, schema);\n// result.data    — typed and Zod-validated\n// result.model   — model ID used (always present, v0.4.0+)\n// result.id      — provider request ID for tracing (OpenAI + Anthropic)\n// result.citations — Perplexity citations if any\n```\n\n### How detection works\n\nThe toolkit checks for Zod 4's internal `_zod` marker at runtime. If the schema is a Zod 4 instance, it converts to JSON Schema using Zod 4's built-in `z.toJSONSchema()` and routes to the native path. If the schema is anything else (plain `{ parse }` object, Zod 3, etc.), it falls back to the v0.3.0 system-prompt path.\n\n### Schema-feature support matrix\n\n| Provider | Native mode | What's enforced | Known limits |\n|---|---|---|---|\n| OpenAI (`gpt-4o`, `gpt-4o-mini`) | `text.format: { type: 'json_schema', strict: true }` (Responses API, v1.0.0) | Schema structure guaranteed; model cannot produce off-schema output | No `format`, `pattern`, or recursive schemas (`z.lazy()`). Throws at conversion time with clear message. |\n| Anthropic | Tool-use with forced `tool_choice: { type: 'tool', name: 'extract' }` | Model must call the tool; `input` is pre-parsed JSON | Defense-in-depth `schema.parse()` still runs |\n| Gemini | `responseSchema` (OpenAPI 3.0) + `responseMimeType: 'application/json'` | Schema communicated to the model; belt-and-braces fence-strip retained | OBJECT schemas with empty `properties: {}` auto-receive a `_placeholder` sentinel (v1.0.0); stripped before Zod parse. |\n| DeepSeek | None (prompt-only, API limitation) | System-prompt nudge + schema.parse() | Same as v0.3.0 |\n| Perplexity | None (prompt-only, API limitation) | System-prompt nudge + `<think>` strip + schema.parse() | Same as v0.3.0; `citations` propagated to structured response |\n\n### Gemini empty-response classification (v6.9.0)\n\nGemini `structured()` (both the strict `responseSchema` path and the prompt-mode fallback) inspects `candidates[0].finishReason` and `promptFeedback.blockReason` **before** attempting `JSON.parse`, so an empty or whitespace-only response is classified by *why* it's empty instead of always throwing a generic `structured_parse_failed` with an empty `Raw: ` message:\n\n| Condition (response text is empty/whitespace-only) | `LlmError.kind` | Retryable |\n|---|---|---|\n| `finishReason === 'MAX_TOKENS'` | `max_tokens` | no — raise `maxTokens`, retrying with the same options reproduces the same truncation |\n| `finishReason === 'SAFETY'` or `promptFeedback.blockReason` is set | `content_filter` | no |\n| Any other finish reason, including a genuine `STOP` (e.g. an all-thought-parts response — `@google/genai`'s `.text` getter silently skips `thought: true` parts) | `empty_response` | no |\n| Response text is **non-empty** but fails `JSON.parse` | `structured_parse_failed` (unchanged) | no |\n\nEach new error's message names the finish reason / block reason and includes `usageMetadata.thoughtsTokenCount` / `candidatesTokenCount` when present, so you can tell a genuine thinking-budget exhaustion apart from a short truncation:\n\n```typescript\ntry {\n  const result = await client.structured(messages, schema);\n} catch (err) {\n  if (err instanceof LlmError && err.kind === 'max_tokens') {\n    // Retry with a higher maxTokens, or a lower reasoningEffort\n  }\n  if (err instanceof LlmError && err.kind === 'empty_response') {\n    // Model produced no visible output at all — inspect err.message for the finish reason\n  }\n}\n```\n\nA successful parse also carries `result.stopReason` (`'end_turn' | 'max_tokens' | 'content_filter'`, optional — Gemini only) so you can detect truncation even when the model's partial output happened to still be valid JSON.\n\n### Prompt-mode escape hatch\n\nIf your schema uses a feature unsupported in strict mode (e.g. `z.function()`, `z.lazy()`) and you need to keep using it, pass the escape hatch:\n\n```typescript\nconst result = await client.structured(messages, schema, {\n  providerOptions: { structuredMode: 'prompt' },\n});\n// Forces the v0.3.0 prompt-only path regardless of schema type\n```\n\nAlternatively, catch the `LlmError` thrown during schema conversion and inform the user:\n\n```typescript\ntry {\n  const result = await client.structured(messages, schema);\n} catch (err) {\n  if (err instanceof LlmError && err.kind === 'unknown') {\n    // Schema contains an unrepresentable feature — message names it\n    console.error(err.message);\n  }\n}\n```\n\n### Zod 3 schemas\n\nIf a Zod 3 schema is passed, the toolkit throws `LlmError` with a clear \"upgrade to Zod 4\" message rather than silently falling through to prompt mode. Pass `providerOptions.structuredMode = 'prompt'` if you cannot upgrade immediately.\n\n## Anthropic prompt caching (v0.4.3)\n\nAnthropic charges full input tokens on every call by default. Enable prompt caching to have Anthropic cache the system message block between calls, paying a 1.25× surcharge on the first (write) call and a 0.10× discount on every subsequent (read) call within the 5-minute TTL window.\n\n```typescript\nconst result = await client.complete(messages, {\n  providerOptions: { promptCache: 'ephemeral' },\n});\n\n// result.usage.cacheCreationTokens — tokens written to cache (first call)\n// result.usage.cacheReadTokens     — tokens read from cache (subsequent calls)\n```\n\nWorks identically on `complete()`, `stream()`, and `structured()` (both strict tool-use and prompt-fallback paths):\n\n```typescript\n// complete()\nconst r = await client.complete(messages, { providerOptions: { promptCache: 'ephemeral' } });\n\n// stream()\nfor await (const chunk of client.stream(messages, { providerOptions: { promptCache: 'ephemeral' } })) {\n  process.stdout.write(chunk.token);\n}\n\n// structured() — Zod 4 schema (strict tool-use path)\n// Also caches the tool definition as a second cache layer.\nconst r = await client.structured(messages, zodSchema, {\n  providerOptions: { promptCache: 'ephemeral' },\n});\n\n// structured() — prompt-fallback path (non-Zod schema or structuredMode: 'prompt')\nconst r = await client.structured(messages, narrowSchema, {\n  providerOptions: { structuredMode: 'prompt', promptCache: 'ephemeral' },\n});\n```\n\n### Cache semantics\n\n| Field | Description |\n|---|---|\n| **TTL** | 5 minutes (default). Anthropic also offers a 1-hour beta TTL — not yet exposed in the toolkit. |\n| **Minimum block size** | 1024 tokens for Claude Sonnet and Opus models; 2048 tokens for Haiku. Below minimum, the API silently ignores the marker — callers pay no write surcharge. |\n| **Write cost** | 1.25× normal input token price. |\n| **Read cost** | 0.10× normal input token price. |\n| **Break-even** | ~3 cache reads within the TTL window. |\n\nThe toolkit always sends the `cache_control` marker and lets Anthropic's API enforce minimum block size. No client-side token estimation is performed — simpler, and the API's behavior is authoritative.\n\n### Usage fields\n\nCache token counts surface in `LlmUsage`:\n\n```typescript\ninterface LlmUsage {\n  inputTokens: number;\n  outputTokens: number;\n  totalTokens: number;\n  cacheCreationTokens?: number; // tokens written to cache (Anthropic only)\n  cacheReadTokens?: number;     // tokens read from cache (Anthropic only)\n}\n```\n\nOn a cold call (cache miss): `cacheCreationTokens > 0`, `cacheReadTokens === 0`.\nOn a warm call (cache hit within TTL): `cacheReadTokens > 0`, `cacheCreationTokens === 0`.\n\n### Provider isolation\n\n`providerOptions.promptCache` is Anthropic-only. Passing it to an OpenAI, Gemini, DeepSeek, or Perplexity client has no effect — those providers ignore unrecognized `providerOptions` fields.\n\nOpenAI has implicit automatic prompt caching on some models (no opt-in needed). Perplexity and Gemini caching models are different — if needed, those warrant separate briefs.\n\n## Provider universe\n\n| Provider | Status | Env var |\n|---|---|---|\n| `anthropic` | Implemented | `ANTHROPIC_API_KEY` |\n| `openai` | Implemented | `OPENAI_API_KEY` |\n| `gemini` | Implemented | `GOOGLE_AI_API_KEY` |\n| `deepseek` | Implemented | `DEEPSEEK_API_KEY` |\n| `perplexity` | Implemented | `PERPLEXITY_API_KEY` |\n\n## Perplexity — web-grounded responses\n\nThe Perplexity provider returns real-time web-grounded answers with source citations. Use it via `createClient` or `createClientFromEnv`:\n\n```typescript\nconst client = createClientFromEnv('perplexity', 'sonar');\nconst response = await client.complete([\n  { role: 'user', content: 'What happened in AI this week?' },\n]);\n\n// Citations are deduplicated by URL\nconsole.log(response.citations);\n// [{ url: 'https://example.com/article' }, { url: 'https://reuters.com/story' }]\n```\n\n### Citations\n\n`LlmResponse.citations` is populated when Perplexity returns source URLs. It is `undefined` for all other providers.\n\n```typescript\ninterface LlmResponse {\n  content: string;\n  model: string;\n  usage: LlmUsage;\n  latencyMs: number;\n  citations?: Array<{\n    url: string;\n    title?: string;  // Perplexity currently returns URLs only; title is always undefined\n  }>;\n}\n```\n\nCitations are deduplicated by URL within a single response. They are **not available in stream mode** — use `complete()` when you need citations.\n\n### Search filters via `providerOptions`\n\nPerplexity supports search-specific parameters. Pass them via the `providerOptions` escape hatch on any call:\n\n```typescript\nawait client.complete(messages, {\n  providerOptions: {\n    search_recency_filter: 'week',   // 'month' | 'week' | 'day' | 'hour'\n    search_domain_filter: ['nytimes.com', 'reuters.com'],  // allowlist\n  },\n});\n```\n\n`providerOptions` is `Record<string, unknown>` — unknown fields are forwarded to the Perplexity API unchanged, so newly-released filters work without a toolkit update. Other providers ignore `providerOptions`.\n\n### Reasoning models\n\nPass reasoning model IDs as the `model` string:\n\n```typescript\nconst client = createClientFromEnv('perplexity', 'sonar-reasoning-pro');\n```\n\nAvailable models (verified 2026-05-08):\n\n| Model | Notes |\n|---|---|\n| `sonar` | Lightweight search model. Default. |\n| `sonar-pro` | Advanced search, more citations. |\n| `sonar-reasoning-pro` | Chain-of-thought reasoning. Replaces deprecated `sonar-reasoning`. |\n| `sonar-deep-research` | Exhaustive research. Perplexity docs indicate async job support — treat as experimental with this toolkit. |\n\n`structured()` with `sonar-reasoning-pro` works correctly — reasoning tokens (`<think>...</think>`) are stripped before JSON parsing.\n\n`sonar-deep-research` is accepted as a model string. If Perplexity's API returns an incompatible async response shape, the call will throw a clear `LlmError`. In that case, use `sonar-reasoning-pro` instead, or wait for a future deep-research-specific brief.\n\n## API\n\n### `createClient(config: LlmClientConfig): LlmClient`\n\nCreates an `LlmClient` for the given provider.\n\n### `createClientFromEnv(provider, model, overrides?): LlmClient`\n\nReads the API key from the environment automatically:\n- `anthropic` → `ANTHROPIC_API_KEY`\n- `openai` → `OPENAI_API_KEY`\n- `gemini` → `GOOGLE_AI_API_KEY`\n- `deepseek` → `DEEPSEEK_API_KEY`\n- `perplexity` → `PERPLEXITY_API_KEY`\n\n### `LlmClient` interface\n\n| Method | Description |\n|---|---|\n| `complete(messages, options?)` | Non-streaming completion. Returns `LlmResponse` (includes `citations` for Perplexity). |\n| `stream(messages, options?)` | Streaming — async generator of `LlmStreamChunk`. Final chunk includes `usage`. Citations unavailable. |\n| `structured(messages, schema, options?)` | Structured output validated against a Zod schema. Returns `LlmStructuredResponse<T>`. |\n| `streamStructured(messages, schema, options?)` | Token streaming + Zod-validated final object. Returns `AsyncGenerator<LlmStreamStructuredEvent<T>>`. See [Streaming structured output (v1.3.0)](#streaming-structured-output-v130). |\n| `withTools(messages, tools, options?)` | Native tool calling. Returns `LlmToolResponse`. See [Tool calling](#tool-calling-v100). |\n\nAll methods accept `LlmCallOptions` as the options parameter:\n\n```typescript\ninterface LlmCallOptions {\n  model?: string;\n  maxTokens?: number;\n  temperature?: number;\n  timeoutMs?: number;              // Per-call timeout (ms). Overrides config.timeoutMs.\n  signal?: AbortSignal;            // Caller-supplied cancel signal. Never retried.\n  streamStallTimeoutMs?: number;   // Per-chunk silence timeout for stream(). Default 30000.\n  mediaResolution?: LlmMediaResolution; // Gemini-only. See \"Media resolution (Gemini)\" below.\n  providerOptions?: Record<string, unknown>;  // Perplexity search filters, etc.\n}\n```\n\n## Tool calling (v1.0.0)\n\n`withTools()` enables native function calling across all supported providers. The toolkit handles provider-specific tool shapes, stop-reason mapping, and argument validation internally.\n\n### `LlmToolSchema` — tool input schema (v5.0.0, breaking)\n\nEvery `LlmTool.inputSchema` must be an `LlmToolSchema` discriminated union. There are two variants:\n\n**Zod variant** (`kind: 'zod'`) — recommended for type-safe tools. Pass a Zod 4 schema. The toolkit converts it to JSON Schema for the wire call and calls `schema.parse()` to validate the model's returned arguments automatically.\n\n```typescript\nimport { z } from 'zod';\nimport { type LlmTool, createClientFromEnv } from '@diabolicallabs/llm-client';\n\nconst weatherTool: LlmTool = {\n  name: 'get_weather',\n  description: 'Get the current weather for a city.',\n  inputSchema: {\n    kind: 'zod',\n    schema: z.object({ city: z.string() }),\n  },\n};\n```\n\n**JSON Schema variant** (`kind: 'jsonSchema'`) — use when you already have a JSON Schema or want to avoid a Zod dependency. The `schema` object is sent verbatim to the provider. The optional `validate` function is called for argument validation; when omitted, the raw model output is returned without validation.\n\n```typescript\nimport { type LlmTool, createClientFromEnv } from '@diabolicallabs/llm-client';\n\nconst weatherTool: LlmTool = {\n  name: 'get_weather',\n  description: 'Get the current weather for a city.',\n  inputSchema: {\n    kind: 'jsonSchema',\n    schema: {\n      type: 'object',\n      properties: { city: { type: 'string' } },\n      required: ['city'],\n    },\n    // validate is optional — omit if you don't need runtime argument checking\n    validate: (d) => {\n      if (typeof (d as { city?: unknown }).city !== 'string') {\n        throw new Error('city must be a string');\n      }\n      return d as { city: string };\n    },\n  },\n};\n```\n\n> **v5 migration:** The v4.x `inputSchema: { parse: fn }` shape (including a bare Zod schema passed directly as `inputSchema`) no longer works. It throws `LlmError({ kind: 'tool_schema_invalid' })` at runtime. Replace it with one of the two variants above.\n\n### Basic usage\n\n```typescript\nimport { z } from 'zod';\nimport { type LlmTool, createClientFromEnv } from '@diabolicallabs/llm-client';\n\nconst client = await createClientFromEnv('anthropic', 'claude-sonnet-4-6');\n\nconst weatherTool: LlmTool = {\n  name: 'get_weather',\n  description: 'Get the current weather for a city.',\n  inputSchema: {\n    kind: 'zod',\n    schema: z.object({ city: z.string() }),\n  },\n};\n\nconst result = await client.withTools(\n  [{ role: 'user', content: 'What is the weather in London?' }],\n  [weatherTool]\n);\n\n// result.stopReason — 'tool_use' | 'end_turn' | 'max_tokens' | 'content_filter' | ...\n// result.toolCalls — array of LlmToolCall (may be empty if model responded with text)\n// result.content   — any text the model produced alongside tool calls\n// result.model     — model ID used\n// result.usage     — normalized token usage\n\nif (result.stopReason === 'tool_use') {\n  for (const call of result.toolCalls) {\n    console.log(call.toolName, call.arguments); // arguments validated by inputSchema\n    console.log(call.id);           // use as tool_call_id in the follow-up message\n    console.log(call.rawArguments); // original JSON string from the model\n  }\n}\n```\n\n### Tool options\n\n```typescript\ninterface LlmCallWithToolsOptions extends LlmCallOptions {\n  toolChoice?: 'auto' | 'any' | 'none' | { name: string };\n  parallelToolCalls?: boolean; // default: true (parallel-enabled)\n}\n```\n\n`toolChoice`:\n- `'auto'` (default) — model decides whether and which tools to call.\n- `'any'` — model must call at least one tool. Maps to `'required'` on OpenAI Responses API; `{ type: 'any' }` on Anthropic.\n- `'none'` — model must not call any tool.\n- `{ name: 'tool_name' }` — model must call the named tool.\n\n`parallelToolCalls: false` — disable parallel tool invocations. Maps to `parallel_tool_calls: false` on OpenAI and DeepSeek; `disable_parallel_tool_use: true` on Anthropic `tool_choice`; ignored on Gemini (no equivalent).\n\n### Provider tool support matrix\n\n| Provider | Tool calling | `parallelToolCalls` | Named `toolChoice` | Stop reasons |\n|---|---|---|---|---|\n| OpenAI | Native (Responses API flat shape) | Supported | Supported | `tool_use`, `end_turn`, `max_tokens`, `refusal` |\n| Anthropic | Native (`{ name, description, input_schema }`) | Supported (inverse: `disable_parallel_tool_use`) | Supported | `tool_use`, `end_turn`, `max_tokens`, `stop_sequence`, `pause_turn`, `refusal` |\n| Gemini | Native (`parametersJsonSchema`) | Not applicable (no Gemini equivalent) | Falls back to AUTO | `tool_use`, `end_turn`, `max_tokens`, `content_filter`, `stop_sequence` |\n| DeepSeek | Native (Chat Completions nested shape) | Supported | Supported | `tool_use`, `end_turn`, `max_tokens`, `content_filter` |\n| Perplexity | Not supported | N/A | N/A | Throws `kind:'bad_request'` immediately |\n\n### Argument validation\n\nAfter the model returns its arguments, the toolkit validates them against the tool's `inputSchema`:\n\n- **`kind: 'zod'`** — calls `schema.parse(args)`. Throws `LlmError({ kind: 'tool_arguments_invalid' })` if validation fails.\n- **`kind: 'jsonSchema'`** — calls `validate(args)` when provided. If `validate` throws or returns a rejected promise, `withTools()` throws `LlmError({ kind: 'tool_arguments_invalid' })`. When `validate` is omitted, the raw output is returned without checking.\n\nPassing an `inputSchema` that has no `kind` field (e.g. the legacy `{ parse: fn }` shape from v4.x) throws `LlmError({ kind: 'tool_schema_invalid' })`, `retryable: false` — before any provider call is made.\n\n### Gemini ID synthesis\n\nGemini does not issue native response IDs or tool call IDs. The toolkit synthesizes UUID v7-style IDs (time-based + random) for `LlmToolCall.id` and for the response-level `id` field on all Gemini responses (`complete()`, `structured()`, `withTools()`). These IDs are time-sortable (the first 12 hex characters encode the millisecond timestamp) but not cryptographically random. Use `idSource` to distinguish synthesized IDs from provider-issued ones.\n\n## Streaming structured output (v1.3.0)\n\n`streamStructured()` combines the typing-progress UX of `stream()` with the Zod-validated final object of `structured()`. It emits incremental token events as the model generates output, then validates the accumulated text against the schema before emitting a final `done` event.\n\n```typescript\nimport { z } from 'zod';\nimport { createClientFromEnv } from '@diabolicallabs/llm-client';\n\nconst client = createClientFromEnv('openai', 'gpt-4o');\nconst schema = z.object({ summary: z.string(), sentiment: z.enum(['positive', 'negative', 'neutral']) });\n\nfor await (const event of client.streamStructured(\n  [{ role: 'user', content: 'Analyze this review: \"Great product, fast shipping!\"' }],\n  schema\n)) {\n  if (event.type === 'token') {\n    process.stdout.write(event.token); // show typing progress\n  } else if (event.type === 'done') {\n    console.log('\\nValidated output:', event.data);\n    console.log('Usage:', event.usage);\n  }\n}\n```\n\n### Event shape\n\n```typescript\ntype LlmStreamStructuredEvent<T> =\n  | { type: 'token'; token: string }  // incremental text chunk\n  | { type: 'done'; data: T; usage: LlmUsage };  // final, validated result\n```\n\n`token` events arrive during generation. Exactly one `done` event arrives at the end. If `JSON.parse()` or `schema.parse()` fails, `LlmError` with `kind: 'structured_parse_failed'` is thrown instead (no `done` event).\n\n### Provider support matrix for `streamStructured()`\n\n| Provider | Support | Notes |\n|---|---|---|\n| OpenAI | Supported | Streams `output_text.delta` events via Responses API. Zod 4 schemas enable `json_schema` strict mode; non-Zod schemas use `json_object` mode. |\n| Anthropic | Supported | Uses forced tool-use (`extract` tool, `tool_choice: tool`). Streams `input_json_delta` events — raw JSON fragments that assemble into the final object. |\n| DeepSeek | Supported | Streams Chat Completions deltas with `response_format: { type: 'json_object' }`. Falls back to `parseJsonOrThrow` if `JSON.parse` fails (handles chain-of-thought preamble from `deepseek-reasoner`). |\n| Gemini | Not supported | Throws `LlmError(kind: 'bad_request')` immediately. Gemini does not reliably support simultaneous `responseSchema` constraints and streaming. Use `stream()` for tokens or `structured()` for validation. |\n| Perplexity | Not supported | Throws `LlmError(kind: 'bad_request')` immediately. Search/retrieval models do not return tool-validated JSON. |\n\n### Failover and pricing\n\n`streamStructured()` **does not support provider failover** — mid-stream model switching would corrupt the token sequence. It always uses the primary model from a `model: string[]` config.\n\n`streamStructured()` **does not attach cost** — cost computation requires final token counts from a complete response object. Use `complete()` or `structured()` if you need cost tracking via `config.pricing`.\n\nAbortSignal, stall detection (`streamStallTimeoutMs`), and timeout (`timeoutMs`) all work identically to `stream()`.\n\n## Provider capability matrix (v1.4.0)\n\nQuery provider capabilities statically — no client instance needed.\n\n```typescript\nimport { getModelCapabilities } from '@diabolicallabs/llm-client';\n\nconst caps = getModelCapabilities('anthropic', 'claude-opus-4-7');\nif (caps === null) {\n  throw new Error('Unknown model');\n}\n\nconsole.log(caps.contextWindow);    // 1_000_000\nconsole.log(caps.tools);            // true\nconsole.log(caps.parallelTools);    // true\nconsole.log(caps.promptCache);      // 'ephemeral'\nconsole.log(caps.structuredOutput); // 'tool-use'\nconsole.log(caps.responseIds);      // 'provider'\nconsole.log(caps.streamStructured); // true\nconsole.log(caps.mediaInput);       // { image: { base64: true, url: true }, document: { pdfBase64: true } }\nconsole.log(caps.reasoningEffort);  // 'anthropic-effort'\n```\n\nReturns `null` for unknown models — never throws.\n\n### `ModelCapabilities` shape\n\n```typescript\ninterface ModelCapabilities {\n  contextWindow: number;          // max input tokens\n  maxOutputTokens: number;        // max single-response tokens\n  streaming: boolean;             // stream() supported\n  tools: boolean;                 // withTools() supported\n  parallelTools: boolean;         // model can invoke multiple tools per turn\n  promptCache: 'ephemeral' | '1h' | null; // Anthropic only; null for all others\n  structuredOutput: 'tool-use' | 'json-schema' | 'response-schema' | null;\n  responseIds: 'provider' | 'synthesized'; // Gemini = 'synthesized'\n  streamStructured: boolean;      // streamStructured() supported\n  mediaInput: {                   // multimodal content block support (v4.2.0+)\n    image: { base64: boolean; url: boolean };\n    document: { pdfBase64: boolean };\n    mediaResolution: 'request' | 'part' | null; // Gemini media-resolution tier (v6.7.0+)\n  };\n  reasoningEffort: 'anthropic-effort' | 'openai-effort' | 'gemini-thinking-level' | null; // v6.3.0+\n}\n```\n\n### Provider capability summary\n\n| Provider | tools | parallelTools | promptCache | structuredOutput | responseIds | streamStructured |\n|---|---|---|---|---|---|---|\n| Anthropic | true | true | `'ephemeral'` | `'tool-use'` | `'provider'` | true |\n| OpenAI | true | true | null | `'json-schema'` | `'provider'` | true |\n| Gemini | true | false | null | `'response-schema'` | `'synthesized'` | false |\n| DeepSeek | true | true | null | `'json-schema'` | `'provider'` | true |\n| Perplexity | false | false | null | null | `'provider'` | false |\n\n### `reasoningEffort` per provider/model (v6.3.0)\n\n`reasoningEffort` is a dialect tag, not a value-set enumeration — cross-reference it against the accepted `LlmReasoningEffort` subset for that dialect (see [Reasoning-effort passthrough](#reasoning-effort-passthrough-v630) below):\n\n| Dialect tag | Accepted `LlmReasoningEffort` values | Example models |\n|---|---|---|\n| `'anthropic-effort'` | `low`, `medium`, `high`, `xhigh`, `max` | `claude-opus-5`, `claude-opus-4-7`, `claude-opus-4-6`, `claude-sonnet-4-6` |\n| `'openai-effort'` | all 7 values | `gpt-5.6-sol`, `gpt-5.6-terra`, `gpt-5.6-luna`, `gpt-5.5`, `gpt-5.5-pro`, `gpt-5.4`, `gpt-5.4-mini`, `o3`, `o4-mini` |\n| `'gemini-thinking-level'` | `minimal`, `low`, `medium`, `high` | `gemini-3.1-pro-preview`, `gemini-3.1-flash-lite`, `gemini-3.5-flash`, `gemini-3.7-flash`, `gemini-3.8-flash` |\n| `null` | not supported | every Perplexity/DeepSeek row; `gpt-4.1`; Gemini 2.5-series (`thinkingBudget`, not `thinkingLevel`); Anthropic models not listed above |\n\n`getModelCapabilities` covers all models in `@diabolicallabs/llm-pricing`'s `DEFAULT_PRICING_TABLE`, including `gemini-3.8-flash` (v6.7.0+, GA 2026-09-02). The table is versioned at `CAPABILITIES_VERSIONED_AT: '2026-09-05'` — import it to detect staleness.\n\n## Reasoning-effort passthrough (v6.3.0)\n\nSet `reasoningEffort` on any call to control how many tokens the model spends thinking/reasoning, where the resolved provider/model supports it. Purely additive and opt-in — omitting it changes nothing.\n\n```typescript\nimport { createClient } from '@diabolicallabs/llm-client';\n\nconst client = createClient({ provider: 'anthropic', model: 'claude-opus-5', apiKey: '...' });\n\nconst response = await client.complete(\n  [{ role: 'user', content: 'Analyze the trade-offs between microservices and monoliths.' }],\n  { reasoningEffort: 'high' } // sweep across 'low' | 'medium' | 'high' | 'xhigh' | 'max'\n);\n\nconsole.log(response.usage.reasoningTokens); // tokens spent on internal reasoning, when reported\n```\n\n**All three providers' accepted value sets differ** — a value unsupported by the resolved provider throws `LlmError({ kind: 'bad_request', retryable: false })` before any SDK call:\n\n| Provider | Wire field | Accepted `LlmReasoningEffort` values |\n|---|---|---|\n| Anthropic | `output_config.effort` | `'low' \\| 'medium' \\| 'high' \\| 'xhigh' \\| 'max'` — no `'none'`/`'minimal'` |\n| OpenAI | `reasoning.effort` | all 7 values — `'none' \\| 'minimal' \\| 'low' \\| 'medium' \\| 'high' \\| 'xhigh' \\| 'max'` |\n| Gemini | `thinkingConfig.thinkingLevel` (uppercase on the wire) | `'minimal' \\| 'low' \\| 'medium' \\| 'high'` — no `'none'`/`'xhigh'`/`'max'` |\n| Perplexity, DeepSeek | — | not supported at all; setting `reasoningEffort` throws `bad_request` before any SDK call, for every method |\n\n```typescript\n// OpenAI — all 7 values valid\nawait client.complete(messages, { model: 'gpt-5.6-sol', reasoningEffort: 'none' });\n\n// Gemini — uppercase mapping happens internally ('high' -> 'HIGH' on the wire)\nawait client.complete(messages, { model: 'gemini-3.5-flash', reasoningEffort: 'high' });\n\n// Throws bad_request before any SDK call — Anthropic has no 'none'/'minimal'\nawait client.complete(messages, { model: 'claude-opus-5', reasoningEffort: 'none' }); // throws\n```\n\n**`LlmUsage.reasoningTokens`** is populated from both providers that report a reasoning/thinking token breakdown separately from `outputTokens` — Anthropic (`usage.output_tokens_details.thinking_tokens`) and OpenAI (`usage.output_tokens_details.reasoning_tokens`) — in both the streaming and non-streaming paths. Undefined for Gemini, Perplexity, and DeepSeek, which don't report this breakdown, and undefined when `reasoningEffort` wasn't set.\n\nCross-reference `getModelCapabilities(provider, model).reasoningEffort` against the table above to know which values a specific model accepts before setting `reasoningEffort` — see [Provider capability matrix](#provider-capability-matrix-v140).\n\n## Media resolution (Gemini) (v6.7.0)\n\nSet `mediaResolution` to control how many tokens a Gemini image, document, or file content block consumes. Gemini-only — silently ignored by Anthropic, OpenAI, DeepSeek, and Perplexity (not a value-set mismatch; those providers simply don't read this field).\n\n```typescript\nimport { createClient } from '@diabolicallabs/llm-client';\n\nconst client = createClient({\n  provider: 'gemini',\n  model: 'gemini-3.8-flash',\n  apiKey: process.env.GOOGLE_AI_API_KEY!,\n  mediaResolution: 'medium', // config-level default for every media part\n});\n\n// Per-call override — applies to every media part in this call\nawait client.complete(messages, { mediaResolution: 'low' });\n\n// Per-block override — applies to this part only, beats call- and config-level\nconst blocks = [\n  {\n    type: 'document' as const,\n    source: { type: 'base64' as const, mediaType: 'application/pdf' as const, data: pdfBase64 },\n    mediaResolution: 'high' as const,\n  },\n];\n```\n\n**Precedence:** block-level > call-level > config-level.\n\n**Live token measurements (one PDF page, verified 2026-09-05):**\n\n| Model | unspecified | `low` | `medium` | `high` |\n|---|---|---|---|---|\n| gemini-3.8-flash | 520 (= medium) | 266 | 520 | 1102 |\n| gemini-3.7-flash | 520 (= medium) | 266 | 520 | 1102 |\n| gemini-2.5-flash | 258 | 66 | 258 | 258 |\n\n**Per-part support is Gemini 3.x only.** Gemini 2.5-series models (`gemini-2.5-pro`, `gemini-2.5-flash`, `gemini-2.5-flash-lite`) return HTTP 400 when a per-part `mediaResolution` is set on a content block — request-level `mediaResolution` still works on 2.5. Cross-reference `getModelCapabilities(provider, model).mediaInput.mediaResolution` (`'part'` | `'request'` | `null`) before setting a per-block value.\n\n**`'ultra_high'` is image-only.** It has no request-level `MediaResolution` enum member — setting `mediaResolution: 'ultra_high'` on `LlmClientConfig` or `LlmCallOptions` throws `bad_request` before any SDK call. Per-block, it is valid on `image` blocks but throws `bad_request` pre-flight on `document` blocks (Google documents `ultra_high` as image-only; the Gemini API itself returns HTTP 400 for it on documents).\n\n**Google's guidance:** `'medium'` for document pages (quality saturates beyond it), `'high'` for small type in standalone images, `'low'` to roughly halve token cost. Gemini 3's default for PDF pages is already `'medium'` — explicitly setting `mediaResolution: 'medium'` on a Gemini 3 document call changes nothing; the lever worth pulling is `'low'` for cost or `'high'` for small-type misses.\n\n## Linked AbortController helper (v1.4.0)\n\n`linkedAbortController` is a utility for fan-out patterns where a root signal cancels all in-flight calls and individual calls have their own per-call timeouts.\n\n```typescript\nimport { linkedAbortController } from '@diabolicallabs/llm-client';\n\nconst root = new AbortController();\n\nconst calls = tasks.map(t => {\n  const child = linkedAbortController(root.signal, { timeoutMs: 30_000 });\n  return client\n    .complete(t.messages, { signal: child.signal })\n    .finally(() => child.dispose()); // clean up on completion — prevents listener leak\n});\n\n// Cancel all in-flight calls at once\nroot.abort('shutdown');\n\n// Or wait for all results (some may have individual timeouts)\nconst results = await Promise.allSettled(calls);\n```\n\n### Behaviour\n\n| Scenario | Result |\n|---|---|\n| Parent aborts | Child aborts immediately, forwarding the parent's abort reason |\n| Parent already aborted at call time | Child aborts synchronously, no API call made |\n| `timeoutMs` fires | Child aborts with timeout reason string; independent of the parent signal |\n| `dispose()` called | Parent listener + timer cleared; child NOT aborted |\n| `abort()` called on handle | Child aborts immediately; `dispose()` called implicitly |\n\nAlways call `dispose()` in a `finally` block — it removes the parent listener and clears the timer, preventing leaks if the parent fires after the call completes.\n\n### API\n\n```typescript\nfunction linkedAbortController(\n  parentSignal: AbortSignal,\n  options?: { timeoutMs?: number }\n): {\n  signal: AbortSignal;     // pass to client.complete(), stream(), etc.\n  abort: (reason?) => void; // abort child immediately\n  dispose: () => void;      // clean up without aborting\n};\n```\n\n## Response IDs everywhere (v1.4.0)\n\nAll three response types (`LlmResponse`, `LlmStructuredResponse<T>`, `LlmToolResponse`) now carry `id: string` and `idSource: 'provider' | 'synthesized'` on every call.\n\n```typescript\nconst response = await client.complete(messages);\nconsole.log(response.id);       // 'msg_abc123' (Anthropic) or synthesized UUID (Gemini)\nconsole.log(response.idSource); // 'provider' | 'synthesized'\n```\n\n### ID sources by provider\n\n| Provider | id source | idSource |\n|---|---|---|\n| Anthropic | `response.id` (Anthropic message ID) | `'provider'` |\n| OpenAI | `response.id` (Responses API) | `'provider'` |\n| DeepSeek | `response.id` (Chat Completions) | `'provider'` |\n| Perplexity | `response.id` (Chat Completions) | `'provider'` |\n| Gemini | UUID v7-style synthesized by toolkit | `'synthesized'` |\n\nSynthesized IDs are time-sortable (first 12 hex chars encode the millisecond timestamp) — useful for trace correlation without a separate timestamp. Check `idSource === 'synthesized'` before treating the ID as a durable provider reference.\n\n**Migration from v1.3.x:** `id` was previously `id?` (optional) on `LlmStructuredResponse` and `LlmToolResponse`, and absent from `LlmResponse`. It is now `id: string` (always present) on all three types. Remove any `response.id !== undefined` null checks.\n\n## Cancellation, timeouts, stall detection\n\n### Per-call timeout override\n\nThe default timeout is set at client construction via `config.timeoutMs` (default 30 000 ms). Override it per-call:\n\n```typescript\nconst client = createClient({\n  provider: 'anthropic',\n  model: 'claude-sonnet-4-6',\n  apiKey: process.env.ANTHROPIC_API_KEY!,\n  timeoutMs: 30_000, // client default\n});\n\n// This call gets 90 seconds — useful for sonar-deep-research or long reasoning\nconst response = await client.complete(messages, { timeoutMs: 90_000 });\n```\n\n**Multimodal and reasoning calls commonly need ≥ 90 seconds.** A whole-document (`document`/`file` content block) call, especially combined with `reasoningEffort`, routinely exceeds the 30 second default — the default itself is unchanged, but raise `timeoutMs` explicitly for these calls:\n\n```typescript\n// A whole-PDF extraction call with reasoning — 30s is not enough for this shape of call.\nconst response = await client.complete(\n  [{ role: 'user', content: [documentBlock, { type: 'text', text: 'Extract the brand guidelines.' }] }],\n  { timeoutMs: 90_000, reasoningEffort: 'medium' }\n);\n```\n\nOn timeout, `LlmError.kind === 'timeout'` and `retryable === true`. Each retry attempt gets a fresh deadline — the timeout resets per attempt, not across the full retry sequence.\n\n### Caller AbortSignal\n\nPass any `AbortSignal` to cancel an in-flight call immediately:\n\n```typescript\nconst ac = new AbortController();\n\n// Cancel on user navigation, request supersede, shutdown, etc.\nconst responsePromise = client.complete(messages, { signal: ac.signal });\n\n// Cancel before the call returns\nac.abort('user navigated away');\n\ntry {\n  await responsePromise;\n} catch (err) {\n  if (err instanceof LlmError && err.kind === 'cancelled') {\n    // Gracefully handle the cancellation\n  }\n}\n```\n\n- A signal already aborted at call time throws immediately — no SDK call is made, no retry.\n- A mid-call abort propagates to the SDK (Anthropic, OpenAI, DeepSeek, Perplexity) or wins a `Promise.race` (Gemini). `kind === 'cancelled'`, `retryable === false`. Never retried.\n\n### Stream stall detection\n\nA stream that emits a first chunk and then silently hangs will stall the consumer indefinitely without this feature. `streamStallTimeoutMs` fires a timer per chunk — if no chunk arrives within the window, the stream is aborted and a `kind: 'stream_stall'` error surfaces:\n\n```typescript\ntry {\n  for await (const chunk of client.stream(messages, { streamStallTimeoutMs: 10_000 })) {\n    process.stdout.write(chunk.token);\n  }\n} catch (err) {\n  if (err instanceof LlmError && err.kind === 'stream_stall') {\n    console.error('stream stalled — retry or fallback');\n  }\n}\n```\n\n- Default `streamStallTimeoutMs`: 30 000 ms (set independently of `timeoutMs` — tolerant of reasoning-model think-pauses).\n- The stall timer resets after each chunk arrives, so slow-but-not-stalled streams complete normally.\n- Stall errors are **not retried** — partial output is unsafe to re-issue. The error surfaces to the caller.\n\n### `LlmError.kind` discriminator (v1.0.0)\n\n```typescript\n// Full taxonomy — all providers emit one of these kinds\ntype LlmErrorKind =\n  | 'rate_limit'              // 429\n  | 'server_error'            // 5xx\n  | 'auth'                    // 401, 403\n  | 'not_found'               // 404\n  | 'bad_request'             // 400\n  | 'content_filter'          // model refused, safety block\n  | 'context_length'          // prompt too long\n  | 'max_tokens'              // structured() output truncated by maxTokens before any parseable text (v6.9.0+, Gemini only)\n  | 'tool_arguments_invalid'  // withTools() argument validation failure (Zod or validate())\n  | 'tool_schema_invalid'     // withTools() — inputSchema missing kind field; legacy shape (v5+)\n  | 'structured_parse_failed' // structured() JSON parse or Zod validation failure on non-empty text\n  | 'empty_response'          // structured() returned no parseable text and no more specific reason applies (v6.9.0+, Gemini only)\n  | 'network'                 // ECONNRESET, ETIMEDOUT, etc.\n  | 'timeout'                 // per-call timeout\n  | 'stream_stall'            // stream silence exceeded streamStallTimeoutMs\n  | 'cancelled'               // AbortSignal fired\n  | 'http'                    // residual unclassified 4xx\n  | 'unknown';                // catch-all\n\nclass LlmError extends Error {\n  readonly provider: string;\n  readonly statusCode?: number;\n  readonly retryable: boolean;\n  readonly kind: LlmErrorKind; // always defined in v1.0.0\n}\n```\n\nSee [MIGRATION.md](./MIGRATION.md) for the full migration table from `err.kind === 'http'` checks to the new specific kinds.\n\n### Gemini cancellation caveat\n\n`@google/genai` does not accept a per-call `AbortSignal`. Cancellation uses `Promise.race` — when the internal controller aborts, we stop awaiting, but the SDK's HTTP request continues in the background until the SDK-level timeout fires. The SDK client is constructed with `httpOptions.timeout = configTimeoutMs * 2` as a backstop. This bounds the leaked request to at most 2× the configured timeout. Native signal support will be added when the SDK provides it.\n\n## Error handling\n\nAll provider errors are normalized into `LlmError`:\n\n```typescript\nimport { LlmError } from '@diabolicallabs/llm-client';\n\ntry {\n  const response = await client.complete(messages);\n} catch (err) {\n  if (err instanceof LlmError) {\n    console.error(err.provider, err.statusCode, err.retryable, err.kind);\n  }\n}\n```\n\nRetryable errors (429, 5xx, network failures, timeout) are retried automatically with exponential backoff and full jitter before throwing. Cancelled and stream-stall errors are never retried.\n\n## DeepSeek model IDs\n\nDeepSeek fully retired the `deepseek-chat` and `deepseek-reasoner` identifiers on\n2026-07-24 15:59 UTC, with **no fallback alias** — calls using either string now error\nat DeepSeek's API. The canonical IDs are:\n\n| Model | API ID | Notes |\n|---|---|---|\n| V4 Flash | `deepseek-v4-flash` | General use and reasoning (thinking mode). **Canonical default.** |\n| V4 Pro | `deepseek-v4-pro` | High-capability tier. Promotional pricing active through 2026-05-31. |\n\n**Retired IDs are rejected client-side.** As of the 2026-08-18 retirement fix, calling\nany `llm-client` method (`complete`, `stream`, `structured`, `withTools`,\n`streamStructured`) with `model: 'deepseek-chat'` or `model: 'deepseek-reasoner'` throws\nan `LlmError({ kind: 'bad_request', retryable: false })` immediately — before any HTTP\ncall reaches DeepSeek — naming the retired ID and pointing to `deepseek-v4-flash` as the\nreplacement:\n\n| Retired ID | Replacement | Was |\n|---|---|---|\n| `deepseek-chat` | `deepseek-v4-flash` | DeepSeek-V3 |\n| `deepseek-reasoner` | `deepseek-v4-flash` (thinking mode) | DeepSeek-R1 |\n\nThis is a deliberate reject-fast design, not a silent remap: auto-rerouting\n`deepseek-chat` to `deepseek-v4-flash` would change which model actually serves the\nrequest without the caller knowing. Update call sites to the canonical IDs — there is no\ncompatibility shim.\n\nUsage:\n\n```typescript\n// Canonical V4 Flash (default — replaces deepseek-chat)\nconst client = createClientFromEnv('deepseek', 'deepseek-v4-flash');\n\n// Canonical V4 Pro\nconst client = createClientFromEnv('deepseek', 'deepseek-v4-pro');\n```\n\n## Per-response cost computation (v1.1.0)\n\nAttach `cost?: LlmCost` to every response by configuring pricing at client creation time. Requires `@diabolicallabs/llm-pricing` as an optional peer dep.\n\n```bash\npnpm add @diabolicallabs/llm-pricing\n```\n\n```typescript\nimport { createClient } from '@diabolicallabs/llm-client';\n\n// createClient() is async (v1.7.0+) — await it\nconst client = await createClient({\n  provider: 'anthropic',\n  model: 'claude-sonnet-4-6',\n  apiKey: process.env.ANTHROPIC_API_KEY!,\n  pricing: { computeOnEveryCall: true },\n});\n\nconst response = await client.complete(messages);\nconsole.log(response.cost);\n// {\n//   input:     0.0003,   // USD\n//   output:    0.00075,  // USD\n//   cacheRead: 0,\n//   cacheWrite: 0,\n//   total:     0.00105,  // USD\n//   currency:  'USD',\n//   isPartial: false,    // true for o-series (invisible reasoning tokens) or sonar-deep-research\n// }\n```\n\n### Remote pricing table (v1.7.0)\n\nSet `pricing.remoteUrl` to fetch the latest prices from a URL on client init, with a stale-while-revalidate cache. No code change or npm release needed when prices change — consumers pick up updates on the next process restart.\n\n```typescript\nconst client = await createClient({\n  provider: 'anthropic',\n  model: 'claude-sonnet-4-6',\n  apiKey: process.env.ANTHROPIC_API_KEY!,\n  pricing: {\n    remoteUrl: 'https://raw.githubusercontent.com/mannism/dlabs-toolkit/main/pricing/table.json',\n    cacheTtlMs: 24 * 60 * 60 * 1000, // 24h (default)\n    computeOnEveryCall: true,\n  },\n});\n```\n\n**Precedence (highest → lowest):**\n\n| `pricing.table` | `pricing.remoteUrl` | Result |\n|---|---|---|\n| set | any | Consumer table always wins — no fetch |\n| unset | set | Fetched on init, cached per TTL |\n| unset | unset | Bundled `DEFAULT_PRICING_TABLE` |\n\nOn fetch failure (network error, HTTP error, schema validation failure, 5s timeout), the client falls back silently to `DEFAULT_PRICING_TABLE` and logs a structured warning. Pricing failures never crash LLM calls.\n\nA structured `pricing_source` log line is emitted on every `createClient()` with a pricing config:\n\n```json\n{ \"event\": \"pricing_source\", \"source\": \"remote\", \"url\": \"...\", \"fetchedAt\": \"...\" }\n```\n\n`source` is one of: `\"remote\"` | `\"cache\"` | `\"fallback\"` | `\"bundled\"` | `\"consumer_override\"`.\n\n### Static table override\n\nThe `pricing.table` option accepts a custom `PricingTable` from `@diabolicallabs/llm-pricing` to override default rates:\n\n```typescript\nimport { DEFAULT_PRICING_TABLE } from '@diabolicallabs/llm-pricing';\n\nconst client = await createClient({\n  provider: 'openai',\n  model: 'gpt-5.5',\n  apiKey: process.env.OPENAI_API_KEY!,\n  pricing: {\n    computeOnEveryCall: true,\n    table: {\n      ...DEFAULT_PRICING_TABLE,\n      openai: {\n        'gpt-5.5': { inputPer1M: 4.5, outputPer1M: 28.0, verifiedAt: '2026-05-14', sourceUrl: 'internal' },\n      },\n    },\n  },\n});\n```\n\n`stream()` does not attach cost — cost requires final token counts from a complete response. Use `complete()` if you need cost tracking. See [`@diabolicallabs/llm-pricing`](../llm-pricing/README.md) for the full pricing table, maintenance plan, and `pnpm pricing:verify` diagnostic script.\n\n## Hooks (v1.5.0+)\n\nAttach `beforeCall` and `afterCall` hooks to any `createClient()` config. Hooks fire for all five call types: `complete`, `stream`, `structured`, `withTools`, `streamStructured`.\n\n```typescript\nconst client = createClient({\n  provider: 'anthropic',\n  model: 'claude-sonnet-4-6',\n  apiKey: process.env.ANTHROPIC_API_KEY!,\n  hooks: {\n    beforeCall: async (ctx) => {\n      // ctx.callType, ctx.provider, ctx.model, ctx.messages, ctx.options\n    },\n    afterCall: async (ctx) => {\n      // ctx.request, ctx.response, ctx.usage, ctx.error, ctx.latencyMs\n    },\n  },\n});\n```\n\n### `beforeCall` — request mutation\n\nReturn `{ messages, options }` to replace the originals for that call. Subsequent calls use the original config values.\n\n```typescript\nhooks: {\n  // PII redaction before the request leaves the process\n  beforeCall: async (ctx) => ({\n    messages: ctx.messages.map((m) => ({\n      ...m,\n      content: redactPii(m.content),\n    })),\n  }),\n}\n```\n\n### `beforeCall` — short-circuit caching\n\nReturn `{ skip: cachedResponse }` to return a pre-built response without executing the provider call. The retry and failover layers do not fire.\n\n```typescript\nhooks: {\n  beforeCall: async (ctx) => {\n    const cached = await cache.get(cacheKey(ctx.messages));\n    if (cached) return { skip: cached };\n  },\n}\n```\n\nFor streaming call types (`stream`, `streamStructured`), `skip` must be an `AsyncGenerator` matching the call's event shape.\n\n### `afterCall` — observability\n\nFires after the call completes (or after generator exhaustion for streams). Errors in `afterCall` are caught, logged as a structured warning, and dropped — they never crash the call that already returned.\n\n```typescript\nhooks: {\n  afterCall: async (ctx) => {\n    logger.info({\n      callType: ctx.request.callType,\n      model: ctx.request.model,\n      latencyMs: ctx.latencyMs,\n      inputTokens: ctx.usage?.inputTokens,\n      outputTokens: ctx.usage?.outputTokens,\n      error: ctx.error?.message,\n    });\n  },\n}\n```\n\n**`ctx.usage` (v1.6.0+):** Populated for all 5 call types. For non-streaming paths (`complete`, `structured`, `withTools`), `ctx.usage` mirrors `ctx.response.usage`. For `stream()`, usage comes from the terminal chunk; for `streamStructured()`, from the `done` event. `ctx.usage` is `undefined` only when the call failed before a response was received.\n\n**`ctx.response`:** `undefined` for `stream()` and `streamStructured()` — no accumulated response object exists for streaming calls. Read token counts from `ctx.usage` instead.\n\n### Hook contract\n\n| Property | Value |\n|---|---|\n| Firing frequency | Once per public method invocation — NOT per retry attempt |\n| `beforeCall` error | Propagates as `LlmError({ kind: 'bad_request' })` |\n| `afterCall` error | Logged as structured warn, dropped — never propagates |\n| `ctx.model` at `beforeCall` | Primary (first) model in config array. May differ from `response.model` if failover fires. |\n| `ctx.usage` (v1.6.0+) | Populated for all 5 call types. `undefined` only on error paths (call failed before a response). |\n| `ctx.response` on streaming | `undefined` for `stream()` and `streamStructured()` — read token counts from `ctx.usage`. |\n\n### When to use hooks vs `instrumentClient`\n\nUse **hooks** when you want request-level interception: PII redaction, system prompt injection, cache short-circuit, custom logging. Hooks are configured directly on `createClient()`.\n\nUse **[`@diabolicallabs/agent-sdk`](../agent-sdk/README.md)** when you want ingestion of `CallRecord` objects to the Agent Spend Dashboard. `instrumentClient()` internally uses the hooks infrastructure since v1.4.0, but the public API (`instrumentClient`, `CallRecord`, `AgentSdkConfig`) stays the SDK's entry point.\n\nBoth compose: `instrumentClient()` merges its `afterCall` handler with any hooks already set on the client config.\n\n## Multimodal content blocks (v4.2.0)\n\n`LlmMessage.content` now accepts `string | LlmContentBlock[]`. String content is backward-compatible across all providers. Array content enables images and PDFs for the providers that support them.\n\n### Provider support table\n\n| Provider | image.base64 | image.url | document.pdfBase64 |\n|---|---|---|---|\n| Anthropic (claude-3.5+ / claude-opus-4 / claude-sonnet-4 / claude-haiku-4-5+) | Yes | Yes | Yes |\n| Anthropic claude-haiku-3 | No | No | No |\n| OpenAI (gpt-5.5 / gpt-5.5-pro / gpt-5.4 / gpt-5.4-mini / gpt-4.1) | Yes | Yes | Yes |\n| OpenAI o4-mini | Yes (image) | Yes (image) | No |\n| Gemini (all) | Yes | No | Yes |\n| Perplexity (all) | No — deferred | No — deferred | No |\n| DeepSeek (all) | No | No | No |\n\nGemini only accepts images via `inlineData` (base64 bytes). Image URL source is not supported on Gemini — the toolkit throws `LlmError({ kind: 'bad_request' })` before making any SDK call.\n\nUse `getModelCapabilities(provider, model).mediaInput` to check support programmatically before constructing a multimodal message.\n\n### Per-block `mediaResolution` (Gemini, v6.7.0+)\n\n`image`, `document`, and `file` blocks all accept an optional `mediaResolution?: LlmMediaResolution` field — a Gemini-only per-part override of the request-level media-resolution knob. Ignored entirely by Anthropic, OpenAI, DeepSeek, and Perplexity. See [Media resolution (Gemini)](#media-resolution-gemini-v670) for the full semantics, precedence rules, and the `'ultra_high'` image-only caveat.\n\n### Usage example\n\n```typescript\nimport { type LlmContentBlock, type LlmMessage, createClient } from '@diabolicallabs/llm-client';\n\nconst client = createClient({\n  provider: 'anthropic',\n  model: 'claude-sonnet-4-6',\n  apiKey: process.env.ANTHROPIC_API_KEY!,\n});\n\nconst blocks: LlmContentBlock[] = [\n  {\n    type: 'document',\n    source: { type: 'base64', mediaType: 'application/pdf', data: pdfBase64 },\n  },\n  {\n    type: 'image',\n    source: { type: 'base64', mediaType: 'image/jpeg', data: jpegBase64 },\n  },\n  { type: 'text', text: 'Summarize these materials.' },\n];\n\nconst response = await client.complete([\n  { role: 'system', content: 'You are a brand strategist.' },\n  { role: 'user', content: blocks },\n]);\n```\n\n### Known limits (API-enforced, not toolkit-validated)\n\n- Anthropic: max 20 MB per image; PDFs via base64 source (no URL PDFs in v4.2.0).\n- Gemini: max ~50 MB total inline data per request; PDFs up to 1000 pages via `inlineData`.\n- OpenAI: standard Responses API file limits apply.\n\n### Unsupported media behavior\n\nProviders that don't support a block type throw `LlmError({ kind: 'bad_request', retryable: false })` **before any network call**. The error message names the provider and the unsupported block/source type:\n\n```\n[llm-client] Provider 'gemini' does not support image content with source 'url' in LlmMessage.content.\nUse a supported provider/model or convert the attachment to text before calling this provider.\n```\n\n## Token normalization\n\nAll providers return `LlmUsage` in a consistent shape regardless of the underlying API's field names:\n\n```typescript\ninterface LlmUsage {\n  inputTokens: number;\n  outputTokens: number;\n  totalTokens: number;\n  cacheCreationTokens?: number; // Anthropic prompt cache only\n  cacheReadTokens?: number;     // Anthropic prompt cache only\n}\n```\n","readmeFilename":"README.md"}