Source & license
Upstream license: AGPL-3.0
License TL;DR
You can use and change it, even commercially. If people use your modified version over a network, offer them its corresponding source under the AGPL. Sharing copies has source-sharing duties too. Sharing source code is different from sharing users’ content.
Explain AGPL v3 in plain English →Summary of the main license. Separate packages and assets can have different terms.
Inspect repository ↗Read this project’s actual license ↗Repository owner
See the upstream repository for the original creator and contributors.
Maintain this project? Maintainer verification →Cloudflare hosting
Free tier eligible within limits
Light personal or small-team traffic can start on the Workers Free plan with D1. Each proxied request counts as Worker requests and D1 writes for logs; Free plan CPU per request and daily request limits cap throughput, and model-provider charges are always separate.
Hosting requirements
- Model usage is billed by each upstream provider under the operator’s own keys; Octafuse records costs but does not pay them.
- The repository ships base templates; `npm run gen:wrangler` generates the deployable Wrangler files.
- Licensed AGPL-3.0: modified versions offered to users over a network must make their source available.
- Source and configuration review establishes a deployment path and conditional costs; this candidate was not executed or load-tested.
- Official Cloudflare pricing pages saved 31 Oct 2026 (Markdown editions of developers.cloudflare.com pricing documentation).
Review findings & limitations
- Model usage is billed by each upstream provider under the operator’s own keys; Octafuse records costs but does not pay them.
- The repository ships base templates; `npm run gen:wrangler` generates the deployable Wrangler files.
- Licensed AGPL-3.0: modified versions offered to users over a network must make their source available.
- Competitor links describe the stated workflow overlap, not feature parity or a verified price saving.
- Source review at the pinned commit; deployment, workload CPU and application security have not been independently tested.
Sources checked 31/10/2026
Repository snapshot: be74c9c. Hosting eligibility reflects the deployment documentation and listed assumptions.
- openrouter ↗
**Octafuse Gateway** 是面向 Agent 的可自托管开源 AI 网关。它将不同供应商的文本、图像、语音与工具能力汇聚到统一入口,支持 Chat Completions、OpenAI Responses API、图像生成与编辑、ASR、TTS、实时语音和智能体工具(Agent Tools),也可以接入自建或私有部署的 AI 服务。通过统一的路由、密钥、预算、计费和审计,Octafuse 帮助个人与团队集中管理和调度分散的 AI 资源。它不只是转发模型请求,更是面向 Agent 的可发现、可调用、可治理、可持续扩展的 AI 能力底座。
- portkey ↗
**Octafuse Gateway** 是面向 Agent 的可自托管开源 AI 网关。它将不同供应商的文本、图像、语音与工具能力汇聚到统一入口,支持 Chat Completions、OpenAI Responses API、图像生成与编辑、ASR、TTS、实时语音和智能体工具(Agent Tools),也可以接入自建或私有部署的 AI 服务。通过统一的路由、密钥、预算、计费和审计,Octafuse 帮助个人与团队集中管理和调度分散的 AI 资源。它不只是转发模型请求,更是面向 Agent 的可发现、可调用、可治理、可持续扩展的 AI 能力底座。
- workers ↗
xample`;生产用 Dashboard Secrets 或 `npx wrangler secret put ADMIN_PASSWORD --name <worker>`。 "$schema": "./node_modules/wrangler/config-schema.json", "main": ".open-next/worker.js", "name": "octafuse-gateway-admin", "compatibility_date": "2025-11-25", "compatibility_flags": ["nodejs_compat"], "assets": { "directory": ".open-next/assets", "binding": "ASSETS" }, "d1_databases": [ { "binding": "DB", "database_name": "octafuse-gateway" } ], "observability": { "enabled": true, "h
- d1 ↗
atibility_flags": ["nodejs_compat"], "assets": { "directory": ".open-next/assets", "binding": "ASSETS" }, "d1_databases": [ { "binding": "DB", "database_name": "octafuse-gateway" } ], "observability": { "enabled": true, "head_sampling_rate": 1 }, "vars": { "ADMIN_USERNAME": "admin", // Admin 无 Next middleware.ts。Workerd 上 getMiddlewareManifest() 的动态 require 会 500; // 上游 issue 仍 open 时用 minimal mode 跳过该路径(见 opennextjs-cloudflare#1232)。 "NEXT_PRIVATE_MINIMAL_MODE": "
- free-tier-eligible ↗
| **Free** | 100,000 per day | No charge for duration | 10 milliseconds of CPU time per invocation |
- free-tier-eligible ↗
| Rows read | 5 million / day | First 25 billion / month included + $0.001 / million rows |
- AGPL-3.0 ↗
GNU AFFERO GENERAL PUBLIC LICENSE Version 3, 19 November 2007 Copyright (C) 2007 Free Software Foundation, Inc. <https://fsf.org/> Everyone is permitted to copy and distribute verbatim copies of this license document, but changing it is not allowed. Preamble The GNU Affero General Public License is a free, copyleft license for software and other kinds of works, specifically designed to ensure cooperation with the community in the case of network server software. The licenses for most software and other practical works are designed to take away your freedom to share and change the works. By contrast, our General Public Licenses are intended to guarantee your freedom to share and change all versions of a program--to make sure it remains free software for all its users. When we speak of free software, we are referring to freedom, not price. Our General Public Licenses are designed to make sure that you
- architecture ↗
"name": "octafuse-gateway-proxy"
- architecture ↗
"database_name": "octafuse-gateway"
- architecture ↗
xample`;生产用 Dashboard Secrets 或 `npx wrangler secret put ADMIN_PASSWORD --name <worker>`。 "$schema": "./node_modules/wrangler/config-schema.json", "main": ".open-next/worker.js", "name": "octafuse-gateway-admin", "compatibility_date": "2025-11-25", "compatibility_flags": ["nodejs_compat"], "assets": { "directory": ".open-next/assets", "binding": "ASSETS" }, "d1_databases": [ { "binding": "DB", "database_name": "octafuse-gateway" } ], "observability": { "enabled": true, "h
- architecture ↗
atibility_flags": ["nodejs_compat"], "assets": { "directory": ".open-next/assets", "binding": "ASSETS" }, "d1_databases": [ { "binding": "DB", "database_name": "octafuse-gateway" } ], "observability": { "enabled": true, "head_sampling_rate": 1 }, "vars": { "ADMIN_USERNAME": "admin", // Admin 无 Next middleware.ts。Workerd 上 getMiddlewareManifest() 的动态 require 会 500; // 上游 issue 仍 open 时用 minimal mode 跳过该路径(见 opennextjs-cloudflare#1232)。 "NEXT_PRIVATE_MINIMAL_MODE": "
Upstream screenshot · OctaFuse/octafuse-gateway repository contributors ↗. Depicts the upstream project. We have not deployed and tested a fresh installation here.
What it can replace
Compare the workflow you need. These mappings describe overlap; full feature parity requires a separate comparison.
One OpenAI-compatible endpoint and key across your own provider accounts, with model routing, fallbacks, budgets and usage logs; it does not resell model access, and every provider is billed separately
See supporting source ↗One OpenAI-compatible endpoint and key across your own provider accounts, with model routing, fallbacks, budgets and usage logs; it does not resell model access, and every provider is billed separately
See supporting source ↗How it works
The shape of Octafuse Gateway on Cloudflare, and how it stacks up against the rented tools it replaces.
Architecture
Diagram of deployment declarations at the reviewed commit. Each app has its own entrypoint; declared resources do not prove runtime calls. Follow file and line sources below.
View upstream source ↗Configuration and workflow sources
Reviewed commit be74c9c6778d. This configuration evidence comes from reading source files. Execution checks, when available, appear in the project's runtime review.
Partial source coverage: 1 files outside collection bounds; 0 collection or parsing issues. Dynamic imports and generated entrypoints may need manual review.
Deployment configuration · 3 files
Cloudflare Workers · compatibility 2025-11-25
octafuse-gateway-admin · default
Entrypoint: .open-next/worker.js
Static assets: .open-next/assets
DB→ D1ASSETS→ Static assets
Cloudflare Workers · compatibility 2025-04-01
octafuse-d1-migrations · default
DB→ D1
Cloudflare Workers · compatibility 2025-04-01
octafuse-gateway-proxy · default
Entrypoint: src/index.ts
DB→ D1
Named environments are separate deployments. Bindings are shown only where declared. Configured routes are URL patterns, not verified application endpoints.
Runtime source · handlers, binding usage and workflow steps
Observed TypeScript/JavaScript declarations from Worker entrypoints and resolved relative imports. Calls and workflow steps may run conditionally; their listed order is not a proven end-to-end request flow. Router declarations may be mounted under a prefix or may not be registered. This shows code wiring, not a successful deployment or runtime test. Dynamic wiring, aliases and generated code may not resolve.
- L47 · Next.js GET request handler exported · calls handle
- L48 · Next.js POST request handler exported · calls handle
- L49 · Next.js PUT request handler exported · calls handle
- L50 · Next.js PATCH request handler exported · calls handle
- L51 · Next.js DELETE request handler exported · calls handle
- L52 · Next.js OPTIONS request handler exported · calls handle
- L16 · handle calls (conditional paths may differ): resolveAdminRequestRuntime, authenticateAdminRequest, logAdminAuthEvent, getBearerKeyPrefix, Response.json, rewriteToInternalAdminPath, getAdminApp, isSameOriginBrowserWrite, app.fetch, handleGatewayApiError
- L10 · Next.js GET request handler exported · calls cookies, cookieStore.get, resolveAdminRequestRuntime, storage.repositories.adminAccess.getValidSession, hashSessionToken, toISOString, Response.json, console.error
- L10 · GET calls (conditional paths may differ): cookies, cookieStore.get, resolveAdminRequestRuntime, storage.repositories.adminAccess.getValidSession, hashSessionToken, toISOString, Response.json, console.error
- L17 · Next.js POST request handler exported · calls request.json, then, m.getCloudflareContext, console.error, Response.json, timingSafeEqualSecret, String, logAdminAuthEvent, setTimeout, generateSessionToken, expiresAt.setHours, expiresAt.getHours, resolveAdminRequestRuntime, toISOString, storage.repositories.adminAccess.deleteExpiredSessions, storage.repositories.adminAccess.insertSession, hashSessionToken, expiresAt.toISOString, cookies, cookieStore.set, resolveCookieSecure
- L91 · Next.js DELETE request handler exported · calls cookies, cookieStore.get, resolveAdminRequestRuntime, storage.repositories.adminAccess.deleteSession, hashSessionToken, cookieStore.delete, logAdminAuthEvent, Response.json, console.error
- L17 · POST calls (conditional paths may differ): request.json, then, m.getCloudflareContext, console.error, Response.json, timingSafeEqualSecret, String, logAdminAuthEvent, setTimeout, generateSessionToken, expiresAt.setHours, expiresAt.getHours, resolveAdminRequestRuntime, toISOString, storage.repositories.adminAccess.deleteExpiredSessions, storage.repositories.adminAccess.insertSession, hashSessionToken, expiresAt.toISOString, cookies, cookieStore.set
- L91 · DELETE calls (conditional paths may differ): cookies, cookieStore.get, resolveAdminRequestRuntime, storage.repositories.adminAccess.deleteSession, hashSessionToken, cookieStore.delete, logAdminAuthEvent, Response.json, console.error
Environment references: env.ADMIN_USERNAME · env.ADMIN_PASSWORD · process.env.ADMIN_USERNAME · process.env.ADMIN_PASSWORD
- L11 · Next.js POST request handler exported · calls cookies, cookieStore.get, resolveAdminRequestRuntime, storage.repositories.adminAccess.deleteSession, hashSessionToken, cookieStore.delete, logAdminAuthEvent, Response.json, console.error
- L11 · POST calls (conditional paths may differ): cookies, cookieStore.get, resolveAdminRequestRuntime, storage.repositories.adminAccess.deleteSession, hashSessionToken, cookieStore.delete, logAdminAuthEvent, Response.json, console.error
- L5 · resolveWorkersStorage calls (conditional paths may differ): resolveWorkerDatabaseConfig, createD1StorageContext
- L112 · app.use("*")
- L115 · app.use("*")
- L116 · app.use("*")
- L131 · app.use("*")
- L153 · app.use("*")
- L160 · app.use("*")
- L162 · app.route("/health")
- L163 · app.route("/v1/chat/completions")
- L164 · app.route("/v1/responses")
- L165 · app.route("/v1/embeddings")
- L166 · app.route("/v1/images")
- L167 · app.route("/v1/audio")
- L179 · app.route("/elevenlabs/v1/speech-to-text")
- L180 · app.route("/elevenlabs/v1/text-to-speech")
- L196 · app.route("/v1/messages")
- L204 · app.route("/messages")
- L205 · app.route("/v1/v1/messages")
- L206 · app.route("/v1beta")
- L207 · app.route("/v1/me")
- L208 · app.route("/v1/models")
- L209 · app.route("/v1/tools/web-search")
- L210 · app.route("/v1/tools/web-fetch")
- L211 · app.route("/v1/tools/web-deep-search")
- L212 · app.route("/v1/tools/ai-detection")
- L213 · app.route("/v1/tools/pricing")
- L214 · app.route("/mcp")
- L215 · app.route("/.well-known/oauth-protected-resource")
- L216 · app.route("/catalog")
- L218 · app.get("/")
- L108 · createProxyApp calls (conditional paths may differ): app.use, logger, cors, next, c.res.headers.get, contentType.includes, c.res.clone, cloned.text, text.slice, console.warn, resolveStorage, c.set, app.route, app.get, c.json
- L52 · isAnthropicMessagesPath calls (conditional paths may differ): path.startsWith
- L63 · maskKey calls (conditional paths may differ): key.slice
- L72 · extractApiKey calls (conditional paths may differ): c.req.header, test, trim, auth.slice, isRealtimeUpgradePath, parseDashScopeRealtimeAuthProtocol, isAnthropicMessagesPath, path.startsWith, url.searchParams.get
- L131 · readJsonRpcMethod calls (conditional paths may differ): text, c.req.raw.clone, JSON.parse, Array.isArray
- L150 · isToolPriceCheckedRoute calls (conditional paths may differ): test
- L13 · healthRoutes.get("/")
- L54 · chatRoutes.use("*")
- L57 · chatRoutes.post("/")
- L21 · openAiBodyRedactedForLog calls (conditional paths may differ): Object.entries, Object.assign, summarizeOpenAiToolsForLog, Array.isArray, summarizeMessagesShapeForLog
- L41 · openAiRequestBodyForLog calls (conditional paths may differ): finalizeRequestLogJson, openAiBodyRedactedForLog
- L46 · openAiUpstreamWireBodyForLog calls (conditional paths may differ): buildRouteRequestBody, finalizeRequestLogJson, openAiBodyRedactedForLog
- L73 · responsesRoutes.use("*")
- L75 · responsesRoutes.post("/")
- L22 · responsesBodyRedactedForLog calls (conditional paths may differ): Object.entries, Object.assign, summarizeOpenAiToolsForLog, Array.isArray, summarizeMessagesShapeForLog
- L47 · responsesRequestBodyForLog calls (conditional paths may differ): finalizeRequestLogJson, responsesBodyRedactedForLog
- L51 · responsesUpstreamWireBodyForLog calls (conditional paths may differ): buildRouteRequestBody, finalizeRequestLogJson, responsesBodyRedactedForLog
- L57 · readPreviousResponseId calls (conditional paths may differ): raw.trim
- L65 · responsesStateRouteUnavailable calls (conditional paths may differ): filter, routes.map
- L46 · embeddingsRoutes.use("*")
- L49 · embeddingsRoutes.post("/")
- L19 · embeddingsBodyRedactedForLog calls (conditional paths may differ): Object.entries, Array.isArray
- L34 · embeddingsRequestBodyForLog calls (conditional paths may differ): finalizeRequestLogJson, embeddingsBodyRedactedForLog
- L38 · embeddingsUpstreamWireBodyForLog calls (conditional paths may differ): buildRouteRequestBody, finalizeRequestLogJson, embeddingsBodyRedactedForLog
- L130 · geminiRoutes.use("*")
- L133 · geminiRoutes.post("/models/:modelAction")
- L34 · geminiBodyRedactedForLog calls (conditional paths may differ): Object.entries, Object.assign, summarizeGeminiToolsForLog, Array.isArray
- L58 · geminiRequestBodyForLog calls (conditional paths may differ): finalizeRequestLogJson, geminiBodyRedactedForLog
- L63 · geminiUpstreamWireBodyForLog calls (conditional paths may differ): buildRouteRequestBody, finalizeRequestLogJson, geminiBodyRedactedForLog
- L73 · geminiEmbedBodyRedactedForLog calls (conditional paths may differ): Object.entries, Array.isArray
- L90 · geminiEmbedUpstreamWireBodyForLog calls (conditional paths may differ): buildRouteRequestBody, finalizeRequestLogJson, geminiEmbedBodyRedactedForLog
- L100 · parseGeminiEmbedAction calls (conditional paths may differ): modelAction.lastIndexOf, trim, modelAction.slice
- L114 · parseGeminiAction calls (conditional paths may differ): modelAction.lastIndexOf, trim, modelAction.slice
- L53 · messagesRoutes.use("*")
- L56 · messagesRoutes.post("/")
- L20 · anthropicBodyRedactedForLog calls (conditional paths may differ): Object.entries, Object.assign, summarizeAnthropicToolsForLog, Array.isArray, summarizeMessagesShapeForLog
- L40 · anthropicRequestBodyForLog calls (conditional paths may differ): finalizeRequestLogJson, anthropicBodyRedactedForLog
- L45 · anthropicUpstreamWireBodyForLog calls (conditional paths may differ): buildRouteRequestBody, finalizeRequestLogJson, anthropicBodyRedactedForLog
- L17 · catalogRoutes.get("/models")
- L83 · imageRoutes.use("*")
- L761 · imageRoutes.post("/generations")
- L1020 · imageRoutes.post("/edits")
- L85 · resolveOpenAiImageRoutes calls (conditional paths may differ): resolveModelRouting, truncateModelIdForLog, console.warn, loadProxyRouteSurface
- L146 · modelDisplayName calls (conditional paths may differ): trim, String
- L153 · truncateModelIdForLog calls (conditional paths may differ): rawModelId.trim, trimmed.slice
- L167 · validateImagesEditsContentType calls (conditional paths may differ): trim, startsWith, ct.toLowerCase
- L176 · summarizeBodyKeys calls (conditional paths may differ): slice, map, Object.keys, Array.isArray
- L214 · rejectImageRequest calls (conditional paths may differ): c.get, console.warn, c.req.header, truncateModelIdForLog, gatewayErrorJson
- L260 · parseMultipartEdits calls (conditional paths may differ): c.req.header, validateImagesEditsContentType, c.req.parseBody, summarizeBodyKeys, modelRaw.trim, normalizeImageCommonParams, Number.isFinite, file.arrayBuffer, images.push, value.startsWith, Array.isArray, collectFile, Object.entries, test, validateImageUpload, pickFormExtraFields, Object.keys
- L572 · finalizeImageResponse calls (conditional paths may differ): scheduleBackgroundWork, materializeNonOkResponse, proxyResult.usagePromise.catch, countValidImageResults, Date.now, Array.isArray, Number.isFinite, JSON.stringify, text, response.clone, markUserModelSuccess, maybeTriggerUserModelCircuitFromUpstream, response.headers.get, formatHttpErrorTextForRequestLog, finalizeRequestLogJson, redactImageRequestForLog, catch, stickyTrace, recordImageUsage, annotateRequestLogWithExtraFields
- L72 · audioRoutes.use("*")
- L296 · audioRoutes.post("/transcriptions")
- L524 · audioRoutes.post("/speech")
- L74 · resolveOpenAiAudioRoutes calls (conditional paths may differ): resolveModelRouting, truncateModelIdForLog, console.warn, loadProxyRouteSurface
- L135 · modelDisplayName calls (conditional paths may differ): trim, String
- L141 · truncateModelIdForLog calls (conditional paths may differ): rawModelId.trim, trimmed.slice
- L159 · multipartTextField calls (conditional paths may differ): value.trim, Array.isArray, item.trim
- L173 · multipartFileField calls (conditional paths may differ): Array.isArray
- L187 · parseMultipartTranscription calls (conditional paths may differ): c.req.parseBody, multipartTextField, toLowerCase, ALLOWED_RESPONSE_FORMATS.has, Number, Number.isFinite, includes, parsedUrl.toString, multipartFileField, file.arrayBuffer, normalizeAudioMimeType, resolveAudioUploadFilename, validateAudioUpload, pickFormExtraFields, Object.keys
- L444 · parseSpeechVoice calls (conditional paths may differ): value.trim, Array.isArray, trim
- L458 · parseSpeechRequest calls (conditional paths may differ): Array.isArray, value.model.trim, Array.from, parseSpeechVoice, toLowerCase, value.response_format.trim, SPEECH_RESPONSE_FORMATS.has, Number, Number.isFinite, value.stream_format.trim, pickExtraFields, Object.keys
- L640 · finalizeSpeechResponse calls (conditional paths may differ): materializeNonOkResponse, markUserModelSuccess, maybeTriggerUserModelCircuitFromUpstream, response.headers.get, formatHttpErrorTextForRequestLog, scheduleBackgroundWork, catch, then, proxyResult.usagePromise.catch, audioTokenUsageFromCounts, speechErrorMessage, recordAudioUsage, annotateRequestLogWithExtraFields, Date.now, timing.snapshot, console.error, String
- L777 · finalizeAudioResponse calls (conditional paths may differ): scheduleBackgroundWork, materializeNonOkResponse, proxyResult.usagePromise.catch, Date.now, markUserModelSuccess, maybeTriggerUserModelCircuitFromUpstream, response.headers.get, formatHttpErrorTextForRequestLog, catch, stickyTrace, recordAudioUsage, annotateRequestLogWithExtraFields, timing.snapshot, console.error, String
- L58 · dashScopeRealtimeRoutes.use("*")
- L59 · dashScopeRealtimeSessionRoutes.use("*")
- L60 · dashScopeRealtimeInferenceRoutes.use("*")
- L310 · dashScopeRealtimeRoutes.get("/")
- L334 · dashScopeRealtimeSessionRoutes.get("/")
- L509 · dashScopeRealtimeInferenceRoutes.get("/")
- L62 · isRealtimeOperation calls (conditional paths may differ): includes
- L66 · isSpeechOperation calls (conditional paths may differ): operation.startsWith
- L76 · modelDisplayName calls (conditional paths may differ): trim, String
- L81 · recordRealtimeUsage calls (conditional paths may differ): scheduleBackgroundWork, catch, proxyResult.usagePromise.then, realtimeErrorMessage, recordAudioUsage, modelDisplayName, JSON.stringify, Date.now, isSpeechOperation, timing.snapshot, console.error, String
- L181 · requireWebSocketUpgrade calls (conditional paths may differ): c.req.header, gatewayErrorJson
- L190 · failoverOptionsFor calls (conditional paths may differ): buildAffinityKey, buildTierKeyPrefix
- L213 · connectUpfront calls (conditional paths may differ): c.get, resolveModelRouting, gatewayErrorJson, rawModelId.slice, pickOperation, resolveRoutesForSurface, resolveRouteStrategyPlan, proxyDashScopeRealtime, parseDashScopeRealtimeAuthProtocol, c.req.header, failoverOptionsFor, proxyResult.response.headers.get, recordRealtimeUsage
- L359 · describeFailedResponse calls (conditional paths may differ): response.headers.get, json, response.clone
- L391 · runDeferredInferenceSession calls (conditional paths may differ): session.waitForRunTask, session.failAndClose, dashScopeInferenceOperationForTask, fail, resolveModelRouting, request.model.slice, resolveRoutesForSurface, resolveRouteStrategyPlan, proxyDashScopeRealtimeDeferred, failoverOptionsFor, describeFailedResponse, upstream.close, deferred.finishUsage, then, session.bridge, recordRealtimeUsage
Environment references: c.env.NODE_REALTIME_DISPATCH · c.env.NODE_REALTIME_DEFERRED
- L53 · dashScopeMultimodalRoutes.use("*")
- L164 · dashScopeMultimodalRoutes.post("/")
- L57 · redactDashScopeMultimodalBody calls (conditional paths may differ): structuredClone, Array.isArray, DATA_URL_RE.test
- L88 · dashScopeMultimodalOperation calls (conditional paths may differ): isImageGenerationModel, isAudioSpeechModel
- L94 · modelDisplayName calls (conditional paths may differ): trim, String
- L100 · resolveDashScopeMultimodalRoutes calls (conditional paths may differ): resolveModelRouting, slice, rawModelId.trim, resolveRoutesForSurface
- L329 · finalizeMultimodalResponse calls (conditional paths may differ): scheduleBackgroundWork, materializeNonOkResponse, proxyResult.usagePromise.catch, markUserModelSuccess, maybeTriggerUserModelCircuitFromUpstream, response.headers.get, formatHttpErrorTextForRequestLog, catch, stickyTrace, recordImageUsage, Date.now, timing.snapshot, recordAudioUsage, console.error, String
- L39 · dashScopeSpeechRoutes.use("*")
- L41 · dashScopeSpeechRoutes.post("/")
- L80 · forwardDashScopeSpeech calls (conditional paths may differ): resolveRoutesForSurface, gatewayErrorJson, trim, String, apiKeyHasBalance, estimateAudioBudgetPrecheck, routes.map, canAffordAudioCost, finalizeRequestLogJson, maybeBlockUserModelCircuit, resolveRouteStrategyPlan, timing.markGatewayComplete, proxyDashScopeJsonPassthrough, buildAffinityKey, buildTierKeyPrefix, stickyConfigFromSurface, c.req.header, materializeNonOkResponse, markUserModelSuccess, maybeTriggerUserModelCircuitFromUpstream
- L40 · dashScopeFileTranscriptionRoutes.use("*")
- L41 · dashScopeTaskRoutes.use("*")
- L43 · dashScopeFileTranscriptionRoutes.post("/")
- L61 · dashScopeTaskRoutes.get("/:taskId")
- L73 · runAsyncPassthrough calls (conditional paths may differ): c.get, Date.now, resolveModelRouting, gatewayErrorJson, rawModelId.slice, audioModelGuardMessage, resolveRoutesForSurface, apiKeyHasBalance, displayName, finalizeRequestLogJson, maybeBlockUserModelCircuit, resolveRouteStrategyPlan, timing.markGatewayComplete, proxyDashScopeJsonPassthrough, buildAffinityKey, buildTierKeyPrefix, stickyConfigFromSurface, c.req.header, materializeNonOkResponse, markUserModelSuccess
- L256 · displayName calls (conditional paths may differ): trim, String
- L52 · miniMaxSpeechToTextRoutes.use("*")
- L146 · miniMaxSpeechToTextRoutes.post("/")
- L54 · textField calls (conditional paths may differ): Array.isArray, value.find
- L63 · fileField calls (conditional paths may differ): Array.isArray
- L77 · modelDisplayName calls (conditional paths may differ): trim, String
- L83 · resolveMiniMaxSpeechRoutes calls (conditional paths may differ): resolveModelRouting, slice, rawModelId.trim, resolveRoutesForSurface
- L301 · finalizeSpeechResponse calls (conditional paths may differ): scheduleBackgroundWork, materializeNonOkResponse, proxyResult.usagePromise.catch, markUserModelSuccess, maybeTriggerUserModelCircuitFromUpstream, response.headers.get, formatHttpErrorTextForRequestLog, catch, stickyTrace, recordAudioUsage, Date.now, timing.snapshot, console.error, String
- L39 · miniMaxT2aRoutes.use("*")
- L41 · miniMaxT2aRoutes.post("/")
- L79 · forwardMiniMaxSpeech calls (conditional paths may differ): resolveRoutesForSurface, gatewayErrorJson, trim, String, apiKeyHasBalance, estimateAudioBudgetPrecheck, routes.map, canAffordAudioCost, finalizeRequestLogJson, maybeBlockUserModelCircuit, resolveRouteStrategyPlan, timing.markGatewayComplete, proxyMiniMaxJsonPassthrough, buildAffinityKey, buildTierKeyPrefix, stickyConfigFromSurface, materializeNonOkResponse, includes, response.headers.get, markUserModelSuccess
- L59 · elevenLabsSpeechToTextRoutes.use("*")
- L62 · elevenLabsSpeechToTextRoutes.get("/realtime")
- L142 · elevenLabsSpeechToTextRoutes.post("/")
- L65 · textValues calls (conditional paths may differ): Array.isArray, value.filter
- L71 · fileField calls (conditional paths may differ): Array.isArray
- L81 · resolveElevenLabsSttRoutes calls (conditional paths may differ): resolveModelRouting, slice, rawModelId.trim, audioModelGuardMessage, resolveRoutesForSurface
- L312 · finalizeSpeechResponse calls (conditional paths may differ): scheduleBackgroundWork, materializeNonOkResponse, proxyResult.usagePromise.catch, markUserModelSuccess, maybeTriggerUserModelCircuitFromUpstream, response.headers.get, formatHttpErrorTextForRequestLog, catch, stickyTrace, recordAudioUsage, Date.now, timing.snapshot, console.error, String
- L53 · elevenLabsTextToSpeechRoutes.use("*")
- L67 · elevenLabsTextToSpeechRoutes.get("/:voiceId/stream-input")
- L69 · handleElevenLabsSpeech calls (conditional paths may differ): c.get, Date.now, c.req.param, isValidElevenLabsVoiceId, gatewayErrorJson, c.req.json, Array.isArray, requestBody.model_id.trim, text.trim, resolveModelRouting, rawModelId.slice, audioModelGuardMessage, forwardElevenLabsSpeech, c.req.query, Array.from
- L130 · forwardElevenLabsSpeech calls (conditional paths may differ): resolveRoutesForSurface, gatewayErrorJson, trim, String, apiKeyHasBalance, estimateAudioSpeechBudgetPrecheck, routes.map, canAffordAudioCost, finalizeRequestLogJson, Object.keys, maybeBlockUserModelCircuit, resolveRouteStrategyPlan, timing.markGatewayComplete, proxyElevenLabsTtsPassthrough, buildAffinityKey, buildTierKeyPrefix, stickyConfigFromSurface, materializeNonOkResponse, markUserModelSuccess, maybeTriggerUserModelCircuitFromUpstream
- L40 · miniMaxImageGenerationRoutes.use("*")
- L61 · miniMaxImageGenerationRoutes.post("/")
- L42 · redactMiniMaxImageBody calls (conditional paths may differ): structuredClone, Array.isArray, DATA_URL_RE.test
- L56 · requestedImageCount calls (conditional paths may differ): Number, Number.isFinite, Math.floor
- L98 · forwardMiniMaxImage calls (conditional paths may differ): resolveRoutesForSurface, gatewayErrorJson, trim, String, apiKeyHasBalance, estimateImageBudgetPrecheck, requestedImageCount, routes.map, canAffordImageCost, finalizeRequestLogJson, redactMiniMaxImageBody, maybeBlockUserModelCircuit, resolveRouteStrategyPlan, timing.markGatewayComplete, proxyMiniMaxJsonPassthrough, buildAffinityKey, buildTierKeyPrefix, stickyConfigFromSurface, materializeNonOkResponse, proxyResult.usagePromise.catch
- L43 · volcengineImageGenerationRoutes.use("*")
- L61 · volcengineImageGenerationRoutes.post("/")
- L45 · redactImageValue calls (conditional paths may differ): DATA_URL_RE.test, Array.isArray, value.map
- L55 · redactVolcengineImageBody calls (conditional paths may differ): structuredClone, redactImageValue
- L98 · forwardVolcengineImage calls (conditional paths may differ): resolveRoutesForSurface, gatewayErrorJson, trim, String, apiKeyHasBalance, countOpenAiGenerationReferenceImages, requestedVolcengineImageCount, volcengineImageBillingSize, estimateImageBudgetPrecheck, routes.map, canAffordImageCost, finalizeRequestLogJson, redactVolcengineImageBody, maybeBlockUserModelCircuit, resolveRouteStrategyPlan, timing.markGatewayComplete, proxyVolcengineJsonPassthrough, buildAffinityKey, buildTierKeyPrefix, stickyConfigFromSurface
- L25 · isMaintenanceExemptRequest calls (conditional paths may differ): path.startsWith, test
- L40 · errorShapeForPath calls (conditional paths may differ): isAnthropicMessagesPath, path.startsWith
- L63 · maintenanceResponseFor calls (conditional paths may differ): isMaintenanceExemptRequest, request.method.toUpperCase, resolveMaintenanceMessage, maintenanceRetryAfterSeconds, JSON.stringify, buildMaintenanceBody, errorShapeForPath, String
- L63 · asObject calls (conditional paths may differ): Array.isArray
- L69 · finiteNonNegative calls (conditional paths may differ): Number.isFinite
- L75 · eventName calls (conditional paths may differ): asObject
- L83 · eventUsage calls (conditional paths may differ): asObject
- L93 · usageKey calls (conditional paths may differ): asObject
- L107 · eventFailureMessage calls (conditional paths may differ): asObject
- L199 · isInferenceOperation calls (conditional paths may differ): operation.endsWith
- L203 · isSessionOperation calls (conditional paths may differ): operation.endsWith
- L208 · rewriteDashScopeRealtimeClientMessage calls (conditional paths may differ): JSON.parse, asObject, eventName, isInferenceOperation, isSessionOperation, buildRouteRequestBody, JSON.stringify
- L236 · realtimeCapability calls (conditional paths may differ): isInferenceOperation
- L256 · normalizeWebSocketCloseCode calls (conditional paths may differ): Number.isInteger
- L271 · closeSocket calls (conditional paths may differ): normalizeWebSocketCloseCode, socket.close, reason.slice
- L287 · bridgeSockets calls (conditional paths may differ): resolve, collector.toUsage, server.accept, upstream.accept, server.addEventListener, rewriteDashScopeRealtimeClientMessage, upstream.send, String, closeSocket, finish, upstream.addEventListener, collector.observeServerMessage, server.send
- L389 · openWorkersUpstream calls (conditional paths may differ): realtimeCapability, resolveUpstreamEndpoint, outboundWebSocketFetchUrl, isSessionOperation, url.searchParams.set, resolveProviderUpstreamSecret, url.toString, applyRouteExtraHeaders, extractUpstreamRequestId
- L430 · workersUnavailableResponse calls (conditional paths may differ): JSON.stringify, Promise.resolve
- L446 · dispatchDashScopeRealtime calls (conditional paths may differ): options.nodeDispatch, workersUnavailableResponse, openWorkersUpstream, Promise.resolve, bridgeSockets
- L503 · wrapWorkersWebSocket calls (conditional paths may differ): socket.accept, createRealtimeSocket, socket.send, closeSocket, socket.addEventListener, handlers.message, handlers.close, handlers.error
- L528 · createWorkersDeferredRealtime calls (conditional paths may differ): wrapWorkersWebSocket, openWorkersUpstream
- L82 · asObject calls (conditional paths may differ): Array.isArray
- L88 · str calls (conditional paths may differ): value.trim
- L93 · inspectDashScopeClientFrame calls (conditional paths may differ): JSON.parse, asObject, str
- L113 · buildDashScopeTaskFailedEvent calls (conditional paths may differ): JSON.stringify
- L62 · asObject calls (conditional paths may differ): Array.isArray
- L68 · parseJsonObject calls (conditional paths may differ): asObject, JSON.parse
- L96 · resolveElevenLabsRealtimeTarget calls (conditional paths may differ): resolveUpstreamEndpoint, Object.entries, STRIPPED_QUERY_KEYS.has, key.toLowerCase, url.searchParams.set, resolveProviderUpstreamSecret, url.toString, applyRouteExtraHeaders
- L125 · elevenLabsAudioByteRate calls (conditional paths may differ): exec, trim, Number, Number.isFinite, toLowerCase
- L134 · base64DecodedByteLength calls (conditional paths may differ): value.endsWith, Math.max, Math.floor
- L157 · serverFailureMessage calls (conditional paths may differ): STT_ERROR_MESSAGE_TYPES.has, type.endsWith
- L265 · safeClose calls (conditional paths may differ): socket.close, normalizeWebSocketCloseCode, reason.slice
- L277 · bridgeElevenLabsRealtime calls (conditional paths may differ): resolve, collector.toUsage, client.onMessage, upstream.send, collector.observeClientMessage, String, safeClose, finish, upstream.onMessage, collector.observeServerMessage, client.send, client.onClose, upstream.onClose, client.onError, upstream.onError
- L355 · elevenLabsRealtimeRejectedResult calls (conditional paths may differ): response.text, JSON.parse, readElevenLabsError, elevenLabsErrorHttpStatus, JSON.stringify, response.headers.get, Promise.resolve
- L391 · workersUnavailableResponse calls (conditional paths may differ): JSON.stringify, Promise.resolve
- L408 · dispatchElevenLabsRealtime calls (conditional paths may differ): options.nodeDispatch, workersUnavailableResponse, resolveElevenLabsRealtimeTarget, toString, outboundWebSocketFetchUrl, extractUpstreamRequestId, elevenLabsRealtimeRejectedResult, bridgeElevenLabsRealtime, wrapWorkersWebSocket
- L38 · authenticateApiKey calls (conditional paths may differ): repos.apiKeys.getApiKeyWithUserByKey, roundGatewayMoney, Number, persistLazyBudgetResetIfNeeded, resolveMeMetadata
- L25 · gatewayErrorJson calls (conditional paths may differ): c.json
- L37 · gatewayErrorResponse calls (conditional paths may differ): JSON.stringify
- L49 · gatewayNestedErrorResponse calls (conditional paths may differ): JSON.stringify
- L76 · withGatewayRequestIdHeader calls (conditional paths may differ): headers.set
- L61 · parseJsonObject calls (conditional paths may differ): JSON.parse, Array.isArray
- L74 · routeRowToResult calls (conditional paths may differ): repos.providers.getProviderById, normalizeUpstreamProtocol, parseProviderEndpoints, parseJsonObject, console.warn, route.route_group.trim, extractMeteredProfileFromPriceOverrideJson, extractChargedProfileFromPriceOverrideJson, fingerprintProviderApiKey
- L126 · routeMatchesSurface calls (conditional paths may differ): isRouteAdapterCompatible
- L146 · resolveRoutesForSurface calls (conditional paths may differ): repos.modelRouting.resolveModelSurface, console.warn, String, repos.modelRouting.getModelRoutesByPoolId, selectActiveRouteRows, repos.modelRouting.getModelRoutesByModelId, map, filter, resolveRouteResultsFromRows, routeMatchesSurface, effectiveUpstreamOperation
- L201 · resolveRouteResultsFromRows calls (conditional paths may differ): routeRowToResult, result.push
- L220 · resolveAllRoutes calls (conditional paths may differ): repos.modelRouting.getModelRoutesByModelId, resolveRouteResultsFromRows
- L230 · getActiveModelRouteRows calls (conditional paths may differ): repos.modelRouting.getModelRoutesByModelId
- L240 · resolveModel calls (conditional paths may differ): resolveAllRoutes
- L155 · firstEventTimeoutMsFor calls (conditional paths may differ): resolveFirstEventTimeoutMs
- L162 · textStreamDispatchOptions calls (conditional paths may differ): firstEventTimeoutMsFor, Math.max
- L200 · proxyChatCompletions calls (conditional paths may differ): loadFirstEventTimeoutConfig, failoverDispatch, dispatchOpenAiRoute, textStreamDispatchOptions
- L229 · proxyResponses calls (conditional paths may differ): loadFirstEventTimeoutConfig, failoverDispatch, dispatchOpenAiResponsesRoute, textStreamDispatchOptions
- L257 · proxyAnthropicMessages calls (conditional paths may differ): loadFirstEventTimeoutConfig, failoverDispatch, dispatchAnthropicRoute, textStreamDispatchOptions
- L285 · proxyImageGenerations calls (conditional paths may differ): failoverDispatch, dispatchImageGenerations
- L310 · proxyImageEdits calls (conditional paths may differ): failoverDispatch, dispatchOpenAiImageEdits
- L335 · proxyAudioTranscriptions calls (conditional paths may differ): failoverDispatch, dispatchAudioTranscriptions
- L366 · proxyAudioSpeech calls (conditional paths may differ): failoverDispatch, dispatchAudioSpeech
- L390 · proxyDashScopeMultimodalPassthrough calls (conditional paths may differ): failoverDispatch, dispatchMultimodalPassthrough
- L421 · proxyDashScopeJsonPassthrough calls (conditional paths may differ): failoverDispatch, dispatchDashScopeJsonPassthroughRoute
- L454 · proxyGeminiImagePassthrough calls (conditional paths may differ): failoverDispatch, dispatchGeminiImagePassthroughRoute
- L489 · proxyVolcengineJsonPassthrough calls (conditional paths may differ): failoverDispatch, dispatchVolcengineJsonPassthroughRoute
- L520 · proxyMiniMaxJsonPassthrough calls (conditional paths may differ): failoverDispatch, dispatchMiniMaxJsonPassthroughRoute
- L553 · proxyMiniMaxAsrPassthrough calls (conditional paths may differ): failoverDispatch, dispatchMiniMaxSpeechPassthrough
- L577 · proxyElevenLabsTtsPassthrough calls (conditional paths may differ): failoverDispatch, dispatchElevenLabsTtsPassthrough
- L601 · proxyElevenLabsSttPassthrough calls (conditional paths may differ): failoverDispatch, dispatchElevenLabsSttPassthrough
- L625 · proxyDashScopeRealtime calls (conditional paths may differ): failoverDispatch, dispatchDashScopeRealtime
- L656 · proxyElevenLabsRealtime calls (conditional paths may differ): failoverDispatch, dispatchElevenLabsRealtime
- L682 · proxyDashScopeRealtimeDeferred calls (conditional paths may differ): failoverDispatch, connectUpstream, Promise.resolve
- L734 · proxyGeminiContent calls (conditional paths may differ): loadFirstEventTimeoutConfig, failoverDispatch, dispatchGeminiRoute, textStreamDispatchOptions
- L762 · proxyEmbeddings calls (conditional paths may differ): failoverDispatch, dispatchOpenAiEmbeddingsRoute
- L785 · proxyGeminiEmbeddings calls (conditional paths may differ): failoverDispatch, dispatchGeminiEmbedRoute
- L14 · asRecord calls (conditional paths may differ): Array.isArray
- L19 · shortLabel calls (conditional paths may differ): value.trim
- L26 · bucketKey calls (conditional paths may differ): shortLabel
- L31 · summarizeMessagesShapeForLog calls (conditional paths may differ): Array.isArray, asRecord, bucketKey, keysByRole.get, keysByRole.set, Object.keys, keys.add, typesByRole.get, typesByRole.set, shortLabel, types.add, sort
- L14 · buildRouteRequestBody calls (conditional paths may differ): mergeRouteRequestBody
- L100 · loadProxyRouteSurface calls (conditional paths may differ): resolveRoutesForSurface
- L135 · resolveProxySurface calls (conditional paths may differ): resolveModelRouting, loadProxyRouteSurface
- L178 · buildProxyFailoverOptions calls (conditional paths may differ): resolveRouteStrategyPlan, buildAffinityKey, buildTierKeyPrefix, stickyConfigFromSurface
- L227 · modelDisplayName calls (conditional paths may differ): trim, String
- L233 · runProxyPipeline calls (conditional paths may differ): c.get, Date.now, spec.parseRequest, resolveModelRouting, gatewayErrorJson, hasPositiveTotalBalance, loadProxyRouteSurface, console.error, console.warn, console.log, join, routes.map, modelDisplayName, spec.accounting.requestBodyForLog, maybeBlockUserModelCircuit, allocateRequestLogId, resolveStreamTimeouts, buildProxyFailoverOptions, timing.markGatewayComplete, spec.dispatch
- L454 · parseJsonModelBody calls (conditional paths may differ): c.req.json, gatewayErrorJson, body.model.trim
- L21 · resolveModelRouting calls (conditional paths may differ): rawModelId.trim, repos.modelRouting.getModelById, t.lastIndexOf, trim, t.slice
- L49 · geminiPathUsesImagePassthrough calls (conditional paths may differ): isImageGenerationModel
- L53 · forwardGeminiImageGeneration calls (conditional paths may differ): c.get, Date.now, c.req.json, gatewayErrorJson, Array.isArray, forwardGeminiImage
- L78 · forwardGeminiImage calls (conditional paths may differ): resolveRoutesForSurface, gatewayErrorJson, trim, String, apiKeyHasBalance, countGeminiReferenceImages, requestedGeminiImageCount, geminiImageBillingSize, c.req.url.includes, c.req.url.slice, c.req.url.indexOf, buildImagePrecheckUsage, estimateGeminiImageOutputTokens, estimateImageBudgetPrecheck, routes.map, canAffordImageCost, finalizeRequestLogJson, geminiBodyRedactedForLog, maybeBlockUserModelCircuit, resolveRouteStrategyPlan
- L13 · parseTags calls (conditional paths may differ): JSON.parse, Array.isArray, arr.filter
- L24 · parseRouteGroupsJson calls (conditional paths may differ): JSON.parse, Array.isArray, seen.has, seen.add, out.push
- L44 · parseMetadata calls (conditional paths may differ): JSON.parse, Array.isArray
- L55 · filterRouteGroupsByAllowlist calls (conditional paths may differ): allowed.map, g.toLowerCase, groups.filter, allowedSet.has
- L69 · parseModelsRouteGroupsQuery calls (conditional paths may differ): raw.trim, raw.split, toLowerCase, part.trim, seen.has, seen.add, out.push
- L95 · parseModelsKindQuery calls (conditional paths may differ): raw.trim, toLowerCase, includes
- L107 · parseCatalogRouteGroupsQuery calls (conditional paths may differ): raw.trim, raw.split, toLowerCase, part.trim, seen.has, seen.add, out.push
- L48 · normalizeRowRouteGroup calls (conditional paths may differ): routeGroup.trim
- L55 · sortProtocols calls (conditional paths may differ): UPSTREAM_PROTOCOLS.filter, set.has
- L60 · resolveRecommendedProtocol calls (conditional paths may differ): protocols.includes
- L66 · buildProtocolsByGroup calls (conditional paths may differ): normalizeRowRouteGroup, byGroup.get, byGroup.set, protocols.add, normalizeUpstreamProtocol, sortProtocols
- L89 · listCatalogDiscoveryModels calls (conditional paths may differ): loadPublicModelListContext, routesByModel.get, buildProtocolsByGroup, sort, Object.keys, a.localeCompare, filterRouteGroupsByAllowlist, protocolUnion.add, sortProtocols, collectInboundSurfaces, buildModelDisplayDiscounts, list.push, normalizePublicModelVendor, parsePricingProfile, parseTags, resolveRecommendedProtocol, parseModelModalitiesJson, parseMetadata
- L39 · groupActiveRoutesByModel calls (conditional paths may differ): map.get, list.push, map.set
- L56 · listPublicModelsWithRoutes calls (conditional paths may differ): repos.modelRouting.listModelsWithActiveRoutes
- L60 · fetchPublicModelListContext calls (conditional paths may differ): Promise.all, repos.modelRouting.listModelsWithActiveRoutes, repos.routes.listModelRoutesWithJoins, getBusinessTimezone, groupActiveRoutesByModel
- L73 · loadPublicModelListContext calls (conditional paths may differ): Date.now, finally, then, fetchPublicModelListContext
- L91 · buildModelDisplayDiscounts calls (conditional paths may differ): buildCoreModelDisplayDiscounts
- L74 · chargeToolUsage calls (conditional paths may differ): roundGatewayMoney, Number.isFinite, params.toolProvider.trim, buildFixedToolCostPricingAudit, crypto.randomUUID, getUserBudgetSnapshot, splitChargeFromBudgetSnapshot, params.repos.users.getById, userRowToSnapshot, snapshotWithOverrides, Number, snapshotToJson, changedFieldsToJson, computeChangedFields, insertRequestUsageAndChargeTx, JSON.stringify
- L217 · canAffordToolCost calls (conditional paths may differ): roundGatewayMoney, canAffordTotalCost
- L231 · apiKeyTotalRemaining calls (conditional paths may differ): computeTotalRemaining
- L240 · apiKeyHasBalance calls (conditional paths may differ): hasPositiveTotalBalance
- L16 · publicOrigin calls (conditional paths may differ): c.req.header, url.protocol.replace
- L24 · readMcpOAuthAuthorizationServer calls (conditional paths may differ): repos.systemConfig.getConfig, normalizeMcpOAuthAuthorizationServer
- L35 · mcpUnauthorizedHeaders calls (conditional paths may differ): path.startsWith, readMcpOAuthAuthorizationServer, console.warn, params.push, protectedResourceMetadataUrl, publicOrigin, params.join
- L49 · clip calls (conditional paths may differ): value.slice
- L53 · parseDefinition calls (conditional paths may differ): JSON.parse, Array.isArray
- L68 · pricingOf calls (conditional paths may differ): parseStoredMcpPricingRule, console.warn, String
- L97 · targetOf calls (conditional paths may differ): parseMcpAuthHeaders
- L115 · asContent calls (conditional paths may differ): Array.isArray, clip, JSON.stringify
- L122 · handleMcpAggregateRequest calls (conditional paths may differ): JSON.stringify, input.deps.listCallable, items.map, items.filter, server.setRequestHandler, map, enabled.filter, parseDefinition, pricingOf, summarizeMcpPricingRule, byName.get, textResult, preflightMcpPricing, canAffordToolCost, Date.now, clip, console.error, input.deps.charge, pricingAudit, callTool
- L381 · mcpAggregateDeps calls (conditional paths may differ): repos.mcpServers.listCallable, chargeToolUsage
- L91 · withUserImageChargedFactor calls (conditional paths may differ): applyUserChargedCostToBreakdown
- L103 · resolveImageBillingParams calls (conditional paths may differ): getUserChargedCostFactorMode
- L143 · pricingAtUtcFromParams calls (conditional paths may differ): Number.isFinite, Number.isNaN, requestedPricingAtUtc.getTime
- L151 · resolveRouteFactors calls (conditional paths may differ): pricingAtUtcFromParams, getBusinessTimezone, resolveRouteEffectiveFactors, parsePricingProfile, resolveDailyScheduleFactor, toProviderFactorAudit, toScheduleAudit, schSide
- L203 · zeroImageCostBreakdown calls (conditional paths may differ): withUserImageChargedFactor, Math.max, Math.floor, JSON.stringify
- L237 · estimateImageTokenCosts calls (conditional paths may differ): resolveSupplierBillingPrices, resolveStandardBillingPrices, resolveChargedBillingPrices, scaleBillingPrices, roundGatewayMoney, computeImageTokenMeteredCost, JSON.stringify, withUserImageChargedFactor, Math.max, Math.floor
- L331 · estimateImagePerImageCosts calls (conditional paths may differ): Math.max, Math.floor, resolveImageCatalogUnitPrice, computeImagePerImageMeteredCost, roundGatewayMoney, JSON.stringify, withUserImageChargedFactor
- L411 · estimateImageCosts calls (conditional paths may differ): resolveImageBillingParams, parsePricingProfile, resolveRouteFactors, resolveImageBillingMode, profileHasImagePerImagePricing, estimateImagePerImageCosts, profileHasImageTokenPricing, buildImagePrecheckUsage, estimateImageTokenCosts, zeroImageCostBreakdown
- L456 · estimateImageBudgetPrecheck calls (conditional paths may differ): estimateImageCosts
- L481 · canAffordImageCost calls (conditional paths may differ): canAffordToolCost
- L492 · withUncertainResultAudit calls (conditional paths may differ): JSON.parse, Array.isArray, JSON.stringify
- L515 · withClientAbortPrecheckAudit calls (conditional paths may differ): withUncertainResultAudit
- L589 · recordImageUsage calls (conditional paths may differ): resolveImageBillingParams, parsePricingProfile, resolveImageBillingMode, shouldChargeUncertainImageResult, Math.max, Math.floor, resolveRouteFactors, profileHasImagePerImagePricing, zeroImageCostBreakdown, resolveUncertainUsageSource, estimateImagePerImageCosts, profileHasImageTokenPricing, estimateImageCosts, buildImagePrecheckUsage, crypto.randomUUID, getUserBudgetSnapshot, splitChargeFromBudgetSnapshot, params.repos.users.getById, userRowToSnapshot, snapshotWithOverrides
- L7 · countOpenAiGenerationReferenceImages calls (conditional paths may differ): image.trim, Array.isArray, image.filter, v.trim
- L21 · openAiImageBillingSize calls (conditional paths may differ): resolution.trim, toLowerCase
- L39 · applyOpenAiImageGenerationExtras calls (conditional paths may differ): body.sequential_image_generation.trim, Array.isArray, body.image.trim, map, body.image.filter, v.trim
- L21 · usageFromStreamFromImage calls (conditional paths may differ): parseOpenAiImageUsage, Promise.resolve
- L104 · appendOpenaiEditImages calls (conditional paths may differ): openaiEditImageFormField, form.append
- L114 · withTimeoutSignal calls (conditional paths may differ): controller.abort, setTimeout, clearTimeout
- L161 · normalizeImageCommonParams calls (conditional paths may differ): input.prompt.trim, Number.isInteger, input.n.trim, Number, v.trim, asOptString
- L231 · validateImageUpload calls (conditional paths may differ): toLowerCase, trim, IMAGE_ALLOWED_MIME.has
- L246 · countValidImageResults calls (conditional paths may differ): Array.isArray, row.b64_json.trim, row.url.trim
- L294 · readJsonResponse calls (conditional paths may differ): response.text, JSON.parse, text.slice, JSON.stringify
- L321 · dispatchOpenAiImageGenerations calls (conditional paths may differ): resolveUpstreamEndpoint, detachUpstreamExtraFields, applyUpstreamExtraFields, protectedUpstreamPathsForRoute, console.log, Date.now, withTimeoutSignal, resolveProviderUpstreamSecret, fetch, applyRouteExtraHeaders, JSON.stringify, extractUpstreamRequestId, readJsonResponse, usageFromStreamFromImage, imageDispatchMeta, getAbortReason, imageAbortErrorPayload, String, console.error, Promise.resolve
- L431 · dispatchOpenAiImageEdits calls (conditional paths may differ): resolveUpstreamEndpoint, console.log, applyUpstreamExtraFields, protectedUpstreamPathsForRoute, form.append, Object.entries, isOpenaiEditImageFormKey, formExtraFieldText, appendOpenaiEditImages, Date.now, withTimeoutSignal, resolveProviderUpstreamSecret, fetch, applyRouteExtraHeaders, extractUpstreamRequestId, readJsonResponse, usageFromStreamFromImage, imageDispatchMeta, getAbortReason, imageAbortErrorPayload
- L72 · maxNForImageRoutes calls (conditional paths may differ): Math.min, routes.map, maxNForImageAdapter
- L77 · asObject calls (conditional paths may differ): Array.isArray
- L83 · asOptString calls (conditional paths may differ): value.trim
- L89 · resolveImageCount calls (conditional paths may differ): value.trim, Number, Number.isInteger
- L98 · collectReferenceImages calls (conditional paths may differ): image.trim, Array.isArray, map, image.filter, item.trim
- L118 · composeDashScopeImageBody calls (conditional paths may differ): detachUpstreamExtraFields, routeCustomParamsBody, asOptString, resolveImageCount, map, collectReferenceImages, pickParameters, applyUpstreamExtraFields, protectedUpstreamPathsForRoute
- L158 · buildDashScopeImageBody calls (conditional paths may differ): composeDashScopeImageBody
- L166 · collectDashScopeImageUrls calls (conditional paths may differ): asObject, Array.isArray, asOptString, urls.push
- L182 · normalizeDashScopeImageResult calls (conditional paths may differ): Math.floor, Date.now, map, collectDashScopeImageUrls
- L189 · resolveImageBillingSize calls (conditional paths may differ): asObject, asOptString, Number.isFinite
- L213 · dashScopeErrorMessage calls (conditional paths may differ): asObject, asOptString
- L219 · withTimeoutSignal calls (conditional paths may differ): controller.abort, onClientAbort, setTimeout, clearTimeout
- L276 · imageDispatchResult calls (conditional paths may differ): JSON.stringify, Promise.resolve
- L299 · bytesToBase64 calls (conditional paths may differ): bytes.subarray, Math.min, String.fromCharCode, btoa
- L309 · maybeDownloadAsB64 calls (conditional paths may differ): fetchImpl, console.warn, out.push, response.arrayBuffer, bytesToBase64, String
- L353 · dispatchDashScopeImageGenerations calls (conditional paths may differ): imageFamilyForAdapter, composeDashScopeImageBody, imageDispatchResult, resolveUpstreamEndpoint, console.log, Date.now, withTimeoutSignal, resolveProviderUpstreamSecret, fetchImpl, applyRouteExtraHeaders, JSON.stringify, extractUpstreamRequestId, response.text, JSON.parse, text.slice, normalizeUpstreamId, asObject, resolveImageBillingSize, console.error, dashScopeErrorMessage
- L13 · collapseWhitespace calls (conditional paths may differ): trim, s.replace
- L17 · truncate calls (conditional paths may differ): collapseWhitespace, t.slice
- L24 · pickSummaryFromJsonBody calls (conditional paths may differ): collapseWhitespace, truncate, em.trim, et.trim, v.trim, topErr.trim
- L79 · formatHttpErrorTextForRequestLog calls (conditional paths may differ): toLowerCase, ct.includes, text.slice, slice.trim, pickSummaryFromJsonBody, JSON.parse, truncate
- L107 · materializeNonOkResponse calls (conditional paths may differ): response.text, withUpstreamErrorCodeHeader, sanitizeRewrappedHeaders
- L131 · formatHttpErrorForRequestLog calls (conditional paths may differ): text, response.clone, formatHttpErrorTextForRequestLog, response.headers.get
- L51 · maybeBlockUserModelCircuit calls (conditional paths may differ): getUserModelCircuitOpen, Date.now, allocateRequestLogId, scheduleBackgroundWork, catch, recordUsage, formatUserModelCircuitOpenErrorMessage, console.error, String, withGatewayRequestIdHeader, buildUserModelCircuitOpenResponse
- L109 · maybeTriggerUserModelCircuitFromUpstream calls (conditional paths may differ): isSensitiveUpstreamResponse, recordUserModelCircuitTrigger
- L145 · maybeTriggerSensitiveContentCircuitFromUpstream calls (conditional paths may differ): maybeTriggerUserModelCircuitFromUpstream
- L8 · scheduleBackgroundWork calls (conditional paths may differ): c.executionCtx.waitUntil, task.catch, console.error, String
- L99 · withUserAudioChargedFactor calls (conditional paths may differ): applyUserChargedCostToBreakdown
- L111 · resolveAudioBillingParams calls (conditional paths may differ): getUserChargedCostFactorMode
- L124 · pricingAtUtcFromParams calls (conditional paths may differ): Number.isFinite, Number.isNaN, requestedPricingAtUtc.getTime
- L132 · resolveRouteFactors calls (conditional paths may differ): pricingAtUtcFromParams, getBusinessTimezone, resolveRouteEffectiveFactors, parsePricingProfile, resolveDailyScheduleFactor, toProviderFactorAudit, toScheduleAudit, schSide
- L184 · buildAudioPerSecondCosts calls (conditional paths may differ): resolveBillableAudioSeconds, computeAudioPerSecondMeteredCost, roundGatewayMoney, JSON.stringify, withUserAudioChargedFactor
- L255 · buildAudioPerCharacterCosts calls (conditional paths may differ): resolveBillableAudioCharacters, computeAudioPerCharacterMeteredCost, roundGatewayMoney, withUserAudioChargedFactor, JSON.stringify
- L321 · buildAudioTokenCosts calls (conditional paths may differ): resolveSupplierBillingPrices, resolveStandardBillingPrices, resolveChargedBillingPrices, scaleBillingPrices, roundGatewayMoney, computeAudioTokenMeteredCost, JSON.stringify, withUserAudioChargedFactor
- L414 · zeroAudioCostBreakdown calls (conditional paths may differ): withUserAudioChargedFactor, JSON.stringify
- L448 · resolveAudioCostsForProfile calls (conditional paths may differ): resolveAudioBillingMode, profileHasAudioPerSecondPricing, buildAudioPerSecondCosts, profileHasAudioTokenPricing, buildAudioTokenPrecheckUsage, zeroAudioCostBreakdown, buildAudioTokenCosts, profileHasAudioPerCharacterPricing, buildAudioPerCharacterCosts
- L495 · estimateAudioSpeechCosts calls (conditional paths may differ): resolveAudioBillingParams, resolveAudioCostsForProfile, parsePricingProfile, resolveRouteFactors
- L530 · estimateAudioSpeechBudgetPrecheck calls (conditional paths may differ): resolveAudioBillingParams, parsePricingProfile, resolveRouteFactors, resolveAudioCostsForProfile, buildSpeechTokenPrecheckUsage, zeroAudioCostBreakdown
- L579 · estimateAudioBudgetPrecheck calls (conditional paths may differ): resolveAudioBillingDuration, resolveAudioBillingParams, parsePricingProfile, resolveRouteFactors, resolveAudioCostsForProfile, zeroAudioCostBreakdown
- L678 · recordAudioUsage calls (conditional paths may differ): resolveAudioBillingParams, parsePricingProfile, resolveRouteFactors, resolveAudioBillingMode, zeroAudioCostBreakdown, resolveAudioCostsForProfile, crypto.randomUUID, getUserBudgetSnapshot, splitChargeFromBudgetSnapshot, params.repos.users.getById, userRowToSnapshot, snapshotWithOverrides, roundGatewayMoney, Number, snapshotToJson, changedFieldsToJson, computeChangedFields, JSON.stringify, console.log, insertRequestUsageAndChargeTx
- L52 · normalizeAudioMimeType calls (conditional paths may differ): toLowerCase, mimeType.trim, raw.split
- L65 · extensionFromAudioMime calls (conditional paths may differ): normalizeAudioMimeType, toLowerCase, mimeType.trim, m.includes
- L80 · resolveAudioUploadFilename calls (conditional paths may differ): extensionFromAudioMime, preferredName.trim, test, raw.includes
- L124 · resolveUpstreamAudioResponseFormat calls (conditional paths may differ): toLowerCase, providerModelName.trim, m.includes
- L155 · withTimeoutSignal calls (conditional paths may differ): controller.abort, setTimeout, clearTimeout
- L180 · validateAudioUpload calls (conditional paths may differ): normalizeAudioMimeType, AUDIO_ALLOWED_MIME.has
- L198 · estimateAudioDurationFromBytes calls (conditional paths may differ): Number.isFinite, Math.max
- L205 · parseDurationFromVerboseJson calls (conditional paths may differ): Array.isArray, Number.isFinite, d.trim, Number
- L223 · parseAudioDurationFromUpstreamBody calls (conditional paths may differ): parseDurationFromVerboseJson, Array.isArray, Number.isFinite
- L256 · extractTranscriptionText calls (conditional paths may differ): Array.isArray
- L268 · reshapeTranscriptionForClient calls (conditional paths may differ): extractTranscriptionText, Array.isArray
- L293 · buildAudioTranscriptionClientResponse calls (conditional paths may differ): extractTranscriptionText, JSON.stringify
- L320 · dispatchOpenAiAudioTranscriptions calls (conditional paths may differ): resolveUpstreamEndpoint, console.log, buildRouteRequestBody, form.append, resolveUpstreamAudioResponseFormat, Object.entries, formExtraFieldText, resolveAudioUploadFilename, Date.now, withTimeoutSignal, resolveProviderUpstreamSecret, fetch, applyRouteExtraHeaders, extractUpstreamRequestId, response.text, JSON.parse, text.slice, parseOpenAiAudioTokenUsage, resolveAudioBillingDuration, parseAudioDurationFromUpstreamBody
- L64 · isObject calls (conditional paths may differ): Array.isArray
- L68 · finiteInteger calls (conditional paths may differ): Number.isInteger
- L76 · copyResponseHeaders calls (conditional paths may differ): copied.delete
- L112 · hexToBase64 calls (conditional paths may differ): test, Number.parseInt, hex.slice, String.fromCharCode, bytes.subarray, btoa
- L127 · base64ToBytes calls (conditional paths may differ): atob, binary.charCodeAt
- L134 · parseDashScopeTtsEvent calls (conditional paths may differ): isObject, value.code.trim, finiteInteger, hexToBase64
- L184 · speechDoneEvent calls (conditional paths may differ): encode, JSON.stringify
- L197 · speechDeltaEvent calls (conditional paths may differ): encode, JSON.stringify
- L203 · updateUsageFromTtsEvent calls (conditional paths may differ): JSON.stringify
- L212 · dashScopeStreamResponse calls (conditional paths may differ): String, resolveUsage, options.reader.read, pending.push, options.parser.push, pending.shift, parseDashScopeTtsEvent, updateUsageFromTtsEvent, controller.enqueue, speechDeltaEvent, base64ToBytes, speechDoneEvent, controller.close, finishUsage, options.reader.cancel, controller.error
- L305 · firstDashScopeEvents calls (conditional paths may differ): response.body.getReader, reader.read, parser.push, parseDashScopeTtsEvent
- L335 · validateCosyVoiceSpeech calls (conditional paths may differ): includes
- L346 · validateQwenAudioSpeech calls (conditional paths may differ): includes
- L356 · validateDashScopeRequest calls (conditional paths may differ): validateCosyVoiceSpeech, validateQwenAudioSpeech, includes
- L375 · composeDashScopeTtsBody calls (conditional paths may differ): voiceId, applyUpstreamExtraFields, protectedUpstreamPathsForRoute
- L431 · buildDashScopeTtsBody calls (conditional paths may differ): composeDashScopeTtsBody
- L439 · dispatchDashScopeTts calls (conditional paths may differ): validateDashScopeRequest, composeDashScopeTtsBody, JSON.stringify, Promise.resolve, resolveUpstreamEndpoint, resolveProviderUpstreamSecret, applyRouteExtraHeaders, extractUpstreamRequestId, firstDashScopeEvents, first.reader.cancel, dashScopeStreamResponse
- L541 · parseOpenAiSpeechUsage calls (conditional paths may differ): isObject, finiteInteger, JSON.stringify
- L550 · wrapOpenAiSpeechBody calls (conditional paths may differ): body.getReader, String, resolveUsage, reader.read, parseOpenAiSpeechUsage, finish, controller.close, controller.enqueue, controller.error, reader.cancel
- L609 · dispatchOpenAiAudioSpeech calls (conditional paths may differ): resolveUpstreamEndpoint, resolveProviderUpstreamSecret, applyUpstreamExtraFields, protectedUpstreamPathsForRoute, applyRouteExtraHeaders, JSON.stringify, extractUpstreamRequestId, Promise.resolve, wrapOpenAiSpeechBody, copyResponseHeaders
- L670 · dispatchDashScopeQwenAudioSpeech calls (conditional paths may differ): dispatchDashScopeTts
- L681 · dispatchDashScopeSpeechSynthesizer calls (conditional paths may differ): dispatchDashScopeTts
- L692 · dispatchDashScopeQwenTts calls (conditional paths may differ): dispatchDashScopeTts
- L703 · dispatchDashScopeMiniMaxTts calls (conditional paths may differ): dispatchDashScopeTts
- L714 · redactAudioSpeechRequestForLog calls (conditional paths may differ): Array.from, voiceId, Boolean
- L49 · asObject calls (conditional paths may differ): Array.isArray
- L55 · asNonNegative calls (conditional paths may differ): Number, Number.isFinite
- L60 · charactersFromPayload calls (conditional paths may differ): asNonNegative, asObject
- L64 · durationSecondsFromPayload calls (conditional paths may differ): asObject, asNonNegative
- L69 · countDashScopeImages calls (conditional paths may differ): asObject, Array.isArray, image.trim
- L84 · taskStatus calls (conditional paths may differ): asObject
- L89 · transcriptionUrl calls (conditional paths may differ): asObject, Array.isArray, first.transcription_url.trim
- L104 · lastJsonNumber calls (conditional paths may differ): window.matchAll, asNonNegative
- L110 · scanSpeechUsage calls (conditional paths may differ): lastJsonNumber, window.slice
- L130 · jsonResponse calls (conditional paths may differ): JSON.stringify
- L142 · dispatchDashScopeJsonPassthrough calls (conditional paths may differ): resolveProviderUpstreamSecret, resolveUpstreamEndpoint, capabilityFor, setTimeout, timeoutController.abort, fetchImpl, applyRouteExtraHeaders, JSON.stringify, extractUpstreamRequestId, response.headers.get, contentType.includes, streamResult, Promise.resolve, response.text, JSON.parse, asObject, billParsed, jsonResponse, usageWith, String
- L256 · billParsed calls (conditional paths may differ): asObject, JSON.stringify, parseOpenAiAudioTokenUsage, countDashScopeImages, charactersFromPayload, taskStatus, transcriptionUrl, fetchImpl, result.text, JSON.parse, durationSecondsFromPayload, resolveAudioBillingDuration
- L334 · streamResult calls (conditional paths may differ): resolveUsage, source.getReader, reader.read, usageWith, controller.close, scanSpeechUsage, decoder.decode, controller.enqueue, String, controller.error, reader.cancel
- L62 · stickyConfigFromSurface calls (conditional paths may differ): parseRoutePoolStickyConfig
- L74 · toIso calls (conditional paths may differ): toISOString
- L78 · parseExpiresAtMs calls (conditional paths may differ): Date.parse, Number.isFinite
- L96 · mergeStickyIntoAttempts calls (conditional paths may differ): attempts.filter
- L109 · stickySessionToTrace calls (conditional paths may differ): emptyStickyTrace
- L122 · resolveStickyTrace calls (conditional paths may differ): emptyStickyTrace, Promise.allSettled, stickySessionToTrace
- L133 · resolveStickySession calls (conditional paths may differ): Date.now, hashAffinityKey, console.warn, repos.routePoolSticky.getBinding, parseExpiresAtMs, params.candidates.find, getProviderCircuitRemainingMs
- L230 · scheduleStickyTouchIfNeeded calls (conditional paths may differ): Date.now, shouldThrottleTouch, parseExpiresAtMs, toIso, session.mutations.push, catch, then, repos.routePoolSticky.touchBinding, console.warn
- L270 · clearStickyBindingSync calls (conditional paths may differ): repos.routePoolSticky.clearBinding, console.warn
- L295 · scheduleStickyBind calls (conditional paths may differ): Date.now, crypto.randomUUID, toIso, Boolean, session.mutations.push, catch, then, repos.routePoolSticky.tryBind, console.warn
- L336 · stickyMutationPromise calls (conditional paths may differ): Promise.allSettled
- L342 · isStickyEnabled calls (conditional paths may differ): coerceStickyEnabled
- L7 · audioModelGuardMessage calls (conditional paths may differ): checkAudioModelGuard
- L48 · subtitleCues calls (conditional paths may differ): readMiniMaxAsrSegments, trim, extractTranscriptionText, parseAudioDurationFromUpstreamBody
- L57 · clientBodyForShape calls (conditional paths may differ): extractTranscriptionText, subtitleCues, renderSegmentsAsSrt, renderSegmentsAsVtt
- L66 · dispatchMiniMaxAudioTranscriptions calls (conditional paths may differ): validateAudioUpload, resolveUpstreamEndpoint, resolveMiniMaxAsrUpstreamFormat, buildRouteRequestBody, form.append, Object.entries, FORM_SKIP_KEYS.has, formExtraFieldText, resolveAudioUploadFilename, Date.now, withTimeoutSignal, resolveProviderUpstreamSecret, fetch, applyRouteExtraHeaders, buildMiniMaxAsrHeaders, extractUpstreamRequestId, response.text, JSON.parse, text.slice, resolveAudioBillingDuration
- L239 · dispatchMiniMaxAsrPassthrough calls (conditional paths may differ): validateAudioUpload, resolveUpstreamEndpoint, buildRouteRequestBody, form.append, Object.entries, PASSTHROUGH_FORM_SKIP_KEYS.has, trim, String, resolveAudioUploadFilename, withTimeoutSignal, resolveProviderUpstreamSecret, fetch, applyRouteExtraHeaders, buildMiniMaxAsrHeaders, extractUpstreamRequestId, response.text, JSON.parse, resolveAudioBillingDuration, parseAudioDurationFromUpstreamBody, response.headers.get
- L48 · elevenLabsStreamHeaders calls (conditional paths may differ): source.forEach, STREAM_HEADER_BLOCKLIST.has, key.toLowerCase, headers.append
- L58 · resolveElevenLabsTtsUrl calls (conditional paths may differ): resolveUpstreamEndpoint, url.pathname.replace, Object.entries, url.searchParams.set, url.toString
- L74 · elevenLabsJsonError calls (conditional paths may differ): JSON.stringify, Promise.resolve
- L98 · elevenLabsUpstreamErrorResult calls (conditional paths may differ): response.text, JSON.parse, readElevenLabsError, elevenLabsErrorHttpStatus, response.headers.get, Promise.resolve
- L125 · elevenLabsTransportError calls (conditional paths may differ): String, elevenLabsJsonError
- L142 · elevenLabsTrackedStream calls (conditional paths may differ): elevenLabsStreamHeaders, resolveUsage, source.getReader, reader.read, finish, controller.close, controller.enqueue, String, controller.error, reader.cancel
- L228 · dispatchElevenLabsTtsPassthrough calls (conditional paths may differ): resolveProviderUpstreamSecret, resolveElevenLabsTtsUrl, elevenLabsTtsVariantSuffix, setTimeout, timeoutController.abort, fetchImpl, applyRouteExtraHeaders, JSON.stringify, extractUpstreamRequestId, elevenLabsUpstreamErrorResult, readElevenLabsCharacterCount, Math.max, Math.floor, elevenLabsTrackedStream, elevenLabsTransportError, clearTimeout
- L299 · buildElevenLabsSttForm calls (conditional paths may differ): form.append, STT_FORM_SKIP_KEYS.has, Object.entries, resolveAudioUploadFilename
- L322 · resolveElevenLabsSttBilling calls (conditional paths may differ): resolveAudioBillingDuration, elevenLabsUpstreamDurationSeconds
- L337 · dispatchElevenLabsSttPassthrough calls (conditional paths may differ): validateAudioUpload, resolveUpstreamEndpoint, buildElevenLabsSttForm, withTimeoutSignal, resolveProviderUpstreamSecret, fetchImpl, applyRouteExtraHeaders, extractUpstreamRequestId, elevenLabsUpstreamErrorResult, response.text, JSON.parse, resolveElevenLabsSttBilling, response.headers.get, Promise.resolve, getAbortReason, elevenLabsTransportError, clear
- L46 · requireWebSocketUpgrade calls (conditional paths may differ): c.req.header, gatewayErrorJson
- L55 · recordRealtimeUsage calls (conditional paths may differ): trim, String, scheduleBackgroundWork, catch, proxyResult.usagePromise.then, realtimeErrorMessage, recordAudioUsage, Date.now, timing.snapshot, console.error
- L146 · handleElevenLabsRealtime calls (conditional paths may differ): Date.now, requireWebSocketUpgrade, isValidElevenLabsVoiceId, gatewayErrorJson, c.req.query, trim, c.get, resolveModelRouting, rawModelId.slice, audioModelGuardMessage, resolveRoutesForSurface, apiKeyHasBalance, resolveRouteStrategyPlan, proxyElevenLabsRealtime, parseDashScopeRealtimeAuthProtocol, c.req.header, buildAffinityKey, buildTierKeyPrefix, proxyResult.response.headers.get, recordRealtimeUsage
- L288 · handleElevenLabsTtsRealtime calls (conditional paths may differ): handleElevenLabsRealtime, c.req.param
- L296 · handleElevenLabsSttRealtime calls (conditional paths may differ): handleElevenLabsRealtime
Environment references: c.env.NODE_ELEVENLABS_REALTIME_DISPATCH
- L51 · maybeScheduleStickyStaleGc calls (conditional paths may differ): Date.now, Math.random, toISOString, session.mutations.push, catch, repos.routePoolSticky.deleteStaleBefore, console.warn
- L196 · clipLogReason calls (conditional paths may differ): trim, reason.replace, collapsed.slice, JSON.stringify
- L209 · readResponsePrefix calls (conditional paths may differ): body.getReader, setTimeout, resolve, then, reader.read, Promise.race, decoder.decode, text.slice, clearTimeout, reader.cancel
- L242 · summarizeUpstreamHttpError calls (conditional paths may differ): response.headers.get, readResponsePrefix, response.clone, formatHttpErrorTextForRequestLog
- L258 · logFailoverDecision calls (conditional paths may differ): input.circuit.slice, providerLabel, console.warn, clipLogReason
- L294 · allProvidersBusyResponse calls (conditional paths may differ): Math.max, Math.ceil, gatewayNestedErrorResponse, String
- L317 · failoverDispatch calls (conditional paths may differ): Array.isArray, map, routes.filter, expectedProtocols.includes, console.warn, overlayClientHeadersOnRouteCustomParams, gatewayErrorResponse, Promise.resolve, emptyRoute, protocolRoutes.find, resolveStickySession, maybeScheduleStickyStaleGc, buildRouteAttemptPlan, Date.now, mergeStickyIntoAttempts, allProvidersBusyResponse, allProvidersBusyDueToCircuitOnly, resolveStickyTrace, stickyMutationPromise, Boolean
- L36 · normalizeUpstreamId calls (conditional paths may differ): value.trim, trimmed.slice
- L43 · normalizeCloudTraceContextRequestId calls (conditional paths may differ): value.trim, trimmed.indexOf, normalizeUpstreamId, trimmed.slice
- L50 · extractHeaderRequestId calls (conditional paths may differ): headers.get, normalizeCloudTraceContextRequestId, normalizeUpstreamId
- L62 · extractUpstreamRequestId calls (conditional paths may differ): extractHeaderRequestId
- L76 · resolveGeminiLoggedRequestId calls (conditional paths may differ): normalizeUpstreamId
- L31 · createRealtimeSocket calls (conditional paths may differ): transport.subscribe, messageListener, queuedMessages.push, closeListener, errorListener, transport.send, transport.close, queuedMessages.splice, listener
- L10 · allocateRequestLogId calls (conditional paths may differ): crypto.randomUUID
- L52 · defaultDescribeOutcome calls (conditional paths may differ): defaultHasUsage, defaultIncompleteErrorMessage, defaultHttpErrorFallback
- L69 · describeResponsesOutcome calls (conditional paths may differ): defaultDescribeOutcome, defaultIncompleteErrorMessage, defaultHttpErrorFallback
- L86 · geminiHasUsage calls (conditional paths may differ): defaultHasUsage
- L91 · describeGeminiOutcome calls (conditional paths may differ): geminiHasUsage, defaultIncompleteErrorMessage, defaultHttpErrorFallback, resolveGeminiLoggedRequestId
- L13 · createDirectFlushAccountingSink calls (conditional paths may differ): recordUsage
- L82 · normalizeInputTokensFromPrompt calls (conditional paths may differ): Number.isFinite, Math.abs
- L113 · usageFromProvider calls (conditional paths may differ): normalizeInputTokensFromPrompt, JSON.stringify
- L162 · hasOpenAiContentDelta calls (conditional paths may differ): Array.isArray
- L177 · processUsageFromDataLine calls (conditional paths may differ): line.startsWith, trim, line.slice, JSON.parse, hasOpenAiReasoningDelta, hasOpenAiContentDelta, normalizeUpstreamId, usageFromProvider
- L219 · transformStreamUsageForClient calls (conditional paths may differ): line.startsWith, trim, line.slice, JSON.parse, Array.isArray, choices.some, String, JSON.stringify
- L258 · pumpWithUsageTracking calls (conditional paths may differ): upstream.getReader, downstream.getWriter, createStreamIdleClock, readWithIdleTimeout, idleClock.timeoutMs, applyStreamIdleTimeout, console.log, reader.cancel, writer.write, encoder.encode, streamIdleTimeoutErrorFrame, idleClock.noteChunk, state.lineBuffer.trim, processUsageFromDataLine, transformStreamUsageForClient, Date.now, decoder.decode, state.lineBuffer.split, lines.pop, console.warn
- L374 · streamResponseWithUsage calls (conditional paths may differ): catch, pumpWithUsageTracking, response.headers.get
- L413 · nonStreamResponseWithUsage calls (conditional paths may differ): response.headers.get, contentType.includes, Promise.resolve, response.text, JSON.parse, usageFromProvider, normalizeUpstreamId, sanitizeRewrappedHeaders
- L460 · dispatchOpenAiRoute calls (conditional paths may differ): resolveUpstreamEndpoint, resolveProviderUpstreamSecret, buildRouteRequestBody, applyVertexOpenAiModelPrefix, fetchUntilHeaders, applyRouteExtraHeaders, JSON.stringify, extractUpstreamRequestId, response.headers.get, contentType.includes, nonStreamResponseWithUsage, peekResponseFirstEvent, Promise.resolve, streamResponseWithUsage
- L109 · ensureResponsesSequenceNumber calls (conditional paths may differ): line.startsWith, trim, line.slice, JSON.parse, Array.isArray, JSON.stringify
- L140 · numberOrZero calls (conditional paths may differ): Number.isFinite
- L144 · usageFromResponses calls (conditional paths may differ): numberOrZero, JSON.stringify
- L167 · applyResponsesUsage calls (conditional paths may differ): usageFromResponses
- L178 · isResponsesTerminalEventType calls (conditional paths may differ): Boolean, TERMINAL_EVENT_TYPES.has
- L182 · applyResponsesEvent calls (conditional paths may differ): REASONING_DELTA_TYPES.has, OUTPUT_DELTA_TYPES.has, normalizeUpstreamId, applyResponsesUsage, parsed.error.message.trim, isResponsesTerminalEventType
- L211 · processResponsesDataLine calls (conditional paths may differ): line.startsWith, trim, line.slice, JSON.parse, applyResponsesEvent
- L228 · syntheticMissingTerminalEvent calls (conditional paths may differ): JSON.stringify
- L246 · pumpResponsesWithUsageTracking calls (conditional paths may differ): upstream.getReader, downstream.getWriter, createStreamIdleClock, writer.write, encoder.encode, Date.now, console.log, readWithIdleTimeout, idleClock.timeoutMs, applyStreamIdleTimeout, reader.cancel, writeChunk, syntheticMissingTerminalEvent, idleClock.noteChunk, state.lineBuffer.trim, processResponsesDataLine, ensureResponsesSequenceNumber, decoder.decode, state.lineBuffer.split, lines.pop
- L372 · streamResponseWithUsage calls (conditional paths may differ): catch, pumpResponsesWithUsageTracking, response.headers.get
- L405 · extractUsageFromResponsesObject calls (conditional paths may differ): usageFromResponses, normalizeUpstreamId
- L417 · nonStreamResponseWithUsage calls (conditional paths may differ): response.headers.get, contentType.includes, Promise.resolve, response.text, JSON.parse, sanitizeRewrappedHeaders, extractUsageFromResponsesObject
- L457 · dispatchOpenAiResponsesRoute calls (conditional paths may differ): resolveUpstreamEndpoint, resolveProviderUpstreamSecret, buildRouteRequestBody, applyVertexOpenAiModelPrefix, fetchUntilHeaders, applyRouteExtraHeaders, JSON.stringify, extractUpstreamRequestId, response.headers.get, contentType.includes, nonStreamResponseWithUsage, peekResponseFirstEvent, Promise.resolve, streamResponseWithUsage
- L44 · parseFirstEventTimeoutMs calls (conditional paths may differ): trim, Number.parseInt, Number.isFinite
- L52 · parseFirstEventTimeoutRouteGroups calls (conditional paths may differ): trim, s.toLowerCase, filter, map, s.split, part.trim
- L65 · resolveFirstEventTimeoutMs calls (conditional paths may differ): groups.includes
- L75 · loadFirstEventTimeoutConfig calls (conditional paths may differ): Date.now, Promise.all, repos.systemConfig.getConfig, parseFirstEventTimeoutMs, parseFirstEventTimeoutRouteGroups
- L97 · firstEventTimeoutErrorResponse calls (conditional paths may differ): JSON.stringify
- L112 · peekResponseFirstEvent calls (conditional paths may differ): peekFirstStreamChunk, console.warn, firstEventTimeoutErrorResponse
- L140 · peekFirstStreamChunk calls (conditional paths may differ): body.getReader, createSseProgressScanner, Date.now, readWithIdleTimeout, reader.cancel, buffered.push, scanner.feed, prependChunks
- L182 · prependChunks calls (conditional paths may differ): controller.enqueue, controller.close, reader.read, reader.cancel
- L38 · streamIdleTimeoutErrorFrame calls (conditional paths may differ): JSON.stringify
- L146 · createStreamIdleClock calls (conditional paths may differ): createSseProgressScanner, Date.now, Math.max, nextStreamReadTimeoutMs, scanner.feed
- L179 · readWithIdleTimeout calls (conditional paths may differ): Number.isFinite, reader.read, setTimeout, resolve, Promise.race, clearTimeout
- L62 · mergeAsrExtras calls (conditional paths may differ): applyUpstreamExtraFields, protectedUpstreamPathsForRoute, Object.defineProperty
- L81 · readRestoredUpstreamPaths calls (conditional paths may differ): Array.isArray, value.filter
- L86 · asObject calls (conditional paths may differ): Array.isArray
- L92 · asFiniteNonNegativeNumber calls (conditional paths may differ): Number, Number.isFinite
- L98 · audioUploadToDataUrl calls (conditional paths may differ): file.bytes.subarray, Math.min, String.fromCharCode, btoa
- L114 · normalizedAsrOptions calls (conditional paths may differ): routeCustomParamsBody, asObject
- L126 · buildDashScopeSyncAsrBody calls (conditional paths may differ): messages.push, audioUploadToDataUrl, mergeAsrExtras, routeCustomParamsBody, normalizedAsrOptions
- L170 · resolveDashScopeAudioFileFormat calls (conditional paths may differ): extensionFromAudioMime, allowed.has, file.filename.match, JSON.stringify
- L186 · normalizedLanguageHints calls (conditional paths may differ): slice
- L193 · buildDashScopeQwenAudioAsrBody calls (conditional paths may differ): content.push, audioUploadToDataUrl, routeCustomParamsBody, resolveDashScopeAudioFileFormat, normalizedLanguageHints, mergeAsrExtras
- L242 · resolveDashScopeFunAsrFormat calls (conditional paths may differ): resolveDashScopeAudioFileFormat
- L247 · buildDashScopeFunAsrBody calls (conditional paths may differ): mergeAsrExtras, audioUploadToDataUrl, routeCustomParamsBody, resolveDashScopeFunAsrFormat
- L280 · buildDashScopeAsyncAsrBody calls (conditional paths may differ): routeCustomParamsBody, mergeAsrExtras
- L309 · firstArrayObject calls (conditional paths may differ): Array.isArray, asObject
- L314 · normalizeDashScopeSyncAsrResult calls (conditional paths may differ): asObject, firstArrayObject, Array.isArray, asFiniteNonNegativeNumber
- L335 · normalizeDashScopeDurationAsrResult calls (conditional paths may differ): asObject, asFiniteNonNegativeNumber, Array.isArray
- L365 · normalizeDashScopeQwenAudioAsrResult calls (conditional paths may differ): normalizeDashScopeDurationAsrResult
- L370 · normalizeDashScopeFunAsrResult calls (conditional paths may differ): normalizeDashScopeDurationAsrResult
- L375 · normalizeDashScopeAsyncAsrResult calls (conditional paths may differ): asObject, Array.isArray, transcript.text.trim, texts.push, segments.push, asFiniteNonNegativeNumber, texts.join
- L416 · parseJsonResponse calls (conditional paths may differ): response.text, JSON.parse, text.slice
- L428 · bodyRequestId calls (conditional paths may differ): normalizeUpstreamId, asObject
- L432 · clientResult calls (conditional paths may differ): reshapeTranscriptionForClient, buildAudioTranscriptionClientResponse, Promise.resolve, readRestoredUpstreamPaths
- L464 · resolveDashScopeDuration calls (conditional paths may differ): resolveAudioBillingDuration
- L477 · withTimeout calls (conditional paths may differ): controller.abort, setTimeout, clearTimeout
- L499 · errorDispatchResult calls (conditional paths may differ): clientResult
- L517 · buildSyncAsrBody calls (conditional paths may differ): buildDashScopeQwenAudioAsrBody, buildDashScopeFunAsrBody, buildDashScopeSyncAsrBody
- L527 · normalizeSyncAsrResult calls (conditional paths may differ): normalizeDashScopeQwenAudioAsrResult, normalizeDashScopeFunAsrResult, normalizeDashScopeSyncAsrResult
- L534 · dispatchDashScopeSyncAsr calls (conditional paths may differ): syncAsrFamily, resolveProviderUpstreamSecret, resolveUpstreamEndpoint, withTimeout, fetchImpl, applyRouteExtraHeaders, JSON.stringify, buildSyncAsrBody, extractUpstreamRequestId, parseJsonResponse, clientResult, bodyRequestId, normalizeSyncAsrResult, asFiniteNonNegativeNumber, asObject, resolveDashScopeDuration, parseOpenAiAudioTokenUsage, errorDispatchResult, timeout.timedOut, String
- L609 · taskOutput calls (conditional paths may differ): asObject
- L613 · waitForPoll calls (conditional paths may differ): setTimeout, signal.removeEventListener, resolve, clearTimeout, reject, signal.addEventListener
- L630 · dispatchDashScopeAsyncAsr calls (conditional paths may differ): resolveProviderUpstreamSecret, withTimeout, resolveUpstreamEndpoint, fetchImpl, applyRouteExtraHeaders, JSON.stringify, buildDashScopeAsyncAsrBody, parseJsonResponse, extractUpstreamRequestId, bodyRequestId, clientResult, taskOutput, taskId.trim, waitForPoll, Array.isArray, asObject, normalizeDashScopeAsyncAsrResult, asFiniteNonNegativeNumber, resolveDashScopeDuration, parseOpenAiAudioTokenUsage
- L784 · extractDashScopeMultimodalDurationSeconds calls (conditional paths may differ): asObject, asFiniteNonNegativeNumber
- L790 · dispatchDashScopeMultimodalPassthrough calls (conditional paths may differ): resolveProviderUpstreamSecret, resolveUpstreamEndpoint, withTimeout, fetchImpl, applyRouteExtraHeaders, JSON.stringify, extractUpstreamRequestId, parseJsonResponse, bodyRequestId, extractDashScopeMultimodalDurationSeconds, parseOpenAiAudioTokenUsage, resolveAudioBillingDuration, Promise.resolve, timeout.timedOut, String, timeout.clear
- L107 · registryConversionAdapterIds calls (conditional paths may differ): map, listConversionAdapters
- L111 · dispatchAudioTranscriptions calls (conditional paths may differ): dispatchOpenAiAudioTranscriptions, dispatchDashScopeSyncAsr, dispatchDashScopeAsyncAsr, dispatchMiniMaxAudioTranscriptions, dispatchElevenLabsAudioTranscriptions
- L156 · dispatchAudioSpeech calls (conditional paths may differ): dispatchOpenAiAudioSpeech, dispatch
- L174 · dispatchImageGenerations calls (conditional paths may differ): dispatchOpenAiImageGenerations, dispatchDashScopeImageGenerations, dispatchMiniMaxOpenAiImage, dispatchVolcengineOpenAiImage, dispatchGeminiOpenAiImage
- L199 · dispatchDashScopeJsonPassthroughRoute calls (conditional paths may differ): dispatchDashScopeJsonPassthrough
- L218 · dispatchMultimodalPassthrough calls (conditional paths may differ): dispatchDashScopeMultimodalPassthrough
- L232 · dispatchGeminiImagePassthroughRoute calls (conditional paths may differ): dispatchGeminiImagePassthrough
- L245 · dispatchVolcengineJsonPassthroughRoute calls (conditional paths may differ): dispatchVolcengineJsonPassthrough
- L256 · dispatchMiniMaxJsonPassthroughRoute calls (conditional paths may differ): dispatchMiniMaxJsonPassthrough
- L268 · dispatchMiniMaxSpeechPassthrough calls (conditional paths may differ): dispatchMiniMaxAsrPassthrough
- L32 · asObject calls (conditional paths may differ): Array.isArray
- L38 · billingPayload calls (conditional paths may differ): Array.isArray
- L43 · traceIdOf calls (conditional paths may differ): asObject, billingPayload, traceId.trim
- L60 · streamResponseHeaders calls (conditional paths may differ): source.forEach, STREAM_HEADER_BLOCKLIST.has, key.toLowerCase, headers.append
- L76 · dispatchMiniMaxJsonPassthrough calls (conditional paths may differ): resolveProviderUpstreamSecret, resolveUpstreamEndpoint, setTimeout, timeoutController.abort, fetchImpl, applyRouteExtraHeaders, JSON.stringify, extractUpstreamRequestId, response.headers.get, contentType.includes, streamResult, response.text, JSON.parse, billingPayload, readMiniMaxBaseResp, miniMaxBaseRespHttpStatus, readMiniMaxUsageCharacters, countMiniMaxImages, jsonResponse, Promise.resolve
- L178 · scanStream calls (conditional paths may differ): window.match, Number, match.match, Number.isFinite, window.slice
- L201 · streamResult calls (conditional paths may differ): resolveUsage, source.getReader, usageWith, reader.read, finish, controller.close, scanStream, decoder.decode, controller.enqueue, String, controller.error, reader.cancel, streamResponseHeaders
- L27 · streamResponseHeaders calls (conditional paths may differ): source.forEach, STREAM_HEADER_BLOCKLIST.has, key.toLowerCase, headers.append
- L47 · errorResult calls (conditional paths may differ): jsonResponse, JSON.stringify, Promise.resolve
- L63 · dispatchVolcengineJsonPassthrough calls (conditional paths may differ): postVolcengineImages, response.headers.get, includes, contentType.toLowerCase, streamResult, response.text, JSON.parse, countVolcengineImages, jsonResponse, Promise.resolve, usageWith, errorResult
- L127 · streamResult calls (conditional paths may differ): resolveUsage, source.getReader, volcengineSseImageCount, usageWith, reader.read, finish, controller.close, scanVolcengineImageSse, decoder.decode, controller.enqueue, String, controller.error, reader.cancel, streamResponseHeaders
- L47 · streamResponseHeaders calls (conditional paths may differ): source.forEach, STREAM_HEADER_BLOCKLIST.has, key.toLowerCase, headers.append
- L63 · withTimeoutSignal calls (conditional paths may differ): controller.abort, setTimeout, clearTimeout
- L88 · errorResult calls (conditional paths may differ): jsonResponse, JSON.stringify, Promise.resolve
- L106 · applyImageMeta calls (conditional paths may differ): parseGeminiImageUsage
- L117 · dispatchGeminiImagePassthrough calls (conditional paths may differ): withTimeoutSignal, resolveUpstreamEndpoint, resolveProviderUpstreamSecret, prepareGeminiUpstreamFetch, resolveGeminiAuthForUpstreamSecret, buildRouteRequestBody, fetchImpl, prepared.url.toString, applyRouteExtraHeaders, JSON.stringify, extractUpstreamRequestId, response.headers.get, contentType.toLowerCase, lowerType.includes, streamResult, response.text, timeout.clear, JSON.parse, Array.isArray, applyImageMeta
- L215 · streamResult calls (conditional paths may differ): timeout.clear, applyImageMeta, resolveUsage, source.getReader, scanGeminiGenerateContentSse, timeout.getAbortReason, finish, controller.error, reader.read, controller.close, decoder.decode, controller.enqueue, reader.cancel, streamResponseHeaders
- L48 · usageFromAnthropic calls (conditional paths may differ): JSON.stringify
- L106 · parseEventData calls (conditional paths may differ): JSON.parse, hasAnthropicReasoningDelta, hasAnthropicContentDelta, normalizeUpstreamId, applyUsage, usageFromAnthropic
- L131 · parseSSEChunk calls (conditional paths may differ): decoder.decode, state.lineBuffer.split, lines.pop, line.startsWith, parseEventData, trim, line.slice
- L146 · processRemainingLineBuffer calls (conditional paths may differ): state.lineBuffer.trim, line.startsWith, parseEventData, trim, line.slice
- L156 · pumpWithUsageTracking calls (conditional paths may differ): upstream.getReader, downstream.getWriter, createStreamIdleClock, readWithIdleTimeout, idleClock.timeoutMs, applyStreamIdleTimeout, console.log, reader.cancel, writer.write, idleFrameEncoder.encode, streamIdleTimeoutErrorFrame, idleClock.noteChunk, processRemainingLineBuffer, parseSSEChunk, Date.now, resolveUsage, writer.close, console.warn, String
- L242 · streamResponseWithUsage calls (conditional paths may differ): catch, pumpWithUsageTracking, response.headers.get
- L273 · nonStreamResponseWithUsage calls (conditional paths may differ): response.headers.get, contentType.includes, Promise.resolve, response.text, JSON.parse, usageFromAnthropic, normalizeUpstreamId, sanitizeRewrappedHeaders
- L313 · dispatchAnthropicRoute calls (conditional paths may differ): resolveUpstreamEndpoint, resolveProviderUpstreamSecret, buildRouteRequestBody, fetchUntilHeaders, applyRouteExtraHeaders, JSON.stringify, extractUpstreamRequestId, response.headers.get, contentType.includes, nonStreamResponseWithUsage, peekResponseFirstEvent, Promise.resolve, streamResponseWithUsage
- L63 · thoughtsTokenCountFromGemini calls (conditional paths may differ): Number.isFinite
- L68 · usageFromGemini calls (conditional paths may differ): thoughtsTokenCountFromGemini, Math.max, JSON.stringify
- L141 · parseJsonUsage calls (conditional paths may differ): JSON.parse, hasGeminiReasoningPart, hasGeminiContentPart, normalizeUpstreamId, applyUsage, usageFromGemini
- L182 · parseSSEChunk calls (conditional paths may differ): decoder.decode, state.lineBuffer.split, lines.pop, line.startsWith, trim, line.slice, parseJsonUsage
- L199 · processRemainingLineBuffer calls (conditional paths may differ): state.lineBuffer.trim, line.startsWith, trim, line.slice, parseJsonUsage
- L211 · pumpWithUsageTracking calls (conditional paths may differ): upstream.getReader, downstream.getWriter, createStreamIdleClock, readWithIdleTimeout, idleClock.timeoutMs, applyStreamIdleTimeout, console.log, reader.cancel, writer.write, idleFrameEncoder.encode, streamIdleTimeoutErrorFrame, idleClock.noteChunk, processRemainingLineBuffer, parseSSEChunk, Date.now, resolveUsage, writer.close, console.warn, String
- L297 · streamResponseWithUsage calls (conditional paths may differ): catch, pumpWithUsageTracking, response.headers.get
- L326 · nonStreamResponseWithUsage calls (conditional paths may differ): response.headers.get, contentType.includes, Promise.resolve, response.text, parseJsonUsage, sanitizeRewrappedHeaders
- L363 · buildInvalidThoughtSignatureRetry calls (conditional paths may differ): Array.isArray, text, response.clone, isInvalidThoughtSignatureErrorBody, sanitizeGeminiThoughtSignatures
- L384 · dispatchGeminiRoute calls (conditional paths may differ): resolveUpstreamEndpoint, resolveProviderUpstreamSecret, prepareGeminiUpstreamFetch, resolveGeminiAuthForUpstreamSecret, buildRouteRequestBody, applyRouteExtraHeaders, fetchUntilHeaders, url.toString, JSON.stringify, send, buildInvalidThoughtSignatureRetry, console.log, extractUpstreamRequestId, response.headers.get, contentType.includes, nonStreamResponseWithUsage, peekResponseFirstEvent, Promise.resolve, streamResponseWithUsage
- L34 · finiteCount calls (conditional paths may differ): Number.isFinite
- L39 · parseOpenAiEmbeddingsUsage calls (conditional paths may differ): JSON.parse, finiteCount, JSON.stringify
- L59 · dispatchOpenAiEmbeddingsRoute calls (conditional paths may differ): resolveUpstreamEndpoint, resolveProviderUpstreamSecret, buildRouteRequestBody, applyVertexOpenAiModelPrefix, fetch, applyRouteExtraHeaders, JSON.stringify, extractUpstreamRequestId, Promise.resolve, response.headers.get, contentType.includes, response.text, parseOpenAiEmbeddingsUsage, sanitizeRewrappedHeaders
- L35 · isPlainObject calls (conditional paths may differ): Array.isArray
- L39 · finiteCount calls (conditional paths may differ): Number.isFinite
- L48 · rewriteGeminiEmbedModel calls (conditional paths may differ): Array.isArray, body.requests.map, isPlainObject
- L67 · parseGeminiEmbedUsage calls (conditional paths may differ): JSON.parse, finiteCount, JSON.stringify
- L87 · dispatchGeminiEmbedRoute calls (conditional paths may differ): resolveUpstreamEndpoint, resolveProviderUpstreamSecret, prepareGeminiUpstreamFetch, resolveGeminiAuthForUpstreamSecret, rewriteGeminiEmbedModel, buildRouteRequestBody, fetch, url.toString, applyRouteExtraHeaders, JSON.stringify, extractUpstreamRequestId, response.headers.get, contentType.includes, Promise.resolve, response.text, parseGeminiEmbedUsage, sanitizeRewrappedHeaders
- L32 · authenticateOAuthAccessToken calls (conditional paths may differ): Date.now, repos.oauthAccessTokens.getByHash, hashOAuthAccessToken, oauthAccessTokenStatus, repos.users.getById, roundGatewayMoney, Number, persistLazyBudgetResetIfNeeded, catch, repos.oauthAccessTokens.touchLastUsed, console.warn
- L117 · truncateForAlert calls (conditional paths may differ): s.trim, t.slice
- L125 · extractHttpStatus calls (conditional paths may differ): errorMessage.match, Number.parseInt, Number.isFinite
- L137 · errorMessageLower calls (conditional paths may differ): toLowerCase
- L141 · hasTimeoutSignal calls (conditional paths may differ): errorMessageLower, test, lower.includes, extractHttpStatus
- L165 · hasRouteConfigSignal calls (conditional paths may differ): errorMessageLower, lower.includes
- L175 · hasAuthSignal calls (conditional paths may differ): errorMessageLower, lower.includes
- L189 · hasRateLimitSignal calls (conditional paths may differ): errorMessageLower, lower.includes
- L200 · classifyGatewayErrorAlert calls (conditional paths may differ): extractHttpStatus, hasRouteConfigSignal, hasTimeoutSignal, hasAuthSignal, hasRateLimitSignal, isSensitiveContentErrorMessage
- L228 · formatLatency calls (conditional paths may differ): toFixed
- L238 · displayModel calls (conditional paths may differ): trim
- L243 · displayProvider calls (conditional paths may differ): trim
- L248 · formatSupplierLine calls (conditional paths may differ): displayProvider, trim
- L259 · formatOccurredAt calls (conditional paths may differ): Number.isNaN, date.getTime, format
- L290 · formatCircuitDurationSeconds calls (conditional paths may differ): Math.max, Math.ceil
- L295 · formatCircuitEventLine calls (conditional paths may differ): formatOccurredAt, toISOString, formatCircuitDurationSeconds, trim, formatCircuitFailureKind
- L312 · buildCircuitMeasuresSection calls (conditional paths may differ): events.map, formatCircuitEventLine
- L320 · buildSummaryLine calls (conditional paths may differ): truncateForAlert, formatLatency, extractHttpStatus
- L331 · buildGatewayErrorAlertSummary calls (conditional paths may differ): classifyGatewayErrorAlert, displayModel, truncateForAlert, formatOccurredAt, toISOString, buildSummaryLine, formatSupplierLine, buildCircuitMeasuresSection, lines.join
- L356 · postJsonWithTimeout calls (conditional paths may differ): setTimeout, ac.abort, fetch, JSON.stringify, clearTimeout
- L371 · sendWeComRobot calls (conditional paths may differ): postJsonWithTimeout, res.text, JSON.parse, truncateForAlert
- L392 · sendFeishuBot calls (conditional paths may differ): postJsonWithTimeout, res.text, JSON.parse, truncateForAlert
- L418 · fireGatewayErrorWebhooks calls (conditional paths may differ): Promise.all, getSystemConfigValue, trim, buildGatewayErrorAlertSummary, truncateForAlert, tasks.push, sendWeComRobot, sendFeishuBot
- L13 · sanitizeRewrappedHeaders calls (conditional paths may differ): source.forEach, REWRAPPED_HEADER_BLOCKLIST.has, key.toLowerCase, headers.append
- L47 · maybePurgeIfOverCapacity calls (conditional paths may differ): circuitUntilByKey.delete
- L58 · toOpenInfo calls (conditional paths may differ): Math.max, Math.ceil
- L68 · getUserModelCircuitOpen calls (conditional paths may differ): Date.now, circuitKey, circuitUntilByKey.get, toOpenInfo
- L85 · getSensitiveContentCircuitOpen calls (conditional paths may differ): Date.now, getUserModelCircuitOpen
- L97 · recordUserModelCircuitTrigger calls (conditional paths may differ): Date.now, circuitKey, circuitUntilByKey.get, Math.min, Math.max, circuitUntilByKey.set, maybePurgeIfOverCapacity, toOpenInfo
- L127 · recordSensitiveContentCircuitTrigger calls (conditional paths may differ): Date.now, recordUserModelCircuitTrigger
- L137 · recordClientErrorCircuitTrigger calls (conditional paths may differ): Date.now, recordUserModelCircuitTrigger
- L147 · markUserModelSuccess calls (conditional paths may differ): Date.now, circuitUntilByKey.delete, circuitKey
- L151 · isSensitiveUpstreamResponse calls (conditional paths may differ): formatHttpErrorTextForRequestLog, isSensitiveContentErrorMessage
- L160 · formatUserModelCircuitOpenErrorMessage calls (conditional paths may differ): toISOString
- L169 · formatSensitiveContentCircuitOpenErrorMessage calls (conditional paths may differ): formatUserModelCircuitOpenErrorMessage
- L173 · buildSensitiveContentCircuitOpenResponse calls (conditional paths may differ): toISOString, JSON.stringify, String
- L195 · buildClientErrorCircuitOpenResponse calls (conditional paths may differ): toISOString, JSON.stringify
- L219 · buildUserModelCircuitOpenResponse calls (conditional paths may differ): buildSensitiveContentCircuitOpenResponse, buildClientErrorCircuitOpenResponse
- L227 · resetUserModelCircuitStateForTests calls (conditional paths may differ): circuitUntilByKey.clear
- L232 · resetSensitiveContentCircuitStateForTests calls (conditional paths may differ): resetUserModelCircuitStateForTests
- L72 · buildRequestPricingAuditJson calls (conditional paths may differ): JSON.stringify
- L89 · applyRouteFactorsToSide calls (conditional paths may differ): normalizeScheduleFactor, scaleBillingPrices, toScheduleAudit, toProviderFactorAudit
- L113 · recordUsage calls (conditional paths may differ): Number.isFinite, Number.isNaN, requestedPricingAtUtc.getTime, getBusinessTimezone, resolveRouteEffectiveFactors, parsePricingProfile, resolveDailyScheduleFactor, toScheduleAudit, resolveSupplierBillingPrices, resolveStandardBillingPrices, resolveChargedBillingPrices, applyRouteFactorsToSide, computeMeteredCost, roundGatewayMoney, factorsJson.trim, parseUserChargedCostFactors, console.warn, resolveUserChargedCostFactorMatch, getUserChargedCostFactorMode, resolveCombinedChargedFactor
- L16 · isFinitePositive calls (conditional paths may differ): Number.isFinite
- L20 · clampBillingSeconds calls (conditional paths may differ): isFinitePositive, Math.min, Math.max
- L28 · parseWavDurationSeconds calls (conditional paths may differ): view.getUint32, isFinitePositive
- L88 · readEbmlFloat calls (conditional paths may differ): view.getFloat32, view.getFloat64
- L99 · parseWebmDurationSeconds calls (conditional paths may differ): Math.min, readEbmlVint, readEbmlFloat, Number.isFinite, isFinitePositive
- L180 · parseAudioFileDurationSeconds calls (conditional paths may differ): split, toLowerCase, trim, parseWavDurationSeconds, mime.includes, parseWebmDurationSeconds
- L203 · acceptClientDurationSeconds calls (conditional paths may differ): isFinitePositive, Number.isFinite
- L216 · resolveAudioBillingDuration calls (conditional paths may differ): isFinitePositive, clampBillingSeconds, parseAudioFileDurationSeconds, acceptClientDurationSeconds, estimateAudioDurationFromBytes
- L6 · orderByHashAffinity calls (conditional paths may differ): sort, routeAffinityScore, a.providerId.localeCompare
- L5 · orderByWeightedRandom calls (conditional paths may differ): pool.reduce, Math.max, Math.random, ordered.push, pool.splice
- L5 · orderByWeightPriority calls (conditional paths may differ): sort, a.providerId.localeCompare
- L39 · purgeIfOverCapacity calls (conditional paths may differ): circuitByProvider.delete
- L51 · parseRetryAfterMs calls (conditional paths may differ): Date.now, retryAfterHeader.trim, test, Number, Date.parse, Number.isNaN, Math.max
- L69 · markProviderFailure calls (conditional paths may differ): Date.now, circuitByProvider.get, Math.min, Math.max, circuitByProvider.set, purgeIfOverCapacity
- L128 · markProviderSuccess calls (conditional paths may differ): Date.now, circuitByProvider.get, circuitByProvider.delete
- L140 · getProviderCircuitRemainingMs calls (conditional paths may differ): Date.now, circuitByProvider.get, Math.max
- L146 · isProviderCircuitOpen calls (conditional paths may differ): Date.now, getProviderCircuitRemainingMs
- L151 · resetProviderCircuitStateForTests calls (conditional paths may differ): circuitByProvider.clear
- L16 · groupRoutesByPriorityDesc calls (conditional paths may differ): groups.get, bucket.push, groups.set, map, sort, groups.entries
- L32 · buildRouteAttemptPlan calls (conditional paths may differ): Date.now, groupRoutesByPriorityDesc, strategy, getProviderCircuitRemainingMs, trackRetryAfter, attempts.push
- L36 · asObject calls (conditional paths may differ): Array.isArray
- L42 · fail calls (conditional paths may differ): JSON.stringify, Promise.resolve
- L64 · upstreamErrorMessage calls (conditional paths may differ): asObject, message.trim
- L70 · dispatchGeminiOpenAiImage calls (conditional paths may differ): detachUpstreamExtraFields, applyUpstreamExtraFields, buildGeminiImageBodyFromOpenAi, protectedUpstreamPathsForRoute, fail, geminiImageBillingSize, withTimeoutSignal, resolveUpstreamEndpoint, resolveProviderUpstreamSecret, prepareGeminiUpstreamFetch, resolveGeminiAuthForUpstreamSecret, prepared.url.toString, applyRouteExtraHeaders, JSON.stringify, response.text, timeout.getAbortReason, timeout.clear, extractUpstreamRequestId, JSON.parse, upstreamErrorMessage
- L58 · asObject calls (conditional paths may differ): Array.isArray
- L68 · errorResult calls (conditional paths may differ): JSON.stringify, Promise.resolve
- L85 · bytesToBase64 calls (conditional paths may differ): String.fromCharCode, bytes.subarray, Math.min, btoa
- L93 · sseFrame calls (conditional paths may differ): encode, JSON.stringify
- L97 · parseMiniMaxOpenAiSpeechEvent calls (conditional paths may differ): readMiniMaxBaseResp, asObject, data.audio.trim, readMiniMaxUsageCharacters, root.trace_id.trim
- L114 · withTimeout calls (conditional paths may differ): setTimeout, controller.abort, clearTimeout
- L136 · postMiniMax calls (conditional paths may differ): withTimeout, resolveUpstreamEndpoint, resolveProviderUpstreamSecret, fetchImpl, applyRouteExtraHeaders, JSON.stringify, extractUpstreamRequestId, timeout.clear, timeout.timedOut
- L192 · speechStreamResponse calls (conditional paths may differ): String, resolveUsage, options.reader.read, pending.push, options.parser.push, pending.shift, parseMiniMaxOpenAiSpeechEvent, applySpeechUsage, bytesToBase64, decodeMiniMaxHexAudio, controller.enqueue, sseFrame, controller.close, finish, options.reader.cancel, controller.error
- L275 · dispatchMiniMaxOpenAiSpeech calls (conditional paths may differ): buildMiniMaxT2aBodyFromOpenAi, voiceId, applyUpstreamExtraFields, protectedUpstreamPathsForRoute, fillMiniMaxSpeechDefaults, errorResult, postMiniMax, posted.response.headers.get, includes, contentType.toLowerCase, posted.clear, posted.response.body.getReader, reader.read, initial.push, parser.push, parseMiniMaxOpenAiSpeechEvent, reader.cancel, readMiniMaxBaseResp, miniMaxBaseRespHttpStatus, String
- L415 · dispatchMiniMaxOpenAiImage calls (conditional paths may differ): errorResult, detachUpstreamExtraFields, buildMiniMaxImageBodyFromOpenAi, applyUpstreamExtraFields, protectedUpstreamPathsForRoute, fail, postMiniMax, posted.response.text, JSON.parse, asObject, String, readMiniMaxBaseResp, miniMaxBaseRespHttpStatus, miniMaxImageResponseToOpenAi, countValidImageResults, JSON.stringify, Promise.resolve, posted.clear
- L59 · bytesToBase64 calls (conditional paths may differ): String.fromCharCode, bytes.subarray, Math.min, btoa
- L67 · sseFrame calls (conditional paths may differ): encode, JSON.stringify
- L72 · speechSseResponse calls (conditional paths may differ): resolveUsage, elevenLabsJsonError, source.getReader, reader.read, controller.enqueue, sseFrame, controller.close, finish, bytesToBase64, String, controller.error, reader.cancel
- L151 · dispatchElevenLabsOpenAiSpeech calls (conditional paths may differ): buildElevenLabsTtsRequestFromOpenAi, voiceId, applyUpstreamExtraFields, protectedUpstreamPathsForRoute, splitElevenLabsTtsQuery, elevenLabsJsonError, setTimeout, timeoutController.abort, resolveElevenLabsTtsUrl, resolveProviderUpstreamSecret, fetchImpl, applyRouteExtraHeaders, JSON.stringify, extractUpstreamRequestId, elevenLabsUpstreamErrorResult, readElevenLabsCharacterCount, Array.from, speechSseResponse, elevenLabsTrackedStream, elevenLabsTransportError
- L251 · dispatchElevenLabsAudioTranscriptions calls (conditional paths may differ): validateAudioUpload, resolveElevenLabsAsrMapping, buildRouteRequestBody, assertElevenLabsAsrNotWebhook, elevenLabsJsonError, Object.entries, ASR_FORM_SKIP_KEYS.has, formExtraFieldText, fields.push, resolveUpstreamEndpoint, buildElevenLabsSttForm, withTimeoutSignal, resolveProviderUpstreamSecret, fetchImpl, applyRouteExtraHeaders, extractUpstreamRequestId, elevenLabsUpstreamErrorResult, response.text, JSON.parse, resolveElevenLabsSttBilling
- L29 · asObject calls (conditional paths may differ): Array.isArray
- L35 · jsonResponse calls (conditional paths may differ): JSON.stringify
- L42 · fail calls (conditional paths may differ): jsonResponse, Promise.resolve
- L60 · upstreamErrorMessage calls (conditional paths may differ): asObject, message.trim
- L66 · dispatchVolcengineOpenAiImage calls (conditional paths may differ): detachUpstreamExtraFields, buildVolcengineImageBodyFromOpenAi, applyUpstreamExtraFields, protectedUpstreamPathsForRoute, fail, postVolcengineImages, posted.response.text, JSON.parse, upstreamErrorMessage, volcengineImageResponseToOpenAi, firstVolcengineImageFailureMessage, volcengineImageBillingSize, jsonResponse, Promise.resolve
- L24 · postVolcengineImages calls (conditional paths may differ): resolveProviderUpstreamSecret, resolveUpstreamEndpoint, setTimeout, timeoutController.abort, fetchImpl, applyRouteExtraHeaders, JSON.stringify, extractUpstreamRequestId, String, clearTimeout
Build and deployment pipeline · 5 GitHub Actions workflows
Repository CI declarations, separate from runtime request processing. Job dependencies and conditions are shown as written; long commands are shortened with an ellipsis; a workflow file does not prove a recent successful run.
Triggers: workflow_dispatch
delete · no job dependencies declared
- Delete matching package versions
actions/github-script@v7
Triggers: pull_request, push, workflow_dispatch
typecheck-admin · no job dependencies declared
- Checkout
actions/checkout@v4 - actions/setup-node@v4
actions/setup-node@v4 - Install
npm ci --ignore-scripts - Typecheck admin (same surface as Docker next build)
npm run typecheck:admin
smoke-node-pg · after typecheck-admin
- Checkout
actions/checkout@v4 - Set up Docker Buildx
docker/setup-buildx-action@v3 - Build and start postgres + proxy + admin
set -euo pipefail docker compose -f docker/compose/node-pg.yml up -d --build postgres gateway-proxy gateway-admin - Wait for proxy health
set -euo pipefail for i in $(seq 1 60); do if curl -fsS "http://127.0.0.1:8787/health" >/dev/null; then echo "proxy healthy after ${i}s" exit 0 fi sleep 2 done echo "proxy failed to become healthy" >&2 docker compose -f docker/compose/node-pg.yml logs gateway-proxy | tail -80 exit 1 - Wait for admin health
set -euo pipefail for i in $(seq 1 90); do if curl -fsS "http://127.0.0.1:8789/" >/dev/null; then echo "admin healthy after ${i}s" exit 0 fi sleep 2 done echo "admin failed to become healthy" >&2 docker compose -f docker/compose/node-pg.yml logs gateway-admin | tail -80 exit 1 - Smoke GET endpoints
set -euo pipefail curl -fsS "http://127.0.0.1:8787/health" | head -c 400 echo curl -fsS -o /dev/null -w "admin_http=%{http_code}\n" "http://127.0.0.1:8789/" - Teardown
docker compose -f docker/compose/node-pg.yml down -v --remove-orphans || trueCondition: always()
Triggers: push, workflow_dispatch
prepare · no job dependencies declared
- Shell command
set -euo pipefail if [ "${{ github.event_name }}" = "workflow_dispatch" ]; then items='[]' if [ "${{ inputs.build_proxy }}" = "true" ]; then items=$(echo "$items" | jq -c '. + [{"dockerfile":"Dockerfile.proxy","image_suffix":"proxy"}]') fi if [ "${{ inputs.build_admin }}" = "true" ]; then items=$(echo "$items" | jq -c '. + [{"dockerfile":"Dockerfile.admin","image_suffix":"admin"}]') fi if [ "${{ inputs.build_migrate }}" = "true" ]; then items=$(echo "$items" | jq -c '. + [{"dockerfile":"Dockerf…
build-and-push · after prepare
- Checkout
actions/checkout@v4 - GHCR image name (lowercase)
echo "repository_lc=$(echo '${{ github.repository }}' | tr '[:upper:]' '[:lower:]')" >> "$GITHUB_OUTPUT" - Set up QEMU
docker/setup-qemu-action@v3 - Set up Docker Buildx
docker/setup-buildx-action@v3 - Log in to GHCR
docker/login-action@v3 - Resolve image destinations (GHCR)
set -euo pipefail { echo "images<<EOF" echo "$GHCR_IMAGE" echo "EOF" } >> "$GITHUB_OUTPUT" - Docker metadata
docker/metadata-action@v5 - Build and push
docker/build-push-action@v6 - Upload digest for release notes
set -euo pipefail echo "$DIGEST" > "${SUFFIX}.digest"Condition: ${{ needs.prepare.outputs.is_tag_release == 'true' }} - Upload digest artifact
actions/upload-artifact@v4Condition: ${{ needs.prepare.outputs.is_tag_release == 'true' }} - Image digest (log)
echo "Image: ${{ matrix.dockerfile }} (${{ matrix.image_suffix }})" echo "Digest: ${{ steps.docker_build.outputs.digest }}" echo "Pushed tags:" && echo '${{ steps.meta.outputs.tags }}'
publish-release · after prepare, build-and-push
Condition: ${{ needs.prepare.outputs.is_tag_release == 'true' }}
- Checkout (release note sources)
actions/checkout@v4 - Download digest artifacts
actions/download-artifact@v4 - Write GitHub Release notes
set -euo pipefail OWNER_REPO_LC=$(echo '${{ github.repository }}' | tr '[:upper:]' '[:lower:]') TAG="${{ github.ref_name }}" VERSION="${TAG#v}" resolve_digest_file() { local s="$1" find digest-artifacts -name "${s}.digest" -type f 2>/dev/null | head -1 } cmd=( node scripts/release/render-release-notes.mjs --version "${VERSION}" --repo "${{ github.repository }}" --owner-repo-lc "${OWNER_REPO_LC}" --out release-notes.md ) for s in proxy admin migrate; do f=$(resolve_digest_file "$s") if [ -n "$f"… - Create or update GitHub Release
set -euo pipefail TAG="${{ github.ref_name }}" if gh release view "$TAG" --repo "${{ github.repository }}" 2>/dev/null; then gh release edit "$TAG" --repo "${{ github.repository }}" --notes-file release-notes.md else gh release create "$TAG" --repo "${{ github.repository }}" --title "OctaFuse ${TAG}" --notes-file release-notes.md fi
Triggers: push
Changesets · no job dependencies declared
- Checkout
actions/checkout@v4 - Setup Node.js
actions/setup-node@v4 - Install dependencies
npm ci - Verify package versions (no drift)
npm run verify:package-versions - Create Version PR or push tags
changesets/action@v1 - Dispatch Docker images workflow when tag did not chain-trigger
set -euo pipefail if [ -n "${CHANGESETS_PAT}" ]; then echo "PAT mode detected; expecting tag push to chain-trigger Docker — skip dispatch." exit 0 fi PKG_VERSION="$(node -p "JSON.parse(require('fs').readFileSync('package.json','utf8')).version")" EXPECTED_TAG="v${PKG_VERSION}" echo "Root package.json version: ${PKG_VERSION} (expected release tag: ${EXPECTED_TAG})" echo "GITHUB_SHA: ${GITHUB_SHA}" git fetch origin --tags # 防御性切回 GITHUB_SHA(changesets/action 通常不改本地 HEAD,但保险)。 git checkout "${GITH…Condition: success()
Triggers: pull_request, push
verify · no job dependencies declared
- actions/checkout@v4
actions/checkout@v4 - actions/setup-node@v4
actions/setup-node@v4 - Assert fixed monorepo versions
npm run verify:package-versions
release:notes: node scripts/release/render-release-notes.mjsdeploy:proxy: npm run gen:wrangler -- --remote && npm run deploy -w @octafuse/proxydeploy:admin: npm run build -w @octafuse/core && npm run gen:wrangler -- --remote && npm run deploy -w @octafuse/admindeploy:cloudflare: node scripts/deploy/deploy-instance.mjs
build: npm run cf-typegen && next build && node ./scripts/link-standalone-next.mjsbuild:docker: next build && node ./scripts/link-standalone-next.mjs && node ./scripts/build-node-server.mjsbuild:cf: npm run cf-typegen && opennextjs-cloudflare builddeploy: npm run build:cf && wrangler deploy worker.ts
prebuild: node -e "try{require('fs').rmSync('dist',{recursive:true,force:true})}catch(e){}"build: npm run build:migrate && npm run build:node-indexbuild:migrate: tsc -p tsconfig.build.migrate.jsonbuild:node-index: esbuild src/index.ts --bundle --platform=node --format=esm --outfile=dist/index.js --packages=external --log-level=warning
deploy: wrangler deploy --config ./wrangler.jsoncprebuild: node -e "try{require('fs').rmSync('dist',{recursive:true,force:true})}catch(e){}"build: node ./scripts/build.mjs
Repository README
View original on GitHub ↗Full upstream document by @OctaFuse · README.md · snapshot be74c9c
Octafuse Gateway
Octafuse Gateway 是面向 Agent 的可自托管开源 AI 网关。它将不同供应商的文本、图像、语音与工具能力汇聚到统一入口,支持 Chat Completions、OpenAI Responses API、图像生成与编辑、ASR、TTS、实时语音和智能体工具(Agent Tools),也可以接入自建或私有部署的 AI 服务。通过统一的路由、密钥、预算、计费和审计,Octafuse 帮助个人与团队集中管理和调度分散的 AI 资源。它不只是转发模型请求,更是面向 Agent 的可发现、可调用、可治理、可持续扩展的 AI 能力底座。
语言: 中文 · English · 日本語 · 한국어 · 官网: octafuse.dev
欢迎开源贡献 · 招募全职 / 兼职核心伙伴:从一次贡献开始,积累开源协作与工程经验,让你的想法成为项目的一部分。也期待热爱项目、具备用户思维、愿意长期投入并承担责任的伙伴,一起维护 Octafuse、探索商业化;有网关与 MaaS 经验者优先。了解如何参与 →
核心能力
Octafuse Gateway 的核心目标是构建统一超级个体(OPC)或企业内部的 AI 能力中枢。通过 Octafuse 将你所持有的各种模态的 AI 能力和多种多样的工具能力实现统一接入、分发、计费等企业级管理控制。
所以它具备以下这些核心能力:
- 供应商(Provider)接入:支持接入任意模型厂商或聚合平台的模型服务。同时,内置大量导入模板(含各种 Coding/Token Plan),无需复制黏贴各平台的接入端点,直接一键导入,然后复制对应的 API 密钥(ApiKey)即可完成接入。支持一键导入的完整列表见官网 Providers Catalog,若有希望加入预置供应商的厂商,欢迎提交 PR。
- AI 模型接入:可直接从预置目录导入模型,无需逐项填写常用参数和价格。支持一键导入的模型列表见官网 Models Catalog;若希望接入新的模型,欢迎提交 PR。
- 多协议接入:AI 模型全协议接入,目前支持:
- OpenAI 端点:
- Chat Completions:
POST /v1/chat/completions - Responses:
POST /v1/responses - Images:
POST /v1/images/generations、POST /v1/images/edits - Audio:
POST /v1/audio/transcriptions、POST /v1/audio/speech - Models:
GET /v1/models
- Chat Completions:
- Anthropic 端点:
POST /v1/messages - Google Gemini 端点:
POST /v1beta/models/{model}:generateContent(含streamGenerateContent) - DashScope 原生端点:
- 同步多模态(ASR、Qwen-TTS、生图):
POST /dashscope/api/v1/services/aigc/multimodal-generation/generation - 语音合成:
POST /dashscope/api/v1/services/audio/tts/SpeechSynthesizer - 异步文件转写:
POST /dashscope/api/v1/services/audio/asr/transcription、GET /dashscope/api/v1/tasks/{taskId} - 实时音频:
GET /dashscope/api-ws/v1/inference(run-task)/GET /dashscope/api-ws/v1/realtime?model=(Qwen-Realtime 会话)
- 同步多模态(ASR、Qwen-TTS、生图):
- MiniMax 原生端点:
- 文件转写:
POST /minimax/v1/speech_to_text - 语音合成:
POST /minimax/v1/t2a_v2 - 生图:
POST /minimax/v1/image_generation
- 文件转写:
- 火山方舟原生端点(Seedream 生图):
POST /volcengine/api/v3/images/generations
- OpenAI 端点:
- 协议适配与转换:可在路由中选择客户端与上游的协议转换关系,让应用继续使用熟悉的调用方式接入不同供应商。例如,可直接用 OpenAI 图片接口调用阿里云百炼的千问 / 万相、火山方舟的 Seedream 和 MiniMax 图像模型,或用 OpenAI 语音接口调用百炼与 MiniMax 的语音识别和语音合成。
- 智能体工具接入:通过
/v1/tools/*统一接入各种供 Agent 使用的工具,并提供日志、计费、成本管控,以方便 Agent 同时从 Gateway 接入模型和工具。当前预置工具如下:- 联网搜索(
POST /v1/tools/web-search):博查、Tavily、阿里云 CleverSee、腾讯云联网搜索 WSA - 网页抓取(
POST /v1/tools/web-fetch):Firecrawl、Tavily Extract、Jina Reader - 深度搜索(
POST /v1/tools/web-deep-search,搜+读一体):Firecrawl Search、Jina Search - AI 率检测(
POST /v1/tools/ai-detection):当前已实现腾讯云 TMS,并预留多引擎扩展目录 - 更多工具持续接入中,也欢迎 PR 继续丰富智能体常用工具。
- 联网搜索(
- AI 能力统一出口:所有接入的模型、平台和工具都通过 Octafuse Gateway 的 Base URL 对外提供服务。客户端只需配置一个网关地址,不必分别记住每个平台和工具的访问地址。
- 多样的路由策略:当一个模型我们有多个资源的时候,为了更高效的使用资源,可以根据情况配置不同的路由策略。目前支持四种策略:
- hash_affinity:默认策略;同用户、模型、协议稳定首选上游,缓存命中率高,适合依赖 Prompt Cache、会话连续性的场景;短时流量不一定完全均匀
- weighted_random:按权重加权随机分流,负载均衡性高,适合按比例分摊成本或 A/B;同一用户可能频繁切换供应商,缓存命中率较低
- weight_priority:按权重从高到低固定排序,结果可预测,适合同层明确主备;首选供应商会承担大部分流量
- weighted_round_robin:按权重轮转分摊,流量更均匀;计数器按运行实例维护,多实例间不保证全局同步
- 用户管理与记账一体化:统一接入后,可继续在 Gateway 中完成用户、额度和成本管理,包括:
- 外部系统(External system)、用户(User)、API 密钥三层结构:通过 External system 区分不同系统或团队,再通过用户下的 API 密钥完成调用鉴权、扣费和审计
- 双额度体系:周期额度适合订阅套餐,永久额度适合加油包或人工加额,两种额度可以同时使用
- 三账本设计:每一个调用对于计费涵盖三个费用计算,包括:目录价(模型/工具标准价)、成本价(实际采购价格)、用户价(用户扣除额度)
- 峰谷计价:支持按模型和路由设置峰谷价格、区分工作日与周末,并预览不同时间段的实际价格
- 用户级模型倍率:可为单个用户按目录模型设置折扣、加价或免单;只改变最终用户计费与预算累加,不影响目录价和供应成本
- 管理后台(Admin)与管理 API:
- 具备完善的管理后台和管理接口,可以手工维护也可以接入其他系统门户使用
- 可观测性与数据分析:详细记录了请求细节和各类数据,可以方便查看、统计、分析
- 测试与联调:提供调试台(Playground)/ 模拟器(Simulator),可快速检查供应商、模型、路由和客户端配置,也支持调试实时语音识别
- 灵活的部署方式:
- 支持 Cloudflare Workers + D1 免费部署
- 支持 Docker + Postgres / MySQL 部署
管理后台一览
| 供应商接入 | 请求入口(Request Surface)→ 策略 → 上游目标(Upstream Target) 路由拓扑 |
|---|---|
![]() |
![]() |
供应商页面负责接入上游账号与协议端点;路由页面把客户端请求入口、路由策略和上游目标放在一条可视链路中。完整配置顺序见 管理后台配置指南。
与其他开源 AI Gateway 的差异
New API、LiteLLM、Sub2API 和 Bifrost 都是成熟且各有所长的开源 AI Gateway。Octafuse 更关注 Agent 能力交付与 AI 资源运营,主要差异集中在以下五个方向:
| 重点方向 | Octafuse 内建机制 | 适合场景 |
|---|---|---|
| Agent 能力 | 联网搜索、网页抓取、深度搜索,以及工具调用日志与计费 | 为 Agent 同时提供模型与工具 |
| 资源接入 | 供应商 / 模型预设、多协议端点和一键导入 | 统一管理分散的 AI 资源 |
| 精细路由 | 独立路由池、分层策略、缓存亲和、主备与熔断 | 在稳定性、缓存命中率和成本间平衡 |
| 运营计费 | 目录价、供应成本、用户扣费三账本,支持分时与多模态计价 | 内部核算、额度管理或对外运营 |
| 灵活部署 | Docker + 多数据库,或 Cloudflare Workers + D1 | 自托管、边缘部署与低成本起步 |
评级说明:
- ✅ 完善:公开版本已形成覆盖该维度主要场景的完整机制
- 🟡 良好:具备成熟的核心能力,但覆盖范围或运营深度相对有限
- 🟠 基础:具备可用的基础实现,仍需较多外部组件或二次开发
- ⚪ 无:官方公开文档未将其列为同类内建能力
展开完整能力对比(24 项)
能力接入与 Agent
| 细分能力 | Octafuse | New API | LiteLLM | Sub2API | Bifrost |
|---|---|---|---|---|---|
| 供应商 / 模型预设与一键导入 | ✅ | 🟡 | 🟡 | 🟡 | 🟡 |
| OpenAI、Anthropic、Gemini 主流协议接入 | ✅ | ✅ | ✅ | ✅ | ✅ |
| DashScope 原生同步 / 实时音频与跨协议路由 | ✅¹ | ⚪ | ⚪ | ⚪ | ⚪ |
| 文本、图像、语音与视频等多模态覆盖 | 🟡² | ✅ | ✅ | 🟡 | ✅ |
| 内置联网搜索、抓取与深度搜索 | ✅ | ⚪ | 🟠 | 🟠 | 🟠 |
| 工具供应商配置、调用日志与计费 | ✅ | ⚪ | 🟡 | 🟠 | 🟠 |
路由与治理
| 细分能力 | Octafuse | New API | LiteLLM | Sub2API | Bifrost |
|---|---|---|---|---|---|
| 协议 / operation 级请求入口与独立路由池 | ✅ | 🟠 | 🟡 | 🟡 | 🟡 |
| 多策略分流与分层覆盖 | ✅ | 🟡 | ✅ | 🟡 | 🟡 |
| Prompt Cache 亲和路由 | ✅ | 🟡 | ✅ | ✅ | ✅ |
| 优先级主备、故障转移与供应商熔断 | ✅ | 🟡 | ✅ | 🟡 | ✅ |
| 外部系统、用户与 API 密钥分层治理 | ✅ | 🟡 | ✅ | 🟡 | ✅ |
| 周期预算、状态与模型访问控制 | ✅ | ✅ | ✅ | ✅ | ✅ |
计费
| 细分能力 | Octafuse | New API | LiteLLM | Sub2API | Bifrost |
|---|---|---|---|---|---|
| 目录价、供应成本、用户扣费三账本 | ✅ | ⚪ | ⚪ | ✅ | ⚪ |
| 按业务时区的分时计价倍率 | ✅ | ⚪ | ⚪ | 🟡 | ⚪ |
| 图像 / 语音差异化计价 | ✅ | 🟡 | 🟡 | 🟡 | 🟠 |
| 智能体工具按次计费 | ✅ | ⚪ | 🟡 | 🟠 | 🟠 |
运维与部署
| 细分能力 | Octafuse | New API | LiteLLM | Sub2API | Bifrost |
|---|---|---|---|---|---|
| 管理后台 | ✅ | ✅ | ✅ | ✅ | ✅ |
| 管理 API | ✅ | ✅ | ✅ | ✅ | ✅ |
| 可观测性 | ✅ | ✅ | ✅ | ✅ | ✅ |
| SQLite / D1 | ✅ | ✅ | ⚪ | ⚪ | ✅ |
| PostgreSQL | ✅ | ✅ | ✅ | ✅ | ✅ |
| MySQL | ✅ | ✅ | ⚪ | ⚪ | ⚪ |
| Docker 自托管部署 | ✅ | ✅ | ✅ | ✅ | ✅ |
| Cloudflare Workers 边缘部署 | ✅ | ⚪ | ⚪ | ⚪ | ⚪ |
1 Octafuse 支持 DashScope 原生同步 / 异步 ASR、语音合成、实时 ASR / TTS 与生图,并可将 OpenAI 兼容的图像、ASR、TTS 请求跨协议路由至 DashScope。MiniMax 与火山方舟的原生接口按同样方式接入。
2 Octafuse 当前已覆盖文本、图像、ASR、TTS 与实时语音;视频等能力尚未纳入统一请求入口。
评价基于各项目当前公开仓库与官方文档,重点衡量“是否内建并形成完整机制”,不评价性能、社区规模、商业支持或二次开发潜力。这是围绕 Octafuse 产品定位的能力比较,不是对各项目全部功能的综合排名。各项目持续演进,具体能力和授权范围请以其最新官方文档为准。
快速开始
需要 Node.js 20+。代理服务(Proxy)与管理后台需两个终端同时运行。
git clone https://github.com/OctaFuse/octafuse-gateway.git
cd octafuse-gateway
npm install
npm run db:migrate
终端 1 — 代理服务(:8787):
npm run dev:proxy
终端 2 — 管理后台(:8789):
npm run dev:admin
| 服务 | 地址 | 说明 |
|---|---|---|
| 代理服务 | http://127.0.0.1:8787 | 推理入口 |
| 管理后台 | http://127.0.0.1:8789 | 控制台;本地默认账号 admin / admin |
首次运行 dev:admin 会生成 packages/admin/.dev.vars。打开管理后台,配置供应商、路由和用户 API 密钥,然后使用该密钥调用代理服务。详细步骤与 curl 示例见 docs/users/quickstart.md。
部署到 Cloudflare
npx wrangler login
npm run bootstrap:cloudflare
详见 Cloudflare 快速部署。用于生产环境前,请修改默认管理后台密码,并为外部集成创建独立、最小权限的 Admin API Key。
Docker 自托管及 Postgres / MySQL 数据库方案见 部署文档索引。
文档
| 任务 | 链接 |
|---|---|
| 功能地图、管理后台配置、客户端接入 | docs/users/ |
| 本地上手与示例请求 | docs/users/quickstart.md |
| API、集成、本地开发、架构 | docs/developers/ |
| Cloudflare / Docker / 迁移 | docs/operators/ |
| 发版与维护 | docs/maintainers/ |
| HTTP 示例 | examples/README.md |
贡献与安全
欢迎从代码、产品体验、测试、文档或用户支持开始参与。贡献方向、长期共建与全职 / 兼职合作机会,详见 参与与共建说明。
开源协议
本仓库使用 GNU Affero General Public License v3.0(AGPLv3) 授权,详见 LICENSE。
Frequently asked about Octafuse Gateway
What is Octafuse Gateway?+
Octafuse Gateway is a self-hosted OpenRouter/Portkey alternative built on the Cloudflare developer platform. A self-hosted AI gateway with one API key, routing, budgets and audit logs
What does Octafuse Gateway replace?+
Octafuse Gateway is listed as an alternative to OpenRouter, Portkey. Compare the features and tradeoffs before migrating.
What Cloudflare primitives does Octafuse Gateway use?+
Octafuse Gateway is built on D1, Workers.
How much does Octafuse Gateway cost to run?+
Light personal or small-team traffic can start on the Workers Free plan with D1. Each proxied request counts as Worker requests and D1 writes for logs; Free plan CPU per request and daily request limits cap throughput, and model-provider charges are always separate. Model usage is billed by each upstream provider under the operator’s own keys; Octafuse records costs but does not pay them. The repository ships base templates; `npm run gen:wrangler` generates the deployable Wrangler files. Licensed AGPL-3.0: modified versions offered to users over a network must make their source available. Source and configuration review establishes a deployment path and conditional costs; this candidate was not executed or load-tested. Official Cloudflare pricing pages saved 31 Oct 2026 (Markdown editions of developers.cloudflare.com pricing documentation). Check current Cloudflare pricing before deploying.
Is Octafuse Gateway open source?+
The upstream repository declares the AGPL-3.0 license. Read its terms at https://raw.githubusercontent.com/OctaFuse/octafuse-gateway/be74c9c6778de5a3e84b84804978e52c7cde43f3/LICENSE. Source code and contributor credit are available at https://github.com/OctaFuse/octafuse-gateway.
Community rating
No ratings yet. Tried this project? Share your experience.
One rating per verified account. You can change or remove yours. Accounts are email verified; use of the software is self-reported.




Discussion · 0
sign in to comment →