@neondatabase/ai-sdk-provider 0.1.1 → 0.4.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/README.md CHANGED
@@ -1,13 +1,15 @@
1
1
  # @neondatabase/ai-sdk-provider
2
2
 
3
- Community [Vercel AI SDK](https://ai-sdk.dev) provider for the [Neon](https://neon.com) AI Gateway.
3
+ Community [Vercel AI SDK](https://ai-sdk.dev) provider for the [Neon](https://neon.com) AI Gateway. Requires **AI SDK v6** (`ai@^6`).
4
4
 
5
- The Neon AI Gateway is **branch-scoped**: each Neon project branch gets its own gateway host, and a platform token authorizes requests for that branch. This provider routes each model to the best gateway endpoint (Anthropic → native Messages, OpenAI → native Responses incl. **Codex**, everything else → unified OpenAI-compatible MLflow endpoint), so a single `neon('databricks-...')` call reaches the whole `databricks-*` catalog.
5
+ The Neon AI Gateway is **branch-scoped**: each Neon project branch gets its own gateway host, and a platform token authorizes requests for that branch. This provider routes each model to the best gateway endpoint (Anthropic → native Messages, OpenAI → native Responses incl. **Codex**, everything else → unified OpenAI-compatible MLflow endpoint), so a single `neon('claude-...')` call reaches the whole catalog.
6
+
7
+ Model ids use the canonical Neon (unprefixed) form — `claude-sonnet-4-6`, `gpt-5`, `gemini-2-5-flash` — matching the [`neon` provider on models.dev](https://models.dev). The typed catalog mirrors that provider exactly (kept in sync by a scheduled drift check), plus a few extra gateway-served ids that models.dev doesn't list yet (e.g. Codex, Llama, Qwen). Any other id — including the legacy `databricks-` prefixed form (`databricks-claude-sonnet-4-6`) — is still accepted as a plain string, so existing code keeps working.
6
8
 
7
9
  ## Install
8
10
 
9
11
  ```bash
10
- npm install @neondatabase/ai-sdk-provider
12
+ npm install @neondatabase/ai-sdk-provider ai@^6
11
13
  ```
12
14
 
13
15
  ## Configuration
@@ -27,7 +29,7 @@ import { generateText } from "ai";
27
29
 
28
30
  // Reads NEON_AI_GATEWAY_BASE_URL + NEON_AI_GATEWAY_TOKEN from the environment.
29
31
  const { text } = await generateText({
30
- model: neon("databricks-claude-haiku-4-5"), // or 'databricks-gpt-5-3-codex', etc.
32
+ model: neon("claude-haiku-4-5"), // or 'gpt-5-3-codex', etc.
31
33
  prompt: "Summarize Postgres for me.",
32
34
  });
33
35
  ```
@@ -47,10 +49,12 @@ const neon = createNeon({
47
49
 
48
50
  | Model family | Endpoint | Why |
49
51
  | --- | --- | --- |
50
- | Anthropic (`databricks-claude-*`) | native Messages API | streaming structured output + native reasoning |
51
- | OpenAI (`databricks-gpt-*`, `*-codex`) | native Responses API | Codex (native-only), native reasoning, image-gen tool |
52
+ | Anthropic (`claude-*`) | native Messages API | streaming structured output + native reasoning |
53
+ | OpenAI (`gpt-*`, `*-codex`) | native Responses API | Codex (native-only), native reasoning, image-gen tool |
52
54
  | Everything else (Gemini, Llama, Qwen, gpt-oss, ...) | unified MLflow endpoint | broad coverage; Gemini is here because its native endpoint does not support streaming |
53
55
 
56
+ Routing matches on the model id, so both the canonical (`gpt-5`) and the legacy `databricks-`-prefixed (`databricks-gpt-5`) forms route identically.
57
+
54
58
  ## Capabilities
55
59
 
56
60
  Verified across Anthropic, OpenAI (incl. Codex), Google, and Meta models: `generateText` / `streamText` (text, system prompts, multi-turn), tool calling (single and multi-step, generate and stream), `generateObject` / `streamObject`, and image (vision) input.
@@ -64,12 +68,11 @@ Available on OpenAI models via the Responses `image_generation` tool (there is n
64
68
  ```ts
65
69
  import { streamText } from "ai";
66
70
  import { neon } from "@neondatabase/ai-sdk-provider/v1";
67
- import { imageGeneration } from "@ai-sdk/openai/internal";
68
71
 
69
72
  const result = streamText({
70
- model: neon("databricks-gpt-5-mini"),
73
+ model: neon("gpt-5-mini"),
71
74
  prompt: "Generate an image of a red apple on a wooden table",
72
- tools: { image: imageGeneration({ partialImages: 3 }) },
75
+ tools: { image: neon.tools.imageGeneration({ partialImages: 3 }) },
73
76
  });
74
77
 
75
78
  for await (const part of result.fullStream) {
@@ -84,6 +87,18 @@ for await (const part of result.fullStream) {
84
87
 
85
88
  - `generateImage()` and embeddings (`embed` / `embedMany`) are not offered by the gateway and throw `NoSuchModelError`.
86
89
  - `gpt-oss-*` models return a non-standard ("harmony") response shape on the unified endpoint and are not fully supported.
90
+ - OpenAI Responses multi-turn tool flows (`generateText` + `stepCountIs`) can return 502 from the gateway; tool calling is covered on Anthropic/Google/Meta in e2e.
91
+
92
+ ## End-to-end tests
93
+
94
+ Against a live branch with AI Gateway enabled:
95
+
96
+ ```bash
97
+ cp .env.example .env # fill NEON_AI_GATEWAY_BASE_URL + NEON_AI_GATEWAY_TOKEN from `neonctl env pull`
98
+ pnpm test:e2e
99
+ ```
100
+
101
+ The matrix covers one models.dev `neon` model per family (Anthropic, OpenAI, Codex, Gemini, Meta) across `generateText`, `streamText`, `generateObject`, tool calling, and `neon.tools.imageGeneration`. Skipped when gateway env vars are absent.
87
102
 
88
103
  ## Versioning
89
104
 
package/dist/index.d.ts CHANGED
@@ -1,7 +1,7 @@
1
1
  import { NeonAnthropicLanguageModel } from "./lib/neon-anthropic-language-model.js";
2
2
  import { NeonChatLanguageModel } from "./lib/neon-chat-language-model.js";
3
- import { NeonChatModelId } from "./lib/neon-chat-options.js";
3
+ import { NEON_EXTRA_MODEL_IDS, NEON_MODELS_DEV_IDS, NeonChatModelId, NeonKnownModelId } from "./lib/neon-chat-options.js";
4
4
  import { NeonModelCapabilities, NeonModelFamily, NeonModelRoute, getNeonModelCapabilities, getNeonModelRoute } from "./lib/neon-model-capabilities.js";
5
5
  import { NeonResponsesLanguageModel } from "./lib/neon-responses-language-model.js";
6
6
  import { NeonErrorData, NeonProvider, NeonProviderSettings, createNeon, neon } from "./lib/provider.js";
7
- export { NeonAnthropicLanguageModel, NeonChatLanguageModel, NeonChatModelId, NeonErrorData, NeonModelCapabilities, NeonModelFamily, NeonModelRoute, NeonProvider, NeonProviderSettings, NeonResponsesLanguageModel, createNeon, getNeonModelCapabilities, getNeonModelRoute, neon };
7
+ export { NEON_EXTRA_MODEL_IDS, NEON_MODELS_DEV_IDS, NeonAnthropicLanguageModel, NeonChatLanguageModel, NeonChatModelId, NeonErrorData, NeonKnownModelId, NeonModelCapabilities, NeonModelFamily, NeonModelRoute, NeonProvider, NeonProviderSettings, NeonResponsesLanguageModel, createNeon, getNeonModelCapabilities, getNeonModelRoute, neon };
package/dist/index.js CHANGED
@@ -1,7 +1,8 @@
1
1
  import { NeonAnthropicLanguageModel } from "./lib/neon-anthropic-language-model.js";
2
2
  import { getNeonModelCapabilities, getNeonModelRoute } from "./lib/neon-model-capabilities.js";
3
3
  import { NeonChatLanguageModel } from "./lib/neon-chat-language-model.js";
4
+ import { NEON_EXTRA_MODEL_IDS, NEON_MODELS_DEV_IDS } from "./lib/neon-chat-options.js";
4
5
  import { NeonResponsesLanguageModel } from "./lib/neon-responses-language-model.js";
5
6
  import { createNeon, neon } from "./lib/provider.js";
6
7
  import "./v1.js";
7
- export { NeonAnthropicLanguageModel, NeonChatLanguageModel, NeonResponsesLanguageModel, createNeon, getNeonModelCapabilities, getNeonModelRoute, neon };
8
+ export { NEON_EXTRA_MODEL_IDS, NEON_MODELS_DEV_IDS, NeonAnthropicLanguageModel, NeonChatLanguageModel, NeonResponsesLanguageModel, createNeon, getNeonModelCapabilities, getNeonModelRoute, neon };
@@ -1,5 +1,5 @@
1
- import { AnthropicLanguageModel } from "@ai-sdk/anthropic/internal";
2
- import { LanguageModelV4, LanguageModelV4CallOptions, LanguageModelV4GenerateResult, LanguageModelV4StreamResult } from "@ai-sdk/provider";
1
+ import { AnthropicMessagesLanguageModel } from "@ai-sdk/anthropic/internal";
2
+ import { LanguageModelV3, LanguageModelV3CallOptions, LanguageModelV3GenerateResult, LanguageModelV3StreamResult } from "@ai-sdk/provider";
3
3
 
4
4
  //#region src/lib/neon-anthropic-language-model.d.ts
5
5
 
@@ -13,10 +13,10 @@ import { LanguageModelV4, LanguageModelV4CallOptions, LanguageModelV4GenerateRes
13
13
  * rejects (`Extra inputs are not permitted`). We disable it via the model's own
14
14
  * `toolStreaming` option so streaming tool calls work. Users can still override.
15
15
  */
16
- declare class NeonAnthropicLanguageModel extends AnthropicLanguageModel implements LanguageModelV4 {
16
+ declare class NeonAnthropicLanguageModel extends AnthropicMessagesLanguageModel implements LanguageModelV3 {
17
17
  private withGatewayCompat;
18
- doGenerate(options: LanguageModelV4CallOptions): Promise<LanguageModelV4GenerateResult>;
19
- doStream(options: LanguageModelV4CallOptions): Promise<LanguageModelV4StreamResult>;
18
+ doGenerate(options: LanguageModelV3CallOptions): Promise<LanguageModelV3GenerateResult>;
19
+ doStream(options: LanguageModelV3CallOptions): Promise<LanguageModelV3StreamResult>;
20
20
  }
21
21
  //#endregion
22
22
  export { NeonAnthropicLanguageModel };
@@ -1 +1 @@
1
- {"version":3,"file":"neon-anthropic-language-model.d.ts","names":[],"sources":["../../src/lib/neon-anthropic-language-model.ts"],"mappings":";;;;;;;AAkBA;;;;;;;;AACS,cADI,0BAAA,SACJ,sBAAA,YACG,eADH,CAAA;UACG,iBAAA;EAAe,UAAA,CAAA,OAAA,EAoBhB,0BApBgB,CAAA,EAqBvB,OArBuB,CAqBf,6BArBe,CAAA;oBA0BhB,6BACP,QAAQ"}
1
+ {"version":3,"file":"neon-anthropic-language-model.d.ts","names":[],"sources":["../../src/lib/neon-anthropic-language-model.ts"],"mappings":";;;;;;;AAkBA;;;;;;;;AACS,cADI,0BAAA,SACJ,8BAAA,YACG,eADH,CAAA;UACG,iBAAA;EAAe,UAAA,CAAA,OAAA,EAoBhB,0BApBgB,CAAA,EAqBvB,OArBuB,CAqBf,6BArBe,CAAA;oBA0BhB,6BACP,QAAQ"}
@@ -1,4 +1,4 @@
1
- import { AnthropicLanguageModel } from "@ai-sdk/anthropic/internal";
1
+ import { AnthropicMessagesLanguageModel } from "@ai-sdk/anthropic/internal";
2
2
  //#region src/lib/neon-anthropic-language-model.ts
3
3
  /**
4
4
  * Language model for Anthropic models served via the Neon AI Gateway's native
@@ -10,7 +10,7 @@ import { AnthropicLanguageModel } from "@ai-sdk/anthropic/internal";
10
10
  * rejects (`Extra inputs are not permitted`). We disable it via the model's own
11
11
  * `toolStreaming` option so streaming tool calls work. Users can still override.
12
12
  */
13
- var NeonAnthropicLanguageModel = class extends AnthropicLanguageModel {
13
+ var NeonAnthropicLanguageModel = class extends AnthropicMessagesLanguageModel {
14
14
  withGatewayCompat(options) {
15
15
  const anthropic = options.providerOptions?.anthropic;
16
16
  if (anthropic != null && "toolStreaming" in anthropic) return options;
@@ -1 +1 @@
1
- {"version":3,"file":"neon-anthropic-language-model.js","names":[],"sources":["../../src/lib/neon-anthropic-language-model.ts"],"sourcesContent":["import { AnthropicLanguageModel } from \"@ai-sdk/anthropic/internal\";\nimport type {\n\tLanguageModelV4,\n\tLanguageModelV4CallOptions,\n\tLanguageModelV4GenerateResult,\n\tLanguageModelV4StreamResult,\n} from \"@ai-sdk/provider\";\n\n/**\n * Language model for Anthropic models served via the Neon AI Gateway's native\n * Messages API (`/ai-gateway/anthropic/v1/messages`). Unlocks streaming\n * structured output and native reasoning for Claude.\n *\n * The shared Anthropic model defaults to fine-grained tool-input streaming\n * (`eager_input_streaming: true`) on streaming tool calls, which the gateway\n * rejects (`Extra inputs are not permitted`). We disable it via the model's own\n * `toolStreaming` option so streaming tool calls work. Users can still override.\n */\nexport class NeonAnthropicLanguageModel\n\textends AnthropicLanguageModel\n\timplements LanguageModelV4\n{\n\tprivate withGatewayCompat(\n\t\toptions: LanguageModelV4CallOptions,\n\t): LanguageModelV4CallOptions {\n\t\tconst anthropic = options.providerOptions?.anthropic;\n\t\t// Respect an explicit user setting.\n\t\tif (anthropic != null && \"toolStreaming\" in anthropic) {\n\t\t\treturn options;\n\t\t}\n\t\treturn {\n\t\t\t...options,\n\t\t\tproviderOptions: {\n\t\t\t\t...options.providerOptions,\n\t\t\t\tanthropic: { ...anthropic, toolStreaming: false },\n\t\t\t},\n\t\t};\n\t}\n\n\toverride doGenerate(\n\t\toptions: LanguageModelV4CallOptions,\n\t): Promise<LanguageModelV4GenerateResult> {\n\t\treturn super.doGenerate(this.withGatewayCompat(options));\n\t}\n\n\toverride doStream(\n\t\toptions: LanguageModelV4CallOptions,\n\t): Promise<LanguageModelV4StreamResult> {\n\t\treturn super.doStream(this.withGatewayCompat(options));\n\t}\n}\n"],"mappings":";;;;;;;;;;;;AAkBA,IAAa,6BAAb,cACS,uBAET;CACC,kBACC,SAC6B;EAC7B,MAAM,YAAY,QAAQ,iBAAiB;EAE3C,IAAI,aAAa,QAAQ,mBAAmB,WAC3C,OAAO;EAER,OAAO;GACN,GAAG;GACH,iBAAiB;IAChB,GAAG,QAAQ;IACX,WAAW;KAAE,GAAG;KAAW,eAAe;IAAM;GACjD;EACD;CACD;CAEA,WACC,SACyC;EACzC,OAAO,MAAM,WAAW,KAAK,kBAAkB,OAAO,CAAC;CACxD;CAEA,SACC,SACuC;EACvC,OAAO,MAAM,SAAS,KAAK,kBAAkB,OAAO,CAAC;CACtD;AACD"}
1
+ {"version":3,"file":"neon-anthropic-language-model.js","names":[],"sources":["../../src/lib/neon-anthropic-language-model.ts"],"sourcesContent":["import { AnthropicMessagesLanguageModel } from \"@ai-sdk/anthropic/internal\";\nimport type {\n\tLanguageModelV3,\n\tLanguageModelV3CallOptions,\n\tLanguageModelV3GenerateResult,\n\tLanguageModelV3StreamResult,\n} from \"@ai-sdk/provider\";\n\n/**\n * Language model for Anthropic models served via the Neon AI Gateway's native\n * Messages API (`/ai-gateway/anthropic/v1/messages`). Unlocks streaming\n * structured output and native reasoning for Claude.\n *\n * The shared Anthropic model defaults to fine-grained tool-input streaming\n * (`eager_input_streaming: true`) on streaming tool calls, which the gateway\n * rejects (`Extra inputs are not permitted`). We disable it via the model's own\n * `toolStreaming` option so streaming tool calls work. Users can still override.\n */\nexport class NeonAnthropicLanguageModel\n\textends AnthropicMessagesLanguageModel\n\timplements LanguageModelV3\n{\n\tprivate withGatewayCompat(\n\t\toptions: LanguageModelV3CallOptions,\n\t): LanguageModelV3CallOptions {\n\t\tconst anthropic = options.providerOptions?.anthropic;\n\t\t// Respect an explicit user setting.\n\t\tif (anthropic != null && \"toolStreaming\" in anthropic) {\n\t\t\treturn options;\n\t\t}\n\t\treturn {\n\t\t\t...options,\n\t\t\tproviderOptions: {\n\t\t\t\t...options.providerOptions,\n\t\t\t\tanthropic: { ...anthropic, toolStreaming: false },\n\t\t\t},\n\t\t};\n\t}\n\n\toverride doGenerate(\n\t\toptions: LanguageModelV3CallOptions,\n\t): Promise<LanguageModelV3GenerateResult> {\n\t\treturn super.doGenerate(this.withGatewayCompat(options));\n\t}\n\n\toverride doStream(\n\t\toptions: LanguageModelV3CallOptions,\n\t): Promise<LanguageModelV3StreamResult> {\n\t\treturn super.doStream(this.withGatewayCompat(options));\n\t}\n}\n"],"mappings":";;;;;;;;;;;;AAkBA,IAAa,6BAAb,cACS,+BAET;CACC,kBACC,SAC6B;EAC7B,MAAM,YAAY,QAAQ,iBAAiB;EAE3C,IAAI,aAAa,QAAQ,mBAAmB,WAC3C,OAAO;EAER,OAAO;GACN,GAAG;GACH,iBAAiB;IAChB,GAAG,QAAQ;IACX,WAAW;KAAE,GAAG;KAAW,eAAe;IAAM;GACjD;EACD;CACD;CAEA,WACC,SACyC;EACzC,OAAO,MAAM,WAAW,KAAK,kBAAkB,OAAO,CAAC;CACxD;CAEA,SACC,SACuC;EACvC,OAAO,MAAM,SAAS,KAAK,kBAAkB,OAAO,CAAC;CACtD;AACD"}
@@ -1,4 +1,4 @@
1
- import { LanguageModelV4CallOptions, LanguageModelV4StreamPart, SharedV4Warning } from "@ai-sdk/provider";
1
+ import { LanguageModelV3CallOptions, LanguageModelV3StreamPart, SharedV3Warning } from "@ai-sdk/provider";
2
2
 
3
3
  //#region src/lib/neon-capabilities.d.ts
4
4
 
@@ -7,14 +7,14 @@ import { LanguageModelV4CallOptions, LanguageModelV4StreamPart, SharedV4Warning
7
7
  * collect a warning for each, so callers get a clear signal instead of a hard
8
8
  * `400` from the gateway.
9
9
  */
10
- declare function applyNeonCapabilities(modelId: string, options: LanguageModelV4CallOptions): {
11
- options: LanguageModelV4CallOptions;
12
- warnings: SharedV4Warning[];
10
+ declare function applyNeonCapabilities(modelId: string, options: LanguageModelV3CallOptions): {
11
+ options: LanguageModelV3CallOptions;
12
+ warnings: SharedV3Warning[];
13
13
  };
14
14
  /**
15
15
  * Merge additional warnings into the `stream-start` part of a model stream.
16
16
  */
17
- declare function mergeStreamStartWarnings(extra: SharedV4Warning[]): TransformStream<LanguageModelV4StreamPart, LanguageModelV4StreamPart>;
17
+ declare function mergeStreamStartWarnings(extra: SharedV3Warning[]): TransformStream<LanguageModelV3StreamPart, LanguageModelV3StreamPart>;
18
18
  //#endregion
19
19
  export { applyNeonCapabilities, mergeStreamStartWarnings };
20
20
  //# sourceMappingURL=neon-capabilities.d.ts.map
@@ -1 +1 @@
1
- {"version":3,"file":"neon-capabilities.d.ts","names":[],"sources":["../../src/lib/neon-capabilities.ts"],"mappings":";;;;;;AAcA;;;AAGc,iBAHE,qBAAA,CAGF,OAAA,EAAA,MAAA,EAAA,OAAA,EADJ,0BACI,CAAA,EAAA;SAAsC,EAAtC,0BAAsC;EAAe,QAAA,EAAf,eAAe,EAAA;AAiGnE,CAAA;;;;AAAiE,iBAAjD,wBAAA,CAAiD,KAAA,EAAjB,eAAiB,EAAA,CAAA,EAAA,eAAA,CAAA,yBAAA,EAAA,yBAAA,CAAA"}
1
+ {"version":3,"file":"neon-capabilities.d.ts","names":[],"sources":["../../src/lib/neon-capabilities.ts"],"mappings":";;;;;;AAaA;;;AAGc,iBAHE,qBAAA,CAGF,OAAA,EAAA,MAAA,EAAA,OAAA,EADJ,0BACI,CAAA,EAAA;SAAsC,EAAtC,0BAAsC;EAAe,QAAA,EAAf,eAAe,EAAA;AA4FnE,CAAA;;;;AAAiE,iBAAjD,wBAAA,CAAiD,KAAA,EAAjB,eAAiB,EAAA,CAAA,EAAA,eAAA,CAAA,yBAAA,EAAA,yBAAA,CAAA"}
@@ -1,5 +1,4 @@
1
1
  import { getNeonModelCapabilities } from "./neon-model-capabilities.js";
2
- import { isCustomReasoning } from "@ai-sdk/provider-utils";
3
2
  //#region src/lib/neon-capabilities.ts
4
3
  /**
5
4
  * Drop call options the resolved model's upstream backend does not accept and
@@ -53,11 +52,9 @@ function applyNeonCapabilities(modelId, options) {
53
52
  }
54
53
  if (!caps.supportsReasoningEffort) {
55
54
  const { providerOptions } = options;
56
- const hasProviderEffort = providerOptions != null && Object.values(providerOptions).some((group) => "reasoningEffort" in group && group.reasoningEffort != null);
57
- const hasReasoningOption = isCustomReasoning(options.reasoning) && options.reasoning !== "none";
58
- if (hasProviderEffort || hasReasoningOption) {
55
+ if (providerOptions != null && Object.values(providerOptions).some((group) => "reasoningEffort" in group && group.reasoningEffort != null)) {
59
56
  dropUnsupported("reasoningEffort");
60
- if (hasProviderEffort && providerOptions != null) {
57
+ if (providerOptions != null) {
61
58
  const cleaned = {};
62
59
  for (const [key, group] of Object.entries(providerOptions)) if ("reasoningEffort" in group) {
63
60
  const { reasoningEffort: _removed, ...rest } = group;
@@ -65,7 +62,6 @@ function applyNeonCapabilities(modelId, options) {
65
62
  } else cleaned[key] = group;
66
63
  patch.providerOptions = cleaned;
67
64
  }
68
- if (hasReasoningOption) patch.reasoning = void 0;
69
65
  }
70
66
  }
71
67
  if (Object.keys(patch).length === 0) return {
@@ -1 +1 @@
1
- {"version":3,"file":"neon-capabilities.js","names":[],"sources":["../../src/lib/neon-capabilities.ts"],"sourcesContent":["import type {\n\tLanguageModelV4CallOptions,\n\tLanguageModelV4StreamPart,\n\tSharedV4ProviderOptions,\n\tSharedV4Warning,\n} from \"@ai-sdk/provider\";\nimport { isCustomReasoning } from \"@ai-sdk/provider-utils\";\nimport { getNeonModelCapabilities } from \"./neon-model-capabilities.js\";\n\n/**\n * Drop call options the resolved model's upstream backend does not accept and\n * collect a warning for each, so callers get a clear signal instead of a hard\n * `400` from the gateway.\n */\nexport function applyNeonCapabilities(\n\tmodelId: string,\n\toptions: LanguageModelV4CallOptions,\n): { options: LanguageModelV4CallOptions; warnings: SharedV4Warning[] } {\n\tconst caps = getNeonModelCapabilities(modelId);\n\tconst warnings: SharedV4Warning[] = [];\n\tconst patch: Partial<LanguageModelV4CallOptions> = {};\n\n\tconst dropUnsupported = (feature: string) => {\n\t\twarnings.push({\n\t\t\ttype: \"unsupported\",\n\t\t\tfeature,\n\t\t\tdetails: `${feature} is not supported by the Neon AI Gateway for ${caps.family} model \"${modelId}\" and was dropped.`,\n\t\t});\n\t};\n\n\tif (options.temperature != null && !caps.supportsTemperature) {\n\t\tpatch.temperature = undefined;\n\t\tdropUnsupported(\"temperature\");\n\t}\n\tif (options.topP != null && !caps.supportsTopP) {\n\t\tpatch.topP = undefined;\n\t\tdropUnsupported(\"topP\");\n\t}\n\n\t// Anthropic-style models accept only one of temperature / topP.\n\tconst effectiveTemperature =\n\t\t\"temperature\" in patch ? patch.temperature : options.temperature;\n\tconst effectiveTopP = \"topP\" in patch ? patch.topP : options.topP;\n\tif (\n\t\tcaps.temperatureTopPMutuallyExclusive &&\n\t\teffectiveTemperature != null &&\n\t\teffectiveTopP != null\n\t) {\n\t\tpatch.topP = undefined;\n\t\twarnings.push({\n\t\t\ttype: \"compatibility\",\n\t\t\tfeature: \"topP\",\n\t\t\tdetails: `${caps.family} models accept only one of temperature or topP; topP was dropped.`,\n\t\t});\n\t}\n\n\tif (options.frequencyPenalty != null && !caps.supportsPenalties) {\n\t\tpatch.frequencyPenalty = undefined;\n\t\tdropUnsupported(\"frequencyPenalty\");\n\t}\n\tif (options.presencePenalty != null && !caps.supportsPenalties) {\n\t\tpatch.presencePenalty = undefined;\n\t\tdropUnsupported(\"presencePenalty\");\n\t}\n\tif (options.seed != null && !caps.supportsSeed) {\n\t\tpatch.seed = undefined;\n\t\tdropUnsupported(\"seed\");\n\t}\n\tif (options.stopSequences != null && !caps.supportsStopSequences) {\n\t\tpatch.stopSequences = undefined;\n\t\tdropUnsupported(\"stopSequences\");\n\t}\n\n\tif (!caps.supportsReasoningEffort) {\n\t\tconst { providerOptions } = options;\n\t\tconst hasProviderEffort =\n\t\t\tproviderOptions != null &&\n\t\t\tObject.values(providerOptions).some(\n\t\t\t\t(group) =>\n\t\t\t\t\t\"reasoningEffort\" in group && group.reasoningEffort != null,\n\t\t\t);\n\t\tconst hasReasoningOption =\n\t\t\tisCustomReasoning(options.reasoning) &&\n\t\t\toptions.reasoning !== \"none\";\n\n\t\tif (hasProviderEffort || hasReasoningOption) {\n\t\t\tdropUnsupported(\"reasoningEffort\");\n\t\t\tif (hasProviderEffort && providerOptions != null) {\n\t\t\t\tconst cleaned: SharedV4ProviderOptions = {};\n\t\t\t\tfor (const [key, group] of Object.entries(providerOptions)) {\n\t\t\t\t\tif (\"reasoningEffort\" in group) {\n\t\t\t\t\t\tconst { reasoningEffort: _removed, ...rest } = group;\n\t\t\t\t\t\tcleaned[key] = rest;\n\t\t\t\t\t} else {\n\t\t\t\t\t\tcleaned[key] = group;\n\t\t\t\t\t}\n\t\t\t\t}\n\t\t\t\tpatch.providerOptions = cleaned;\n\t\t\t}\n\t\t\tif (hasReasoningOption) {\n\t\t\t\tpatch.reasoning = undefined;\n\t\t\t}\n\t\t}\n\t}\n\n\tif (Object.keys(patch).length === 0) {\n\t\treturn { options, warnings };\n\t}\n\treturn { options: { ...options, ...patch }, warnings };\n}\n\n/**\n * Merge additional warnings into the `stream-start` part of a model stream.\n */\nexport function mergeStreamStartWarnings(extra: SharedV4Warning[]) {\n\tlet merged = false;\n\treturn new TransformStream<\n\t\tLanguageModelV4StreamPart,\n\t\tLanguageModelV4StreamPart\n\t>({\n\t\ttransform(part, controller) {\n\t\t\tif (!merged && part.type === \"stream-start\") {\n\t\t\t\tmerged = true;\n\t\t\t\tcontroller.enqueue({\n\t\t\t\t\t...part,\n\t\t\t\t\twarnings: [...extra, ...part.warnings],\n\t\t\t\t});\n\t\t\t} else {\n\t\t\t\tcontroller.enqueue(part);\n\t\t\t}\n\t\t},\n\t});\n}\n"],"mappings":";;;;;;;;AAcA,SAAgB,sBACf,SACA,SACuE;CACvE,MAAM,OAAO,yBAAyB,OAAO;CAC7C,MAAM,WAA8B,CAAC;CACrC,MAAM,QAA6C,CAAC;CAEpD,MAAM,mBAAmB,YAAoB;EAC5C,SAAS,KAAK;GACb,MAAM;GACN;GACA,SAAS,GAAG,QAAQ,+CAA+C,KAAK,OAAO,UAAU,QAAQ;EAClG,CAAC;CACF;CAEA,IAAI,QAAQ,eAAe,QAAQ,CAAC,KAAK,qBAAqB;EAC7D,MAAM,cAAc,KAAA;EACpB,gBAAgB,aAAa;CAC9B;CACA,IAAI,QAAQ,QAAQ,QAAQ,CAAC,KAAK,cAAc;EAC/C,MAAM,OAAO,KAAA;EACb,gBAAgB,MAAM;CACvB;CAGA,MAAM,uBACL,iBAAiB,QAAQ,MAAM,cAAc,QAAQ;CACtD,MAAM,gBAAgB,UAAU,QAAQ,MAAM,OAAO,QAAQ;CAC7D,IACC,KAAK,oCACL,wBAAwB,QACxB,iBAAiB,MAChB;EACD,MAAM,OAAO,KAAA;EACb,SAAS,KAAK;GACb,MAAM;GACN,SAAS;GACT,SAAS,GAAG,KAAK,OAAO;EACzB,CAAC;CACF;CAEA,IAAI,QAAQ,oBAAoB,QAAQ,CAAC,KAAK,mBAAmB;EAChE,MAAM,mBAAmB,KAAA;EACzB,gBAAgB,kBAAkB;CACnC;CACA,IAAI,QAAQ,mBAAmB,QAAQ,CAAC,KAAK,mBAAmB;EAC/D,MAAM,kBAAkB,KAAA;EACxB,gBAAgB,iBAAiB;CAClC;CACA,IAAI,QAAQ,QAAQ,QAAQ,CAAC,KAAK,cAAc;EAC/C,MAAM,OAAO,KAAA;EACb,gBAAgB,MAAM;CACvB;CACA,IAAI,QAAQ,iBAAiB,QAAQ,CAAC,KAAK,uBAAuB;EACjE,MAAM,gBAAgB,KAAA;EACtB,gBAAgB,eAAe;CAChC;CAEA,IAAI,CAAC,KAAK,yBAAyB;EAClC,MAAM,EAAE,oBAAoB;EAC5B,MAAM,oBACL,mBAAmB,QACnB,OAAO,OAAO,eAAe,CAAC,CAAC,MAC7B,UACA,qBAAqB,SAAS,MAAM,mBAAmB,IACzD;EACD,MAAM,qBACL,kBAAkB,QAAQ,SAAS,KACnC,QAAQ,cAAc;EAEvB,IAAI,qBAAqB,oBAAoB;GAC5C,gBAAgB,iBAAiB;GACjC,IAAI,qBAAqB,mBAAmB,MAAM;IACjD,MAAM,UAAmC,CAAC;IAC1C,KAAK,MAAM,CAAC,KAAK,UAAU,OAAO,QAAQ,eAAe,GACxD,IAAI,qBAAqB,OAAO;KAC/B,MAAM,EAAE,iBAAiB,UAAU,GAAG,SAAS;KAC/C,QAAQ,OAAO;IAChB,OACC,QAAQ,OAAO;IAGjB,MAAM,kBAAkB;GACzB;GACA,IAAI,oBACH,MAAM,YAAY,KAAA;EAEpB;CACD;CAEA,IAAI,OAAO,KAAK,KAAK,CAAC,CAAC,WAAW,GACjC,OAAO;EAAE;EAAS;CAAS;CAE5B,OAAO;EAAE,SAAS;GAAE,GAAG;GAAS,GAAG;EAAM;EAAG;CAAS;AACtD;;;;AAKA,SAAgB,yBAAyB,OAA0B;CAClE,IAAI,SAAS;CACb,OAAO,IAAI,gBAGT,EACD,UAAU,MAAM,YAAY;EAC3B,IAAI,CAAC,UAAU,KAAK,SAAS,gBAAgB;GAC5C,SAAS;GACT,WAAW,QAAQ;IAClB,GAAG;IACH,UAAU,CAAC,GAAG,OAAO,GAAG,KAAK,QAAQ;GACtC,CAAC;EACF,OACC,WAAW,QAAQ,IAAI;CAEzB,EACD,CAAC;AACF"}
1
+ {"version":3,"file":"neon-capabilities.js","names":[],"sources":["../../src/lib/neon-capabilities.ts"],"sourcesContent":["import type {\n\tLanguageModelV3CallOptions,\n\tLanguageModelV3StreamPart,\n\tSharedV3ProviderOptions,\n\tSharedV3Warning,\n} from \"@ai-sdk/provider\";\nimport { getNeonModelCapabilities } from \"./neon-model-capabilities.js\";\n\n/**\n * Drop call options the resolved model's upstream backend does not accept and\n * collect a warning for each, so callers get a clear signal instead of a hard\n * `400` from the gateway.\n */\nexport function applyNeonCapabilities(\n\tmodelId: string,\n\toptions: LanguageModelV3CallOptions,\n): { options: LanguageModelV3CallOptions; warnings: SharedV3Warning[] } {\n\tconst caps = getNeonModelCapabilities(modelId);\n\tconst warnings: SharedV3Warning[] = [];\n\tconst patch: Partial<LanguageModelV3CallOptions> = {};\n\n\tconst dropUnsupported = (feature: string) => {\n\t\twarnings.push({\n\t\t\ttype: \"unsupported\",\n\t\t\tfeature,\n\t\t\tdetails: `${feature} is not supported by the Neon AI Gateway for ${caps.family} model \"${modelId}\" and was dropped.`,\n\t\t});\n\t};\n\n\tif (options.temperature != null && !caps.supportsTemperature) {\n\t\tpatch.temperature = undefined;\n\t\tdropUnsupported(\"temperature\");\n\t}\n\tif (options.topP != null && !caps.supportsTopP) {\n\t\tpatch.topP = undefined;\n\t\tdropUnsupported(\"topP\");\n\t}\n\n\t// Anthropic-style models accept only one of temperature / topP.\n\tconst effectiveTemperature =\n\t\t\"temperature\" in patch ? patch.temperature : options.temperature;\n\tconst effectiveTopP = \"topP\" in patch ? patch.topP : options.topP;\n\tif (\n\t\tcaps.temperatureTopPMutuallyExclusive &&\n\t\teffectiveTemperature != null &&\n\t\teffectiveTopP != null\n\t) {\n\t\tpatch.topP = undefined;\n\t\twarnings.push({\n\t\t\ttype: \"compatibility\",\n\t\t\tfeature: \"topP\",\n\t\t\tdetails: `${caps.family} models accept only one of temperature or topP; topP was dropped.`,\n\t\t});\n\t}\n\n\tif (options.frequencyPenalty != null && !caps.supportsPenalties) {\n\t\tpatch.frequencyPenalty = undefined;\n\t\tdropUnsupported(\"frequencyPenalty\");\n\t}\n\tif (options.presencePenalty != null && !caps.supportsPenalties) {\n\t\tpatch.presencePenalty = undefined;\n\t\tdropUnsupported(\"presencePenalty\");\n\t}\n\tif (options.seed != null && !caps.supportsSeed) {\n\t\tpatch.seed = undefined;\n\t\tdropUnsupported(\"seed\");\n\t}\n\n\tif (options.stopSequences != null && !caps.supportsStopSequences) {\n\t\tpatch.stopSequences = undefined;\n\t\tdropUnsupported(\"stopSequences\");\n\t}\n\n\tif (!caps.supportsReasoningEffort) {\n\t\tconst { providerOptions } = options;\n\t\tconst hasProviderEffort =\n\t\t\tproviderOptions != null &&\n\t\t\tObject.values(providerOptions).some(\n\t\t\t\t(group) =>\n\t\t\t\t\t\"reasoningEffort\" in group && group.reasoningEffort != null,\n\t\t\t);\n\n\t\tif (hasProviderEffort) {\n\t\t\tdropUnsupported(\"reasoningEffort\");\n\t\t\tif (providerOptions != null) {\n\t\t\t\tconst cleaned: SharedV3ProviderOptions = {};\n\t\t\t\tfor (const [key, group] of Object.entries(providerOptions)) {\n\t\t\t\t\tif (\"reasoningEffort\" in group) {\n\t\t\t\t\t\tconst { reasoningEffort: _removed, ...rest } = group;\n\t\t\t\t\t\tcleaned[key] = rest;\n\t\t\t\t\t} else {\n\t\t\t\t\t\tcleaned[key] = group;\n\t\t\t\t\t}\n\t\t\t\t}\n\t\t\t\tpatch.providerOptions = cleaned;\n\t\t\t}\n\t\t}\n\t}\n\n\tif (Object.keys(patch).length === 0) {\n\t\treturn { options, warnings };\n\t}\n\treturn { options: { ...options, ...patch }, warnings };\n}\n\n/**\n * Merge additional warnings into the `stream-start` part of a model stream.\n */\nexport function mergeStreamStartWarnings(extra: SharedV3Warning[]) {\n\tlet merged = false;\n\treturn new TransformStream<\n\t\tLanguageModelV3StreamPart,\n\t\tLanguageModelV3StreamPart\n\t>({\n\t\ttransform(part, controller) {\n\t\t\tif (!merged && part.type === \"stream-start\") {\n\t\t\t\tmerged = true;\n\t\t\t\tcontroller.enqueue({\n\t\t\t\t\t...part,\n\t\t\t\t\twarnings: [...extra, ...part.warnings],\n\t\t\t\t});\n\t\t\t} else {\n\t\t\t\tcontroller.enqueue(part);\n\t\t\t}\n\t\t},\n\t});\n}\n"],"mappings":";;;;;;;AAaA,SAAgB,sBACf,SACA,SACuE;CACvE,MAAM,OAAO,yBAAyB,OAAO;CAC7C,MAAM,WAA8B,CAAC;CACrC,MAAM,QAA6C,CAAC;CAEpD,MAAM,mBAAmB,YAAoB;EAC5C,SAAS,KAAK;GACb,MAAM;GACN;GACA,SAAS,GAAG,QAAQ,+CAA+C,KAAK,OAAO,UAAU,QAAQ;EAClG,CAAC;CACF;CAEA,IAAI,QAAQ,eAAe,QAAQ,CAAC,KAAK,qBAAqB;EAC7D,MAAM,cAAc,KAAA;EACpB,gBAAgB,aAAa;CAC9B;CACA,IAAI,QAAQ,QAAQ,QAAQ,CAAC,KAAK,cAAc;EAC/C,MAAM,OAAO,KAAA;EACb,gBAAgB,MAAM;CACvB;CAGA,MAAM,uBACL,iBAAiB,QAAQ,MAAM,cAAc,QAAQ;CACtD,MAAM,gBAAgB,UAAU,QAAQ,MAAM,OAAO,QAAQ;CAC7D,IACC,KAAK,oCACL,wBAAwB,QACxB,iBAAiB,MAChB;EACD,MAAM,OAAO,KAAA;EACb,SAAS,KAAK;GACb,MAAM;GACN,SAAS;GACT,SAAS,GAAG,KAAK,OAAO;EACzB,CAAC;CACF;CAEA,IAAI,QAAQ,oBAAoB,QAAQ,CAAC,KAAK,mBAAmB;EAChE,MAAM,mBAAmB,KAAA;EACzB,gBAAgB,kBAAkB;CACnC;CACA,IAAI,QAAQ,mBAAmB,QAAQ,CAAC,KAAK,mBAAmB;EAC/D,MAAM,kBAAkB,KAAA;EACxB,gBAAgB,iBAAiB;CAClC;CACA,IAAI,QAAQ,QAAQ,QAAQ,CAAC,KAAK,cAAc;EAC/C,MAAM,OAAO,KAAA;EACb,gBAAgB,MAAM;CACvB;CAEA,IAAI,QAAQ,iBAAiB,QAAQ,CAAC,KAAK,uBAAuB;EACjE,MAAM,gBAAgB,KAAA;EACtB,gBAAgB,eAAe;CAChC;CAEA,IAAI,CAAC,KAAK,yBAAyB;EAClC,MAAM,EAAE,oBAAoB;EAQ5B,IANC,mBAAmB,QACnB,OAAO,OAAO,eAAe,CAAC,CAAC,MAC7B,UACA,qBAAqB,SAAS,MAAM,mBAAmB,IACzD,GAEsB;GACtB,gBAAgB,iBAAiB;GACjC,IAAI,mBAAmB,MAAM;IAC5B,MAAM,UAAmC,CAAC;IAC1C,KAAK,MAAM,CAAC,KAAK,UAAU,OAAO,QAAQ,eAAe,GACxD,IAAI,qBAAqB,OAAO;KAC/B,MAAM,EAAE,iBAAiB,UAAU,GAAG,SAAS;KAC/C,QAAQ,OAAO;IAChB,OACC,QAAQ,OAAO;IAGjB,MAAM,kBAAkB;GACzB;EACD;CACD;CAEA,IAAI,OAAO,KAAK,KAAK,CAAC,CAAC,WAAW,GACjC,OAAO;EAAE;EAAS;CAAS;CAE5B,OAAO;EAAE,SAAS;GAAE,GAAG;GAAS,GAAG;EAAM;EAAG;CAAS;AACtD;;;;AAKA,SAAgB,yBAAyB,OAA0B;CAClE,IAAI,SAAS;CACb,OAAO,IAAI,gBAGT,EACD,UAAU,MAAM,YAAY;EAC3B,IAAI,CAAC,UAAU,KAAK,SAAS,gBAAgB;GAC5C,SAAS;GACT,WAAW,QAAQ;IAClB,GAAG;IACH,UAAU,CAAC,GAAG,OAAO,GAAG,KAAK,QAAQ;GACtC,CAAC;EACF,OACC,WAAW,QAAQ,IAAI;CAEzB,EACD,CAAC;AACF"}
@@ -1,5 +1,5 @@
1
1
  import { OpenAICompatibleChatLanguageModel } from "@ai-sdk/openai-compatible";
2
- import { LanguageModelV4, LanguageModelV4CallOptions, LanguageModelV4GenerateResult, LanguageModelV4StreamResult } from "@ai-sdk/provider";
2
+ import { LanguageModelV3, LanguageModelV3CallOptions, LanguageModelV3GenerateResult, LanguageModelV3StreamResult } from "@ai-sdk/provider";
3
3
 
4
4
  //#region src/lib/neon-chat-language-model.d.ts
5
5
 
@@ -12,9 +12,9 @@ import { LanguageModelV4, LanguageModelV4CallOptions, LanguageModelV4GenerateRes
12
12
  * parameters an upstream backend is known to reject are dropped and reported as
13
13
  * warnings instead of failing the request.
14
14
  */
15
- declare class NeonChatLanguageModel extends OpenAICompatibleChatLanguageModel implements LanguageModelV4 {
16
- doGenerate(options: LanguageModelV4CallOptions): Promise<LanguageModelV4GenerateResult>;
17
- doStream(options: LanguageModelV4CallOptions): Promise<LanguageModelV4StreamResult>;
15
+ declare class NeonChatLanguageModel extends OpenAICompatibleChatLanguageModel implements LanguageModelV3 {
16
+ doGenerate(options: LanguageModelV3CallOptions): Promise<LanguageModelV3GenerateResult>;
17
+ doStream(options: LanguageModelV3CallOptions): Promise<LanguageModelV3StreamResult>;
18
18
  }
19
19
  //#endregion
20
20
  export { NeonChatLanguageModel };
@@ -1 +1 @@
1
- {"version":3,"file":"neon-chat-language-model.js","names":[],"sources":["../../src/lib/neon-chat-language-model.ts"],"sourcesContent":["import { OpenAICompatibleChatLanguageModel } from \"@ai-sdk/openai-compatible\";\nimport type {\n\tLanguageModelV4,\n\tLanguageModelV4CallOptions,\n\tLanguageModelV4GenerateResult,\n\tLanguageModelV4StreamResult,\n} from \"@ai-sdk/provider\";\nimport {\n\tapplyNeonCapabilities,\n\tmergeStreamStartWarnings,\n} from \"./neon-capabilities.js\";\n\n/**\n * Language model for the Neon AI Gateway unified (MLflow) endpoint.\n *\n * Used for every model that is not routed to a provider-native endpoint\n * (Gemini, Llama, Qwen, gpt-oss, ...). It is a thin specialization of the shared\n * OpenAI-compatible chat model that adds per-model capability handling:\n * parameters an upstream backend is known to reject are dropped and reported as\n * warnings instead of failing the request.\n */\nexport class NeonChatLanguageModel\n\textends OpenAICompatibleChatLanguageModel\n\timplements LanguageModelV4\n{\n\toverride async doGenerate(\n\t\toptions: LanguageModelV4CallOptions,\n\t): Promise<LanguageModelV4GenerateResult> {\n\t\tconst { options: adjusted, warnings } = applyNeonCapabilities(\n\t\t\tthis.modelId,\n\t\t\toptions,\n\t\t);\n\t\tconst result = await super.doGenerate(adjusted);\n\t\treturn warnings.length > 0\n\t\t\t? { ...result, warnings: [...warnings, ...result.warnings] }\n\t\t\t: result;\n\t}\n\n\toverride async doStream(\n\t\toptions: LanguageModelV4CallOptions,\n\t): Promise<LanguageModelV4StreamResult> {\n\t\tconst { options: adjusted, warnings } = applyNeonCapabilities(\n\t\t\tthis.modelId,\n\t\t\toptions,\n\t\t);\n\t\tconst result = await super.doStream(adjusted);\n\t\treturn warnings.length > 0\n\t\t\t? {\n\t\t\t\t\t...result,\n\t\t\t\t\tstream: result.stream.pipeThrough(\n\t\t\t\t\t\tmergeStreamStartWarnings(warnings),\n\t\t\t\t\t),\n\t\t\t\t}\n\t\t\t: result;\n\t}\n}\n"],"mappings":";;;;;;;;;;;;AAqBA,IAAa,wBAAb,cACS,kCAET;CACC,MAAe,WACd,SACyC;EACzC,MAAM,EAAE,SAAS,UAAU,aAAa,sBACvC,KAAK,SACL,OACD;EACA,MAAM,SAAS,MAAM,MAAM,WAAW,QAAQ;EAC9C,OAAO,SAAS,SAAS,IACtB;GAAE,GAAG;GAAQ,UAAU,CAAC,GAAG,UAAU,GAAG,OAAO,QAAQ;EAAE,IACzD;CACJ;CAEA,MAAe,SACd,SACuC;EACvC,MAAM,EAAE,SAAS,UAAU,aAAa,sBACvC,KAAK,SACL,OACD;EACA,MAAM,SAAS,MAAM,MAAM,SAAS,QAAQ;EAC5C,OAAO,SAAS,SAAS,IACtB;GACA,GAAG;GACH,QAAQ,OAAO,OAAO,YACrB,yBAAyB,QAAQ,CAClC;EACD,IACC;CACJ;AACD"}
1
+ {"version":3,"file":"neon-chat-language-model.js","names":[],"sources":["../../src/lib/neon-chat-language-model.ts"],"sourcesContent":["import { OpenAICompatibleChatLanguageModel } from \"@ai-sdk/openai-compatible\";\nimport type {\n\tLanguageModelV3,\n\tLanguageModelV3CallOptions,\n\tLanguageModelV3GenerateResult,\n\tLanguageModelV3StreamResult,\n} from \"@ai-sdk/provider\";\nimport {\n\tapplyNeonCapabilities,\n\tmergeStreamStartWarnings,\n} from \"./neon-capabilities.js\";\n\n/**\n * Language model for the Neon AI Gateway unified (MLflow) endpoint.\n *\n * Used for every model that is not routed to a provider-native endpoint\n * (Gemini, Llama, Qwen, gpt-oss, ...). It is a thin specialization of the shared\n * OpenAI-compatible chat model that adds per-model capability handling:\n * parameters an upstream backend is known to reject are dropped and reported as\n * warnings instead of failing the request.\n */\nexport class NeonChatLanguageModel\n\textends OpenAICompatibleChatLanguageModel\n\timplements LanguageModelV3\n{\n\toverride async doGenerate(\n\t\toptions: LanguageModelV3CallOptions,\n\t): Promise<LanguageModelV3GenerateResult> {\n\t\tconst { options: adjusted, warnings } = applyNeonCapabilities(\n\t\t\tthis.modelId,\n\t\t\toptions,\n\t\t);\n\t\tconst result = await super.doGenerate(adjusted);\n\t\treturn warnings.length > 0\n\t\t\t? { ...result, warnings: [...warnings, ...result.warnings] }\n\t\t\t: result;\n\t}\n\n\toverride async doStream(\n\t\toptions: LanguageModelV3CallOptions,\n\t): Promise<LanguageModelV3StreamResult> {\n\t\tconst { options: adjusted, warnings } = applyNeonCapabilities(\n\t\t\tthis.modelId,\n\t\t\toptions,\n\t\t);\n\t\tconst result = await super.doStream(adjusted);\n\t\treturn warnings.length > 0\n\t\t\t? {\n\t\t\t\t\t...result,\n\t\t\t\t\tstream: result.stream.pipeThrough(\n\t\t\t\t\t\tmergeStreamStartWarnings(warnings),\n\t\t\t\t\t),\n\t\t\t\t}\n\t\t\t: result;\n\t}\n}\n"],"mappings":";;;;;;;;;;;;AAqBA,IAAa,wBAAb,cACS,kCAET;CACC,MAAe,WACd,SACyC;EACzC,MAAM,EAAE,SAAS,UAAU,aAAa,sBACvC,KAAK,SACL,OACD;EACA,MAAM,SAAS,MAAM,MAAM,WAAW,QAAQ;EAC9C,OAAO,SAAS,SAAS,IACtB;GAAE,GAAG;GAAQ,UAAU,CAAC,GAAG,UAAU,GAAG,OAAO,QAAQ;EAAE,IACzD;CACJ;CAEA,MAAe,SACd,SACuC;EACvC,MAAM,EAAE,SAAS,UAAU,aAAa,sBACvC,KAAK,SACL,OACD;EACA,MAAM,SAAS,MAAM,MAAM,SAAS,QAAQ;EAC5C,OAAO,SAAS,SAAS,IACtB;GACA,GAAG;GACH,QAAQ,OAAO,OAAO,YACrB,yBAAyB,QAAQ,CAClC;EACD,IACC;CACJ;AACD"}
@@ -1,5 +1,21 @@
1
1
  //#region src/lib/neon-chat-options.d.ts
2
- type NeonChatModelId = "databricks-claude-opus-4-8" | "databricks-claude-opus-4-7" | "databricks-claude-opus-4-6" | "databricks-claude-opus-4-5" | "databricks-claude-opus-4-1" | "databricks-claude-sonnet-4-6" | "databricks-claude-sonnet-4-5" | "databricks-claude-sonnet-4" | "databricks-claude-haiku-4-5" | "databricks-gpt-5" | "databricks-gpt-5-mini" | "databricks-gpt-5-nano" | "databricks-gpt-5-1" | "databricks-gpt-5-2" | "databricks-gpt-5-2-codex" | "databricks-gpt-5-3-codex" | "databricks-gpt-5-4" | "databricks-gpt-5-4-mini" | "databricks-gpt-5-4-nano" | "databricks-gpt-5-5" | "databricks-gpt-5-5-pro" | "databricks-gpt-oss-120b" | "databricks-gpt-oss-20b" | "databricks-gemini-3-5-flash" | "databricks-gemini-3-1-flash-lite" | "databricks-gemini-2-5-pro" | "databricks-gemini-2-5-flash" | "databricks-gemma-3-12b" | "databricks-llama-4-maverick" | "databricks-meta-llama-3-3-70b-instruct" | "databricks-meta-llama-3-1-8b-instruct" | "databricks-qwen3-next-80b-a3b-instruct" | "databricks-qwen35-122b-a10b" | (string & {});
2
+ /** The models.dev `neon` catalog (canonical, unprefixed ids). */
3
+ declare const NEON_MODELS_DEV_IDS: readonly ["claude-opus-4-7", "claude-opus-4-6", "claude-opus-4-5", "claude-opus-4-1", "claude-sonnet-4-6", "claude-sonnet-4-5", "claude-sonnet-4", "claude-haiku-4-5", "gpt-5", "gpt-5-mini", "gpt-5-nano", "gpt-5-1", "gpt-5-2", "gpt-5-4", "gpt-5-4-mini", "gpt-5-4-nano", "gpt-5-5", "gpt-oss-120b", "gpt-oss-20b", "gemini-3-pro", "gemini-3-flash", "gemini-3-1-pro", "gemini-3-1-flash-lite", "gemini-2-5-pro", "gemini-2-5-flash"];
4
+ /**
5
+ * Ids the gateway serves that the models.dev `neon` provider does not list.
6
+ * Verified to resolve against the gateway; retained for autocomplete. If
7
+ * models.dev later lists one of these, the drift check flags it for promotion
8
+ * into `NEON_MODELS_DEV_IDS`.
9
+ */
10
+ declare const NEON_EXTRA_MODEL_IDS: readonly ["claude-opus-4-8", "gpt-5-2-codex", "gpt-5-3-codex", "gpt-5-5-pro", "gemini-3-5-flash", "gemma-3-12b", "llama-4-maverick", "meta-llama-3-3-70b-instruct", "meta-llama-3-1-8b-instruct", "qwen3-next-80b-a3b-instruct", "qwen35-122b-a10b"];
11
+ /** A known Neon AI Gateway model id (models.dev catalog + gateway extras). */
12
+ type NeonKnownModelId = (typeof NEON_MODELS_DEV_IDS)[number] | (typeof NEON_EXTRA_MODEL_IDS)[number];
13
+ /**
14
+ * A Neon AI Gateway model id. Known ids are listed for autocomplete; any other
15
+ * id (e.g. a brand-new model, or the legacy `databricks-` prefixed form) is
16
+ * accepted via the `(string & {})` fallback.
17
+ */
18
+ type NeonChatModelId = NeonKnownModelId | (string & {});
3
19
  //#endregion
4
- export { NeonChatModelId };
20
+ export { NEON_EXTRA_MODEL_IDS, NEON_MODELS_DEV_IDS, NeonChatModelId, NeonKnownModelId };
5
21
  //# sourceMappingURL=neon-chat-options.d.ts.map
@@ -1 +1 @@
1
- {"version":3,"file":"neon-chat-options.d.ts","names":[],"sources":["../../src/lib/neon-chat-options.ts"],"mappings":";KAOY,eAAA"}
1
+ {"version":3,"file":"neon-chat-options.d.ts","names":[],"sources":["../../src/lib/neon-chat-options.ts"],"mappings":";;AAiBa,cAAA,mBA8BH,EAAA,SAAA,CAAA,iBAAA,EAAA,iBAAA,EAAA,iBAAA,EAAA,iBAAA,EAAA,mBAAA,EAAA,mBAAA,EAAA,iBAAA,EAAA,kBAAA,EAAA,OAAA,EAAA,YAAA,EAAA,YAAA,EAAA,SAAA,EAAA,SAAA,EAAA,SAAA,EAAA,cAAA,EAAA,cAAA,EAAA,SAAA,EAAA,cAAA,EAAA,aAAA,EAAA,cAAA,EAAA,gBAAA,EAAA,gBAAA,EAAA,uBAAA,EAAA,gBAAA,EAAA,kBAAA,CAAA;AAQV;AAoBA;;;;AAE+B;AAOnB,cA7BC,oBA6BiB,EAAA,SAAgB,CAAA,iBAAA,EAAA,eAAA,EAAA,eAAA,EAAA,aAAA,EAAA,kBAAA,EAAA,aAAA,EAAA,kBAAA,EAAA,6BAAA,EAAA,4BAAA,EAAA,6BAAA,EAAA,kBAAA,CAAA;;KATlC,gBAAA,WACD,uCACA;;;;;;KAOC,eAAA,GAAkB"}
@@ -1 +1,52 @@
1
- export {};
1
+ //#region src/lib/neon-chat-options.ts
2
+ /** The models.dev `neon` catalog (canonical, unprefixed ids). */
3
+ const NEON_MODELS_DEV_IDS = [
4
+ "claude-opus-4-7",
5
+ "claude-opus-4-6",
6
+ "claude-opus-4-5",
7
+ "claude-opus-4-1",
8
+ "claude-sonnet-4-6",
9
+ "claude-sonnet-4-5",
10
+ "claude-sonnet-4",
11
+ "claude-haiku-4-5",
12
+ "gpt-5",
13
+ "gpt-5-mini",
14
+ "gpt-5-nano",
15
+ "gpt-5-1",
16
+ "gpt-5-2",
17
+ "gpt-5-4",
18
+ "gpt-5-4-mini",
19
+ "gpt-5-4-nano",
20
+ "gpt-5-5",
21
+ "gpt-oss-120b",
22
+ "gpt-oss-20b",
23
+ "gemini-3-pro",
24
+ "gemini-3-flash",
25
+ "gemini-3-1-pro",
26
+ "gemini-3-1-flash-lite",
27
+ "gemini-2-5-pro",
28
+ "gemini-2-5-flash"
29
+ ];
30
+ /**
31
+ * Ids the gateway serves that the models.dev `neon` provider does not list.
32
+ * Verified to resolve against the gateway; retained for autocomplete. If
33
+ * models.dev later lists one of these, the drift check flags it for promotion
34
+ * into `NEON_MODELS_DEV_IDS`.
35
+ */
36
+ const NEON_EXTRA_MODEL_IDS = [
37
+ "claude-opus-4-8",
38
+ "gpt-5-2-codex",
39
+ "gpt-5-3-codex",
40
+ "gpt-5-5-pro",
41
+ "gemini-3-5-flash",
42
+ "gemma-3-12b",
43
+ "llama-4-maverick",
44
+ "meta-llama-3-3-70b-instruct",
45
+ "meta-llama-3-1-8b-instruct",
46
+ "qwen3-next-80b-a3b-instruct",
47
+ "qwen35-122b-a10b"
48
+ ];
49
+ //#endregion
50
+ export { NEON_EXTRA_MODEL_IDS, NEON_MODELS_DEV_IDS };
51
+
52
+ //# sourceMappingURL=neon-chat-options.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"neon-chat-options.js","names":[],"sources":["../../src/lib/neon-chat-options.ts"],"sourcesContent":["// Models served by the Neon AI Gateway. Anthropic and OpenAI models are routed\n// to their provider-native endpoints; everything else uses the unified MLflow\n// (OpenAI-compatible) endpoint.\n//\n// Ids use the canonical Neon (unprefixed) form, matching the `neon` provider on\n// models.dev. The gateway also accepts the legacy `databricks-` prefixed form\n// (the `databricks` provider on models.dev), which still resolves via the\n// `(string & {})` fallback on `NeonChatModelId`.\n//\n// `NEON_MODELS_DEV_IDS` mirrors the models.dev `neon` catalog exactly — the\n// `neon-catalog-drift.test.ts` maintainer check fails if the two diverge.\n// `NEON_EXTRA_MODEL_IDS` are additional ids the gateway serves that models.dev\n// does not (yet) list; they are kept for autocomplete and verified to resolve\n// against the gateway. The authoritative, always-current catalog is shown in\n// the Neon Console under the branch's \"AI Gateway\" tab.\n\n/** The models.dev `neon` catalog (canonical, unprefixed ids). */\nexport const NEON_MODELS_DEV_IDS = [\n\t// Anthropic (native Messages API)\n\t\"claude-opus-4-7\",\n\t\"claude-opus-4-6\",\n\t\"claude-opus-4-5\",\n\t\"claude-opus-4-1\",\n\t\"claude-sonnet-4-6\",\n\t\"claude-sonnet-4-5\",\n\t\"claude-sonnet-4\",\n\t\"claude-haiku-4-5\",\n\t// OpenAI (native Responses API)\n\t\"gpt-5\",\n\t\"gpt-5-mini\",\n\t\"gpt-5-nano\",\n\t\"gpt-5-1\",\n\t\"gpt-5-2\",\n\t\"gpt-5-4\",\n\t\"gpt-5-4-mini\",\n\t\"gpt-5-4-nano\",\n\t\"gpt-5-5\",\n\t// OpenAI open-weight (unified MLflow endpoint)\n\t\"gpt-oss-120b\",\n\t\"gpt-oss-20b\",\n\t// Google (unified MLflow endpoint)\n\t\"gemini-3-pro\",\n\t\"gemini-3-flash\",\n\t\"gemini-3-1-pro\",\n\t\"gemini-3-1-flash-lite\",\n\t\"gemini-2-5-pro\",\n\t\"gemini-2-5-flash\",\n] as const;\n\n/**\n * Ids the gateway serves that the models.dev `neon` provider does not list.\n * Verified to resolve against the gateway; retained for autocomplete. If\n * models.dev later lists one of these, the drift check flags it for promotion\n * into `NEON_MODELS_DEV_IDS`.\n */\nexport const NEON_EXTRA_MODEL_IDS = [\n\t// Anthropic (native Messages API)\n\t\"claude-opus-4-8\",\n\t// OpenAI (native Responses API) — Codex is served only natively\n\t\"gpt-5-2-codex\",\n\t\"gpt-5-3-codex\",\n\t\"gpt-5-5-pro\",\n\t// Google (unified MLflow endpoint)\n\t\"gemini-3-5-flash\",\n\t\"gemma-3-12b\",\n\t// Meta (unified MLflow endpoint)\n\t\"llama-4-maverick\",\n\t\"meta-llama-3-3-70b-instruct\",\n\t\"meta-llama-3-1-8b-instruct\",\n\t// Alibaba (unified MLflow endpoint)\n\t\"qwen3-next-80b-a3b-instruct\",\n\t\"qwen35-122b-a10b\",\n] as const;\n\n/** A known Neon AI Gateway model id (models.dev catalog + gateway extras). */\nexport type NeonKnownModelId =\n\t| (typeof NEON_MODELS_DEV_IDS)[number]\n\t| (typeof NEON_EXTRA_MODEL_IDS)[number];\n\n/**\n * A Neon AI Gateway model id. Known ids are listed for autocomplete; any other\n * id (e.g. a brand-new model, or the legacy `databricks-` prefixed form) is\n * accepted via the `(string & {})` fallback.\n */\nexport type NeonChatModelId = NeonKnownModelId | (string & {});\n"],"mappings":";;AAiBA,MAAa,sBAAsB;CAElC;CACA;CACA;CACA;CACA;CACA;CACA;CACA;CAEA;CACA;CACA;CACA;CACA;CACA;CACA;CACA;CACA;CAEA;CACA;CAEA;CACA;CACA;CACA;CACA;CACA;AACD;;;;;;;AAQA,MAAa,uBAAuB;CAEnC;CAEA;CACA;CACA;CAEA;CACA;CAEA;CACA;CACA;CAEA;CACA;AACD"}
@@ -1 +1 @@
1
- {"version":3,"file":"neon-model-capabilities.js","names":[],"sources":["../../src/lib/neon-model-capabilities.ts"],"sourcesContent":["export type NeonModelFamily =\n\t| \"anthropic\"\n\t| \"google\"\n\t| \"openai\"\n\t| \"meta\"\n\t| \"other\";\n\n/**\n * Which gateway endpoint a model should be routed to.\n *\n * - `anthropic`: native Messages API — streaming structured output + native reasoning.\n * - `openai`: native Responses API — models served only natively (e.g. Codex),\n * native reasoning, and the image-generation tool.\n * - `mlflow`: the unified, OpenAI-compatible endpoint (the fallback). Gemini is\n * routed here because the gateway's native Gemini endpoint does not support\n * streaming (`streamGenerateContent` is rejected).\n */\nexport type NeonModelRoute = \"anthropic\" | \"openai\" | \"mlflow\";\n\nexport function getNeonModelRoute(modelId: string): NeonModelRoute {\n\tconst id = modelId.toLowerCase();\n\tif (id.includes(\"claude\")) {\n\t\treturn \"anthropic\";\n\t}\n\t// OpenAI proprietary models (gpt-4/gpt-5 families, Codex) are served only via\n\t// the native Responses API. `gpt-oss` is open-weight and served on the\n\t// unified chat endpoint, so it is intentionally excluded here.\n\tif (\n\t\t(id.includes(\"gpt-\") && !id.includes(\"gpt-oss\")) ||\n\t\tid.includes(\"codex\")\n\t) {\n\t\treturn \"openai\";\n\t}\n\treturn \"mlflow\";\n}\n\nexport interface NeonModelCapabilities {\n\tfamily: NeonModelFamily;\n\tsupportsTemperature: boolean;\n\tsupportsTopP: boolean;\n\t/**\n\t * Whether `temperature` and `topP` may be sent together. Anthropic models\n\t * accept only one of the two.\n\t */\n\ttemperatureTopPMutuallyExclusive: boolean;\n\tsupportsPenalties: boolean;\n\tsupportsSeed: boolean;\n\tsupportsStopSequences: boolean;\n\tsupportsReasoningEffort: boolean;\n}\n\nconst PERMISSIVE: Omit<NeonModelCapabilities, \"family\"> = {\n\tsupportsTemperature: true,\n\tsupportsTopP: true,\n\ttemperatureTopPMutuallyExclusive: false,\n\tsupportsPenalties: true,\n\tsupportsSeed: true,\n\tsupportsStopSequences: true,\n\tsupportsReasoningEffort: true,\n};\n\n/**\n * Heuristic, prefix-based capability detection for MLflow-routed Neon models.\n *\n * The unified endpoint proxies to heterogeneous upstream providers, each of\n * which accepts a different subset of the OpenAI-style parameters the AI SDK\n * emits. Sending a parameter an upstream rejects results in a hard `400`, so we\n * strip the parameters a family is known to reject and surface a warning\n * instead. Unknown/untested models stay permissive (passed through unchanged).\n */\nexport function getNeonModelCapabilities(\n\tmodelId: string,\n): NeonModelCapabilities {\n\tconst id = modelId.toLowerCase();\n\n\t// Anthropic (Claude): rejects penalties and seed, accepts only one of\n\t// temperature/topP, and rejects the OpenAI `reasoning_effort` field.\n\tif (id.includes(\"claude\")) {\n\t\treturn {\n\t\t\tfamily: \"anthropic\",\n\t\t\tsupportsTemperature: true,\n\t\t\tsupportsTopP: true,\n\t\t\ttemperatureTopPMutuallyExclusive: true,\n\t\t\tsupportsPenalties: false,\n\t\t\tsupportsSeed: false,\n\t\t\tsupportsStopSequences: true,\n\t\t\tsupportsReasoningEffort: false,\n\t\t};\n\t}\n\n\t// Google (Gemini): accepts standard sampling params but rejects the OpenAI\n\t// `reasoning_effort` field (not part of Gemini's generation config).\n\tif (id.includes(\"gemini\")) {\n\t\treturn {\n\t\t\tfamily: \"google\",\n\t\t\t...PERMISSIVE,\n\t\t\tsupportsReasoningEffort: false,\n\t\t};\n\t}\n\n\t// OpenAI GPT-5 reasoning family (routed to the native Responses API). The\n\t// Responses model strips parameters the Responses API doesn't accept\n\t// (penalties, seed, stop), but its reasoning-model detection matches the bare\n\t// model id (`gpt-5`), which the gateway's `databricks-` prefix defeats. So we\n\t// only handle the temperature/topP restriction here: the original gpt-5 /\n\t// gpt-5-mini / gpt-5-nano require the default temperature and reject topP,\n\t// while gpt-5.1+ (a minor version digit follows) accept them again.\n\tif (/gpt-5/.test(id)) {\n\t\tconst hasMinorVersion = /gpt-5[.-]\\d/.test(id);\n\t\treturn {\n\t\t\tfamily: \"openai\",\n\t\t\tsupportsTemperature: hasMinorVersion,\n\t\t\tsupportsTopP: hasMinorVersion,\n\t\t\ttemperatureTopPMutuallyExclusive: false,\n\t\t\tsupportsPenalties: true,\n\t\t\tsupportsSeed: true,\n\t\t\tsupportsStopSequences: true,\n\t\t\tsupportsReasoningEffort: true,\n\t\t};\n\t}\n\n\t// Meta (Llama): rejects penalties and seed; accepts sampling params and stop.\n\tif (id.includes(\"llama\")) {\n\t\treturn {\n\t\t\tfamily: \"meta\",\n\t\t\tsupportsTemperature: true,\n\t\t\tsupportsTopP: true,\n\t\t\ttemperatureTopPMutuallyExclusive: false,\n\t\t\tsupportsPenalties: false,\n\t\t\tsupportsSeed: false,\n\t\t\tsupportsStopSequences: true,\n\t\t\tsupportsReasoningEffort: true,\n\t\t};\n\t}\n\n\treturn { family: \"other\", ...PERMISSIVE };\n}\n"],"mappings":";AAmBA,SAAgB,kBAAkB,SAAiC;CAClE,MAAM,KAAK,QAAQ,YAAY;CAC/B,IAAI,GAAG,SAAS,QAAQ,GACvB,OAAO;CAKR,IACE,GAAG,SAAS,MAAM,KAAK,CAAC,GAAG,SAAS,SAAS,KAC9C,GAAG,SAAS,OAAO,GAEnB,OAAO;CAER,OAAO;AACR;AAiBA,MAAM,aAAoD;CACzD,qBAAqB;CACrB,cAAc;CACd,kCAAkC;CAClC,mBAAmB;CACnB,cAAc;CACd,uBAAuB;CACvB,yBAAyB;AAC1B;;;;;;;;;;AAWA,SAAgB,yBACf,SACwB;CACxB,MAAM,KAAK,QAAQ,YAAY;CAI/B,IAAI,GAAG,SAAS,QAAQ,GACvB,OAAO;EACN,QAAQ;EACR,qBAAqB;EACrB,cAAc;EACd,kCAAkC;EAClC,mBAAmB;EACnB,cAAc;EACd,uBAAuB;EACvB,yBAAyB;CAC1B;CAKD,IAAI,GAAG,SAAS,QAAQ,GACvB,OAAO;EACN,QAAQ;EACR,GAAG;EACH,yBAAyB;CAC1B;CAUD,IAAI,QAAQ,KAAK,EAAE,GAAG;EACrB,MAAM,kBAAkB,cAAc,KAAK,EAAE;EAC7C,OAAO;GACN,QAAQ;GACR,qBAAqB;GACrB,cAAc;GACd,kCAAkC;GAClC,mBAAmB;GACnB,cAAc;GACd,uBAAuB;GACvB,yBAAyB;EAC1B;CACD;CAGA,IAAI,GAAG,SAAS,OAAO,GACtB,OAAO;EACN,QAAQ;EACR,qBAAqB;EACrB,cAAc;EACd,kCAAkC;EAClC,mBAAmB;EACnB,cAAc;EACd,uBAAuB;EACvB,yBAAyB;CAC1B;CAGD,OAAO;EAAE,QAAQ;EAAS,GAAG;CAAW;AACzC"}
1
+ {"version":3,"file":"neon-model-capabilities.js","names":[],"sources":["../../src/lib/neon-model-capabilities.ts"],"sourcesContent":["export type NeonModelFamily =\n\t| \"anthropic\"\n\t| \"google\"\n\t| \"openai\"\n\t| \"meta\"\n\t| \"other\";\n\n/**\n * Which gateway endpoint a model should be routed to.\n *\n * - `anthropic`: native Messages API — streaming structured output + native reasoning.\n * - `openai`: native Responses API — models served only natively (e.g. Codex),\n * native reasoning, and the image-generation tool.\n * - `mlflow`: the unified, OpenAI-compatible endpoint (the fallback). Gemini is\n * routed here because the gateway's native Gemini endpoint does not support\n * streaming (`streamGenerateContent` is rejected).\n */\nexport type NeonModelRoute = \"anthropic\" | \"openai\" | \"mlflow\";\n\nexport function getNeonModelRoute(modelId: string): NeonModelRoute {\n\tconst id = modelId.toLowerCase();\n\tif (id.includes(\"claude\")) {\n\t\treturn \"anthropic\";\n\t}\n\t// OpenAI proprietary models (gpt-4/gpt-5 families, Codex) are served only via\n\t// the native Responses API. `gpt-oss` is open-weight and served on the\n\t// unified chat endpoint, so it is intentionally excluded here.\n\tif (\n\t\t(id.includes(\"gpt-\") && !id.includes(\"gpt-oss\")) ||\n\t\tid.includes(\"codex\")\n\t) {\n\t\treturn \"openai\";\n\t}\n\treturn \"mlflow\";\n}\n\nexport interface NeonModelCapabilities {\n\tfamily: NeonModelFamily;\n\tsupportsTemperature: boolean;\n\tsupportsTopP: boolean;\n\t/**\n\t * Whether `temperature` and `topP` may be sent together. Anthropic models\n\t * accept only one of the two.\n\t */\n\ttemperatureTopPMutuallyExclusive: boolean;\n\tsupportsPenalties: boolean;\n\tsupportsSeed: boolean;\n\tsupportsStopSequences: boolean;\n\tsupportsReasoningEffort: boolean;\n}\n\nconst PERMISSIVE: Omit<NeonModelCapabilities, \"family\"> = {\n\tsupportsTemperature: true,\n\tsupportsTopP: true,\n\ttemperatureTopPMutuallyExclusive: false,\n\tsupportsPenalties: true,\n\tsupportsSeed: true,\n\tsupportsStopSequences: true,\n\tsupportsReasoningEffort: true,\n};\n\n/**\n * Heuristic, prefix-based capability detection for MLflow-routed Neon models.\n *\n * The unified endpoint proxies to heterogeneous upstream providers, each of\n * which accepts a different subset of the OpenAI-style parameters the AI SDK\n * emits. Sending a parameter an upstream rejects results in a hard `400`, so we\n * strip the parameters a family is known to reject and surface a warning\n * instead. Unknown/untested models stay permissive (passed through unchanged).\n */\nexport function getNeonModelCapabilities(\n\tmodelId: string,\n): NeonModelCapabilities {\n\tconst id = modelId.toLowerCase();\n\n\t// Anthropic (Claude): rejects penalties and seed, accepts only one of\n\t// temperature/topP, and rejects the OpenAI `reasoning_effort` field.\n\tif (id.includes(\"claude\")) {\n\t\treturn {\n\t\t\tfamily: \"anthropic\",\n\t\t\tsupportsTemperature: true,\n\t\t\tsupportsTopP: true,\n\t\t\ttemperatureTopPMutuallyExclusive: true,\n\t\t\tsupportsPenalties: false,\n\t\t\tsupportsSeed: false,\n\t\t\tsupportsStopSequences: true,\n\t\t\tsupportsReasoningEffort: false,\n\t\t};\n\t}\n\n\t// Google (Gemini): accepts standard sampling params but rejects the OpenAI\n\t// `reasoning_effort` field (not part of Gemini's generation config).\n\tif (id.includes(\"gemini\")) {\n\t\treturn {\n\t\t\tfamily: \"google\",\n\t\t\t...PERMISSIVE,\n\t\t\tsupportsReasoningEffort: false,\n\t\t};\n\t}\n\n\t// OpenAI GPT-5 reasoning family (routed to the native Responses API). The\n\t// Responses model strips parameters the Responses API doesn't accept\n\t// (penalties, seed, stop), but its reasoning-model detection matches the bare\n\t// model id (`gpt-5`), which the gateway's optional `databricks-` prefix can\n\t// defeat. So we only handle the temperature/topP restriction here: the\n\t// original gpt-5 / gpt-5-mini / gpt-5-nano require the default temperature and\n\t// reject topP, while gpt-5.1+ (a minor version digit follows) accept them\n\t// again. The regex matches both prefixed and unprefixed ids.\n\tif (/gpt-5/.test(id)) {\n\t\tconst hasMinorVersion = /gpt-5[.-]\\d/.test(id);\n\t\treturn {\n\t\t\tfamily: \"openai\",\n\t\t\tsupportsTemperature: hasMinorVersion,\n\t\t\tsupportsTopP: hasMinorVersion,\n\t\t\ttemperatureTopPMutuallyExclusive: false,\n\t\t\tsupportsPenalties: true,\n\t\t\tsupportsSeed: true,\n\t\t\tsupportsStopSequences: true,\n\t\t\tsupportsReasoningEffort: true,\n\t\t};\n\t}\n\n\t// Meta (Llama): rejects penalties and seed; accepts sampling params and stop.\n\tif (id.includes(\"llama\")) {\n\t\treturn {\n\t\t\tfamily: \"meta\",\n\t\t\tsupportsTemperature: true,\n\t\t\tsupportsTopP: true,\n\t\t\ttemperatureTopPMutuallyExclusive: false,\n\t\t\tsupportsPenalties: false,\n\t\t\tsupportsSeed: false,\n\t\t\tsupportsStopSequences: true,\n\t\t\tsupportsReasoningEffort: true,\n\t\t};\n\t}\n\n\treturn { family: \"other\", ...PERMISSIVE };\n}\n"],"mappings":";AAmBA,SAAgB,kBAAkB,SAAiC;CAClE,MAAM,KAAK,QAAQ,YAAY;CAC/B,IAAI,GAAG,SAAS,QAAQ,GACvB,OAAO;CAKR,IACE,GAAG,SAAS,MAAM,KAAK,CAAC,GAAG,SAAS,SAAS,KAC9C,GAAG,SAAS,OAAO,GAEnB,OAAO;CAER,OAAO;AACR;AAiBA,MAAM,aAAoD;CACzD,qBAAqB;CACrB,cAAc;CACd,kCAAkC;CAClC,mBAAmB;CACnB,cAAc;CACd,uBAAuB;CACvB,yBAAyB;AAC1B;;;;;;;;;;AAWA,SAAgB,yBACf,SACwB;CACxB,MAAM,KAAK,QAAQ,YAAY;CAI/B,IAAI,GAAG,SAAS,QAAQ,GACvB,OAAO;EACN,QAAQ;EACR,qBAAqB;EACrB,cAAc;EACd,kCAAkC;EAClC,mBAAmB;EACnB,cAAc;EACd,uBAAuB;EACvB,yBAAyB;CAC1B;CAKD,IAAI,GAAG,SAAS,QAAQ,GACvB,OAAO;EACN,QAAQ;EACR,GAAG;EACH,yBAAyB;CAC1B;CAWD,IAAI,QAAQ,KAAK,EAAE,GAAG;EACrB,MAAM,kBAAkB,cAAc,KAAK,EAAE;EAC7C,OAAO;GACN,QAAQ;GACR,qBAAqB;GACrB,cAAc;GACd,kCAAkC;GAClC,mBAAmB;GACnB,cAAc;GACd,uBAAuB;GACvB,yBAAyB;EAC1B;CACD;CAGA,IAAI,GAAG,SAAS,OAAO,GACtB,OAAO;EACN,QAAQ;EACR,qBAAqB;EACrB,cAAc;EACd,kCAAkC;EAClC,mBAAmB;EACnB,cAAc;EACd,uBAAuB;EACvB,yBAAyB;CAC1B;CAGD,OAAO;EAAE,QAAQ;EAAS,GAAG;CAAW;AACzC"}
@@ -1,5 +1,5 @@
1
1
  import { OpenAIResponsesLanguageModel } from "@ai-sdk/openai/internal";
2
- import { LanguageModelV4, LanguageModelV4CallOptions, LanguageModelV4GenerateResult, LanguageModelV4StreamResult } from "@ai-sdk/provider";
2
+ import { LanguageModelV3, LanguageModelV3CallOptions, LanguageModelV3GenerateResult, LanguageModelV3StreamResult } from "@ai-sdk/provider";
3
3
 
4
4
  //#region src/lib/neon-responses-language-model.d.ts
5
5
 
@@ -10,16 +10,17 @@ import { LanguageModelV4, LanguageModelV4CallOptions, LanguageModelV4GenerateRes
10
10
  * reasoning and the image-generation tool.
11
11
  *
12
12
  * The shared OpenAI Responses model shapes a request based on whether the model
13
- * is a reasoning model, but it detects that from the bare model id (`gpt-5`),
14
- * which the gateway's required `databricks-` prefix defeats. For the GPT-5
15
- * reasoning family we set the model's own `forceReasoning` provider option so it
16
- * applies the correct reasoning behavior. Users can still override it.
13
+ * is a reasoning model, but its detection is brittle here: the gateway also
14
+ * accepts the legacy `databricks-` prefix, which defeats the upstream bare-id
15
+ * (`gpt-5`) match. For the GPT-5 reasoning family we set the model's own
16
+ * `forceReasoning` provider option so it applies the correct reasoning behavior
17
+ * for both id forms. Users can still override it.
17
18
  */
18
- declare class NeonResponsesLanguageModel extends OpenAIResponsesLanguageModel implements LanguageModelV4 {
19
+ declare class NeonResponsesLanguageModel extends OpenAIResponsesLanguageModel implements LanguageModelV3 {
19
20
  private get isReasoningFamily();
20
21
  private withForcedReasoning;
21
- doGenerate(options: LanguageModelV4CallOptions): Promise<LanguageModelV4GenerateResult>;
22
- doStream(options: LanguageModelV4CallOptions): Promise<LanguageModelV4StreamResult>;
22
+ doGenerate(options: LanguageModelV3CallOptions): Promise<LanguageModelV3GenerateResult>;
23
+ doStream(options: LanguageModelV3CallOptions): Promise<LanguageModelV3StreamResult>;
23
24
  }
24
25
  //#endregion
25
26
  export { NeonResponsesLanguageModel };
@@ -1 +1 @@
1
- {"version":3,"file":"neon-responses-language-model.d.ts","names":[],"sources":["../../src/lib/neon-responses-language-model.ts"],"mappings":";;;;;;;AAoBA;;;;;;;;;;AAE2B,cAFd,0BAAA,SACJ,4BAAA,YACG,eAAe,CAAA;;;sBA2BhB,6BACP,QAAQ;oBAKD,6BACP,QAAQ"}
1
+ {"version":3,"file":"neon-responses-language-model.d.ts","names":[],"sources":["../../src/lib/neon-responses-language-model.ts"],"mappings":";;;;;;;AAqBA;;;;;;;;;;AAE2B;cAFd,0BAAA,SACJ,4BAAA,YACG;;;sBA2BD,6BACP,QAAQ;oBAKD,6BACP,QAAQ"}
@@ -7,10 +7,11 @@ import { OpenAIResponsesLanguageModel } from "@ai-sdk/openai/internal";
7
7
  * reasoning and the image-generation tool.
8
8
  *
9
9
  * The shared OpenAI Responses model shapes a request based on whether the model
10
- * is a reasoning model, but it detects that from the bare model id (`gpt-5`),
11
- * which the gateway's required `databricks-` prefix defeats. For the GPT-5
12
- * reasoning family we set the model's own `forceReasoning` provider option so it
13
- * applies the correct reasoning behavior. Users can still override it.
10
+ * is a reasoning model, but its detection is brittle here: the gateway also
11
+ * accepts the legacy `databricks-` prefix, which defeats the upstream bare-id
12
+ * (`gpt-5`) match. For the GPT-5 reasoning family we set the model's own
13
+ * `forceReasoning` provider option so it applies the correct reasoning behavior
14
+ * for both id forms. Users can still override it.
14
15
  */
15
16
  var NeonResponsesLanguageModel = class extends OpenAIResponsesLanguageModel {
16
17
  get isReasoningFamily() {
@@ -1 +1 @@
1
- {"version":3,"file":"neon-responses-language-model.js","names":[],"sources":["../../src/lib/neon-responses-language-model.ts"],"sourcesContent":["import { OpenAIResponsesLanguageModel } from \"@ai-sdk/openai/internal\";\nimport type {\n\tLanguageModelV4,\n\tLanguageModelV4CallOptions,\n\tLanguageModelV4GenerateResult,\n\tLanguageModelV4StreamResult,\n} from \"@ai-sdk/provider\";\n\n/**\n * Language model for OpenAI models served via the Neon AI Gateway's native\n * Responses API (`/ai-gateway/openai/v1/responses`). This route is required for\n * models that are only served natively (e.g. Codex) and unlocks native\n * reasoning and the image-generation tool.\n *\n * The shared OpenAI Responses model shapes a request based on whether the model\n * is a reasoning model, but it detects that from the bare model id (`gpt-5`),\n * which the gateway's required `databricks-` prefix defeats. For the GPT-5\n * reasoning family we set the model's own `forceReasoning` provider option so it\n * applies the correct reasoning behavior. Users can still override it.\n */\nexport class NeonResponsesLanguageModel\n\textends OpenAIResponsesLanguageModel\n\timplements LanguageModelV4\n{\n\tprivate get isReasoningFamily(): boolean {\n\t\treturn /gpt-5/.test(this.modelId.toLowerCase());\n\t}\n\n\tprivate withForcedReasoning(\n\t\toptions: LanguageModelV4CallOptions,\n\t): LanguageModelV4CallOptions {\n\t\tif (!this.isReasoningFamily) {\n\t\t\treturn options;\n\t\t}\n\t\tconst openai = options.providerOptions?.openai;\n\t\t// Respect an explicit user setting.\n\t\tif (openai != null && \"forceReasoning\" in openai) {\n\t\t\treturn options;\n\t\t}\n\t\treturn {\n\t\t\t...options,\n\t\t\tproviderOptions: {\n\t\t\t\t...options.providerOptions,\n\t\t\t\topenai: { ...openai, forceReasoning: true },\n\t\t\t},\n\t\t};\n\t}\n\n\toverride doGenerate(\n\t\toptions: LanguageModelV4CallOptions,\n\t): Promise<LanguageModelV4GenerateResult> {\n\t\treturn super.doGenerate(this.withForcedReasoning(options));\n\t}\n\n\toverride doStream(\n\t\toptions: LanguageModelV4CallOptions,\n\t): Promise<LanguageModelV4StreamResult> {\n\t\treturn super.doStream(this.withForcedReasoning(options));\n\t}\n}\n"],"mappings":";;;;;;;;;;;;;;AAoBA,IAAa,6BAAb,cACS,6BAET;CACC,IAAY,oBAA6B;EACxC,OAAO,QAAQ,KAAK,KAAK,QAAQ,YAAY,CAAC;CAC/C;CAEA,oBACC,SAC6B;EAC7B,IAAI,CAAC,KAAK,mBACT,OAAO;EAER,MAAM,SAAS,QAAQ,iBAAiB;EAExC,IAAI,UAAU,QAAQ,oBAAoB,QACzC,OAAO;EAER,OAAO;GACN,GAAG;GACH,iBAAiB;IAChB,GAAG,QAAQ;IACX,QAAQ;KAAE,GAAG;KAAQ,gBAAgB;IAAK;GAC3C;EACD;CACD;CAEA,WACC,SACyC;EACzC,OAAO,MAAM,WAAW,KAAK,oBAAoB,OAAO,CAAC;CAC1D;CAEA,SACC,SACuC;EACvC,OAAO,MAAM,SAAS,KAAK,oBAAoB,OAAO,CAAC;CACxD;AACD"}
1
+ {"version":3,"file":"neon-responses-language-model.js","names":[],"sources":["../../src/lib/neon-responses-language-model.ts"],"sourcesContent":["import { OpenAIResponsesLanguageModel } from \"@ai-sdk/openai/internal\";\nimport type {\n\tLanguageModelV3,\n\tLanguageModelV3CallOptions,\n\tLanguageModelV3GenerateResult,\n\tLanguageModelV3StreamResult,\n} from \"@ai-sdk/provider\";\n\n/**\n * Language model for OpenAI models served via the Neon AI Gateway's native\n * Responses API (`/ai-gateway/openai/v1/responses`). This route is required for\n * models that are only served natively (e.g. Codex) and unlocks native\n * reasoning and the image-generation tool.\n *\n * The shared OpenAI Responses model shapes a request based on whether the model\n * is a reasoning model, but its detection is brittle here: the gateway also\n * accepts the legacy `databricks-` prefix, which defeats the upstream bare-id\n * (`gpt-5`) match. For the GPT-5 reasoning family we set the model's own\n * `forceReasoning` provider option so it applies the correct reasoning behavior\n * for both id forms. Users can still override it.\n */\nexport class NeonResponsesLanguageModel\n\textends OpenAIResponsesLanguageModel\n\timplements LanguageModelV3\n{\n\tprivate get isReasoningFamily(): boolean {\n\t\treturn /gpt-5/.test(this.modelId.toLowerCase());\n\t}\n\n\tprivate withForcedReasoning(\n\t\toptions: LanguageModelV3CallOptions,\n\t): LanguageModelV3CallOptions {\n\t\tif (!this.isReasoningFamily) {\n\t\t\treturn options;\n\t\t}\n\t\tconst openai = options.providerOptions?.openai;\n\t\t// Respect an explicit user setting.\n\t\tif (openai != null && \"forceReasoning\" in openai) {\n\t\t\treturn options;\n\t\t}\n\t\treturn {\n\t\t\t...options,\n\t\t\tproviderOptions: {\n\t\t\t\t...options.providerOptions,\n\t\t\t\topenai: { ...openai, forceReasoning: true },\n\t\t\t},\n\t\t};\n\t}\n\n\toverride doGenerate(\n\t\toptions: LanguageModelV3CallOptions,\n\t): Promise<LanguageModelV3GenerateResult> {\n\t\treturn super.doGenerate(this.withForcedReasoning(options));\n\t}\n\n\toverride doStream(\n\t\toptions: LanguageModelV3CallOptions,\n\t): Promise<LanguageModelV3StreamResult> {\n\t\treturn super.doStream(this.withForcedReasoning(options));\n\t}\n}\n"],"mappings":";;;;;;;;;;;;;;;AAqBA,IAAa,6BAAb,cACS,6BAET;CACC,IAAY,oBAA6B;EACxC,OAAO,QAAQ,KAAK,KAAK,QAAQ,YAAY,CAAC;CAC/C;CAEA,oBACC,SAC6B;EAC7B,IAAI,CAAC,KAAK,mBACT,OAAO;EAER,MAAM,SAAS,QAAQ,iBAAiB;EAExC,IAAI,UAAU,QAAQ,oBAAoB,QACzC,OAAO;EAER,OAAO;GACN,GAAG;GACH,iBAAiB;IAChB,GAAG,QAAQ;IACX,QAAQ;KAAE,GAAG;KAAQ,gBAAgB;IAAK;GAC3C;EACD;CACD;CAEA,WACC,SACyC;EACzC,OAAO,MAAM,WAAW,KAAK,oBAAoB,OAAO,CAAC;CAC1D;CAEA,SACC,SACuC;EACvC,OAAO,MAAM,SAAS,KAAK,oBAAoB,OAAO,CAAC;CACxD;AACD"}
@@ -1,9 +1,11 @@
1
1
  import { NeonChatModelId } from "./neon-chat-options.js";
2
+ import { openai } from "@ai-sdk/openai";
3
+ import { LanguageModelV3, ProviderV3 } from "@ai-sdk/provider";
2
4
  import { FetchFunction } from "@ai-sdk/provider-utils";
3
- import { LanguageModelV4, ProviderV4 } from "@ai-sdk/provider";
4
5
  import { z } from "zod/v4";
5
6
 
6
7
  //#region src/lib/provider.d.ts
8
+
7
9
  declare const neonErrorSchema: z.ZodObject<{
8
10
  error: z.ZodObject<{
9
11
  message: z.ZodString;
@@ -30,13 +32,15 @@ interface NeonProviderSettings {
30
32
  /** Custom fetch implementation (e.g. for testing or middleware). */
31
33
  fetch?: FetchFunction;
32
34
  }
33
- interface NeonProvider extends ProviderV4 {
35
+ interface NeonProvider extends ProviderV3 {
34
36
  /** Creates a Neon AI Gateway model for text generation. */
35
- (modelId: NeonChatModelId): LanguageModelV4;
37
+ (modelId: NeonChatModelId): LanguageModelV3;
36
38
  /** Creates a Neon AI Gateway model for text generation. */
37
- languageModel(modelId: NeonChatModelId): LanguageModelV4;
39
+ languageModel(modelId: NeonChatModelId): LanguageModelV3;
38
40
  /** Creates a Neon AI Gateway chat model for text generation. */
39
- chat(modelId: NeonChatModelId): LanguageModelV4;
41
+ chat(modelId: NeonChatModelId): LanguageModelV3;
42
+ /** OpenAI Responses tools (e.g. `imageGeneration`) for OpenAI-routed models. */
43
+ tools: typeof openai.tools;
40
44
  /** @deprecated Use `embeddingModel` instead. */
41
45
  textEmbeddingModel(modelId: string): never;
42
46
  }
@@ -1 +1 @@
1
- {"version":3,"file":"provider.d.ts","names":[],"sources":["../../src/lib/provider.ts"],"mappings":";;;;;;cAiCM,iBAAe,CAAA,CAAA;;IAAf,OAAA,aAOJ;IAAA,IAAA,eAAA,cAAA,YAAA,CAAA,CAAA;;;;;KAEU,aAAA,GAAgB,CAAA,CAAE,aAAa;UA4C1B,oBAAA;;;;;;;;;AArDI;AASrB;EAAyB,MAAA,CAAA,EAAA,MAAA;;SAAK,CAAA,EA2DnB,MA3DmB,CAAA,MAAA,EAAA,MAAA,CAAA;EAAK;EA4ClB,KAAA,CAAA,EAkBR,aAlBQ;;AAeN,UAMM,YAAA,SAAqB,UAN3B,CAAA;;EAGW,CAAA,OAAA,EAKX,eALW,CAAA,EAKO,eALP;EAGL;EAAa,aAAA,CAAA,OAAA,EAKN,eALM,CAAA,EAKY,eALZ;;MAED,CAAA,OAAA,EAMd,eANc,CAAA,EAMI,eANJ;;oBAGa,CAAA,OAAA,EAAA,MAAA,CAAA,EAAA,KAAA;;AAGT,iBAMjB,UAAA,CANiB,OAAA,CAAA,EAMG,oBANH,CAAA,EAM+B,YAN/B;;AARe,cAuGnC,IAvGmC,EAuG/B,YAvG+B"}
1
+ {"version":3,"file":"provider.d.ts","names":[],"sources":["../../src/lib/provider.ts"],"mappings":";;;;;;;;cAmCM,iBAAe,CAAA,CAAA;;;;;IAAA,IAAA,eAAA,cAAA,aAAA,CAAA,CAAA;EAAA,CAAA,eAAA,CAAA;AASrB,CAAA,eAAY,CAAA;AAAa,KAAb,aAAA,GAAgB,CAAA,CAAE,KAAL,CAAA,OAAkB,eAAlB,CAAA;AAAkB,UA4C1B,oBAAA,CA5C0B;;AAAR;AA4CnC;;;SAkBS,CAAA,EAAA,MAAA;EAAa;AAGtB;;;QAE6B,CAAA,EAAA,MAAA;;SAGa,CAAA,EAX/B,MAW+B,CAAA,MAAA,EAAA,MAAA,CAAA;;OAGT,CAAA,EAXxB,aAWwB;;AARK,UAArB,YAAA,SAAqB,UAAA,CAAA;EAAU;EAiBhC,CAAA,OAAA,EAfL,eAee,CAAA,EAfG,eAeH;EAAA;eAAU,CAAA,OAAA,EAZZ,eAYY,CAAA,EAZM,eAYN;;EAAwC,IAAA,CAAA,OAAA,EAT7D,eAS6D,CAAA,EAT3C,eAS2C;EA0F/D;gBAhGE,MAAA,CAAe;;;;iBAMd,UAAA,WAAoB,uBAA4B;;cA0FnD,MAAI"}
@@ -3,10 +3,23 @@ import { getNeonModelRoute } from "./neon-model-capabilities.js";
3
3
  import { NeonChatLanguageModel } from "./neon-chat-language-model.js";
4
4
  import { NeonResponsesLanguageModel } from "./neon-responses-language-model.js";
5
5
  import { VERSION } from "./version.js";
6
- import { generateId, loadApiKey, loadSetting, withUserAgentSuffix, withoutTrailingSlash } from "@ai-sdk/provider-utils";
6
+ import { openai } from "@ai-sdk/openai";
7
7
  import { NoSuchModelError } from "@ai-sdk/provider";
8
+ import { generateId, loadApiKey, loadSetting, withUserAgentSuffix, withoutTrailingSlash } from "@ai-sdk/provider-utils";
8
9
  import { z } from "zod/v4";
9
10
  //#region src/lib/provider.ts
11
+ /**
12
+ * Community Vercel AI SDK provider for the Neon AI Gateway.
13
+ *
14
+ * `createNeon()` returns a provider that routes each model to the best gateway
15
+ * endpoint based on its id (Anthropic → native Messages, OpenAI → native
16
+ * Responses incl. Codex, everything else → unified MLflow), so a single
17
+ * `neon('claude-...')` call (same base URL + token) reaches the whole catalog.
18
+ * Ids use the canonical Neon (unprefixed) form; the legacy `databricks-` prefix
19
+ * is also accepted. Configure with the branch-scoped `NEON_AI_GATEWAY_BASE_URL` +
20
+ * `NEON_AI_GATEWAY_TOKEN` emitted by `neonctl env pull` / `neon dev`, or pass
21
+ * `baseURL` / `apiKey` explicitly.
22
+ */
10
23
  const neonErrorStructure = {
11
24
  errorSchema: z.object({ error: z.object({
12
25
  message: z.string(),
@@ -86,9 +99,10 @@ function createNeon(options = {}) {
86
99
  }
87
100
  };
88
101
  const provider = (modelId) => createLanguageModel(modelId);
89
- provider.specificationVersion = "v4";
102
+ provider.specificationVersion = "v3";
90
103
  provider.languageModel = createLanguageModel;
91
104
  provider.chat = createLanguageModel;
105
+ provider.tools = openai.tools;
92
106
  provider.embeddingModel = (modelId) => {
93
107
  throw new NoSuchModelError({
94
108
  modelId,
@@ -1 +1 @@
1
- {"version":3,"file":"provider.js","names":[],"sources":["../../src/lib/provider.ts"],"sourcesContent":["/**\n * Community Vercel AI SDK provider for the Neon AI Gateway.\n *\n * `createNeon()` returns a provider that routes each model to the best gateway\n * endpoint based on its id (Anthropic → native Messages, OpenAI → native\n * Responses incl. Codex, everything else → unified MLflow), so a single\n * `neon('databricks-...')` call (same base URL + token) reaches the whole\n * catalog. Configure with the branch-scoped `NEON_AI_GATEWAY_BASE_URL` +\n * `NEON_AI_GATEWAY_TOKEN` emitted by `neonctl env pull` / `neon dev`, or pass\n * `baseURL` / `apiKey` explicitly.\n */\nimport type { ProviderErrorStructure } from \"@ai-sdk/openai-compatible\";\nimport {\n\ttype LanguageModelV4,\n\tNoSuchModelError,\n\ttype ProviderV4,\n} from \"@ai-sdk/provider\";\nimport {\n\ttype FetchFunction,\n\tgenerateId,\n\tloadApiKey,\n\tloadSetting,\n\twithoutTrailingSlash,\n\twithUserAgentSuffix,\n} from \"@ai-sdk/provider-utils\";\nimport { z } from \"zod/v4\";\nimport { NeonAnthropicLanguageModel } from \"./neon-anthropic-language-model.js\";\nimport { NeonChatLanguageModel } from \"./neon-chat-language-model.js\";\nimport type { NeonChatModelId } from \"./neon-chat-options.js\";\nimport { getNeonModelRoute } from \"./neon-model-capabilities.js\";\nimport { NeonResponsesLanguageModel } from \"./neon-responses-language-model.js\";\nimport { VERSION } from \"./version.js\";\n\nconst neonErrorSchema = z.object({\n\terror: z.object({\n\t\tmessage: z.string(),\n\t\ttype: z.string().nullish(),\n\t\tparam: z.unknown().nullish(),\n\t\tcode: z.unknown().nullish(),\n\t}),\n});\n\nexport type NeonErrorData = z.infer<typeof neonErrorSchema>;\n\nconst neonErrorStructure: ProviderErrorStructure<NeonErrorData> = {\n\terrorSchema: neonErrorSchema,\n\terrorToMessage: (data) => data.error.message,\n};\n\n/**\n * Recursively remove the JSON Schema `$schema` marker, which some gateway\n * backends (notably Gemini) reject in tool/structured-output schemas. Other\n * backends ignore its absence, so stripping it everywhere is safe.\n */\nfunction stripJsonSchemaMarker(value: unknown): unknown {\n\tif (Array.isArray(value)) {\n\t\treturn value.map(stripJsonSchemaMarker);\n\t}\n\tif (value !== null && typeof value === \"object\") {\n\t\tconst result: Record<string, unknown> = {};\n\t\tfor (const [key, entry] of Object.entries(value)) {\n\t\t\tif (key === \"$schema\") {\n\t\t\t\tcontinue;\n\t\t\t}\n\t\t\tresult[key] = stripJsonSchemaMarker(entry);\n\t\t}\n\t\treturn result;\n\t}\n\treturn value;\n}\n\nfunction transformNeonRequestBody(\n\targs: Record<string, unknown>,\n): Record<string, unknown> {\n\tconst transformed = { ...args };\n\tif (transformed.tools != null) {\n\t\ttransformed.tools = stripJsonSchemaMarker(transformed.tools);\n\t}\n\tif (transformed.response_format != null) {\n\t\ttransformed.response_format = stripJsonSchemaMarker(\n\t\t\ttransformed.response_format,\n\t\t);\n\t}\n\treturn transformed;\n}\n\nexport interface NeonProviderSettings {\n\t/**\n\t * Neon AI Gateway base URL — the branch-scoped host root, e.g.\n\t * `https://<branch-id>-api.ai.<region>.aws.neon.tech`. The gateway paths are\n\t * appended internally. Falls back to the `NEON_AI_GATEWAY_BASE_URL` env var.\n\t */\n\tbaseURL?: string;\n\n\t/**\n\t * Neon AI Gateway platform token (the `nt_live_...` value). Falls back to the\n\t * `NEON_AI_GATEWAY_TOKEN` env var.\n\t */\n\tapiKey?: string;\n\n\t/** Custom headers to include in the requests. */\n\theaders?: Record<string, string>;\n\n\t/** Custom fetch implementation (e.g. for testing or middleware). */\n\tfetch?: FetchFunction;\n}\n\nexport interface NeonProvider extends ProviderV4 {\n\t/** Creates a Neon AI Gateway model for text generation. */\n\t(modelId: NeonChatModelId): LanguageModelV4;\n\n\t/** Creates a Neon AI Gateway model for text generation. */\n\tlanguageModel(modelId: NeonChatModelId): LanguageModelV4;\n\n\t/** Creates a Neon AI Gateway chat model for text generation. */\n\tchat(modelId: NeonChatModelId): LanguageModelV4;\n\n\t/** @deprecated Use `embeddingModel` instead. */\n\ttextEmbeddingModel(modelId: string): never;\n}\n\nexport function createNeon(options: NeonProviderSettings = {}): NeonProvider {\n\t// Resolved lazily so that `createNeon()` and the default `neon` instance do\n\t// not throw at import time when configuration comes from the environment.\n\tconst getHost = () =>\n\t\twithoutTrailingSlash(\n\t\t\tloadSetting({\n\t\t\t\tsettingValue: options.baseURL,\n\t\t\t\tenvironmentVariableName: \"NEON_AI_GATEWAY_BASE_URL\",\n\t\t\t\tsettingName: \"baseURL\",\n\t\t\t\tdescription: \"Neon AI Gateway base URL\",\n\t\t\t}),\n\t\t);\n\n\tconst getHeaders = (extra?: Record<string, string>) =>\n\t\twithUserAgentSuffix(\n\t\t\t{\n\t\t\t\tAuthorization: `Bearer ${loadApiKey({\n\t\t\t\t\tapiKey: options.apiKey,\n\t\t\t\t\tenvironmentVariableName: \"NEON_AI_GATEWAY_TOKEN\",\n\t\t\t\t\tdescription: \"Neon AI Gateway token\",\n\t\t\t\t})}`,\n\t\t\t\t...extra,\n\t\t\t\t...options.headers,\n\t\t\t},\n\t\t\t`neondatabase/ai-sdk-provider/${VERSION}`,\n\t\t);\n\n\t// Anthropic models -> native Messages API.\n\tconst createAnthropicModel = (modelId: NeonChatModelId) =>\n\t\tnew NeonAnthropicLanguageModel(modelId, {\n\t\t\tprovider: \"neon.anthropic\",\n\t\t\tbaseURL: `${getHost()}/ai-gateway/anthropic/v1`,\n\t\t\theaders: () => getHeaders({ \"anthropic-version\": \"2023-06-01\" }),\n\t\t\tfetch: options.fetch,\n\t\t\tgenerateId,\n\t\t});\n\n\t// OpenAI models (incl. Codex, only served natively) -> Responses API.\n\tconst createOpenAIModel = (modelId: NeonChatModelId) =>\n\t\tnew NeonResponsesLanguageModel(modelId, {\n\t\t\tprovider: \"neon.openai.responses\",\n\t\t\turl: ({ path }) => `${getHost()}/ai-gateway/openai/v1${path}`,\n\t\t\theaders: getHeaders,\n\t\t\tfetch: options.fetch,\n\t\t\tfileIdPrefixes: [\"file-\"],\n\t\t});\n\n\t// Everything else (Gemini, Llama, Qwen, gpt-oss, ...) -> unified MLflow\n\t// endpoint. Gemini is here because its native endpoint can't stream.\n\tconst createChatModel = (modelId: NeonChatModelId) =>\n\t\tnew NeonChatLanguageModel(modelId, {\n\t\t\tprovider: \"neon.chat\",\n\t\t\turl: ({ path }) => `${getHost()}/ai-gateway/mlflow/v1${path}`,\n\t\t\theaders: getHeaders,\n\t\t\tfetch: options.fetch,\n\t\t\terrorStructure: neonErrorStructure,\n\t\t\ttransformRequestBody: transformNeonRequestBody,\n\t\t\tsupportsStructuredOutputs: true,\n\t\t});\n\n\tconst createLanguageModel = (modelId: NeonChatModelId): LanguageModelV4 => {\n\t\tswitch (getNeonModelRoute(modelId)) {\n\t\t\tcase \"anthropic\":\n\t\t\t\treturn createAnthropicModel(modelId);\n\t\t\tcase \"openai\":\n\t\t\t\treturn createOpenAIModel(modelId);\n\t\t\tdefault:\n\t\t\t\treturn createChatModel(modelId);\n\t\t}\n\t};\n\n\tconst provider = (modelId: NeonChatModelId) => createLanguageModel(modelId);\n\n\tprovider.specificationVersion = \"v4\" as const;\n\tprovider.languageModel = createLanguageModel;\n\tprovider.chat = createLanguageModel;\n\n\tprovider.embeddingModel = (modelId: string) => {\n\t\tthrow new NoSuchModelError({ modelId, modelType: \"embeddingModel\" });\n\t};\n\tprovider.textEmbeddingModel = provider.embeddingModel;\n\tprovider.imageModel = (modelId: string) => {\n\t\tthrow new NoSuchModelError({ modelId, modelType: \"imageModel\" });\n\t};\n\n\treturn provider;\n}\n\n/** Default Neon provider instance (reads `NEON_AI_GATEWAY_*` env vars). */\nexport const neon = createNeon();\n"],"mappings":";;;;;;;;;AA4CA,MAAM,qBAA4D;CACjE,aAZuB,EAAE,OAAO,EAChC,OAAO,EAAE,OAAO;EACf,SAAS,EAAE,OAAO;EAClB,MAAM,EAAE,OAAO,CAAC,CAAC,QAAQ;EACzB,OAAO,EAAE,QAAQ,CAAC,CAAC,QAAQ;EAC3B,MAAM,EAAE,QAAQ,CAAC,CAAC,QAAQ;CAC3B,CAAC,EACF,CAK4B;CAC3B,iBAAiB,SAAS,KAAK,MAAM;AACtC;;;;;;AAOA,SAAS,sBAAsB,OAAyB;CACvD,IAAI,MAAM,QAAQ,KAAK,GACtB,OAAO,MAAM,IAAI,qBAAqB;CAEvC,IAAI,UAAU,QAAQ,OAAO,UAAU,UAAU;EAChD,MAAM,SAAkC,CAAC;EACzC,KAAK,MAAM,CAAC,KAAK,UAAU,OAAO,QAAQ,KAAK,GAAG;GACjD,IAAI,QAAQ,WACX;GAED,OAAO,OAAO,sBAAsB,KAAK;EAC1C;EACA,OAAO;CACR;CACA,OAAO;AACR;AAEA,SAAS,yBACR,MAC0B;CAC1B,MAAM,cAAc,EAAE,GAAG,KAAK;CAC9B,IAAI,YAAY,SAAS,MACxB,YAAY,QAAQ,sBAAsB,YAAY,KAAK;CAE5D,IAAI,YAAY,mBAAmB,MAClC,YAAY,kBAAkB,sBAC7B,YAAY,eACb;CAED,OAAO;AACR;AAqCA,SAAgB,WAAW,UAAgC,CAAC,GAAiB;CAG5E,MAAM,gBACL,qBACC,YAAY;EACX,cAAc,QAAQ;EACtB,yBAAyB;EACzB,aAAa;EACb,aAAa;CACd,CAAC,CACF;CAED,MAAM,cAAc,UACnB,oBACC;EACC,eAAe,UAAU,WAAW;GACnC,QAAQ,QAAQ;GAChB,yBAAyB;GACzB,aAAa;EACd,CAAC;EACD,GAAG;EACH,GAAG,QAAQ;CACZ,GACA,gCAAgC,SACjC;CAGD,MAAM,wBAAwB,YAC7B,IAAI,2BAA2B,SAAS;EACvC,UAAU;EACV,SAAS,GAAG,QAAQ,EAAE;EACtB,eAAe,WAAW,EAAE,qBAAqB,aAAa,CAAC;EAC/D,OAAO,QAAQ;EACf;CACD,CAAC;CAGF,MAAM,qBAAqB,YAC1B,IAAI,2BAA2B,SAAS;EACvC,UAAU;EACV,MAAM,EAAE,WAAW,GAAG,QAAQ,EAAE,uBAAuB;EACvD,SAAS;EACT,OAAO,QAAQ;EACf,gBAAgB,CAAC,OAAO;CACzB,CAAC;CAIF,MAAM,mBAAmB,YACxB,IAAI,sBAAsB,SAAS;EAClC,UAAU;EACV,MAAM,EAAE,WAAW,GAAG,QAAQ,EAAE,uBAAuB;EACvD,SAAS;EACT,OAAO,QAAQ;EACf,gBAAgB;EAChB,sBAAsB;EACtB,2BAA2B;CAC5B,CAAC;CAEF,MAAM,uBAAuB,YAA8C;EAC1E,QAAQ,kBAAkB,OAAO,GAAjC;GACC,KAAK,aACJ,OAAO,qBAAqB,OAAO;GACpC,KAAK,UACJ,OAAO,kBAAkB,OAAO;GACjC,SACC,OAAO,gBAAgB,OAAO;EAChC;CACD;CAEA,MAAM,YAAY,YAA6B,oBAAoB,OAAO;CAE1E,SAAS,uBAAuB;CAChC,SAAS,gBAAgB;CACzB,SAAS,OAAO;CAEhB,SAAS,kBAAkB,YAAoB;EAC9C,MAAM,IAAI,iBAAiB;GAAE;GAAS,WAAW;EAAiB,CAAC;CACpE;CACA,SAAS,qBAAqB,SAAS;CACvC,SAAS,cAAc,YAAoB;EAC1C,MAAM,IAAI,iBAAiB;GAAE;GAAS,WAAW;EAAa,CAAC;CAChE;CAEA,OAAO;AACR;;AAGA,MAAa,OAAO,WAAW"}
1
+ {"version":3,"file":"provider.js","names":["openaiProvider"],"sources":["../../src/lib/provider.ts"],"sourcesContent":["/**\n * Community Vercel AI SDK provider for the Neon AI Gateway.\n *\n * `createNeon()` returns a provider that routes each model to the best gateway\n * endpoint based on its id (Anthropic → native Messages, OpenAI → native\n * Responses incl. Codex, everything else → unified MLflow), so a single\n * `neon('claude-...')` call (same base URL + token) reaches the whole catalog.\n * Ids use the canonical Neon (unprefixed) form; the legacy `databricks-` prefix\n * is also accepted. Configure with the branch-scoped `NEON_AI_GATEWAY_BASE_URL` +\n * `NEON_AI_GATEWAY_TOKEN` emitted by `neonctl env pull` / `neon dev`, or pass\n * `baseURL` / `apiKey` explicitly.\n */\nimport { openai as openaiProvider } from \"@ai-sdk/openai\";\nimport type { ProviderErrorStructure } from \"@ai-sdk/openai-compatible\";\nimport {\n\ttype LanguageModelV3,\n\tNoSuchModelError,\n\ttype ProviderV3,\n} from \"@ai-sdk/provider\";\nimport {\n\ttype FetchFunction,\n\tgenerateId,\n\tloadApiKey,\n\tloadSetting,\n\twithoutTrailingSlash,\n\twithUserAgentSuffix,\n} from \"@ai-sdk/provider-utils\";\nimport { z } from \"zod/v4\";\nimport { NeonAnthropicLanguageModel } from \"./neon-anthropic-language-model.js\";\nimport { NeonChatLanguageModel } from \"./neon-chat-language-model.js\";\nimport type { NeonChatModelId } from \"./neon-chat-options.js\";\nimport { getNeonModelRoute } from \"./neon-model-capabilities.js\";\nimport { NeonResponsesLanguageModel } from \"./neon-responses-language-model.js\";\nimport { VERSION } from \"./version.js\";\n\nconst neonErrorSchema = z.object({\n\terror: z.object({\n\t\tmessage: z.string(),\n\t\ttype: z.string().nullish(),\n\t\tparam: z.unknown().nullish(),\n\t\tcode: z.unknown().nullish(),\n\t}),\n});\n\nexport type NeonErrorData = z.infer<typeof neonErrorSchema>;\n\nconst neonErrorStructure: ProviderErrorStructure<NeonErrorData> = {\n\terrorSchema: neonErrorSchema,\n\terrorToMessage: (data) => data.error.message,\n};\n\n/**\n * Recursively remove the JSON Schema `$schema` marker, which some gateway\n * backends (notably Gemini) reject in tool/structured-output schemas. Other\n * backends ignore its absence, so stripping it everywhere is safe.\n */\nfunction stripJsonSchemaMarker(value: unknown): unknown {\n\tif (Array.isArray(value)) {\n\t\treturn value.map(stripJsonSchemaMarker);\n\t}\n\tif (value !== null && typeof value === \"object\") {\n\t\tconst result: Record<string, unknown> = {};\n\t\tfor (const [key, entry] of Object.entries(value)) {\n\t\t\tif (key === \"$schema\") {\n\t\t\t\tcontinue;\n\t\t\t}\n\t\t\tresult[key] = stripJsonSchemaMarker(entry);\n\t\t}\n\t\treturn result;\n\t}\n\treturn value;\n}\n\nfunction transformNeonRequestBody(\n\targs: Record<string, unknown>,\n): Record<string, unknown> {\n\tconst transformed = { ...args };\n\tif (transformed.tools != null) {\n\t\ttransformed.tools = stripJsonSchemaMarker(transformed.tools);\n\t}\n\tif (transformed.response_format != null) {\n\t\ttransformed.response_format = stripJsonSchemaMarker(\n\t\t\ttransformed.response_format,\n\t\t);\n\t}\n\treturn transformed;\n}\n\nexport interface NeonProviderSettings {\n\t/**\n\t * Neon AI Gateway base URL — the branch-scoped host root, e.g.\n\t * `https://<branch-id>-api.ai.<region>.aws.neon.tech`. The gateway paths are\n\t * appended internally. Falls back to the `NEON_AI_GATEWAY_BASE_URL` env var.\n\t */\n\tbaseURL?: string;\n\n\t/**\n\t * Neon AI Gateway platform token (the `nt_live_...` value). Falls back to the\n\t * `NEON_AI_GATEWAY_TOKEN` env var.\n\t */\n\tapiKey?: string;\n\n\t/** Custom headers to include in the requests. */\n\theaders?: Record<string, string>;\n\n\t/** Custom fetch implementation (e.g. for testing or middleware). */\n\tfetch?: FetchFunction;\n}\n\nexport interface NeonProvider extends ProviderV3 {\n\t/** Creates a Neon AI Gateway model for text generation. */\n\t(modelId: NeonChatModelId): LanguageModelV3;\n\n\t/** Creates a Neon AI Gateway model for text generation. */\n\tlanguageModel(modelId: NeonChatModelId): LanguageModelV3;\n\n\t/** Creates a Neon AI Gateway chat model for text generation. */\n\tchat(modelId: NeonChatModelId): LanguageModelV3;\n\n\t/** OpenAI Responses tools (e.g. `imageGeneration`) for OpenAI-routed models. */\n\ttools: typeof openaiProvider.tools;\n\n\t/** @deprecated Use `embeddingModel` instead. */\n\ttextEmbeddingModel(modelId: string): never;\n}\n\nexport function createNeon(options: NeonProviderSettings = {}): NeonProvider {\n\t// Resolved lazily so that `createNeon()` and the default `neon` instance do\n\t// not throw at import time when configuration comes from the environment.\n\tconst getHost = () =>\n\t\twithoutTrailingSlash(\n\t\t\tloadSetting({\n\t\t\t\tsettingValue: options.baseURL,\n\t\t\t\tenvironmentVariableName: \"NEON_AI_GATEWAY_BASE_URL\",\n\t\t\t\tsettingName: \"baseURL\",\n\t\t\t\tdescription: \"Neon AI Gateway base URL\",\n\t\t\t}),\n\t\t);\n\n\tconst getHeaders = (extra?: Record<string, string>) =>\n\t\twithUserAgentSuffix(\n\t\t\t{\n\t\t\t\tAuthorization: `Bearer ${loadApiKey({\n\t\t\t\t\tapiKey: options.apiKey,\n\t\t\t\t\tenvironmentVariableName: \"NEON_AI_GATEWAY_TOKEN\",\n\t\t\t\t\tdescription: \"Neon AI Gateway token\",\n\t\t\t\t})}`,\n\t\t\t\t...extra,\n\t\t\t\t...options.headers,\n\t\t\t},\n\t\t\t`neondatabase/ai-sdk-provider/${VERSION}`,\n\t\t);\n\n\t// Anthropic models -> native Messages API.\n\tconst createAnthropicModel = (modelId: NeonChatModelId) =>\n\t\tnew NeonAnthropicLanguageModel(modelId, {\n\t\t\tprovider: \"neon.anthropic\",\n\t\t\tbaseURL: `${getHost()}/ai-gateway/anthropic/v1`,\n\t\t\theaders: () => getHeaders({ \"anthropic-version\": \"2023-06-01\" }),\n\t\t\tfetch: options.fetch,\n\t\t\tgenerateId,\n\t\t});\n\n\t// OpenAI models (incl. Codex, only served natively) -> Responses API.\n\tconst createOpenAIModel = (modelId: NeonChatModelId) =>\n\t\tnew NeonResponsesLanguageModel(modelId, {\n\t\t\tprovider: \"neon.openai.responses\",\n\t\t\turl: ({ path }) => `${getHost()}/ai-gateway/openai/v1${path}`,\n\t\t\theaders: getHeaders,\n\t\t\tfetch: options.fetch,\n\t\t\tfileIdPrefixes: [\"file-\"],\n\t\t});\n\n\t// Everything else (Gemini, Llama, Qwen, gpt-oss, ...) -> unified MLflow\n\t// endpoint. Gemini is here because its native endpoint can't stream.\n\tconst createChatModel = (modelId: NeonChatModelId) =>\n\t\tnew NeonChatLanguageModel(modelId, {\n\t\t\tprovider: \"neon.chat\",\n\t\t\turl: ({ path }) => `${getHost()}/ai-gateway/mlflow/v1${path}`,\n\t\t\theaders: getHeaders,\n\t\t\tfetch: options.fetch,\n\t\t\terrorStructure: neonErrorStructure,\n\t\t\ttransformRequestBody: transformNeonRequestBody,\n\t\t\tsupportsStructuredOutputs: true,\n\t\t});\n\n\tconst createLanguageModel = (modelId: NeonChatModelId): LanguageModelV3 => {\n\t\tswitch (getNeonModelRoute(modelId)) {\n\t\t\tcase \"anthropic\":\n\t\t\t\treturn createAnthropicModel(modelId);\n\t\t\tcase \"openai\":\n\t\t\t\treturn createOpenAIModel(modelId);\n\t\t\tdefault:\n\t\t\t\treturn createChatModel(modelId);\n\t\t}\n\t};\n\n\tconst provider = (modelId: NeonChatModelId) => createLanguageModel(modelId);\n\n\tprovider.specificationVersion = \"v3\" as const;\n\tprovider.languageModel = createLanguageModel;\n\tprovider.chat = createLanguageModel;\n\tprovider.tools = openaiProvider.tools;\n\n\tprovider.embeddingModel = (modelId: string) => {\n\t\tthrow new NoSuchModelError({ modelId, modelType: \"embeddingModel\" });\n\t};\n\tprovider.textEmbeddingModel = provider.embeddingModel;\n\tprovider.imageModel = (modelId: string) => {\n\t\tthrow new NoSuchModelError({ modelId, modelType: \"imageModel\" });\n\t};\n\n\treturn provider;\n}\n\n/** Default Neon provider instance (reads `NEON_AI_GATEWAY_*` env vars). */\nexport const neon = createNeon();\n"],"mappings":";;;;;;;;;;;;;;;;;;;;;;AA8CA,MAAM,qBAA4D;CACjE,aAZuB,EAAE,OAAO,EAChC,OAAO,EAAE,OAAO;EACf,SAAS,EAAE,OAAO;EAClB,MAAM,EAAE,OAAO,CAAC,CAAC,QAAQ;EACzB,OAAO,EAAE,QAAQ,CAAC,CAAC,QAAQ;EAC3B,MAAM,EAAE,QAAQ,CAAC,CAAC,QAAQ;CAC3B,CAAC,EACF,CAK4B;CAC3B,iBAAiB,SAAS,KAAK,MAAM;AACtC;;;;;;AAOA,SAAS,sBAAsB,OAAyB;CACvD,IAAI,MAAM,QAAQ,KAAK,GACtB,OAAO,MAAM,IAAI,qBAAqB;CAEvC,IAAI,UAAU,QAAQ,OAAO,UAAU,UAAU;EAChD,MAAM,SAAkC,CAAC;EACzC,KAAK,MAAM,CAAC,KAAK,UAAU,OAAO,QAAQ,KAAK,GAAG;GACjD,IAAI,QAAQ,WACX;GAED,OAAO,OAAO,sBAAsB,KAAK;EAC1C;EACA,OAAO;CACR;CACA,OAAO;AACR;AAEA,SAAS,yBACR,MAC0B;CAC1B,MAAM,cAAc,EAAE,GAAG,KAAK;CAC9B,IAAI,YAAY,SAAS,MACxB,YAAY,QAAQ,sBAAsB,YAAY,KAAK;CAE5D,IAAI,YAAY,mBAAmB,MAClC,YAAY,kBAAkB,sBAC7B,YAAY,eACb;CAED,OAAO;AACR;AAwCA,SAAgB,WAAW,UAAgC,CAAC,GAAiB;CAG5E,MAAM,gBACL,qBACC,YAAY;EACX,cAAc,QAAQ;EACtB,yBAAyB;EACzB,aAAa;EACb,aAAa;CACd,CAAC,CACF;CAED,MAAM,cAAc,UACnB,oBACC;EACC,eAAe,UAAU,WAAW;GACnC,QAAQ,QAAQ;GAChB,yBAAyB;GACzB,aAAa;EACd,CAAC;EACD,GAAG;EACH,GAAG,QAAQ;CACZ,GACA,gCAAgC,SACjC;CAGD,MAAM,wBAAwB,YAC7B,IAAI,2BAA2B,SAAS;EACvC,UAAU;EACV,SAAS,GAAG,QAAQ,EAAE;EACtB,eAAe,WAAW,EAAE,qBAAqB,aAAa,CAAC;EAC/D,OAAO,QAAQ;EACf;CACD,CAAC;CAGF,MAAM,qBAAqB,YAC1B,IAAI,2BAA2B,SAAS;EACvC,UAAU;EACV,MAAM,EAAE,WAAW,GAAG,QAAQ,EAAE,uBAAuB;EACvD,SAAS;EACT,OAAO,QAAQ;EACf,gBAAgB,CAAC,OAAO;CACzB,CAAC;CAIF,MAAM,mBAAmB,YACxB,IAAI,sBAAsB,SAAS;EAClC,UAAU;EACV,MAAM,EAAE,WAAW,GAAG,QAAQ,EAAE,uBAAuB;EACvD,SAAS;EACT,OAAO,QAAQ;EACf,gBAAgB;EAChB,sBAAsB;EACtB,2BAA2B;CAC5B,CAAC;CAEF,MAAM,uBAAuB,YAA8C;EAC1E,QAAQ,kBAAkB,OAAO,GAAjC;GACC,KAAK,aACJ,OAAO,qBAAqB,OAAO;GACpC,KAAK,UACJ,OAAO,kBAAkB,OAAO;GACjC,SACC,OAAO,gBAAgB,OAAO;EAChC;CACD;CAEA,MAAM,YAAY,YAA6B,oBAAoB,OAAO;CAE1E,SAAS,uBAAuB;CAChC,SAAS,gBAAgB;CACzB,SAAS,OAAO;CAChB,SAAS,QAAQA,OAAe;CAEhC,SAAS,kBAAkB,YAAoB;EAC9C,MAAM,IAAI,iBAAiB;GAAE;GAAS,WAAW;EAAiB,CAAC;CACpE;CACA,SAAS,qBAAqB,SAAS;CACvC,SAAS,cAAc,YAAoB;EAC1C,MAAM,IAAI,iBAAiB;GAAE;GAAS,WAAW;EAAa,CAAC;CAChE;CAEA,OAAO;AACR;;AAGA,MAAa,OAAO,WAAW"}
package/dist/package.js CHANGED
@@ -1,5 +1,5 @@
1
1
  //#region package.json
2
- var version = "0.1.1";
2
+ var version = "0.4.0";
3
3
  //#endregion
4
4
  export { version };
5
5
 
package/dist/v1.d.ts CHANGED
@@ -1,7 +1,7 @@
1
1
  import { NeonAnthropicLanguageModel } from "./lib/neon-anthropic-language-model.js";
2
2
  import { NeonChatLanguageModel } from "./lib/neon-chat-language-model.js";
3
- import { NeonChatModelId } from "./lib/neon-chat-options.js";
3
+ import { NEON_EXTRA_MODEL_IDS, NEON_MODELS_DEV_IDS, NeonChatModelId, NeonKnownModelId } from "./lib/neon-chat-options.js";
4
4
  import { NeonModelCapabilities, NeonModelFamily, NeonModelRoute, getNeonModelCapabilities, getNeonModelRoute } from "./lib/neon-model-capabilities.js";
5
5
  import { NeonResponsesLanguageModel } from "./lib/neon-responses-language-model.js";
6
6
  import { NeonErrorData, NeonProvider, NeonProviderSettings, createNeon, neon } from "./lib/provider.js";
7
- export { NeonAnthropicLanguageModel, NeonChatLanguageModel, type NeonChatModelId, type NeonErrorData, type NeonModelCapabilities, type NeonModelFamily, type NeonModelRoute, type NeonProvider, type NeonProviderSettings, NeonResponsesLanguageModel, createNeon, getNeonModelCapabilities, getNeonModelRoute, neon };
7
+ export { NEON_EXTRA_MODEL_IDS, NEON_MODELS_DEV_IDS, NeonAnthropicLanguageModel, NeonChatLanguageModel, type NeonChatModelId, type NeonErrorData, type NeonKnownModelId, type NeonModelCapabilities, type NeonModelFamily, type NeonModelRoute, type NeonProvider, type NeonProviderSettings, NeonResponsesLanguageModel, createNeon, getNeonModelCapabilities, getNeonModelRoute, neon };
package/dist/v1.js CHANGED
@@ -1,6 +1,7 @@
1
1
  import { NeonAnthropicLanguageModel } from "./lib/neon-anthropic-language-model.js";
2
2
  import { getNeonModelCapabilities, getNeonModelRoute } from "./lib/neon-model-capabilities.js";
3
3
  import { NeonChatLanguageModel } from "./lib/neon-chat-language-model.js";
4
+ import { NEON_EXTRA_MODEL_IDS, NEON_MODELS_DEV_IDS } from "./lib/neon-chat-options.js";
4
5
  import { NeonResponsesLanguageModel } from "./lib/neon-responses-language-model.js";
5
6
  import { createNeon, neon } from "./lib/provider.js";
6
- export { NeonAnthropicLanguageModel, NeonChatLanguageModel, NeonResponsesLanguageModel, createNeon, getNeonModelCapabilities, getNeonModelRoute, neon };
7
+ export { NEON_EXTRA_MODEL_IDS, NEON_MODELS_DEV_IDS, NeonAnthropicLanguageModel, NeonChatLanguageModel, NeonResponsesLanguageModel, createNeon, getNeonModelCapabilities, getNeonModelRoute, neon };
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@neondatabase/ai-sdk-provider",
3
- "version": "0.1.1",
3
+ "version": "0.4.0",
4
4
  "description": "Community Vercel AI SDK provider for the Neon AI Gateway.",
5
5
  "keywords": [
6
6
  "neon",
@@ -44,6 +44,7 @@
44
44
  "devDependencies": {
45
45
  "@types/node": "^20.19.0",
46
46
  "@vitest/coverage-v8": "3.0.9",
47
+ "ai": "6.0.132",
47
48
  "console-fail-test": "0.5.0",
48
49
  "tsdown": "^0.14.1",
49
50
  "typescript": "^5.8.2",
@@ -57,19 +58,22 @@
57
58
  "provenance": false
58
59
  },
59
60
  "dependencies": {
60
- "@ai-sdk/anthropic": "4.0.0-beta.42",
61
- "@ai-sdk/openai": "4.0.0-beta.44",
62
- "@ai-sdk/openai-compatible": "3.0.0-beta.36",
63
- "@ai-sdk/provider": "4.0.0-beta.14",
64
- "@ai-sdk/provider-utils": "5.0.0-beta.30"
61
+ "@ai-sdk/anthropic": "3.0.82",
62
+ "@ai-sdk/openai": "3.0.69",
63
+ "@ai-sdk/openai-compatible": "2.0.48",
64
+ "@ai-sdk/provider": "3.0.10",
65
+ "@ai-sdk/provider-utils": "4.0.27"
65
66
  },
66
67
  "peerDependencies": {
68
+ "ai": "^6.0.0",
67
69
  "zod": "^3.25.76 || ^4.1.8"
68
70
  },
69
71
  "scripts": {
70
72
  "build": "tsc --noEmit && tsdown",
71
73
  "test": "vitest --passWithNoTests",
72
74
  "test:ci": "vitest run --passWithNoTests",
75
+ "test:drift": "NEON_DRIFT_CHECK=1 vitest run neon-catalog-drift",
76
+ "test:e2e": "vitest run --config vitest.e2e.config.ts",
73
77
  "tsc": "tsc"
74
78
  }
75
79
  }