UNPKG

@juspay/neurolink

Version:

The pipe layer of an AI nervous system: one interface connecting provider neurons to your application, across three inference types — generate, stream and decide. `decide` returns typed, calibrated judgements from a non-generative model (~400ms, ~$0.00002

90 lines (89 loc) • 4.17 kB
/** * Gemini-Compatible Proxy Routes * * Exposes the Google `generateContent` / `streamGenerateContent` endpoints the * Gemini CLI calls when pointed at this proxy via `GOOGLE_GEMINI_BASE_URL`. * ALL requests are routed through ctx.neurolink.stream() via the shared proxy * translation engine — no direct HTTP calls to any upstream provider. * * This is a thin wrapper that parses the Google wire format and delegates to * the same translation engine openaiProxyRoutes.ts and claudeProxyRoutes.ts * use, mirroring that file's validate → log → delegate shape. * * An optional ModelRouter can remap incoming model names to different * provider/model pairs, exactly as it does for the OpenAI-compatible door. */ import type { ModelRouterInterface, ParsedGeminiRequest, ProxyRuntimeConfigProvider, RouteGroup } from "../../types/index.js"; /** * Google bakes the action into the final path segment as `<model>:<action>` * (`models/gemini-2.5-pro:generateContent`). Hono's router has no way to * express a literal `:` after a named param — verified directly against the * `hono` version this repo pins: registering `:model\:generateContent` * doesn't escape the colon, it becomes *part of the param name*, and the * resulting param still greedily swallows the whole trailing segment * (`streamGenerateContent` included) because nothing after the leading `:` * stops the capture except the next `/`. A `:model{regex}` constraint * followed by literal text fails outright — the route never matches (404 on * every request). A bare `:model` segment is therefore the only shape that * actually matches; it captures `<model>:<action>` whole, and this function * splits it back apart in the handler instead of in the route table. */ /** * Pull "<model>:<action>" out of the request path. * * Read from `ctx.path`, not from a route param. Hono does capture the whole * `gemini-2.5-pro:generateContent` segment — the colon is not a route * separator, so one route covers both actions — but the proxy's mount loop * builds its ServerContext from `path`, `headers`, `query`, `body`, `method` * and `requestId` only. The captured param never reaches the handler, and * reading `ctx.params` here would be `undefined` on every request. */ declare function splitModelAction(requestPath: string): { modelId: string; action: string | undefined; }; /** * buildProxyTranslationPlan's classifier expects ParsedClaudeRequest, whose * `maxTokens` is required. Gemini's is optional (Google omits * `generationConfig.maxOutputTokens` on plenty of real requests), so the gap * is bridged the same way the OpenAI door bridges it: fill in a safe default * and let the (structurally near-identical) rest pass through untouched. */ declare function adaptGeminiForTranslationPlan(parsed: ParsedGeminiRequest): { model: string; maxTokens: number; temperature?: number; topP?: number; systemPrompt?: string; stream: boolean; prompt: string; images: string[]; conversationMessages: Array<{ role: string; content: string; }>; tools: Record<string, { description?: string; inputSchema: unknown; execute?: (...args: unknown[]) => unknown; }>; stopSequences?: string[]; }; /** * Create Gemini-compatible proxy routes. * * Every request flows through ctx.neurolink.stream() — no direct HTTP calls * to any upstream provider. * * @param modelRouter - Optional model router for remapping model names. * @param basePath - Base path prefix (default: ""). * @param loopbackPort - Unused by this door; kept for parameter-shape parity * with createOpenAIProxyRoutes (see DEFAULT_LOOPBACK_PORT). * @returns RouteGroup with Gemini-compatible endpoints. */ export declare function createGeminiProxyRoutes(modelRouter?: ModelRouterInterface, basePath?: string, _loopbackPort?: number, runtimeConfigProvider?: ProxyRuntimeConfigProvider): RouteGroup; export declare const __testHooks: { splitModelAction: typeof splitModelAction; adaptGeminiForTranslationPlan: typeof adaptGeminiForTranslationPlan; }; export {};