UNPKG

openclaw

Version:

Multi-channel AI gateway with extensible messaging integrations

177 lines (176 loc) 7.71 kB
import { c as normalizeOptionalString } from "../../string-coerce-mnp54Vah.js"; import { n as ensureAuthProfileStore } from "../../store-C8spD0DG.js"; import { t as normalizeOptionalSecretInput } from "../../normalize-secret-input-OwRUfByL.js"; import { n as listProfilesForProvider } from "../../profile-list-DI8_o0Rw.js"; import { s as upsertAuthProfileWithLock } from "../../profiles-BMWtmBgj.js"; import "../../string-coerce-runtime-CEGJWkQ_.js"; import { t as definePluginEntry } from "../../plugin-entry-C7DUzV0e.js"; import { i as normalizeApiKeyInput, n as ensureApiKeyFromOptionEnvOrPrompt, s as validateApiKeyInput } from "../../provider-auth-input-CjZ71i7e.js"; import { n as buildApiKeyCredential, t as applyAuthProfileConfig } from "../../provider-auth-helpers-BgLOn-Ws.js"; import "../../provider-auth-DAOC_qI9.js"; import { n as CLOUDFLARE_AI_GATEWAY_DEFAULT_MODEL_REF } from "../../models-Ds0snX1K.js"; import { t as buildCloudflareAiGatewayCatalogProvider } from "../../catalog-provider-BrPUPZrU.js"; import { r as buildCloudflareAiGatewayConfigPatch, t as applyCloudflareAiGatewayConfig } from "../../onboard-KAsbd0d0.js"; import { r as wrapCloudflareAiGatewayProviderStream } from "../../stream-wrappers-au8AjR2X.js"; //#region extensions/cloudflare-ai-gateway/index.ts /** * Bundled provider plugin entry for Cloudflare AI Gateway setup, catalog * discovery, failover classification, and stream wrapping. */ const PROVIDER_ID = "cloudflare-ai-gateway"; const PROVIDER_ENV_VAR = "CLOUDFLARE_AI_GATEWAY_API_KEY"; const PROFILE_ID = "cloudflare-ai-gateway:default"; async function upsertAuthProfileWithLockOrThrow(params) { if (!await upsertAuthProfileWithLock(params)) throw new Error("Failed to update auth profile store; the auth store lock may be busy. Wait a moment and retry."); } function readRequiredTextInput(value) { return typeof value === "string" ? value.trim() : ""; } async function resolveCloudflareGatewayMetadataInteractive(ctx) { let accountId = normalizeOptionalString(ctx.accountId) ?? ""; let gatewayId = normalizeOptionalString(ctx.gatewayId) ?? ""; if (!accountId) accountId = readRequiredTextInput(await ctx.prompter.text({ message: "Enter Cloudflare Account ID", validate: (val) => readRequiredTextInput(val) ? void 0 : "Account ID is required" })); if (!gatewayId) gatewayId = readRequiredTextInput(await ctx.prompter.text({ message: "Enter Cloudflare AI Gateway ID", validate: (val) => readRequiredTextInput(val) ? void 0 : "Gateway ID is required" })); return { accountId, gatewayId }; } var cloudflare_ai_gateway_default = definePluginEntry({ id: PROVIDER_ID, name: "Cloudflare AI Gateway Provider", description: "Bundled Cloudflare AI Gateway provider plugin", register(api) { api.registerProvider({ id: PROVIDER_ID, label: "Cloudflare AI Gateway", docsPath: "/providers/cloudflare-ai-gateway", envVars: ["CLOUDFLARE_AI_GATEWAY_API_KEY"], auth: [{ id: "api-key", label: "Cloudflare AI Gateway", hint: "Account ID + Gateway ID + API key", kind: "api_key", wizard: { choiceId: "cloudflare-ai-gateway-api-key", choiceLabel: "Cloudflare AI Gateway", choiceHint: "Account ID + Gateway ID + API key", groupId: "cloudflare-ai-gateway", groupLabel: "Cloudflare AI Gateway", groupHint: "Account ID + Gateway ID + API key" }, run: async (ctx) => { const metadata = await resolveCloudflareGatewayMetadataInteractive({ accountId: normalizeOptionalSecretInput(ctx.opts?.cloudflareAiGatewayAccountId), gatewayId: normalizeOptionalSecretInput(ctx.opts?.cloudflareAiGatewayGatewayId), prompter: ctx.prompter }); let capturedSecretInput = ""; let capturedCredential = false; let capturedMode; await ensureApiKeyFromOptionEnvOrPrompt({ token: normalizeOptionalSecretInput(ctx.opts?.cloudflareAiGatewayApiKey), tokenProvider: "cloudflare-ai-gateway", secretInputMode: ctx.allowSecretRefPrompt === false ? ctx.secretInputMode ?? "plaintext" : ctx.secretInputMode, config: ctx.config, expectedProviders: [PROVIDER_ID], provider: PROVIDER_ID, envLabel: PROVIDER_ENV_VAR, promptMessage: "Enter Cloudflare AI Gateway API key", normalize: normalizeApiKeyInput, validate: validateApiKeyInput, prompter: ctx.prompter, setCredential: async (apiKey, mode) => { capturedSecretInput = apiKey; capturedCredential = true; capturedMode = mode; } }); if (!capturedCredential) throw new Error("Missing Cloudflare AI Gateway API key."); return { profiles: [{ profileId: PROFILE_ID, credential: buildApiKeyCredential(PROVIDER_ID, capturedSecretInput ?? "", { accountId: metadata.accountId, gatewayId: metadata.gatewayId }, capturedMode ? { secretInputMode: capturedMode } : void 0) }], configPatch: buildCloudflareAiGatewayConfigPatch(metadata), defaultModel: CLOUDFLARE_AI_GATEWAY_DEFAULT_MODEL_REF }; }, runNonInteractive: async (ctx) => { const authStore = ensureAuthProfileStore(ctx.agentDir, { allowKeychainPrompt: false }); const storedMetadata = authStore.profiles[PROFILE_ID]?.type === "api_key" ? { accountId: normalizeOptionalString(authStore.profiles[PROFILE_ID]?.metadata?.accountId), gatewayId: normalizeOptionalString(authStore.profiles[PROFILE_ID]?.metadata?.gatewayId) } : {}; const accountId = normalizeOptionalSecretInput(ctx.opts.cloudflareAiGatewayAccountId) ?? storedMetadata.accountId; const gatewayId = normalizeOptionalSecretInput(ctx.opts.cloudflareAiGatewayGatewayId) ?? storedMetadata.gatewayId; if (!accountId || !gatewayId) { ctx.runtime.error("Cloudflare AI Gateway setup requires --cloudflare-ai-gateway-account-id and --cloudflare-ai-gateway-gateway-id."); ctx.runtime.exit(1); return null; } const resolved = await ctx.resolveApiKey({ provider: PROVIDER_ID, flagValue: normalizeOptionalSecretInput(ctx.opts.cloudflareAiGatewayApiKey), flagName: "--cloudflare-ai-gateway-api-key", envVar: PROVIDER_ENV_VAR }); if (!resolved) return null; if (resolved.source !== "profile") { const credential = ctx.toApiKeyCredential({ provider: PROVIDER_ID, resolved, metadata: { accountId, gatewayId } }); if (!credential) return null; await upsertAuthProfileWithLockOrThrow({ profileId: PROFILE_ID, credential, agentDir: ctx.agentDir }); } return applyCloudflareAiGatewayConfig(applyAuthProfileConfig(ctx.config, { profileId: PROFILE_ID, provider: PROVIDER_ID, mode: "api_key" }), { accountId, gatewayId }); } }], catalog: { order: "late", run: async (ctx) => { const authStore = ensureAuthProfileStore(ctx.agentDir, { allowKeychainPrompt: false }); const envManagedApiKey = normalizeOptionalString(ctx.env[PROVIDER_ENV_VAR]) ? PROVIDER_ENV_VAR : void 0; for (const profileId of listProfilesForProvider(authStore, PROVIDER_ID)) { const provider = buildCloudflareAiGatewayCatalogProvider({ credential: authStore.profiles[profileId], envApiKey: envManagedApiKey }); if (!provider) continue; return { provider }; } return null; } }, classifyFailoverReason: ({ errorMessage }) => /\bworkers?_ai\b.*\b(?:rate|limit|quota)\b/i.test(errorMessage) ? "rate_limit" : void 0, wrapStreamFn: wrapCloudflareAiGatewayProviderStream }); } }); //#endregion export { cloudflare_ai_gateway_default as default };