Thanks to visit codestin.com
Credit goes to github.com

Skip to content

Commit efb5a3f

Browse files
authored
feat: support ai gateway (#7609)
* feat: initial ai gateway support * fix: clean up duplication * fix: extract func * fix: format and lint errors * use new ai gateway package and tests * cleanup * update to use new package * use ai published package * format/types * chaining * lint * ignore rule * feedback * remove dev log * Remove unused import
1 parent 961abee commit efb5a3f

File tree

11 files changed

+608
-23
lines changed

11 files changed

+608
-23
lines changed

package-lock.json

Lines changed: 82 additions & 18 deletions
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

package.json

Lines changed: 3 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -62,10 +62,11 @@
6262
"@netlify/blobs": "10.0.10",
6363
"@netlify/build": "35.1.6",
6464
"@netlify/build-info": "10.0.7",
65+
"@netlify/ai": "0.2.1",
6566
"@netlify/config": "24.0.3",
6667
"@netlify/dev-utils": "4.1.3",
6768
"@netlify/edge-bundler": "14.5.4",
68-
"@netlify/edge-functions-bootstrap": "2.14.0",
69+
"@netlify/edge-functions": "2.17.4",
6970
"@netlify/headers-parser": "9.0.2",
7071
"@netlify/local-functions-proxy": "2.0.3",
7172
"@netlify/redirect-parser": "15.0.3",
@@ -157,7 +158,7 @@
157158
"@bugsnag/js": "8.4.0",
158159
"@eslint/compat": "1.3.2",
159160
"@eslint/js": "9.24.0",
160-
"@netlify/edge-functions": "2.17.4",
161+
"@netlify/edge-functions-bootstrap": "2.14.0",
161162
"@netlify/functions": "3.0.4",
162163
"@netlify/types": "2.0.3",
163164
"@sindresorhus/slugify": "2.2.1",

src/commands/dev/dev.ts

Lines changed: 14 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -19,6 +19,8 @@ import {
1919
netlifyCommand,
2020
} from '../../utils/command-helpers.js'
2121
import detectServerSettings, { getConfigWithPlugins } from '../../utils/detect-server-settings.js'
22+
import { parseAIGatewayContext, setupAIGateway } from '@netlify/ai/bootstrap'
23+
2224
import { UNLINKED_SITE_MOCK_ID, getDotEnvVariables, getSiteInformation, injectEnvVariables } from '../../utils/dev.js'
2325
import { getEnvelopeEnv } from '../../utils/env/index.js'
2426
import { ensureNetlifyIgnore } from '../../utils/gitignore.js'
@@ -143,8 +145,6 @@ export const dev = async (options: OptionValues, command: BaseCommand) => {
143145
}
144146

145147
env = await getDotEnvVariables({ devConfig, env, site })
146-
injectEnvVariables(env)
147-
await promptEditorHelper({ chalk, config, log, NETLIFYDEVLOG, repositoryRoot, state })
148148

149149
const { accountId, addonsUrls, capabilities, siteUrl, timeouts } = await getSiteInformation({
150150
// inherited from base command --offline
@@ -155,6 +155,14 @@ export const dev = async (options: OptionValues, command: BaseCommand) => {
155155
siteInfo,
156156
})
157157

158+
if (!options.offline && !options.offlineEnv) {
159+
await setupAIGateway({ api, env, siteID: site.id, siteURL: siteUrl })
160+
}
161+
162+
injectEnvVariables(env)
163+
164+
await promptEditorHelper({ chalk, config, log, NETLIFYDEVLOG, repositoryRoot, state })
165+
158166
let settings: ServerSettings
159167
try {
160168
settings = await detectServerSettings(devConfig, options, command)
@@ -204,7 +212,11 @@ export const dev = async (options: OptionValues, command: BaseCommand) => {
204212
// FIXME(serhalp): `applyMutations` is `(any, any) => any)`. Add types in `@netlify/config`.
205213
const mutatedConfig: typeof config = applyMutations(config, configMutations)
206214

215+
// eslint-disable-next-line @typescript-eslint/no-unnecessary-condition
216+
const aiGatewayContext = parseAIGatewayContext(env.AI_GATEWAY?.value)
217+
207218
const functionsRegistry = await startFunctionsServer({
219+
aiGatewayContext,
208220
blobsContext,
209221
command,
210222
config: mutatedConfig,

src/commands/functions/functions-serve.ts

Lines changed: 11 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -2,6 +2,8 @@ import { join } from 'path'
22

33
import { OptionValues } from 'commander'
44

5+
import { parseAIGatewayContext, setupAIGateway } from '@netlify/ai/bootstrap'
6+
57
import { getBlobsContextWithEdgeAccess } from '../../lib/blobs/blobs.js'
68
import { startFunctionsServer } from '../../lib/functions/server.js'
79
import { printBanner } from '../../utils/dev-server-banner.js'
@@ -28,7 +30,6 @@ export const functionsServe = async (options: OptionValues, command: BaseCommand
2830
env.NETLIFY_DEV = { sources: ['internal'], value: 'true' }
2931

3032
env = await getDotEnvVariables({ devConfig: { ...config.dev }, env, site })
31-
injectEnvVariables(env)
3233

3334
const { accountId, capabilities, siteUrl, timeouts } = await getSiteInformation({
3435
offline: options.offline,
@@ -37,6 +38,12 @@ export const functionsServe = async (options: OptionValues, command: BaseCommand
3738
siteInfo,
3839
})
3940

41+
if (!options.offline) {
42+
await setupAIGateway({ api, env, siteID: site.id, siteURL: siteUrl })
43+
}
44+
45+
injectEnvVariables(env)
46+
4047
const functionsPort = await acquirePort({
4148
configuredPort: options.port || config.dev?.functionsPort,
4249
defaultPort: DEFAULT_PORT,
@@ -49,8 +56,11 @@ export const functionsServe = async (options: OptionValues, command: BaseCommand
4956
siteID: site.id ?? UNLINKED_SITE_MOCK_ID,
5057
})
5158

59+
const aiGatewayContext = parseAIGatewayContext(env.AI_GATEWAY?.value)
60+
5261
await startFunctionsServer({
5362
loadDistFunctions: process.env.NETLIFY_FUNCTIONS_SERVE_LOAD_DIST_FUNCTIONS === 'true',
63+
aiGatewayContext,
5464
blobsContext,
5565
config,
5666
debug: options.debug,

src/lib/functions/netlify-function.ts

Lines changed: 10 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -10,6 +10,7 @@ import semver from 'semver'
1010
import { logAndThrowError, type NormalizedCachedConfigConfig } from '../../utils/command-helpers.js'
1111
import { BACKGROUND } from '../../utils/functions/get-functions.js'
1212
import { type BlobsContextWithEdgeAccess, getBlobsEventProperty } from '../blobs/blobs.js'
13+
import type { AIGatewayContext } from '@netlify/ai/bootstrap'
1314
import type { ServerSettings } from '../../utils/types.js'
1415

1516
import type { BaseBuildResult, InvokeFunctionResult, Runtime } from './runtimes/index.js'
@@ -42,6 +43,7 @@ const getNextRun = function (schedule: string) {
4243
}
4344

4445
export default class NetlifyFunction<BuildResult extends BaseBuildResult> {
46+
private readonly aiGatewayContext?: AIGatewayContext | null
4547
private readonly blobsContext: BlobsContextWithEdgeAccess
4648
private readonly config: NormalizedCachedConfigConfig
4749
private readonly directory?: string
@@ -74,6 +76,7 @@ export default class NetlifyFunction<BuildResult extends BaseBuildResult> {
7476
private srcFiles = new Set<string>()
7577

7678
constructor({
79+
aiGatewayContext,
7780
blobsContext,
7881
config,
7982
directory,
@@ -87,6 +90,7 @@ export default class NetlifyFunction<BuildResult extends BaseBuildResult> {
8790
timeoutBackground,
8891
timeoutSynchronous,
8992
}: {
93+
aiGatewayContext?: AIGatewayContext | null
9094
blobsContext: BlobsContextWithEdgeAccess
9195
config: NormalizedCachedConfigConfig
9296
directory?: string
@@ -101,6 +105,7 @@ export default class NetlifyFunction<BuildResult extends BaseBuildResult> {
101105
timeoutBackground?: number
102106
timeoutSynchronous?: number
103107
}) {
108+
this.aiGatewayContext = aiGatewayContext
104109
this.blobsContext = blobsContext
105110
this.config = config
106111
this.directory = directory
@@ -284,6 +289,11 @@ export default class NetlifyFunction<BuildResult extends BaseBuildResult> {
284289
event.blobs = Buffer.from(payload).toString('base64')
285290
}
286291

292+
if (this.aiGatewayContext) {
293+
const payload = JSON.stringify(this.aiGatewayContext)
294+
event.aiGateway = Buffer.from(payload).toString('base64')
295+
}
296+
287297
try {
288298
const result = await this.runtime.invokeFunction({
289299
context,

0 commit comments

Comments
 (0)