@neon/ai-sdk-provider 0.10.0 → 1.0.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 +26 -4
- package/dist/index.d.ts +3 -2
- package/dist/index.js +1 -2
- package/dist/lib/neon-embedding-options.d.ts +13 -0
- package/dist/lib/neon-embedding-options.d.ts.map +1 -0
- package/dist/lib/neon-embedding-options.js +9 -0
- package/dist/lib/neon-embedding-options.js.map +1 -0
- package/dist/lib/provider.d.ts +8 -2
- package/dist/lib/provider.d.ts.map +1 -1
- package/dist/lib/provider.js +24 -7
- package/dist/lib/provider.js.map +1 -1
- package/dist/package.js +1 -1
- package/package.json +1 -1
package/README.md
CHANGED
|
@@ -2,7 +2,7 @@
|
|
|
2
2
|
|
|
3
3
|
Community [Vercel AI SDK](https://ai-sdk.dev) provider for the [Neon](https://neon.com) AI Gateway. Supports **AI SDK v6 and v7** (`ai@^6` or `ai@^7`).
|
|
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. Use the same `neon(modelId)` API across the branch's
|
|
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. Use the same `neon(modelId)` API across the branch's text models; the provider selects Anthropic Messages, OpenAI Responses, or Chat Completions for each model. Embedding models use `neon.embeddingModel(modelId)`.
|
|
6
6
|
|
|
7
7
|
Use canonical model ids such as `gpt-5-mini`, `llama-4-maverick`, and `gemini-3-flash`, matching [neon.com/models](https://neon.com/models). The typed catalog includes the known model ids, and arbitrary strings are accepted so newly available models work before the types update.
|
|
8
8
|
|
|
@@ -59,7 +59,7 @@ Routing matches on the model id.
|
|
|
59
59
|
|
|
60
60
|
## Capabilities
|
|
61
61
|
|
|
62
|
-
`generateText` and `streamText` work with any model available to your branch. `generateObject`, `streamObject`, and single- or multi-step tool calls work with OpenAI (including Codex), Meta, Alibaba, Zhipu AI, and Thinking Machines models. Gemini currently supports `generateText` and `streamText`; structured output and multi-step tools are not supported. Vision input works on models that accept images.
|
|
62
|
+
`generateText` and `streamText` work with any text model available to your branch. `generateObject`, `streamObject`, and single- or multi-step tool calls work with OpenAI (including Codex), Meta, Alibaba, Zhipu AI, and Thinking Machines models. Gemini currently supports `generateText` and `streamText`; structured output and multi-step tools are not supported. Vision input works on models that accept images.
|
|
63
63
|
|
|
64
64
|
Claude models use the Messages API. On both that route and Chat Completions the provider removes call options the gateway rejects and reports each one in `result.warnings` instead of failing the request — see [Dropped call options](#dropped-call-options). Unsupported Responses API storage options throw before a request is sent — see [Errors](#errors).
|
|
65
65
|
|
|
@@ -108,6 +108,28 @@ getNeonModelCapabilities('glm-5-2').supportsPenalties; // false
|
|
|
108
108
|
|
|
109
109
|
A model none of these rules match is left untouched, so a brand-new id gets the gateway's own error rather than a guess. That is also why the table can lag: an id added since the last release inherits the permissive default until someone measures it.
|
|
110
110
|
|
|
111
|
+
## Embeddings
|
|
112
|
+
|
|
113
|
+
`neon.embeddingModel()` calls the gateway's OpenAI-compatible `/v1/embeddings` endpoint with the same base URL and token. It works with `embed()` and `embedMany()`.
|
|
114
|
+
|
|
115
|
+
```ts
|
|
116
|
+
import { neon } from "@neon/ai-sdk-provider";
|
|
117
|
+
import { embed, embedMany } from "ai";
|
|
118
|
+
|
|
119
|
+
const { embedding } = await embed({
|
|
120
|
+
model: neon.embeddingModel("qwen3-embedding-0-6b"), // or "gte-large-en"
|
|
121
|
+
value: "Neon branches are copy-on-write.",
|
|
122
|
+
});
|
|
123
|
+
|
|
124
|
+
const { embeddings } = await embedMany({
|
|
125
|
+
model: neon.embeddingModel("qwen3-embedding-0-6b"),
|
|
126
|
+
values: ["Scale to zero", "Instant restore", "Read replicas"],
|
|
127
|
+
providerOptions: { neon: { dimensions: 256 } },
|
|
128
|
+
});
|
|
129
|
+
```
|
|
130
|
+
|
|
131
|
+
Both models return 1024-dimensional vectors. `qwen3-embedding-0-6b` honors `providerOptions.neon.dimensions` for shorter vectors; `gte-large-en` ignores it. The gateway accepts at most 150 inputs per request, so `embedMany()` splits larger lists into batches of 150. `NeonEmbeddingModelId` autocompletes the known ids; any other string is passed through to the gateway. `textEmbeddingModel()` is a deprecated alias.
|
|
132
|
+
|
|
111
133
|
## Image generation
|
|
112
134
|
|
|
113
135
|
Available on OpenAI models via the Responses `image_generation` tool (there is no `generateImage()` image-model endpoint). Use `streamText` — streaming returns the image as a `tool-result` part and avoids the gateway's non-streaming response-size cap and read timeout:
|
|
@@ -211,7 +233,7 @@ So `store` is only refused on the Responses route; the same option is ignored el
|
|
|
211
233
|
|
|
212
234
|
## Limitations
|
|
213
235
|
|
|
214
|
-
- The gateway does not offer image
|
|
236
|
+
- The gateway does not offer an image model endpoint, so `generateImage()` throws `NoSuchModelError`. Image generation is available through the Responses API's built-in `image_generation` tool with `neon.tools.imageGeneration()`.
|
|
215
237
|
- Results from provider-executed tools (`neon.tools.imageGeneration`, and the other Responses built-ins) are not replayed to the gateway on a later step — see [Edit a generated image](#edit-a-generated-image).
|
|
216
238
|
- The Responses route is stateless, so the provider sends `store: false` and refuses `store: true`, `store: null`, `previousResponseId`, or `conversation` — see [Errors](#errors).
|
|
217
239
|
|
|
@@ -230,4 +252,4 @@ pnpm test:e2e
|
|
|
230
252
|
|
|
231
253
|
A run with neither **fails**; it does not skip. The gateway is on every branch and needs no provisioning, so the API-key path is the one CI uses — no gateway token is stored as a secret.
|
|
232
254
|
|
|
233
|
-
The matrix covers one published catalog model per family (Anthropic, OpenAI, Codex, Gemini, Meta, Alibaba, Zhipu, Thinking Machines) across `generateText`, `streamText`, `generateObject`, tool calling, and `neon.tools.imageGeneration`. `generateObject` and tool calling run on the subset of families where they are verified (see [Capabilities](#capabilities)). A family whose representative id the branch does not serve skips its cases, and a single assertion fails the run listing exactly which pinned ids went missing — so a shrinking catalog is reported rather than silently reducing coverage. Model access is granted per account, so the account behind the key needs every id in `MATRIX_MODELS`. The suite also fetches the live `/v1/models` catalog and calls every currently enabled model with both AI SDK 6 and AI SDK 7.
|
|
255
|
+
The matrix covers one published catalog model per family (Anthropic, OpenAI, Codex, Gemini, Meta, Alibaba, Zhipu, Thinking Machines) across `generateText`, `streamText`, `generateObject`, tool calling, and `neon.tools.imageGeneration`. `generateObject` and tool calling run on the subset of families where they are verified (see [Capabilities](#capabilities)). A family whose representative id the branch does not serve skips its cases, and a single assertion fails the run listing exactly which pinned ids went missing — so a shrinking catalog is reported rather than silently reducing coverage. Model access is granted per account, so the account behind the key needs every id in `MATRIX_MODELS`. The suite also fetches the live `/v1/models` catalog and calls every currently enabled text model with `generateText` and every embedding model with `embed` and `embedMany`, on both AI SDK 6 and AI SDK 7.
|
package/dist/index.d.ts
CHANGED
|
@@ -1,7 +1,8 @@
|
|
|
1
1
|
import { NeonAnthropicLanguageModel } from "./lib/neon-anthropic-language-model.js";
|
|
2
2
|
import { NeonChatLanguageModel } from "./lib/neon-chat-language-model.js";
|
|
3
|
-
import {
|
|
3
|
+
import { NeonChatModelId, NeonKnownModelId } from "./lib/neon-chat-options.js";
|
|
4
|
+
import { NeonEmbeddingModelId } from "./lib/neon-embedding-options.js";
|
|
4
5
|
import { NeonModelCapabilities, NeonModelFamily, NeonModelRoute, getNeonModelCapabilities, getNeonModelRoute } from "./lib/neon-model-capabilities.js";
|
|
5
6
|
import { NeonResponsesLanguageModel } from "./lib/neon-responses-language-model.js";
|
|
6
7
|
import { NeonErrorData, NeonProvider, NeonProviderSettings, createNeon, neon } from "./lib/provider.js";
|
|
7
|
-
export {
|
|
8
|
+
export { NeonAnthropicLanguageModel, NeonChatLanguageModel, type NeonChatModelId, type NeonEmbeddingModelId, type NeonErrorData, type NeonKnownModelId, type NeonModelCapabilities, type NeonModelFamily, type NeonModelRoute, type NeonProvider, type NeonProviderSettings, NeonResponsesLanguageModel, createNeon, getNeonModelCapabilities, getNeonModelRoute, neon };
|
package/dist/index.js
CHANGED
|
@@ -1,7 +1,6 @@
|
|
|
1
1
|
import { getNeonModelCapabilities, getNeonModelRoute } from "./lib/neon-model-capabilities.js";
|
|
2
2
|
import { NeonAnthropicLanguageModel } from "./lib/neon-anthropic-language-model.js";
|
|
3
3
|
import { NeonChatLanguageModel } from "./lib/neon-chat-language-model.js";
|
|
4
|
-
import { NEON_MODELS_DEV_IDS } from "./lib/neon-chat-options.js";
|
|
5
4
|
import { NeonResponsesLanguageModel } from "./lib/neon-responses-language-model.js";
|
|
6
5
|
import { createNeon, neon } from "./lib/provider.js";
|
|
7
|
-
export {
|
|
6
|
+
export { NeonAnthropicLanguageModel, NeonChatLanguageModel, NeonResponsesLanguageModel, createNeon, getNeonModelCapabilities, getNeonModelRoute, neon };
|
|
@@ -0,0 +1,13 @@
|
|
|
1
|
+
//#region src/lib/neon-embedding-options.d.ts
|
|
2
|
+
/** Published embedding model ids from https://neon.com/models.json. */
|
|
3
|
+
declare const NEON_EMBEDDING_MODEL_IDS: readonly ["gte-large-en", "qwen3-embedding-0-6b"];
|
|
4
|
+
/**
|
|
5
|
+
* A Neon AI Gateway embedding model id. Known ids are listed for autocomplete;
|
|
6
|
+
* any other id is accepted via the `(string & {})` fallback.
|
|
7
|
+
*/
|
|
8
|
+
type NeonEmbeddingModelId = (typeof NEON_EMBEDDING_MODEL_IDS)[number] | (string & {});
|
|
9
|
+
/** The gateway rejects an embeddings request with more inputs than this. */
|
|
10
|
+
declare const NEON_MAX_EMBEDDINGS_PER_CALL = 150;
|
|
11
|
+
//#endregion
|
|
12
|
+
export { NEON_EMBEDDING_MODEL_IDS, NEON_MAX_EMBEDDINGS_PER_CALL, NeonEmbeddingModelId };
|
|
13
|
+
//# sourceMappingURL=neon-embedding-options.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"neon-embedding-options.d.ts","names":[],"sources":["../../src/lib/neon-embedding-options.ts"],"mappings":";;AAMa,cAAA,wBAGH,EAAA,SAAA,CAAA,cAAA,EAAA,sBAAA,CAAA;AAMV;AAKA;;;KALY,oBAAA,WACD;;cAIE,4BAAA"}
|
|
@@ -0,0 +1,9 @@
|
|
|
1
|
+
//#region src/lib/neon-embedding-options.ts
|
|
2
|
+
/** Published embedding model ids from https://neon.com/models.json. */
|
|
3
|
+
const NEON_EMBEDDING_MODEL_IDS = ["gte-large-en", "qwen3-embedding-0-6b"];
|
|
4
|
+
/** The gateway rejects an embeddings request with more inputs than this. */
|
|
5
|
+
const NEON_MAX_EMBEDDINGS_PER_CALL = 150;
|
|
6
|
+
//#endregion
|
|
7
|
+
export { NEON_EMBEDDING_MODEL_IDS, NEON_MAX_EMBEDDINGS_PER_CALL };
|
|
8
|
+
|
|
9
|
+
//# sourceMappingURL=neon-embedding-options.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"neon-embedding-options.js","names":[],"sources":["../../src/lib/neon-embedding-options.ts"],"sourcesContent":["// Embedding models served on the Neon AI Gateway's OpenAI-compatible\n// `/v1/embeddings` endpoint. Mirrors the `\"type\": \"embedding\"` entries of\n// https://neon.com/models.json — `neon-catalog-drift.test.ts` fails if the two\n// diverge.\n\n/** Published embedding model ids from https://neon.com/models.json. */\nexport const NEON_EMBEDDING_MODEL_IDS = [\n\t\"gte-large-en\",\n\t\"qwen3-embedding-0-6b\",\n] as const;\n\n/**\n * A Neon AI Gateway embedding model id. Known ids are listed for autocomplete;\n * any other id is accepted via the `(string & {})` fallback.\n */\nexport type NeonEmbeddingModelId =\n\t| (typeof NEON_EMBEDDING_MODEL_IDS)[number]\n\t| (string & {});\n\n/** The gateway rejects an embeddings request with more inputs than this. */\nexport const NEON_MAX_EMBEDDINGS_PER_CALL = 150;\n"],"mappings":";;AAMA,MAAa,2BAA2B,CACvC,gBACA,sBACD;;AAWA,MAAa,+BAA+B"}
|
package/dist/lib/provider.d.ts
CHANGED
|
@@ -1,6 +1,7 @@
|
|
|
1
1
|
import { NeonChatModelId } from "./neon-chat-options.js";
|
|
2
|
+
import { NeonEmbeddingModelId } from "./neon-embedding-options.js";
|
|
2
3
|
import { neonOpenAITools } from "./neon-openai-tools.js";
|
|
3
|
-
import { LanguageModelV3, ProviderV3 } from "@ai-sdk/provider";
|
|
4
|
+
import { EmbeddingModelV3, LanguageModelV3, ProviderV3 } from "@ai-sdk/provider";
|
|
4
5
|
import { FetchFunction } from "@ai-sdk/provider-utils";
|
|
5
6
|
import { z } from "zod/v4";
|
|
6
7
|
|
|
@@ -40,8 +41,13 @@ interface NeonProvider extends ProviderV3 {
|
|
|
40
41
|
chat(modelId: NeonChatModelId): LanguageModelV3;
|
|
41
42
|
/** OpenAI Responses tools (e.g. `imageGeneration`) for OpenAI-routed models. */
|
|
42
43
|
tools: typeof neonOpenAITools;
|
|
44
|
+
/**
|
|
45
|
+
* Creates a Neon AI Gateway embedding model for `embed()` and `embedMany()`.
|
|
46
|
+
* Provider options go under `providerOptions.neon` (`dimensions`, `user`).
|
|
47
|
+
*/
|
|
48
|
+
embeddingModel(modelId: NeonEmbeddingModelId): EmbeddingModelV3;
|
|
43
49
|
/** @deprecated Use `embeddingModel` instead. */
|
|
44
|
-
textEmbeddingModel(modelId:
|
|
50
|
+
textEmbeddingModel(modelId: NeonEmbeddingModelId): EmbeddingModelV3;
|
|
45
51
|
}
|
|
46
52
|
declare function createNeon(options?: NeonProviderSettings): NeonProvider;
|
|
47
53
|
/** Default Neon provider instance (reads `NEON_AI_GATEWAY_*` env vars). */
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"provider.d.ts","names":[],"sources":["../../src/lib/provider.ts"],"mappings":"
|
|
1
|
+
{"version":3,"file":"provider.d.ts","names":[],"sources":["../../src/lib/provider.ts"],"mappings":";;;;;;;;cA6CM,iBAAe,CAAA,CAAA;;IAAf,OAAA,aAOJ;IAAA,IAAA,eAAA,cAAA,YAAA,CAAA,CAAA;;;;GAAA,CAAA,CAAA,IAAA,CAAA;KAEU,aAAA,GAAgB,CAAA,CAAE,aAAa;UA4C1B,oBAAA;;;;;;;EA9Cf;AAPmB;AAAA;AASrB;EAAyB,MAAA,CAAA,EAAA,MAAA;EAAkB;EAAf,OAAE,CAAA,EA2DnB,MA3DmB,CAAA,MAAA,EAAA,MAAA,CAAA;EAAK;EA4ClB,KAAA,CAAA,EAkBR,aAlBQ;AAAoB;AAe1B,UAMM,YAAA,SAAqB,UAN3B,CAAA;EAGF;EAAa,CAAA,OAAA,EAKX,eALW,CAAA,EAKO,eALP;EAGL;EAAa,aAAA,CAAA,OAAA,EAKN,eALM,CAAA,EAKY,eALZ;EAEnB;EAAkB,IAAA,CAAA,OAAA,EAMd,eANc,CAAA,EAMI,eANJ;EAGL;EAAkB,KAAA,EAAA,OAM3B,eAN2B;EAG3B;AAAkB;AAGlB;AAMU;EAAuB,cAAA,CAAA,OAAA,EAAvB,oBAAuB,CAAA,EAAA,gBAAA;EAGnB;EAAuB,kBAAA,CAAA,OAAA,EAAvB,oBAAuB,CAAA,EAAA,gBAAA;AApBd;AAAU,iBAuBhC,UAAA,CAvBgC,OAAA,CAAA,EAuBZ,oBAvBY,CAAA,EAuBgB,YAvBhB;AAuBhD;AAA0B,cA4Hb,IA5Ha,EA4HT,YA5HS"}
|
package/dist/lib/provider.js
CHANGED
|
@@ -2,14 +2,28 @@ import { getNeonModelRoute } from "./neon-model-capabilities.js";
|
|
|
2
2
|
import { NeonAnthropicLanguageModel } from "./neon-anthropic-language-model.js";
|
|
3
3
|
import { NeonChatLanguageModel } from "./neon-chat-language-model.js";
|
|
4
4
|
import { NeonResponsesLanguageModel } from "./neon-responses-language-model.js";
|
|
5
|
+
import "./neon-embedding-options.js";
|
|
5
6
|
import { wrapFetchWithGatewayErrorNormalization } from "./neon-gateway-error.js";
|
|
6
7
|
import { wrapFetchWithHarmonyNormalization } from "./neon-harmony-normalize.js";
|
|
7
8
|
import { neonOpenAITools } from "./neon-openai-tools.js";
|
|
8
9
|
import { VERSION } from "./version.js";
|
|
10
|
+
import { OpenAICompatibleEmbeddingModel } from "@ai-sdk/openai-compatible";
|
|
9
11
|
import { NoSuchModelError } from "@ai-sdk/provider";
|
|
10
12
|
import { generateId, loadApiKey, loadSetting, withUserAgentSuffix, withoutTrailingSlash } from "@ai-sdk/provider-utils";
|
|
11
13
|
import { z } from "zod/v4";
|
|
12
14
|
//#region src/lib/provider.ts
|
|
15
|
+
/**
|
|
16
|
+
* Community Vercel AI SDK provider for the Neon AI Gateway.
|
|
17
|
+
*
|
|
18
|
+
* `createNeon()` returns a provider that routes each model to the best gateway
|
|
19
|
+
* endpoint based on its id (Anthropic → native Messages, OpenAI → native
|
|
20
|
+
* Responses incl. Codex, everything else → unified Chat Completions), so a single
|
|
21
|
+
* `neon('claude-...')` call (same base URL + token) reaches the whole catalog.
|
|
22
|
+
* Ids use the canonical Neon (unprefixed) form; the legacy `databricks-` prefix
|
|
23
|
+
* is also accepted. Configure with the branch-scoped `NEON_AI_GATEWAY_BASE_URL` +
|
|
24
|
+
* `NEON_AI_GATEWAY_TOKEN` emitted by `neonctl env pull` / `neon dev`, or pass
|
|
25
|
+
* `baseURL` / `apiKey` explicitly.
|
|
26
|
+
*/
|
|
13
27
|
const neonErrorStructure = {
|
|
14
28
|
errorSchema: z.object({ error: z.object({
|
|
15
29
|
message: z.string(),
|
|
@@ -81,6 +95,14 @@ function createNeon(options = {}) {
|
|
|
81
95
|
transformRequestBody: transformNeonRequestBody,
|
|
82
96
|
supportsStructuredOutputs: true
|
|
83
97
|
});
|
|
98
|
+
const createEmbeddingModel = (modelId) => new OpenAICompatibleEmbeddingModel(modelId, {
|
|
99
|
+
provider: "neon.embedding",
|
|
100
|
+
url: ({ path }) => `${getHost()}/v1${path}`,
|
|
101
|
+
headers: getHeaders,
|
|
102
|
+
fetch: wrapFetchWithGatewayErrorNormalization(options.fetch, "openai"),
|
|
103
|
+
errorStructure: neonErrorStructure,
|
|
104
|
+
maxEmbeddingsPerCall: 150
|
|
105
|
+
});
|
|
84
106
|
const createLanguageModel = (modelId) => {
|
|
85
107
|
switch (getNeonModelRoute(modelId)) {
|
|
86
108
|
case "anthropic": return createAnthropicModel(modelId);
|
|
@@ -93,13 +115,8 @@ function createNeon(options = {}) {
|
|
|
93
115
|
provider.languageModel = createLanguageModel;
|
|
94
116
|
provider.chat = createLanguageModel;
|
|
95
117
|
provider.tools = neonOpenAITools;
|
|
96
|
-
provider.embeddingModel =
|
|
97
|
-
|
|
98
|
-
modelId,
|
|
99
|
-
modelType: "embeddingModel"
|
|
100
|
-
});
|
|
101
|
-
};
|
|
102
|
-
provider.textEmbeddingModel = provider.embeddingModel;
|
|
118
|
+
provider.embeddingModel = createEmbeddingModel;
|
|
119
|
+
provider.textEmbeddingModel = createEmbeddingModel;
|
|
103
120
|
provider.imageModel = (modelId) => {
|
|
104
121
|
throw new NoSuchModelError({
|
|
105
122
|
modelId,
|
package/dist/lib/provider.js.map
CHANGED
|
@@ -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 Chat Completions), 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 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 { wrapFetchWithGatewayErrorNormalization } from \"./neon-gateway-error.js\";\nimport { wrapFetchWithHarmonyNormalization } from \"./neon-harmony-normalize.js\";\nimport { getNeonModelRoute } from \"./neon-model-capabilities.js\";\nimport { neonOpenAITools } from \"./neon-openai-tools.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 neonOpenAITools;\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()}/anthropic/v1`,\n\t\t\theaders: () => getHeaders({ \"anthropic-version\": \"2023-06-01\" }),\n\t\t\tfetch: wrapFetchWithGatewayErrorNormalization(\n\t\t\t\toptions.fetch,\n\t\t\t\t\"anthropic\",\n\t\t\t),\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()}/openai/v1${path}`,\n\t\t\theaders: getHeaders,\n\t\t\t// This route returns Databricks error envelopes the OpenAI schema\n\t\t\t// cannot read, which reach the caller as a bare \"Bad Request\".\n\t\t\t// `OpenAIConfig` has no error hook, so the rewrite rides on fetch.\n\t\t\tfetch: wrapFetchWithGatewayErrorNormalization(\n\t\t\t\toptions.fetch,\n\t\t\t\t\"openai\",\n\t\t\t),\n\t\t\tfileIdPrefixes: [\"file-\"],\n\t\t});\n\n\t// Everything else (Gemini, Llama, Qwen, gpt-oss, ...) -> unified Chat\n\t// Completions 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()}/v1${path}`,\n\t\t\theaders: getHeaders,\n\t\t\t// Two wrappers, on disjoint halves of the response: the harmony one\n\t\t\t// rewrites successful gpt-oss bodies and returns early on any error,\n\t\t\t// the error one only touches non-2xx bodies. This route emits the\n\t\t\t// same flat `{ error_code, message }` Databricks envelope as the\n\t\t\t// Responses route (an out-of-range `temperature`, say), which\n\t\t\t// `errorStructure` below cannot read on its own.\n\t\t\t//\n\t\t\t// TODO(#308): Temporary workaround for gpt-oss. The gateway returns a\n\t\t\t// non-compliant \"harmony\" content-array shape; this wrapper normalizes it\n\t\t\t// to the Chat Completions contract and is a transparent pass-through for\n\t\t\t// every compliant response. Remove it (and neon-harmony-normalize.ts) once\n\t\t\t// the gateway returns spec-compliant gpt-oss responses.\n\t\t\tfetch: wrapFetchWithHarmonyNormalization(\n\t\t\t\twrapFetchWithGatewayErrorNormalization(options.fetch, \"openai\"),\n\t\t\t),\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 = neonOpenAITools;\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":";;;;;;;;;;;;AAgDA,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,uCACN,QAAQ,OACR,WACD;EACA;CACD,CAAC;CAGF,MAAM,qBAAqB,YAC1B,IAAI,2BAA2B,SAAS;EACvC,UAAU;EACV,MAAM,EAAE,WAAW,GAAG,QAAQ,EAAE,YAAY;EAC5C,SAAS;EAIT,OAAO,uCACN,QAAQ,OACR,QACD;EACA,gBAAgB,CAAC,OAAO;CACzB,CAAC;CAIF,MAAM,mBAAmB,YACxB,IAAI,sBAAsB,SAAS;EAClC,UAAU;EACV,MAAM,EAAE,WAAW,GAAG,QAAQ,EAAE,KAAK;EACrC,SAAS;EAaT,OAAO,kCACN,uCAAuC,QAAQ,OAAO,QAAQ,CAC/D;EACA,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,QAAQ;CAEjB,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":[],"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 Chat Completions), 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 {\n\tOpenAICompatibleEmbeddingModel,\n\ttype ProviderErrorStructure,\n} from \"@ai-sdk/openai-compatible\";\nimport {\n\ttype EmbeddingModelV3,\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 {\n\tNEON_MAX_EMBEDDINGS_PER_CALL,\n\ttype NeonEmbeddingModelId,\n} from \"./neon-embedding-options.js\";\nimport { wrapFetchWithGatewayErrorNormalization } from \"./neon-gateway-error.js\";\nimport { wrapFetchWithHarmonyNormalization } from \"./neon-harmony-normalize.js\";\nimport { getNeonModelRoute } from \"./neon-model-capabilities.js\";\nimport { neonOpenAITools } from \"./neon-openai-tools.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 neonOpenAITools;\n\n\t/**\n\t * Creates a Neon AI Gateway embedding model for `embed()` and `embedMany()`.\n\t * Provider options go under `providerOptions.neon` (`dimensions`, `user`).\n\t */\n\tembeddingModel(modelId: NeonEmbeddingModelId): EmbeddingModelV3;\n\n\t/** @deprecated Use `embeddingModel` instead. */\n\ttextEmbeddingModel(modelId: NeonEmbeddingModelId): EmbeddingModelV3;\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()}/anthropic/v1`,\n\t\t\theaders: () => getHeaders({ \"anthropic-version\": \"2023-06-01\" }),\n\t\t\tfetch: wrapFetchWithGatewayErrorNormalization(\n\t\t\t\toptions.fetch,\n\t\t\t\t\"anthropic\",\n\t\t\t),\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()}/openai/v1${path}`,\n\t\t\theaders: getHeaders,\n\t\t\t// This route returns Databricks error envelopes the OpenAI schema\n\t\t\t// cannot read, which reach the caller as a bare \"Bad Request\".\n\t\t\t// `OpenAIConfig` has no error hook, so the rewrite rides on fetch.\n\t\t\tfetch: wrapFetchWithGatewayErrorNormalization(\n\t\t\t\toptions.fetch,\n\t\t\t\t\"openai\",\n\t\t\t),\n\t\t\tfileIdPrefixes: [\"file-\"],\n\t\t});\n\n\t// Everything else (Gemini, Llama, Qwen, gpt-oss, ...) -> unified Chat\n\t// Completions 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()}/v1${path}`,\n\t\t\theaders: getHeaders,\n\t\t\t// Two wrappers, on disjoint halves of the response: the harmony one\n\t\t\t// rewrites successful gpt-oss bodies and returns early on any error,\n\t\t\t// the error one only touches non-2xx bodies. This route emits the\n\t\t\t// same flat `{ error_code, message }` Databricks envelope as the\n\t\t\t// Responses route (an out-of-range `temperature`, say), which\n\t\t\t// `errorStructure` below cannot read on its own.\n\t\t\t//\n\t\t\t// TODO(#308): Temporary workaround for gpt-oss. The gateway returns a\n\t\t\t// non-compliant \"harmony\" content-array shape; this wrapper normalizes it\n\t\t\t// to the Chat Completions contract and is a transparent pass-through for\n\t\t\t// every compliant response. Remove it (and neon-harmony-normalize.ts) once\n\t\t\t// the gateway returns spec-compliant gpt-oss responses.\n\t\t\tfetch: wrapFetchWithHarmonyNormalization(\n\t\t\t\twrapFetchWithGatewayErrorNormalization(options.fetch, \"openai\"),\n\t\t\t),\n\t\t\terrorStructure: neonErrorStructure,\n\t\t\ttransformRequestBody: transformNeonRequestBody,\n\t\t\tsupportsStructuredOutputs: true,\n\t\t});\n\n\tconst createEmbeddingModel = (modelId: NeonEmbeddingModelId) =>\n\t\tnew OpenAICompatibleEmbeddingModel(modelId, {\n\t\t\tprovider: \"neon.embedding\",\n\t\t\turl: ({ path }) => `${getHost()}/v1${path}`,\n\t\t\theaders: getHeaders,\n\t\t\tfetch: wrapFetchWithGatewayErrorNormalization(\n\t\t\t\toptions.fetch,\n\t\t\t\t\"openai\",\n\t\t\t),\n\t\t\terrorStructure: neonErrorStructure,\n\t\t\tmaxEmbeddingsPerCall: NEON_MAX_EMBEDDINGS_PER_CALL,\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 = neonOpenAITools;\n\n\tprovider.embeddingModel = createEmbeddingModel;\n\tprovider.textEmbeddingModel = createEmbeddingModel;\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":"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"}
|
package/dist/package.js
CHANGED