From 23e8766224ca5b03494bc6d3b1f22205565c0685 Mon Sep 17 00:00:00 2001 From: kathmbeck Date: Thu, 6 Nov 2025 09:15:09 -0500 Subject: [PATCH 1/3] feat: add AI Gateway support to @netlify/dev for Vite plugin --- packages/dev/package.json | 1 + packages/dev/src/main.ts | 26 ++++++++++++++++++++++++++ 2 files changed, 27 insertions(+) diff --git a/packages/dev/package.json b/packages/dev/package.json index 63290e69..4e9bc611 100644 --- a/packages/dev/package.json +++ b/packages/dev/package.json @@ -56,6 +56,7 @@ "vitest": "^3.0.0" }, "dependencies": { + "@netlify/ai": "^0.3.3", "@netlify/blobs": "10.3.3", "@netlify/config": "^23.2.0", "@netlify/dev-utils": "4.3.1", diff --git a/packages/dev/src/main.ts b/packages/dev/src/main.ts index 3325edd8..c0f8e267 100644 --- a/packages/dev/src/main.ts +++ b/packages/dev/src/main.ts @@ -3,6 +3,8 @@ import { IncomingMessage } from 'node:http' import path from 'node:path' import process from 'node:process' +import { parseAIGatewayContext, setupAIGateway } from '@netlify/ai/bootstrap' +import { NetlifyAPI } from '@netlify/api' import { resolveConfig } from '@netlify/config' import { ensureNetlifyIgnore, @@ -459,6 +461,30 @@ export class NetlifyDev { this.#cleanupJobs.push(() => runtime.stop()) + // Bootstrap AI Gateway: Fetch AI Gateway tokens and inject them into env + if (this.#features.environmentVariables && config?.api && siteID && config?.siteInfo?.url) { + await setupAIGateway({ + api: config.api, + env: config.env || {}, + siteID, + siteURL: config.siteInfo.url, + }) + + // Inject AI_GATEWAY into process.env via runtime + if (config.env.AI_GATEWAY) { + runtime.env.set('AI_GATEWAY', config.env.AI_GATEWAY.value) + + // Parse and inject individual provider keys (OPENAI_API_KEY, etc.) + const aiGatewayContext = parseAIGatewayContext(config.env.AI_GATEWAY.value) + if (aiGatewayContext?.envVars) { + for (const envVar of aiGatewayContext.envVars) { + runtime.env.set(envVar.key, aiGatewayContext.token) + runtime.env.set(envVar.url, aiGatewayContext.url) + } + } + } + } + let serverAddress: string | undefined // If a custom server has been provided, use it. If not, we must stand up From b7f47d9d6d77d42d41c877441aa21d3c5391ab39 Mon Sep 17 00:00:00 2001 From: kathmbeck Date: Thu, 6 Nov 2025 14:14:34 -0500 Subject: [PATCH 2/3] fix build/lint --- package.json | 2 +- packages/dev/src/main.ts | 1 - packages/dev/tsup.config.ts | 1 + 3 files changed, 2 insertions(+), 2 deletions(-) diff --git a/package.json b/package.json index 9fdc2ed7..8c74e54f 100644 --- a/package.json +++ b/package.json @@ -18,8 +18,8 @@ "packages/redirects", "packages/runtime", "packages/static", - "packages/dev", "packages/ai", + "packages/dev", "packages/nuxt-module", "packages/vite-plugin", "packages/vite-plugin-tanstack-start" diff --git a/packages/dev/src/main.ts b/packages/dev/src/main.ts index c0f8e267..0ffcdd81 100644 --- a/packages/dev/src/main.ts +++ b/packages/dev/src/main.ts @@ -4,7 +4,6 @@ import path from 'node:path' import process from 'node:process' import { parseAIGatewayContext, setupAIGateway } from '@netlify/ai/bootstrap' -import { NetlifyAPI } from '@netlify/api' import { resolveConfig } from '@netlify/config' import { ensureNetlifyIgnore, diff --git a/packages/dev/tsup.config.ts b/packages/dev/tsup.config.ts index e93f4974..c5ce64ec 100644 --- a/packages/dev/tsup.config.ts +++ b/packages/dev/tsup.config.ts @@ -13,5 +13,6 @@ export default defineConfig([ watch: argv.includes('--watch'), platform: 'node', bundle: true, + external: ['@netlify/ai'], }, ]) From 850e1cd2b94990e2666dd1ade26d58cd4f235d73 Mon Sep 17 00:00:00 2001 From: kathmbeck Date: Thu, 6 Nov 2025 15:46:40 -0500 Subject: [PATCH 3/3] set netlify env vars --- packages/dev/src/main.ts | 15 ++++++++++----- 1 file changed, 10 insertions(+), 5 deletions(-) diff --git a/packages/dev/src/main.ts b/packages/dev/src/main.ts index 0ffcdd81..e5818ee8 100644 --- a/packages/dev/src/main.ts +++ b/packages/dev/src/main.ts @@ -473,12 +473,17 @@ export class NetlifyDev { if (config.env.AI_GATEWAY) { runtime.env.set('AI_GATEWAY', config.env.AI_GATEWAY.value) - // Parse and inject individual provider keys (OPENAI_API_KEY, etc.) + // Parse and inject AI Gateway env vars const aiGatewayContext = parseAIGatewayContext(config.env.AI_GATEWAY.value) - if (aiGatewayContext?.envVars) { - for (const envVar of aiGatewayContext.envVars) { - runtime.env.set(envVar.key, aiGatewayContext.token) - runtime.env.set(envVar.url, aiGatewayContext.url) + if (aiGatewayContext) { + runtime.env.set('NETLIFY_AI_GATEWAY_KEY', aiGatewayContext.token) + runtime.env.set('NETLIFY_AI_GATEWAY_URL', aiGatewayContext.url) + + if (aiGatewayContext.envVars) { + for (const envVar of aiGatewayContext.envVars) { + runtime.env.set(envVar.key, aiGatewayContext.token) + runtime.env.set(envVar.url, aiGatewayContext.url) + } } } }