import { randomBytes } from "crypto"; import { type IncomingMessage, type ServerResponse } from "http"; import { Readable } from "stream"; import { routeRequests, InsufficientBalanceError, ProviderManager, } from "@routstr/sdk"; import type { UsageTrackingDriver, SdkLogger } from "@routstr/sdk"; import { logger } from "../../utils/logger"; import { CocodHttpError, type CocodClient, type CocodState, } from "../wallet/cocod-client"; import { decodeCashuTokenAmount } from "../wallet"; import { getClientsFromStore } from "../../utils/clients"; type ClientMode = "xcashu" | "lazyrefund" | "apikeys"; type WalletStatusOutput = { daemon: "running"; wallet: "connected" | "error"; walletState: CocodState; balances?: Record; mode: ClientMode; error?: string; }; type DaemonDeps = { provider: string | null; server: { close(cb?: () => void): void }; store: any; walletClient: CocodClient; walletAdapter: any; storageAdapter: any; providerRegistry: any; discoveryAdapter: any; modelManager: any; ensureProvidersBootstrapped: () => Promise; getRoutstr21Models: (forceRefresh?: boolean) => Promise; getModelProviders: (modelId: string) => Promise; mode?: ClientMode; /** Nostr hex pubkey for routstr review/model events (kind 38425/38423). */ routstrPubkey?: string; providerManager: ProviderManager; }; /** * Extracts the client ID from an incoming request by looking up the API key * in the store's clientIds list. */ function getClientIdFromRequest( req: IncomingMessage, store: { getState(): any }, ): string | undefined { const authHeader = req.headers.authorization; if (!authHeader || !authHeader.startsWith("Bearer ")) { return undefined; } const apiKey = authHeader.slice(7); // Remove "Bearer " prefix if (!apiKey.startsWith("sk-")) { return undefined; } const clients = getClientsFromStore(store); const matchingClient = clients.find((c) => c.apiKey === apiKey); return matchingClient?.clientId; } function generateApiKey(): string { const bytes = randomBytes(24); return `sk-${bytes.toString("hex")}`; } async function readBody(req: IncomingMessage): Promise { return new Promise((resolve, reject) => { let data = ""; req.on("data", (chunk) => { data += chunk.toString(); }); req.on("end", () => resolve(data)); req.on("error", reject); }); } async function readJsonBody( req: IncomingMessage, ): Promise> { const bodyText = await readBody(req); if (!bodyText) { return {}; } try { return JSON.parse(bodyText) as Record; } catch { throw new CocodHttpError(400, "Invalid JSON body."); } } function parseLimit(value: string | null, fallback = 10): number { const requested = Number.parseInt(value || String(fallback), 10); return Number.isFinite(requested) && requested > 0 ? Math.min(requested, 100000) // Cap at 100k entries : fallback; } function sendJson( res: ServerResponse, status: number, payload: Record, ): void { res.writeHead(status, { "Content-Type": "application/json" }); res.end(JSON.stringify(payload)); } function toErrorMessage(error: unknown): string { return error instanceof Error ? error.message : String(error); } function getWalletStateMessage(state: CocodState): string { switch (state) { case "LOCKED": return "Wallet is locked. Unlock it before performing wallet operations."; case "UNINITIALIZED": return "Wallet is not initialized. Run 'routstrd onboard' first."; case "ERROR": return "Wallet is in an error state."; default: return "Wallet is unavailable."; } } function respondWithError( res: ServerResponse, error: unknown, fallbackStatus = 500, ): void { if (error instanceof CocodHttpError) { sendJson(res, error.status, { error: error.message }); return; } sendJson(res, fallbackStatus, { error: toErrorMessage(error) }); } async function respond( res: ServerResponse, getPayload: () => Promise>, ): Promise { try { sendJson(res, 200, await getPayload()); } catch (error) { respondWithError(res, error); } } function requireStringField( body: Record, field: string, ): string | null { const value = body[field]; return typeof value === "string" && value.trim() ? value.trim() : null; } function getRequiredStringField( body: Record, field: string, ): string { const value = requireStringField(body, field); if (!value) { throw new CocodHttpError(400, `Missing required '${field}' field.`); } return value; } function getRequiredPositiveNumberField( body: Record, field: string, ): number { const value = body[field]; if (typeof value === "number" && Number.isFinite(value) && value > 0) { return value; } if (typeof value === "string" && value.trim()) { const parsed = Number.parseInt(value.trim(), 10); if (Number.isFinite(parsed) && parsed > 0) { return parsed; } } throw new CocodHttpError(400, `Missing required '${field}' field.`); } function optionalStringField( body: Record, field: string, ): string | undefined { const value = body[field]; return typeof value === "string" && value.trim() ? value.trim() : undefined; } function getCurrentMode(deps: DaemonDeps): ClientMode { const stateMode = deps.store.getState()?.mode; return stateMode || deps.mode || "apikeys"; } async function buildStatusOutput( deps: DaemonDeps, ): Promise { const mode = getCurrentMode(deps); try { const walletState = await deps.walletClient.getStatus(); if (walletState !== "UNLOCKED") { return { daemon: "running", wallet: "error", walletState, mode, error: getWalletStateMessage(walletState), }; } const balances = await deps.walletAdapter.getBalances(); return { daemon: "running", wallet: "connected", walletState, balances, mode, }; } catch (error) { return { daemon: "running", wallet: "error", walletState: "ERROR", mode, error: toErrorMessage(error), }; } } async function buildWalletDetails(deps: DaemonDeps): Promise<{ state: CocodState; ready: boolean; balances?: Record; unit?: "sat"; activeMint?: string | null; }> { const state = await deps.walletClient.getStatus(); if (state !== "UNLOCKED") { return { state, ready: false }; } const balances = await deps.walletAdapter.getBalances(); return { state, ready: true, balances, unit: "sat", activeMint: deps.walletAdapter.getActiveMintUrl(), }; } function makeSdkLogger(prefix?: string): SdkLogger { const tag = prefix ? `[${prefix}]` : undefined; const fmt = (...args: unknown[]) => (tag ? [tag, ...args] : args); return { log: (...args: unknown[]) => logger.log(...fmt(...args)), warn: (...args: unknown[]) => logger.log(...fmt(...args)), error: (...args: unknown[]) => logger.error(...fmt(...args)), debug: (...args: unknown[]) => logger.debug(...fmt(...args)), child: (p: string) => makeSdkLogger(prefix ? `${prefix}:${p}` : p), }; } const sdkLogger: SdkLogger = makeSdkLogger(); export function createDaemonRequestHandler(deps: { provider: string | null; server: { close(cb?: () => void): void }; store: any; walletClient: CocodClient; walletAdapter: any; storageAdapter: any; providerRegistry: any; discoveryAdapter: any; modelManager: any; ensureProvidersBootstrapped: () => Promise; getRoutstr21Models: (forceRefresh?: boolean) => Promise; getModelProviders: (modelId: string) => Promise; mode?: "xcashu" | "apikeys"; /** Nostr hex pubkey for routstr review/model events (kind 38425/38423). */ routstrPubkey?: string; usageTrackingDriver: UsageTrackingDriver; providerManager: ProviderManager; }) { return async function handler(req: IncomingMessage, res: ServerResponse) { const host = req.headers.host || "localhost"; const url = new URL(req.url || "/", `http://${host}`); if (req.method === "GET" && url.pathname === "/health") { sendJson(res, 200, { ok: true }); return; } if (req.method === "GET" && url.pathname === "/ping") { sendJson(res, 200, { output: "pong" }); return; } if (req.method === "GET" && url.pathname === "/status") { const output = await buildStatusOutput(deps); sendJson(res, 200, { output }); return; } if (req.method === "GET" && url.pathname === "/wallet/status") { await respond(res, async () => ({ output: await buildWalletDetails(deps), })); return; } if (req.method === "POST" && url.pathname === "/wallet/unlock") { await respond(res, async () => { const body = await readJsonBody(req); const passphrase = getRequiredStringField(body, "passphrase"); const message = await deps.walletClient.unlock(passphrase); const state = await deps.walletClient.getStatus(); return { output: { message, state } }; }); return; } if (req.method === "GET" && url.pathname === "/wallet/balance") { await respond(res, async () => { const balances = await deps.walletAdapter.getBalances(); return { output: { balances, unit: "sat", activeMint: deps.walletAdapter.getActiveMintUrl(), walletState: "UNLOCKED", }, }; }); return; } if (req.method === "POST" && url.pathname === "/wallet/receive/cashu") { await respond(res, async () => { const body = await readJsonBody(req); const token = getRequiredStringField(body, "token"); const message = await deps.walletClient.receiveCashu(token); const { amount, unit } = decodeCashuTokenAmount(token); return { output: { message, amount, unit } }; }); return; } if (req.method === "POST" && url.pathname === "/wallet/receive/bolt11") { await respond(res, async () => { const body = await readJsonBody(req); const amount = getRequiredPositiveNumberField(body, "amount"); const mintUrl = optionalStringField(body, "mintUrl"); const invoice = await deps.walletClient.receiveBolt11(amount, mintUrl); return { output: { invoice, amount, mintUrl } }; }); return; } if (req.method === "POST" && url.pathname === "/wallet/send/cashu") { await respond(res, async () => { const body = await readJsonBody(req); const amount = getRequiredPositiveNumberField(body, "amount"); const mintUrl = optionalStringField(body, "mintUrl"); const token = await deps.walletClient.sendCashu(amount, mintUrl); return { output: { token, amount, mintUrl } }; }); return; } if (req.method === "POST" && url.pathname === "/wallet/send/bolt11") { await respond(res, async () => { const body = await readJsonBody(req); const invoice = getRequiredStringField(body, "invoice"); const mintUrl = optionalStringField(body, "mintUrl"); const message = await deps.walletClient.sendBolt11(invoice, mintUrl); return { output: { message, invoice, mintUrl } }; }); return; } if (req.method === "GET" && url.pathname === "/wallet/mints") { await respond(res, async () => { const mints = await deps.walletClient.listMints(); return { output: { mints, activeMint: mints[0] || null, }, }; }); return; } if (req.method === "POST" && url.pathname === "/wallet/mints") { await respond(res, async () => { const body = await readJsonBody(req); const mintUrl = getRequiredStringField(body, "url"); const message = await deps.walletClient.addMint(mintUrl); return { output: { message, url: mintUrl } }; }); return; } if (req.method === "POST" && url.pathname === "/wallet/mints/info") { await respond(res, async () => { const body = await readJsonBody(req); const mintUrl = getRequiredStringField(body, "url"); const info = await deps.walletClient.getMintInfo(mintUrl); return { output: { url: mintUrl, info } }; }); return; } if (req.method === "GET" && url.pathname === "/models") { try { const forceRefresh = url.searchParams.get("refresh")?.toLowerCase() === "true"; const models = await deps.getRoutstr21Models(forceRefresh); sendJson(res, 200, { output: { models } }); } catch (error) { sendJson(res, 500, { error: toErrorMessage(error) }); } return; } // Get providers for a specific model const modelProvidersMatch = url.pathname.match(/^\/models\/([^\/]+)\/providers$/); if (req.method === "GET" && modelProvidersMatch && modelProvidersMatch[1]) { try { const modelId = decodeURIComponent(modelProvidersMatch[1]); const modelWithProviders = await deps.getModelProviders(modelId); if (!modelWithProviders) { sendJson(res, 404, { error: `Model '${modelId}' not found` }); return; } sendJson(res, 200, { output: modelWithProviders }); } catch (error) { sendJson(res, 500, { error: toErrorMessage(error) }); } return; } if (req.method === "GET" && url.pathname === "/v1/models") { try { const forceRefresh = url.searchParams.get("refresh")?.toLowerCase() === "true"; const models = await deps.getRoutstr21Models(forceRefresh); sendJson(res, 200, { object: "list", data: models.map((model) => ({ ...model, object: "model" })), }); } catch (error) { sendJson(res, 500, { error: toErrorMessage(error) }); } return; } if (req.method === "POST" && url.pathname === "/stop") { sendJson(res, 200, { output: "stopping" }); setTimeout(() => { deps.server.close(() => { process.exit(0); }); }, 50); return; } if (req.method === "POST" && url.pathname === "/refund") { try { const body = await readJsonBody(req); const mintUrl = getRequiredStringField(body, "mintUrl"); const state = deps.store.getState(); const pendingDistribution = (state.cachedTokens || []).map( (t: { baseUrl: string; balance?: number }) => ({ baseUrl: t.baseUrl, amount: t.balance || 0, }), ); const apiKeysStored = (state.apiKeys || []).map( (k: { baseUrl: string; balance?: number }) => ({ baseUrl: k.baseUrl, amount: k.balance || 0, }), ); if (pendingDistribution.length === 0 && apiKeysStored.length === 0) { sendJson(res, 200, { output: { message: "No pending tokens to refund", results: [] }, }); return; } const refundBaseUrls = pendingDistribution .map((p: { baseUrl: string }) => p.baseUrl) .concat(apiKeysStored.map((p: { baseUrl: string }) => p.baseUrl)); const { RoutstrClient } = await import("@routstr/sdk"); const client = new RoutstrClient( deps.walletAdapter, deps.storageAdapter, deps.providerRegistry, "min", "apikeys", ); const spender = client.getCashuSpender(); const results = await spender.refundProviders(mintUrl, true); sendJson(res, 200, { output: { message: `Refunded to ${mintUrl}`, pendingTokens: pendingDistribution.length, apiKeys: apiKeysStored.length, results: results.map( (r: { baseUrl: string; success: boolean }) => ({ baseUrl: r.baseUrl, success: r.success, }), ), }, }); } catch (error) { logger.error(`Refund error: ${toErrorMessage(error)}`); respondWithError(res, error); } return; } if (req.method === "GET" && url.pathname === "/balance") { try { const balances = await deps.walletAdapter.getBalances(); sendJson(res, 200, { output: { balances, unit: "sat", activeMint: deps.walletAdapter.getActiveMintUrl(), }, }); } catch (error) { respondWithError(res, error); } return; } if (req.method === "GET" && url.pathname === "/keys/balance") { try { const walletBalances = await deps.walletAdapter.getBalances(); const totalWallet = Object.values(walletBalances).reduce( (sum, balance) => sum + Number(balance), 0, ); const state = deps.store.getState(); const cachedTokens = state.cachedTokens || []; const totalCached = cachedTokens.reduce( (sum: number, t: { balance?: number }) => sum + (t.balance || 0), 0, ); const apiKeys = state.apiKeys || []; const totalApiKeys = apiKeys.reduce( (sum: number, k: { balance?: number }) => sum + (k.balance || 0), 0, ); const keys: Array<{ id: string; name: string; balance: number }> = [ { id: "wallet", name: "Wallet", balance: totalWallet }, ...cachedTokens.map((t: { baseUrl: string; balance?: number }) => ({ id: `cached:${t.baseUrl}`, name: `Cached: ${t.baseUrl}`, balance: t.balance || 0, })), ...apiKeys.map((k: { baseUrl: string; balance?: number }) => ({ id: `apikey:${k.baseUrl}`, name: `API Key: ${k.baseUrl}`, balance: k.balance || 0, })), ]; sendJson(res, 200, { output: { keys, total: totalWallet + totalCached + totalApiKeys, unit: "sat", apikeysCalled: apiKeys.length, }, }); } catch (error) { res.writeHead(500, { "Content-Type": "application/json" }); res.end(JSON.stringify({ error: String(error) })); } return; } if (req.method === "POST" && url.pathname === "/providers/disable") { try { const bodyText = await readBody(req); const body = bodyText ? JSON.parse(bodyText) : {}; const indices = body.indices as number[] | undefined; if (!Array.isArray(indices)) { res.writeHead(400, { "Content-Type": "application/json" }); res.end( JSON.stringify({ error: "Missing or invalid 'indices' field (expected number[]).", }), ); return; } const state = deps.store.getState(); const baseUrlsList: string[] = state.baseUrlsList || []; const disabledProviders: string[] = [ ...(state.disabledProviders || []), ]; const toDisable: string[] = []; for (const idx of indices) { if ( typeof idx === "number" && idx >= 0 && idx < baseUrlsList.length ) { const baseUrl = baseUrlsList[idx]!; if (!disabledProviders.includes(baseUrl)) { disabledProviders.push(baseUrl); toDisable.push(baseUrl); } } } deps.store.getState().setDisabledProviders(disabledProviders); res.writeHead(200, { "Content-Type": "application/json" }); res.end( JSON.stringify({ output: { message: `Disabled ${toDisable.length} provider(s)`, disabled: toDisable, }, }), ); } catch (error) { res.writeHead(500, { "Content-Type": "application/json" }); res.end(JSON.stringify({ error: String(error) })); } return; } if (req.method === "POST" && url.pathname === "/providers/enable") { try { const bodyText = await readBody(req); const body = bodyText ? JSON.parse(bodyText) : {}; const indices = body.indices as number[] | undefined; if (!Array.isArray(indices)) { res.writeHead(400, { "Content-Type": "application/json" }); res.end( JSON.stringify({ error: "Missing or invalid 'indices' field (expected number[]).", }), ); return; } const state = deps.store.getState(); const baseUrlsList: string[] = state.baseUrlsList || []; const disabledProviders: string[] = [ ...(state.disabledProviders || []), ]; const toEnable: string[] = []; for (const idx of indices) { if ( typeof idx === "number" && idx >= 0 && idx < baseUrlsList.length ) { const baseUrl = baseUrlsList[idx]!; const pos = disabledProviders.indexOf(baseUrl); if (pos !== -1) { disabledProviders.splice(pos, 1); toEnable.push(baseUrl); } } } deps.store.getState().setDisabledProviders(disabledProviders); res.writeHead(200, { "Content-Type": "application/json" }); res.end( JSON.stringify({ output: { message: `Enabled ${toEnable.length} provider(s)`, enabled: toEnable, }, }), ); } catch (error) { res.writeHead(500, { "Content-Type": "application/json" }); res.end(JSON.stringify({ error: String(error) })); } return; } // Client management endpoints if (req.method === "GET" && url.pathname === "/clients") { try { const clients = getClientsFromStore(deps.store).map((c) => ({ id: c.clientId, name: c.name, apiKey: c.apiKey, createdAt: c.createdAt, lastUsed: c.lastUsed, ownerNpub: c.ownerNpub, })); res.writeHead(200, { "Content-Type": "application/json" }); res.end( JSON.stringify({ output: { clients, totalCount: clients.length, }, }), ); } catch (error) { res.writeHead(500, { "Content-Type": "application/json" }); res.end(JSON.stringify({ error: String(error) })); } return; } if (req.method === "POST" && url.pathname === "/clients/add") { try { const bodyText = await readBody(req); const body = bodyText ? JSON.parse(bodyText) : {}; const name = body.name as string | undefined; const explicitId = body.id as string | undefined; const ownerNpub = body.ownerNpub as string | undefined; if (!name || typeof name !== "string" || name.trim() === "") { res.writeHead(400, { "Content-Type": "application/json" }); res.end( JSON.stringify({ error: "Missing required 'name' field (must be a non-empty string).", }), ); return; } if (!explicitId || typeof explicitId !== "string" || explicitId.trim() === "") { res.writeHead(400, { "Content-Type": "application/json" }); res.end( JSON.stringify({ error: "Missing required 'id' field (must be a non-empty string).", }), ); return; } const sanitizeId = (value: string) => value .toLowerCase() .replace(/\s+/g, "-") .replace(/[^a-z0-9-]/g, ""); const clientId = sanitizeId(explicitId); if (!clientId) { res.writeHead(400, { "Content-Type": "application/json" }); res.end( JSON.stringify({ error: "Invalid client id. Must contain alphanumeric characters.", }), ); return; } const existingClients = getClientsFromStore(deps.store); const existingClient = existingClients.find( (c) => c.clientId === clientId, ); if (existingClient) { res.writeHead(409, { "Content-Type": "application/json" }); res.end( JSON.stringify({ error: `Client with id '${clientId}' already exists.`, }), ); return; } const apiKey = generateApiKey(); const newClient = { clientId, name: name.trim(), apiKey, createdAt: Date.now(), ...(ownerNpub && typeof ownerNpub === "string" ? { ownerNpub } : {}), }; deps.store .getState() .setClientIds((prev: typeof existingClients) => [ ...(prev || []), newClient, ]); logger.log(`Added client '${name}' with id '${clientId}'`); res.writeHead(200, { "Content-Type": "application/json" }); res.end( JSON.stringify({ output: { message: `Client '${name}' added successfully`, client: { id: clientId, name: name.trim(), apiKey, createdAt: newClient.createdAt, ownerNpub: newClient.ownerNpub, }, }, }), ); } catch (error) { respondWithError(res, error); } return; } if (req.method === "POST" && url.pathname === "/clients/delete") { try { const bodyText = await readBody(req); const body = bodyText ? JSON.parse(bodyText) : {}; const id = body.id as string | undefined; if (!id || typeof id !== "string" || id.trim() === "") { res.writeHead(400, { "Content-Type": "application/json" }); res.end( JSON.stringify({ error: "Missing required 'id' field (must be a non-empty string).", }), ); return; } const existingClients = getClientsFromStore(deps.store); const index = existingClients.findIndex( (c) => c.clientId === id, ); if (index === -1) { res.writeHead(404, { "Content-Type": "application/json" }); res.end( JSON.stringify({ error: `Client with id '${id}' not found.`, }), ); return; } const removedClient = existingClients[index]!; const updatedClients = existingClients.filter( (_c: unknown, i: number) => i !== index, ); deps.store.getState().setClientIds(updatedClients); logger.log( `Deleted client '${removedClient.name}' with id '${id}'`, ); res.writeHead(200, { "Content-Type": "application/json" }); res.end( JSON.stringify({ output: { message: `Client '${removedClient.name}' deleted successfully`, id, }, }), ); } catch (error) { respondWithError(res, error); } return; } if (req.method === "GET" && url.pathname === "/providers") { try { const state = deps.store.getState(); const baseUrlsList: string[] = state.baseUrlsList || []; const disabledProviders: string[] = state.disabledProviders || []; const providers = baseUrlsList.map((baseUrl, index) => ({ index, baseUrl, disabled: disabledProviders.includes(baseUrl), })); // Only count disabled providers that are actually in the current list // (filter out stale entries from previously disabled providers that are no longer present) const activeDisabledCount = providers.filter((p) => p.disabled).length; res.writeHead(200, { "Content-Type": "application/json" }); res.end( JSON.stringify({ output: { providers, disabledCount: activeDisabledCount, totalCount: baseUrlsList.length, }, }), ); } catch (error) { res.writeHead(500, { "Content-Type": "application/json" }); res.end(JSON.stringify({ error: String(error) })); } return; } if (req.method === "GET" && url.pathname === "/usage") { try { const output = await deps.usageTrackingDriver.list({ limit: parseLimit(url.searchParams.get("limit")), }); res.writeHead(200, { "Content-Type": "application/json" }); res.end(JSON.stringify({ output })); } catch (error) { sendJson(res, 500, { error: toErrorMessage(error) }); } return; } if (req.method === "GET" && url.pathname === "/usagePi") { try { const timestamp = (url.searchParams.get("timestamp") || "").trim(); if (!timestamp) { sendJson(res, 400, { error: "Missing required 'timestamp' query parameter.", }); return; } const usageDriver = deps.usageTrackingDriver; const limit = parseLimit(url.searchParams.get("limit")); const allMatching = await usageDriver.list(); const requestIdPrefix = `gen-${timestamp}-`; const filtered = allMatching.filter((entry) => entry.requestId.startsWith(requestIdPrefix), ); const entries = filtered.slice(0, limit); const totalEntries = filtered.length; const totalSatsCost = filtered.reduce( (sum, entry) => sum + (entry.satsCost || 0), 0, ); const recentSatsCost = entries.reduce( (sum, entry) => sum + (entry.satsCost || 0), 0, ); res.writeHead(200, { "Content-Type": "application/json" }); res.end( JSON.stringify({ output: { entries, totalEntries, totalSatsCost, recentSatsCost, limit, timestamp, }, }), ); } catch (error) { sendJson(res, 500, { error: toErrorMessage(error) }); } return; } // Allow client management endpoints through if (req.method !== "POST" && !url.pathname.startsWith("/clients")) { res.writeHead(405, { "Content-Type": "application/json" }); res.end(JSON.stringify({ error: "Only POST is supported." })); return; } let requestBody: unknown = {}; try { requestBody = await readJsonBody(req); } catch (error) { sendJson(res, 400, { error: "Invalid JSON body.", details: toErrorMessage(error), }); return; } const bodyObj = requestBody as Record; const modelId = typeof bodyObj.model === "string" ? bodyObj.model : ""; if (!modelId) { sendJson(res, 400, { error: "Missing required 'model' field." }); return; } const forcedProvider: string | undefined = url.searchParams.get("provider") || (req.headers["x-routstr-provider"] as string | undefined) || deps.provider || undefined; // Convert req.headers to Record const incomingHeaders: Record = {}; for (const [key, value] of Object.entries(req.headers)) { if (typeof value === "string") { incomingHeaders[key] = value; } else if (Array.isArray(value) && value.length > 0) { incomingHeaders[key] = value[0]!; } } try { await deps.ensureProvidersBootstrapped(); const reqId = randomBytes(4).toString("hex"); const reqLogger = sdkLogger.child(`req:${reqId}`); logger.log(`[req:${reqId}] Routing request with path: `, url.pathname); const response = await routeRequests({ modelId, requestBody, path: url.pathname, forcedProvider, headers: incomingHeaders, walletAdapter: deps.walletAdapter, storageAdapter: deps.storageAdapter, providerRegistry: deps.providerRegistry, discoveryAdapter: deps.discoveryAdapter, modelManager: deps.modelManager, debugLevel: "DEBUG", mode: deps.mode, usageTrackingDriver: deps.usageTrackingDriver, sdkStore: deps.store, providerManager: deps.providerManager, logger: reqLogger, ...(deps.routstrPubkey ? { routstrPubkey: deps.routstrPubkey } : {}), }); // Bridge the Web `Response` to the Node `ServerResponse` with no // transforms: status + headers + pipe(body → res). res.statusCode = response.status; response.headers.forEach((value, key) => { res.setHeader(key, value); }); const finalize = (response as any).finalize as | (() => Promise) | undefined; if (!response.body) { res.end(); if (finalize) { try { await finalize(); } catch (err) { logger.error(`[daemon] finalize error: ${toErrorMessage(err)}`); } } return; } const nodeReadable = Readable.fromWeb(response.body as any); await new Promise((resolve, reject) => { let settled = false; const finish = () => { if (settled) return; settled = true; resolve(); }; const fail = (err: unknown) => { if (settled) return; settled = true; reject(err); }; res.once("finish", finish); res.once("close", finish); res.once("error", fail); nodeReadable.once("error", fail); nodeReadable.pipe(res); }); if (finalize) { try { await finalize(); } catch (err) { logger.error(`[daemon] finalize error: ${toErrorMessage(err)}`); } } return; } catch (error) { const message = error instanceof Error ? error.message : String(error); logger.error(`[daemon] Error: ${message}`); if (error instanceof InsufficientBalanceError) { const balanceError = error as { required?: number; available?: number; maxMintBalance?: number; maxMintUrl?: string; }; res.writeHead(402, { "Content-Type": "application/json" }); res.end( JSON.stringify({ error: message, error_type: "insufficient_balance", required: balanceError.required, available: balanceError.available, maxMintBalance: balanceError.maxMintBalance, maxMintUrl: balanceError.maxMintUrl, }), ); return; } res.writeHead(500, { "Content-Type": "application/json" }); res.end(JSON.stringify({ error: message })); } }; }