Download packages/core/src/plugin/provider/cloudflare-ai-gateway.ts from SaylorTwift/opencode: direct link, hf CLI and curl.
- Browser
- Download file 3.69 kB
-
https://huggingface.co/SaylorTwift/opencode/resolve/main/packages/core/src/plugin/provider/cloudflare-ai-gateway.ts
- Command line
-
hf download hf://SaylorTwift/opencode/packages/core/src/plugin/provider/cloudflare-ai-gateway.ts
-
curl -L -o cloudflare-ai-gateway.ts https://huggingface.co/SaylorTwift/opencode/resolve/main/packages/core/src/plugin/provider/cloudflare-ai-gateway.ts
3.69 kB
| import os from "os" | |
| import { InstallationVersion } from "../../installation/version" | |
| import { Effect, Option, Schema } from "effect" | |
| import { define } from "../internal" | |
| export const CloudflareAIGatewayPlugin = define({ | |
| id: "cloudflare-ai-gateway", | |
| effect: Effect.fn(function* (ctx) { | |
| yield* ctx.aisdk.sdk( | |
| Effect.fn(function* (evt) { | |
| if (evt.package !== "ai-gateway-provider") return | |
| if (evt.options.baseURL) return | |
| const config = gatewayConfig(evt.options) | |
| if (!config) return | |
| const metadata = gatewayMetadata(evt.options) | |
| const { createAiGateway } = yield* Effect.promise(() => import("ai-gateway-provider")).pipe(Effect.orDie) | |
| const { createUnified } = yield* Effect.promise(() => import("ai-gateway-provider/providers/unified")).pipe( | |
| Effect.orDie, | |
| ) | |
| const gateway = createAiGateway({ | |
| accountId: config.accountId, | |
| gateway: config.gatewayId, | |
| apiKey: config.apiKey, | |
| options: gatewayOptions(evt.options, metadata), | |
| } as any) | |
| evt.sdk = { | |
| languageModel(modelID: string) { | |
| // Workers AI is the only first-party provider whose upstream is Cloudflare itself, so it is | |
| // the only one that should receive the Cloudflare token as its upstream Authorization header. | |
| // The Unified API addresses Workers AI both with the explicit "workers-ai/" prefix and as | |
| // bare "@cf/..." ids. Third-party providers must not receive the token; they rely on the | |
| // gateway's stored/BYOK keys instead. | |
| const isWorkersAi = modelID.startsWith("workers-ai/") || modelID.startsWith("@cf/") | |
| const unified = createUnified(isWorkersAi ? { apiKey: config.apiKey } : {}) | |
| return gateway(unified(modelID)) | |
| }, | |
| } | |
| }), | |
| ) | |
| }), | |
| }) | |
| type GatewayConfig = { | |
| accountId: string | |
| gatewayId: string | |
| apiKey: string | |
| } | |
| const decodeJson = Schema.decodeUnknownOption(Schema.UnknownFromJsonString) | |
| function gatewayConfig(options: Record<string, unknown>): GatewayConfig | undefined { | |
| const accountId = process.env.CLOUDFLARE_ACCOUNT_ID ?? stringOption(options, "accountId") | |
| // Credential projection copies key metadata into options. The prompt stores the | |
| // gateway as gatewayId, while older config examples may use gateway. | |
| const gatewayId = | |
| process.env.CLOUDFLARE_GATEWAY_ID ?? stringOption(options, "gatewayId") ?? stringOption(options, "gateway") | |
| const apiKey = process.env.CLOUDFLARE_API_TOKEN ?? process.env.CF_AIG_TOKEN ?? stringOption(options, "apiKey") | |
| if (!accountId || !gatewayId || !apiKey) return undefined | |
| return { accountId, gatewayId, apiKey } | |
| } | |
| function gatewayMetadata(options: Record<string, unknown>) { | |
| // Preserve the legacy cf-aig-metadata header escape hatch for gateway logging | |
| // metadata, but prefer the typed metadata option when present. | |
| if (options.metadata !== undefined) return options.metadata | |
| const raw = (options.headers as Record<string, string> | undefined)?.["cf-aig-metadata"] | |
| return raw ? Option.getOrUndefined(decodeJson(raw)) : undefined | |
| } | |
| function gatewayOptions(options: Record<string, unknown>, metadata: unknown) { | |
| return { | |
| metadata, | |
| cacheTtl: options.cacheTtl, | |
| cacheKey: options.cacheKey, | |
| skipCache: options.skipCache, | |
| collectLog: options.collectLog, | |
| headers: { | |
| "User-Agent": `opencode/${InstallationVersion} cloudflare-ai-gateway (${os.platform()} ${os.release()}; ${os.arch()})`, | |
| }, | |
| } | |
| } | |
| function stringOption(options: Record<string, unknown>, key: string) { | |
| return typeof options[key] === "string" ? options[key] : undefined | |
| } | |