{"_id":"@axium-lab/helix","_rev":"5-cbf00b3aa3a8c32c8fbf3f1ddcc1186d","name":"@axium-lab/helix","dist-tags":{"latest":"0.3.2"},"versions":{"0.2.0":{"name":"@axium-lab/helix","version":"0.2.0","author":{"name":"Axium Lab"},"license":"MIT","_id":"@axium-lab/helix@0.2.0","maintainers":[{"name":"luisperis.com","email":"luis.peris@kaira.es"}],"homepage":"https://github.com/axium-lab/helix#readme","bugs":{"url":"https://github.com/axium-lab/helix/issues"},"dist":{"shasum":"b30e03b6a8f4eacbe16998a177ecbdcd299e0087","tarball":"https://registry.npmjs.org/@axium-lab/helix/-/helix-0.2.0.tgz","fileCount":26,"integrity":"sha512-HWNHvOG5T0yCE0ic8oEbw91nydcDL+tNLeBIfO+rbFdgAQ+yuMx8jCPKbpF6/uR2qGlnfxKlqDO26FGEYQwRyg==","signatures":[{"sig":"MEQCIFngT+g5ijWB/G6DJGHSBYxAl7HFkbMtQLPMg4Sw/ZyRAiA9zQKEo9TSyJ2VrdAatGykVHSUbkrI4RZBbGneaVYzRQ==","keyid":"SHA256:DhQ8wR5APBvFHLF/+Tc+AYvPOdTpcIDqOhxsBHRwC7U"}],"unpackedSize":3031988},"main":"./dist/cjs/index.cjs","type":"module","types":"./dist/esm/index.d.ts","module":"./dist/esm/index.js","engines":{"node":">=22"},"exports":{".":{"types":"./dist/esm/index.d.ts","import":"./dist/esm/index.js","require":"./dist/cjs/index.cjs"},"./core":{"types":"./dist/esm/core/index.d.ts","import":"./dist/esm/core/index.js","require":"./dist/cjs/core/index.cjs"},"./dialects":{"types":"./dist/esm/dialects/index.d.ts","import":"./dist/esm/dialects/index.js","require":"./dist/cjs/dialects/index.cjs"},"./transports":{"types":"./dist/esm/transports/index.d.ts","import":"./dist/esm/transports/index.js","require":"./dist/cjs/transports/index.cjs"}},"gitHead":"a3987f6c073dd9211cd6a0a911b434a0babcb048","scripts":{"test":"vitest run","build":"tsup && node scripts/check-dist.mjs","clean":"rm -rf dist","test:mock":"vitest run tests/mock","test:unit":"vitest run tests/unit","typecheck":"tsc --noEmit","test:watch":"vitest","test:manual":"HELIX_MANUAL=1 vitest run","test:integration":"vitest run tests/integration"},"_npmUser":{"name":"luisperis.com","email":"luis.peris@kaira.es"},"repository":{"url":"git+https://github.com/axium-lab/helix.git","type":"git"},"_npmVersion":"11.9.0","description":"Dialect translation across LLM providers (OpenAI, Anthropic, Gemini) plus a provider-agnostic SDK","directories":{},"_nodeVersion":"24.14.0","publishConfig":{"access":"public"},"_hasShrinkwrap":false,"devDependencies":{"tsup":"^8.5.1","openai":"^6.0.0","vitest":"^3.2.0","typescript":"^5.9.3","@types/node":"^22.0.0","@google/genai":"^2.6.0","@anthropic-ai/sdk":"^0.68.0"},"_npmOperationalInternal":{"tmp":"tmp/helix_0.2.0_1786366760093_0.23294502856360744","host":"s3://npm-registry-packages-npm-production"}},"0.2.1":{"name":"@axium-lab/helix","version":"0.2.1","author":{"name":"Axium Lab"},"license":"MIT","_id":"@axium-lab/helix@0.2.1","maintainers":[{"name":"luisperis.com","email":"luis.peris@kaira.es"}],"homepage":"https://github.com/axium-lab/helix#readme","bugs":{"url":"https://github.com/axium-lab/helix/issues"},"dist":{"shasum":"514e14976d5bb51120eb15bf7adfb8fc1afa28b8","tarball":"https://registry.npmjs.org/@axium-lab/helix/-/helix-0.2.1.tgz","fileCount":26,"integrity":"sha512-8a+3OeR4oCR24Or1B1Q+/OnjJ+89UMSHE+YlHdrCTcHU3xQWvgYLz/7hxEK7Y1cKpYBEOUq1D22f6+HZ7GX8Qw==","signatures":[{"sig":"MEUCIQCERenCoRT6fRxuoHSryxhK6UnLqQIcRD6Mlx713qyjdgIgURKtmq+TnD7vyEzRg7Nkj0VyPtd6TaUSINypako/mBI=","keyid":"SHA256:DhQ8wR5APBvFHLF/+Tc+AYvPOdTpcIDqOhxsBHRwC7U"}],"unpackedSize":3037234},"main":"./dist/cjs/index.cjs","type":"module","types":"./dist/esm/index.d.ts","module":"./dist/esm/index.js","engines":{"node":">=22"},"exports":{".":{"types":"./dist/esm/index.d.ts","import":"./dist/esm/index.js","require":"./dist/cjs/index.cjs"},"./core":{"types":"./dist/esm/core/index.d.ts","import":"./dist/esm/core/index.js","require":"./dist/cjs/core/index.cjs"},"./dialects":{"types":"./dist/esm/dialects/index.d.ts","import":"./dist/esm/dialects/index.js","require":"./dist/cjs/dialects/index.cjs"},"./transports":{"types":"./dist/esm/transports/index.d.ts","import":"./dist/esm/transports/index.js","require":"./dist/cjs/transports/index.cjs"}},"gitHead":"6c956ef9156a289e97acde6cdaa3b4775ebb42ea","scripts":{"test":"vitest run","build":"tsup && node scripts/check-dist.mjs","clean":"rm -rf dist","test:mock":"vitest run tests/mock","test:unit":"vitest run tests/unit","typecheck":"tsc --noEmit","test:watch":"vitest","test:manual":"HELIX_MANUAL=1 vitest run","test:integration":"vitest run tests/integration"},"_npmUser":{"name":"luisperis.com","email":"luis.peris@kaira.es"},"repository":{"url":"git+https://github.com/axium-lab/helix.git","type":"git"},"_npmVersion":"11.9.0","description":"Dialect translation across LLM providers (OpenAI, Anthropic, Gemini) plus a provider-agnostic SDK","directories":{},"_nodeVersion":"24.14.0","publishConfig":{"access":"public"},"_hasShrinkwrap":false,"devDependencies":{"tsup":"^8.5.1","openai":"^6.0.0","vitest":"^3.2.0","typescript":"^5.9.3","@types/node":"^22.0.0","@google/genai":"^2.6.0","@anthropic-ai/sdk":"^0.68.0"},"_npmOperationalInternal":{"tmp":"tmp/helix_0.2.1_1786701431983_0.38312623703905224","host":"s3://npm-registry-packages-npm-production"}},"0.3.1":{"name":"@axium-lab/helix","version":"0.3.1","author":{"name":"Axium Lab"},"license":"MIT","_id":"@axium-lab/helix@0.3.1","maintainers":[{"name":"luisperis.com","email":"luis.peris@kaira.es"}],"homepage":"https://github.com/axium-lab/helix#readme","bugs":{"url":"https://github.com/axium-lab/helix/issues"},"dist":{"shasum":"40e49724da46c3914ba5be09504f768489d9cabd","tarball":"https://registry.npmjs.org/@axium-lab/helix/-/helix-0.3.1.tgz","fileCount":26,"integrity":"sha512-9j2YfGPYQzDpaZMSt+M5O3fyWRO44UhPpDeexOXw59qSSOO8xHFZcj3FNuC/H41xG8uyWqbF1ifhTzgsuHrciQ==","signatures":[{"sig":"MEUCIEhfJYXJFDxkj5m/17sVkVz2nZdrFTypQlHByWynuLDLAiEA9q7+IxzRUSa/w8uD2VGruDymramDlyOzO+r+ihOvM90=","keyid":"SHA256:DhQ8wR5APBvFHLF/+Tc+AYvPOdTpcIDqOhxsBHRwC7U"}],"unpackedSize":3404908},"main":"./dist/cjs/index.cjs","type":"module","types":"./dist/esm/index.d.ts","module":"./dist/esm/index.js","engines":{"node":">=22"},"exports":{".":{"types":"./dist/esm/index.d.ts","import":"./dist/esm/index.js","require":"./dist/cjs/index.cjs"},"./core":{"types":"./dist/esm/core/index.d.ts","import":"./dist/esm/core/index.js","require":"./dist/cjs/core/index.cjs"},"./dialects":{"types":"./dist/esm/dialects/index.d.ts","import":"./dist/esm/dialects/index.js","require":"./dist/cjs/dialects/index.cjs"},"./transports":{"types":"./dist/esm/transports/index.d.ts","import":"./dist/esm/transports/index.js","require":"./dist/cjs/transports/index.cjs"}},"gitHead":"70228a7a64091765f9184dc0c423cdfada2c32d4","scripts":{"test":"vitest run","build":"tsup && node scripts/check-dist.mjs","clean":"rm -rf dist","test:mock":"vitest run tests/mock","test:unit":"vitest run tests/unit","typecheck":"tsc --noEmit","test:watch":"vitest","test:manual":"HELIX_MANUAL=1 vitest run","test:integration":"vitest run tests/integration"},"_npmUser":{"name":"luisperis.com","email":"luis.peris@kaira.es"},"repository":{"url":"git+https://github.com/axium-lab/helix.git","type":"git"},"_npmVersion":"11.9.0","description":"Dialect translation across LLM providers (OpenAI, Anthropic, Gemini) plus a provider-agnostic SDK","directories":{},"_nodeVersion":"24.14.0","publishConfig":{"access":"public"},"_hasShrinkwrap":false,"devDependencies":{"tsup":"^8.5.1","openai":"^6.0.0","vitest":"^3.2.0","typescript":"^5.9.3","@types/node":"^22.0.0","@google/genai":"^2.6.0","@anthropic-ai/sdk":"^0.68.0"},"optionalDependencies":{"@google-cloud/storage":"^8.0.0"},"_npmOperationalInternal":{"tmp":"tmp/helix_0.3.1_1787140469206_0.5292247767020011","host":"s3://npm-registry-packages-npm-production"}},"0.3.2":{"name":"@axium-lab/helix","version":"0.3.2","author":{"name":"Axium Lab"},"license":"MIT","_id":"@axium-lab/helix@0.3.2","maintainers":[{"name":"luisperis.com","email":"luis.peris@kaira.es"}],"homepage":"https://github.com/axium-lab/helix#readme","bugs":{"url":"https://github.com/axium-lab/helix/issues"},"dist":{"shasum":"b0c8b87352bb030135e5b3a558a2ef4adda2bea5","tarball":"https://registry.npmjs.org/@axium-lab/helix/-/helix-0.3.2.tgz","fileCount":26,"integrity":"sha512-8TxYOtCaqJUlVg/OzdVZm+B9MBESQofOxLznbolG/uZUAspRWrVqOw/kmZHUxSvXAg4iSBMAN32rAUr4dWFb+A==","signatures":[{"sig":"MEUCIQDPzZQbC1bDbBhbc+ciny6hPAXo+UPSXHQf4wEs6OUHJwIgSACVcBB80IRv2QFF9nqzZKYw6btWj2R/oV17QERHGjo=","keyid":"SHA256:DhQ8wR5APBvFHLF/+Tc+AYvPOdTpcIDqOhxsBHRwC7U"}],"unpackedSize":3407761},"main":"./dist/cjs/index.cjs","type":"module","types":"./dist/esm/index.d.ts","module":"./dist/esm/index.js","engines":{"node":">=22"},"exports":{".":{"types":"./dist/esm/index.d.ts","import":"./dist/esm/index.js","require":"./dist/cjs/index.cjs"},"./core":{"types":"./dist/esm/core/index.d.ts","import":"./dist/esm/core/index.js","require":"./dist/cjs/core/index.cjs"},"./dialects":{"types":"./dist/esm/dialects/index.d.ts","import":"./dist/esm/dialects/index.js","require":"./dist/cjs/dialects/index.cjs"},"./transports":{"types":"./dist/esm/transports/index.d.ts","import":"./dist/esm/transports/index.js","require":"./dist/cjs/transports/index.cjs"}},"gitHead":"143dab1d2be64a7d3062ce359685865198df8c26","scripts":{"test":"vitest run","build":"tsup && node scripts/check-dist.mjs","clean":"rm -rf dist","test:mock":"vitest run tests/mock","test:unit":"vitest run tests/unit","typecheck":"tsc --noEmit","test:watch":"vitest","test:manual":"HELIX_MANUAL=1 vitest run","test:integration":"vitest run tests/integration"},"_npmUser":{"name":"luisperis.com","email":"luis.peris@kaira.es"},"repository":{"url":"git+https://github.com/axium-lab/helix.git","type":"git"},"_npmVersion":"11.9.0","description":"Dialect translation across LLM providers (OpenAI, Anthropic, Gemini) plus a provider-agnostic SDK","directories":{},"_nodeVersion":"24.14.0","publishConfig":{"access":"public"},"_hasShrinkwrap":false,"devDependencies":{"tsup":"^8.5.1","openai":"^6.0.0","vitest":"^3.2.0","typescript":"^5.9.3","@types/node":"^22.0.0","@google/genai":"^2.6.0","@anthropic-ai/sdk":"^0.68.0"},"optionalDependencies":{"@google-cloud/storage":"^8.0.0"},"_npmOperationalInternal":{"tmp":"tmp/helix_0.3.2_1787825731125_0.9567669133398986","host":"s3://npm-registry-packages-npm-production"}}},"time":{"created":"2026-08-10T12:59:19.938Z","modified":"2026-10-02T08:07:07.218Z","0.2.0":"2026-08-10T12:59:20.282Z","0.2.1":"2026-08-14T09:57:12.164Z","0.3.1":"2026-08-19T11:54:29.402Z","0.3.2":"2026-08-27T10:15:31.295Z"},"bugs":{"url":"https://github.com/axium-lab/helix/issues"},"author":{"name":"Axium Lab"},"license":"MIT","homepage":"https://github.com/axium-lab/helix#readme","repository":{"url":"git+https://github.com/axium-lab/helix.git","type":"git"},"description":"Dialect translation across LLM providers (OpenAI, Anthropic, Gemini) plus a provider-agnostic SDK","maintainers":[{"email":"pedro.losas@fluxaria.com","name":"pedro-losas-pla"},{"email":"luis.peris@kaira.es","name":"luisperis.com"}],"readme":"# Helix\n\nTranslation between LLM wire formats, plus a provider-agnostic SDK.\n\n**A single npm package, with no server and no process of its own.** It gets\nimported. The parent project, **Axium**, is what exposes HTTP.\n\n> **Branch `refactor`.** Complete rewrite of v0.1, which is frozen on `main` as a\n> reference and is neither compiled nor tested. It used to be vendored here under\n> `old_code/`; consult it with `git show main:<path>` instead.\n\n---\n\n## What works, and what does not\n\nThe honest version. Nothing below is aspirational — every ✅ is exercised by the\ntest suite, and most of it against a live server.\n\n### Dialects\n\nA dialect is a wire format Helix can both read and write.\n\n| Dialect | Status | Surfaces |\n|---|---|---|\n| **`openai`** | ✅ complete | `/v1/chat/completions` and `/v1/responses` |\n| **`gemini`** | ✅ complete | `generateContent` / `streamGenerateContent`, and the **Interactions API** |\n| **`anthropic`** | ❌ **not implemented** | — |\n\nGemini's [Interactions API](https://ai.google.dev/gemini-api/docs) — the surface\nGoogle recommends for new work — is opt-in, so existing callers keep the behaviour\nthey have:\n\n```ts\nnew Helix({\n  transport: new GeminiTransport({ apiKey }),\n  encodeOptions: { surface: 'gemini.interactions' },\n});\n```\n\nIt adds stored responses (`helix.responses.get` / `.cancel` / `.delete`,\n`store`, `background`, `previous_response_id`) and `reasoning.effort` maps\ndirectly onto `thinking_level`. Two things to know before switching:\n\n- **It exposes no sampling controls.** `temperature`, `top_p`, `top_k`, `n` and the\n  penalties do not exist on this surface; each one warns when dropped.\n- **Multi-turn tool use needs the whole assistant turn replayed**, reasoning\n  included — the signature it carries is validated server-side. In exchange, the\n  round trip works, which it does not on `generateContent` (see `por-arreglar.md`).\n\nAnthropic is not started. `dialects.anthropic` does not exist and will not\ncompile — the registry is typed as a partial record precisely so that a missing\ndialect is a compile error rather than an `undefined` at runtime.\n\n### Endpoints\n\nAn endpoint is *where* a request goes. Several share one dialect, which is the\npoint of separating the two.\n\n| Transport | Dialect | Generation | Streaming | Models | Files |\n|---|---|---|---|---|---|\n| `OpenAITransport` | `openai` | ✅ | ✅ | ✅ | ✅ |\n| `AzureTransport` | `openai` | ✅ | ✅ | ✅ | ✅ |\n| `OpenAICompatibleTransport` | `openai` | ✅ | ✅ | ⚠️ | ⚠️ |\n| `GeminiTransport` | `gemini` | ✅ | ✅ | ✅ | ✅ |\n| `GeminiEnterpriseTransport` | `gemini` | ✅ | ✅ | ✅ | ⚠️ via Cloud Storage |\n| **Anthropic** | `anthropic` | ❌ **not implemented** | | | |\n| **Bedrock** | `anthropic` | ❌ not planned | | | |\n\n⚠️ **OpenAI-compatible vendors** (Groq, Ollama, OpenRouter, vLLM…) implement the\ngeneration surface reliably and the rest inconsistently. Declare what yours\nsupports and `helix.capabilities` will report it truthfully:\n\n```ts\nnew OpenAICompatibleTransport({\n  baseUrl: 'https://api.groq.com/openai/v1',\n  apiKey,\n  capabilities: { files: false, models: false },\n});\n```\n\n⚠️ **Gemini Enterprise** — the product Google used to call **Vertex AI** — **has\nno Files API.** `GeminiEnterpriseTransport` backs `files.*` with Google Cloud\nStorage when you give it a bucket, and reports `capabilities.files: false` when\nyou do not. Ids are `gs://bucket/object`, which the `gemini` dialect already\naccepts as a `file_id` — so you can also skip uploads entirely and reference an\nobject you put there yourself.\n\nGemini Enterprise authenticates with OAuth rather than a key, in four ways:\n\n```ts\nconst where = { projectId, location: 'us-central1' };\n\n// A service account key. Helix signs the JWT itself — no extra dependency.\nnew GeminiEnterpriseTransport({ ...where, credentials });\n\n// A token you already have.\nnew GeminiEnterpriseTransport({ ...where, accessToken });\n\n// Delegation, for Workload Identity Federation or impersonation.\nnew GeminiEnterpriseTransport({ ...where, getAccessToken });\n\n// Nothing: the GCE/Cloud Run metadata server. How this runs on Google's compute.\nnew GeminiEnterpriseTransport(where);\n```\n\nFiles need `credentials` or ADC specifically: the Storage client mints its own\ntoken and takes a key, so an `accessToken` authenticates the model endpoint but\nnot Storage.\n\n### Operations\n\n| Operation | Status |\n|---|---|\n| `responses.create` | ✅ |\n| `responses.stream` | ✅ decoding and encoding, in both directions |\n| `models.list` / `models.get` | ✅ |\n| `files.create` / `get` / `list` / `delete` | ✅ |\n| `test.connection` | ✅ |\n| `embeddings`, `batches`, `images`, `audio`, `fine-tuning` | ❌ out of scope for v1 |\n\n### Known limitations\n\n- **File uploads are held in memory.** `file` takes a `Uint8Array`; there is no\n  streaming upload. Gemini's own limit for a single-chunk upload is around 20 MB.\n- **Model names are not translated.** Sending an OpenAI request to Gemini produces\n  a Gemini-shaped call for `gpt-4o-mini`. Choosing an equivalent model is a policy\n  decision and belongs to the caller.\n- **`HelixResponse` has no `passthrough`.** Unlike requests, provider extras on a\n  response (`system_fingerprint`, `logprobs`) survive only inside `metadata.raw`.\n\n---\n\n## Install\n\nPublished publicly on npm — no registry configuration and no token needed:\n\n```bash\nnpm install @axium-lab/helix\n```\n\nNode 22 or newer; ESM and CJS builds both ship.\n\n---\n\n## What it is for\n\nTwo use cases from one engine:\n\n1. **Dialect translation.** Convert a request in one provider's format into\n   another's, and the response back. Helix exposes the functions; **Axium** mounts\n   them on HTTP routes so a client only changes its `baseURL`.\n2. **Provider-agnostic SDK.** A facade that also normalises `models` and `files`,\n   which LangChain does not cover.\n\n```ts\nimport { Helix, OpenAITransport } from '@axium-lab/helix';\n\nconst helix = new Helix({ transport: new OpenAITransport({ apiKey }) });\n\nconst res = await helix.responses.create({\n  model: 'gpt-4o-mini',\n  instructions: 'Be concise.',\n  input: [{ role: 'user', content: [{ type: 'input_text', text: 'Hello.' }] }],\n});\n```\n\nSwapping the transport is the only edit needed to talk to a different provider.\n\nFull surface in [`API.md`](./API.md); the design explained in\n[`CONCEPTS.md`](./CONCEPTS.md). Both are also published as a browsable site under\n[`docs/`](./docs) — open `docs/index.html`.\n\n---\n\n## The design principle\n\n**Both use cases are the same engine walked in opposite directions.** Every\ndialect is a module with four functions:\n\n| function | translation (used by Axium) | SDK |\n|---|---|---|\n| `decodeRequest` wire→IR | ✅ | — |\n| `encodeRequest` IR→wire | — | ✅ |\n| `decodeResponse` wire→IR | — | ✅ |\n| `encodeResponse` IR→wire | ✅ | — |\n\nWith a central IR this is **N+M** transformers instead of N×M. And because HTTP\nlives in Axium, all four are **public API**: breaking that contract is a breaking\nchange.\n\nThe axes are kept apart deliberately:\n\n- A **dialect** knows wire formats and never touches the network.\n- A **transport** knows URLs and credentials and never reads a payload.\n\nWhich is why `azure` is not a provider but an endpoint speaking the `openai`\ndialect — and why adding it required **no translation code at all**.\n\nTwo documented exceptions exist, both in transports that must read a body: Azure\nneeds the deployment name from `body.model` for its URL, and Gemini's file upload\nis a two-step resumable exchange. **A third would mean the contract should grow\nmulti-step operations rather than collect exceptions.**\n\n---\n\n## No required runtime dependencies\n\n`package.json` declares no `dependencies`. The provider SDKs are devDependencies\nused through `import type` only, to type foreign wire formats without shipping\nthem — enforced by `verbatimModuleSyntax` and verified at build time by\n`scripts/check-dist.mjs`, which fails the build if any of them reaches the emitted\n`.d.ts`.\n\nThat check matters: a leaked type would turn a devDependency into a peer\ndependency for every consumer, and TypeScript gives no warning about it.\n\n**One `optionalDependency`:** `@google-cloud/storage`, which backs `files.*` on\nGemini Enterprise. It is reached through a dynamic `import()` that only runs when\nyou configure a bucket, and `tsup` marks it external so it is never inlined —\nleaving it out of the bundle entirely rather than shipping 1.9 MB to everyone.\nInstall it if you want files there; otherwise nothing changes for you. Everything\nelse, OAuth signing included, is plain `fetch` and `crypto.subtle`.\n\n---\n\n## Development\n\n```bash\nnpm install\nnpm run typecheck\nnpm test              # everything\nnpm run build         # tsup + the dist guard\n```\n\n### Tests\n\n| Tier | Against | Network | What it validates |\n|---|---|---|---|\n| `test:unit` | fixtures on disk | **no** | dialects, the IR, pure logic |\n| `test:mock` | [llm-mock](https://github.com/axium-lab/llm-mock) | yes | transports, assembly, real wire shapes |\n| `test:integration` | real providers | yes | self-skips without credentials |\n| `test:manual` | real providers | yes | a scratchpad, not a check — **excluded from `npm test` and from CI** |\n\nThe manual tier is a **mode, not a directory in the run**: `HELIX_MANUAL=1` makes\nthe run contain `tests/manual/` and nothing else, and without it those files are\nnot collected at all — so no CI can reach a scratchpad that spends money. A\npositional argument picks one file:\n\n```bash\nnpm run test:manual                          # the whole tier\nnpm run test:manual -- structured-output     # one file\n```\n\nThe unit tier is guarded: **a unit test that reaches the network fails**. Three did\nso by accident during development, and each passed for the wrong reason — an auth\nfailure throws just as convincingly as a missing implementation.\n\n`llm-mock` needs no credentials and costs nothing; it is configured in\n[`.env.test`](./.env.test), committed on purpose. Real provider keys go in\n`.env.test.local`, which is git-ignored.\n\n---\n\n## Why v0.1 is kept\n\nv0.1 is frozen on `main` with 8 ADRs, as a map of provider quirks paid for against\nreal APIs. Several were carried into this rewrite and re-confirmed against a live\nserver:\n\n- Azure lists deployments with `api-version=2023-03-15-preview` **hardcoded**:\n  newer versions return 404 on that endpoint even when valid for inference\n  (ADR-0004).\n- Gemini Files enforces a **fixed 48 h retention**; `purpose` and `expires_after`\n  are accepted and ignored.\n- Gemini Enterprise has no Files API at all, and is fronted by Cloud Storage instead.\n- Gemini Enterprise lists publisher models **globally and only on `v1beta1`** — the\n  project-qualified path 404s, and so does `v1`. The same shape as Azure's pinned\n  api-version above, re-confirmed against a live project on 2026-08-15.\n- Eleven error categories with `httpStatus` fallbacks (502 connection, 504 timeout,\n  500 otherwise) so an error can be forwarded straight to a client (ADR-0006).\n\nConsult it without leaving the branch:\n\n```bash\ngit show main:src/internal/providers/azure/azure.models.ts\n```\n","readmeFilename":"README.md"}