@neondatabase/ai-sdk-provider 0.0.0 → 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/LICENSE.md +178 -0
- package/README.md +24 -9
- package/dist/index.d.ts +7 -0
- package/dist/index.js +8 -0
- package/dist/lib/neon-anthropic-language-model.d.ts +23 -0
- package/dist/lib/neon-anthropic-language-model.d.ts.map +1 -0
- package/dist/lib/neon-anthropic-language-model.js +38 -0
- package/dist/lib/neon-anthropic-language-model.js.map +1 -0
- package/dist/lib/neon-capabilities.d.ts +20 -0
- package/dist/lib/neon-capabilities.d.ts.map +1 -0
- package/dist/lib/neon-capabilities.js +97 -0
- package/dist/lib/neon-capabilities.js.map +1 -0
- package/dist/lib/neon-chat-language-model.d.ts +21 -0
- package/dist/lib/neon-chat-language-model.d.ts.map +1 -0
- package/dist/lib/neon-chat-language-model.js +34 -0
- package/dist/lib/neon-chat-language-model.js.map +1 -0
- package/dist/lib/neon-chat-options.d.ts +21 -0
- package/dist/lib/neon-chat-options.d.ts.map +1 -0
- package/dist/lib/neon-chat-options.js +52 -0
- package/dist/lib/neon-chat-options.js.map +1 -0
- package/dist/lib/neon-model-capabilities.d.ts +41 -0
- package/dist/lib/neon-model-capabilities.d.ts.map +1 -0
- package/dist/lib/neon-model-capabilities.js +74 -0
- package/dist/lib/neon-model-capabilities.js.map +1 -0
- package/dist/lib/neon-responses-language-model.d.ts +27 -0
- package/dist/lib/neon-responses-language-model.d.ts.map +1 -0
- package/dist/lib/neon-responses-language-model.js +45 -0
- package/dist/lib/neon-responses-language-model.js.map +1 -0
- package/dist/lib/provider.d.ts +52 -0
- package/dist/lib/provider.d.ts.map +1 -0
- package/dist/lib/provider.js +126 -0
- package/dist/lib/provider.js.map +1 -0
- package/dist/lib/version.d.ts +5 -0
- package/dist/lib/version.d.ts.map +1 -0
- package/dist/lib/version.js +7 -0
- package/dist/lib/version.js.map +1 -0
- package/dist/package.js +6 -0
- package/dist/package.js.map +1 -0
- package/dist/v1.d.ts +7 -0
- package/dist/v1.js +7 -0
- package/package.json +78 -23
- package/src/index.ts +0 -5
- package/src/lib/neon-anthropic-language-model.ts +0 -51
- package/src/lib/neon-capabilities.ts +0 -133
- package/src/lib/neon-chat-language-model.ts +0 -56
- package/src/lib/neon-chat-options.ts +0 -48
- package/src/lib/neon-model-capabilities.test.ts +0 -66
- package/src/lib/neon-model-capabilities.ts +0 -137
- package/src/lib/neon-responses-language-model.ts +0 -60
- package/src/lib/provider.ts +0 -211
- package/src/lib/version.ts +0 -2
- package/src/v1.ts +0 -26
- package/tsconfig.json +0 -4
- package/tsdown.config.ts +0 -12
- package/vitest.config.ts +0 -17
package/src/lib/provider.ts
DELETED
|
@@ -1,211 +0,0 @@
|
|
|
1
|
-
/**
|
|
2
|
-
* Community Vercel AI SDK provider for the Neon AI Gateway.
|
|
3
|
-
*
|
|
4
|
-
* `createNeon()` returns a provider that routes each model to the best gateway
|
|
5
|
-
* endpoint based on its id (Anthropic → native Messages, OpenAI → native
|
|
6
|
-
* Responses incl. Codex, everything else → unified MLflow), so a single
|
|
7
|
-
* `neon('databricks-...')` call (same base URL + token) reaches the whole
|
|
8
|
-
* catalog. Configure with the branch-scoped `NEON_AI_GATEWAY_BASE_URL` +
|
|
9
|
-
* `NEON_AI_GATEWAY_TOKEN` emitted by `neonctl env pull` / `neon dev`, or pass
|
|
10
|
-
* `baseURL` / `apiKey` explicitly.
|
|
11
|
-
*/
|
|
12
|
-
import type { ProviderErrorStructure } from "@ai-sdk/openai-compatible";
|
|
13
|
-
import {
|
|
14
|
-
type LanguageModelV4,
|
|
15
|
-
NoSuchModelError,
|
|
16
|
-
type ProviderV4,
|
|
17
|
-
} from "@ai-sdk/provider";
|
|
18
|
-
import {
|
|
19
|
-
type FetchFunction,
|
|
20
|
-
generateId,
|
|
21
|
-
loadApiKey,
|
|
22
|
-
loadSetting,
|
|
23
|
-
withoutTrailingSlash,
|
|
24
|
-
withUserAgentSuffix,
|
|
25
|
-
} from "@ai-sdk/provider-utils";
|
|
26
|
-
import { z } from "zod/v4";
|
|
27
|
-
import { NeonAnthropicLanguageModel } from "./neon-anthropic-language-model.js";
|
|
28
|
-
import { NeonChatLanguageModel } from "./neon-chat-language-model.js";
|
|
29
|
-
import type { NeonChatModelId } from "./neon-chat-options.js";
|
|
30
|
-
import { getNeonModelRoute } from "./neon-model-capabilities.js";
|
|
31
|
-
import { NeonResponsesLanguageModel } from "./neon-responses-language-model.js";
|
|
32
|
-
import { VERSION } from "./version.js";
|
|
33
|
-
|
|
34
|
-
const neonErrorSchema = z.object({
|
|
35
|
-
error: z.object({
|
|
36
|
-
message: z.string(),
|
|
37
|
-
type: z.string().nullish(),
|
|
38
|
-
param: z.unknown().nullish(),
|
|
39
|
-
code: z.unknown().nullish(),
|
|
40
|
-
}),
|
|
41
|
-
});
|
|
42
|
-
|
|
43
|
-
export type NeonErrorData = z.infer<typeof neonErrorSchema>;
|
|
44
|
-
|
|
45
|
-
const neonErrorStructure: ProviderErrorStructure<NeonErrorData> = {
|
|
46
|
-
errorSchema: neonErrorSchema,
|
|
47
|
-
errorToMessage: (data) => data.error.message,
|
|
48
|
-
};
|
|
49
|
-
|
|
50
|
-
/**
|
|
51
|
-
* Recursively remove the JSON Schema `$schema` marker, which some gateway
|
|
52
|
-
* backends (notably Gemini) reject in tool/structured-output schemas. Other
|
|
53
|
-
* backends ignore its absence, so stripping it everywhere is safe.
|
|
54
|
-
*/
|
|
55
|
-
function stripJsonSchemaMarker(value: unknown): unknown {
|
|
56
|
-
if (Array.isArray(value)) {
|
|
57
|
-
return value.map(stripJsonSchemaMarker);
|
|
58
|
-
}
|
|
59
|
-
if (value !== null && typeof value === "object") {
|
|
60
|
-
const result: Record<string, unknown> = {};
|
|
61
|
-
for (const [key, entry] of Object.entries(value)) {
|
|
62
|
-
if (key === "$schema") {
|
|
63
|
-
continue;
|
|
64
|
-
}
|
|
65
|
-
result[key] = stripJsonSchemaMarker(entry);
|
|
66
|
-
}
|
|
67
|
-
return result;
|
|
68
|
-
}
|
|
69
|
-
return value;
|
|
70
|
-
}
|
|
71
|
-
|
|
72
|
-
function transformNeonRequestBody(
|
|
73
|
-
args: Record<string, unknown>,
|
|
74
|
-
): Record<string, unknown> {
|
|
75
|
-
const transformed = { ...args };
|
|
76
|
-
if (transformed.tools != null) {
|
|
77
|
-
transformed.tools = stripJsonSchemaMarker(transformed.tools);
|
|
78
|
-
}
|
|
79
|
-
if (transformed.response_format != null) {
|
|
80
|
-
transformed.response_format = stripJsonSchemaMarker(
|
|
81
|
-
transformed.response_format,
|
|
82
|
-
);
|
|
83
|
-
}
|
|
84
|
-
return transformed;
|
|
85
|
-
}
|
|
86
|
-
|
|
87
|
-
export interface NeonProviderSettings {
|
|
88
|
-
/**
|
|
89
|
-
* Neon AI Gateway base URL — the branch-scoped host root, e.g.
|
|
90
|
-
* `https://<branch-id>-api.ai.<region>.aws.neon.tech`. The gateway paths are
|
|
91
|
-
* appended internally. Falls back to the `NEON_AI_GATEWAY_BASE_URL` env var.
|
|
92
|
-
*/
|
|
93
|
-
baseURL?: string;
|
|
94
|
-
|
|
95
|
-
/**
|
|
96
|
-
* Neon AI Gateway platform token (the `nt_live_...` value). Falls back to the
|
|
97
|
-
* `NEON_AI_GATEWAY_TOKEN` env var.
|
|
98
|
-
*/
|
|
99
|
-
apiKey?: string;
|
|
100
|
-
|
|
101
|
-
/** Custom headers to include in the requests. */
|
|
102
|
-
headers?: Record<string, string>;
|
|
103
|
-
|
|
104
|
-
/** Custom fetch implementation (e.g. for testing or middleware). */
|
|
105
|
-
fetch?: FetchFunction;
|
|
106
|
-
}
|
|
107
|
-
|
|
108
|
-
export interface NeonProvider extends ProviderV4 {
|
|
109
|
-
/** Creates a Neon AI Gateway model for text generation. */
|
|
110
|
-
(modelId: NeonChatModelId): LanguageModelV4;
|
|
111
|
-
|
|
112
|
-
/** Creates a Neon AI Gateway model for text generation. */
|
|
113
|
-
languageModel(modelId: NeonChatModelId): LanguageModelV4;
|
|
114
|
-
|
|
115
|
-
/** Creates a Neon AI Gateway chat model for text generation. */
|
|
116
|
-
chat(modelId: NeonChatModelId): LanguageModelV4;
|
|
117
|
-
|
|
118
|
-
/** @deprecated Use `embeddingModel` instead. */
|
|
119
|
-
textEmbeddingModel(modelId: string): never;
|
|
120
|
-
}
|
|
121
|
-
|
|
122
|
-
export function createNeon(options: NeonProviderSettings = {}): NeonProvider {
|
|
123
|
-
// Resolved lazily so that `createNeon()` and the default `neon` instance do
|
|
124
|
-
// not throw at import time when configuration comes from the environment.
|
|
125
|
-
const getHost = () =>
|
|
126
|
-
withoutTrailingSlash(
|
|
127
|
-
loadSetting({
|
|
128
|
-
settingValue: options.baseURL,
|
|
129
|
-
environmentVariableName: "NEON_AI_GATEWAY_BASE_URL",
|
|
130
|
-
settingName: "baseURL",
|
|
131
|
-
description: "Neon AI Gateway base URL",
|
|
132
|
-
}),
|
|
133
|
-
);
|
|
134
|
-
|
|
135
|
-
const getHeaders = (extra?: Record<string, string>) =>
|
|
136
|
-
withUserAgentSuffix(
|
|
137
|
-
{
|
|
138
|
-
Authorization: `Bearer ${loadApiKey({
|
|
139
|
-
apiKey: options.apiKey,
|
|
140
|
-
environmentVariableName: "NEON_AI_GATEWAY_TOKEN",
|
|
141
|
-
description: "Neon AI Gateway token",
|
|
142
|
-
})}`,
|
|
143
|
-
...extra,
|
|
144
|
-
...options.headers,
|
|
145
|
-
},
|
|
146
|
-
`neondatabase/ai-sdk-provider/${VERSION}`,
|
|
147
|
-
);
|
|
148
|
-
|
|
149
|
-
// Anthropic models -> native Messages API.
|
|
150
|
-
const createAnthropicModel = (modelId: NeonChatModelId) =>
|
|
151
|
-
new NeonAnthropicLanguageModel(modelId, {
|
|
152
|
-
provider: "neon.anthropic",
|
|
153
|
-
baseURL: `${getHost()}/ai-gateway/anthropic/v1`,
|
|
154
|
-
headers: () => getHeaders({ "anthropic-version": "2023-06-01" }),
|
|
155
|
-
fetch: options.fetch,
|
|
156
|
-
generateId,
|
|
157
|
-
});
|
|
158
|
-
|
|
159
|
-
// OpenAI models (incl. Codex, only served natively) -> Responses API.
|
|
160
|
-
const createOpenAIModel = (modelId: NeonChatModelId) =>
|
|
161
|
-
new NeonResponsesLanguageModel(modelId, {
|
|
162
|
-
provider: "neon.openai.responses",
|
|
163
|
-
url: ({ path }) => `${getHost()}/ai-gateway/openai/v1${path}`,
|
|
164
|
-
headers: getHeaders,
|
|
165
|
-
fetch: options.fetch,
|
|
166
|
-
fileIdPrefixes: ["file-"],
|
|
167
|
-
});
|
|
168
|
-
|
|
169
|
-
// Everything else (Gemini, Llama, Qwen, gpt-oss, ...) -> unified MLflow
|
|
170
|
-
// endpoint. Gemini is here because its native endpoint can't stream.
|
|
171
|
-
const createChatModel = (modelId: NeonChatModelId) =>
|
|
172
|
-
new NeonChatLanguageModel(modelId, {
|
|
173
|
-
provider: "neon.chat",
|
|
174
|
-
url: ({ path }) => `${getHost()}/ai-gateway/mlflow/v1${path}`,
|
|
175
|
-
headers: getHeaders,
|
|
176
|
-
fetch: options.fetch,
|
|
177
|
-
errorStructure: neonErrorStructure,
|
|
178
|
-
transformRequestBody: transformNeonRequestBody,
|
|
179
|
-
supportsStructuredOutputs: true,
|
|
180
|
-
});
|
|
181
|
-
|
|
182
|
-
const createLanguageModel = (modelId: NeonChatModelId): LanguageModelV4 => {
|
|
183
|
-
switch (getNeonModelRoute(modelId)) {
|
|
184
|
-
case "anthropic":
|
|
185
|
-
return createAnthropicModel(modelId);
|
|
186
|
-
case "openai":
|
|
187
|
-
return createOpenAIModel(modelId);
|
|
188
|
-
default:
|
|
189
|
-
return createChatModel(modelId);
|
|
190
|
-
}
|
|
191
|
-
};
|
|
192
|
-
|
|
193
|
-
const provider = (modelId: NeonChatModelId) => createLanguageModel(modelId);
|
|
194
|
-
|
|
195
|
-
provider.specificationVersion = "v4" as const;
|
|
196
|
-
provider.languageModel = createLanguageModel;
|
|
197
|
-
provider.chat = createLanguageModel;
|
|
198
|
-
|
|
199
|
-
provider.embeddingModel = (modelId: string) => {
|
|
200
|
-
throw new NoSuchModelError({ modelId, modelType: "embeddingModel" });
|
|
201
|
-
};
|
|
202
|
-
provider.textEmbeddingModel = provider.embeddingModel;
|
|
203
|
-
provider.imageModel = (modelId: string) => {
|
|
204
|
-
throw new NoSuchModelError({ modelId, modelType: "imageModel" });
|
|
205
|
-
};
|
|
206
|
-
|
|
207
|
-
return provider;
|
|
208
|
-
}
|
|
209
|
-
|
|
210
|
-
/** Default Neon provider instance (reads `NEON_AI_GATEWAY_*` env vars). */
|
|
211
|
-
export const neon = createNeon();
|
package/src/lib/version.ts
DELETED
package/src/v1.ts
DELETED
|
@@ -1,26 +0,0 @@
|
|
|
1
|
-
/**
|
|
2
|
-
* `@neondatabase/ai-sdk-provider/v1` — community Vercel AI SDK provider for the
|
|
3
|
-
* Neon AI Gateway.
|
|
4
|
-
*
|
|
5
|
-
* - `createNeon()` / `neon` — the provider. Routes each model to the best
|
|
6
|
-
* gateway endpoint (Anthropic → native Messages, OpenAI → native Responses
|
|
7
|
-
* incl. Codex, everything else → unified MLflow).
|
|
8
|
-
*/
|
|
9
|
-
export { NeonAnthropicLanguageModel } from "./lib/neon-anthropic-language-model.js";
|
|
10
|
-
export { NeonChatLanguageModel } from "./lib/neon-chat-language-model.js";
|
|
11
|
-
export type { NeonChatModelId } from "./lib/neon-chat-options.js";
|
|
12
|
-
export {
|
|
13
|
-
getNeonModelCapabilities,
|
|
14
|
-
getNeonModelRoute,
|
|
15
|
-
type NeonModelCapabilities,
|
|
16
|
-
type NeonModelFamily,
|
|
17
|
-
type NeonModelRoute,
|
|
18
|
-
} from "./lib/neon-model-capabilities.js";
|
|
19
|
-
export { NeonResponsesLanguageModel } from "./lib/neon-responses-language-model.js";
|
|
20
|
-
export {
|
|
21
|
-
createNeon,
|
|
22
|
-
type NeonErrorData,
|
|
23
|
-
type NeonProvider,
|
|
24
|
-
type NeonProviderSettings,
|
|
25
|
-
neon,
|
|
26
|
-
} from "./lib/provider.js";
|
package/tsconfig.json
DELETED
package/tsdown.config.ts
DELETED
|
@@ -1,12 +0,0 @@
|
|
|
1
|
-
import { defineConfig } from "tsdown";
|
|
2
|
-
|
|
3
|
-
export default defineConfig({
|
|
4
|
-
name: "@neondatabase/ai-sdk-provider",
|
|
5
|
-
bundle: false,
|
|
6
|
-
clean: true,
|
|
7
|
-
dts: true,
|
|
8
|
-
entry: ["src/index.ts", "src/v1.ts", "src/lib/**/*.ts", "!src/**/*.test.*"],
|
|
9
|
-
format: "esm",
|
|
10
|
-
outDir: "dist",
|
|
11
|
-
treeshake: true,
|
|
12
|
-
});
|
package/vitest.config.ts
DELETED
|
@@ -1,17 +0,0 @@
|
|
|
1
|
-
import { defineConfig } from "vitest/config";
|
|
2
|
-
|
|
3
|
-
export default defineConfig({
|
|
4
|
-
test: {
|
|
5
|
-
clearMocks: true,
|
|
6
|
-
mockReset: true,
|
|
7
|
-
unstubEnvs: true,
|
|
8
|
-
coverage: {
|
|
9
|
-
all: true,
|
|
10
|
-
include: ["src"],
|
|
11
|
-
exclude: ["src/**/*.test.ts"],
|
|
12
|
-
reporter: ["html", "lcov"],
|
|
13
|
-
},
|
|
14
|
-
exclude: ["lib", "node_modules", "dist"],
|
|
15
|
-
setupFiles: ["console-fail-test/setup"],
|
|
16
|
-
},
|
|
17
|
-
});
|