{"_id":"@avanor/sdk-vercel-ai","_rev":"6-b0cb99510c0d13c39ebff86f9140d6d7","name":"@avanor/sdk-vercel-ai","dist-tags":{"latest":"0.1.3"},"versions":{"0.1.0":{"name":"@avanor/sdk-vercel-ai","version":"0.1.0","keywords":["vercel-ai","ai-sdk","llm","governance","observability","agents"],"license":"SEE LICENSE IN LICENSE","_id":"@avanor/sdk-vercel-ai@0.1.0","maintainers":[{"name":"avanorceo","email":"logan@avanor.ai"}],"dist":{"shasum":"d76ff620d369904948a8bf9852755616b413d809","tarball":"https://registry.npmjs.org/@avanor/sdk-vercel-ai/-/sdk-vercel-ai-0.1.0.tgz","fileCount":10,"integrity":"sha512-XC2VvB8WZ5bjg+xQ7RL05AdSN67G2nieNNARP5EwLn55MtAFpb6Nh8l5KPHB+xIf3m2MwQftUJqcAqhzBs2mig==","signatures":[{"sig":"MEQCIDP4o2M/j60gkhkQu/d3t+Pb5pFjZ0qATooVnkIhb4ekAiAqZdqygde73C1voNiX4K/EojuXDWLmaDxTS1bFRTkiMg==","keyid":"SHA256:DhQ8wR5APBvFHLF/+Tc+AYvPOdTpcIDqOhxsBHRwC7U"}],"unpackedSize":55961},"main":"./dist/index.cjs","type":"module","_from":"file:avanor-sdk-vercel-ai-0.1.0.tgz","types":"./dist/index.d.ts","module":"./dist/index.mjs","engines":{"node":">=20"},"exports":{".":{"types":"./dist/index.d.ts","import":"./dist/index.mjs","require":"./dist/index.cjs"}},"scripts":{"test":"vitest run","build":"tsup","coverage":"vitest run --coverage","typecheck":"tsc --noEmit","test:watch":"vitest"},"_npmUser":{"name":"avanorceo","email":"logan@avanor.ai"},"_resolved":"/tmp/51f963e854f64e90b4d37b1ccd1adf21/avanor-sdk-vercel-ai-0.1.0.tgz","_integrity":"sha512-XC2VvB8WZ5bjg+xQ7RL05AdSN67G2nieNNARP5EwLn55MtAFpb6Nh8l5KPHB+xIf3m2MwQftUJqcAqhzBs2mig==","deprecated":"depends on @avanor/sdk@0.1.0 which has known bugs — install @avanor/sdk-vercel-ai@^0.1.1","_npmVersion":"10.8.2","description":"Avanor SDK — Vercel AI SDK auto-instrumentation","directories":{},"sideEffects":false,"_nodeVersion":"20.20.2","dependencies":{"@avanor/sdk":"0.1.0"},"avanorIpClass":"background_perpetual_embedded","productBucket":"core","publishConfig":{"access":"public"},"_hasShrinkwrap":false,"devDependencies":{"ai":"^6.0.0","tsup":"^8.3.0","vitest":"^4.0.0","typescript":"^5.8.2","@types/node":"^22.0.0","@opentelemetry/api":"^1.9.1","@vitest/coverage-v8":"^4.0.0","@opentelemetry/sdk-trace-base":"^1.30.0"},"peerDependencies":{"ai":"^4.0.0 || ^5.0.0 || ^6.0.0"},"peerDependenciesMeta":{"ai":{"optional":true}},"_npmOperationalInternal":{"tmp":"tmp/sdk-vercel-ai_0.1.0_1779340490385_0.3413833879824759","host":"s3://npm-registry-packages-npm-production"}},"0.1.1":{"name":"@avanor/sdk-vercel-ai","version":"0.1.1","keywords":["vercel-ai","ai-sdk","llm","governance","observability","agents"],"license":"SEE LICENSE IN LICENSE","_id":"@avanor/sdk-vercel-ai@0.1.1","maintainers":[{"name":"avanorceo","email":"logan@avanor.ai"}],"dist":{"shasum":"ae566585f671502421732fe227a4f851d6b32ea8","tarball":"https://registry.npmjs.org/@avanor/sdk-vercel-ai/-/sdk-vercel-ai-0.1.1.tgz","fileCount":10,"integrity":"sha512-4LSY1A9GQq6jBnnIgEoKCG5bG3rZ23fzqCMfxTAbJh0Z0zXiqsDpaCH33aeAjV7MvzU6S67PkGrqmhHasOygRw==","signatures":[{"sig":"MEYCIQDkZ/dycR2If2NZ8k+RPHbzuc06q0bFpJ88Cy7fb5/t4AIhAPwEkgT7yXdabTdt6dXSs+EeVjPWPayRYMat0tfnW1uM","keyid":"SHA256:DhQ8wR5APBvFHLF/+Tc+AYvPOdTpcIDqOhxsBHRwC7U"}],"unpackedSize":58190},"main":"./dist/index.cjs","type":"module","_from":"file:avanor-sdk-vercel-ai-0.1.1.tgz","types":"./dist/index.d.ts","module":"./dist/index.mjs","engines":{"node":">=20"},"exports":{".":{"types":"./dist/index.d.ts","import":"./dist/index.mjs","require":"./dist/index.cjs"}},"scripts":{"test":"vitest run","build":"tsup","coverage":"vitest run --coverage","typecheck":"tsc --noEmit","test:watch":"vitest"},"_npmUser":{"name":"avanorceo","email":"logan@avanor.ai"},"_resolved":"/tmp/11407038aaa387f24c9ea837f0f433c6/avanor-sdk-vercel-ai-0.1.1.tgz","_integrity":"sha512-4LSY1A9GQq6jBnnIgEoKCG5bG3rZ23fzqCMfxTAbJh0Z0zXiqsDpaCH33aeAjV7MvzU6S67PkGrqmhHasOygRw==","deprecated":"depends on @avanor/sdk@0.1.1 — install @avanor/sdk-vercel-ai@^0.1.2","_npmVersion":"10.8.2","description":"Avanor SDK — Vercel AI SDK auto-instrumentation","directories":{},"sideEffects":false,"_nodeVersion":"20.20.2","dependencies":{"@avanor/sdk":"0.1.1"},"avanorIpClass":"background_perpetual_embedded","productBucket":"core","publishConfig":{"access":"public"},"_hasShrinkwrap":false,"devDependencies":{"ai":"^6.0.0","tsup":"^8.3.0","vitest":"^4.0.0","typescript":"^5.8.2","@types/node":"^22.0.0","@opentelemetry/api":"^1.9.1","@vitest/coverage-v8":"^4.0.0","@opentelemetry/sdk-trace-base":"^1.30.0"},"peerDependencies":{"ai":"^4.0.0 || ^5.0.0 || ^6.0.0"},"peerDependenciesMeta":{"ai":{"optional":true}},"_npmOperationalInternal":{"tmp":"tmp/sdk-vercel-ai_0.1.1_1779344275069_0.9866928002921966","host":"s3://npm-registry-packages-npm-production"}},"0.1.2":{"name":"@avanor/sdk-vercel-ai","version":"0.1.2","keywords":["vercel-ai","ai-sdk","llm","governance","observability","agents"],"license":"SEE LICENSE IN LICENSE","_id":"@avanor/sdk-vercel-ai@0.1.2","maintainers":[{"name":"avanorceo","email":"logan@avanor.ai"}],"dist":{"shasum":"9883f32bf73582b234e938060e8603e8177e1648","tarball":"https://registry.npmjs.org/@avanor/sdk-vercel-ai/-/sdk-vercel-ai-0.1.2.tgz","fileCount":10,"integrity":"sha512-S394UF2MxA/H/VhDAg7DH/gO50mIpHKGw5OxQtvyqE1yYNZdm8al+I6tjEH5cQoZ/2CcRYN59r8ILbdVTCNa6g==","signatures":[{"sig":"MEQCIAX1zBo/R1o/HGeAVm4JIcKV9GmQypnjvVpBPamdXUjsAiBeSNfAH9aqeConkDbdBip7K9XArDyHoyGnxLWCCuVdNQ==","keyid":"SHA256:DhQ8wR5APBvFHLF/+Tc+AYvPOdTpcIDqOhxsBHRwC7U"}],"unpackedSize":58302},"main":"./dist/index.cjs","type":"module","_from":"file:avanor-sdk-vercel-ai-0.1.2.tgz","types":"./dist/index.d.ts","module":"./dist/index.mjs","engines":{"node":">=20"},"exports":{".":{"types":"./dist/index.d.ts","import":"./dist/index.mjs","require":"./dist/index.cjs"}},"scripts":{"test":"vitest run","build":"tsup","coverage":"vitest run --coverage","typecheck":"tsc --noEmit","test:watch":"vitest"},"_npmUser":{"name":"avanorceo","email":"logan@avanor.ai"},"_resolved":"/tmp/989f2260b84f2d8417afb14cfc31bf02/avanor-sdk-vercel-ai-0.1.2.tgz","_integrity":"sha512-S394UF2MxA/H/VhDAg7DH/gO50mIpHKGw5OxQtvyqE1yYNZdm8al+I6tjEH5cQoZ/2CcRYN59r8ILbdVTCNa6g==","_npmVersion":"10.8.2","description":"Avanor SDK — Vercel AI SDK auto-instrumentation","directories":{},"sideEffects":false,"_nodeVersion":"20.20.2","dependencies":{"@avanor/sdk":"0.1.2"},"avanorIpClass":"background_perpetual_embedded","productBucket":"core","publishConfig":{"access":"public"},"_hasShrinkwrap":false,"devDependencies":{"ai":"^6.0.0","tsup":"^8.3.0","vitest":"^4.0.0","typescript":"^5.8.2","@types/node":"^22.0.0","@opentelemetry/api":"^1.9.1","@vitest/coverage-v8":"^4.0.0","@opentelemetry/sdk-trace-base":"^1.30.0"},"peerDependencies":{"ai":"^4.0.0 || ^5.0.0 || ^6.0.0"},"peerDependenciesMeta":{"ai":{"optional":true}},"_npmOperationalInternal":{"tmp":"tmp/sdk-vercel-ai_0.1.2_1779375988543_0.08517197484584949","host":"s3://npm-registry-packages-npm-production"}},"0.1.3":{"name":"@avanor/sdk-vercel-ai","version":"0.1.3","description":"Avanor SDK — Vercel AI SDK auto-instrumentation","type":"module","main":"./dist/index.cjs","module":"./dist/index.mjs","types":"./dist/index.d.ts","exports":{".":{"types":"./dist/index.d.ts","import":"./dist/index.mjs","require":"./dist/index.cjs"}},"engines":{"node":">=20"},"license":"SEE LICENSE IN LICENSE","avanorIpClass":"background_perpetual_embedded","productBucket":"core","publishConfig":{"access":"public"},"sideEffects":false,"dependencies":{"@avanor/sdk":"0.3.0"},"peerDependencies":{"ai":"^4.0.0 || ^5.0.0 || ^6.0.0"},"peerDependenciesMeta":{"ai":{"optional":true}},"devDependencies":{"@opentelemetry/api":"^1.9.1","@opentelemetry/sdk-trace-base":"^1.30.0","@types/node":"^22.0.0","@vitest/coverage-v8":"^4.0.0","ai":"^6.0.0","tsup":"^8.3.0","typescript":"^5.8.2","vitest":"^4.0.0"},"keywords":["vercel-ai","ai-sdk","llm","governance","observability","agents"],"scripts":{"build":"tsup","test":"vitest run","test:watch":"vitest","coverage":"vitest run --coverage","typecheck":"tsc --noEmit"},"_id":"@avanor/sdk-vercel-ai@0.1.3","_integrity":"sha512-Af1dpK6wxrQPTYL4zwrkaDKCxuekHw2fM0HdSdeMnKxg0dimC2DFLAWwpOqr/3MkTa5L43VMcnXOWrE4EDqfWA==","_resolved":"/tmp/b3f226decc2f0d9f7360725855cd6e8b/avanor-sdk-vercel-ai-0.1.3.tgz","_from":"file:avanor-sdk-vercel-ai-0.1.3.tgz","_nodeVersion":"20.20.2","_npmVersion":"10.8.2","dist":{"integrity":"sha512-Af1dpK6wxrQPTYL4zwrkaDKCxuekHw2fM0HdSdeMnKxg0dimC2DFLAWwpOqr/3MkTa5L43VMcnXOWrE4EDqfWA==","shasum":"ec00bdefc0bc81836e9c3b2a369452e22620309f","tarball":"https://registry.npmjs.org/@avanor/sdk-vercel-ai/-/sdk-vercel-ai-0.1.3.tgz","fileCount":10,"unpackedSize":119757,"signatures":[{"keyid":"SHA256:DhQ8wR5APBvFHLF/+Tc+AYvPOdTpcIDqOhxsBHRwC7U","sig":"MEYCIQCekkpd4BhTt6w9s3ySAZIAzhgZitYQHpY5aGXzOWJb2gIhAI9dhbukvMpTzrl5yv0QUD6vCLpt77ZAYq8ytR3KBaQ2"}]},"_npmUser":{"name":"avanorceo","email":"logan@avanor.ai"},"directories":{},"maintainers":[{"name":"avanorceo","email":"logan@avanor.ai"}],"_npmOperationalInternal":{"host":"s3://npm-registry-packages-npm-production","tmp":"tmp/sdk-vercel-ai_0.1.3_1785614254194_0.4964021598017081"},"_hasShrinkwrap":false}},"time":{"created":"2026-05-21T05:14:50.235Z","modified":"2026-08-01T19:57:34.486Z","0.1.0":"2026-05-21T05:14:50.529Z","0.1.1":"2026-05-21T06:17:55.214Z","0.1.2":"2026-05-21T15:06:28.684Z","0.1.3":"2026-08-01T19:57:34.341Z"},"license":"SEE LICENSE IN LICENSE","keywords":["vercel-ai","ai-sdk","llm","governance","observability","agents"],"description":"Avanor SDK — Vercel AI SDK auto-instrumentation","maintainers":[{"name":"avanorceo","email":"logan@avanor.ai"}],"readme":"# @avanor/sdk-vercel-ai\n\n> Avanor SDK. Vercel AI SDK auto-instrumentation.\n\nWraps Vercel AI SDK's `generateText`, `streamText`, and `generateObject` with\n`llm.call` spans carrying OTel GenAI semconv attributes, and reports AI\ndiscovery for the call shapes where it can do so honestly.\n\n## Install\n\n```bash\nnpm install @avanor/sdk @avanor/sdk-vercel-ai\n```\n\nAdd `ai` to your dependencies if it isn't already.\n\n## Quickstart\n\n```ts\nimport { Avanor } from '@avanor/sdk';\nimport { instrumentVercelAI } from '@avanor/sdk-vercel-ai';\n\nAvanor.init({\n  apiKey: process.env.AVANOR_API_KEY!,\n  environment: process.env.NODE_ENV ?? 'dev',\n  service: 'broker-portal',\n});\n\n// Drop-in replacement for the bare `ai` functions:\nconst { generateText, streamText, generateObject } = instrumentVercelAI();\n\nconst result = await generateText({\n  model: 'anthropic/claude-haiku-4.5', // a gateway model id\n  prompt: 'Hi',\n});\n```\n\n## What this adapter fills\n\nTwo different mechanisms, feeding different pages on different timetables. One\ndoes not imply the other.\n\n| Mechanism | Which calls | Where it lands |\n|---|---|---|\n| the `llm.call` span this adapter opens around every wrapped call | all three of `generateText`, `streamText`, `generateObject`, in every model shape | an agent event, which graduates into the **Agents** roster on a 30-minute reconcile schedule, with governance off |\n| a discovery report this adapter sends after the call completes | `generateText` and `generateObject` only, and only when `model` is a gateway-form **string** | **Inventory**, directly, and the same Agents roster on the same schedule |\n\nSo a `streamText`-only app will show up on Agents and stay absent from\nInventory. That is the code behaving as designed, not a broken install.\n\nNeither mechanism fills **Activity** or the **Audit Log**. Those come from your\nown `allow()` / `guard()` and `attest()` calls, which this adapter does not make\nfor you. Activity additionally needs the agent switched to governed before\n`allow()` records anything. See\n[`@avanor/sdk`'s README](https://www.npmjs.com/package/@avanor/sdk) for the full\npath per page.\n\n### Which model shape reports discovery\n\n| `model` you pass | Discovery reported? |\n|---|---|\n| `'anthropic/claude-haiku-4.5'` (gateway string) | **Yes.** The namespace before the slash is a value your own source code declared, so reporting it invents nothing. |\n| `'gpt-4o'` (bare string) | No. There is no namespace in the input, so naming a provider would mean the adapter supplying a fact from nowhere. |\n| `openai('gpt-4o')` (provider instance) | No. The object carries the provider package's own model id, not a caller-declared namespace. |\n\nIf you pass provider instances, this adapter alone will not fill Inventory for\nthem. They are covered **only if you also install the auto rail**\n(`node --import @avanor/sdk/auto`), whose network host matcher recognises\n`api.openai.com` alongside eleven other provider host rules, several of them\nwildcards covering more than one host. Installing this adapter does\nnot install that rail, and vice versa. See the coverage matrix in\n[`@avanor/sdk`'s README](https://www.npmjs.com/package/@avanor/sdk) for which\nhosts are on the list and what each producer does and does not see.\n\n**What the reported `provider` is, and is not.** It is the namespace your model\nid declared. It is not a guaranteed identification of the vendor that served the\ninference: `'meta/llama-3.3-70b'` reports `meta`, the creator of the weights,\nwhile the gateway may route that call to Bedrock, Groq, or anywhere else. The\nserving provider is only reachable through an async gateway lookup that cannot\nbe made from inside your synchronous model call. Treat the field as \"which model\nfamily this feature asked for\", not as \"which vendor we have a data-processing\nrelationship with\".\n\n### Why this exists\n\nA customer calling a model gateway matches neither of the auto rail's automatic\nmechanisms: no vendor library is patched, and no allowlisted provider host is\ncontacted. Their Inventory stays empty while their Agents page shows live\ngoverned agents. This adapter sits directly on the model call and already holds\nthe provider namespace, the model, and the token counts, so it can report them.\n\nOne thing that is not automatic but does see gateway calls: if you have turned on\nthe AI SDK's own `experimental_telemetry` and you run the auto rail, those spans\nland in Avanor's tracer provider and its span consumer picks the call up. That is\nan opt-in you make in your own code. If it applies to you, read the next section\nbefore installing this adapter as well.\n\n### Do not assume the rails deduplicate\n\nIf you run **both** `node --import @avanor/sdk/auto` and this adapter in the same\nprocess, one AI feature can produce **two** Inventory rows. The two rails resolve\nfeature identity differently (different call-site precedence, this adapter sends\nan empty route where the auto rail sends the real one, and the auto rail applies\na dev-mode call-site bypass this adapter does not). The rows stay\ndistinguishable on the wire via `avanor.discovery.source` (`explicit` here,\na detection-mechanism value there), but nothing merges them at write time. If you\nneed exactly one row per feature today, run one rail.\n\n## Multi-tenant: pass the client explicitly\n\n`instrumentVercelAI()` with no argument resolves its client from the module-level\nsingleton that only `Avanor.init()` populates. If your process builds clients with\n`Avanor.createClient()` per tenant instead, that singleton is never populated, and\nthe adapter silently returns the raw, uninstrumented `ai` functions: no spans, no\ndiscovery, no error, in every tenant.\n\nPass the client:\n\n```ts\nconst tenantClient = Avanor.createClient({ apiKey, environment, service });\nconst { generateText } = instrumentVercelAI({ client: tenantClient });\n```\n\nThere is no request-scoped mechanism today, so the client has to travel from\nwhere you construct it to where you make the model call, through your own\nplumbing. Build the wrapper at the narrowest scope that is guaranteed to be\nsingle-tenant, not at module scope. Do not work around this by registering one\ntenant's client as a process-wide default: that attributes every call to\nwhichever tenant loaded first.\n\n## Attributes captured per call\n\n| Attribute | Value |\n|---|---|\n| `gen_ai.provider.name` | `'vercel-ai'` |\n| `gen_ai.operation.name` | `'generateText'`, `'streamText'`, `'generateObject'` |\n| `gen_ai.request.model` | The model spec (model id when extractable) |\n| `gen_ai.usage.input_tokens` | From the result's `usage` (non-stream paths) |\n| `gen_ai.usage.output_tokens` | From the result's `usage` (non-stream paths) |\n\n`gen_ai.provider.name` names the **integration**, not the model vendor, and it is\na shipped field on rows you already have. The discovery report carries the model\nid's namespace separately. Both are correct; they answer different questions.\n\n## Streaming limitations (v0)\n\nFor `streamText`, the span closes when the wrapped function returns the\nstream handle, not when the stream completes. The wrapped result is still the\nexact Vercel AI SDK return value, so you can `await result.text`,\n`await result.usage`, etc., as normal.\n\nToken-usage attributes are **not** captured for `streamText` in v0. The span\ncarries provider/operation/model attributes only. Full streaming-completion\ncapture (token usage, finish reason, and so on) lands in v0.5.\n\n`streamText` also reports **no discovery**. There is no completion hook, so the\nonly row it could emit would carry no token counts and an end time for a call\nthat had not ended. A fabricated row is worse than a missing one in a compliance\nsurface, so nothing is emitted until the v0.5 completion hook exists.\n\n## Other known gaps\n\n### Two build shapes still cannot load the optional `ai` peer, and where they cannot your model call throws\n\nThe most severe item on this page, and the only one that makes your own code fail\nrather than merely reporting less. `0.1.3` repaired the loader for every shape it\ncan reach. Two shapes it cannot reach are below. Both were measured after the\nfix, and both fail on every version of this package, including the one you are\nreading this from.\n\n- **Emitting an ES module from your bundler** (`output.module: true` with\n  `experiments.outputModule`), on an otherwise-working config. Internal cause:\n  `Dynamic require of \"ai\" is not supported`. Both loader branches need a\n  `require` your bundler has removed, so no branch is left that can succeed.\n- **Relocating the emitted bundle outside the directory tree that holds\n  `node_modules/ai`.** The same artifact that worked before the move fails after\n  it. Internal cause: `Cannot find module 'ai'`, because the load resolves\n  relative to the OUTPUT bundle's location rather than to your source. Next.js\n  `output: 'standalone'` and its file tracing relocate output in exactly that\n  way.\n\nIn both, `instrumentVercelAI()` logs that `ai` is not installed and returns\nwrappers that throw on call:\n\n```\n@avanor/sdk-vercel-ai: `ai` package not installed. Run `npm install ai`\n(or `pnpm add ai`) to use instrumentVercelAI().\n```\n\n**That message is wrong when you already have `ai` installed**, and it sends the\ndebugging in the wrong direction. The real cause is the load path, not a missing\npackage.\n\n**Those two lines are the only thing you will see.** The underlying loader error\nis caught and discarded by `loadAi()`, which latches a flag and returns\n`undefined`, so the internal causes named anywhere on this page\n(`Dynamic require of \"ai\" is not supported`, `Cannot find module 'ai'`) will not\nappear in your logs. Verified: a consumer run against the built dist with `ai`\ngenuinely installed emitted neither string. Do not grep for them to decide\nwhether this applies to you. Grep for `` `ai` package not installed ``.\n\n**What you can do.** Keep this package out of the bundle: add\n`@avanor/sdk-vercel-ai` itself to your bundler's `externals`, or consume the\nCommonJS entry. Neither shape above is something this package can observe or\nresolve from inside a bundle, so externalizing it is the answer for both. Adding\n**`ai`** to `externals` does nothing, because a dynamic `require` creates no\nbundler dependency for that entry to match. Next.js externalizes `node_modules`\npackages in its server build by default, which would put you in the externalized\ncase, but that is read off Next.js's documented default and has not been\nconfirmed against a real app.\n\n**Turbopack has been tested by nobody**, in either direction, before `0.1.3` or\nafter.\n\n`0.1.3` also introduces one new build-time warning. A bundler that parses\n`dist/index.mjs` now emits `module.createRequire failed parsing argument.` where\nit previously emitted nothing. The peer still loads. The warning is the bundler\nreporting that it could not statically analyse the call.\n\n#### What `0.1.3` repaired, and what `<= 0.1.2` still does\n\nThese tables are kept rather than deleted because they are not history for\neveryone: **if you are pinned to `0.1.2` or earlier, they describe the package\nyou have.** Every \"on `<= 0.1.2`\" column below is a measurement of `0.1.0`,\n`0.1.1` and `0.1.2`, all of which carry the identical pre-fix loader. The gap has\nbeen present since `a2f8ef6d` (2026-05-20); `0.1.3` is the first published\nversion that closes it.\n\nOn `<= 0.1.2` this package loaded its optional `ai` peer through a bare\n`require()` call that whole classes of ordinary install could not run. It was not\n\"ESM is broken\": some ESM shapes worked and some CommonJS shapes did not. What\ndecided the outcome was **which of this package's two built files your toolchain\nparsed**, `dist/index.mjs` or `dist/index.cjs`, and not which module system your\nown app was written in.\n\nUnbundled, plain Node:\n\n| how you load the adapter | on `<= 0.1.2` | on `0.1.3` |\n|---|---|---|\n| `require('@avanor/sdk-vercel-ai')`, which resolves `dist/index.cjs` | **works.** Verified end to end against the real `ai` package. | works |\n| `import '@avanor/sdk-vercel-ai'`, which resolves `dist/index.mjs` | **fails.** Internal cause: `Dynamic require of \"ai\" is not supported`. | works |\n\nBundled, measured on webpack 5 with `target: 'node'` across eight configurations:\n\n| what the bundler parses | on `<= 0.1.2` | on `0.1.3` |\n|---|---|---|\n| `dist/index.mjs` | **works.** | works |\n| `dist/index.cjs` | **fails.** Internal cause: `Cannot find module 'ai'`. Unlike the runtime error, the accompanying `Critical dependency: require function is used in a way in which dependencies cannot be statically extracted` warning IS visible, at BUILD time. | works, and that `Critical dependency` warning is still emitted |\n\nNote that on `<= 0.1.2` bundling **inverts** the unbundled answer: unbundled it\nis the CommonJS file that works, bundled it is the ESM file. Those eight\nconfigurations were 2 files x 2 modes x 2 `externals` settings, and across them\nthe only variable that moved the outcome was which of the two files webpack\nparsed: not the mode, and not whether `ai` was listed in `externals`. Two further\nindependences were observed separately rather than inside that matrix, so treat\nthem as weaker evidence: your own app's module system, and the webpack version.\n\n`0.1.3`'s loader tries the ambient `require` first and falls back to\n`createRequire` when that throws, which covers both built files instead of one\neach. Measured across twelve configurations against the real `ai` package, both\nwith the peer installed and with it absent: four in plain Node with no bundler\ninvolved, and eight across four webpack configurations (webpack 5.109.2,\n`target: 'node'`). **Optionality is preserved.** With `ai` genuinely absent,\nevery one of those shapes still behaves the way an optional peer must: the module\nloads, and only calling the wrapper throws. The load failure stays caught, not\nfatal at import.\n\nWhat `0.1.3` does **not** repair is the two shapes at the top of this section.\nThey fail on `<= 0.1.2` and on `0.1.3` alike.\n\n### Smaller gaps\n\n- **A model call that throws reports no discovery.** The report is emitted only\n  after a successful call, so a feature whose calls always fail never appears in\n  Inventory.\n- **Object-form models report no discovery.** The model object does expose a\n  `provider` field, but its values are sub-provider-qualified (`'openai.chat'`,\n  `'anthropic.messages'`) and using them raw would fragment one vendor across\n  several Inventory rows. Wiring it needs a canonicalisation decision first.\n\n## Zero false-positive guarantee\n\nScoped, deliberately, to the case where this package successfully loaded `ai`.\nWhere it did, the guarantee is unconditional: each wrapped function returns the\nexact same value as the underlying `ai` function. No wrapping, no transformation,\nno extra fields. The discovery report is fire-and-forget and fully isolated, so\nnothing in it, including a customer-supplied client whose `reportDiscovery`\nthrows, can change what your `generateText` returns or throws. That isolation is\na property of the discovery report specifically, which sits behind its own\ntry/catch. It is not claimed for the span path: `startActiveSpan`,\n`setAttribute`, `setStatus` and the `end()` in the `finally` are not individually\nwrapped, so a throwing tracer would propagate.\n\nWhere it did NOT load `ai`, there is no wrapped `ai` function to return a value\nfrom. `instrumentVercelAI()` returns wrappers that throw on call, so your model\ncall fails rather than returning anything. That is the peer-load gap documented\nabove, not a property of the wrapping, and it is the only way in which installing\nthis package changes the outcome of your own code. On `0.1.3` two build shapes\nreach it; on `<= 0.1.2` many more do. Establish which case you are in before\ntreating the guarantee as covering you.\n\n## Docs\n\nThere is no Vercel AI recipe page yet. This adapter is documented on the\nauto-discovery page, which covers which surfaces each install fills and which it\ndoes not: <https://www.avanor.ai/docs/sdk/auto-discovery>\n\nThe exported types for the whole SDK family are at\n<https://www.avanor.ai/docs/sdk/api-reference>, and the core install is at\n<https://www.avanor.ai/docs/sdk/quickstart>.\n\n## License\n\nAvanor Source License v1 (BSL-modeled, 4-year Apache 2.0 sunset). See\n[LICENSE](./LICENSE).\n","readmeFilename":"README.md"}