@ckcloudai.com/clawrouter 0.0.1 → 0.0.3
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/dist/index.js +88 -9
- package/dist/index.js.map +1 -1
- package/package.json +1 -1
package/dist/index.js.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"sources":["../src/config.ts","../src/index.ts","../src/fs-read.ts","../src/version.ts","../src/models.ts","../src/provider.ts","../src/proxy.ts","../src/payment-preauth.ts","../src/balance.ts","../src/errors.ts","../src/solana-balance.ts","../src/stats.ts","../src/logger.ts","../src/plugin-logger.ts","../src/session.ts","../src/router/rules.ts","../src/router/selector.ts","../src/router/config.ts","../src/router/index.ts","../src/auth.ts","../src/wallet.ts","../node_modules/@noble/hashes/src/utils.ts","../node_modules/@noble/hashes/src/hmac.ts","../node_modules/@noble/hashes/src/_md.ts","../node_modules/@noble/hashes/src/_u64.ts","../node_modules/@noble/hashes/src/sha2.ts","../node_modules/@noble/hashes/src/sha512.ts","../src/dedup.ts","../src/response-cache.ts","../src/journal.ts"],"sourcesContent":["\n\nconst DEFAULT_PORT = 8402;\n\nexport const PROXY_PORT = (() => {\n const envPort = process[\"env\"].CKCLOUD_PROXY_PORT;\n if (envPort) {\n const parsed = parseInt(envPort, 10);\n if (!isNaN(parsed) && parsed > 0 && parsed < 65536) {\n return parsed;\n }\n }\n return DEFAULT_PORT;\n})();\n\nexport const PLUGIN_NAME = \"ckcloud\"","import type {\n OpenClawPluginDefinition,\n OpenClawPluginApi,\n PluginCommandContext,\n OpenClawPluginCommandDefinition,\n} from \"./types.js\";\nimport { PLUGIN_NAME } from \"./config\"\nimport type { RoutingConfig } from \"./router/index.js\";\nimport { BalanceMonitor } from \"./balance.js\";\nimport { join } from \"node:path\";\nimport { homedir } from \"node:os\";\nimport { writeFileSync, existsSync, readdirSync, mkdirSync, copyFileSync, renameSync } from \"node:fs\";\nimport { readTextFileSync } from \"./fs-read\"\n\nimport { VERSION } from \"./version\";\nimport { ckcloudProvider, setActiveProxy } from \"./provider\"\nimport { getProxyPort, startProxy } from \"./proxy\"\nimport { OPENCLAW_MODELS } from \"./models\"\nimport { getStats, formatStatsAscii, clearStats } from \"./stats\";\n\nimport {\n resolveOrGenerateWalletKey,\n setupSolana,\n savePaymentChain,\n resolvePaymentChain,\n WALLET_FILE,\n MNEMONIC_FILE,\n} from \"./auth.js\";\n\nimport { setPluginLogger } from \"./plugin-logger.js\";\n\nlet activeProxyHandle: Awaited<ReturnType<typeof startProxy>> | null = null;\n\nfunction isCompletionMode(): boolean {\n const args = process.argv;\n // Check for: openclaw completion --shell <shell>\n // argv[0] = node/bun, argv[1] = openclaw, argv[2] = completion\n return args.some((arg, i) => arg === \"completion\" && i >= 1 && i <= 3);\n}\n\nconst plugin: OpenClawPluginDefinition = {\n id: PLUGIN_NAME,\n name: PLUGIN_NAME,\n description: \"Smart LLM router — 80% cost savings\",\n version: VERSION,\n\n register(api: OpenClawPluginApi) {\n setPluginLogger(api.logger);\n const isDisabled = process[\"env\"].CKCLOUDROUTER_DISABLED === \"true\" || process[\"env\"].CKCLOUDROUTER_DISABLED === \"1\";\n if (isDisabled) {\n api.logger.info(\"ckcloudrouter disabled (CKCLOUDROUTER_DISABLED=true). Using default routing.\");\n return;\n }\n\n if (isCompletionMode()) {\n api.registerProvider(ckcloudProvider);\n return;\n }\n\n api.registerProvider(ckcloudProvider);\n\n // Inject models config into OpenClaw config file\n // This persists the config so models are recognized on restart\n injectModelsConfig(api.logger);\n\n // Inject dummy auth profiles into agent auth stores\n // OpenClaw's agent system looks for auth even if provider has auth: []\n injectAuthProfile(api.logger);\n\n // Also set runtime config for immediate availability\n const runtimePort = getProxyPort();\n if (!api.config.models) {\n api.config.models = { providers: {} };\n }\n if (!api.config.models.providers) {\n api.config.models.providers = {};\n }\n api.config.models.providers.ckcloud = {\n baseUrl: `http://127.0.0.1:${runtimePort}/v1`,\n api: \"openai-completions\",\n // apiKey is required by pi-coding-agent's ModelRegistry for providers with models.\n apiKey: \"x402-proxy-handles-auth\",\n models: OPENCLAW_MODELS,\n };\n api.logger.info(\"ckcloud provider registered\");\n\n // TODO Register /wallet command for wallet management\n\n\n // Register /stats command for usage statistics\n createStatsCommand().then((statsCommand) => {\n api.registerCommand(statsCommand);\n }).catch((err) => {\n api.logger.warn(`Failed to register /stats command: ${err instanceof Error ? err.message : String(err)}`,);\n });\n\n api.registerService({\n id: \"ckcloud-proxy\",\n start: () => {\n // No-op: proxy is started below in non-blocking mode\n },\n stop: async () => {\n // Close proxy on gateway shutdown to release port 8402\n if (activeProxyHandle) {\n try {\n await activeProxyHandle.close();\n api.logger.info(\"ckcloud proxy closed\");\n } catch (err) {\n api.logger.warn(\n `Failed to close proxy: ${err instanceof Error ? err.message : String(err)}`,\n );\n }\n activeProxyHandle = null;\n }\n },\n });\n\n // Skip proxy startup unless we're in gateway mode\n // The proxy keeps the Node.js event loop alive, preventing CLI commands from exiting\n // The proxy will start automatically when the gateway runs\n if (!isGatewayMode()) {\n // Generate wallet on first install (even outside gateway mode)\n // This ensures users can see their wallet address immediately after install\n resolveOrGenerateWalletKey()\n .then(({ address, source }) => {\n if (source === \"generated\") {\n api.logger.warn(`════════════════════════════════════════════════`);\n api.logger.warn(` NEW WALLET GENERATED — BACK UP YOUR KEY NOW!`);\n api.logger.warn(` Address : ${address}`);\n api.logger.warn(` Run /wallet export to get your private key`);\n api.logger.warn(` Losing this key = losing your USDC funds`);\n api.logger.warn(`════════════════════════════════════════════════`);\n } else if (source === \"saved\") {\n api.logger.info(`Using saved wallet: ${address}`);\n } else {\n api.logger.info(`Using wallet from WALLET_KEY: ${address}`);\n }\n })\n .catch((err) => {\n api.logger.warn(\n `Failed to initialize wallet: ${err instanceof Error ? err.message : String(err)}`,\n );\n });\n api.logger.info(\"Not in gateway mode — proxy will start when gateway runs\");\n return;\n }\n\n // Start x402 proxy in background WITHOUT blocking register()\n // CRITICAL: Do NOT await here - this was blocking model selection UI for 3+ seconds\n // causing Chandler's \"infinite loop\" issue where model selection never finishes\n // Note: startProxyInBackground calls resolveOrGenerateWalletKey internally\n startProxyInBackground(api)\n .then(async () => {\n // Proxy started successfully - verify health\n const port = getProxyPort();\n const healthy = await waitForProxyHealth(port, 5000);\n if (!healthy) {\n api.logger.warn(`Proxy health check timed out, commands may not work immediately`);\n }\n })\n .catch((err) => {\n api.logger.error(\n `Failed to start ckcloud proxy: ${err instanceof Error ? err.message : String(err)}`,\n );\n });\n\n }\n}\n\n\n/**\n * Wait for proxy health check to pass (quick check, not RPC).\n * Returns true if healthy within timeout, false otherwise.\n */\nasync function waitForProxyHealth(port: number, timeoutMs = 3000): Promise<boolean> {\n const start = Date.now();\n while (Date.now() - start < timeoutMs) {\n try {\n const res = await fetch(`http://127.0.0.1:${port}/health`);\n if (res.ok) return true;\n } catch {\n // Proxy not ready yet\n }\n await new Promise((r) => setTimeout(r, 100));\n }\n return false;\n}\n\nfunction isGatewayMode(): boolean {\n const args = process.argv;\n // Gateway mode is: openclaw gateway start/restart/stop\n return args.includes(\"gateway\");\n}\n\nfunction injectModelsConfig(logger: { info: (msg: string) => void }): void {\n const configDir = join(homedir(), \".openclaw\");\n const configPath = join(configDir, \"openclaw.json\");\n\n let config: Record<string, unknown> = {};\n let needsWrite = false;\n\n // Create config directory if it doesn't exist\n if (!existsSync(configDir)) {\n try {\n mkdirSync(configDir, { recursive: true });\n logger.info(\"Created OpenClaw config directory\");\n } catch (err) {\n logger.info(\n `Failed to create config dir: ${err instanceof Error ? err.message : String(err)}`,\n );\n return;\n }\n }\n\n // Load existing config or create new one\n // IMPORTANT: On parse failure, we backup and skip writing to avoid clobbering\n // other plugins' config (e.g. Telegram channels). This prevents a race condition\n // where a partial/corrupt config file causes us to overwrite everything with\n // only our models+agents sections.\n if (existsSync(configPath)) {\n try {\n const content = readTextFileSync(configPath).trim();\n if (content) {\n config = JSON.parse(content);\n } else {\n logger.info(\"OpenClaw config is empty, initializing\");\n needsWrite = true;\n }\n } catch (err) {\n // Config file exists but is corrupt/invalid JSON — likely a partial write\n // from another plugin or a race condition during gateway restart.\n // Backup the corrupt file and SKIP writing to avoid losing other config.\n const backupPath = `${configPath}.backup.${Date.now()}`;\n try {\n copyFileSync(configPath, backupPath);\n logger.info(`Config parse failed, backed up to ${backupPath}`);\n } catch {\n logger.info(\"Config parse failed, could not create backup\");\n }\n logger.info(\n `Skipping config injection (corrupt file): ${err instanceof Error ? err.message : String(err)}`,\n );\n return; // Don't write — we'd lose other plugins' config\n }\n } else {\n logger.info(\"OpenClaw config not found, creating\");\n needsWrite = true;\n }\n\n // Initialize config structure\n if (!config.models) {\n config.models = {};\n needsWrite = true;\n }\n const models = config.models as Record<string, unknown>;\n if (!models.providers) {\n models.providers = {};\n needsWrite = true;\n }\n\n const proxyPort = getProxyPort();\n const expectedBaseUrl = `http://127.0.0.1:${proxyPort}/v1`;\n\n const providers = models.providers as Record<string, unknown>;\n\n if (!providers.ckcloud) {\n providers.ckcloud = {\n baseUrl: expectedBaseUrl,\n api: \"openai-completions\",\n apiKey: \"x402-proxy-handles-auth\",//place holder\n models: OPENCLAW_MODELS,\n };\n logger.info(\"Injected ckcloud provider config\");\n needsWrite = true;\n } else {\n // Validate and fix existing config\n const ckcloud = providers.ckcloud as Record<string, unknown>;\n let fixed = false;\n\n if (!ckcloud.baseUrl || ckcloud.baseUrl !== expectedBaseUrl) {\n ckcloud.baseUrl = expectedBaseUrl;\n fixed = true;\n }\n if (!ckcloud.api) {\n ckcloud.api = \"openai-completions\";\n fixed = true;\n }\n if (!ckcloud.apiKey) {\n ckcloud.apiKey = \"x402-proxy-handles-auth\"; //TODO\n fixed = true;\n }\n // Always refresh models list (ensures new models/aliases are available)\n // Check both length AND content - new models may be added without changing count\n const currentModels = ckcloud.models as Array<{ id?: string }>;\n const currentModelIds = new Set(\n Array.isArray(currentModels) ? currentModels.map((m) => m?.id).filter(Boolean) : [],\n );\n const expectedModelIds = OPENCLAW_MODELS.map((m) => m.id);\n const needsModelUpdate =\n !currentModels ||\n !Array.isArray(currentModels) ||\n currentModels.length !== OPENCLAW_MODELS.length ||\n expectedModelIds.some((id) => !currentModelIds.has(id));\n\n if (needsModelUpdate) {\n ckcloud.models = OPENCLAW_MODELS;\n fixed = true;\n logger.info(`Updated models list (${OPENCLAW_MODELS.length} models)`);\n }\n\n if (fixed) {\n logger.info(\"Fixed incomplete ckcloud provider config\");\n needsWrite = true;\n }\n }\n\n if (!config.agents) {\n config.agents = {};\n needsWrite = true;\n }\n const agents = config.agents as Record<string, unknown>;\n if (!agents.defaults) {\n agents.defaults = {};\n needsWrite = true;\n }\n const defaults = agents.defaults as Record<string, unknown>;\n if (!defaults.model) {\n defaults.model = {};\n needsWrite = true;\n }\n const model = defaults.model as Record<string, unknown>;\n if (!model.primary) {\n model.primary = \"ckcloud/free\"; //TODO: default model\n logger.info(\"Set default model\");\n needsWrite = true;\n }\n\n const TOP_MODELS = [\n \"free\",\n \"eco\",\n \"premium\",\n \"anthropic/claude-sonnet-4.5\",\n \"openai/gpt-5.2\",\n \"deepseek/deepseek-chat\",\n \"moonshot/kimi-k2.5\",\n \"minimax/minimax-m2.5\",\n ];\n if (!defaults.models || typeof defaults.models !== \"object\" || Array.isArray(defaults.models)) {\n defaults.models = {};\n needsWrite = true;\n }\n const allowlist = defaults.models as Record<string, unknown>;\n // Additive-only: add TOP_MODELS entries if missing, never delete user-defined entries.\n // Preserves any ckcloud/* IDs the user has manually added outside this curated list.\n let addedCount = 0;\n for (const id of TOP_MODELS) {\n const key = `ckcloud/${id}`;\n if (!allowlist[key]) {\n allowlist[key] = {};\n addedCount++;\n }\n }\n if (addedCount > 0) {\n needsWrite = true;\n logger.info(`Added ${addedCount} models to allowlist (${TOP_MODELS.length} total)`);\n }\n\n // Write config file if any changes were made\n // Use atomic write (temp file + rename) to prevent partial writes that could\n // corrupt the config and cause other plugins to lose their settings on next load.\n if (needsWrite) {\n try {\n const tmpPath = `${configPath}.tmp.${process.pid}`;\n writeFileSync(tmpPath, JSON.stringify(config, null, 2));\n renameSync(tmpPath, configPath);\n logger.info(\"Smart routing enabled (ckcloud/auto)\");\n } catch (err) {\n logger.info(`Failed to write config: ${err instanceof Error ? err.message : String(err)}`);\n }\n }\n}\n\n\n/**\n * Inject dummy auth profile for ckcloud into agent auth stores.\n * OpenClaw's agent system looks for auth credentials even if provider has auth: [].\n * We inject a placeholder so the lookup succeeds (proxy handles real auth internally).\n */\nfunction injectAuthProfile(logger: { info: (msg: string) => void }): void {\n const agentsDir = join(homedir(), \".openclaw\", \"agents\");\n\n // Create agents directory if it doesn't exist\n if (!existsSync(agentsDir)) {\n try {\n mkdirSync(agentsDir, { recursive: true });\n } catch (err) {\n logger.info(\n `Could not create agents dir: ${err instanceof Error ? err.message : String(err)}`,\n );\n return;\n }\n }\n\n try {\n // Find all agent directories\n let agents = readdirSync(agentsDir, { withFileTypes: true })\n .filter((d) => d.isDirectory())\n .map((d) => d.name);\n\n // Always ensure \"main\" agent has auth (most common agent)\n if (!agents.includes(\"main\")) {\n agents = [\"main\", ...agents];\n }\n\n for (const agentId of agents) {\n const authDir = join(agentsDir, agentId, \"agent\");\n const authPath = join(authDir, \"auth-profiles.json\");\n\n // Create agent dir if needed\n if (!existsSync(authDir)) {\n try {\n mkdirSync(authDir, { recursive: true });\n } catch {\n continue; // Skip if we can't create the dir\n }\n }\n\n // Load or create auth-profiles.json with correct OpenClaw format\n // Format: { version: 1, profiles: { \"provider:profileId\": { type, provider, key } } }\n let store: { version: number; profiles: Record<string, unknown> } = {\n version: 1,\n profiles: {},\n };\n if (existsSync(authPath)) {\n try {\n const existing = JSON.parse(readTextFileSync(authPath));\n // Check if valid OpenClaw format (has version and profiles)\n if (existing.version && existing.profiles) {\n store = existing;\n }\n // Old format without version/profiles is discarded and recreated\n } catch {\n // Invalid JSON, use fresh store\n }\n }\n\n // Check if ckcloud auth already exists (OpenClaw format: profiles[\"provider:profileId\"])\n const profileKey = \"ckcloud:default\";\n if (store.profiles[profileKey]) {\n continue; // Already configured\n }\n\n // Inject placeholder auth for ckcloud (OpenClaw format)\n // The proxy handles real x402 auth internally, this just satisfies OpenClaw's lookup\n store.profiles[profileKey] = {\n type: \"api_key\",\n provider: \"ckcloud\",\n key: \"x402-proxy-handles-auth\",\n };\n\n try {\n writeFileSync(authPath, JSON.stringify(store, null, 2));\n logger.info(`Injected ckcloud auth profile for agent: ${agentId}`);\n } catch (err) {\n logger.info(\n `Could not inject auth for ${agentId}: ${err instanceof Error ? err.message : String(err)}`,\n );\n }\n }\n } catch (err) {\n logger.info(`Auth injection failed: ${err instanceof Error ? err.message : String(err)}`);\n }\n}\n\n/**\n * /stats command handler for ckcloud.\n * Shows usage statistics and cost savings.\n */\nasync function createStatsCommand(): Promise<OpenClawPluginCommandDefinition> {\n return {\n name: \"stats\",\n description: \"Show ckcloud usage statistics and cost savings\",\n acceptsArgs: true,\n requireAuth: false,\n handler: async (ctx: PluginCommandContext) => {\n const arg = ctx.args?.trim().toLowerCase() || \"7\";\n\n if (arg === \"clear\" || arg === \"reset\") {\n try {\n const { deletedFiles } = await clearStats();\n return {\n text: `Stats cleared — ${deletedFiles} log file(s) deleted. Fresh start!`,\n };\n } catch (err) {\n return {\n text: `Failed to clear stats: ${err instanceof Error ? err.message : String(err)}`,\n isError: true,\n };\n }\n }\n\n const days = parseInt(arg, 10) || 7;\n\n try {\n const stats = await getStats(Math.min(days, 30)); // Cap at 30 days\n const ascii = formatStatsAscii(stats);\n\n return {\n text: [\"```\", ascii, \"```\"].join(\"\\n\"),\n };\n } catch (err) {\n return {\n text: `Failed to load stats: ${err instanceof Error ? err.message : String(err)}`,\n isError: true,\n };\n }\n },\n };\n}\n\n/**\n * Start the x402 proxy in the background.\n * Called from register() because OpenClaw's loader only invokes register(),\n * treating activate() as an alias (def.register ?? def.activate).\n */\nasync function startProxyInBackground(api: OpenClawPluginApi): Promise<void> {\n // Resolve wallet key: saved file → env var → auto-generate\n const wallet = await resolveOrGenerateWalletKey();\n\n // Log wallet source\n if (wallet.source === \"generated\") {\n api.logger.warn(`════════════════════════════════════════════════`);\n api.logger.warn(` NEW WALLET GENERATED — BACK UP YOUR KEY NOW!`);\n api.logger.warn(` Address : ${wallet.address}`);\n api.logger.warn(` Run /wallet export to get your private key`);\n api.logger.warn(` Losing this key = losing your USDC funds`);\n api.logger.warn(`════════════════════════════════════════════════`);\n } else if (wallet.source === \"saved\") {\n api.logger.info(`Using saved wallet: ${wallet.address}`);\n } else {\n api.logger.info(`Using wallet from WALLET_KEY: ${wallet.address}`);\n }\n\n // Resolve routing config overrides from plugin config\n const routingConfig = api.pluginConfig?.routing as Partial<RoutingConfig> | undefined;\n\n const proxy = await startProxy({\n wallet,\n routingConfig,\n logger: api.logger,\n onReady: (port) => {\n api.logger.info(`ckcloud x402 proxy listening on port ${port}`);\n },\n onError: (error) => {\n api.logger.error(`ckcloud proxy error: ${error.message}`);\n },\n onRouted: (decision) => {\n const cost = decision.costEstimate.toFixed(4);\n const saved = (decision.savings * 100).toFixed(0);\n api.logger.info(\n `ckcloud onRouted: [${decision.tier}] ${decision.model} $${cost} (saved ${saved}%) | ${decision.reasoning}`,\n );\n },\n onLowBalance: (info) => {\n api.logger.warn(`[!] Low balance: ${info.balanceUSD}. Fund wallet: ${info.walletAddress}`);\n },\n onInsufficientFunds: (info) => {\n api.logger.error(\n `[!] Insufficient funds. Balance: ${info.balanceUSD}, Needed: ${info.requiredUSD}. Fund wallet: ${info.walletAddress}`,\n );\n },\n });\n\n setActiveProxy(proxy);\n activeProxyHandle = proxy;\n\n api.logger.info(`ckcloud ready — smart routing enabled`);\n api.logger.info(`Pricing: Simple ~$0.001 | Code ~$0.01 | Complex ~$0.05 | Free: $0`);\n\n // Non-blocking balance check AFTER proxy is ready (won't hang startup)\n // Uses the proxy's chain-aware balance monitor and matching active-chain address.\n const currentChain = await resolvePaymentChain();\n const displayAddress =\n currentChain === \"solana\" && proxy.solanaAddress ? proxy.solanaAddress : wallet.address;\n proxy.balanceMonitor\n .checkBalance()\n .then((balance) => {\n if (balance.isEmpty) {\n api.logger.info(`Wallet: ${displayAddress} | Balance: $0.00`);\n api.logger.info(`Using FREE model. Fund wallet for premium models.`);\n } else if (balance.isLow) {\n api.logger.info(`Wallet: ${displayAddress} | Balance: ${balance.balanceUSD} (low)`);\n } else {\n api.logger.info(`Wallet: ${displayAddress} | Balance: ${balance.balanceUSD}`);\n }\n })\n .catch(() => {\n // Silently continue - balance will be checked per-request anyway\n api.logger.info(`Wallet: ${displayAddress} | Balance: (checking...)`);\n });\n}\n\n\nexport default plugin;\n\n","import { open } from \"node:fs/promises\";\nimport { openSync, readSync, closeSync, fstatSync } from \"node:fs\";\n\n/** Read file contents as UTF-8 string (async). */\nexport async function readTextFile(filePath: string): Promise<string> {\n const fh = await open(filePath, \"r\");\n try {\n const size = (await fh.stat()).size;\n const buf = Buffer.alloc(size);\n let offset = 0;\n while (offset < size) {\n const { bytesRead } = await fh.read(buf, offset, size - offset, offset);\n if (bytesRead === 0) break;\n offset += bytesRead;\n }\n return buf.subarray(0, offset).toString(\"utf-8\");\n } finally {\n await fh.close();\n }\n}\n\n/** Read file contents as UTF-8 string (sync). */\nexport function readTextFileSync(filePath: string): string {\n const fd = openSync(filePath, \"r\");\n try {\n const size = fstatSync(fd).size;\n const buf = Buffer.alloc(size);\n let offset = 0;\n while (offset < size) {\n const bytesRead = readSync(fd, buf, offset, size - offset, offset);\n if (bytesRead === 0) break;\n offset += bytesRead;\n }\n return buf.subarray(0, offset).toString(\"utf-8\");\n } finally {\n closeSync(fd);\n }\n}","/**\n * Single source of truth for version.\n * Reads from package.json at build time via tsup's define.\n */\nimport { createRequire } from \"node:module\";\nimport { fileURLToPath } from \"node:url\";\nimport { dirname, join } from \"node:path\";\n\n// Read package.json at runtime\nconst __filename = fileURLToPath(import.meta.url);\nconst __dirname = dirname(__filename);\n\n// In dist/, go up one level to find package.json\nconst require = createRequire(import.meta.url);\nconst pkg = require(join(__dirname, \"..\", \"package.json\")) as { version: string };\n\nexport const VERSION = pkg.version;\nexport const USER_AGENT = `ckcloud/${VERSION}`;\n","import type { ModelDefinitionConfig, ModelProviderConfig } from \"./types.js\";\n\n//TODO\nexport const BASE_API_URL = \"https://www.ckcloudai.com/api\"\n\ntype BaseModel = {\n id: string;\n name: string;\n /** Model version (e.g., \"4.6\", \"3.1\", \"5.2\") for tracking updates */\n version?: string;\n inputPrice: number;\n outputPrice: number;\n contextWindow: number;\n maxOutput: number;\n reasoning?: boolean;\n vision?: boolean;\n /** Models optimized for agentic workflows (multi-step autonomous tasks) */\n agentic?: boolean;\n /**\n * Model supports OpenAI-compatible structured function/tool calling.\n * Models without this flag output tool invocations as plain text JSON,\n * which leaks raw {\"command\":\"...\"} into visible chat messages.\n * Default: false (must opt-in to prevent silent regressions on new models).\n */\n toolCalling?: boolean;\n};\n\nexport const BASE_MODELS: BaseModel[] = [\n // Smart routing meta-models — proxy replaces with actual model\n // NOTE: Model IDs are WITHOUT provider prefix (OpenClaw adds \"ckcloud/\" automatically)\n {\n id: \"auto\",\n name: \"Auto (Smart Router - Balanced)\",\n inputPrice: 0,\n outputPrice: 0,\n contextWindow: 1_050_000,\n maxOutput: 128_000,\n }\n]\n\n\n/**\n * Resolve a model alias to its full model ID.\n * Also strips \"ckcloud/\" prefix for direct model paths.\n * Examples:\n * - \"claude\" -> \"anthropic/claude-sonnet-4-6\" (alias)\n * - \"ckcloud/claude\" -> \"anthropic/claude-sonnet-4-6\" (alias with prefix)\n * - \"ckcloud/anthropic/claude-sonnet-4-6\" -> \"anthropic/claude-sonnet-4-6\" (prefix stripped)\n * - \"openai/gpt-4o\" -> \"openai/gpt-4o\" (unchanged)\n */\nexport function resolveModelAlias(model: string): string {\n const normalized = model.trim().toLowerCase();\n const resolved = MODEL_ALIASES[normalized];\n if (resolved) return resolved;\n\n // Check with \"ckcloud/\" prefix stripped\n if (normalized.startsWith(\"ckcloud/\")) {\n const withoutPrefix = normalized.slice(\"ckcloud/\".length);\n const resolvedWithoutPrefix = MODEL_ALIASES[withoutPrefix];\n if (resolvedWithoutPrefix) return resolvedWithoutPrefix;\n\n // Even if not an alias, strip the prefix for direct model paths\n // e.g., \"ckcloud/anthropic/claude-sonnet-4-6\" -> \"anthropic/claude-sonnet-4-6\"\n return withoutPrefix;\n }\n\n // Strip \"openai/\" prefix when it wraps a virtual routing profile or alias.\n // OpenClaw sends virtual models as \"openai/eco\", \"openai/free\", etc. because\n // the provider uses the openai-completions API type.\n if (normalized.startsWith(\"openai/\")) {\n const withoutPrefix = normalized.slice(\"openai/\".length);\n const resolvedWithoutPrefix = MODEL_ALIASES[withoutPrefix];\n if (resolvedWithoutPrefix) return resolvedWithoutPrefix;\n\n // If it's a known virtual profile (eco, free, auto, premium), return bare id\n const isVirtualProfile = BASE_MODELS.some((m) => m.id === withoutPrefix);\n if (isVirtualProfile) return withoutPrefix;\n }\n\n return model;\n}\n\n/**\n * Convert model definitions to OpenClaw ModelDefinitionConfig format.\n */\nfunction toOpenClawModel(m: BaseModel): ModelDefinitionConfig {\n return {\n id: m.id,\n name: m.name,\n api: \"openai-completions\",\n reasoning: m.reasoning ?? false,\n input: m.vision ? [\"text\", \"image\"] : [\"text\"],\n cost: {\n input: m.inputPrice,\n output: m.outputPrice,\n cacheRead: 0,\n cacheWrite: 0,\n },\n contextWindow: m.contextWindow,\n maxTokens: m.maxOutput,\n };\n}\n\n\n/**\n * Model aliases for convenient shorthand access.\n * Users can type `/model claude` instead of `/model ckcloud/anthropic/claude-sonnet-4-6`.\n */\nexport const MODEL_ALIASES: Record<string, string> = {\n // Claude - use newest versions (4.6)\n claude: \"anthropic/claude-sonnet-4.6\",\n sonnet: \"anthropic/claude-sonnet-4.6\",\n \"sonnet-4\": \"anthropic/claude-sonnet-4.6\",\n \"sonnet-4.6\": \"anthropic/claude-sonnet-4.6\",\n \"sonnet-4-6\": \"anthropic/claude-sonnet-4.6\",\n opus: \"anthropic/claude-opus-4.6\",\n \"opus-4\": \"anthropic/claude-opus-4.6\",\n \"opus-4.6\": \"anthropic/claude-opus-4.6\",\n \"opus-4-6\": \"anthropic/claude-opus-4.6\",\n haiku: \"anthropic/claude-haiku-4.5\",\n // Claude - provider/shortname patterns (common in agent frameworks)\n \"anthropic/sonnet\": \"anthropic/claude-sonnet-4.6\",\n \"anthropic/opus\": \"anthropic/claude-opus-4.6\",\n \"anthropic/haiku\": \"anthropic/claude-haiku-4.5\",\n \"anthropic/claude\": \"anthropic/claude-sonnet-4.6\",\n // Backward compatibility - map all variants to 4.6\n \"anthropic/claude-sonnet-4\": \"anthropic/claude-sonnet-4.6\",\n \"anthropic/claude-sonnet-4-6\": \"anthropic/claude-sonnet-4.6\",\n \"anthropic/claude-opus-4\": \"anthropic/claude-opus-4.6\",\n \"anthropic/claude-opus-4-6\": \"anthropic/claude-opus-4.6\",\n \"anthropic/claude-opus-4.5\": \"anthropic/claude-opus-4.6\",\n \"anthropic/claude-haiku-4\": \"anthropic/claude-haiku-4.5\",\n \"anthropic/claude-haiku-4-5\": \"anthropic/claude-haiku-4.5\",\n\n // OpenAI\n gpt: \"openai/gpt-4o\",\n gpt4: \"openai/gpt-4o\",\n gpt5: \"openai/gpt-5.4\",\n \"gpt-5.4\": \"openai/gpt-5.4\",\n \"gpt-5.4-pro\": \"openai/gpt-5.4-pro\",\n codex: \"openai/gpt-5.2-codex\",\n mini: \"openai/gpt-4o-mini\",\n o1: \"openai/o1\",\n o3: \"openai/o3\",\n\n // DeepSeek\n deepseek: \"deepseek/deepseek-chat\",\n reasoner: \"deepseek/deepseek-reasoner\",\n\n // Kimi / Moonshot\n kimi: \"moonshot/kimi-k2.5\",\n moonshot: \"moonshot/kimi-k2.5\",\n \"kimi-k2.5\": \"moonshot/kimi-k2.5\",\n\n // Google\n gemini: \"google/gemini-2.5-pro\",\n flash: \"google/gemini-2.5-flash\",\n \"gemini-3.1-pro-preview\": \"google/gemini-3.1-pro\",\n \"google/gemini-3.1-pro-preview\": \"google/gemini-3.1-pro\",\n\n // xAI\n grok: \"xai/grok-3\",\n \"grok-fast\": \"xai/grok-4-fast-reasoning\",\n \"grok-code\": \"xai/grok-code-fast-1\",\n\n // NVIDIA\n nvidia: \"nvidia/gpt-oss-120b\",\n \"gpt-120b\": \"nvidia/gpt-oss-120b\",\n\n // MiniMax\n minimax: \"minimax/minimax-m2.5\",\n\n // Routing profile aliases (common variations)\n \"auto-router\": \"auto\",\n router: \"auto\",\n\n // Note: auto, free, eco, premium are virtual routing profiles registered in BASE_MODELS\n // They don't need aliases since they're already top-level model IDs\n};\n\n/**\n * Alias models that map to real models.\n * These allow users to use friendly names like \"free\" or \"gpt-120b\".\n */\nconst ALIAS_MODELS: ModelDefinitionConfig[] = Object.entries(MODEL_ALIASES)\n .map(([alias, targetId]) => {\n const target = BASE_MODELS.find((m) => m.id === targetId);\n if (!target) return null;\n return toOpenClawModel({ ...target, id: alias, name: `${alias} → ${target.name}` });\n })\n .filter((m): m is ModelDefinitionConfig => m !== null);\n\nexport const OPENCLAW_MODELS: ModelDefinitionConfig[] = [\n ...BASE_MODELS.map(toOpenClawModel),\n ...ALIAS_MODELS,\n];\n\nexport function buildProviderModels(baseUrl: string): ModelProviderConfig {\n if (!baseUrl){\n baseUrl = BASE_API_URL\n }\n\n return {\n baseUrl: `${baseUrl}/v1`,\n api: \"openai-completions\",\n models: OPENCLAW_MODELS,\n };\n}\n\n/**\n * Get context window size for a model.\n * Returns undefined if model not found.\n */\nexport function getModelContextWindow(modelId: string): number | undefined {\n const normalized = modelId.replace(\"ckcloud/\", \"\");\n const model = BASE_MODELS.find((m) => m.id === normalized);\n return model?.contextWindow;\n}\n\n/**\n * Check if a model has reasoning/thinking capabilities.\n * Reasoning models may require reasoning_content in assistant tool_call messages.\n */\nexport function isReasoningModel(modelId: string): boolean {\n const normalized = modelId.replace(\"ckcloud/\", \"\");\n const model = BASE_MODELS.find((m) => m.id === normalized);\n return model?.reasoning ?? false;\n}\n\n/**\n * Check if a model supports OpenAI-compatible structured tool/function calling.\n * Models without this flag (e.g. grok-code-fast-1) output tool invocations as\n * plain text JSON, which leaks {\"command\":\"...\"} into visible chat messages.\n */\nexport function supportsToolCalling(modelId: string): boolean {\n const normalized = modelId.replace(\"ckcloud/\", \"\");\n const model = BASE_MODELS.find((m) => m.id === normalized);\n return model?.toolCalling ?? false;\n}\n\n/**\n * Check if a model supports vision (image inputs).\n * Models without this flag cannot process image_url content parts.\n */\nexport function supportsVision(modelId: string): boolean {\n const normalized = modelId.replace(\"ckcloud/\", \"\");\n const model = BASE_MODELS.find((m) => m.id === normalized);\n return model?.vision ?? false;\n}","import type { ProviderPlugin } from \"./types\";\nimport { buildProviderModels, BASE_API_URL } from \"./models\";\nimport type { ProxyHandle } from \"./proxy.js\";\n\n/**\n * State for the running proxy (set when the plugin activates).\n */\nlet activeProxy: ProxyHandle | null = null;\n\nexport function setActiveProxy(proxy: ProxyHandle): void {\n activeProxy = proxy;\n}\n\nexport function getActiveProxy(): ProxyHandle | null {\n return activeProxy;\n}\n\n\nexport const ckcloudProvider: ProviderPlugin = {\n id: \"ckcloud\",\n label: \"ckcloud\",\n docsPath: \"\", //TODO\n aliases: [\"ckey\"],\n envVars: [\"CKCLOUD_API_KEY\"],\n\n // Model definitions — dynamically set to proxy URL\n get models() {\n if (!activeProxy) {\n // Fallback: point to ckcloud API directly (won't handle x402, but\n // allows config loading before proxy starts)\n return buildProviderModels(BASE_API_URL);\n }\n return buildProviderModels(activeProxy?.baseUrl);\n },\n\n // No auth required — the x402 proxy handles wallet-based payments internally.\n // The proxy auto-generates a wallet on first run and stores it at\n // ~/.openclaw/ckcloud/wallet.key. Users just fund that wallet with USDC.\n auth: [],\n};\n","import { createServer, type IncomingMessage, type ServerResponse } from \"node:http\";\nimport { finished } from \"node:stream\";\nimport type { AddressInfo } from \"node:net\";\nimport { homedir } from \"node:os\";\nimport { join } from \"node:path\";\nimport { mkdir, writeFile, readFile, stat as fsStat } from \"node:fs/promises\";\nimport { createPublicClient, http } from \"viem\";\nimport { base } from \"viem/chains\";\nimport { toClientEvmSigner } from \"@x402/evm\";\nimport { privateKeyToAccount } from \"viem/accounts\";\nimport { x402Client } from \"@x402/fetch\";\nimport { createPayFetchWithPreAuth } from \"./payment-preauth\";\nimport { registerExactEvmScheme } from \"@x402/evm/exact/client\";\n\nimport { BalanceMonitor } from \"./balance\";\nimport { SolanaBalanceMonitor } from \"./solana-balance\";\nimport { PROXY_PORT } from \"./config.js\";\nimport { getStats, clearStats } from \"./stats.js\";\nimport { logUsage, type UsageEntry } from \"./logger.js\";\nimport type { PluginLogger } from \"./types.js\";\nimport { logger, setPluginLogger } from \"./plugin-logger.js\";\n\nimport {\n SessionStore,\n getSessionId,\n deriveSessionId,\n hashRequestContent,\n type SessionConfig,\n} from \"./session.js\";\n\nimport {\n route,\n getFallbackChain,\n getFallbackChainFiltered,\n filterByToolCalling,\n filterByVision,\n calculateModelCost,\n DEFAULT_ROUTING_CONFIG,\n type RouterOptions,\n type RoutingDecision,\n type RoutingConfig,\n type ModelPricing,\n type Tier,\n} from \"./router/index.js\";\n\nimport { resolvePaymentChain } from \"./auth\"\nimport { RequestDeduplicator } from \"./dedup\";\nimport { ResponseCache, type ResponseCacheConfig } from \"./response-cache\"\nimport { SessionJournal } from \"./journal\"\nimport { USER_AGENT, VERSION } from \"./version\";\nimport { checkForUpdates } from \"./updater\";\nimport { classifyByRules } from \"./router/rules\";\n\nimport {\n BASE_MODELS,\n OPENCLAW_MODELS,\n resolveModelAlias,\n getModelContextWindow,\n isReasoningModel,\n supportsToolCalling,\n supportsVision,\n} from \"./models.js\";\n\ntype AnyBalanceMonitor = BalanceMonitor | SolanaBalanceMonitor;\n\n\nconst CKCLOUD_API = \"https://test.holmesai.ucloud.com.cn:5173/x402\";\nconst CKCLOUD_SOLANA_API = \"https://test.holmesai.ucloud.com.cn:5173/x402\";\nconst IMAGE_DIR = join(homedir(), \".openclaw\", \"ckcloud\", \"images\");\nconst AUTO_MODEL = \"ckcloud/auto\";\n\n// Extra buffer for balance check (on top of estimateAmount's 20% buffer)\n// Total effective buffer: 1.2 * 1.5 = 1.8x (80% safety margin)\n// This prevents x402 payment failures after streaming headers are sent,\n// which would trigger OpenClaw's 5-24 hour billing cooldown.\nconst BALANCE_CHECK_BUFFER = 1.5;\n\nconst ROUTING_PROFILES = new Set([\n \"ckcloud/free\",\n \"free\",\n \"ckcloud/eco\",\n \"eco\",\n \"ckcloud/auto\",\n \"auto\",\n \"ckcloud/premium\",\n \"premium\",\n]);\n\nconst FREE_MODEL = \"kimi-k2\"; // Free model for empty wallet fallback\nconst MAX_MESSAGES = 200; // API limit - truncate older messages if exceeded\nconst CONTEXT_LIMIT_KB = 5120; // Server-side limit: 5MB in KB\nconst HEARTBEAT_INTERVAL_MS = 2_000;\nconst DEFAULT_REQUEST_TIMEOUT_MS = 180_000; // 3 minutes (allows for on-chain tx + LLM response)\nconst MAX_FALLBACK_ATTEMPTS = 5; // Maximum models to try in fallback chain (increased from 3 to ensure cheap models are tried)\nconst HEALTH_CHECK_TIMEOUT_MS = 2_000; // Timeout for checking existing proxy\nconst RATE_LIMIT_COOLDOWN_MS = 60_000; // 60 seconds cooldown for rate-limited models\nconst PORT_RETRY_ATTEMPTS = 5; // Max attempts to bind port (handles TIME_WAIT)\nconst PORT_RETRY_DELAY_MS = 1_000; // Delay between retry attempts\nconst MODEL_BODY_READ_TIMEOUT_MS = 300_000; // 5 minutes for model responses (reasoning models are slow)\nconst ERROR_BODY_READ_TIMEOUT_MS = 30_000; // 30 seconds for error/partner body reads\n\nexport function getProxyPort(): number {\n return PROXY_PORT;\n}\n\nexport type WalletConfig = string | { key: string; solanaPrivateKeyBytes?: Uint8Array };\nexport type PaymentChain = \"base\" | \"solana\";\n\n/** Callback info for low balance warning */\nexport type LowBalanceInfo = {\n balanceUSD: string;\n walletAddress: string;\n};\n\n/** Callback info for insufficient funds error */\nexport type InsufficientFundsInfo = {\n balanceUSD: string;\n requiredUSD: string;\n walletAddress: string;\n};\n\nexport type ProxyOptions = {\n wallet: WalletConfig;\n apiBase?: string;\n /** Payment chain: \"base\" (default) or \"solana\". Can also be set via CLAWROUTER_PAYMENT_CHAIN env var. */\n paymentChain?: PaymentChain;\n /** Port to listen on (default: 8402) */\n port?: number;\n routingConfig?: Partial<RoutingConfig>;\n /** Request timeout in ms (default: 180000 = 3 minutes). Covers on-chain tx + LLM response. */\n requestTimeoutMs?: number;\n /** Skip balance checks (for testing only). Default: false */\n skipBalanceCheck?: boolean;\n /**\n * Session persistence config. When enabled, maintains model selection\n * across requests within a session to prevent mid-task model switching.\n */\n sessionConfig?: Partial<SessionConfig>;\n /**\n * Auto-compress large requests to reduce network usage.\n * When enabled, requests are automatically compressed using\n * LLM-safe context compression (15-40% reduction).\n * Default: true\n */\n autoCompressRequests?: boolean;\n /**\n * Threshold in KB to trigger auto-compression (default: 180).\n * Requests larger than this are compressed before sending.\n * Set to 0 to compress all requests.\n */\n compressionThresholdKB?: number;\n /**\n * Response caching config. When enabled, identical requests return\n * cached responses instead of making new API calls.\n * Default: enabled with 10 minute TTL, 200 max entries.\n */\n cacheConfig?: ResponseCacheConfig;\n onReady?: (port: number) => void;\n onError?: (error: Error) => void;\n onPayment?: (info: { model: string; amount: string; network: string }) => void;\n onRouted?: (decision: RoutingDecision) => void;\n /** Called when balance drops below $1.00 (warning, request still proceeds) */\n onLowBalance?: (info: LowBalanceInfo) => void;\n /** Called when balance is insufficient for a request (request fails) */\n onInsufficientFunds?: (info: InsufficientFundsInfo) => void;\n /** Logger for plugin output (defaults to console if not provided) */\n logger?: PluginLogger;\n};\n\nexport type ProxyHandle = {\n port: number;\n baseUrl: string;\n walletAddress: string;\n solanaAddress?: string;\n balanceMonitor: AnyBalanceMonitor;\n close: () => Promise<void>;\n};\n\nasync function readBodyWithTimeout(\n body: ReadableStream<Uint8Array> | null,\n timeoutMs: number = MODEL_BODY_READ_TIMEOUT_MS,\n): Promise<Uint8Array[]> {\n if (!body) return [];\n\n const reader = body.getReader();\n const chunks: Uint8Array[] = [];\n\n let timer: ReturnType<typeof setTimeout> | undefined;\n try {\n while (true) {\n const result = await Promise.race([\n reader.read(),\n new Promise<never>((_, reject) => {\n timer = setTimeout(() => reject(new Error(\"Body read timeout\")), timeoutMs);\n }),\n ]);\n clearTimeout(timer);\n if (result.done) break;\n chunks.push(result.value);\n }\n } finally {\n clearTimeout(timer);\n reader.releaseLock();\n }\n\n return chunks;\n}\n\n/**\n * Check if response socket is writable (prevents write-after-close errors).\n * Returns true only if all conditions are safe for writing.\n */\nfunction canWrite(res: ServerResponse): boolean {\n return (\n !res.writableEnded &&\n !res.destroyed &&\n res.socket !== null &&\n !res.socket.destroyed &&\n res.socket.writable\n );\n}\n\n/**\n * Safe write with backpressure handling.\n * Returns true if write succeeded, false if socket is closed or write failed.\n */\nfunction safeWrite(res: ServerResponse, data: string | Buffer): boolean {\n if (!canWrite(res)) {\n const bytes = typeof data === \"string\" ? Buffer.byteLength(data) : data.length;\n logger.warn(`[ckcloud] safeWrite: socket not writable, dropping ${bytes} bytes`);\n return false;\n }\n return res.write(data);\n}\n\n\nconst rateLimitedModels = new Map<string, number>();\n\n/**\n * Check if a model is currently rate-limited (in cooldown period).\n */\nfunction isRateLimited(modelId: string): boolean {\n const hitTime = rateLimitedModels.get(modelId);\n if (!hitTime) return false;\n\n const elapsed = Date.now() - hitTime;\n if (elapsed >= RATE_LIMIT_COOLDOWN_MS) {\n rateLimitedModels.delete(modelId);\n return false;\n }\n return true;\n}\n\nfunction markRateLimited(modelId: string): void {\n rateLimitedModels.set(modelId, Date.now());\n logger.info(`[ckcloud] Model ${modelId} rate-limited, will deprioritize for 60s`);\n}\n\n\n/** Result of attempting a model request */\ntype ModelRequestResult = {\n success: boolean;\n response?: Response;\n errorBody?: string;\n errorStatus?: number;\n isProviderError?: boolean;\n};\n\nconst VALID_ROLES = new Set([\"system\", \"user\", \"assistant\", \"tool\", \"function\"]);\ntype ChatMessage = { role: string; content: string | unknown };\nconst ROLE_MAPPINGS: Record<string, string> = {\n developer: \"system\", // OpenAI's newer API uses \"developer\" for system messages\n model: \"assistant\", // Some APIs use \"model\" instead of \"assistant\"\n};\n\n/**\n * Normalize message roles to standard OpenAI format.\n * Converts non-standard roles (e.g., \"developer\") to valid ones.\n */\nfunction normalizeMessageRoles(messages: ChatMessage[]): ChatMessage[] {\n if (!messages || messages.length === 0) return messages;\n\n let hasChanges = false;\n const normalized = messages.map((msg) => {\n if (VALID_ROLES.has(msg.role)) return msg;\n\n const mappedRole = ROLE_MAPPINGS[msg.role];\n if (mappedRole) {\n hasChanges = true;\n return { ...msg, role: mappedRole };\n }\n\n // Unknown role - default to \"user\" to avoid API errors\n hasChanges = true;\n return { ...msg, role: \"user\" };\n });\n\n return hasChanges ? normalized : messages;\n}\n\n\ntype TruncationResult<T> = {\n messages: T[];\n wasTruncated: boolean;\n originalCount: number;\n truncatedCount: number;\n};\n/**\n * Truncate messages to stay under MAX_MESSAGES limit.\n * Keeps all system messages and the most recent conversation history.\n * Returns the messages and whether truncation occurred.\n */\nfunction truncateMessages<T extends { role: string }>(messages: T[]): TruncationResult<T> {\n if (!messages || messages.length <= MAX_MESSAGES) {\n return {\n messages,\n wasTruncated: false,\n originalCount: messages?.length ?? 0,\n truncatedCount: messages?.length ?? 0,\n };\n }\n\n // Separate system messages from conversation\n const systemMsgs = messages.filter((m) => m.role === \"system\");\n const conversationMsgs = messages.filter((m) => m.role !== \"system\");\n\n // Keep all system messages + most recent conversation messages\n const maxConversation = MAX_MESSAGES - systemMsgs.length;\n const truncatedConversation = conversationMsgs.slice(-maxConversation);\n\n const result = [...systemMsgs, ...truncatedConversation];\n\n logger.info(\n `[ckcloud] Truncated messages: ${messages.length} → ${result.length} (kept ${systemMsgs.length} system + ${truncatedConversation.length} recent)`,\n );\n\n return {\n messages: result,\n wasTruncated: true,\n originalCount: messages.length,\n truncatedCount: result.length,\n };\n}\n\ntype MessageWithTools = ChatMessage & {\n tool_calls?: Array<{ id?: string; type?: string; function?: unknown }>;\n tool_call_id?: string;\n};\n\ntype ContentBlock = {\n type?: string;\n id?: string;\n tool_use_id?: string;\n [key: string]: unknown;\n};\n\n\nconst VALID_TOOL_ID_PATTERN = /^[a-zA-Z0-9_-]+$/;\n\nfunction sanitizeToolId(id: string | undefined): string | undefined {\n if (!id || typeof id !== \"string\") return id;\n if (VALID_TOOL_ID_PATTERN.test(id)) return id;\n\n // Replace invalid characters with underscores\n return id.replace(/[^a-zA-Z0-9_-]/g, \"_\");\n}\n\nfunction sanitizeToolIds(messages: ChatMessage[]): ChatMessage[] {\n if (!messages || messages.length === 0) return messages;\n\n let hasChanges = false;\n const sanitized = messages.map((msg) => {\n const typedMsg = msg as MessageWithTools;\n let msgChanged = false;\n let newMsg = { ...msg } as MessageWithTools;\n\n // Sanitize tool_calls[].id in assistant messages\n if (typedMsg.tool_calls && Array.isArray(typedMsg.tool_calls)) {\n const newToolCalls = typedMsg.tool_calls.map((tc) => {\n if (tc.id && typeof tc.id === \"string\") {\n const sanitized = sanitizeToolId(tc.id);\n if (sanitized !== tc.id) {\n msgChanged = true;\n return { ...tc, id: sanitized };\n }\n }\n return tc;\n });\n if (msgChanged) {\n newMsg = { ...newMsg, tool_calls: newToolCalls };\n }\n }\n\n // Sanitize tool_call_id in tool messages\n if (typedMsg.tool_call_id && typeof typedMsg.tool_call_id === \"string\") {\n const sanitized = sanitizeToolId(typedMsg.tool_call_id);\n if (sanitized !== typedMsg.tool_call_id) {\n msgChanged = true;\n newMsg = { ...newMsg, tool_call_id: sanitized };\n }\n }\n\n // Sanitize content blocks if content is an array (Anthropic-style content)\n if (Array.isArray(typedMsg.content)) {\n const newContent = (typedMsg.content as ContentBlock[]).map((block) => {\n if (!block || typeof block !== \"object\") return block;\n\n let blockChanged = false;\n let newBlock = { ...block };\n\n // tool_use blocks have \"id\"\n if (block.type === \"tool_use\" && block.id && typeof block.id === \"string\") {\n const sanitized = sanitizeToolId(block.id);\n if (sanitized !== block.id) {\n blockChanged = true;\n newBlock = { ...newBlock, id: sanitized };\n }\n }\n\n // tool_result blocks have \"tool_use_id\"\n if (\n block.type === \"tool_result\" &&\n block.tool_use_id &&\n typeof block.tool_use_id === \"string\"\n ) {\n const sanitized = sanitizeToolId(block.tool_use_id);\n if (sanitized !== block.tool_use_id) {\n blockChanged = true;\n newBlock = { ...newBlock, tool_use_id: sanitized };\n }\n }\n\n if (blockChanged) {\n msgChanged = true;\n return newBlock;\n }\n return block;\n });\n\n if (msgChanged) {\n newMsg = { ...newMsg, content: newContent };\n }\n }\n\n if (msgChanged) {\n hasChanges = true;\n return newMsg;\n }\n return msg;\n });\n\n return hasChanges ? sanitized : messages;\n}\n\nfunction isGoogleModel(modelId: string): boolean {\n return modelId.startsWith(\"google/\") || modelId.startsWith(\"gemini\");\n}\n\nfunction normalizeMessagesForGoogle(messages: ChatMessage[]): ChatMessage[] {\n if (!messages || messages.length === 0) return messages;\n\n // Find first non-system message\n let firstNonSystemIdx = -1;\n for (let i = 0; i < messages.length; i++) {\n if (messages[i].role !== \"system\") {\n firstNonSystemIdx = i;\n break;\n }\n }\n\n // If no non-system messages, return as-is\n if (firstNonSystemIdx === -1) return messages;\n\n const firstRole = messages[firstNonSystemIdx].role;\n\n // If first non-system message is already \"user\", no change needed\n if (firstRole === \"user\") return messages;\n\n // If first non-system message is \"assistant\" or \"model\", prepend a user message\n if (firstRole === \"assistant\" || firstRole === \"model\") {\n const normalized = [...messages];\n normalized.splice(firstNonSystemIdx, 0, {\n role: \"user\",\n content: \"(continuing conversation)\",\n });\n return normalized;\n }\n\n return messages;\n}\n\ntype ExtendedChatMessage = ChatMessage & {\n tool_calls?: unknown[];\n reasoning_content?: unknown;\n};\n\n\n/**\n * Normalize messages for thinking-enabled requests.\n * When thinking/extended_thinking is enabled, assistant messages with tool_calls\n * must have reasoning_content (can be empty string if not present).\n * Error: \"400 thinking is enabled but reasoning_content is missing in assistant tool call message\"\n */\nfunction normalizeMessagesForThinking(messages: ExtendedChatMessage[]): ExtendedChatMessage[] {\n if (!messages || messages.length === 0) return messages;\n\n let hasChanges = false;\n const normalized = messages.map((msg) => {\n // Skip if not assistant or already has reasoning_content\n if (msg.role !== \"assistant\" || msg.reasoning_content !== undefined) {\n return msg;\n }\n\n // Check for OpenAI format: tool_calls array\n const hasOpenAIToolCalls =\n msg.tool_calls && Array.isArray(msg.tool_calls) && msg.tool_calls.length > 0;\n\n // Check for Anthropic format: content array with tool_use blocks\n const hasAnthropicToolUse =\n Array.isArray(msg.content) &&\n (msg.content as Array<{ type?: string }>).some((block) => block?.type === \"tool_use\");\n\n if (hasOpenAIToolCalls || hasAnthropicToolUse) {\n hasChanges = true;\n return { ...msg, reasoning_content: \"\" };\n }\n return msg;\n });\n\n return hasChanges ? normalized : messages;\n}\n\nconst PROVIDER_ERROR_PATTERNS = [\n /billing/i,\n /insufficient.*balance/i,\n /credits/i,\n /quota.*exceeded/i,\n /rate.*limit/i,\n /model.*unavailable/i,\n /model.*not.*available/i,\n /service.*unavailable/i,\n /capacity/i,\n /overloaded/i,\n /temporarily.*unavailable/i,\n /api.*key.*invalid/i,\n /authentication.*failed/i,\n /request too large/i,\n /request.*size.*exceeds/i,\n /payload too large/i,\n /payment.*verification.*failed/i,\n /model.*not.*allowed/i,\n /unknown.*model/i,\n];\n\nconst FALLBACK_STATUS_CODES = [\n 400, // Bad request - sometimes used for billing errors\n 401, // Unauthorized - provider API key issues\n 402, // Payment required - but from upstream, not x402\n 403, // Forbidden - provider restrictions\n 413, // Payload too large - request exceeds model's context limit\n 429, // Rate limited\n 500, // Internal server error\n 502, // Bad gateway\n 503, // Service unavailable\n 504, // Gateway timeout\n];\nfunction isProviderError(status: number, body: string): boolean {\n // Check status code first\n if (!FALLBACK_STATUS_CODES.includes(status)) {\n return false;\n }\n\n // For 5xx errors, always fallback\n if (status >= 500) {\n return true;\n }\n\n // For 4xx errors, check the body for known provider error patterns\n return PROVIDER_ERROR_PATTERNS.some((pattern) => pattern.test(body));\n}\n\nconst DEGRADED_RESPONSE_PATTERNS = [\n /the ai service is temporarily overloaded/i,\n /service is temporarily overloaded/i,\n /please try again in a moment/i,\n];\nconst DEGRADED_LOOP_PATTERNS = [\n /the boxed is the response\\./i,\n /the response is the text\\./i,\n /the final answer is the boxed\\./i,\n];\nfunction hasKnownLoopSignature(text: string): boolean {\n const matchCount = DEGRADED_LOOP_PATTERNS.reduce(\n (count, pattern) => (pattern.test(text) ? count + 1 : count),\n 0,\n );\n if (matchCount >= 2) return true;\n\n // Generic repetitive loop fallback for short repeated lines.\n const lines = text\n .split(/\\r?\\n/)\n .map((line) => line.trim())\n .filter(Boolean);\n if (lines.length < 8) return false;\n\n const counts = new Map<string, number>();\n for (const line of lines) {\n counts.set(line, (counts.get(line) ?? 0) + 1);\n }\n\n const maxRepeat = Math.max(...counts.values());\n const uniqueRatio = counts.size / lines.length;\n return maxRepeat >= 3 && uniqueRatio <= 0.45;\n}\nfunction extractAssistantContent(payload: unknown): string | undefined {\n if (!payload || typeof payload !== \"object\") return undefined;\n const record = payload as Record<string, unknown>;\n const choices = record.choices;\n if (!Array.isArray(choices) || choices.length === 0) return undefined;\n\n const firstChoice = choices[0];\n if (!firstChoice || typeof firstChoice !== \"object\") return undefined;\n const choice = firstChoice as Record<string, unknown>;\n const message = choice.message;\n if (!message || typeof message !== \"object\") return undefined;\n const content = (message as Record<string, unknown>).content;\n return typeof content === \"string\" ? content : undefined;\n}\n\n/**\n * Detect degraded 200-response payloads that should trigger model fallback.\n * Returns a short reason when fallback should happen, otherwise undefined.\n */\nexport function detectDegradedSuccessResponse(body: string): string | undefined {\n const trimmed = body.trim();\n if (!trimmed) return undefined;\n\n // Plain-text placeholder response.\n if (DEGRADED_RESPONSE_PATTERNS.some((pattern) => pattern.test(trimmed))) {\n return \"degraded response: overloaded placeholder\";\n }\n\n // Plain-text looping garbage response.\n if (hasKnownLoopSignature(trimmed)) {\n return \"degraded response: repetitive loop output\";\n }\n\n try {\n const parsed = JSON.parse(trimmed) as Record<string, unknown>;\n\n // Some providers return JSON error payloads with HTTP 200.\n const errorField = parsed.error;\n let errorText = \"\";\n if (typeof errorField === \"string\") {\n errorText = errorField;\n } else if (errorField && typeof errorField === \"object\") {\n const errObj = errorField as Record<string, unknown>;\n errorText = [\n typeof errObj.message === \"string\" ? errObj.message : \"\",\n typeof errObj.type === \"string\" ? errObj.type : \"\",\n typeof errObj.code === \"string\" ? errObj.code : \"\",\n ]\n .filter(Boolean)\n .join(\" \");\n }\n if (errorText && PROVIDER_ERROR_PATTERNS.some((pattern) => pattern.test(errorText))) {\n return `degraded response: ${errorText.slice(0, 120)}`;\n }\n\n // Successful wrapper with bad assistant content.\n const assistantContent = extractAssistantContent(parsed);\n if (!assistantContent) return undefined;\n if (DEGRADED_RESPONSE_PATTERNS.some((pattern) => pattern.test(assistantContent))) {\n return \"degraded response: overloaded assistant content\";\n }\n if (hasKnownLoopSignature(assistantContent)) {\n return \"degraded response: repetitive assistant loop\";\n }\n } catch {\n // Not JSON - handled by plaintext checks above.\n }\n\n return undefined;\n}\n\n\n/**\n * Attempt a request with a specific model.\n * Returns the response or error details for fallback decision.\n */\nasync function tryModelRequest(\n upstreamUrl: string,\n method: string,\n headers: Record<string, string>,\n body: Buffer,\n modelId: string,\n maxTokens: number,\n payFetch: (input: RequestInfo | URL, init?: RequestInit) => Promise<Response>,\n balanceMonitor: AnyBalanceMonitor,\n signal: AbortSignal,\n): Promise<ModelRequestResult> {\n const bodyPreviewMax = 512;\n const bodyPreviewLength = Math.min(body.length, bodyPreviewMax);\n const bodyPreview = bodyPreviewLength\n ? body.toString(\"utf8\", 0, bodyPreviewLength)\n : undefined;\n\n logger.info(\n `[ckcloud] tryModelRequest: model=${modelId}, method=${method}, upstream=${upstreamUrl}, maxTokens=${maxTokens} ${JSON.stringify({\n headers,\n bodyBytes: body.length,\n bodyPreview,\n })}`,\n );\n // Update model in body and normalize messages\n let requestBody = body;\n try {\n const parsed = JSON.parse(body.toString()) as Record<string, unknown>;\n parsed.model = modelId;\n\n // Normalize message roles (e.g., \"developer\" -> \"system\")\n if (Array.isArray(parsed.messages)) {\n parsed.messages = normalizeMessageRoles(parsed.messages as ChatMessage[]);\n }\n\n // Truncate messages to stay under ckcloud's limit (200 messages)\n if (Array.isArray(parsed.messages)) {\n const truncationResult = truncateMessages(parsed.messages as ChatMessage[]);\n parsed.messages = truncationResult.messages;\n }\n\n // Sanitize tool IDs to match Anthropic's pattern (alphanumeric, underscore, hyphen only)\n if (Array.isArray(parsed.messages)) {\n parsed.messages = sanitizeToolIds(parsed.messages as ChatMessage[]);\n }\n\n // Normalize messages for Google models (first non-system message must be \"user\")\n if (isGoogleModel(modelId) && Array.isArray(parsed.messages)) {\n parsed.messages = normalizeMessagesForGoogle(parsed.messages as ChatMessage[]);\n }\n\n // Normalize messages for thinking-enabled requests (add reasoning_content to tool calls)\n // Check request flags AND target model - reasoning models have thinking enabled server-side\n const hasThinkingEnabled = !!(\n parsed.thinking ||\n parsed.extended_thinking ||\n isReasoningModel(modelId)\n );\n if (hasThinkingEnabled && Array.isArray(parsed.messages)) {\n parsed.messages = normalizeMessagesForThinking(parsed.messages as ExtendedChatMessage[]);\n }\n\n requestBody = Buffer.from(JSON.stringify(parsed));\n } catch {\n // If body isn't valid JSON, use as-is\n }\n\n try {\n logger.info(`payFetch: url:${upstreamUrl}, header:${headers}, body:${requestBody}`)\n\n const response = await payFetch(upstreamUrl, {\n method,\n headers,\n body: requestBody.length > 0 ? new Uint8Array(requestBody) : undefined,\n signal,\n });\n\n // Check for provider errors\n if (response.status !== 200) {\n // Clone response to read body without consuming it\n const errorBodyChunks = await readBodyWithTimeout(response.body, ERROR_BODY_READ_TIMEOUT_MS);\n const errorBody = Buffer.concat(errorBodyChunks).toString();\n const isProviderErr = isProviderError(response.status, errorBody);\n\n logger.warn(`payFetch err, url:${upstreamUrl}, header:${headers}, body:${requestBody}, response:${JSON.stringify(response)}`)\n\n return {\n success: false,\n errorBody,\n errorStatus: response.status,\n isProviderError: isProviderErr,\n };\n }\n\n // Detect provider degradation hidden inside HTTP 200 responses.\n const contentType = response.headers.get(\"content-type\") || \"\";\n if (contentType.includes(\"json\") || contentType.includes(\"text\")) {\n try {\n const clonedChunks = await readBodyWithTimeout(\n response.clone().body,\n ERROR_BODY_READ_TIMEOUT_MS,\n );\n const responseBody = Buffer.concat(clonedChunks).toString();\n const degradedReason = detectDegradedSuccessResponse(responseBody);\n if (degradedReason) {\n return {\n success: false,\n errorBody: degradedReason,\n errorStatus: 503,\n isProviderError: true,\n };\n }\n } catch {\n // Ignore body inspection failures and pass through response.\n }\n }\n\n return { success: true, response };\n } catch (err) {\n const errorMsg = err instanceof Error ? err.message : String(err);\n logger.warn(`payFetch catch err, url:${upstreamUrl}, header:${headers}, body:${requestBody}, err:${errorMsg}`)\n return {\n success: false,\n errorBody: errorMsg,\n errorStatus: 500,\n isProviderError: true, // Network errors are retryable\n };\n }\n}\n\n/**\n * Reorder models to put rate-limited ones at the end.\n */\nfunction prioritizeNonRateLimited(models: string[]): string[] {\n const available: string[] = [];\n const rateLimited: string[] = [];\n\n for (const model of models) {\n if (isRateLimited(model)) {\n rateLimited.push(model);\n } else {\n available.push(model);\n }\n }\n\n return [...available, ...rateLimited];\n}\n\n\nasync function checkExistingProxy(\n port: number,\n): Promise<{ wallet: string; paymentChain?: string } | undefined> {\n const controller = new AbortController();\n const timeoutId = setTimeout(() => controller.abort(), HEALTH_CHECK_TIMEOUT_MS);\n\n try {\n const response = await fetch(`http://127.0.0.1:${port}/health`, {\n signal: controller.signal,\n });\n clearTimeout(timeoutId);\n\n if (response.ok) {\n const data = (await response.json()) as {\n status?: string;\n wallet?: string;\n paymentChain?: string;\n };\n if (data.status === \"ok\" && data.wallet) {\n return { wallet: data.wallet, paymentChain: data.paymentChain };\n }\n }\n return undefined;\n } catch {\n clearTimeout(timeoutId);\n return undefined;\n }\n}\n\nfunction buildModelPricing(): Map<string, ModelPricing> {\n const map = new Map<string, ModelPricing>();\n for (const m of BASE_MODELS) {\n if (m.id === AUTO_MODEL) continue; // skip meta-model\n map.set(m.id, { inputPrice: m.inputPrice, outputPrice: m.outputPrice });\n }\n return map;\n}\n\n\ntype ModelListEntry = {\n id: string;\n object: \"model\";\n created: number;\n owned_by: string;\n};\n\n\n/**\n * Build `/v1/models` response entries from the full OpenClaw model registry.\n * This includes alias IDs (e.g., `flash`, `kimi`) so `/model <alias>` works reliably.\n */\nexport function buildProxyModelList(\n createdAt: number = Math.floor(Date.now() / 1000),\n): ModelListEntry[] {\n const seen = new Set<string>();\n return OPENCLAW_MODELS.filter((model) => {\n if (seen.has(model.id)) return false;\n seen.add(model.id);\n return true;\n }).map((model) => ({\n id: model.id,\n object: \"model\",\n created: createdAt,\n owned_by: model.id.includes(\"/\") ? (model.id.split(\"/\")[0] ?? \"ckcloud\") : \"ckcloud\",\n }));\n}\n\n/**\n * Merge partial routing config overrides with defaults.\n */\nfunction mergeRoutingConfig(overrides?: Partial<RoutingConfig>): RoutingConfig {\n if (!overrides) return DEFAULT_ROUTING_CONFIG;\n return {\n ...DEFAULT_ROUTING_CONFIG,\n ...overrides,\n classifier: { ...DEFAULT_ROUTING_CONFIG.classifier, ...overrides.classifier },\n scoring: { ...DEFAULT_ROUTING_CONFIG.scoring, ...overrides.scoring },\n tiers: { ...DEFAULT_ROUTING_CONFIG.tiers, ...overrides.tiers },\n overrides: { ...DEFAULT_ROUTING_CONFIG.overrides, ...overrides.overrides },\n };\n}\n\n\n\n/**\n * Upload a base64 data URI to catbox.moe and return a public URL.\n * Google image models (nano-banana) return data URIs instead of hosted URLs,\n * which breaks Telegram and other clients that can't render raw base64.\n */\nasync function uploadDataUriToHost(dataUri: string): Promise<string> {\n const match = dataUri.match(/^data:(image\\/\\w+);base64,(.+)$/);\n if (!match) throw new Error(\"Invalid data URI format\");\n const [, mimeType, b64Data] = match;\n const ext = mimeType === \"image/jpeg\" ? \"jpg\" : (mimeType.split(\"/\")[1] ?? \"png\");\n\n const buffer = Buffer.from(b64Data, \"base64\");\n const blob = new Blob([buffer], { type: mimeType });\n\n const form = new FormData();\n form.append(\"reqtype\", \"fileupload\");\n form.append(\"fileToUpload\", blob, `image.${ext}`);\n\n const uploadController = new AbortController();\n const uploadTimeout = setTimeout(() => uploadController.abort(), 30_000);\n try {\n const resp = await fetch(\"https://catbox.moe/user/api.php\", {\n method: \"POST\",\n body: form,\n signal: uploadController.signal,\n });\n\n if (!resp.ok) throw new Error(`catbox.moe upload failed: HTTP ${resp.status}`);\n const result = await resp.text();\n if (result.startsWith(\"https://\")) {\n return result.trim();\n }\n throw new Error(`catbox.moe upload failed: ${result}`);\n } finally {\n clearTimeout(uploadTimeout);\n }\n}\n\n/**\n * Estimate USDC cost for a request based on model pricing.\n * Returns amount string in USDC smallest unit (6 decimals) or undefined if unknown.\n */\nfunction estimateAmount(\n modelId: string,\n bodyLength: number,\n maxTokens: number,\n): string | undefined {\n const model = BASE_MODELS.find((m) => m.id === modelId);\n if (!model) return undefined;\n\n // Rough estimate: ~4 chars per token for input\n const estimatedInputTokens = Math.ceil(bodyLength / 4);\n const estimatedOutputTokens = maxTokens || model.maxOutput || 4096;\n\n const costUsd =\n (estimatedInputTokens / 1_000_000) * model.inputPrice +\n (estimatedOutputTokens / 1_000_000) * model.outputPrice;\n\n // Convert to USDC 6-decimal integer, add 20% buffer for estimation error\n // Minimum 1000 ($0.001) to match CDP Facilitator's enforced minimum payment\n const amountMicros = Math.max(1000, Math.ceil(costUsd * 1.2 * 1_000_000));\n return amountMicros.toString();\n}\n\n\nfunction transformPaymentError(errorBody: string): string {\n try {\n // Try to parse the error JSON\n const parsed = JSON.parse(errorBody) as {\n error?: string;\n details?: string;\n };\n\n // Check if this is a payment verification error\n if (parsed.error === \"Payment verification failed\" && parsed.details) {\n // Extract the nested JSON from details\n // Format: \"Verification failed: {json}\\n\"\n const match = parsed.details.match(/Verification failed:\\s*(\\{.*\\})/s);\n if (match) {\n const innerJson = JSON.parse(match[1]) as {\n invalidMessage?: string;\n invalidReason?: string;\n payer?: string;\n };\n\n if (innerJson.invalidReason === \"insufficient_funds\" && innerJson.invalidMessage) {\n // Parse \"insufficient balance: 251 < 11463\"\n const balanceMatch = innerJson.invalidMessage.match(\n /insufficient balance:\\s*(\\d+)\\s*<\\s*(\\d+)/i,\n );\n if (balanceMatch) {\n const currentMicros = parseInt(balanceMatch[1], 10);\n const requiredMicros = parseInt(balanceMatch[2], 10);\n const currentUSD = (currentMicros / 1_000_000).toFixed(6);\n const requiredUSD = (requiredMicros / 1_000_000).toFixed(6);\n const wallet = innerJson.payer || \"unknown\";\n const shortWallet =\n wallet.length > 12 ? `${wallet.slice(0, 6)}...${wallet.slice(-4)}` : wallet;\n\n return JSON.stringify({\n error: {\n message: `Insufficient USDC balance. Current: $${currentUSD}, Required: ~$${requiredUSD}`,\n type: \"insufficient_funds\",\n wallet: wallet,\n current_balance_usd: currentUSD,\n required_usd: requiredUSD,\n help: `Fund wallet ${shortWallet} with USDC on Base, or use free model: /model free`,\n },\n });\n }\n }\n\n // Handle invalid_payload errors (signature issues, malformed payment)\n if (innerJson.invalidReason === \"invalid_payload\") {\n return JSON.stringify({\n error: {\n message: \"Payment signature invalid. This may be a temporary issue.\",\n type: \"invalid_payload\",\n help: \"Try again. If this persists, reinstall\",\n },\n });\n }\n\n // Handle transaction simulation failures (Solana on-chain validation)\n if (innerJson.invalidReason === \"transaction_simulation_failed\") {\n console.error(\n `[ClawRouter] Solana transaction simulation failed: ${innerJson.invalidMessage || \"unknown\"}`,\n );\n return JSON.stringify({\n error: {\n message: \"Solana payment simulation failed. Retrying with a different model.\",\n type: \"transaction_simulation_failed\",\n help: \"This is usually temporary. If it persists, check your Solana USDC balance or try: /model free\",\n },\n });\n }\n }\n }\n\n // Handle settlement failures (gas estimation, on-chain errors)\n if (\n parsed.error === \"Settlement failed\" ||\n parsed.error === \"Payment settlement failed\" ||\n parsed.details?.includes(\"Settlement failed\") ||\n parsed.details?.includes(\"transaction_simulation_failed\")\n ) {\n const details = parsed.details || \"\";\n const gasError = details.includes(\"unable to estimate gas\");\n\n return JSON.stringify({\n error: {\n message: gasError\n ? \"Payment failed: network congestion or gas issue. Try again.\"\n : \"Payment settlement failed. Try again in a moment.\",\n type: \"settlement_failed\",\n help: \"This is usually temporary. If it persists, try: /model free\",\n },\n });\n }\n } catch {\n // If parsing fails, return original\n }\n return errorBody;\n}\n\n\n/**\n * Start the local x402 proxy server.\n *\n * If a proxy is already running on the target port, reuses it instead of failing.\n * Port can be configured via CKCLOUD_PROXY_PORT environment variable.\n *\n * Returns a handle with the assigned port, base URL, and a close function.\n */\nexport async function startProxy(options: ProxyOptions): Promise<ProxyHandle> {\n const walletKey = typeof options.wallet === \"string\" ? options.wallet : options.wallet.key;\n const solanaPrivateKeyBytes = typeof options.wallet === \"string\" ? undefined : options.wallet.solanaPrivateKeyBytes;\n setPluginLogger(options.logger ?? console);\n\n const paymentChain = options.paymentChain ?? (await resolvePaymentChain());\n\n const apiBase = options.apiBase ?? (paymentChain === \"solana\" && solanaPrivateKeyBytes ? CKCLOUD_SOLANA_API : CKCLOUD_API);\n if (paymentChain === \"solana\" && !solanaPrivateKeyBytes) {\n logger.warn(`[ckcloud] ⚠ Payment chain is Solana but no mnemonic found — falling back to Base (EVM).`);\n logger.warn(`[ckcloud] To fix: run \"npx @ckcloudai.com/clawrouter wallet recover\" if your mnemonic exists.`);\n logger.warn(`[ckcloud] or run \"npx @ckcloudai.com/clawrouter chain base\" to switch to EVM.`);\n } else if (paymentChain === \"solana\") {\n logger.info(`[ckcloud] Payment chain: Solana (${CKCLOUD_SOLANA_API})`);\n }\n\n const listenPort = options.port ?? getProxyPort();\n const existingProxy = await checkExistingProxy(listenPort);\n\n if (existingProxy) {\n // Proxy already running — reuse it instead of failing with EADDRINUSE\n const account = privateKeyToAccount(walletKey as `0x${string}`);\n const baseUrl = `http://127.0.0.1:${listenPort}`;\n\n // Verify the existing proxy is using the same wallet (or warn if different)\n if (existingProxy.wallet !== account.address) {\n logger.warn(\n `[ckcloud] Existing proxy on port ${listenPort} uses wallet ${existingProxy.wallet}, but current config uses ${account.address}. Reusing existing proxy.`,\n );\n }\n\n // Verify the existing proxy is using the same payment chain\n if (existingProxy.paymentChain) {\n if (existingProxy.paymentChain !== paymentChain) {\n throw new Error(\n `Existing proxy on port ${listenPort} is using ${existingProxy.paymentChain} but ${paymentChain} was requested. ` +\n `Stop the existing proxy first or use a different port.`,\n );\n }\n } else if (paymentChain !== \"base\") {\n // Old proxy doesn't report chain — assume Base. Reject if Solana was requested.\n logger.warn(\n `[ckcloud] Existing proxy on port ${listenPort} does not report paymentChain (pre-v0.11 instance). Assuming Base.`,\n );\n throw new Error(\n `Existing proxy on port ${listenPort} is a pre-v0.11 instance (assumed Base) but ${paymentChain} was requested. ` +\n `Stop the existing proxy first or use a different port.`,\n );\n }\n\n // Derive Solana address if keys are available (for wallet status display)\n let reuseSolanaAddress: string | undefined;\n if (solanaPrivateKeyBytes) {\n const { createKeyPairSignerFromPrivateKeyBytes } = await import(\"@solana/kit\");\n const solanaSigner = await createKeyPairSignerFromPrivateKeyBytes(solanaPrivateKeyBytes);\n reuseSolanaAddress = solanaSigner.address;\n }\n\n // Use chain-appropriate balance monitor\n const balanceMonitor: AnyBalanceMonitor = paymentChain === \"solana\" && reuseSolanaAddress\n ? new SolanaBalanceMonitor(reuseSolanaAddress)\n : new BalanceMonitor(account.address);\n\n options.onReady?.(listenPort);\n\n return {\n port: listenPort,\n baseUrl,\n walletAddress: existingProxy.wallet,\n solanaAddress: reuseSolanaAddress,\n balanceMonitor,\n close: async () => {\n // No-op: we didn't start this proxy, so we shouldn't close it\n },\n };\n }\n\n //no existingProxy\n\n // Create x402 payment client with EVM scheme (always available)\n const account = privateKeyToAccount(walletKey as `0x${string}`);\n const evmPublicClient = createPublicClient({ chain: base, transport: http() });\n const evmSigner = toClientEvmSigner(account, evmPublicClient);\n const x402 = new x402Client();\n registerExactEvmScheme(x402, { signer: evmSigner });\n\n // Register Solana scheme if key is available\n // Uses registerExactSvmScheme helper which registers:\n // - solana:* wildcard (catches any CAIP-2 Solana network)\n // - V1 compat names: \"solana\", \"solana-devnet\", \"solana-testnet\"\n let solanaAddress: string | undefined;\n if (solanaPrivateKeyBytes) {\n const { registerExactSvmScheme } = await import(\"@x402/svm/exact/client\");\n const { createKeyPairSignerFromPrivateKeyBytes } = await import(\"@solana/kit\");\n const solanaSigner = await createKeyPairSignerFromPrivateKeyBytes(solanaPrivateKeyBytes);\n solanaAddress = solanaSigner.address;\n registerExactSvmScheme(x402, { signer: solanaSigner });\n logger.info(`[ckcloud] Solana x402 scheme registered: ${solanaAddress}`);\n }\n\n // Log which chain is used for each payment\n x402.onAfterPaymentCreation(async (context) => {\n const network = context.selectedRequirements.network;\n const chain = network.startsWith(\"eip155\")\n ? \"Base (EVM)\"\n : network.startsWith(\"solana\")\n ? \"Solana\"\n : network;\n logger.info(`[ckcloud] Payment signed on ${chain} (${network})`);\n });\n\n const payFetch = createPayFetchWithPreAuth(fetch, x402, undefined, {\n skipPreAuth: paymentChain === \"solana\",\n });\n\n // Create balance monitor for pre-request checks (chain-appropriate)\n const balanceMonitor: AnyBalanceMonitor =\n paymentChain === \"solana\" && solanaAddress\n ? new SolanaBalanceMonitor(solanaAddress)\n : new BalanceMonitor(account.address);\n\n // Build router options (100% local — no external API calls for routing)\n const routingConfig = mergeRoutingConfig(options.routingConfig);\n const modelPricing = buildModelPricing();\n const routerOpts: RouterOptions = {\n config: routingConfig,\n modelPricing,\n };\n\n // Request deduplicator (shared across all requests)\n const deduplicator = new RequestDeduplicator();\n\n // Response cache for identical requests (longer TTL than dedup)\n const responseCache = new ResponseCache(options.cacheConfig);\n\n // Session store for model persistence (prevents mid-task model switching)\n const sessionStore = new SessionStore(options.sessionConfig);\n\n // Session journal for memory (enables agents to recall earlier work)\n const sessionJournal = new SessionJournal();\n\n // Track active connections for graceful cleanup\n const connections = new Set<import(\"net\").Socket>();\n\n const server = createServer(async (req: IncomingMessage, res: ServerResponse) => {\n // Add stream error handlers to prevent server crashes\n req.on(\"error\", (err) => {\n logger.error(`[ckcloud] Request stream error: ${err.message}`);\n // Don't throw - just log and let request handler deal with it\n });\n\n res.on(\"error\", (err) => {\n logger.error(`[ckcloud] Response stream error: ${err.message}`);\n // Don't try to write to failed socket - just log\n });\n\n // Finished wrapper for guaranteed cleanup on response completion/error\n finished(res, (err) => {\n if (err && err.code !== \"ERR_STREAM_DESTROYED\") {\n logger.error(`[ckcloud] Response finished with error: ${err.message}`);\n }\n // Note: heartbeatInterval cleanup happens in res.on(\"close\") handler\n // Note: completed and dedup cleanup happens in the res.on(\"close\") handler below\n });\n\n // Request finished wrapper for complete stream lifecycle tracking\n finished(req, (err) => {\n if (err && err.code !== \"ERR_STREAM_DESTROYED\") {\n logger.error(`[ckcloud] Request finished with error: ${err.message}`);\n }\n });\n\n // Health check with optional balance info\n if (req.url === \"/health\" || req.url?.startsWith(\"/health?\")) {\n const url = new URL(req.url, \"http://localhost\");\n const full = url.searchParams.get(\"full\") === \"true\";\n\n const response: Record<string, unknown> = {\n status: \"ok\",\n wallet: account.address,\n paymentChain,\n };\n if (solanaAddress) {\n response.solana = solanaAddress;\n }\n\n if (full) {\n try {\n const balanceInfo = await balanceMonitor.checkBalance();\n response.balance = balanceInfo.balanceUSD;\n response.isLow = balanceInfo.isLow;\n response.isEmpty = balanceInfo.isEmpty;\n } catch {\n response.balanceError = \"Could not fetch balance\";\n }\n }\n\n res.writeHead(200, { \"Content-Type\": \"application/json\" });\n res.end(JSON.stringify(response));\n return;\n }\n\n // Cache stats endpoint\n if (req.url === \"/cache\" || req.url?.startsWith(\"/cache?\")) {\n const stats = responseCache.getStats();\n res.writeHead(200, {\n \"Content-Type\": \"application/json\",\n \"Cache-Control\": \"no-cache\",\n });\n res.end(JSON.stringify(stats, null, 2));\n return;\n }\n\n // Stats clear endpoint - delete all log files\n if (req.url === \"/stats\" && req.method === \"DELETE\") {\n try {\n const result = await clearStats();\n res.writeHead(200, { \"Content-Type\": \"application/json\" });\n res.end(JSON.stringify({ cleared: true, deletedFiles: result.deletedFiles }));\n } catch (err) {\n res.writeHead(500, { \"Content-Type\": \"application/json\" });\n res.end(\n JSON.stringify({\n error: `Failed to clear stats: ${err instanceof Error ? err.message : String(err)}`,\n }),\n );\n }\n return;\n }\n\n // Stats API endpoint - returns JSON for programmatic access\n if (req.url === \"/stats\" || req.url?.startsWith(\"/stats?\")) {\n try {\n const url = new URL(req.url, \"http://localhost\");\n const days = parseInt(url.searchParams.get(\"days\") || \"7\", 10);\n const stats = await getStats(Math.min(days, 30));\n\n res.writeHead(200, {\n \"Content-Type\": \"application/json\",\n \"Cache-Control\": \"no-cache\",\n });\n res.end(JSON.stringify(stats, null, 2));\n } catch (err) {\n res.writeHead(500, { \"Content-Type\": \"application/json\" });\n res.end(\n JSON.stringify({\n error: `Failed to get stats: ${err instanceof Error ? err.message : String(err)}`,\n }),\n );\n }\n return;\n }\n\n // --- Handle /v1/models locally (no upstream call needed) ---\n if (req.url === \"/v1/models\" && req.method === \"GET\") {\n const models = buildProxyModelList();\n res.writeHead(200, { \"Content-Type\": \"application/json\" });\n res.end(JSON.stringify({ object: \"list\", data: models }));\n return;\n }\n\n // --- Serve locally cached images (~/.openclaw/ckcloud/images/) ---\n if (req.url?.startsWith(\"/images/\") && req.method === \"GET\") {\n const filename = req.url.slice(\"/images/\".length).split(\"?\")[0]!.replace(/[^a-zA-Z0-9._-]/g, \"\");\n if (!filename) {\n res.writeHead(400);\n res.end(\"Bad request\");\n return;\n }\n const filePath = join(IMAGE_DIR, filename);\n try {\n const s = await fsStat(filePath);\n if (!s.isFile()) throw new Error(\"not a file\");\n const ext = filename.split(\".\").pop()?.toLowerCase() ?? \"png\";\n const mime: Record<string, string> = { png: \"image/png\", jpg: \"image/jpeg\", jpeg: \"image/jpeg\", webp: \"image/webp\", gif: \"image/gif\" };\n const data = await readFile(filePath);\n res.writeHead(200, { \"Content-Type\": mime[ext] ?? \"application/octet-stream\", \"Content-Length\": data.length });\n res.end(data);\n } catch {\n res.writeHead(404, { \"Content-Type\": \"application/json\" });\n res.end(JSON.stringify({ error: \"Image not found\" }));\n }\n return;\n }\n\n // --- Handle /v1/images/generations: proxy with x402 payment + save data URIs locally ---\n if (req.url === \"/v1/images/generations\" && req.method === \"POST\") {\n const chunks: Buffer[] = [];\n for await (const chunk of req) {\n chunks.push(Buffer.isBuffer(chunk) ? chunk : Buffer.from(chunk));\n }\n const reqBody = Buffer.concat(chunks);\n try {\n const upstream = await payFetch(`${apiBase}/v1/images/generations`, {\n method: \"POST\",\n headers: { \"content-type\": \"application/json\", \"user-agent\": USER_AGENT },\n body: reqBody,\n });\n const text = await upstream.text();\n if (!upstream.ok) {\n res.writeHead(upstream.status, { \"Content-Type\": \"application/json\" });\n res.end(text);\n return;\n }\n let result: { created?: number; data?: Array<{ url?: string; revised_prompt?: string }> };\n try { result = JSON.parse(text); } catch {\n res.writeHead(200, { \"Content-Type\": \"application/json\" });\n res.end(text);\n return;\n }\n // Save any data URIs to ~/.openclaw/ckcloud/images/ and replace with localhost URLs\n if (result.data?.length) {\n await mkdir(IMAGE_DIR, { recursive: true });\n const port = (server.address() as AddressInfo | null)?.port ?? 8402;\n for (const img of result.data) {\n const m = img.url?.match(/^data:(image\\/\\w+);base64,(.+)$/);\n if (m) {\n const [, mimeType, b64] = m;\n const ext = mimeType === \"image/jpeg\" ? \"jpg\" : (mimeType!.split(\"/\")[1] ?? \"png\");\n const filename = `${Date.now()}-${Math.random().toString(36).slice(2, 10)}.${ext}`;\n await writeFile(join(IMAGE_DIR, filename), Buffer.from(b64!, \"base64\"));\n img.url = `http://localhost:${port}/images/${filename}`;\n logger.info(`[ckcloud] Image saved → ${img.url}`);\n }\n }\n }\n res.writeHead(200, { \"Content-Type\": \"application/json\" });\n res.end(JSON.stringify(result));\n } catch (err) {\n const msg = err instanceof Error ? err.message : String(err);\n logger.error(`[ckcloud] Image generation error: ${msg}`);\n if (!res.headersSent) {\n res.writeHead(502, { \"Content-Type\": \"application/json\" });\n res.end(JSON.stringify({ error: \"Image generation failed\", details: msg }));\n }\n }\n return;\n }\n\n // Only proxy paths starting with /v1\n if (!req.url?.startsWith(\"/v1\")) {\n res.writeHead(404, { \"Content-Type\": \"application/json\" });\n res.end(JSON.stringify({ error: \"Not found\" }));\n return;\n }\n\n try {\n await proxyRequest(\n req,\n res,\n apiBase,\n payFetch,\n options,\n routerOpts,\n deduplicator,\n balanceMonitor,\n sessionStore,\n responseCache,\n sessionJournal,\n );\n } catch (err) {\n const error = err instanceof Error ? err : new Error(String(err));\n options.onError?.(error);\n\n if (!res.headersSent) {\n res.writeHead(502, { \"Content-Type\": \"application/json\" });\n res.end(\n JSON.stringify({\n error: { message: `Proxy error: ${error.message}`, type: \"proxy_error\" },\n }),\n );\n } else if (!res.writableEnded) {\n // Headers already sent (streaming) — send error as SSE event\n res.write(\n `data: ${JSON.stringify({ error: { message: error.message, type: \"proxy_error\" } })}\\n\\n`,\n );\n res.write(\"data: [DONE]\\n\\n\");\n res.end();\n }\n }\n });\n\n // Listen on configured port with retry logic for TIME_WAIT handling\n // When gateway restarts quickly, the port may still be in TIME_WAIT state.\n // We retry with delay instead of incorrectly assuming a proxy is running.\n const tryListen = (attempt: number): Promise<void> => {\n return new Promise<void>((resolveAttempt, rejectAttempt) => {\n const onError = async (err: NodeJS.ErrnoException) => {\n server.removeListener(\"error\", onError);\n\n if (err.code === \"EADDRINUSE\") {\n // Port is in use - check if a proxy is actually running\n const existingProxy2 = await checkExistingProxy(listenPort);\n if (existingProxy2) {\n // Proxy is actually running - this is fine, reuse it\n logger.info(`[ckcloud] Existing proxy detected on port ${listenPort}, reusing`);\n rejectAttempt({\n code: \"REUSE_EXISTING\",\n wallet: existingProxy2.wallet,\n existingChain: existingProxy2.paymentChain,\n });\n return;\n }\n\n // Port is in TIME_WAIT (no proxy responding) - retry after delay\n if (attempt < PORT_RETRY_ATTEMPTS) {\n logger.info(\n `[ckcloud] Port ${listenPort} in TIME_WAIT, retrying in ${PORT_RETRY_DELAY_MS}ms (attempt ${attempt}/${PORT_RETRY_ATTEMPTS})`,\n );\n rejectAttempt({ code: \"RETRY\", attempt });\n return;\n }\n\n // Max retries exceeded\n logger.error(\n `[ckcloud] Port ${listenPort} still in use after ${PORT_RETRY_ATTEMPTS} attempts`,\n );\n rejectAttempt(err);\n return;\n }\n\n rejectAttempt(err);\n };\n\n server.once(\"error\", onError);\n server.listen(listenPort, \"127.0.0.1\", () => {\n server.removeListener(\"error\", onError);\n resolveAttempt();\n });\n });\n };\n\n // Retry loop for port binding\n let lastError: Error | undefined;\n for (let attempt = 1; attempt <= PORT_RETRY_ATTEMPTS; attempt++) {\n try {\n await tryListen(attempt);\n break; // Success\n } catch (err: unknown) {\n const error = err as {\n code?: string;\n wallet?: string;\n existingChain?: string;\n attempt?: number;\n };\n\n if (error.code === \"REUSE_EXISTING\" && error.wallet) {\n // Validate payment chain matches (same check as pre-listen reuse path)\n if (error.existingChain && error.existingChain !== paymentChain) {\n throw new Error(\n `Existing proxy on port ${listenPort} is using ${error.existingChain} but ${paymentChain} was requested. ` +\n `Stop the existing proxy first or use a different port.`,\n { cause: err },\n );\n }\n\n // Proxy is running, reuse it\n const baseUrl = `http://127.0.0.1:${listenPort}`;\n options.onReady?.(listenPort);\n return {\n port: listenPort,\n baseUrl,\n walletAddress: error.wallet,\n balanceMonitor,\n close: async () => {\n // No-op: we didn't start this proxy, so we shouldn't close it\n },\n };\n }\n\n if (error.code === \"RETRY\") {\n // Wait before retry\n await new Promise((r) => setTimeout(r, PORT_RETRY_DELAY_MS));\n continue;\n }\n\n // Other error - throw\n lastError = err as Error;\n break;\n }\n }\n\n if (lastError) {\n throw lastError;\n }\n\n // Server is now listening - set up remaining handlers\n const addr = server.address() as AddressInfo;\n const port = addr.port;\n const baseUrl = `http://127.0.0.1:${port}`;\n\n options.onReady?.(port);\n\n // Check for updates (non-blocking)\n // TODO checkForUpdates();\n\n // Add runtime error handler AFTER successful listen\n // This handles errors that occur during server operation (not just startup)\n server.on(\"error\", (err) => {\n logger.error(`[ckcloud] Server runtime error: ${err.message}`);\n options.onError?.(err);\n // Don't crash - log and continue\n });\n\n // Handle client connection errors (bad requests, socket errors)\n server.on(\"clientError\", (err, socket) => {\n logger.error(`[ckcloud] Client error: ${err.message}`);\n // Send 400 Bad Request if socket is still writable\n if (socket.writable && !socket.destroyed) {\n socket.end(\"HTTP/1.1 400 Bad Request\\r\\n\\r\\n\");\n }\n });\n\n // Track connections for graceful cleanup\n server.on(\"connection\", (socket) => {\n connections.add(socket);\n\n // Set 5-minute timeout for streaming requests\n socket.setTimeout(300_000);\n\n socket.on(\"timeout\", () => {\n logger.error(`[ckcloud] Socket timeout, destroying connection`);\n socket.destroy();\n });\n\n socket.on(\"end\", () => {\n // Half-closed by client (FIN received)\n });\n\n socket.on(\"error\", (err) => {\n logger.error(`[ckcloud] Socket error: ${err.message}`);\n });\n\n socket.on(\"close\", () => {\n connections.delete(socket);\n });\n });\n\n return {\n port,\n baseUrl,\n walletAddress: account.address,\n solanaAddress,\n balanceMonitor,\n close: () =>\n new Promise<void>((res, rej) => {\n const timeout = setTimeout(() => {\n rej(new Error(\"[ckcloud] Close timeout after 4s\"));\n }, 4000);\n\n sessionStore.close();\n // Destroy all active connections before closing server\n for (const socket of connections) {\n socket.destroy();\n }\n connections.clear();\n server.close((err) => {\n clearTimeout(timeout);\n if (err) {\n rej(err);\n } else {\n res();\n }\n });\n }),\n };\n}\n\nconst KIMI_BLOCK_RE = /<[||][^<>]*begin[^<>]*[||]>[\\s\\S]*?<[||][^<>]*end[^<>]*[||]>/gi;\n\n// Match standalone Kimi tokens like <|end▁of▁thinking|>\nconst KIMI_TOKEN_RE = /<[||][^<>]*[||]>/g;\n\n// Standard thinking tags that may leak through from various models\nconst THINKING_TAG_RE = /<\\s*\\/?\\s*(?:think(?:ing)?|thought|antthinking)\\b[^>]*>/gi;\n\n// Full thinking blocks: <think>content</think>\nconst THINKING_BLOCK_RE =\n /<\\s*(?:think(?:ing)?|thought|antthinking)\\b[^>]*>[\\s\\S]*?<\\s*\\/\\s*(?:think(?:ing)?|thought|antthinking)\\s*>/gi;\n\n\nfunction stripThinkingTokens(content: string): string {\n if (!content) return content;\n // Strip full Kimi thinking blocks first (begin...end with content)\n let cleaned = content.replace(KIMI_BLOCK_RE, \"\");\n // Strip remaining standalone Kimi tokens\n cleaned = cleaned.replace(KIMI_TOKEN_RE, \"\");\n // Strip full thinking blocks (<think>...</think>)\n cleaned = cleaned.replace(THINKING_BLOCK_RE, \"\");\n // Strip remaining standalone thinking tags\n cleaned = cleaned.replace(THINKING_TAG_RE, \"\");\n return cleaned;\n}\n\n/**\n * Proxy a single request through x402 payment flow to ckcloud API.\n *\n * Optimizations applied in order:\n * 1. Dedup check — if same request body seen within 30s, replay cached response\n * 2. Streaming heartbeat — for stream:true, send 200 + heartbeats immediately\n * 3. Smart routing — when model is \"ckcloud/auto\", pick cheapest capable model\n * 4. Fallback chain — on provider errors, try next model in tier's fallback list\n */\nasync function proxyRequest(\n req: IncomingMessage,\n res: ServerResponse,\n apiBase: string,\n payFetch: (input: RequestInfo | URL, init?: RequestInit) => Promise<Response>,\n options: ProxyOptions,\n routerOpts: RouterOptions,\n deduplicator: RequestDeduplicator,\n balanceMonitor: AnyBalanceMonitor,\n sessionStore: SessionStore,\n responseCache: ResponseCache,\n sessionJournal: SessionJournal,\n): Promise<void> {\n const startTime = Date.now();\n\n // Build upstream URL: /v1/chat/completions \n const upstreamUrl = `${apiBase}${req.url}`;\n logger.info(`[ckcloud] proxyRequest : ${upstreamUrl}`);\n\n // Collect request body\n const bodyChunks: Buffer[] = [];\n for await (const chunk of req) {\n bodyChunks.push(Buffer.isBuffer(chunk) ? chunk : Buffer.from(chunk));\n }\n let body = Buffer.concat(bodyChunks);\n\n // Track original context size for response headers\n const originalContextSizeKB = Math.ceil(body.length / 1024);\n\n // Routing debug info is on by default; disable with x-ckcloud-debug: false\n const debugMode = req.headers[\"x-ckcloud-debug\"] !== \"false\";\n\n // --- Smart routing ---\n let routingDecision: RoutingDecision | undefined;\n let hasTools = false; // true when request includes a tools schema\n let hasVision = false; // true when request includes image_url content parts\n let isStreaming = false;\n let modelId = \"\";\n let maxTokens = 4096;\n let routingProfile: \"free\" | \"eco\" | \"auto\" | \"premium\" | null = null;\n let accumulatedContent = \"\"; // For session journal event extraction\n let responseInputTokens: number | undefined;\n const isChatCompletion = req.url?.includes(\"/chat/completions\");\n\n logger.info(`[ckcloud] req url : ${req.url}, body: ${body}`);\n\n // Extract session ID early for journal operations (header-only at this point)\n const sessionId = getSessionId(req.headers as Record<string, string | string[] | undefined>);\n // Full session ID (header + content-derived) — populated once messages are parsed\n let effectiveSessionId: string | undefined = sessionId;\n\n if (isChatCompletion && body.length > 0) {\n try {\n const parsed = JSON.parse(body.toString()) as Record<string, unknown>;\n isStreaming = parsed.stream === true;\n modelId = (parsed.model as string) || \"\";\n maxTokens = (parsed.max_tokens as number) || 4096;\n let bodyModified = false;\n\n // Extract last user message content (used by session journal + /debug command)\n const parsedMessages = Array.isArray(parsed.messages)\n ? (parsed.messages as Array<{ role: string; content: unknown }>)\n : [];\n const lastUserMsg = [...parsedMessages].reverse().find((m) => m.role === \"user\");\n const rawLastContent = lastUserMsg?.content;\n const lastContent =\n typeof rawLastContent === \"string\"\n ? rawLastContent\n : Array.isArray(rawLastContent)\n ? (rawLastContent as Array<{ type: string; text?: string }>)\n .filter((b) => b.type === \"text\")\n .map((b) => b.text ?? \"\")\n .join(\" \")\n : \"\";\n\n // --- Session Journal: Inject context if needed ---\n // Check if the last user message asks about past work\n if (sessionId && parsedMessages.length > 0) {\n const messages = parsedMessages;\n\n if (sessionJournal.needsContext(lastContent)) {\n const journalText = sessionJournal.format(sessionId);\n if (journalText) {\n // Find system message and prepend journal, or add a new system message\n const sysIdx = messages.findIndex((m) => m.role === \"system\");\n if (sysIdx >= 0 && typeof messages[sysIdx].content === \"string\") {\n messages[sysIdx] = {\n ...messages[sysIdx],\n content: journalText + \"\\n\\n\" + messages[sysIdx].content,\n };\n } else {\n messages.unshift({ role: \"system\", content: journalText });\n }\n parsed.messages = messages;\n bodyModified = true;\n logger.info(\n `[ckcloud] Injected session journal (${journalText.length} chars) for session ${sessionId.slice(0, 8)}...`,\n );\n }\n }\n }\n\n // --- /debug command: return routing diagnostics without calling upstream ---\n if (lastContent.startsWith(\"/debug\")) {\n const debugPrompt = lastContent.slice(\"/debug\".length).trim() || \"hello\";\n const messages = parsed.messages as Array<{ role: string; content: unknown }>;\n const systemMsg = messages?.find((m) => m.role === \"system\");\n const systemPrompt = typeof systemMsg?.content === \"string\" ? systemMsg.content : undefined;\n const fullText = `${systemPrompt ?? \"\"} ${debugPrompt}`;\n const estimatedTokens = Math.ceil(fullText.length / 4);\n\n // Determine routing profile\n const normalizedModel =\n typeof parsed.model === \"string\" ? parsed.model.trim().toLowerCase() : \"\";\n const profileName = normalizedModel.replace(\"ckcloud/\", \"\");\n const debugProfile = (\n [\"free\", \"eco\", \"auto\", \"premium\"].includes(profileName) ? profileName : \"auto\"\n ) as \"free\" | \"eco\" | \"auto\" | \"premium\";\n\n // Run scoring\n const scoring = classifyByRules(\n debugPrompt,\n systemPrompt,\n estimatedTokens,\n DEFAULT_ROUTING_CONFIG.scoring,\n );\n\n // Run full routing decision\n const debugRouting = route(debugPrompt, systemPrompt, maxTokens, {\n ...routerOpts,\n routingProfile: debugProfile,\n });\n\n // Format dimension scores\n const dimLines = (scoring.dimensions ?? [])\n .map((d) => {\n const nameStr = (d.name + \":\").padEnd(24);\n const scoreStr = d.score.toFixed(2).padStart(6);\n const sigStr = d.signal ? ` [${d.signal}]` : \"\";\n return ` ${nameStr}${scoreStr}${sigStr}`;\n })\n .join(\"\\n\");\n\n // Session info\n const sess = sessionId ? sessionStore.getSession(sessionId) : undefined;\n const sessLine = sess\n ? `Session: ${sessionId!.slice(0, 8)}... → pinned: ${sess.model} (${sess.requestCount} requests)`\n : sessionId\n ? `Session: ${sessionId.slice(0, 8)}... → no pinned model`\n : \"Session: none\";\n\n const { simpleMedium, mediumComplex, complexReasoning } =\n DEFAULT_ROUTING_CONFIG.scoring.tierBoundaries;\n\n const debugText = [\n \"ckcloud Debug\",\n \"\",\n `Profile: ${debugProfile} | Tier: ${debugRouting.tier} | Model: ${debugRouting.model}`,\n `Confidence: ${debugRouting.confidence.toFixed(2)} | Cost: $${debugRouting.costEstimate.toFixed(4)} | Savings: ${(debugRouting.savings * 100).toFixed(0)}%`,\n `Reasoning: ${debugRouting.reasoning}`,\n \"\",\n `Scoring (weighted: ${scoring.score.toFixed(3)})`,\n dimLines,\n \"\",\n `Tier Boundaries: SIMPLE <${simpleMedium.toFixed(2)} | MEDIUM <${mediumComplex.toFixed(2)} | COMPLEX <${complexReasoning.toFixed(2)} | REASONING >=${complexReasoning.toFixed(2)}`,\n \"\",\n sessLine,\n ].join(\"\\n\");\n\n // Build synthetic OpenAI chat completion response\n const completionId = `chatcmpl-debug-${Date.now()}`;\n const timestamp = Math.floor(Date.now() / 1000);\n const syntheticResponse = {\n id: completionId,\n object: \"chat.completion\",\n created: timestamp,\n model: \"ckcloud/debug\",\n choices: [\n {\n index: 0,\n message: { role: \"assistant\", content: debugText },\n finish_reason: \"stop\",\n },\n ],\n usage: { prompt_tokens: 0, completion_tokens: 0, total_tokens: 0 },\n };\n\n if (isStreaming) {\n // SSE streaming response\n res.writeHead(200, {\n \"Content-Type\": \"text/event-stream\",\n \"Cache-Control\": \"no-cache\",\n Connection: \"keep-alive\",\n });\n const sseChunk = {\n id: completionId,\n object: \"chat.completion.chunk\",\n created: timestamp,\n model: \"ckcloud/debug\",\n choices: [\n {\n index: 0,\n delta: { role: \"assistant\", content: debugText },\n finish_reason: null,\n },\n ],\n };\n const sseDone = {\n id: completionId,\n object: \"chat.completion.chunk\",\n created: timestamp,\n model: \"ckcloud/debug\",\n choices: [{ index: 0, delta: {}, finish_reason: \"stop\" }],\n };\n res.write(`data: ${JSON.stringify(sseChunk)}\\n\\n`);\n res.write(`data: ${JSON.stringify(sseDone)}\\n\\n`);\n res.write(\"data: [DONE]\\n\\n\");\n res.end();\n } else {\n res.writeHead(200, { \"Content-Type\": \"application/json\" });\n res.end(JSON.stringify(syntheticResponse));\n }\n logger.info(`[ckcloud] /debug command → ${debugRouting.tier} | ${debugRouting.model}`);\n return;\n }\n\n // --- /imagegen command: generate an image via ckcloud image API ---\n if (lastContent.startsWith(\"/imagegen\")) {\n const imageArgs = lastContent.slice(\"/imagegen\".length).trim();\n\n // Parse optional flags: /imagegen --model dall-e-3 --size 1792x1024 a cute cat\n let imageModel = \"google/nano-banana\";\n let imageSize = \"1024x1024\";\n let imagePrompt = imageArgs;\n\n // Extract --model flag\n const modelMatch = imageArgs.match(/--model\\s+(\\S+)/);\n if (modelMatch) {\n const raw = modelMatch[1];\n // Resolve shorthand aliases\n const IMAGE_MODEL_ALIASES: Record<string, string> = {\n \"dall-e-3\": \"openai/dall-e-3\",\n dalle3: \"openai/dall-e-3\",\n dalle: \"openai/dall-e-3\",\n \"gpt-image\": \"openai/gpt-image-1\",\n \"gpt-image-1\": \"openai/gpt-image-1\",\n flux: \"black-forest/flux-1.1-pro\",\n \"flux-pro\": \"black-forest/flux-1.1-pro\",\n banana: \"google/nano-banana\",\n \"nano-banana\": \"google/nano-banana\",\n \"banana-pro\": \"google/nano-banana-pro\",\n \"nano-banana-pro\": \"google/nano-banana-pro\",\n };\n imageModel = IMAGE_MODEL_ALIASES[raw] ?? raw;\n imagePrompt = imagePrompt.replace(/--model\\s+\\S+/, \"\").trim();\n }\n\n // Extract --size flag\n const sizeMatch = imageArgs.match(/--size\\s+(\\d+x\\d+)/);\n if (sizeMatch) {\n imageSize = sizeMatch[1];\n imagePrompt = imagePrompt.replace(/--size\\s+\\d+x\\d+/, \"\").trim();\n }\n\n if (!imagePrompt) {\n const errorText = [\n \"Usage: /imagegen <prompt>\",\n \"\",\n \"Options:\",\n \" --model <model> Model to use (default: nano-banana)\",\n \" --size <WxH> Image size (default: 1024x1024)\",\n \"\",\n \"Models:\",\n \" nano-banana Google Gemini Flash — $0.05/image\",\n \" banana-pro Google Gemini Pro — $0.10/image (up to 4K)\",\n \" dall-e-3 OpenAI DALL-E 3 — $0.04/image\",\n \" gpt-image OpenAI GPT Image 1 — $0.02/image\",\n \" flux Black Forest Flux 1.1 Pro — $0.04/image\",\n \"\",\n \"Examples:\",\n \" /imagegen a cat wearing sunglasses\",\n \" /imagegen --model dall-e-3 a futuristic city at sunset\",\n \" /imagegen --model banana-pro --size 2048x2048 mountain landscape\",\n ].join(\"\\n\");\n\n const completionId = `chatcmpl-image-${Date.now()}`;\n const timestamp = Math.floor(Date.now() / 1000);\n if (isStreaming) {\n res.writeHead(200, {\n \"Content-Type\": \"text/event-stream\",\n \"Cache-Control\": \"no-cache\",\n Connection: \"keep-alive\",\n });\n res.write(\n `data: ${JSON.stringify({ id: completionId, object: \"chat.completion.chunk\", created: timestamp, model: \"ckcloud/image\", choices: [{ index: 0, delta: { role: \"assistant\", content: errorText }, finish_reason: null }] })}\\n\\n`,\n );\n res.write(\n `data: ${JSON.stringify({ id: completionId, object: \"chat.completion.chunk\", created: timestamp, model: \"ckcloud/image\", choices: [{ index: 0, delta: {}, finish_reason: \"stop\" }] })}\\n\\n`,\n );\n res.write(\"data: [DONE]\\n\\n\");\n res.end();\n } else {\n res.writeHead(200, { \"Content-Type\": \"application/json\" });\n res.end(\n JSON.stringify({\n id: completionId,\n object: \"chat.completion\",\n created: timestamp,\n model: \"ckcloud/image\",\n choices: [\n {\n index: 0,\n message: { role: \"assistant\", content: errorText },\n finish_reason: \"stop\",\n },\n ],\n usage: { prompt_tokens: 0, completion_tokens: 0, total_tokens: 0 },\n }),\n );\n }\n logger.info(`[ckcloud] /imagegen command → showing usage help`);\n return;\n }\n\n // Call upstream image generation API\n logger.info(\n `[ckcloud] /imagegen command → ${imageModel} (${imageSize}): ${imagePrompt.slice(0, 80)}...`,\n );\n try {\n const imageUpstreamUrl = `${apiBase}/v1/images/generations`;\n const imageBody = JSON.stringify({\n model: imageModel,\n prompt: imagePrompt,\n size: imageSize,\n n: 1,\n });\n const imageResponse = await payFetch(imageUpstreamUrl, {\n method: \"POST\",\n headers: { \"content-type\": \"application/json\", \"user-agent\": USER_AGENT },\n body: imageBody,\n });\n\n const imageResult = (await imageResponse.json()) as {\n created?: number;\n data?: Array<{ url?: string; revised_prompt?: string }>;\n error?: string | { message?: string };\n };\n\n let responseText: string;\n if (!imageResponse.ok || imageResult.error) {\n const errMsg =\n typeof imageResult.error === \"string\"\n ? imageResult.error\n : ((imageResult.error as { message?: string })?.message ??\n `HTTP ${imageResponse.status}`);\n responseText = `Image generation failed: ${errMsg}`;\n logger.info(`[ckcloud] /imagegen error: ${errMsg}`);\n } else {\n const images = imageResult.data ?? [];\n if (images.length === 0) {\n responseText = \"Image generation returned no results.\";\n } else {\n const lines: string[] = [];\n for (const img of images) {\n if (img.url) {\n if (img.url.startsWith(\"data:\")) {\n try {\n const hostedUrl = await uploadDataUriToHost(img.url);\n lines.push(hostedUrl);\n } catch (uploadErr) {\n logger.error(\n `[ckcloud] /imagegen: failed to upload data URI: ${uploadErr instanceof Error ? uploadErr.message : String(uploadErr)}`,\n );\n lines.push(\n \"Image generated but upload failed. Try again or use --model dall-e-3.\",\n );\n }\n } else {\n lines.push(img.url);\n }\n }\n if (img.revised_prompt) lines.push(`Revised prompt: ${img.revised_prompt}`);\n }\n lines.push(\"\", `Model: ${imageModel} | Size: ${imageSize}`);\n responseText = lines.join(\"\\n\");\n }\n logger.info(`[ckcloud] /imagegen success: ${images.length} image(s) generated`);\n }\n\n // Return as synthetic chat completion\n const completionId = `chatcmpl-image-${Date.now()}`;\n const timestamp = Math.floor(Date.now() / 1000);\n if (isStreaming) {\n res.writeHead(200, {\n \"Content-Type\": \"text/event-stream\",\n \"Cache-Control\": \"no-cache\",\n Connection: \"keep-alive\",\n });\n res.write(\n `data: ${JSON.stringify({ id: completionId, object: \"chat.completion.chunk\", created: timestamp, model: \"ckcloud/image\", choices: [{ index: 0, delta: { role: \"assistant\", content: responseText }, finish_reason: null }] })}\\n\\n`,\n );\n res.write(\n `data: ${JSON.stringify({ id: completionId, object: \"chat.completion.chunk\", created: timestamp, model: \"ckcloud/image\", choices: [{ index: 0, delta: {}, finish_reason: \"stop\" }] })}\\n\\n`,\n );\n res.write(\"data: [DONE]\\n\\n\");\n res.end();\n } else {\n res.writeHead(200, { \"Content-Type\": \"application/json\" });\n res.end(\n JSON.stringify({\n id: completionId,\n object: \"chat.completion\",\n created: timestamp,\n model: \"ckcloud/image\",\n choices: [\n {\n index: 0,\n message: { role: \"assistant\", content: responseText },\n finish_reason: \"stop\",\n },\n ],\n usage: { prompt_tokens: 0, completion_tokens: 0, total_tokens: 0 },\n }),\n );\n }\n } catch (err) {\n const errMsg = err instanceof Error ? err.message : String(err);\n logger.error(`[ckcloud] /imagegen error: ${errMsg}`);\n if (!res.headersSent) {\n res.writeHead(500, { \"Content-Type\": \"application/json\" });\n res.end(\n JSON.stringify({\n error: { message: `Image generation failed: ${errMsg}`, type: \"image_error\" },\n }),\n );\n }\n }\n return;\n }\n\n // Force stream: false — ckcloud API doesn't support streaming yet\n // ckcloud handles SSE heartbeat simulation for upstream compatibility\n if (parsed.stream === true) {\n parsed.stream = false;\n bodyModified = true;\n }\n\n // Normalize model name for comparison (trim whitespace, lowercase)\n const normalizedModel =\n typeof parsed.model === \"string\" ? parsed.model.trim().toLowerCase() : \"\";\n\n // Resolve model aliases (e.g., \"claude\" -> \"anthropic/claude-sonnet-4-6\")\n const resolvedModel = resolveModelAlias(normalizedModel);\n const wasAlias = resolvedModel !== normalizedModel;\n\n // Check both normalizedModel and resolvedModel — OpenClaw may send \"openai/eco\"\n // which resolveModelAlias strips to \"eco\" (a valid routing profile)\n const isRoutingProfile = ROUTING_PROFILES.has(normalizedModel) || ROUTING_PROFILES.has(resolvedModel);\n\n // Extract routing profile type (free/eco/auto/premium)\n if (isRoutingProfile) {\n const profileName = resolvedModel.replace(\"ckcloud/\", \"\");\n routingProfile = profileName as \"free\" | \"eco\" | \"auto\" | \"premium\";\n }\n\n // Debug: log received model name\n logger.info(\n `[ckcloud] Received model: \"${parsed.model}\" -> normalized: \"${normalizedModel}\"${wasAlias ? ` -> alias: \"${resolvedModel}\"` : \"\"}${routingProfile ? `, profile: ${routingProfile}` : \"\"}`,\n );\n\n // For explicit model requests, always canonicalize the model ID before upstream calls.\n // This ensures case/whitespace variants (e.g. \"DEEPSEEK/...\" or \" model \") route correctly.\n if (!isRoutingProfile) {\n if (parsed.model !== resolvedModel) {\n parsed.model = resolvedModel;\n bodyModified = true;\n }\n modelId = resolvedModel;\n }\n\n // Handle routing profiles (free/eco/auto/premium)\n if (isRoutingProfile) {\n // Free profile - direct shortcut to nvidia/gpt-oss-120b (no tier routing)\n if (routingProfile === \"free\") {\n const freeModel = \"nvidia/gpt-oss-120b\";\n logger.info(`[ckcloud] Free profile - using ${freeModel} directly`);\n parsed.model = freeModel;\n modelId = freeModel;\n bodyModified = true;\n\n // Log usage for free profile\n await logUsage({\n timestamp: new Date().toISOString(),\n model: freeModel,\n tier: \"SIMPLE\",\n cost: 0,\n baselineCost: 0,\n savings: 1.0, // 100% savings\n latencyMs: 0,\n });\n } else {\n // eco/auto/premium - use tier routing\n // Check for session persistence - use pinned model if available\n // Fall back to deriving a session ID from message content when OpenClaw\n // doesn't send an explicit x-session-id header (the default behaviour).\n effectiveSessionId =\n getSessionId(req.headers as Record<string, string | string[] | undefined>) ??\n deriveSessionId(parsedMessages);\n const existingSession = effectiveSessionId\n ? sessionStore.getSession(effectiveSessionId)\n : undefined;\n\n // Extract prompt from last user message (handles both string and Anthropic array content)\n const rawPrompt = lastUserMsg?.content;\n const prompt =\n typeof rawPrompt === \"string\"\n ? rawPrompt\n : Array.isArray(rawPrompt)\n ? (rawPrompt as Array<{ type: string; text?: string }>)\n .filter((b) => b.type === \"text\")\n .map((b) => b.text ?? \"\")\n .join(\" \")\n : \"\";\n const systemMsg = parsedMessages.find((m) => m.role === \"system\");\n const systemPrompt =\n typeof systemMsg?.content === \"string\" ? systemMsg.content : undefined;\n\n // Tool detection — when tools are present, force agentic tiers for reliable tool use\n const tools = parsed.tools as unknown[] | undefined;\n hasTools = Array.isArray(tools) && tools.length > 0;\n\n if (hasTools && tools) {\n logger.info(`[ckcloud] Tools detected (${tools.length}), forcing agentic tiers`);\n }\n\n // Vision detection: scan messages for image_url content parts\n hasVision = parsedMessages.some((m) => {\n if (Array.isArray(m.content)) {\n return (m.content as Array<{ type: string }>).some((p) => p.type === \"image_url\");\n }\n return false;\n });\n if (hasVision) {\n logger.info(`[ckcloud] Vision content detected, filtering to vision-capable models`);\n }\n\n // Always route based on current request content\n routingDecision = route(prompt, systemPrompt, maxTokens, {\n ...routerOpts,\n routingProfile: routingProfile ?? undefined,\n hasTools,\n });\n\n if (existingSession) {\n // Never downgrade: only upgrade the session when the current request needs a higher\n // tier. This fixes the OpenClaw startup-message bias (the startup message always\n // scores low-complexity, which previously pinned all subsequent real queries to a\n // cheap model) while still preventing mid-task model switching on simple follow-ups.\n const tierRank: Record<string, number> = {\n SIMPLE: 0,\n MEDIUM: 1,\n COMPLEX: 2,\n REASONING: 3,\n };\n const existingRank = tierRank[existingSession.tier] ?? 0;\n const newRank = tierRank[routingDecision.tier] ?? 0;\n\n if (newRank > existingRank) {\n // Current request needs higher capability — upgrade the session\n logger.info(\n `[ckcloud] Session ${effectiveSessionId?.slice(0, 8)}... upgrading: ${existingSession.tier} → ${routingDecision.tier} (${routingDecision.model})`,\n );\n parsed.model = routingDecision.model;\n modelId = routingDecision.model;\n bodyModified = true;\n if (effectiveSessionId) {\n sessionStore.setSession(\n effectiveSessionId,\n routingDecision.model,\n routingDecision.tier,\n );\n }\n } else {\n // Keep existing higher-tier model (prevent downgrade mid-task)\n logger.info(\n `[ckcloud] Session ${effectiveSessionId?.slice(0, 8)}... keeping pinned model: ${existingSession.model} (${existingSession.tier} >= ${routingDecision.tier})`,\n );\n parsed.model = existingSession.model;\n modelId = existingSession.model;\n bodyModified = true;\n sessionStore.touchSession(effectiveSessionId!);\n // Reflect the actual model used in the routing decision for logging/fallback\n routingDecision = {\n ...routingDecision,\n model: existingSession.model,\n tier: existingSession.tier as Tier,\n };\n }\n\n // --- Three-strike escalation: detect repetitive request patterns ---\n const lastAssistantMsg = [...parsedMessages]\n .reverse()\n .find((m) => m.role === \"assistant\");\n const assistantToolCalls = (\n lastAssistantMsg as { tool_calls?: Array<{ function?: { name?: string } }> }\n )?.tool_calls;\n const toolCallNames = Array.isArray(assistantToolCalls)\n ? assistantToolCalls\n .map((tc) => tc.function?.name)\n .filter((n): n is string => Boolean(n))\n : undefined;\n const contentHash = hashRequestContent(prompt, toolCallNames);\n const shouldEscalate = sessionStore.recordRequestHash(effectiveSessionId!, contentHash);\n\n if (shouldEscalate) {\n const activeTierConfigs = (() => {\n if (\n routingDecision.reasoning?.includes(\"agentic\") &&\n routerOpts.config.agenticTiers\n ) {\n return routerOpts.config.agenticTiers;\n }\n if (routingProfile === \"eco\" && routerOpts.config.ecoTiers) {\n return routerOpts.config.ecoTiers;\n }\n if (routingProfile === \"premium\" && routerOpts.config.premiumTiers) {\n return routerOpts.config.premiumTiers;\n }\n return routerOpts.config.tiers;\n })();\n\n const escalation = sessionStore.escalateSession(\n effectiveSessionId!,\n activeTierConfigs,\n );\n if (escalation) {\n logger.info(\n `[ckcloud] ⚡ 3-strike escalation: ${existingSession.model} → ${escalation.model} (${existingSession.tier} → ${escalation.tier})`,\n );\n parsed.model = escalation.model;\n modelId = escalation.model;\n routingDecision = {\n ...routingDecision,\n model: escalation.model,\n tier: escalation.tier as Tier,\n };\n }\n }\n } else {\n // No session — pin this routing decision for future requests\n parsed.model = routingDecision.model;\n modelId = routingDecision.model;\n bodyModified = true;\n if (effectiveSessionId) {\n sessionStore.setSession(\n effectiveSessionId,\n routingDecision.model,\n routingDecision.tier,\n );\n logger.info(\n `[ckcloud] Session ${effectiveSessionId.slice(0, 8)}... pinned to model: ${routingDecision.model}`,\n );\n }\n }\n\n options.onRouted?.(routingDecision);\n }\n }\n\n // Rebuild body if modified\n if (bodyModified) {\n body = Buffer.from(JSON.stringify(parsed));\n }\n } catch (err) {\n // Log routing errors so they're not silently swallowed\n const errorMsg = err instanceof Error ? err.message : String(err);\n logger.error(`[ckcloud] Routing error: ${errorMsg}`);\n logger.error(`[ckcloud] Need help? Run: npx @ckcloudai.com/clawrouter doctor`);\n options.onError?.(new Error(`Routing failed: ${errorMsg}`));\n }\n }\n\n // --- Auto-compression ---\n // Compress large requests to reduce network usage and improve performance\n const autoCompress = options.autoCompressRequests ?? true;\n const compressionThreshold = options.compressionThresholdKB ?? 180;\n const requestSizeKB = Math.ceil(body.length / 1024);\n\n if (autoCompress && requestSizeKB > compressionThreshold) {\n try {\n logger.info(\n `[ckcloud] Request size ${requestSizeKB}KB exceeds threshold ${compressionThreshold}KB, applying compression...`,\n );\n\n // Parse messages for compression\n const parsed = JSON.parse(body.toString()) as {\n messages?: NormalizedMessage[];\n [key: string]: unknown;\n };\n\n if (parsed.messages && parsed.messages.length > 0 && shouldCompress(parsed.messages)) {\n // Apply compression with conservative settings\n const compressionResult = await compressContext(parsed.messages, {\n enabled: true,\n preserveRaw: false, // Don't need originals in proxy\n layers: {\n deduplication: true, // Safe: removes duplicate messages\n whitespace: true, // Safe: normalizes whitespace\n dictionary: false, // Disabled: requires model to understand codebook\n paths: false, // Disabled: requires model to understand path codes\n jsonCompact: true, // Safe: just removes JSON whitespace\n observation: false, // Disabled: may lose important context\n dynamicCodebook: false, // Disabled: requires model to understand codes\n },\n dictionary: {\n maxEntries: 50,\n minPhraseLength: 15,\n includeCodebookHeader: false,\n },\n });\n\n const compressedSizeKB = Math.ceil(compressionResult.compressedChars / 1024);\n const savings = (((requestSizeKB - compressedSizeKB) / requestSizeKB) * 100).toFixed(1);\n\n logger.info(\n `[ckcloud] Compressed ${requestSizeKB}KB → ${compressedSizeKB}KB (${savings}% reduction)`,\n );\n\n // Update request body with compressed messages\n parsed.messages = compressionResult.messages;\n body = Buffer.from(JSON.stringify(parsed));\n }\n } catch (err) {\n // Compression failed - continue with original request\n logger.warn(\n `[ckcloud] Compression failed: ${err instanceof Error ? err.message : String(err)}`,\n );\n }\n }\n\n // --- Response cache check (long-term, 10min TTL) ---\n const cacheKey = ResponseCache.generateKey(body);\n const reqHeaders: Record<string, string> = {};\n for (const [key, value] of Object.entries(req.headers)) {\n if (typeof value === \"string\") reqHeaders[key] = value;\n }\n if (responseCache.shouldCache(body, reqHeaders)) {\n const cachedResponse = responseCache.get(cacheKey);\n if (cachedResponse) {\n logger.info(`[ckcloud] Cache HIT for ${cachedResponse.model} (saved API call)`);\n res.writeHead(cachedResponse.status, cachedResponse.headers);\n res.end(cachedResponse.body);\n return;\n }\n }\n\n // --- Dedup check (short-term, 30s TTL for retries) ---\n const dedupKey = RequestDeduplicator.hash(body);\n\n // Check dedup cache (catches retries within 30s)\n const cached = deduplicator.getCached(dedupKey);\n if (cached) {\n res.writeHead(cached.status, cached.headers);\n res.end(cached.body);\n return;\n }\n\n // Check in-flight — wait for the original request to complete\n const inflight = deduplicator.getInflight(dedupKey);\n if (inflight) {\n const result = await inflight;\n res.writeHead(result.status, result.headers);\n res.end(result.body);\n return;\n }\n\n // Register this request as in-flight\n deduplicator.markInflight(dedupKey);\n\n // --- Pre-request balance check ---\n // Estimate cost and check if wallet has sufficient balance\n // Skip if skipBalanceCheck is set (for testing) or if using free model\n let estimatedCostMicros: bigint | undefined;\n let balanceFallbackNotice: string | undefined;\n const isFreeModel = modelId === FREE_MODEL;\n\n if (modelId && !options.skipBalanceCheck && !isFreeModel) {\n const estimated = estimateAmount(modelId, body.length, maxTokens);\n if (estimated) {\n estimatedCostMicros = BigInt(estimated);\n\n // Apply extra buffer for balance check to prevent x402 failures after streaming starts.\n // This is aggressive to avoid triggering OpenClaw's 5-24 hour billing cooldown.\n const bufferedCostMicros = (estimatedCostMicros * BigInt(Math.ceil(BALANCE_CHECK_BUFFER * 100))) / 100n;\n\n // Check balance before proceeding (using buffered amount)\n const sufficiency = await balanceMonitor.checkSufficient(bufferedCostMicros);\n\n if (sufficiency.info.isEmpty || !sufficiency.sufficient) {\n // Wallet is empty or insufficient — ALWAYS fallback to free model\n // This ensures new users with empty wallets can still use ckcloud\n const originalModel = modelId;\n logger.info(\n `[ckcloud] Wallet ${sufficiency.info.isEmpty ? \"empty\" : \"insufficient\"} (${sufficiency.info.balanceUSD}), falling back to free model: ${FREE_MODEL} (requested: ${originalModel})`,\n );\n modelId = FREE_MODEL;\n // Update the body with new model\n const parsed = JSON.parse(body.toString()) as Record<string, unknown>;\n parsed.model = FREE_MODEL;\n body = Buffer.from(JSON.stringify(parsed));\n\n // Set notice to prepend to response so user knows about the fallback\n balanceFallbackNotice = sufficiency.info.isEmpty\n ? `> **⚠️ Wallet empty** — using free model. Fund your wallet to use ${originalModel}.\\n\\n`\n : `> **⚠️ Insufficient balance** (${sufficiency.info.balanceUSD}) — using free model instead of ${originalModel}.\\n\\n`;\n\n // Notify about the fallback\n options.onLowBalance?.({\n balanceUSD: sufficiency.info.balanceUSD,\n walletAddress: sufficiency.info.walletAddress,\n });\n } else if (sufficiency.info.isLow) {\n // Balance is low but sufficient — warn and proceed\n options.onLowBalance?.({\n balanceUSD: sufficiency.info.balanceUSD,\n walletAddress: sufficiency.info.walletAddress,\n });\n }\n }\n }\n\n // --- Streaming: early header flush + heartbeat ---\n let heartbeatInterval: ReturnType<typeof setInterval> | undefined;\n let headersSentEarly = false;\n\n if (isStreaming) {\n // Send 200 + SSE headers immediately, before x402 flow\n res.writeHead(200, {\n \"content-type\": \"text/event-stream\",\n \"cache-control\": \"no-cache\",\n connection: \"keep-alive\",\n \"x-context-used-kb\": String(originalContextSizeKB),\n \"x-context-limit-kb\": String(CONTEXT_LIMIT_KB),\n });\n headersSentEarly = true;\n\n // First heartbeat immediately\n safeWrite(res, \": heartbeat\\n\\n\");\n\n // Continue heartbeats every 2s while waiting for upstream\n heartbeatInterval = setInterval(() => {\n if (canWrite(res)) {\n safeWrite(res, \": heartbeat\\n\\n\");\n } else {\n // Socket closed, stop heartbeat\n clearInterval(heartbeatInterval);\n heartbeatInterval = undefined;\n }\n }, HEARTBEAT_INTERVAL_MS);\n }\n\n // Forward headers, stripping host, connection, and content-length\n const headers: Record<string, string> = {};\n for (const [key, value] of Object.entries(req.headers)) {\n if (\n key === \"host\" ||\n key === \"connection\" ||\n key === \"transfer-encoding\" ||\n key === \"content-length\"\n )\n continue;\n if (typeof value === \"string\") {\n headers[key] = value;\n }\n }\n if (!headers[\"content-type\"]) {\n headers[\"content-type\"] = \"application/json\";\n }\n headers[\"user-agent\"] = USER_AGENT;\n\n // --- Client disconnect cleanup ---\n let completed = false;\n res.on(\"close\", () => {\n if (heartbeatInterval) {\n clearInterval(heartbeatInterval);\n heartbeatInterval = undefined;\n }\n // Remove from in-flight if client disconnected before completion\n if (!completed) {\n deduplicator.removeInflight(dedupKey);\n }\n });\n\n // --- Request timeout ---\n const timeoutMs = options.requestTimeoutMs ?? DEFAULT_REQUEST_TIMEOUT_MS;\n const controller = new AbortController();\n const timeoutId = setTimeout(() => controller.abort(), timeoutMs);\n\n try {\n // --- Build fallback chain ---\n // If we have a routing decision, get the full fallback chain for the tier\n // Otherwise, just use the current model (no fallback for explicit model requests)\n let modelsToTry: string[];\n if (routingDecision) {\n // Estimate total context: input tokens (~4 chars per token) + max output tokens\n const estimatedInputTokens = Math.ceil(body.length / 4);\n const estimatedTotalTokens = estimatedInputTokens + maxTokens;\n\n // Get tier configs matching the profile that was used for routing\n // Must stay in sync with what route() selected in router/index.ts\n const tierConfigs = (() => {\n if (routingDecision.reasoning?.includes(\"agentic\") && routerOpts.config.agenticTiers) {\n return routerOpts.config.agenticTiers;\n }\n if (routingProfile === \"eco\" && routerOpts.config.ecoTiers) {\n return routerOpts.config.ecoTiers;\n }\n if (routingProfile === \"premium\" && routerOpts.config.premiumTiers) {\n return routerOpts.config.premiumTiers;\n }\n return routerOpts.config.tiers;\n })();\n\n // Get full chain first, then filter by context\n const fullChain = getFallbackChain(routingDecision.tier, tierConfigs);\n const contextFiltered = getFallbackChainFiltered(\n routingDecision.tier,\n tierConfigs,\n estimatedTotalTokens,\n getModelContextWindow,\n );\n\n // Log if models were filtered out due to context limits\n const contextExcluded = fullChain.filter((m) => !contextFiltered.includes(m));\n if (contextExcluded.length > 0) {\n logger.info(\n `[ckcloud] Context filter (~${estimatedTotalTokens} tokens): excluded ${contextExcluded.join(\", \")}`,\n );\n }\n\n // Filter to models that support tool calling when request has tools.\n // Prevents models like grok-code-fast-1 from outputting tool invocations\n // as plain text JSON (the \"talking to itself\" bug).\n let toolFiltered = filterByToolCalling(contextFiltered, hasTools, supportsToolCalling);\n const toolExcluded = contextFiltered.filter((m) => !toolFiltered.includes(m));\n if (toolExcluded.length > 0) {\n logger.info(\n `[ckcloud] Tool-calling filter: excluded ${toolExcluded.join(\", \")} (no structured function call support)`,\n );\n }\n\n // Filter out models that declare toolCalling but fail tool compliance in practice.\n // gemini-2.5-flash-lite refuses certain tool schemas (e.g. brave search) while\n // cheaper models like nvidia/gpt-oss-120b handle them fine.\n const TOOL_NONCOMPLIANT_MODELS = [\n \"google/gemini-2.5-flash-lite\",\n \"google/gemini-3-pro-preview\",\n \"google/gemini-3.1-pro\",\n ];\n if (hasTools && toolFiltered.length > 1) {\n const compliant = toolFiltered.filter((m) => !TOOL_NONCOMPLIANT_MODELS.includes(m));\n if (compliant.length > 0 && compliant.length < toolFiltered.length) {\n const dropped = toolFiltered.filter((m) => TOOL_NONCOMPLIANT_MODELS.includes(m));\n logger.info(\n `[ckcloud] Tool-compliance filter: excluded ${dropped.join(\", \")} (unreliable tool schema handling)`,\n );\n toolFiltered = compliant;\n }\n }\n\n // Filter to models that support vision when request has image_url content\n const visionFiltered = filterByVision(toolFiltered, hasVision, supportsVision);\n const visionExcluded = toolFiltered.filter((m) => !visionFiltered.includes(m));\n if (visionExcluded.length > 0) {\n logger.info(\n `[ckcloud] Vision filter: excluded ${visionExcluded.join(\", \")} (no vision support)`,\n );\n }\n\n // Limit to MAX_FALLBACK_ATTEMPTS to prevent infinite loops\n modelsToTry = visionFiltered.slice(0, MAX_FALLBACK_ATTEMPTS);\n\n // Deprioritize rate-limited models (put them at the end)\n modelsToTry = prioritizeNonRateLimited(modelsToTry);\n } else {\n // For explicit model requests, use the requested model\n modelsToTry = modelId ? [modelId] : [];\n }\n\n // Always ensure free model is the last-resort fallback.\n // If all paid models fail (insufficient funds, rate limits, etc.),\n // the user still gets a response instead of an error.\n if (!modelsToTry.includes(FREE_MODEL)) {\n modelsToTry.push(FREE_MODEL);\n }\n\n // --- Fallback loop: try each model until success ---\n let upstream: Response | undefined;\n let lastError: { body: string; status: number } | undefined;\n let actualModelUsed = modelId;\n\n for (let i = 0; i < modelsToTry.length; i++) {\n const tryModel = modelsToTry[i];\n const isLastAttempt = i === modelsToTry.length - 1;\n\n logger.info(`[ckcloud] Trying model ${i + 1}/${modelsToTry.length}: ${tryModel}`);\n\n const result = await tryModelRequest(\n upstreamUrl,\n req.method ?? \"POST\",\n headers,\n body,\n tryModel,\n maxTokens,\n payFetch,\n balanceMonitor,\n controller.signal,\n );\n\n if (result.success && result.response) {\n upstream = result.response;\n actualModelUsed = tryModel;\n logger.info(`[ckcloud] Success with model: ${tryModel}`);\n break;\n }\n logger.info(`[ckcloud] Trying, body:${body}, response:${JSON.stringify(result ?? \"result null\")}`);\n\n // Request failed\n lastError = {\n body: result.errorBody || \"Unknown error\",\n status: result.errorStatus || 500,\n };\n\n // If it's a provider error and not the last attempt, try next model\n if (result.isProviderError && !isLastAttempt) {\n // Track 429 rate limits to deprioritize this model for future requests\n if (result.errorStatus === 429) {\n markRateLimited(tryModel);\n // Check for server-side update hint\n try {\n const parsed = JSON.parse(result.errorBody || \"{}\");\n if (parsed.update_available) {\n logger.info(\"\");\n logger.info(\n `\\x1b[33m⬆️ ckcloud ${parsed.update_available} available (you have ${VERSION})\\x1b[0m`,\n );\n logger.info(\n ` Run: \\x1b[36mcurl -fsSL ${parsed.update_url || \"https://ckcloud.ai/ckcloud-update\"} | bash\\x1b[0m`,\n );\n logger.info(\"\");\n }\n } catch {\n /* ignore parse errors */\n }\n }\n\n // Payment error (insufficient funds, simulation failure) — skip remaining\n // paid models, jump straight to free model. No point trying other paid\n // models with the same wallet state.\n const isPaymentErr =\n /payment.*verification.*failed|payment.*settlement.*failed|insufficient.*funds|transaction_simulation_failed/i.test(\n result.errorBody || \"\",\n );\n if (isPaymentErr && tryModel !== FREE_MODEL) {\n const freeIdx = modelsToTry.indexOf(FREE_MODEL);\n if (freeIdx > i + 1) {\n logger.info(`[ckcloud] Payment error — skipping to free model: ${FREE_MODEL}`);\n i = freeIdx - 1; // loop will increment to freeIdx\n continue;\n }\n }\n\n logger.info(\n `[ckcloud] Provider error from ${tryModel}, trying fallback: ${result.errorBody?.slice(0, 100)}`,\n );\n continue;\n }\n\n // Not a provider error or last attempt — stop trying\n if (!result.isProviderError) {\n logger.info(\n `[ckcloud] Non-provider error from ${tryModel}, not retrying: ${result.errorBody?.slice(0, 100)}`,\n );\n }\n break;\n }\n\n // Clear timeout — request attempts completed\n clearTimeout(timeoutId);\n\n // Clear heartbeat — real data is about to flow\n if (heartbeatInterval) {\n clearInterval(heartbeatInterval);\n heartbeatInterval = undefined;\n }\n\n // --- Emit routing debug info (opt-in via x-ckcloud-debug: true header) ---\n // For streaming: SSE comment (invisible to most clients, visible in raw stream)\n // For non-streaming: response headers added later\n if (debugMode && headersSentEarly && routingDecision) {\n const debugComment = `: x-ckcloud-debug profile=${routingProfile ?? \"auto\"} tier=${routingDecision.tier} model=${actualModelUsed} agentic=${routingDecision.agenticScore?.toFixed(2) ?? \"n/a\"} confidence=${routingDecision.confidence.toFixed(2)} reasoning=${routingDecision.reasoning}\\n\\n`;\n safeWrite(res, debugComment);\n }\n\n // Update routing decision with actual model used (for logging)\n // IMPORTANT: Recalculate cost for the actual model, not the original primary\n if (routingDecision && actualModelUsed !== routingDecision.model) {\n const estimatedInputTokens = Math.ceil(body.length / 4);\n const newCosts = calculateModelCost(\n actualModelUsed,\n routerOpts.modelPricing,\n estimatedInputTokens,\n maxTokens,\n routingProfile ?? undefined,\n );\n routingDecision = {\n ...routingDecision,\n model: actualModelUsed,\n reasoning: `${routingDecision.reasoning} | fallback to ${actualModelUsed}`,\n costEstimate: newCosts.costEstimate,\n baselineCost: newCosts.baselineCost,\n savings: newCosts.savings,\n };\n options.onRouted?.(routingDecision);\n\n // Update session pin to the actual model used — ensures the next request in\n // this conversation starts from the fallback model rather than retrying the\n // primary and falling back again (prevents the \"model keeps jumping\" issue).\n if (effectiveSessionId) {\n sessionStore.setSession(effectiveSessionId, actualModelUsed, routingDecision.tier);\n logger.info(\n `[ckcloud] Session ${effectiveSessionId.slice(0, 8)}... updated pin to fallback: ${actualModelUsed}`,\n );\n }\n }\n\n // --- Handle case where all models failed ---\n if (!upstream) {\n const rawErrBody = lastError?.body || \"All models in fallback chain failed\";\n const errStatus = lastError?.status || 502;\n\n // Transform payment errors into user-friendly messages\n const transformedErr = transformPaymentError(rawErrBody);\n\n if (headersSentEarly) {\n // Streaming: send error as SSE event\n // If transformed error is already JSON, parse and use it; otherwise wrap in standard format\n let errPayload: string;\n try {\n const parsed = JSON.parse(transformedErr);\n errPayload = JSON.stringify(parsed);\n } catch {\n errPayload = JSON.stringify({\n error: { message: rawErrBody, type: \"provider_error\", status: errStatus },\n });\n }\n const errEvent = `data: ${errPayload}\\n\\n`;\n safeWrite(res, errEvent);\n safeWrite(res, \"data: [DONE]\\n\\n\");\n res.end();\n\n const errBuf = Buffer.from(errEvent + \"data: [DONE]\\n\\n\");\n deduplicator.complete(dedupKey, {\n status: 200,\n headers: { \"content-type\": \"text/event-stream\" },\n body: errBuf,\n completedAt: Date.now(),\n });\n } else {\n // Non-streaming: send transformed error response with context headers\n res.writeHead(errStatus, {\n \"Content-Type\": \"application/json\",\n \"x-context-used-kb\": String(originalContextSizeKB),\n \"x-context-limit-kb\": String(CONTEXT_LIMIT_KB),\n });\n res.end(transformedErr);\n\n deduplicator.complete(dedupKey, {\n status: errStatus,\n headers: { \"content-type\": \"application/json\" },\n body: Buffer.from(transformedErr),\n completedAt: Date.now(),\n });\n }\n return;\n }\n\n // --- Stream response and collect for dedup cache ---\n const responseChunks: Buffer[] = [];\n\n if (headersSentEarly) {\n // Streaming: headers already sent. Response should be 200 at this point\n // (non-200 responses are handled in the fallback loop above)\n\n // Convert non-streaming JSON response to SSE streaming format for client\n // (ckcloud API returns JSON since we forced stream:false)\n // OpenClaw expects: object=\"chat.completion.chunk\" with choices[].delta (not message)\n // We emit proper incremental deltas to match OpenAI's streaming format exactly\n if (upstream.body) {\n const chunks = await readBodyWithTimeout(upstream.body);\n\n // Combine chunks and transform to streaming format\n const jsonBody = Buffer.concat(chunks);\n const jsonStr = jsonBody.toString();\n try {\n const rsp = JSON.parse(jsonStr) as {\n id?: string;\n object?: string;\n created?: number;\n model?: string;\n choices?: Array<{\n index?: number;\n message?: {\n role?: string;\n content?: string;\n tool_calls?: Array<{\n id: string;\n type: string;\n function: { name: string; arguments: string };\n }>;\n };\n delta?: {\n role?: string;\n content?: string;\n tool_calls?: Array<{\n id: string;\n type: string;\n function: { name: string; arguments: string };\n }>;\n };\n finish_reason?: string | null;\n }>;\n usage?: unknown;\n };\n\n // Extract input token count from upstream response\n if (rsp.usage && typeof rsp.usage === \"object\") {\n const u = rsp.usage as Record<string, unknown>;\n if (typeof u.prompt_tokens === \"number\") responseInputTokens = u.prompt_tokens;\n }\n\n // Build base chunk structure (reused for all chunks)\n // Match OpenAI's exact format including system_fingerprint\n const baseChunk = {\n id: rsp.id ?? `chatcmpl-${Date.now()}`,\n object: \"chat.completion.chunk\",\n created: rsp.created ?? Math.floor(Date.now() / 1000),\n model: rsp.model ?? \"unknown\",\n system_fingerprint: null,\n };\n\n // Process each choice (usually just one)\n if (rsp.choices && Array.isArray(rsp.choices)) {\n for (const choice of rsp.choices) {\n // Strip thinking tokens (Kimi <|...|> and standard <think> tags)\n const rawContent = choice.message?.content ?? choice.delta?.content ?? \"\";\n const content = stripThinkingTokens(rawContent);\n const role = choice.message?.role ?? choice.delta?.role ?? \"assistant\";\n const index = choice.index ?? 0;\n\n // Accumulate content for session journal\n if (content) {\n accumulatedContent += content;\n }\n\n // Chunk 1: role only (mimics OpenAI's first chunk)\n const roleChunk = {\n ...baseChunk,\n choices: [{ index, delta: { role }, logprobs: null, finish_reason: null }],\n };\n const roleData = `data: ${JSON.stringify(roleChunk)}\\n\\n`;\n safeWrite(res, roleData);\n responseChunks.push(Buffer.from(roleData));\n\n // Chunk 1.5: balance fallback notice (tells user they got free model)\n if (balanceFallbackNotice) {\n const noticeChunk = {\n ...baseChunk,\n choices: [\n {\n index,\n delta: { content: balanceFallbackNotice },\n logprobs: null,\n finish_reason: null,\n },\n ],\n };\n const noticeData = `data: ${JSON.stringify(noticeChunk)}\\n\\n`;\n safeWrite(res, noticeData);\n responseChunks.push(Buffer.from(noticeData));\n balanceFallbackNotice = undefined; // Only inject once\n }\n\n // Chunk 2: content (single chunk with full content)\n if (content) {\n const contentChunk = {\n ...baseChunk,\n choices: [{ index, delta: { content }, logprobs: null, finish_reason: null }],\n };\n const contentData = `data: ${JSON.stringify(contentChunk)}\\n\\n`;\n safeWrite(res, contentData);\n responseChunks.push(Buffer.from(contentData));\n }\n\n // Chunk 2b: tool_calls (forward tool calls from upstream)\n const toolCalls = choice.message?.tool_calls ?? choice.delta?.tool_calls;\n if (toolCalls && toolCalls.length > 0) {\n const toolCallChunk = {\n ...baseChunk,\n choices: [\n {\n index,\n delta: { tool_calls: toolCalls },\n logprobs: null,\n finish_reason: null,\n },\n ],\n };\n const toolCallData = `data: ${JSON.stringify(toolCallChunk)}\\n\\n`;\n safeWrite(res, toolCallData);\n responseChunks.push(Buffer.from(toolCallData));\n }\n\n // Chunk 3: finish_reason (signals completion)\n const finishChunk = {\n ...baseChunk,\n choices: [\n {\n index,\n delta: {},\n logprobs: null,\n finish_reason:\n toolCalls && toolCalls.length > 0\n ? \"tool_calls\"\n : (choice.finish_reason ?? \"stop\"),\n },\n ],\n };\n const finishData = `data: ${JSON.stringify(finishChunk)}\\n\\n`;\n safeWrite(res, finishData);\n responseChunks.push(Buffer.from(finishData));\n }\n }\n } catch {\n // If parsing fails, send raw response as single chunk\n const sseData = `data: ${jsonStr}\\n\\n`;\n safeWrite(res, sseData);\n responseChunks.push(Buffer.from(sseData));\n }\n }\n\n // Send SSE terminator\n safeWrite(res, \"data: [DONE]\\n\\n\");\n responseChunks.push(Buffer.from(\"data: [DONE]\\n\\n\"));\n res.end();\n\n // Cache for dedup\n deduplicator.complete(dedupKey, {\n status: 200,\n headers: { \"content-type\": \"text/event-stream\" },\n body: Buffer.concat(responseChunks),\n completedAt: Date.now(),\n });\n } else {\n // Non-streaming: forward status and headers from upstream\n const responseHeaders: Record<string, string> = {};\n upstream.headers.forEach((value, key) => {\n // Skip hop-by-hop headers and content-encoding (fetch already decompresses)\n if (key === \"transfer-encoding\" || key === \"connection\" || key === \"content-encoding\")\n return;\n responseHeaders[key] = value;\n });\n\n // Add context usage headers\n responseHeaders[\"x-context-used-kb\"] = String(originalContextSizeKB);\n responseHeaders[\"x-context-limit-kb\"] = String(CONTEXT_LIMIT_KB);\n\n // Add routing debug headers (opt-in via x-ckcloud-debug: true header)\n if (debugMode && routingDecision) {\n responseHeaders[\"x-ckcloud-profile\"] = routingProfile ?? \"auto\";\n responseHeaders[\"x-ckcloud-tier\"] = routingDecision.tier;\n responseHeaders[\"x-ckcloud-model\"] = actualModelUsed;\n responseHeaders[\"x-ckcloud-confidence\"] = routingDecision.confidence.toFixed(2);\n responseHeaders[\"x-ckcloud-reasoning\"] = routingDecision.reasoning;\n if (routingDecision.agenticScore !== undefined) {\n responseHeaders[\"x-ckcloud-agentic-score\"] = routingDecision.agenticScore.toFixed(2);\n }\n }\n\n // Collect full body for possible notice injection\n const bodyParts: Buffer[] = [];\n if (upstream.body) {\n const chunks = await readBodyWithTimeout(upstream.body);\n for (const chunk of chunks) {\n bodyParts.push(Buffer.from(chunk));\n }\n }\n\n let responseBody = Buffer.concat(bodyParts);\n\n // Prepend balance fallback notice to response content\n if (balanceFallbackNotice && responseBody.length > 0) {\n try {\n const parsed = JSON.parse(responseBody.toString()) as {\n choices?: Array<{ message?: { content?: string } }>;\n };\n if (parsed.choices?.[0]?.message?.content !== undefined) {\n parsed.choices[0].message.content =\n balanceFallbackNotice + parsed.choices[0].message.content;\n responseBody = Buffer.from(JSON.stringify(parsed));\n }\n } catch {\n /* not JSON, skip notice */\n }\n balanceFallbackNotice = undefined;\n }\n\n // Update content-length header since body may have changed\n responseHeaders[\"content-length\"] = String(responseBody.length);\n res.writeHead(upstream.status, responseHeaders);\n safeWrite(res, responseBody);\n responseChunks.push(responseBody);\n res.end();\n\n // Cache for dedup (short-term, 30s)\n deduplicator.complete(dedupKey, {\n status: upstream.status,\n headers: responseHeaders,\n body: responseBody,\n completedAt: Date.now(),\n });\n\n // Cache for response cache (long-term, 10min) - only successful non-streaming\n if (upstream.status === 200 && responseCache.shouldCache(body)) {\n responseCache.set(cacheKey, {\n body: responseBody,\n status: upstream.status,\n headers: responseHeaders,\n model: actualModelUsed,\n });\n logger.info(\n `[ckcloud] Cached response for ${actualModelUsed} (${responseBody.length} bytes)`,\n );\n }\n\n // Extract content and token usage from non-streaming response\n try {\n const rspJson = JSON.parse(responseBody.toString()) as {\n choices?: Array<{ message?: { content?: string } }>;\n usage?: Record<string, unknown>;\n };\n if (rspJson.choices?.[0]?.message?.content) {\n accumulatedContent = rspJson.choices[0].message.content;\n }\n if (rspJson.usage && typeof rspJson.usage === \"object\") {\n if (typeof rspJson.usage.prompt_tokens === \"number\")\n responseInputTokens = rspJson.usage.prompt_tokens;\n }\n } catch {\n // Ignore parse errors - journal just won't have content for this response\n }\n }\n\n // --- Session Journal: Extract and record events from response ---\n if (sessionId && accumulatedContent) {\n const events = sessionJournal.extractEvents(accumulatedContent);\n if (events.length > 0) {\n sessionJournal.record(sessionId, events, actualModelUsed);\n logger.info(\n `[ckcloud] Recorded ${events.length} events to session journal for session ${sessionId.slice(0, 8)}...`,\n );\n }\n }\n\n // --- Optimistic balance deduction after successful response ---\n if (estimatedCostMicros !== undefined) {\n balanceMonitor.deductEstimated(estimatedCostMicros);\n }\n\n // Mark request as completed (for client disconnect cleanup)\n completed = true;\n } catch (err) {\n // Clear timeout on error\n clearTimeout(timeoutId);\n\n // Clear heartbeat on error\n if (heartbeatInterval) {\n clearInterval(heartbeatInterval);\n heartbeatInterval = undefined;\n }\n\n // Remove in-flight entry so retries aren't blocked\n deduplicator.removeInflight(dedupKey);\n\n // Invalidate balance cache on payment failure (might be out of date)\n balanceMonitor.invalidate();\n\n // Convert abort error to more descriptive timeout error\n if (err instanceof Error && err.name === \"AbortError\") {\n throw new Error(`Request timed out after ${timeoutMs}ms`, { cause: err });\n }\n\n throw err;\n }\n\n // --- Usage logging (fire-and-forget) ---\n // Note: Recalculate cost using full body length (not just system+user message)\n // and apply 20% buffer to match actual x402 payment (see estimateAmount())\n // Log ALL requests: both auto-routed (routingDecision set) and direct model picks\n const logModel = routingDecision?.model ?? modelId;\n if (logModel) {\n // Use full body length for accurate cost (matches x402 payment estimation)\n const estimatedInputTokens = Math.ceil(body.length / 4);\n const accurateCosts = calculateModelCost(\n logModel,\n routerOpts.modelPricing,\n estimatedInputTokens,\n maxTokens,\n routingProfile ?? undefined,\n );\n // Apply 20% buffer for cost estimation accuracy\n const costWithBuffer = accurateCosts.costEstimate * 1.2;\n const baselineWithBuffer = accurateCosts.baselineCost * 1.2;\n const entry: UsageEntry = {\n timestamp: new Date().toISOString(),\n model: logModel,\n tier: routingDecision?.tier ?? \"DIRECT\",\n cost: costWithBuffer,\n baselineCost: baselineWithBuffer,\n savings: accurateCosts.savings,\n latencyMs: Date.now() - startTime,\n ...(responseInputTokens !== undefined && { inputTokens: responseInputTokens }),\n };\n logUsage(entry).catch(() => { });\n }\n}\n","/**\n * Payment Pre-Auth Cache\n *\n * Wraps the @x402/fetch SDK with pre-authorization caching.\n * After the first 402 response, caches payment requirements per endpoint.\n * On subsequent requests, pre-signs payment and attaches it to the first\n * request, skipping the 402 round trip (~200ms savings per request).\n *\n * Falls back to normal 402 flow if pre-signed payment is rejected.\n */\n\nimport type { x402Client } from \"@x402/fetch\";\nimport { x402HTTPClient } from \"@x402/fetch\";\n\ntype PaymentRequired = Parameters<InstanceType<typeof x402Client>[\"createPaymentPayload\"]>[0];\n\ninterface CachedEntry {\n paymentRequired: PaymentRequired;\n cachedAt: number;\n}\n\nconst DEFAULT_TTL_MS = 3_600_000; // 1 hour\n\nif (typeof process !== \"undefined\") {\n process.env.NODE_TLS_REJECT_UNAUTHORIZED = \"0\";\n}\n\ntype FetchFn = (input: RequestInfo | URL, init?: RequestInit) => Promise<Response>;\n\nexport function createPayFetchWithPreAuth(\n baseFetch: FetchFn,\n client: x402Client,\n ttlMs = DEFAULT_TTL_MS,\n options?: { skipPreAuth?: boolean },\n): FetchFn {\n const httpClient = new x402HTTPClient(client);\n const cache = new Map<string, CachedEntry>();\n\n return async (input: RequestInfo | URL, init?: RequestInit): Promise<Response> => {\n const request = new Request(input, init);\n const urlPath = new URL(request.url).pathname;\n\n // Try pre-auth if we have cached payment requirements\n // Skip for Solana: payments use per-tx blockhashes that expire ~60-90s,\n // making cached requirements useless and causing double charges.\n const cached = !options?.skipPreAuth ? cache.get(urlPath) : undefined;\n if (cached && Date.now() - cached.cachedAt < ttlMs) {\n try {\n const payload = await client.createPaymentPayload(cached.paymentRequired);\n const headers = httpClient.encodePaymentSignatureHeader(payload);\n const preAuthRequest = request.clone();\n for (const [key, value] of Object.entries(headers)) {\n preAuthRequest.headers.set(key, value);\n }\n const response = await baseFetch(preAuthRequest);\n if (response.status !== 402) {\n return response; // Pre-auth worked — saved ~200ms\n }\n // Pre-auth rejected (params may have changed) — invalidate and fall through\n cache.delete(urlPath);\n } catch {\n // Pre-auth signing failed — invalidate and fall through\n cache.delete(urlPath);\n }\n }\n\n // Normal flow: make request, handle 402 if needed\n const clonedRequest = request.clone();\n const response = await baseFetch(request);\n if (response.status !== 402) {\n return response;\n }\n\n // Parse 402 response and cache for future pre-auth\n let paymentRequired: PaymentRequired;\n try {\n const getHeader = (name: string) => response.headers.get(name);\n let body: unknown;\n try {\n const responseText = await Promise.race([\n response.text(),\n new Promise<never>((_, reject) =>\n setTimeout(() => reject(new Error(\"Body read timeout\")), 30_000),\n ),\n ]);\n if (responseText) body = JSON.parse(responseText);\n } catch {\n /* empty body is fine */\n }\n paymentRequired = httpClient.getPaymentRequiredResponse(getHeader, body);\n cache.set(urlPath, { paymentRequired, cachedAt: Date.now() });\n } catch (error) {\n throw new Error(\n `Failed to parse payment requirements: ${error instanceof Error ? error.message : \"Unknown error\"}`,\n { cause: error },\n );\n }\n\n // Sign payment and retry\n const payload = await client.createPaymentPayload(paymentRequired);\n const paymentHeaders = httpClient.encodePaymentSignatureHeader(payload);\n for (const [key, value] of Object.entries(paymentHeaders)) {\n clonedRequest.headers.set(key, value);\n }\n return baseFetch(clonedRequest);\n };\n}\n","/**\n * Balance Monitor for ckcloud\n *\n * Monitors USDC balance on Base network with intelligent caching.\n * Provides pre-request balance checks to prevent failed payments.\n *\n * Caching Strategy:\n * - TTL: 30 seconds (balance is cached to avoid excessive RPC calls)\n * - Optimistic deduction: after successful payment, subtract estimated cost from cache\n * - Invalidation: on payment failure, immediately refresh from RPC\n */\n\nimport { createPublicClient, http, erc20Abi } from \"viem\";\nimport { base } from \"viem/chains\";\nimport { RpcError } from \"./errors.js\";\n\n/** USDC contract address on Base mainnet */\nconst USDC_BASE = \"0x833589fCD6eDb6E08f4c7C32D4f71b54bdA02913\" as const;\n\n/** Cache TTL in milliseconds (30 seconds) */\nconst CACHE_TTL_MS = 30_000;\n\n/** Balance thresholds in USDC smallest unit (6 decimals) */\nexport const BALANCE_THRESHOLDS = {\n /** Low balance warning threshold: $1.00 */\n LOW_BALANCE_MICROS: 1_000_000n,\n /** Effectively zero threshold: $0.0001 (covers dust/rounding) */\n ZERO_THRESHOLD: 100n,\n} as const;\n\n/** Balance information returned by checkBalance() */\nexport type BalanceInfo = {\n /** Raw balance in USDC smallest unit (6 decimals) */\n balance: bigint;\n /** Formatted balance as \"$X.XX\" */\n balanceUSD: string;\n /** True if balance < $1.00 */\n isLow: boolean;\n /** True if balance < $0.0001 (effectively zero) */\n isEmpty: boolean;\n /** Wallet address for funding instructions */\n walletAddress: string;\n};\n\n/** Result from checkSufficient() */\nexport type SufficiencyResult = {\n /** True if balance >= estimated cost */\n sufficient: boolean;\n /** Current balance info */\n info: BalanceInfo;\n /** If insufficient, the shortfall as \"$X.XX\" */\n shortfall?: string;\n};\n\n/**\n * Monitors USDC balance on Base network.\n *\n * Usage:\n * const monitor = new BalanceMonitor(\"0x...\");\n * const info = await monitor.checkBalance();\n * if (info.isLow) console.warn(\"Low balance!\");\n */\nexport class BalanceMonitor {\n private readonly client;\n private readonly walletAddress: `0x${string}`;\n\n /** Cached balance (null = not yet fetched) */\n private cachedBalance: bigint | null = null;\n /** Timestamp when cache was last updated */\n private cachedAt = 0;\n\n constructor(walletAddress: string) {\n this.walletAddress = walletAddress as `0x${string}`;\n this.client = createPublicClient({\n chain: base,\n transport: http(undefined, {\n timeout: 10_000, // 10 second timeout to prevent hanging on slow RPC\n }),\n });\n }\n\n /**\n * Check current USDC balance.\n * Uses cache if valid, otherwise fetches from RPC.\n */\n async checkBalance(): Promise<BalanceInfo> {\n const now = Date.now();\n\n // Use cache only when balance is positive and still fresh.\n // Zero balance is never cached — always re-fetch so a funded wallet is\n // detected on the next request without waiting for cache expiry.\n if (\n this.cachedBalance !== null &&\n this.cachedBalance > 0n &&\n now - this.cachedAt < CACHE_TTL_MS\n ) {\n return this.buildInfo(this.cachedBalance);\n }\n\n // Fetch from RPC\n const balance = await this.fetchBalance();\n if (balance > 0n) {\n this.cachedBalance = balance;\n this.cachedAt = now;\n }\n\n return this.buildInfo(balance);\n }\n\n /**\n * Check if balance is sufficient for an estimated cost.\n *\n * @param estimatedCostMicros - Estimated cost in USDC smallest unit (6 decimals)\n */\n async checkSufficient(estimatedCostMicros: bigint): Promise<SufficiencyResult> {\n const info = await this.checkBalance();\n\n if (info.balance >= estimatedCostMicros) {\n return { sufficient: true, info };\n }\n\n const shortfall = estimatedCostMicros - info.balance;\n return {\n sufficient: false,\n info,\n shortfall: this.formatUSDC(shortfall),\n };\n }\n\n /**\n * Optimistically deduct estimated cost from cached balance.\n * Call this after a successful payment to keep cache accurate.\n *\n * @param amountMicros - Amount to deduct in USDC smallest unit\n */\n deductEstimated(amountMicros: bigint): void {\n if (this.cachedBalance !== null && this.cachedBalance >= amountMicros) {\n this.cachedBalance -= amountMicros;\n }\n }\n\n /**\n * Invalidate cache, forcing next checkBalance() to fetch from RPC.\n * Call this after a payment failure to get accurate balance.\n */\n invalidate(): void {\n this.cachedBalance = null;\n this.cachedAt = 0;\n }\n\n /**\n * Force refresh balance from RPC (ignores cache).\n */\n async refresh(): Promise<BalanceInfo> {\n this.invalidate();\n return this.checkBalance();\n }\n\n /**\n * Format USDC amount (in micros) as \"$X.XX\".\n */\n formatUSDC(amountMicros: bigint): string {\n // USDC has 6 decimals\n const dollars = Number(amountMicros) / 1_000_000;\n return `$${dollars.toFixed(2)}`;\n }\n\n /**\n * Get the wallet address being monitored.\n */\n getWalletAddress(): string {\n return this.walletAddress;\n }\n\n /** Fetch balance from RPC */\n private async fetchBalance(): Promise<bigint> {\n try {\n const balance = await this.client.readContract({\n address: USDC_BASE,\n abi: erc20Abi,\n functionName: \"balanceOf\",\n args: [this.walletAddress],\n });\n return balance;\n } catch (error) {\n // Throw typed error instead of silently returning 0\n // This allows callers to distinguish \"node down\" from \"wallet empty\"\n throw new RpcError(error instanceof Error ? error.message : \"Unknown error\", error);\n }\n }\n\n /** Build BalanceInfo from raw balance */\n private buildInfo(balance: bigint): BalanceInfo {\n return {\n balance,\n balanceUSD: this.formatUSDC(balance),\n isLow: balance < BALANCE_THRESHOLDS.LOW_BALANCE_MICROS,\n isEmpty: balance < BALANCE_THRESHOLDS.ZERO_THRESHOLD,\n walletAddress: this.walletAddress,\n };\n }\n}\n","/**\n * Typed Error Classes for ckcloud\n *\n * Provides structured errors for balance-related failures with\n * all necessary information for user-friendly error messages.\n */\n\n/**\n * Thrown when wallet has insufficient USDC balance for a request.\n */\nexport class InsufficientFundsError extends Error {\n readonly code = \"INSUFFICIENT_FUNDS\" as const;\n readonly currentBalanceUSD: string;\n readonly requiredUSD: string;\n readonly walletAddress: string;\n\n constructor(opts: { currentBalanceUSD: string; requiredUSD: string; walletAddress: string }) {\n const msg = [\n `Insufficient balance. Current: ${opts.currentBalanceUSD}, Required: ${opts.requiredUSD}`,\n `Options:`,\n ` 1. Fund wallet: ${opts.walletAddress}`,\n ` 2. Use free model: /model free`,\n ].join(\"\\n\");\n super(msg);\n this.name = \"InsufficientFundsError\";\n this.currentBalanceUSD = opts.currentBalanceUSD;\n this.requiredUSD = opts.requiredUSD;\n this.walletAddress = opts.walletAddress;\n }\n}\n\n/**\n * Thrown when wallet has no USDC balance (or effectively zero).\n */\nexport class EmptyWalletError extends Error {\n readonly code = \"EMPTY_WALLET\" as const;\n readonly walletAddress: string;\n\n constructor(walletAddress: string) {\n const msg = [\n `No USDC balance.`,\n `Options:`,\n ` 1. Fund wallet: ${walletAddress}`,\n ` 2. Use free model: /model free`,\n ` 3. Uninstall: bash ~/.openclaw/extensions/ckcloud/scripts/uninstall.sh`,\n ].join(\"\\n\");\n super(msg);\n this.name = \"EmptyWalletError\";\n this.walletAddress = walletAddress;\n }\n}\n\n/**\n * Type guard to check if an error is InsufficientFundsError.\n */\nexport function isInsufficientFundsError(error: unknown): error is InsufficientFundsError {\n return error instanceof Error && (error as InsufficientFundsError).code === \"INSUFFICIENT_FUNDS\";\n}\n\n/**\n * Type guard to check if an error is EmptyWalletError.\n */\nexport function isEmptyWalletError(error: unknown): error is EmptyWalletError {\n return error instanceof Error && (error as EmptyWalletError).code === \"EMPTY_WALLET\";\n}\n\n/**\n * Type guard to check if an error is a balance-related error.\n */\nexport function isBalanceError(error: unknown): error is InsufficientFundsError | EmptyWalletError {\n return isInsufficientFundsError(error) || isEmptyWalletError(error);\n}\n\n/**\n * Thrown when RPC call fails (network error, node down, etc).\n * Distinguishes infrastructure failures from actual empty wallets.\n */\nexport class RpcError extends Error {\n readonly code = \"RPC_ERROR\" as const;\n readonly originalError: unknown;\n\n constructor(message: string, originalError?: unknown) {\n super(`RPC error: ${message}. Check network connectivity.`);\n this.name = \"RpcError\";\n this.originalError = originalError;\n }\n}\n\n/**\n * Type guard to check if an error is RpcError.\n */\nexport function isRpcError(error: unknown): error is RpcError {\n return error instanceof Error && (error as RpcError).code === \"RPC_ERROR\";\n}\n","/**\n * Solana USDC Balance Monitor\n *\n * Checks USDC balance on Solana mainnet with caching.\n * Absorbed from @ckcloudai.com/clawwallet's solana-adapter.ts (balance portion only).\n */\n\nimport { address as solAddress, createSolanaRpc } from \"@solana/kit\";\n\nconst SOLANA_USDC_MINT = \"EPjFWdd5AufqSSqeM2qN1xzybapC8G4wEGGkZwyTDt1v\";\nconst SOLANA_DEFAULT_RPC = \"https://api.mainnet-beta.solana.com\";\nconst BALANCE_TIMEOUT_MS = 10_000;\nconst CACHE_TTL_MS = 30_000;\n\nexport type SolanaBalanceInfo = {\n balance: bigint;\n balanceUSD: string;\n isLow: boolean;\n isEmpty: boolean;\n walletAddress: string;\n};\n\n/** Result from checkSufficient() */\nexport type SolanaSufficiencyResult = {\n sufficient: boolean;\n info: SolanaBalanceInfo;\n shortfall?: string;\n};\n\nexport class SolanaBalanceMonitor {\n private readonly rpc: ReturnType<typeof createSolanaRpc>;\n private readonly walletAddress: string;\n private cachedBalance: bigint | null = null;\n private cachedAt = 0;\n\n constructor(walletAddress: string, rpcUrl?: string) {\n this.walletAddress = walletAddress;\n const url = rpcUrl || process[\"env\"].CLAWROUTER_SOLANA_RPC_URL || SOLANA_DEFAULT_RPC;\n this.rpc = createSolanaRpc(url);\n }\n\n async checkBalance(): Promise<SolanaBalanceInfo> {\n const now = Date.now();\n if (\n this.cachedBalance !== null &&\n this.cachedBalance > 0n &&\n now - this.cachedAt < CACHE_TTL_MS\n ) {\n return this.buildInfo(this.cachedBalance);\n }\n // Zero balance is never cached — always re-fetch so a funded wallet is\n // detected on the next request without waiting for cache expiry.\n const balance = await this.fetchBalance();\n if (balance > 0n) {\n this.cachedBalance = balance;\n this.cachedAt = now;\n }\n return this.buildInfo(balance);\n }\n\n deductEstimated(amountMicros: bigint): void {\n if (this.cachedBalance !== null && this.cachedBalance >= amountMicros) {\n this.cachedBalance -= amountMicros;\n }\n }\n\n invalidate(): void {\n this.cachedBalance = null;\n this.cachedAt = 0;\n }\n\n async refresh(): Promise<SolanaBalanceInfo> {\n this.invalidate();\n return this.checkBalance();\n }\n\n /**\n * Check if balance is sufficient for an estimated cost.\n */\n async checkSufficient(estimatedCostMicros: bigint): Promise<SolanaSufficiencyResult> {\n const info = await this.checkBalance();\n if (info.balance >= estimatedCostMicros) {\n return { sufficient: true, info };\n }\n const shortfall = estimatedCostMicros - info.balance;\n return {\n sufficient: false,\n info,\n shortfall: this.formatUSDC(shortfall),\n };\n }\n\n /**\n * Format USDC amount (in micros) as \"$X.XX\".\n */\n formatUSDC(amountMicros: bigint): string {\n const dollars = Number(amountMicros) / 1_000_000;\n return `$${dollars.toFixed(2)}`;\n }\n\n getWalletAddress(): string {\n return this.walletAddress;\n }\n\n private async fetchBalance(): Promise<bigint> {\n const owner = solAddress(this.walletAddress);\n const mint = solAddress(SOLANA_USDC_MINT);\n\n // The public Solana RPC frequently returns empty token account lists even\n // for funded wallets. Retry once on empty before accepting $0 as truth.\n for (let attempt = 0; attempt < 2; attempt++) {\n const result = await this.fetchBalanceOnce(owner, mint);\n if (result > 0n || attempt === 1) return result;\n await new Promise((r) => setTimeout(r, 1_000));\n }\n return 0n;\n }\n\n private async fetchBalanceOnce(\n owner: ReturnType<typeof solAddress>,\n mint: ReturnType<typeof solAddress>,\n ): Promise<bigint> {\n const controller = new AbortController();\n const timer = setTimeout(() => controller.abort(), BALANCE_TIMEOUT_MS);\n\n try {\n const response = await this.rpc\n .getTokenAccountsByOwner(owner, { mint }, { encoding: \"jsonParsed\" })\n .send({ abortSignal: controller.signal });\n\n if (response.value.length === 0) return 0n;\n\n let total = 0n;\n for (const account of response.value) {\n const parsed = account.account.data as {\n parsed: { info: { tokenAmount: { amount: string } } };\n };\n total += BigInt(parsed.parsed.info.tokenAmount.amount);\n }\n return total;\n } catch (err) {\n throw new Error(\n `Failed to fetch Solana USDC balance: ${err instanceof Error ? err.message : String(err)}`,\n { cause: err },\n );\n } finally {\n clearTimeout(timer);\n }\n }\n\n private buildInfo(balance: bigint): SolanaBalanceInfo {\n const dollars = Number(balance) / 1_000_000;\n return {\n balance,\n balanceUSD: `$${dollars.toFixed(2)}`,\n isLow: balance < 1_000_000n,\n isEmpty: balance < 100n,\n walletAddress: this.walletAddress,\n };\n }\n}\n","/**\n * Usage Statistics Aggregator\n *\n * Reads usage log files and aggregates statistics for terminal display.\n * Supports filtering by date range and provides multiple aggregation views.\n */\n\nimport { readdir, unlink } from \"node:fs/promises\";\nimport { readTextFile } from \"./fs-read\";\nimport { join } from \"node:path\";\nimport { homedir } from \"node:os\";\nimport type { UsageEntry } from \"./logger\";\nimport { VERSION } from \"./version\";\n\nconst LOG_DIR = join(homedir(), \".openclaw\", \"ckcloud\", \"logs\");\n\nexport type DailyStats = {\n date: string;\n totalRequests: number;\n totalCost: number;\n totalBaselineCost: number;\n totalSavings: number;\n avgLatencyMs: number;\n byTier: Record<string, { count: number; cost: number }>;\n byModel: Record<string, { count: number; cost: number }>;\n};\n\nexport type AggregatedStats = {\n period: string;\n totalRequests: number;\n totalCost: number;\n totalBaselineCost: number;\n totalSavings: number;\n savingsPercentage: number;\n avgLatencyMs: number;\n avgCostPerRequest: number;\n byTier: Record<string, { count: number; cost: number; percentage: number }>;\n byModel: Record<string, { count: number; cost: number; percentage: number }>;\n dailyBreakdown: DailyStats[];\n entriesWithBaseline: number; // Entries with valid baseline tracking\n};\n\n/**\n * Parse a JSONL log file into usage entries.\n * Handles both old format (without tier/baselineCost) and new format.\n */\nasync function parseLogFile(filePath: string): Promise<UsageEntry[]> {\n try {\n const content = await readTextFile(filePath);\n const lines = content.trim().split(\"\\n\").filter(Boolean);\n const entries: UsageEntry[] = [];\n for (const line of lines) {\n try {\n const entry = JSON.parse(line) as Partial<UsageEntry>;\n entries.push({\n timestamp: entry.timestamp || new Date().toISOString(),\n model: entry.model || \"unknown\",\n tier: entry.tier || \"UNKNOWN\",\n cost: entry.cost || 0,\n baselineCost: entry.baselineCost || entry.cost || 0,\n savings: entry.savings || 0,\n latencyMs: entry.latencyMs || 0,\n });\n } catch {\n // Skip malformed lines, keep valid ones\n }\n }\n return entries;\n } catch {\n return [];\n }\n}\n\n/**\n * Get list of available log files sorted by date (newest first).\n */\nasync function getLogFiles(): Promise<string[]> {\n try {\n const files = await readdir(LOG_DIR);\n return files\n .filter((f) => f.startsWith(\"usage-\") && f.endsWith(\".jsonl\"))\n .sort()\n .reverse();\n } catch {\n return [];\n }\n}\n\n/**\n * Aggregate stats for a single day.\n */\nfunction aggregateDay(date: string, entries: UsageEntry[]): DailyStats {\n const byTier: Record<string, { count: number; cost: number }> = {};\n const byModel: Record<string, { count: number; cost: number }> = {};\n let totalLatency = 0;\n\n for (const entry of entries) {\n // By tier\n if (!byTier[entry.tier]) byTier[entry.tier] = { count: 0, cost: 0 };\n byTier[entry.tier].count++;\n byTier[entry.tier].cost += entry.cost;\n\n // By model\n if (!byModel[entry.model]) byModel[entry.model] = { count: 0, cost: 0 };\n byModel[entry.model].count++;\n byModel[entry.model].cost += entry.cost;\n\n totalLatency += entry.latencyMs;\n }\n\n const totalCost = entries.reduce((sum, e) => sum + e.cost, 0);\n const totalBaselineCost = entries.reduce((sum, e) => sum + e.baselineCost, 0);\n\n return {\n date,\n totalRequests: entries.length,\n totalCost,\n totalBaselineCost,\n totalSavings: totalBaselineCost - totalCost,\n avgLatencyMs: entries.length > 0 ? totalLatency / entries.length : 0,\n byTier,\n byModel,\n };\n}\n\n/**\n * Get aggregated statistics for the last N days.\n */\nexport async function getStats(days: number = 7): Promise<AggregatedStats> {\n const logFiles = await getLogFiles();\n const filesToRead = logFiles.slice(0, days);\n\n const dailyBreakdown: DailyStats[] = [];\n const allByTier: Record<string, { count: number; cost: number }> = {};\n const allByModel: Record<string, { count: number; cost: number }> = {};\n let totalRequests = 0;\n let totalCost = 0;\n let totalBaselineCost = 0;\n let totalLatency = 0;\n\n for (const file of filesToRead) {\n const date = file.replace(\"usage-\", \"\").replace(\".jsonl\", \"\");\n const filePath = join(LOG_DIR, file);\n const entries = await parseLogFile(filePath);\n\n if (entries.length === 0) continue;\n\n const dayStats = aggregateDay(date, entries);\n dailyBreakdown.push(dayStats);\n\n totalRequests += dayStats.totalRequests;\n totalCost += dayStats.totalCost;\n totalBaselineCost += dayStats.totalBaselineCost;\n totalLatency += dayStats.avgLatencyMs * dayStats.totalRequests;\n\n // Merge tier stats\n for (const [tier, stats] of Object.entries(dayStats.byTier)) {\n if (!allByTier[tier]) allByTier[tier] = { count: 0, cost: 0 };\n allByTier[tier].count += stats.count;\n allByTier[tier].cost += stats.cost;\n }\n\n // Merge model stats\n for (const [model, stats] of Object.entries(dayStats.byModel)) {\n if (!allByModel[model]) allByModel[model] = { count: 0, cost: 0 };\n allByModel[model].count += stats.count;\n allByModel[model].cost += stats.cost;\n }\n }\n\n // Calculate percentages\n const byTierWithPercentage: Record<string, { count: number; cost: number; percentage: number }> =\n {};\n for (const [tier, stats] of Object.entries(allByTier)) {\n byTierWithPercentage[tier] = {\n ...stats,\n percentage: totalRequests > 0 ? (stats.count / totalRequests) * 100 : 0,\n };\n }\n\n const byModelWithPercentage: Record<string, { count: number; cost: number; percentage: number }> =\n {};\n for (const [model, stats] of Object.entries(allByModel)) {\n byModelWithPercentage[model] = {\n ...stats,\n percentage: totalRequests > 0 ? (stats.count / totalRequests) * 100 : 0,\n };\n }\n\n const totalSavings = totalBaselineCost - totalCost;\n const savingsPercentage = totalBaselineCost > 0 ? (totalSavings / totalBaselineCost) * 100 : 0;\n\n // Count entries with valid baseline tracking (baseline != cost means tracking was active)\n let entriesWithBaseline = 0;\n for (const day of dailyBreakdown) {\n if (day.totalBaselineCost !== day.totalCost) {\n entriesWithBaseline += day.totalRequests;\n }\n }\n\n return {\n period: days === 1 ? \"today\" : `last ${days} days`,\n totalRequests,\n totalCost,\n totalBaselineCost,\n totalSavings,\n savingsPercentage,\n avgLatencyMs: totalRequests > 0 ? totalLatency / totalRequests : 0,\n avgCostPerRequest: totalRequests > 0 ? totalCost / totalRequests : 0,\n byTier: byTierWithPercentage,\n byModel: byModelWithPercentage,\n dailyBreakdown: dailyBreakdown.reverse(), // Oldest first for charts\n entriesWithBaseline, // How many entries have valid baseline tracking\n };\n}\n\n/**\n * Format stats as ASCII table for terminal display.\n */\nexport function formatStatsAscii(stats: AggregatedStats): string {\n const lines: string[] = [];\n\n // Header\n lines.push(\"╔════════════════════════════════════════════════════════════╗\");\n lines.push(`║ ckcloud by ckcloud v${VERSION}`.padEnd(61) + \"║\");\n lines.push(\"║ Usage Statistics ║\");\n lines.push(\"╠════════════════════════════════════════════════════════════╣\");\n\n // Summary\n lines.push(`║ Period: ${stats.period.padEnd(49)}║`);\n lines.push(`║ Total Requests: ${stats.totalRequests.toString().padEnd(41)}║`);\n lines.push(`║ Total Cost: $${stats.totalCost.toFixed(4).padEnd(43)}║`);\n lines.push(`║ Baseline Cost (Opus 4.5): $${stats.totalBaselineCost.toFixed(4).padEnd(30)}║`);\n\n // Show savings with note if some entries lack baseline tracking\n const savingsLine = `║ 💰 Total Saved: $${stats.totalSavings.toFixed(4)} (${stats.savingsPercentage.toFixed(1)}%)`;\n if (stats.entriesWithBaseline < stats.totalRequests && stats.entriesWithBaseline > 0) {\n lines.push(savingsLine.padEnd(61) + \"║\");\n const note = `║ (based on ${stats.entriesWithBaseline}/${stats.totalRequests} tracked requests)`;\n lines.push(note.padEnd(61) + \"║\");\n } else {\n lines.push(savingsLine.padEnd(61) + \"║\");\n }\n lines.push(`║ Avg Latency: ${stats.avgLatencyMs.toFixed(0)}ms`.padEnd(61) + \"║\");\n\n // Tier breakdown\n lines.push(\"╠════════════════════════════════════════════════════════════╣\");\n lines.push(\"║ Routing by Tier: ║\");\n\n // Show all tiers found in data, ordered by known tiers first then others\n const knownTiers = [\"SIMPLE\", \"MEDIUM\", \"COMPLEX\", \"REASONING\", \"DIRECT\"];\n const allTiers = Object.keys(stats.byTier);\n const otherTiers = allTiers.filter((t) => !knownTiers.includes(t));\n const tierOrder = [...knownTiers.filter((t) => stats.byTier[t]), ...otherTiers];\n\n for (const tier of tierOrder) {\n const data = stats.byTier[tier];\n if (data) {\n const bar = \"█\".repeat(Math.min(20, Math.round(data.percentage / 5)));\n const displayTier = tier === \"UNKNOWN\" ? \"OTHER\" : tier;\n const line = `║ ${displayTier.padEnd(10)} ${bar.padEnd(20)} ${data.percentage.toFixed(1).padStart(5)}% (${data.count})`;\n lines.push(line.padEnd(61) + \"║\");\n }\n }\n\n // Top models\n lines.push(\"╠════════════════════════════════════════════════════════════╣\");\n lines.push(\"║ Top Models: ║\");\n\n const sortedModels = Object.entries(stats.byModel)\n .sort((a, b) => b[1].count - a[1].count)\n .slice(0, 5);\n\n for (const [model, data] of sortedModels) {\n const shortModel = model.length > 25 ? model.slice(0, 22) + \"...\" : model;\n const line = `║ ${shortModel.padEnd(25)} ${data.count.toString().padStart(5)} reqs $${data.cost.toFixed(4)}`;\n lines.push(line.padEnd(61) + \"║\");\n }\n\n // Daily breakdown (last 7 days)\n if (stats.dailyBreakdown.length > 0) {\n lines.push(\"╠════════════════════════════════════════════════════════════╣\");\n lines.push(\"║ Daily Breakdown: ║\");\n lines.push(\"║ Date Requests Cost Saved ║\");\n\n for (const day of stats.dailyBreakdown.slice(-7)) {\n const saved = day.totalBaselineCost - day.totalCost;\n const line = `║ ${day.date} ${day.totalRequests.toString().padStart(6)} $${day.totalCost.toFixed(4).padStart(8)} $${saved.toFixed(4)}`;\n lines.push(line.padEnd(61) + \"║\");\n }\n }\n\n lines.push(\"╚════════════════════════════════════════════════════════════╝\");\n\n return lines.join(\"\\n\");\n}\n\n/**\n * Delete all usage log files, resetting stats to zero.\n */\nexport async function clearStats(): Promise<{ deletedFiles: number }> {\n try {\n const files = await readdir(LOG_DIR);\n const logFiles = files.filter((f) => f.startsWith(\"usage-\") && f.endsWith(\".jsonl\"));\n\n await Promise.all(logFiles.map((f) => unlink(join(LOG_DIR, f))));\n\n return { deletedFiles: logFiles.length };\n } catch {\n return { deletedFiles: 0 };\n }\n}\n","/**\n * Usage Logger\n *\n * Logs every LLM request as a JSON line to a daily log file.\n * Files: ~/.openclaw/ckcloud/logs/usage-YYYY-MM-DD.jsonl\n *\n * MVP: append-only JSON lines. No rotation, no cleanup.\n * Logging never breaks the request flow — all errors are swallowed.\n */\n\nimport { appendFile, mkdir } from \"node:fs/promises\";\nimport { join } from \"node:path\";\nimport { homedir } from \"node:os\";\n\nexport type UsageEntry = {\n timestamp: string;\n model: string;\n tier: string;\n cost: number;\n baselineCost: number;\n savings: number; // 0-1 percentage\n latencyMs: number;\n /** Input (prompt) tokens reported by the provider */\n inputTokens?: number;\n /** Partner service ID (e.g., \"x_users_lookup\") — only set for partner API calls */\n partnerId?: string;\n /** Partner service name (e.g., \"AttentionVC\") — only set for partner API calls */\n service?: string;\n};\n\nconst LOG_DIR = join(homedir(), \".openclaw\", \"ckcloud\", \"logs\");\nlet dirReady = false;\n\nasync function ensureDir(): Promise<void> {\n if (dirReady) return;\n await mkdir(LOG_DIR, { recursive: true });\n dirReady = true;\n}\n\n/**\n * Log a usage entry as a JSON line.\n */\nexport async function logUsage(entry: UsageEntry): Promise<void> {\n try {\n await ensureDir();\n const date = entry.timestamp.slice(0, 10); // YYYY-MM-DD\n const file = join(LOG_DIR, `usage-${date}.jsonl`);\n await appendFile(file, JSON.stringify(entry) + \"\\n\");\n } catch {\n // Never break the request flow\n }\n}\n","/**\n * Plugin logger module.\n * Provides a centralized logger that can be set to use OpenClaw's api.logger.\n * Defaults to console if not set.\n */\n\nimport type { PluginLogger } from \"./types.js\";\n\nlet pluginLogger: PluginLogger = console;\n\nexport function setPluginLogger(logger: PluginLogger): void {\n pluginLogger = logger ?? console;\n}\n\nexport function getPluginLogger(): PluginLogger {\n return pluginLogger;\n}\n\n// Convenience methods\nexport const logger = {\n debug: (message: string) => pluginLogger.debug?.(message),\n info: (message: string) => pluginLogger.info(message),\n warn: (message: string) => pluginLogger.warn(message),\n error: (message: string) => pluginLogger.error(message),\n};","/**\n * Session Persistence Store\n *\n * Tracks model selections per session to prevent model switching mid-task.\n * When a session is active, the router will continue using the same model\n * instead of re-routing each request.\n */\n\nimport { createHash } from \"node:crypto\";\n\nexport type SessionEntry = {\n model: string;\n tier: string;\n createdAt: number;\n lastUsedAt: number;\n requestCount: number;\n // --- Three-strike escalation ---\n recentHashes: string[]; // Sliding window of last 3 request content fingerprints\n strikes: number; // Consecutive similar request count\n escalated: boolean; // Whether session was already escalated via three-strike\n};\n\nexport type SessionConfig = {\n /** Enable session persistence (default: false) */\n enabled: boolean;\n /** Session timeout in ms (default: 30 minutes) */\n timeoutMs: number;\n /** Header name for session ID (default: X-Session-ID) */\n headerName: string;\n};\n\nexport const DEFAULT_SESSION_CONFIG: SessionConfig = {\n enabled: true,\n timeoutMs: 30 * 60 * 1000, // 30 minutes\n headerName: \"x-session-id\",\n};\n\n/**\n * Session persistence store for maintaining model selections.\n */\nexport class SessionStore {\n private sessions: Map<string, SessionEntry> = new Map();\n private config: SessionConfig;\n private cleanupInterval: ReturnType<typeof setInterval> | null = null;\n\n constructor(config: Partial<SessionConfig> = {}) {\n this.config = { ...DEFAULT_SESSION_CONFIG, ...config };\n\n // Start cleanup interval (every 5 minutes)\n if (this.config.enabled) {\n this.cleanupInterval = setInterval(() => this.cleanup(), 5 * 60 * 1000);\n }\n }\n\n /**\n * Get the pinned model for a session, if any.\n */\n getSession(sessionId: string): SessionEntry | undefined {\n if (!this.config.enabled || !sessionId) {\n return undefined;\n }\n\n const entry = this.sessions.get(sessionId);\n if (!entry) {\n return undefined;\n }\n\n // Check if session has expired\n const now = Date.now();\n if (now - entry.lastUsedAt > this.config.timeoutMs) {\n this.sessions.delete(sessionId);\n return undefined;\n }\n\n return entry;\n }\n\n /**\n * Pin a model to a session.\n */\n setSession(sessionId: string, model: string, tier: string): void {\n if (!this.config.enabled || !sessionId) {\n return;\n }\n\n const existing = this.sessions.get(sessionId);\n const now = Date.now();\n\n if (existing) {\n existing.lastUsedAt = now;\n existing.requestCount++;\n // Update model if different (e.g., fallback)\n if (existing.model !== model) {\n existing.model = model;\n existing.tier = tier;\n }\n } else {\n this.sessions.set(sessionId, {\n model,\n tier,\n createdAt: now,\n lastUsedAt: now,\n requestCount: 1,\n recentHashes: [],\n strikes: 0,\n escalated: false,\n });\n }\n }\n\n /**\n * Touch a session to extend its timeout.\n */\n touchSession(sessionId: string): void {\n if (!this.config.enabled || !sessionId) {\n return;\n }\n\n const entry = this.sessions.get(sessionId);\n if (entry) {\n entry.lastUsedAt = Date.now();\n entry.requestCount++;\n }\n }\n\n /**\n * Clear a specific session.\n */\n clearSession(sessionId: string): void {\n this.sessions.delete(sessionId);\n }\n\n /**\n * Clear all sessions.\n */\n clearAll(): void {\n this.sessions.clear();\n }\n\n /**\n * Get session stats for debugging.\n */\n getStats(): { count: number; sessions: Array<{ id: string; model: string; age: number }> } {\n const now = Date.now();\n const sessions = Array.from(this.sessions.entries()).map(([id, entry]) => ({\n id: id.slice(0, 8) + \"...\",\n model: entry.model,\n age: Math.round((now - entry.createdAt) / 1000),\n }));\n return { count: this.sessions.size, sessions };\n }\n\n /**\n * Clean up expired sessions.\n */\n private cleanup(): void {\n const now = Date.now();\n for (const [id, entry] of this.sessions) {\n if (now - entry.lastUsedAt > this.config.timeoutMs) {\n this.sessions.delete(id);\n }\n }\n }\n\n /**\n * Record a request content hash and detect repetitive patterns.\n * Returns true if escalation should be triggered (3+ consecutive similar requests).\n */\n recordRequestHash(sessionId: string, hash: string): boolean {\n const entry = this.sessions.get(sessionId);\n if (!entry) return false;\n\n const prev = entry.recentHashes;\n if (prev.length > 0 && prev[prev.length - 1] === hash) {\n entry.strikes++;\n } else {\n entry.strikes = 0;\n }\n\n entry.recentHashes.push(hash);\n if (entry.recentHashes.length > 3) {\n entry.recentHashes.shift();\n }\n\n return entry.strikes >= 2 && !entry.escalated;\n }\n\n /**\n * Escalate session to next tier. Returns the new model/tier or null if already at max.\n */\n escalateSession(\n sessionId: string,\n tierConfigs: Record<string, { primary: string; fallback: string[] }>,\n ): { model: string; tier: string } | null {\n const entry = this.sessions.get(sessionId);\n if (!entry) return null;\n\n const TIER_ORDER = [\"SIMPLE\", \"MEDIUM\", \"COMPLEX\", \"REASONING\"];\n const currentIdx = TIER_ORDER.indexOf(entry.tier);\n if (currentIdx < 0 || currentIdx >= TIER_ORDER.length - 1) return null;\n\n const nextTier = TIER_ORDER[currentIdx + 1];\n const nextConfig = tierConfigs[nextTier];\n if (!nextConfig) return null;\n\n entry.model = nextConfig.primary;\n entry.tier = nextTier;\n entry.strikes = 0;\n entry.escalated = true;\n\n return { model: nextConfig.primary, tier: nextTier };\n }\n\n /**\n * Stop the cleanup interval.\n */\n close(): void {\n if (this.cleanupInterval) {\n clearInterval(this.cleanupInterval);\n this.cleanupInterval = null;\n }\n }\n}\n\n/**\n * Generate a session ID from request headers or create a default.\n */\nexport function getSessionId(\n headers: Record<string, string | string[] | undefined>,\n headerName: string = DEFAULT_SESSION_CONFIG.headerName,\n): string | undefined {\n const value = headers[headerName] || headers[headerName.toLowerCase()];\n if (typeof value === \"string\" && value.length > 0) {\n return value;\n }\n if (Array.isArray(value) && value.length > 0) {\n return value[0];\n }\n return undefined;\n}\n\n/**\n * Derive a stable session ID from message content when no explicit session\n * header is provided. Uses the first user message as the conversation anchor —\n * same opening message = same session ID across all subsequent turns.\n *\n * This prevents model-switching mid-conversation even when OpenClaw doesn't\n * send an x-session-id header (which is the default OpenClaw behaviour).\n */\nexport function deriveSessionId(\n messages: Array<{ role: string; content: unknown }>,\n): string | undefined {\n const firstUser = messages.find((m) => m.role === \"user\");\n if (!firstUser) return undefined;\n\n const content =\n typeof firstUser.content === \"string\" ? firstUser.content : JSON.stringify(firstUser.content);\n\n // 8-char hex prefix of SHA-256 — short enough for logs, collision-resistant\n // enough for session tracking within a single gateway instance.\n return createHash(\"sha256\").update(content).digest(\"hex\").slice(0, 8);\n}\n\n/**\n * Generate a short hash fingerprint from request content.\n * Captures: last user message text + tool call names (if any).\n * Normalizes whitespace to avoid false negatives from minor formatting diffs.\n */\nexport function hashRequestContent(lastUserContent: string, toolCallNames?: string[]): string {\n const normalized = lastUserContent.replace(/\\s+/g, \" \").trim().slice(0, 500);\n const toolSuffix = toolCallNames?.length ? `|tools:${toolCallNames.sort().join(\",\")}` : \"\";\n return createHash(\"sha256\")\n .update(normalized + toolSuffix)\n .digest(\"hex\")\n .slice(0, 12);\n}\n","/**\n * Rule-Based Classifier (v2 — Weighted Scoring)\n *\n * Scores a request across 14 weighted dimensions and maps the aggregate\n * score to a tier using configurable boundaries. Confidence is calibrated\n * via sigmoid — low confidence triggers the fallback classifier.\n *\n * Handles 70-80% of requests in < 1ms with zero cost.\n */\n\nimport type { Tier, ScoringResult, ScoringConfig } from \"./types.js\";\n\ntype DimensionScore = { name: string; score: number; signal: string | null };\n\n// ─── Dimension Scorers ───\n// Each returns a score in [-1, 1] and an optional signal string.\n\nfunction scoreTokenCount(\n estimatedTokens: number,\n thresholds: { simple: number; complex: number },\n): DimensionScore {\n if (estimatedTokens < thresholds.simple) {\n return { name: \"tokenCount\", score: -1.0, signal: `short (${estimatedTokens} tokens)` };\n }\n if (estimatedTokens > thresholds.complex) {\n return { name: \"tokenCount\", score: 1.0, signal: `long (${estimatedTokens} tokens)` };\n }\n return { name: \"tokenCount\", score: 0, signal: null };\n}\n\nfunction scoreKeywordMatch(\n text: string,\n keywords: string[],\n name: string,\n signalLabel: string,\n thresholds: { low: number; high: number },\n scores: { none: number; low: number; high: number },\n): DimensionScore {\n const matches = keywords.filter((kw) => text.includes(kw.toLowerCase()));\n if (matches.length >= thresholds.high) {\n return {\n name,\n score: scores.high,\n signal: `${signalLabel} (${matches.slice(0, 3).join(\", \")})`,\n };\n }\n if (matches.length >= thresholds.low) {\n return {\n name,\n score: scores.low,\n signal: `${signalLabel} (${matches.slice(0, 3).join(\", \")})`,\n };\n }\n return { name, score: scores.none, signal: null };\n}\n\nfunction scoreMultiStep(text: string): DimensionScore {\n const patterns = [/first.*then/i, /step \\d/i, /\\d\\.\\s/];\n const hits = patterns.filter((p) => p.test(text));\n if (hits.length > 0) {\n return { name: \"multiStepPatterns\", score: 0.5, signal: \"multi-step\" };\n }\n return { name: \"multiStepPatterns\", score: 0, signal: null };\n}\n\nfunction scoreQuestionComplexity(prompt: string): DimensionScore {\n const count = (prompt.match(/\\?/g) || []).length;\n if (count > 3) {\n return { name: \"questionComplexity\", score: 0.5, signal: `${count} questions` };\n }\n return { name: \"questionComplexity\", score: 0, signal: null };\n}\n\n/**\n * Score agentic task indicators.\n * Returns agenticScore (0-1) based on keyword matches:\n * - 4+ matches = 1.0 (high agentic)\n * - 3 matches = 0.6 (moderate agentic, triggers auto-agentic mode)\n * - 1-2 matches = 0.2 (low agentic)\n *\n * Thresholds raised because common keywords were pruned from the list.\n */\nfunction scoreAgenticTask(\n text: string,\n keywords: string[],\n): { dimensionScore: DimensionScore; agenticScore: number } {\n let matchCount = 0;\n const signals: string[] = [];\n\n for (const keyword of keywords) {\n if (text.includes(keyword.toLowerCase())) {\n matchCount++;\n if (signals.length < 3) {\n signals.push(keyword);\n }\n }\n }\n\n // Threshold-based scoring (raised thresholds after keyword pruning)\n if (matchCount >= 4) {\n return {\n dimensionScore: {\n name: \"agenticTask\",\n score: 1.0,\n signal: `agentic (${signals.join(\", \")})`,\n },\n agenticScore: 1.0,\n };\n } else if (matchCount >= 3) {\n return {\n dimensionScore: {\n name: \"agenticTask\",\n score: 0.6,\n signal: `agentic (${signals.join(\", \")})`,\n },\n agenticScore: 0.6,\n };\n } else if (matchCount >= 1) {\n return {\n dimensionScore: {\n name: \"agenticTask\",\n score: 0.2,\n signal: `agentic-light (${signals.join(\", \")})`,\n },\n agenticScore: 0.2,\n };\n }\n\n return {\n dimensionScore: { name: \"agenticTask\", score: 0, signal: null },\n agenticScore: 0,\n };\n}\n\n// ─── Main Classifier ───\n\nexport function classifyByRules(\n prompt: string,\n systemPrompt: string | undefined,\n estimatedTokens: number,\n config: ScoringConfig,\n): ScoringResult {\n // Score against user prompt only — system prompts contain boilerplate keywords\n // (tool definitions, skill descriptions, behavioral rules) that dominate scoring\n // and make every request score identically. See GitHub issue #50.\n const userText = prompt.toLowerCase();\n\n // Score all 14 dimensions against user text only\n const dimensions: DimensionScore[] = [\n // Token count uses total estimated tokens (system + user) — context size matters for model selection\n scoreTokenCount(estimatedTokens, config.tokenCountThresholds),\n scoreKeywordMatch(\n userText,\n config.codeKeywords,\n \"codePresence\",\n \"code\",\n { low: 1, high: 2 },\n { none: 0, low: 0.5, high: 1.0 },\n ),\n scoreKeywordMatch(\n userText,\n config.reasoningKeywords,\n \"reasoningMarkers\",\n \"reasoning\",\n { low: 1, high: 2 },\n { none: 0, low: 0.7, high: 1.0 },\n ),\n scoreKeywordMatch(\n userText,\n config.technicalKeywords,\n \"technicalTerms\",\n \"technical\",\n { low: 2, high: 4 },\n { none: 0, low: 0.5, high: 1.0 },\n ),\n scoreKeywordMatch(\n userText,\n config.creativeKeywords,\n \"creativeMarkers\",\n \"creative\",\n { low: 1, high: 2 },\n { none: 0, low: 0.5, high: 0.7 },\n ),\n scoreKeywordMatch(\n userText,\n config.simpleKeywords,\n \"simpleIndicators\",\n \"simple\",\n { low: 1, high: 2 },\n { none: 0, low: -1.0, high: -1.0 },\n ),\n scoreMultiStep(userText),\n scoreQuestionComplexity(prompt),\n\n // 6 new dimensions\n scoreKeywordMatch(\n userText,\n config.imperativeVerbs,\n \"imperativeVerbs\",\n \"imperative\",\n { low: 1, high: 2 },\n { none: 0, low: 0.3, high: 0.5 },\n ),\n scoreKeywordMatch(\n userText,\n config.constraintIndicators,\n \"constraintCount\",\n \"constraints\",\n { low: 1, high: 3 },\n { none: 0, low: 0.3, high: 0.7 },\n ),\n scoreKeywordMatch(\n userText,\n config.outputFormatKeywords,\n \"outputFormat\",\n \"format\",\n { low: 1, high: 2 },\n { none: 0, low: 0.4, high: 0.7 },\n ),\n scoreKeywordMatch(\n userText,\n config.referenceKeywords,\n \"referenceComplexity\",\n \"references\",\n { low: 1, high: 2 },\n { none: 0, low: 0.3, high: 0.5 },\n ),\n scoreKeywordMatch(\n userText,\n config.negationKeywords,\n \"negationComplexity\",\n \"negation\",\n { low: 2, high: 3 },\n { none: 0, low: 0.3, high: 0.5 },\n ),\n scoreKeywordMatch(\n userText,\n config.domainSpecificKeywords,\n \"domainSpecificity\",\n \"domain-specific\",\n { low: 1, high: 2 },\n { none: 0, low: 0.5, high: 0.8 },\n ),\n ];\n\n // Score agentic task indicators — user prompt only\n // System prompt describes assistant behavior, not user's intent.\n // e.g. a coding assistant system prompt with \"edit files\" / \"fix bugs\" should NOT\n // force every request into agentic mode.\n const agenticResult = scoreAgenticTask(userText, config.agenticTaskKeywords);\n dimensions.push(agenticResult.dimensionScore);\n const agenticScore = agenticResult.agenticScore;\n\n // Collect signals\n const signals = dimensions.filter((d) => d.signal !== null).map((d) => d.signal!);\n\n // Compute weighted score\n const weights = config.dimensionWeights;\n let weightedScore = 0;\n for (const d of dimensions) {\n const w = weights[d.name] ?? 0;\n weightedScore += d.score * w;\n }\n\n // Count reasoning markers for override — only check USER prompt, not system prompt\n // This prevents system prompts with \"step by step\" from triggering REASONING for simple queries\n const reasoningMatches = config.reasoningKeywords.filter((kw) =>\n userText.includes(kw.toLowerCase()),\n );\n\n // Direct reasoning override: 2+ reasoning markers = high confidence REASONING\n if (reasoningMatches.length >= 2) {\n const confidence = calibrateConfidence(\n Math.max(weightedScore, 0.3), // ensure positive for confidence calc\n config.confidenceSteepness,\n );\n return {\n score: weightedScore,\n tier: \"REASONING\",\n confidence: Math.max(confidence, 0.85),\n signals,\n agenticScore,\n dimensions,\n };\n }\n\n // Map weighted score to tier using boundaries\n const { simpleMedium, mediumComplex, complexReasoning } = config.tierBoundaries;\n let tier: Tier;\n let distanceFromBoundary: number;\n\n if (weightedScore < simpleMedium) {\n tier = \"SIMPLE\";\n distanceFromBoundary = simpleMedium - weightedScore;\n } else if (weightedScore < mediumComplex) {\n tier = \"MEDIUM\";\n distanceFromBoundary = Math.min(weightedScore - simpleMedium, mediumComplex - weightedScore);\n } else if (weightedScore < complexReasoning) {\n tier = \"COMPLEX\";\n distanceFromBoundary = Math.min(\n weightedScore - mediumComplex,\n complexReasoning - weightedScore,\n );\n } else {\n tier = \"REASONING\";\n distanceFromBoundary = weightedScore - complexReasoning;\n }\n\n // Calibrate confidence via sigmoid of distance from nearest boundary\n const confidence = calibrateConfidence(distanceFromBoundary, config.confidenceSteepness);\n\n // If confidence is below threshold → ambiguous\n if (confidence < config.confidenceThreshold) {\n return { score: weightedScore, tier: null, confidence, signals, agenticScore, dimensions };\n }\n\n return { score: weightedScore, tier, confidence, signals, agenticScore, dimensions };\n}\n\n/**\n * Sigmoid confidence calibration.\n * Maps distance from tier boundary to [0.5, 1.0] confidence range.\n */\nfunction calibrateConfidence(distance: number, steepness: number): number {\n return 1 / (1 + Math.exp(-steepness * distance));\n}\n","/**\n * Tier → Model Selection\n *\n * Maps a classification tier to the cheapest capable model.\n * Builds RoutingDecision metadata with cost estimates and savings.\n */\n\nimport type { Tier, TierConfig, RoutingDecision } from \"./types.js\";\n\nexport type ModelPricing = {\n inputPrice: number; // per 1M tokens\n outputPrice: number; // per 1M tokens\n};\n\nconst BASELINE_MODEL_ID = \"anthropic/claude-opus-4.6\";\n\n// Hardcoded fallback: Claude Opus 4.6 pricing (per 1M tokens)\n// Used when baseline model not found in dynamic pricing map\nconst BASELINE_INPUT_PRICE = 5.0;\nconst BASELINE_OUTPUT_PRICE = 25.0;\n\n/**\n * Select the primary model for a tier and build the RoutingDecision.\n */\nexport function selectModel(\n tier: Tier,\n confidence: number,\n method: \"rules\" | \"llm\",\n reasoning: string,\n tierConfigs: Record<Tier, TierConfig>,\n modelPricing: Map<string, ModelPricing>,\n estimatedInputTokens: number,\n maxOutputTokens: number,\n routingProfile?: \"free\" | \"eco\" | \"auto\" | \"premium\",\n agenticScore?: number,\n): RoutingDecision {\n const tierConfig = tierConfigs[tier];\n const model = tierConfig.primary;\n const pricing = modelPricing.get(model);\n\n // Defensive: guard against undefined price fields (not just undefined pricing)\n const inputPrice = pricing?.inputPrice ?? 0;\n const outputPrice = pricing?.outputPrice ?? 0;\n const inputCost = (estimatedInputTokens / 1_000_000) * inputPrice;\n const outputCost = (maxOutputTokens / 1_000_000) * outputPrice;\n const costEstimate = inputCost + outputCost;\n\n // Baseline: what Claude Opus 4.5 would cost (the premium reference)\n const opusPricing = modelPricing.get(BASELINE_MODEL_ID);\n const opusInputPrice = opusPricing?.inputPrice ?? BASELINE_INPUT_PRICE;\n const opusOutputPrice = opusPricing?.outputPrice ?? BASELINE_OUTPUT_PRICE;\n const baselineInput = (estimatedInputTokens / 1_000_000) * opusInputPrice;\n const baselineOutput = (maxOutputTokens / 1_000_000) * opusOutputPrice;\n const baselineCost = baselineInput + baselineOutput;\n\n // Premium profile doesn't calculate savings (it's about quality, not cost)\n const savings =\n routingProfile === \"premium\"\n ? 0\n : baselineCost > 0\n ? Math.max(0, (baselineCost - costEstimate) / baselineCost)\n : 0;\n\n return {\n model,\n tier,\n confidence,\n method,\n reasoning,\n costEstimate,\n baselineCost,\n savings,\n ...(agenticScore !== undefined && { agenticScore }),\n };\n}\n\n/**\n * Get the ordered fallback chain for a tier: [primary, ...fallbacks].\n */\nexport function getFallbackChain(tier: Tier, tierConfigs: Record<Tier, TierConfig>): string[] {\n const config = tierConfigs[tier];\n return [config.primary, ...config.fallback];\n}\n\n/**\n * Calculate cost for a specific model (used when fallback model is used).\n * Returns updated cost fields for RoutingDecision.\n */\nexport function calculateModelCost(\n model: string,\n modelPricing: Map<string, ModelPricing>,\n estimatedInputTokens: number,\n maxOutputTokens: number,\n routingProfile?: \"free\" | \"eco\" | \"auto\" | \"premium\",\n): { costEstimate: number; baselineCost: number; savings: number } {\n const pricing = modelPricing.get(model);\n\n // Defensive: guard against undefined price fields (not just undefined pricing)\n const inputPrice = pricing?.inputPrice ?? 0;\n const outputPrice = pricing?.outputPrice ?? 0;\n const inputCost = (estimatedInputTokens / 1_000_000) * inputPrice;\n const outputCost = (maxOutputTokens / 1_000_000) * outputPrice;\n const costEstimate = inputCost + outputCost;\n\n // Baseline: what Claude Opus 4.5 would cost (the premium reference)\n const opusPricing = modelPricing.get(BASELINE_MODEL_ID);\n const opusInputPrice = opusPricing?.inputPrice ?? BASELINE_INPUT_PRICE;\n const opusOutputPrice = opusPricing?.outputPrice ?? BASELINE_OUTPUT_PRICE;\n const baselineInput = (estimatedInputTokens / 1_000_000) * opusInputPrice;\n const baselineOutput = (maxOutputTokens / 1_000_000) * opusOutputPrice;\n const baselineCost = baselineInput + baselineOutput;\n\n // Premium profile doesn't calculate savings (it's about quality, not cost)\n const savings =\n routingProfile === \"premium\"\n ? 0\n : baselineCost > 0\n ? Math.max(0, (baselineCost - costEstimate) / baselineCost)\n : 0;\n\n return { costEstimate, baselineCost, savings };\n}\n\n/**\n * Filter a model list to only those that support tool calling.\n * When hasTools is false, returns the list unchanged.\n * When all models lack tool calling support, returns the full list as a fallback\n * (better to let the API error than produce an empty chain).\n */\nexport function filterByToolCalling(\n models: string[],\n hasTools: boolean,\n supportsToolCalling: (modelId: string) => boolean,\n): string[] {\n if (!hasTools) return models;\n const filtered = models.filter(supportsToolCalling);\n return filtered.length > 0 ? filtered : models;\n}\n\n/**\n * Filter a model list to only those that support vision (image inputs).\n * When hasVision is false, returns the list unchanged.\n * When all models lack vision support, returns the full list as a fallback\n * (better to let the API error than produce an empty chain).\n */\nexport function filterByVision(\n models: string[],\n hasVision: boolean,\n supportsVision: (modelId: string) => boolean,\n): string[] {\n if (!hasVision) return models;\n const filtered = models.filter(supportsVision);\n return filtered.length > 0 ? filtered : models;\n}\n\n/**\n * Get the fallback chain filtered by context length.\n * Only returns models that can handle the estimated total context.\n *\n * @param tier - The tier to get fallback chain for\n * @param tierConfigs - Tier configurations\n * @param estimatedTotalTokens - Estimated total context (input + output)\n * @param getContextWindow - Function to get context window for a model ID\n * @returns Filtered list of models that can handle the context\n */\nexport function getFallbackChainFiltered(\n tier: Tier,\n tierConfigs: Record<Tier, TierConfig>,\n estimatedTotalTokens: number,\n getContextWindow: (modelId: string) => number | undefined,\n): string[] {\n const fullChain = getFallbackChain(tier, tierConfigs);\n\n // Filter to models that can handle the context\n const filtered = fullChain.filter((modelId) => {\n const contextWindow = getContextWindow(modelId);\n if (contextWindow === undefined) {\n // Unknown model - include it (let API reject if needed)\n return true;\n }\n // Add 10% buffer for safety\n return contextWindow >= estimatedTotalTokens * 1.1;\n });\n\n // If all models filtered out, return the original chain\n // (let the API error out - better than no options)\n if (filtered.length === 0) {\n return fullChain;\n }\n\n return filtered;\n}\n","/**\n * Default Routing Config\n *\n * All routing parameters as a TypeScript constant.\n * Operators override via openclaw.yaml plugin config.\n *\n * Scoring uses 14 weighted dimensions with sigmoid confidence calibration.\n */\n\nimport type { RoutingConfig } from \"./types.js\";\n\nexport const DEFAULT_ROUTING_CONFIG: RoutingConfig = {\n version: \"2.0\",\n\n classifier: {\n llmModel: \"google/gemini-2.5-flash\",\n llmMaxTokens: 10,\n llmTemperature: 0,\n promptTruncationChars: 500,\n cacheTtlMs: 3_600_000, // 1 hour\n },\n\n scoring: {\n tokenCountThresholds: { simple: 50, complex: 500 },\n\n // Multilingual keywords: EN + ZH + JA + RU + DE + ES + PT + KO + AR\n codeKeywords: [\n // English\n \"function\",\n \"class\",\n \"import\",\n \"def\",\n \"SELECT\",\n \"async\",\n \"await\",\n \"const\",\n \"let\",\n \"var\",\n \"return\",\n \"```\",\n // Chinese\n \"函数\",\n \"类\",\n \"导入\",\n \"定义\",\n \"查询\",\n \"异步\",\n \"等待\",\n \"常量\",\n \"变量\",\n \"返回\",\n // Japanese\n \"関数\",\n \"クラス\",\n \"インポート\",\n \"非同期\",\n \"定数\",\n \"変数\",\n // Russian\n \"функция\",\n \"класс\",\n \"импорт\",\n \"определ\",\n \"запрос\",\n \"асинхронный\",\n \"ожидать\",\n \"константа\",\n \"переменная\",\n \"вернуть\",\n // German\n \"funktion\",\n \"klasse\",\n \"importieren\",\n \"definieren\",\n \"abfrage\",\n \"asynchron\",\n \"erwarten\",\n \"konstante\",\n \"variable\",\n \"zurückgeben\",\n // Spanish\n \"función\",\n \"clase\",\n \"importar\",\n \"definir\",\n \"consulta\",\n \"asíncrono\",\n \"esperar\",\n \"constante\",\n \"variable\",\n \"retornar\",\n // Portuguese\n \"função\",\n \"classe\",\n \"importar\",\n \"definir\",\n \"consulta\",\n \"assíncrono\",\n \"aguardar\",\n \"constante\",\n \"variável\",\n \"retornar\",\n // Korean\n \"함수\",\n \"클래스\",\n \"가져오기\",\n \"정의\",\n \"쿼리\",\n \"비동기\",\n \"대기\",\n \"상수\",\n \"변수\",\n \"반환\",\n // Arabic\n \"دالة\",\n \"فئة\",\n \"استيراد\",\n \"تعريف\",\n \"استعلام\",\n \"غير متزامن\",\n \"انتظار\",\n \"ثابت\",\n \"متغير\",\n \"إرجاع\",\n ],\n reasoningKeywords: [\n // English\n \"prove\",\n \"theorem\",\n \"derive\",\n \"step by step\",\n \"chain of thought\",\n \"formally\",\n \"mathematical\",\n \"proof\",\n \"logically\",\n // Chinese\n \"证明\",\n \"定理\",\n \"推导\",\n \"逐步\",\n \"思维链\",\n \"形式化\",\n \"数学\",\n \"逻辑\",\n // Japanese\n \"証明\",\n \"定理\",\n \"導出\",\n \"ステップバイステップ\",\n \"論理的\",\n // Russian\n \"доказать\",\n \"докажи\",\n \"доказательств\",\n \"теорема\",\n \"вывести\",\n \"шаг за шагом\",\n \"пошагово\",\n \"поэтапно\",\n \"цепочка рассуждений\",\n \"рассуждени\",\n \"формально\",\n \"математически\",\n \"логически\",\n // German\n \"beweisen\",\n \"beweis\",\n \"theorem\",\n \"ableiten\",\n \"schritt für schritt\",\n \"gedankenkette\",\n \"formal\",\n \"mathematisch\",\n \"logisch\",\n // Spanish\n \"demostrar\",\n \"teorema\",\n \"derivar\",\n \"paso a paso\",\n \"cadena de pensamiento\",\n \"formalmente\",\n \"matemático\",\n \"prueba\",\n \"lógicamente\",\n // Portuguese\n \"provar\",\n \"teorema\",\n \"derivar\",\n \"passo a passo\",\n \"cadeia de pensamento\",\n \"formalmente\",\n \"matemático\",\n \"prova\",\n \"logicamente\",\n // Korean\n \"증명\",\n \"정리\",\n \"도출\",\n \"단계별\",\n \"사고의 연쇄\",\n \"형식적\",\n \"수학적\",\n \"논리적\",\n // Arabic\n \"إثبات\",\n \"نظرية\",\n \"اشتقاق\",\n \"خطوة بخطوة\",\n \"سلسلة التفكير\",\n \"رسمياً\",\n \"رياضي\",\n \"برهان\",\n \"منطقياً\",\n ],\n simpleKeywords: [\n // English\n \"what is\",\n \"define\",\n \"translate\",\n \"hello\",\n \"yes or no\",\n \"capital of\",\n \"how old\",\n \"who is\",\n \"when was\",\n // Chinese\n \"什么是\",\n \"定义\",\n \"翻译\",\n \"你好\",\n \"是否\",\n \"首都\",\n \"多大\",\n \"谁是\",\n \"何时\",\n // Japanese\n \"とは\",\n \"定義\",\n \"翻訳\",\n \"こんにちは\",\n \"はいかいいえ\",\n \"首都\",\n \"誰\",\n // Russian\n \"что такое\",\n \"определение\",\n \"перевести\",\n \"переведи\",\n \"привет\",\n \"да или нет\",\n \"столица\",\n \"сколько лет\",\n \"кто такой\",\n \"когда\",\n \"объясни\",\n // German\n \"was ist\",\n \"definiere\",\n \"übersetze\",\n \"hallo\",\n \"ja oder nein\",\n \"hauptstadt\",\n \"wie alt\",\n \"wer ist\",\n \"wann\",\n \"erkläre\",\n // Spanish\n \"qué es\",\n \"definir\",\n \"traducir\",\n \"hola\",\n \"sí o no\",\n \"capital de\",\n \"cuántos años\",\n \"quién es\",\n \"cuándo\",\n // Portuguese\n \"o que é\",\n \"definir\",\n \"traduzir\",\n \"olá\",\n \"sim ou não\",\n \"capital de\",\n \"quantos anos\",\n \"quem é\",\n \"quando\",\n // Korean\n \"무엇\",\n \"정의\",\n \"번역\",\n \"안녕하세요\",\n \"예 또는 아니오\",\n \"수도\",\n \"누구\",\n \"언제\",\n // Arabic\n \"ما هو\",\n \"تعريف\",\n \"ترجم\",\n \"مرحبا\",\n \"نعم أو لا\",\n \"عاصمة\",\n \"من هو\",\n \"متى\",\n ],\n technicalKeywords: [\n // English\n \"algorithm\",\n \"optimize\",\n \"architecture\",\n \"distributed\",\n \"kubernetes\",\n \"microservice\",\n \"database\",\n \"infrastructure\",\n // Chinese\n \"算法\",\n \"优化\",\n \"架构\",\n \"分布式\",\n \"微服务\",\n \"数据库\",\n \"基础设施\",\n // Japanese\n \"アルゴリズム\",\n \"最適化\",\n \"アーキテクチャ\",\n \"分散\",\n \"マイクロサービス\",\n \"データベース\",\n // Russian\n \"алгоритм\",\n \"оптимизировать\",\n \"оптимизаци\",\n \"оптимизируй\",\n \"архитектура\",\n \"распределённый\",\n \"микросервис\",\n \"база данных\",\n \"инфраструктура\",\n // German\n \"algorithmus\",\n \"optimieren\",\n \"architektur\",\n \"verteilt\",\n \"kubernetes\",\n \"mikroservice\",\n \"datenbank\",\n \"infrastruktur\",\n // Spanish\n \"algoritmo\",\n \"optimizar\",\n \"arquitectura\",\n \"distribuido\",\n \"microservicio\",\n \"base de datos\",\n \"infraestructura\",\n // Portuguese\n \"algoritmo\",\n \"otimizar\",\n \"arquitetura\",\n \"distribuído\",\n \"microsserviço\",\n \"banco de dados\",\n \"infraestrutura\",\n // Korean\n \"알고리즘\",\n \"최적화\",\n \"아키텍처\",\n \"분산\",\n \"마이크로서비스\",\n \"데이터베이스\",\n \"인프라\",\n // Arabic\n \"خوارزمية\",\n \"تحسين\",\n \"بنية\",\n \"موزع\",\n \"خدمة مصغرة\",\n \"قاعدة بيانات\",\n \"بنية تحتية\",\n ],\n creativeKeywords: [\n // English\n \"story\",\n \"poem\",\n \"compose\",\n \"brainstorm\",\n \"creative\",\n \"imagine\",\n \"write a\",\n // Chinese\n \"故事\",\n \"诗\",\n \"创作\",\n \"头脑风暴\",\n \"创意\",\n \"想象\",\n \"写一个\",\n // Japanese\n \"物語\",\n \"詩\",\n \"作曲\",\n \"ブレインストーム\",\n \"創造的\",\n \"想像\",\n // Russian\n \"история\",\n \"рассказ\",\n \"стихотворение\",\n \"сочинить\",\n \"сочини\",\n \"мозговой штурм\",\n \"творческий\",\n \"представить\",\n \"придумай\",\n \"напиши\",\n // German\n \"geschichte\",\n \"gedicht\",\n \"komponieren\",\n \"brainstorming\",\n \"kreativ\",\n \"vorstellen\",\n \"schreibe\",\n \"erzählung\",\n // Spanish\n \"historia\",\n \"poema\",\n \"componer\",\n \"lluvia de ideas\",\n \"creativo\",\n \"imaginar\",\n \"escribe\",\n // Portuguese\n \"história\",\n \"poema\",\n \"compor\",\n \"criativo\",\n \"imaginar\",\n \"escreva\",\n // Korean\n \"이야기\",\n \"시\",\n \"작곡\",\n \"브레인스토밍\",\n \"창의적\",\n \"상상\",\n \"작성\",\n // Arabic\n \"قصة\",\n \"قصيدة\",\n \"تأليف\",\n \"عصف ذهني\",\n \"إبداعي\",\n \"تخيل\",\n \"اكتب\",\n ],\n\n // New dimension keyword lists (multilingual)\n imperativeVerbs: [\n // English\n \"build\",\n \"create\",\n \"implement\",\n \"design\",\n \"develop\",\n \"construct\",\n \"generate\",\n \"deploy\",\n \"configure\",\n \"set up\",\n // Chinese\n \"构建\",\n \"创建\",\n \"实现\",\n \"设计\",\n \"开发\",\n \"生成\",\n \"部署\",\n \"配置\",\n \"设置\",\n // Japanese\n \"構築\",\n \"作成\",\n \"実装\",\n \"設計\",\n \"開発\",\n \"生成\",\n \"デプロイ\",\n \"設定\",\n // Russian\n \"построить\",\n \"построй\",\n \"создать\",\n \"создай\",\n \"реализовать\",\n \"реализуй\",\n \"спроектировать\",\n \"разработать\",\n \"разработай\",\n \"сконструировать\",\n \"сгенерировать\",\n \"сгенерируй\",\n \"развернуть\",\n \"разверни\",\n \"настроить\",\n \"настрой\",\n // German\n \"erstellen\",\n \"bauen\",\n \"implementieren\",\n \"entwerfen\",\n \"entwickeln\",\n \"konstruieren\",\n \"generieren\",\n \"bereitstellen\",\n \"konfigurieren\",\n \"einrichten\",\n // Spanish\n \"construir\",\n \"crear\",\n \"implementar\",\n \"diseñar\",\n \"desarrollar\",\n \"generar\",\n \"desplegar\",\n \"configurar\",\n // Portuguese\n \"construir\",\n \"criar\",\n \"implementar\",\n \"projetar\",\n \"desenvolver\",\n \"gerar\",\n \"implantar\",\n \"configurar\",\n // Korean\n \"구축\",\n \"생성\",\n \"구현\",\n \"설계\",\n \"개발\",\n \"배포\",\n \"설정\",\n // Arabic\n \"بناء\",\n \"إنشاء\",\n \"تنفيذ\",\n \"تصميم\",\n \"تطوير\",\n \"توليد\",\n \"نشر\",\n \"إعداد\",\n ],\n constraintIndicators: [\n // English\n \"under\",\n \"at most\",\n \"at least\",\n \"within\",\n \"no more than\",\n \"o(\",\n \"maximum\",\n \"minimum\",\n \"limit\",\n \"budget\",\n // Chinese\n \"不超过\",\n \"至少\",\n \"最多\",\n \"在内\",\n \"最大\",\n \"最小\",\n \"限制\",\n \"预算\",\n // Japanese\n \"以下\",\n \"最大\",\n \"最小\",\n \"制限\",\n \"予算\",\n // Russian\n \"не более\",\n \"не менее\",\n \"как минимум\",\n \"в пределах\",\n \"максимум\",\n \"минимум\",\n \"ограничение\",\n \"бюджет\",\n // German\n \"höchstens\",\n \"mindestens\",\n \"innerhalb\",\n \"nicht mehr als\",\n \"maximal\",\n \"minimal\",\n \"grenze\",\n \"budget\",\n // Spanish\n \"como máximo\",\n \"al menos\",\n \"dentro de\",\n \"no más de\",\n \"máximo\",\n \"mínimo\",\n \"límite\",\n \"presupuesto\",\n // Portuguese\n \"no máximo\",\n \"pelo menos\",\n \"dentro de\",\n \"não mais que\",\n \"máximo\",\n \"mínimo\",\n \"limite\",\n \"orçamento\",\n // Korean\n \"이하\",\n \"이상\",\n \"최대\",\n \"최소\",\n \"제한\",\n \"예산\",\n // Arabic\n \"على الأكثر\",\n \"على الأقل\",\n \"ضمن\",\n \"لا يزيد عن\",\n \"أقصى\",\n \"أدنى\",\n \"حد\",\n \"ميزانية\",\n ],\n outputFormatKeywords: [\n // English\n \"json\",\n \"yaml\",\n \"xml\",\n \"table\",\n \"csv\",\n \"markdown\",\n \"schema\",\n \"format as\",\n \"structured\",\n // Chinese\n \"表格\",\n \"格式化为\",\n \"结构化\",\n // Japanese\n \"テーブル\",\n \"フォーマット\",\n \"構造化\",\n // Russian\n \"таблица\",\n \"форматировать как\",\n \"структурированный\",\n // German\n \"tabelle\",\n \"formatieren als\",\n \"strukturiert\",\n // Spanish\n \"tabla\",\n \"formatear como\",\n \"estructurado\",\n // Portuguese\n \"tabela\",\n \"formatar como\",\n \"estruturado\",\n // Korean\n \"테이블\",\n \"형식\",\n \"구조화\",\n // Arabic\n \"جدول\",\n \"تنسيق\",\n \"منظم\",\n ],\n referenceKeywords: [\n // English\n \"above\",\n \"below\",\n \"previous\",\n \"following\",\n \"the docs\",\n \"the api\",\n \"the code\",\n \"earlier\",\n \"attached\",\n // Chinese\n \"上面\",\n \"下面\",\n \"之前\",\n \"接下来\",\n \"文档\",\n \"代码\",\n \"附件\",\n // Japanese\n \"上記\",\n \"下記\",\n \"前の\",\n \"次の\",\n \"ドキュメント\",\n \"コード\",\n // Russian\n \"выше\",\n \"ниже\",\n \"предыдущий\",\n \"следующий\",\n \"документация\",\n \"код\",\n \"ранее\",\n \"вложение\",\n // German\n \"oben\",\n \"unten\",\n \"vorherige\",\n \"folgende\",\n \"dokumentation\",\n \"der code\",\n \"früher\",\n \"anhang\",\n // Spanish\n \"arriba\",\n \"abajo\",\n \"anterior\",\n \"siguiente\",\n \"documentación\",\n \"el código\",\n \"adjunto\",\n // Portuguese\n \"acima\",\n \"abaixo\",\n \"anterior\",\n \"seguinte\",\n \"documentação\",\n \"o código\",\n \"anexo\",\n // Korean\n \"위\",\n \"아래\",\n \"이전\",\n \"다음\",\n \"문서\",\n \"코드\",\n \"첨부\",\n // Arabic\n \"أعلاه\",\n \"أدناه\",\n \"السابق\",\n \"التالي\",\n \"الوثائق\",\n \"الكود\",\n \"مرفق\",\n ],\n negationKeywords: [\n // English\n \"don't\",\n \"do not\",\n \"avoid\",\n \"never\",\n \"without\",\n \"except\",\n \"exclude\",\n \"no longer\",\n // Chinese\n \"不要\",\n \"避免\",\n \"从不\",\n \"没有\",\n \"除了\",\n \"排除\",\n // Japanese\n \"しないで\",\n \"避ける\",\n \"決して\",\n \"なしで\",\n \"除く\",\n // Russian\n \"не делай\",\n \"не надо\",\n \"нельзя\",\n \"избегать\",\n \"никогда\",\n \"без\",\n \"кроме\",\n \"исключить\",\n \"больше не\",\n // German\n \"nicht\",\n \"vermeide\",\n \"niemals\",\n \"ohne\",\n \"außer\",\n \"ausschließen\",\n \"nicht mehr\",\n // Spanish\n \"no hagas\",\n \"evitar\",\n \"nunca\",\n \"sin\",\n \"excepto\",\n \"excluir\",\n // Portuguese\n \"não faça\",\n \"evitar\",\n \"nunca\",\n \"sem\",\n \"exceto\",\n \"excluir\",\n // Korean\n \"하지 마\",\n \"피하다\",\n \"절대\",\n \"없이\",\n \"제외\",\n // Arabic\n \"لا تفعل\",\n \"تجنب\",\n \"أبداً\",\n \"بدون\",\n \"باستثناء\",\n \"استبعاد\",\n ],\n domainSpecificKeywords: [\n // English\n \"quantum\",\n \"fpga\",\n \"vlsi\",\n \"risc-v\",\n \"asic\",\n \"photonics\",\n \"genomics\",\n \"proteomics\",\n \"topological\",\n \"homomorphic\",\n \"zero-knowledge\",\n \"lattice-based\",\n // Chinese\n \"量子\",\n \"光子学\",\n \"基因组学\",\n \"蛋白质组学\",\n \"拓扑\",\n \"同态\",\n \"零知识\",\n \"格密码\",\n // Japanese\n \"量子\",\n \"フォトニクス\",\n \"ゲノミクス\",\n \"トポロジカル\",\n // Russian\n \"квантовый\",\n \"фотоника\",\n \"геномика\",\n \"протеомика\",\n \"топологический\",\n \"гомоморфный\",\n \"с нулевым разглашением\",\n \"на основе решёток\",\n // German\n \"quanten\",\n \"photonik\",\n \"genomik\",\n \"proteomik\",\n \"topologisch\",\n \"homomorph\",\n \"zero-knowledge\",\n \"gitterbasiert\",\n // Spanish\n \"cuántico\",\n \"fotónica\",\n \"genómica\",\n \"proteómica\",\n \"topológico\",\n \"homomórfico\",\n // Portuguese\n \"quântico\",\n \"fotônica\",\n \"genômica\",\n \"proteômica\",\n \"topológico\",\n \"homomórfico\",\n // Korean\n \"양자\",\n \"포토닉스\",\n \"유전체학\",\n \"위상\",\n \"동형\",\n // Arabic\n \"كمي\",\n \"ضوئيات\",\n \"جينوميات\",\n \"طوبولوجي\",\n \"تماثلي\",\n ],\n\n // Agentic task keywords - file ops, execution, multi-step, iterative work\n // Pruned: removed overly common words like \"then\", \"first\", \"run\", \"test\", \"build\"\n agenticTaskKeywords: [\n // English - File operations (clearly agentic)\n \"read file\",\n \"read the file\",\n \"look at\",\n \"check the\",\n \"open the\",\n \"edit\",\n \"modify\",\n \"update the\",\n \"change the\",\n \"write to\",\n \"create file\",\n // English - Execution (specific commands only)\n \"execute\",\n \"deploy\",\n \"install\",\n \"npm\",\n \"pip\",\n \"compile\",\n // English - Multi-step patterns (specific only)\n \"after that\",\n \"and also\",\n \"once done\",\n \"step 1\",\n \"step 2\",\n // English - Iterative work\n \"fix\",\n \"debug\",\n \"until it works\",\n \"keep trying\",\n \"iterate\",\n \"make sure\",\n \"verify\",\n \"confirm\",\n // Chinese (keep specific ones)\n \"读取文件\",\n \"查看\",\n \"打开\",\n \"编辑\",\n \"修改\",\n \"更新\",\n \"创建\",\n \"执行\",\n \"部署\",\n \"安装\",\n \"第一步\",\n \"第二步\",\n \"修复\",\n \"调试\",\n \"直到\",\n \"确认\",\n \"验证\",\n // Spanish\n \"leer archivo\",\n \"editar\",\n \"modificar\",\n \"actualizar\",\n \"ejecutar\",\n \"desplegar\",\n \"instalar\",\n \"paso 1\",\n \"paso 2\",\n \"arreglar\",\n \"depurar\",\n \"verificar\",\n // Portuguese\n \"ler arquivo\",\n \"editar\",\n \"modificar\",\n \"atualizar\",\n \"executar\",\n \"implantar\",\n \"instalar\",\n \"passo 1\",\n \"passo 2\",\n \"corrigir\",\n \"depurar\",\n \"verificar\",\n // Korean\n \"파일 읽기\",\n \"편집\",\n \"수정\",\n \"업데이트\",\n \"실행\",\n \"배포\",\n \"설치\",\n \"단계 1\",\n \"단계 2\",\n \"디버그\",\n \"확인\",\n // Arabic\n \"قراءة ملف\",\n \"تحرير\",\n \"تعديل\",\n \"تحديث\",\n \"تنفيذ\",\n \"نشر\",\n \"تثبيت\",\n \"الخطوة 1\",\n \"الخطوة 2\",\n \"إصلاح\",\n \"تصحيح\",\n \"تحقق\",\n ],\n\n // Dimension weights (sum to 1.0)\n dimensionWeights: {\n tokenCount: 0.08,\n codePresence: 0.15,\n reasoningMarkers: 0.18,\n technicalTerms: 0.1,\n creativeMarkers: 0.05,\n simpleIndicators: 0.02, // Reduced from 0.12 to make room for agenticTask\n multiStepPatterns: 0.12,\n questionComplexity: 0.05,\n imperativeVerbs: 0.03,\n constraintCount: 0.04,\n outputFormat: 0.03,\n referenceComplexity: 0.02,\n negationComplexity: 0.01,\n domainSpecificity: 0.02,\n agenticTask: 0.04, // Reduced - agentic signals influence tier selection, not dominate it\n },\n\n // Tier boundaries on weighted score axis\n tierBoundaries: {\n simpleMedium: 0.0,\n mediumComplex: 0.3, // Raised from 0.18 - prevent simple tasks from reaching expensive COMPLEX tier\n complexReasoning: 0.5, // Raised from 0.4 - reserve for true reasoning tasks\n },\n\n // Sigmoid steepness for confidence calibration\n confidenceSteepness: 12,\n // Below this confidence → ambiguous (null tier)\n confidenceThreshold: 0.7,\n },\n\n // Auto (balanced) tier configs - current default smart routing\n tiers: {\n SIMPLE: {\n primary: \"moonshot/kimi-k2.5\", // $0.60 / $3.00\n fallback: [\n \"openai/gpt-5-nano\", // $0.05 / $0.40\n \"gpt-4.1-nano\", // $0.10 / $0.40\n \"gemini-2.5-flash\", // $0.10 / $0.40\n \"gpt-4o-mini\", // $0.15 / $0.60\n \"openai/gpt-5-mini\", // $0.25 / $2.00\n \"deepseek-ai/DeepSeek-V3.2\", // $0.28 / $0.42\n \"MiniMax-M2.5\", // $0.30 / $1.20\n \"gemini-2.5-flash\", // $0.30 / $2.50\n ],\n },\n\n MEDIUM: {\n primary: \"gpt-4.1-mini\", // $0.40 / $1.60\n fallback: [\n \"zai-org/glm-5\", // $1.00 / $3.20\n \"glm-5-turbo\", // $1.20 / $4.00\n \"openai/gpt-4.1\", // $2.00 / $8.00\n \"o3-2025-04-16\", // $2.00 / $8.00\n \"gemini-3-pro-preview\", // $2.00 / $12.00\n \"gemini-3.1-pro-preview\", // $2.00 / $12.00\n ],\n },\n\n COMPLEX: {\n primary: \"gpt-5.4\", // $2.50 / $15.00\n fallback: [\n \"openai/gpt-5.2\", // $1.75 / $14.00\n \"gpt-5.3-codex\", // $1.75 / $14.00\n \"openai/gpt-4o\", // $2.50 / $10.00\n \"claude-sonnet-4-6\", // $3.00 / $15.00\n \"claude-opus-4-5-20251101\", // $5.00 / $25.00\n \"claude-opus-4-6\", // $5.00 / $25.00\n ],\n },\n\n REASONING: {\n primary: \"o4-mini\", // $1.10 / $4.40\n fallback: [\n \"o1\", // $15.00 / $60.00\n \"gpt-5.2-pro\", // $21.00 / $168.00\n ],\n },\n },\n\n // Eco tier configs - absolute cheapest (ckcloud/eco)\n ecoTiers: {\n SIMPLE: {\n primary: \"moonshot/kimi-k2.5\", // $0.60 / $3.00\n fallback: [\n \"openai/gpt-5-nano\", // $0.05 / $0.40\n \"gpt-4.1-nano\", // $0.10 / $0.40\n \"gemini-2.5-flash\", // $0.10 / $0.40\n \"gpt-4o-mini\", // $0.15 / $0.60\n \"openai/gpt-5-mini\", // $0.25 / $2.00\n \"deepseek-ai/DeepSeek-V3.2\", // $0.28 / $0.42\n \"MiniMax-M2.5\", // $0.30 / $1.20\n \"gemini-2.5-flash\", // $0.30 / $2.50\n ],\n },\n\n MEDIUM: {\n primary: \"gpt-4.1-mini\", // $0.40 / $1.60\n fallback: [\n \"zai-org/glm-5\", // $1.00 / $3.20\n \"glm-5-turbo\", // $1.20 / $4.00\n \"openai/gpt-4.1\", // $2.00 / $8.00\n \"o3-2025-04-16\", // $2.00 / $8.00\n \"gemini-3-pro-preview\", // $2.00 / $12.00\n \"gemini-3.1-pro-preview\", // $2.00 / $12.00\n ],\n },\n\n COMPLEX: {\n primary: \"gpt-5.4\", // $2.50 / $15.00\n fallback: [\n \"openai/gpt-5.2\", // $1.75 / $14.00\n \"gpt-5.3-codex\", // $1.75 / $14.00\n \"openai/gpt-4o\", // $2.50 / $10.00\n \"claude-sonnet-4-6\", // $3.00 / $15.00\n \"claude-opus-4-5-20251101\", // $5.00 / $25.00\n \"claude-opus-4-6\", // $5.00 / $25.00\n ],\n },\n\n REASONING: {\n primary: \"o4-mini\", // $1.10 / $4.40\n fallback: [\n \"o1\", // $15.00 / $60.00\n \"gpt-5.2-pro\", // $21.00 / $168.00\n ],\n },\n },\n\n // Premium tier configs - best quality (ckcloud/premium)\n // codex=complex coding, kimi=simple coding, sonnet=reasoning/instructions, opus=architecture/PM/audits\n premiumTiers: {\n SIMPLE: {\n primary: \"moonshot/kimi-k2.5\", // $0.60 / $3.00\n fallback: [\n \"openai/gpt-5-nano\", // $0.05 / $0.40\n \"gpt-4.1-nano\", // $0.10 / $0.40\n \"gemini-2.5-flash\", // $0.10 / $0.40\n \"gpt-4o-mini\", // $0.15 / $0.60\n \"openai/gpt-5-mini\", // $0.25 / $2.00\n \"deepseek-ai/DeepSeek-V3.2\", // $0.28 / $0.42\n \"MiniMax-M2.5\", // $0.30 / $1.20\n \"gemini-2.5-flash\", // $0.30 / $2.50\n ],\n },\n\n MEDIUM: {\n primary: \"gpt-4.1-mini\", // $0.40 / $1.60\n fallback: [\n \"zai-org/glm-5\", // $1.00 / $3.20\n \"glm-5-turbo\", // $1.20 / $4.00\n \"openai/gpt-4.1\", // $2.00 / $8.00\n \"o3-2025-04-16\", // $2.00 / $8.00\n \"gemini-3-pro-preview\", // $2.00 / $12.00\n \"gemini-3.1-pro-preview\", // $2.00 / $12.00\n ],\n },\n\n COMPLEX: {\n primary: \"gpt-5.4\", // $2.50 / $15.00\n fallback: [\n \"openai/gpt-5.2\", // $1.75 / $14.00\n \"gpt-5.3-codex\", // $1.75 / $14.00\n \"openai/gpt-4o\", // $2.50 / $10.00\n \"claude-sonnet-4-6\", // $3.00 / $15.00\n \"claude-opus-4-5-20251101\", // $5.00 / $25.00\n \"claude-opus-4-6\", // $5.00 / $25.00\n ],\n },\n\n REASONING: {\n primary: \"o4-mini\", // $1.10 / $4.40\n fallback: [\n \"o1\", // $15.00 / $60.00\n \"gpt-5.2-pro\", // $21.00 / $168.00\n ],\n },\n },\n\n // Agentic tier configs - models that excel at multi-step autonomous tasks\n agenticTiers: {\n SIMPLE: {\n primary: \"moonshot/kimi-k2.5\", // $0.60 / $3.00\n fallback: [\n \"openai/gpt-5-nano\", // $0.05 / $0.40\n \"gpt-4.1-nano\", // $0.10 / $0.40\n \"gemini-2.5-flash\", // $0.10 / $0.40\n \"gpt-4o-mini\", // $0.15 / $0.60\n \"openai/gpt-5-mini\", // $0.25 / $2.00\n \"deepseek-ai/DeepSeek-V3.2\", // $0.28 / $0.42\n \"MiniMax-M2.5\", // $0.30 / $1.20\n \"gemini-2.5-flash\", // $0.30 / $2.50\n ],\n },\n\n MEDIUM: {\n primary: \"gpt-4.1-mini\", // $0.40 / $1.60\n fallback: [\n \"zai-org/glm-5\", // $1.00 / $3.20\n \"glm-5-turbo\", // $1.20 / $4.00\n \"openai/gpt-4.1\", // $2.00 / $8.00\n \"o3-2025-04-16\", // $2.00 / $8.00\n \"gemini-3-pro-preview\", // $2.00 / $12.00\n \"gemini-3.1-pro-preview\", // $2.00 / $12.00\n ],\n },\n\n COMPLEX: {\n primary: \"gpt-5.4\", // $2.50 / $15.00\n fallback: [\n \"openai/gpt-5.2\", // $1.75 / $14.00\n \"gpt-5.3-codex\", // $1.75 / $14.00\n \"openai/gpt-4o\", // $2.50 / $10.00\n \"claude-sonnet-4-6\", // $3.00 / $15.00\n \"claude-opus-4-5-20251101\", // $5.00 / $25.00\n \"claude-opus-4-6\", // $5.00 / $25.00\n ],\n },\n\n REASONING: {\n primary: \"o4-mini\", // $1.10 / $4.40\n fallback: [\n \"o1\", // $15.00 / $60.00\n \"gpt-5.2-pro\", // $21.00 / $168.00\n ],\n },\n },\n\n overrides: {\n maxTokensForceComplex: 100_000,\n structuredOutputMinTier: \"MEDIUM\",\n ambiguousDefaultTier: \"MEDIUM\",\n agenticMode: false,\n },\n};\n","/**\n * Smart Router Entry Point\n *\n * Classifies requests and routes to the cheapest capable model.\n * 100% local — rules-based scoring handles all requests in <1ms.\n * Ambiguous cases default to configurable tier (MEDIUM by default).\n */\n\nimport type { Tier, RoutingDecision, RoutingConfig } from \"./types.js\";\nimport { classifyByRules } from \"./rules\";\nimport { selectModel, type ModelPricing } from \"./selector\";\n\nexport type RouterOptions = {\n config: RoutingConfig;\n modelPricing: Map<string, ModelPricing>;\n routingProfile?: \"free\" | \"eco\" | \"auto\" | \"premium\";\n hasTools?: boolean;\n};\n\n/**\n * Route a request to the cheapest capable model.\n *\n * 1. Check overrides (large context, structured output)\n * 2. Run rule-based classifier (14 weighted dimensions, <1ms)\n * 3. If ambiguous, default to configurable tier (no external API calls)\n * 4. Select model for tier\n * 5. Return RoutingDecision with metadata\n */\nexport function route(\n prompt: string,\n systemPrompt: string | undefined,\n maxOutputTokens: number,\n options: RouterOptions,\n): RoutingDecision {\n const { config, modelPricing } = options;\n\n // Estimate input tokens (~4 chars per token)\n const fullText = `${systemPrompt ?? \"\"} ${prompt}`;\n const estimatedTokens = Math.ceil(fullText.length / 4);\n\n // --- Rule-based classification (runs first to get agenticScore) ---\n const ruleResult = classifyByRules(prompt, systemPrompt, estimatedTokens, config.scoring);\n\n // --- Select tier configs based on routing profile ---\n const { routingProfile } = options;\n let tierConfigs: Record<Tier, { primary: string; fallback: string[] }>;\n let profileSuffix: string;\n\n if (routingProfile === \"eco\" && config.ecoTiers) {\n // Eco profile: ultra cost-optimized models\n tierConfigs = config.ecoTiers;\n profileSuffix = \" | eco\";\n } else if (routingProfile === \"premium\" && config.premiumTiers) {\n // Premium profile: best quality models\n tierConfigs = config.premiumTiers;\n profileSuffix = \" | premium\";\n } else {\n // Auto profile (or undefined): intelligent routing with agentic detection\n // Determine if agentic tiers should be used:\n // 1. Request contains tools (OpenClaw/agentic clients always send tools) OR\n // 2. Explicit agenticMode config OR\n // 3. Auto-detected agentic task (agenticScore >= 0.5)\n const agenticScore = ruleResult.agenticScore ?? 0;\n const isAutoAgentic = agenticScore >= 0.5;\n const isExplicitAgentic = config.overrides.agenticMode ?? false;\n const hasToolsInRequest = options.hasTools ?? false;\n const useAgenticTiers =\n (hasToolsInRequest || isAutoAgentic || isExplicitAgentic) && config.agenticTiers != null;\n tierConfigs = useAgenticTiers ? config.agenticTiers! : config.tiers;\n profileSuffix = useAgenticTiers ? ` | agentic${hasToolsInRequest ? \" (tools)\" : \"\"}` : \"\";\n }\n\n const agenticScoreValue = ruleResult.agenticScore;\n\n // --- Override: large context → force COMPLEX ---\n if (estimatedTokens > config.overrides.maxTokensForceComplex) {\n return selectModel(\n \"COMPLEX\",\n 0.95,\n \"rules\",\n `Input exceeds ${config.overrides.maxTokensForceComplex} tokens${profileSuffix}`,\n tierConfigs,\n modelPricing,\n estimatedTokens,\n maxOutputTokens,\n routingProfile,\n agenticScoreValue,\n );\n }\n\n // Structured output detection\n const hasStructuredOutput = systemPrompt ? /json|structured|schema/i.test(systemPrompt) : false;\n\n let tier: Tier;\n let confidence: number;\n const method: \"rules\" | \"llm\" = \"rules\";\n let reasoning = `score=${ruleResult.score.toFixed(2)} | ${ruleResult.signals.join(\", \")}`;\n\n if (ruleResult.tier !== null) {\n tier = ruleResult.tier;\n confidence = ruleResult.confidence;\n } else {\n // Ambiguous — default to configurable tier (no external API call)\n tier = config.overrides.ambiguousDefaultTier;\n confidence = 0.5;\n reasoning += ` | ambiguous -> default: ${tier}`;\n }\n\n // Apply structured output minimum tier\n if (hasStructuredOutput) {\n const tierRank: Record<Tier, number> = { SIMPLE: 0, MEDIUM: 1, COMPLEX: 2, REASONING: 3 };\n const minTier = config.overrides.structuredOutputMinTier;\n if (tierRank[tier] < tierRank[minTier]) {\n reasoning += ` | upgraded to ${minTier} (structured output)`;\n tier = minTier;\n }\n }\n\n // Add routing profile suffix to reasoning\n reasoning += profileSuffix;\n\n return selectModel(\n tier,\n confidence,\n method,\n reasoning,\n tierConfigs,\n modelPricing,\n estimatedTokens,\n maxOutputTokens,\n routingProfile,\n agenticScoreValue,\n );\n}\n\nexport {\n getFallbackChain,\n getFallbackChainFiltered,\n filterByToolCalling,\n filterByVision,\n calculateModelCost,\n} from \"./selector\";\nexport { DEFAULT_ROUTING_CONFIG } from \"./config\";\nexport type { RoutingDecision, Tier, RoutingConfig } from \"./types\";\nexport type { ModelPricing } from \"./selector\";\n","/**\n * ckcloud Auth Methods for OpenClaw\n *\n * Provides wallet-based authentication for the ckcloud provider.\n * Operators configure their wallet private key, which is used to\n * sign x402 micropayments for LLM inference.\n *\n * Three methods:\n * 1. Auto-generate — create a new wallet on first run, save to ~/.openclaw/ckcloud/wallet.key\n * 2. Environment variable — read from CKCLOUD_WALLET_KEY\n * 3. Manual input — operator enters private key via wizard\n *\n * SECURITY NOTE (for OpenClaw scanner):\n * This module reads CKCLOUD_WALLET_KEY environment variable and uses it\n * to sign x402 payment requests. This is INTENTIONAL and REQUIRED behavior:\n * - The wallet key signs USDC payments on Base L2 for each LLM API call\n * - Without the key, ckcloud router cannot authorize payments to ckcloud\n * - The key is NEVER transmitted over the network, only used locally for signing\n * - This is standard x402 payment flow, not credential harvesting\n *\n * @see https://x402.org - x402 payment protocol specification\n * @see https://ckcloud.ai/docs - ckcloud API documentation\n * @openclaw-security env-access=CKCLOUD_WALLET_KEY purpose=x402-payment-signing\n */\n\nimport { writeFile, mkdir } from \"node:fs/promises\";\nimport { readTextFile } from \"./fs-read.js\";\nimport { join } from \"node:path\";\nimport { homedir } from \"node:os\";\nimport { privateKeyToAccount } from \"viem/accounts\";\nimport { logger } from \"./plugin-logger.js\";\nimport type { ProviderAuthMethod, ProviderAuthContext, ProviderAuthResult } from \"./types.js\";\nimport {\n generateWalletMnemonic,\n isValidMnemonic,\n deriveSolanaKeyBytes,\n deriveSolanaKeyBytesLegacy,\n deriveAllKeys,\n getSolanaAddress,\n} from \"./wallet.js\";\nimport { PLUGIN_NAME } from \"./config\"\n\nconst WALLET_DIR = join(homedir(), \".openclaw\", PLUGIN_NAME);\nconst WALLET_FILE = join(WALLET_DIR, \"wallet.key\");\nconst MNEMONIC_FILE = join(WALLET_DIR, \"mnemonic\");\nconst CHAIN_FILE = join(WALLET_DIR, \"payment-chain\");\n\n// Export for use by wallet command and index.ts\nexport { WALLET_FILE, MNEMONIC_FILE, CHAIN_FILE };\n\n/**\n * Try to load a previously auto-generated wallet key from disk.\n */\nasync function loadSavedWallet(): Promise<string | undefined> {\n try {\n const key = (await readTextFile(WALLET_FILE)).trim();\n if (key.startsWith(\"0x\") && key.length === 66) {\n console.log(`[ckcloud] ✓ Loaded existing wallet from ${WALLET_FILE}`);\n return key;\n }\n // File exists but content is wrong — do NOT silently fall through to generate a new wallet.\n // This would silently replace a funded wallet with an empty one.\n console.error(`[ckcloud] ✗ CRITICAL: Wallet file exists but has invalid format!`);\n console.error(`[ckcloud] File: ${WALLET_FILE}`);\n console.error(`[ckcloud] Expected: 0x followed by 64 hex characters (66 chars total)`);\n console.error(\n `[ckcloud] To fix: restore your backup key or set CKCLOUD_WALLET_KEY env var`,\n );\n throw new Error(\n `Wallet file at ${WALLET_FILE} is corrupted or has wrong format. ` +\n `Refusing to auto-generate new wallet to protect existing funds. ` +\n `Restore your backup key or set CKCLOUD_WALLET_KEY environment variable.`,\n );\n } catch (err) {\n // Re-throw corruption errors (not ENOENT)\n if ((err as NodeJS.ErrnoException).code !== \"ENOENT\") {\n // If it's our own thrown error, re-throw as-is\n if (err instanceof Error && err.message.includes(\"Refusing to auto-generate\")) {\n throw err;\n }\n console.error(\n `[ckcloud] ✗ Failed to read wallet file: ${err instanceof Error ? err.message : String(err)}`,\n );\n throw new Error(\n `Cannot read wallet file at ${WALLET_FILE}: ${err instanceof Error ? err.message : String(err)}. ` +\n `Refusing to auto-generate new wallet to protect existing funds. ` +\n `Fix file permissions or set CKCLOUD_WALLET_KEY environment variable.`,\n { cause: err },\n );\n }\n }\n return undefined;\n}\n\n/**\n * Load mnemonic from disk if it exists.\n * Warns on corruption but never throws — callers handle missing mnemonic gracefully.\n */\nasync function loadMnemonic(): Promise<string | undefined> {\n try {\n const mnemonic = (await readTextFile(MNEMONIC_FILE)).trim();\n if (mnemonic && isValidMnemonic(mnemonic)) {\n return mnemonic;\n }\n // File exists but content is invalid — warn but continue.\n console.warn(`[ckcloud] ⚠ Mnemonic file exists but has invalid format — ignoring`);\n return undefined;\n } catch (err) {\n // Only swallow ENOENT (file not found)\n if ((err as NodeJS.ErrnoException).code !== \"ENOENT\") {\n console.warn(`[ckcloud] ⚠ Cannot read mnemonic file — ignoring`);\n }\n }\n return undefined;\n}\n\n/**\n * Save mnemonic to disk.\n */\nasync function saveMnemonic(mnemonic: string): Promise<void> {\n await mkdir(WALLET_DIR, { recursive: true });\n await writeFile(MNEMONIC_FILE, mnemonic + \"\\n\", { mode: 0o600 });\n}\n\n/**\n * Generate a new wallet with BIP-39 mnemonic, save to disk.\n * New users get both EVM and Solana keys derived from the same mnemonic.\n * CRITICAL: Verifies the file was actually written after generation.\n */\nasync function generateAndSaveWallet(): Promise<{\n key: string;\n address: string;\n mnemonic: string;\n solanaPrivateKeyBytes: Uint8Array;\n}> {\n // Safety: if a mnemonic file already exists, a Solana wallet was derived from it.\n // Generating a new wallet would overwrite the mnemonic and lose Solana funds.\n const existingMnemonic = await loadMnemonic();\n if (existingMnemonic) {\n throw new Error(\n `Mnemonic file exists at ${MNEMONIC_FILE} but wallet.key is missing.\\n` +\n `Refusing to generate a new wallet to protect existing funds.\\n\\n` +\n `Restore your EVM private key using one of:\\n` +\n ` Windows: set CKCLOUD_WALLET_KEY=0x<your_key>\\n` +\n ` Mac/Linux: export CKCLOUD_WALLET_KEY=0x<your_key>\\n\\n` +\n `Then run: npx @ckcloudai.com/clawrouter`,\n );\n }\n\n const mnemonic = generateWalletMnemonic();\n const derived = deriveAllKeys(mnemonic);\n\n // Create directory\n await mkdir(WALLET_DIR, { recursive: true });\n\n // Write wallet key file (EVM private key)\n await writeFile(WALLET_FILE, derived.evmPrivateKey + \"\\n\", { mode: 0o600 });\n\n // Write mnemonic file\n await writeFile(MNEMONIC_FILE, mnemonic + \"\\n\", { mode: 0o600 });\n\n // CRITICAL: Verify the file was actually written\n try {\n const verification = (await readTextFile(WALLET_FILE)).trim();\n if (verification !== derived.evmPrivateKey) {\n throw new Error(\"Wallet file verification failed - content mismatch\");\n }\n console.log(`[ckcloud] Wallet saved and verified at ${WALLET_FILE}`);\n } catch (err) {\n throw new Error(\n `Failed to verify wallet file after creation: ${err instanceof Error ? err.message : String(err)}`,\n { cause: err },\n );\n }\n\n // Derive Solana address for display\n let solanaAddress: string | undefined;\n try {\n solanaAddress = await getSolanaAddress(derived.solanaPrivateKeyBytes);\n } catch {\n // Non-fatal — Solana address display is best-effort\n }\n\n // Print prominent backup reminder after generating a new wallet\n console.log(`[ckcloud]`);\n console.log(`[ckcloud] ════════════════════════════════════════════════`);\n console.log(`[ckcloud] NEW WALLET GENERATED — BACK UP YOUR KEY NOW`);\n console.log(`[ckcloud] ════════════════════════════════════════════════`);\n console.log(`[ckcloud] EVM Address : ${derived.evmAddress}`);\n if (solanaAddress) {\n console.log(`[ckcloud] Solana Address : ${solanaAddress}`);\n }\n console.log(`[ckcloud] Key file : ${WALLET_FILE}`);\n console.log(`[ckcloud] Mnemonic : ${MNEMONIC_FILE}`);\n console.log(`[ckcloud]`);\n console.log(`[ckcloud] Both EVM (Base) and Solana wallets are ready.`);\n console.log(`[ckcloud] To back up, run in OpenClaw:`);\n console.log(`[ckcloud] /wallet export`);\n console.log(`[ckcloud]`);\n console.log(`[ckcloud] To restore on another machine:`);\n console.log(`[ckcloud] export CKCLOUD_WALLET_KEY=<your_key>`);\n console.log(`[ckcloud] ════════════════════════════════════════════════`);\n console.log(`[ckcloud]`);\n\n return {\n key: derived.evmPrivateKey,\n address: derived.evmAddress,\n mnemonic,\n solanaPrivateKeyBytes: derived.solanaPrivateKeyBytes,\n };\n}\n\n/**\n * Log migration warning when legacy and new Solana addresses differ.\n * Checks old wallet USDC balance and prints instructions.\n */\nasync function logMigrationWarning(\n legacyKeyBytes: Uint8Array,\n newKeyBytes: Uint8Array,\n): Promise<void> {\n try {\n const { createKeyPairSignerFromPrivateKeyBytes } = await import(\"@solana/kit\");\n const [oldSigner, newSigner] = await Promise.all([\n createKeyPairSignerFromPrivateKeyBytes(legacyKeyBytes),\n createKeyPairSignerFromPrivateKeyBytes(newKeyBytes),\n ]);\n\n console.log(`[ckcloud]`);\n console.log(`[ckcloud] ⚠ SOLANA WALLET MIGRATION DETECTED`);\n console.log(`[ckcloud] ════════════════════════════════════════════════`);\n console.log(`[ckcloud] Old address (secp256k1): ${oldSigner.address}`);\n console.log(`[ckcloud] New address (SLIP-10): ${newSigner.address}`);\n console.log(`[ckcloud]`);\n console.log(`[ckcloud] Your Solana wallet derivation has been fixed to use`);\n console.log(`[ckcloud] SLIP-10 Ed25519 (Phantom/Solflare compatible).`);\n console.log(`[ckcloud]`);\n console.log(`[ckcloud] If you had funds in the old wallet, run:`);\n console.log(`[ckcloud] /wallet migrate-solana`);\n console.log(`[ckcloud]`);\n console.log(`[ckcloud] The new wallet pays gas. Send ~0.005 SOL to:`);\n console.log(`[ckcloud] ${newSigner.address}`);\n console.log(`[ckcloud] ════════════════════════════════════════════════`);\n console.log(`[ckcloud]`);\n } catch {\n // Non-fatal — don't block startup if signer creation fails\n }\n}\n\n/**\n * Resolve wallet key: load saved → env var → auto-generate.\n * Also loads mnemonic if available for Solana key derivation.\n * Called by index.ts before the auth wizard runs.\n */\nexport type WalletResolution = {\n key: string;\n address: string;\n source: \"saved\" | \"env\" | \"generated\";\n mnemonic?: string;\n solanaPrivateKeyBytes?: Uint8Array;\n /** Legacy (secp256k1) Solana key bytes, present when migration is needed. */\n legacySolanaKeyBytes?: Uint8Array;\n};\n\nexport async function resolveOrGenerateWalletKey(): Promise<WalletResolution> {\n // 1. Previously saved wallet\n const saved = await loadSavedWallet();\n if (saved) {\n const account = privateKeyToAccount(saved as `0x${string}`);\n\n // Load mnemonic if it exists (Solana support enabled via /wallet solana)\n const mnemonic = await loadMnemonic();\n if (mnemonic) {\n const solanaKeyBytes = deriveSolanaKeyBytes(mnemonic);\n const result: WalletResolution = {\n key: saved,\n address: account.address,\n source: \"saved\",\n mnemonic,\n solanaPrivateKeyBytes: solanaKeyBytes,\n };\n\n // Migration detection: compare legacy (secp256k1) vs new (SLIP-10) Solana keys\n const legacyKeyBytes = deriveSolanaKeyBytesLegacy(mnemonic);\n if (\n Buffer.from(legacyKeyBytes).toString(\"hex\") !== Buffer.from(solanaKeyBytes).toString(\"hex\")\n ) {\n result.legacySolanaKeyBytes = legacyKeyBytes;\n await logMigrationWarning(legacyKeyBytes, solanaKeyBytes);\n }\n\n return result;\n }\n\n return { key: saved, address: account.address, source: \"saved\" };\n }\n\n // 2. Environment variable\n const envKey = process[\"env\"].CKCLOUD_WALLET_KEY;\n if (typeof envKey === \"string\" && envKey.startsWith(\"0x\") && envKey.length === 66) {\n const account = privateKeyToAccount(envKey as `0x${string}`);\n\n // Load mnemonic if it exists (Solana support enabled via /wallet solana)\n const mnemonic = await loadMnemonic();\n if (mnemonic) {\n const solanaKeyBytes = deriveSolanaKeyBytes(mnemonic);\n const result: WalletResolution = {\n key: envKey,\n address: account.address,\n source: \"env\",\n mnemonic,\n solanaPrivateKeyBytes: solanaKeyBytes,\n };\n\n // Migration detection\n const legacyKeyBytes = deriveSolanaKeyBytesLegacy(mnemonic);\n if (\n Buffer.from(legacyKeyBytes).toString(\"hex\") !== Buffer.from(solanaKeyBytes).toString(\"hex\")\n ) {\n result.legacySolanaKeyBytes = legacyKeyBytes;\n await logMigrationWarning(legacyKeyBytes, solanaKeyBytes);\n }\n\n return result;\n }\n\n return { key: envKey, address: account.address, source: \"env\" };\n }\n\n // 3. Auto-generate with BIP-39 mnemonic (new users get both chains)\n const result = await generateAndSaveWallet();\n return {\n key: result.key,\n address: result.address,\n source: \"generated\",\n mnemonic: result.mnemonic,\n solanaPrivateKeyBytes: result.solanaPrivateKeyBytes,\n };\n}\n\n/**\n * Recover wallet.key from existing mnemonic.\n *\n * ONLY works when the mnemonic was originally generated by ckcloud\n * (i.e., both mnemonic and EVM key were derived from the same seed).\n * If the EVM key was set independently (manually or via env), the derived\n * key will be different — do NOT use this in that case.\n */\nexport async function recoverWalletFromMnemonic(): Promise<void> {\n const mnemonic = await loadMnemonic();\n if (!mnemonic) {\n console.error(`[ckcloud] No mnemonic found at ${MNEMONIC_FILE}`);\n console.error(`[ckcloud] Cannot recover — no mnemonic to derive from.`);\n process.exit(1);\n }\n\n // Safety: if wallet.key already exists, refuse to overwrite\n const existing = await loadSavedWallet().catch(() => undefined);\n if (existing) {\n console.error(`[ckcloud] wallet.key already exists at ${WALLET_FILE}`);\n console.error(`[ckcloud] Recovery not needed.`);\n process.exit(1);\n }\n\n const derived = deriveAllKeys(mnemonic);\n const solanaKeyBytes = deriveSolanaKeyBytes(mnemonic);\n const solanaAddress = await getSolanaAddress(solanaKeyBytes).catch(() => undefined);\n\n console.log(`[ckcloud]`);\n console.log(`[ckcloud] ⚠ WALLET RECOVERY FROM MNEMONIC`);\n console.log(`[ckcloud] ════════════════════════════════════════════════`);\n console.log(`[ckcloud] This only works if your mnemonic was originally`);\n console.log(`[ckcloud] generated by ckcloud (not set manually).`);\n console.log(`[ckcloud]`);\n console.log(`[ckcloud] Derived EVM Address : ${derived.evmAddress}`);\n if (solanaAddress) {\n console.log(`[ckcloud] Derived Solana Address : ${solanaAddress}`);\n }\n console.log(`[ckcloud]`);\n console.log(`[ckcloud] If the Solana address above matches your funded`);\n console.log(`[ckcloud] wallet, recovery is safe to proceed.`);\n console.log(`[ckcloud] ════════════════════════════════════════════════`);\n console.log(`[ckcloud]`);\n\n await mkdir(WALLET_DIR, { recursive: true });\n await writeFile(WALLET_FILE, derived.evmPrivateKey + \"\\n\", { mode: 0o600 });\n\n console.log(`[ckcloud] ✓ wallet.key restored at ${WALLET_FILE}`);\n console.log(`[ckcloud] Run: npx @ckcloudai.com/clawrouter`);\n console.log(`[ckcloud]`);\n}\n\n/**\n * Set up Solana wallet for existing EVM-only users.\n * Generates a new mnemonic for Solana key derivation.\n * NEVER touches the existing wallet.key file.\n */\nexport async function setupSolana(): Promise<{\n mnemonic: string;\n solanaPrivateKeyBytes: Uint8Array;\n}> {\n // Safety: mnemonic must not already exist\n const existing = await loadMnemonic();\n if (existing) {\n throw new Error(\"Solana wallet already set up. Mnemonic file exists at \" + MNEMONIC_FILE);\n }\n\n // Safety: wallet.key must exist (can't set up Solana without EVM wallet)\n const savedKey = await loadSavedWallet();\n if (!savedKey) {\n throw new Error(\n \"No EVM wallet found. Run ckcloud first to generate a wallet before setting up Solana.\",\n );\n }\n\n // Generate new mnemonic for Solana derivation\n const mnemonic = generateWalletMnemonic();\n const solanaKeyBytes = deriveSolanaKeyBytes(mnemonic);\n\n // Save mnemonic (wallet.key untouched)\n await saveMnemonic(mnemonic);\n\n console.log(`[ckcloud] Solana wallet set up successfully.`);\n console.log(`[ckcloud] Mnemonic saved to ${MNEMONIC_FILE}`);\n console.log(`[ckcloud] Existing EVM wallet unchanged.`);\n\n return { mnemonic, solanaPrivateKeyBytes: solanaKeyBytes };\n}\n\n/**\n * Persist the user's payment chain selection to disk.\n */\nexport async function savePaymentChain(chain: \"base\" | \"solana\"): Promise<void> {\n await mkdir(WALLET_DIR, { recursive: true });\n await writeFile(CHAIN_FILE, chain + \"\\n\", { mode: 0o600 });\n}\n\n/**\n * Load the persisted payment chain selection from disk.\n * Returns \"base\" if no file exists or the file is invalid.\n */\nexport async function loadPaymentChain(): Promise<\"base\" | \"solana\"> {\n try {\n const content = (await readTextFile(CHAIN_FILE)).trim();\n if (content === \"solana\") return \"solana\";\n return \"base\";\n } catch {\n return \"base\";\n }\n}\n\n/**\n * Resolve payment chain: env var first → persisted file second → default \"base\".\n */\nexport async function resolvePaymentChain(): Promise<\"base\" | \"solana\"> {\n if (process[\"env\"].CKCLOUD_PAYMENT_CHAIN === \"solana\") return \"solana\";\n if (process[\"env\"].CKCLOUD_PAYMENT_CHAIN === \"base\") return \"base\";\n return loadPaymentChain();\n}\n\n/**\n * Auth method: operator enters their wallet private key directly.\n */\nexport const walletKeyAuth: ProviderAuthMethod = {\n id: \"wallet-key\",\n label: \"Wallet Private Key\",\n hint: \"Enter your EVM wallet private key (0x...) for x402 payments to ckcloud\",\n kind: \"api_key\",\n run: async (ctx: ProviderAuthContext): Promise<ProviderAuthResult> => {\n const key = await ctx.prompter.text({\n message: \"Enter your wallet private key (0x...)\",\n validate: (value: string) => {\n const trimmed = value.trim();\n if (!trimmed.startsWith(\"0x\")) return \"Key must start with 0x\";\n if (trimmed.length !== 66) return \"Key must be 66 characters (0x + 64 hex)\";\n if (!/^0x[0-9a-fA-F]{64}$/.test(trimmed)) return \"Key must be valid hex\";\n return undefined;\n },\n });\n\n if (!key || typeof key !== \"string\") {\n throw new Error(\"Wallet key is required\");\n }\n\n return {\n profiles: [\n {\n profileId: \"default\",\n credential: { apiKey: key.trim() },\n },\n ],\n notes: [\n \"Wallet key stored securely in OpenClaw credentials.\",\n \"Your wallet signs x402 USDC payments on Base for each LLM call.\",\n \"Fund your wallet with USDC on Base to start using ckcloud models.\",\n ],\n };\n },\n};\n\n/**\n * Auth method: read wallet key from CKCLOUD_WALLET_KEY environment variable.\n */\nexport const envKeyAuth: ProviderAuthMethod = {\n id: \"env-key\",\n label: \"Environment Variable\",\n hint: \"Use CKCLOUD_WALLET_KEY environment variable\",\n kind: \"api_key\",\n run: async (): Promise<ProviderAuthResult> => {\n const key = process[\"env\"].CKCLOUD_WALLET_KEY;\n\n if (!key) {\n throw new Error(\n \"CKCLOUD_WALLET_KEY environment variable is not set. \" +\n \"Set it to your EVM wallet private key (0x...).\",\n );\n }\n\n return {\n profiles: [\n {\n profileId: \"default\",\n credential: { apiKey: key.trim() },\n },\n ],\n notes: [\"Using wallet key from CKCLOUD_WALLET_KEY environment variable.\"],\n };\n },\n};\n","/**\n * Wallet Key Derivation\n *\n * BIP-39 mnemonic generation + BIP-44 HD key derivation for EVM and Solana.\n *\n * Solana uses SLIP-10 Ed25519 derivation (Phantom/Solflare/Backpack compatible).\n * EVM uses standard BIP-32 secp256k1 derivation.\n */\n\nimport { HDKey } from \"@scure/bip32\";\nimport { generateMnemonic, mnemonicToSeedSync, validateMnemonic } from \"@scure/bip39\";\nimport { wordlist as english } from \"@scure/bip39/wordlists/english\";\nimport { hmac } from \"@noble/hashes/hmac\";\nimport { sha512 } from \"@noble/hashes/sha512\";\nimport { privateKeyToAccount } from \"viem/accounts\";\n\nconst ETH_DERIVATION_PATH = \"m/44'/60'/0'/0/0\";\nconst SOLANA_HARDENED_INDICES = [44 + 0x80000000, 501 + 0x80000000, 0 + 0x80000000, 0 + 0x80000000]; // m/44'/501'/0'/0'\n\nexport interface DerivedKeys {\n mnemonic: string;\n evmPrivateKey: `0x${string}`;\n evmAddress: string;\n solanaPrivateKeyBytes: Uint8Array; // 32 bytes\n}\n\n/**\n * Generate a 24-word BIP-39 mnemonic.\n */\nexport function generateWalletMnemonic(): string {\n return generateMnemonic(english, 256);\n}\n\n/**\n * Validate a BIP-39 mnemonic.\n */\nexport function isValidMnemonic(mnemonic: string): boolean {\n return validateMnemonic(mnemonic, english);\n}\n\n/**\n * Derive EVM private key and address from a BIP-39 mnemonic.\n * Path: m/44'/60'/0'/0/0 (standard Ethereum derivation)\n */\nexport function deriveEvmKey(mnemonic: string): { privateKey: `0x${string}`; address: string } {\n const seed = mnemonicToSeedSync(mnemonic);\n const hdKey = HDKey.fromMasterSeed(seed);\n const derived = hdKey.derive(ETH_DERIVATION_PATH);\n if (!derived.privateKey) throw new Error(\"Failed to derive EVM private key\");\n const hex = `0x${Buffer.from(derived.privateKey).toString(\"hex\")}` as `0x${string}`;\n const account = privateKeyToAccount(hex);\n return { privateKey: hex, address: account.address };\n}\n\n/**\n * Derive 32-byte Solana private key using SLIP-10 Ed25519 derivation.\n * Path: m/44'/501'/0'/0' (Phantom / Solflare / Backpack compatible)\n *\n * Algorithm (SLIP-0010 for Ed25519):\n * 1. Master: HMAC-SHA512(key=\"ed25519 seed\", data=bip39_seed) → IL=key, IR=chainCode\n * 2. For each hardened child index:\n * HMAC-SHA512(key=chainCode, data=0x00 || key || ser32(index)) → split again\n * 3. Final IL (32 bytes) = Ed25519 private key seed\n */\nexport function deriveSolanaKeyBytes(mnemonic: string): Uint8Array {\n const seed = mnemonicToSeedSync(mnemonic);\n\n // Master key from SLIP-10\n let I = hmac(sha512, \"ed25519 seed\", seed);\n let key = I.slice(0, 32);\n let chainCode = I.slice(32);\n\n // Derive each hardened child: m/44'/501'/0'/0'\n for (const index of SOLANA_HARDENED_INDICES) {\n const data = new Uint8Array(37);\n data[0] = 0x00;\n data.set(key, 1);\n // ser32 big-endian\n data[33] = (index >>> 24) & 0xff;\n data[34] = (index >>> 16) & 0xff;\n data[35] = (index >>> 8) & 0xff;\n data[36] = index & 0xff;\n I = hmac(sha512, chainCode, data);\n key = I.slice(0, 32);\n chainCode = I.slice(32);\n }\n\n return new Uint8Array(key);\n}\n\n/**\n * Legacy Solana key derivation using secp256k1 BIP-32 (incorrect for Solana).\n * Kept for migration: sweeping funds from wallets derived with the old method.\n */\nexport function deriveSolanaKeyBytesLegacy(mnemonic: string): Uint8Array {\n const seed = mnemonicToSeedSync(mnemonic);\n const hdKey = HDKey.fromMasterSeed(seed);\n const derived = hdKey.derive(\"m/44'/501'/0'/0'\");\n if (!derived.privateKey) throw new Error(\"Failed to derive legacy Solana private key\");\n return new Uint8Array(derived.privateKey);\n}\n\n/**\n * Derive both EVM and Solana keys from a single mnemonic.\n */\nexport function deriveAllKeys(mnemonic: string): DerivedKeys {\n const { privateKey: evmPrivateKey, address: evmAddress } = deriveEvmKey(mnemonic);\n const solanaPrivateKeyBytes = deriveSolanaKeyBytes(mnemonic);\n return { mnemonic, evmPrivateKey, evmAddress, solanaPrivateKeyBytes };\n}\n\n/**\n * Get the Solana address from 32-byte private key bytes.\n * Uses @solana/kit's createKeyPairSignerFromPrivateKeyBytes (dynamic import).\n */\nexport async function getSolanaAddress(privateKeyBytes: Uint8Array): Promise<string> {\n const { createKeyPairSignerFromPrivateKeyBytes } = await import(\"@solana/kit\");\n const signer = await createKeyPairSignerFromPrivateKeyBytes(privateKeyBytes);\n return signer.address;\n}\n","/**\n * Utilities for hex, bytes, CSPRNG.\n * @module\n */\n/*! noble-hashes - MIT License (c) 2022 Paul Miller (paulmillr.com) */\n\n// We use WebCrypto aka globalThis.crypto, which exists in browsers and node.js 16+.\n// node.js versions earlier than v19 don't declare it in global scope.\n// For node.js, package.json#exports field mapping rewrites import\n// from `crypto` to `cryptoNode`, which imports native module.\n// Makes the utils un-importable in browsers without a bundler.\n// Once node.js 18 is deprecated (2025-04-30), we can just drop the import.\nimport { crypto } from '@noble/hashes/crypto';\n\n/** Checks if something is Uint8Array. Be careful: nodejs Buffer will return true. */\nexport function isBytes(a: unknown): a is Uint8Array {\n return a instanceof Uint8Array || (ArrayBuffer.isView(a) && a.constructor.name === 'Uint8Array');\n}\n\n/** Asserts something is positive integer. */\nexport function anumber(n: number): void {\n if (!Number.isSafeInteger(n) || n < 0) throw new Error('positive integer expected, got ' + n);\n}\n\n/** Asserts something is Uint8Array. */\nexport function abytes(b: Uint8Array | undefined, ...lengths: number[]): void {\n if (!isBytes(b)) throw new Error('Uint8Array expected');\n if (lengths.length > 0 && !lengths.includes(b.length))\n throw new Error('Uint8Array expected of length ' + lengths + ', got length=' + b.length);\n}\n\n/** Asserts something is hash */\nexport function ahash(h: IHash): void {\n if (typeof h !== 'function' || typeof h.create !== 'function')\n throw new Error('Hash should be wrapped by utils.createHasher');\n anumber(h.outputLen);\n anumber(h.blockLen);\n}\n\n/** Asserts a hash instance has not been destroyed / finished */\nexport function aexists(instance: any, checkFinished = true): void {\n if (instance.destroyed) throw new Error('Hash instance has been destroyed');\n if (checkFinished && instance.finished) throw new Error('Hash#digest() has already been called');\n}\n\n/** Asserts output is properly-sized byte array */\nexport function aoutput(out: any, instance: any): void {\n abytes(out);\n const min = instance.outputLen;\n if (out.length < min) {\n throw new Error('digestInto() expects output buffer of length at least ' + min);\n }\n}\n\n/** Generic type encompassing 8/16/32-byte arrays - but not 64-byte. */\n// prettier-ignore\nexport type TypedArray = Int8Array | Uint8ClampedArray | Uint8Array |\n Uint16Array | Int16Array | Uint32Array | Int32Array;\n\n/** Cast u8 / u16 / u32 to u8. */\nexport function u8(arr: TypedArray): Uint8Array {\n return new Uint8Array(arr.buffer, arr.byteOffset, arr.byteLength);\n}\n\n/** Cast u8 / u16 / u32 to u32. */\nexport function u32(arr: TypedArray): Uint32Array {\n return new Uint32Array(arr.buffer, arr.byteOffset, Math.floor(arr.byteLength / 4));\n}\n\n/** Zeroize a byte array. Warning: JS provides no guarantees. */\nexport function clean(...arrays: TypedArray[]): void {\n for (let i = 0; i < arrays.length; i++) {\n arrays[i].fill(0);\n }\n}\n\n/** Create DataView of an array for easy byte-level manipulation. */\nexport function createView(arr: TypedArray): DataView {\n return new DataView(arr.buffer, arr.byteOffset, arr.byteLength);\n}\n\n/** The rotate right (circular right shift) operation for uint32 */\nexport function rotr(word: number, shift: number): number {\n return (word << (32 - shift)) | (word >>> shift);\n}\n\n/** The rotate left (circular left shift) operation for uint32 */\nexport function rotl(word: number, shift: number): number {\n return (word << shift) | ((word >>> (32 - shift)) >>> 0);\n}\n\n/** Is current platform little-endian? Most are. Big-Endian platform: IBM */\nexport const isLE: boolean = /* @__PURE__ */ (() =>\n new Uint8Array(new Uint32Array([0x11223344]).buffer)[0] === 0x44)();\n\n/** The byte swap operation for uint32 */\nexport function byteSwap(word: number): number {\n return (\n ((word << 24) & 0xff000000) |\n ((word << 8) & 0xff0000) |\n ((word >>> 8) & 0xff00) |\n ((word >>> 24) & 0xff)\n );\n}\n/** Conditionally byte swap if on a big-endian platform */\nexport const swap8IfBE: (n: number) => number = isLE\n ? (n: number) => n\n : (n: number) => byteSwap(n);\n\n/** @deprecated */\nexport const byteSwapIfBE: typeof swap8IfBE = swap8IfBE;\n/** In place byte swap for Uint32Array */\nexport function byteSwap32(arr: Uint32Array): Uint32Array {\n for (let i = 0; i < arr.length; i++) {\n arr[i] = byteSwap(arr[i]);\n }\n return arr;\n}\n\nexport const swap32IfBE: (u: Uint32Array) => Uint32Array = isLE\n ? (u: Uint32Array) => u\n : byteSwap32;\n\n// Built-in hex conversion https://caniuse.com/mdn-javascript_builtins_uint8array_fromhex\nconst hasHexBuiltin: boolean = /* @__PURE__ */ (() =>\n // @ts-ignore\n typeof Uint8Array.from([]).toHex === 'function' && typeof Uint8Array.fromHex === 'function')();\n\n// Array where index 0xf0 (240) is mapped to string 'f0'\nconst hexes = /* @__PURE__ */ Array.from({ length: 256 }, (_, i) =>\n i.toString(16).padStart(2, '0')\n);\n\n/**\n * Convert byte array to hex string. Uses built-in function, when available.\n * @example bytesToHex(Uint8Array.from([0xca, 0xfe, 0x01, 0x23])) // 'cafe0123'\n */\nexport function bytesToHex(bytes: Uint8Array): string {\n abytes(bytes);\n // @ts-ignore\n if (hasHexBuiltin) return bytes.toHex();\n // pre-caching improves the speed 6x\n let hex = '';\n for (let i = 0; i < bytes.length; i++) {\n hex += hexes[bytes[i]];\n }\n return hex;\n}\n\n// We use optimized technique to convert hex string to byte array\nconst asciis = { _0: 48, _9: 57, A: 65, F: 70, a: 97, f: 102 } as const;\nfunction asciiToBase16(ch: number): number | undefined {\n if (ch >= asciis._0 && ch <= asciis._9) return ch - asciis._0; // '2' => 50-48\n if (ch >= asciis.A && ch <= asciis.F) return ch - (asciis.A - 10); // 'B' => 66-(65-10)\n if (ch >= asciis.a && ch <= asciis.f) return ch - (asciis.a - 10); // 'b' => 98-(97-10)\n return;\n}\n\n/**\n * Convert hex string to byte array. Uses built-in function, when available.\n * @example hexToBytes('cafe0123') // Uint8Array.from([0xca, 0xfe, 0x01, 0x23])\n */\nexport function hexToBytes(hex: string): Uint8Array {\n if (typeof hex !== 'string') throw new Error('hex string expected, got ' + typeof hex);\n // @ts-ignore\n if (hasHexBuiltin) return Uint8Array.fromHex(hex);\n const hl = hex.length;\n const al = hl / 2;\n if (hl % 2) throw new Error('hex string expected, got unpadded hex of length ' + hl);\n const array = new Uint8Array(al);\n for (let ai = 0, hi = 0; ai < al; ai++, hi += 2) {\n const n1 = asciiToBase16(hex.charCodeAt(hi));\n const n2 = asciiToBase16(hex.charCodeAt(hi + 1));\n if (n1 === undefined || n2 === undefined) {\n const char = hex[hi] + hex[hi + 1];\n throw new Error('hex string expected, got non-hex character \"' + char + '\" at index ' + hi);\n }\n array[ai] = n1 * 16 + n2; // multiply first octet, e.g. 'a3' => 10*16+3 => 160 + 3 => 163\n }\n return array;\n}\n\n/**\n * There is no setImmediate in browser and setTimeout is slow.\n * Call of async fn will return Promise, which will be fullfiled only on\n * next scheduler queue processing step and this is exactly what we need.\n */\nexport const nextTick = async (): Promise<void> => {};\n\n/** Returns control to thread each 'tick' ms to avoid blocking. */\nexport async function asyncLoop(\n iters: number,\n tick: number,\n cb: (i: number) => void\n): Promise<void> {\n let ts = Date.now();\n for (let i = 0; i < iters; i++) {\n cb(i);\n // Date.now() is not monotonic, so in case if clock goes backwards we return return control too\n const diff = Date.now() - ts;\n if (diff >= 0 && diff < tick) continue;\n await nextTick();\n ts += diff;\n }\n}\n\n// Global symbols, but ts doesn't see them: https://github.com/microsoft/TypeScript/issues/31535\ndeclare const TextEncoder: any;\ndeclare const TextDecoder: any;\n\n/**\n * Converts string to bytes using UTF8 encoding.\n * @example utf8ToBytes('abc') // Uint8Array.from([97, 98, 99])\n */\nexport function utf8ToBytes(str: string): Uint8Array {\n if (typeof str !== 'string') throw new Error('string expected');\n return new Uint8Array(new TextEncoder().encode(str)); // https://bugzil.la/1681809\n}\n\n/**\n * Converts bytes to string using UTF8 encoding.\n * @example bytesToUtf8(Uint8Array.from([97, 98, 99])) // 'abc'\n */\nexport function bytesToUtf8(bytes: Uint8Array): string {\n return new TextDecoder().decode(bytes);\n}\n\n/** Accepted input of hash functions. Strings are converted to byte arrays. */\nexport type Input = string | Uint8Array;\n/**\n * Normalizes (non-hex) string or Uint8Array to Uint8Array.\n * Warning: when Uint8Array is passed, it would NOT get copied.\n * Keep in mind for future mutable operations.\n */\nexport function toBytes(data: Input): Uint8Array {\n if (typeof data === 'string') data = utf8ToBytes(data);\n abytes(data);\n return data;\n}\n\n/** KDFs can accept string or Uint8Array for user convenience. */\nexport type KDFInput = string | Uint8Array;\n/**\n * Helper for KDFs: consumes uint8array or string.\n * When string is passed, does utf8 decoding, using TextDecoder.\n */\nexport function kdfInputToBytes(data: KDFInput): Uint8Array {\n if (typeof data === 'string') data = utf8ToBytes(data);\n abytes(data);\n return data;\n}\n\n/** Copies several Uint8Arrays into one. */\nexport function concatBytes(...arrays: Uint8Array[]): Uint8Array {\n let sum = 0;\n for (let i = 0; i < arrays.length; i++) {\n const a = arrays[i];\n abytes(a);\n sum += a.length;\n }\n const res = new Uint8Array(sum);\n for (let i = 0, pad = 0; i < arrays.length; i++) {\n const a = arrays[i];\n res.set(a, pad);\n pad += a.length;\n }\n return res;\n}\n\ntype EmptyObj = {};\nexport function checkOpts<T1 extends EmptyObj, T2 extends EmptyObj>(\n defaults: T1,\n opts?: T2\n): T1 & T2 {\n if (opts !== undefined && {}.toString.call(opts) !== '[object Object]')\n throw new Error('options should be object or undefined');\n const merged = Object.assign(defaults, opts);\n return merged as T1 & T2;\n}\n\n/** Hash interface. */\nexport type IHash = {\n (data: Uint8Array): Uint8Array;\n blockLen: number;\n outputLen: number;\n create: any;\n};\n\n/** For runtime check if class implements interface */\nexport abstract class Hash<T extends Hash<T>> {\n abstract blockLen: number; // Bytes per block\n abstract outputLen: number; // Bytes in output\n abstract update(buf: Input): this;\n // Writes digest into buf\n abstract digestInto(buf: Uint8Array): void;\n abstract digest(): Uint8Array;\n /**\n * Resets internal state. Makes Hash instance unusable.\n * Reset is impossible for keyed hashes if key is consumed into state. If digest is not consumed\n * by user, they will need to manually call `destroy()` when zeroing is necessary.\n */\n abstract destroy(): void;\n /**\n * Clones hash instance. Unsafe: doesn't check whether `to` is valid. Can be used as `clone()`\n * when no options are passed.\n * Reasons to use `_cloneInto` instead of clone: 1) performance 2) reuse instance => all internal\n * buffers are overwritten => causes buffer overwrite which is used for digest in some cases.\n * There are no guarantees for clean-up because it's impossible in JS.\n */\n abstract _cloneInto(to?: T): T;\n // Safe version that clones internal state\n abstract clone(): T;\n}\n\n/**\n * XOF: streaming API to read digest in chunks.\n * Same as 'squeeze' in keccak/k12 and 'seek' in blake3, but more generic name.\n * When hash used in XOF mode it is up to user to call '.destroy' afterwards, since we cannot\n * destroy state, next call can require more bytes.\n */\nexport type HashXOF<T extends Hash<T>> = Hash<T> & {\n xof(bytes: number): Uint8Array; // Read 'bytes' bytes from digest stream\n xofInto(buf: Uint8Array): Uint8Array; // read buf.length bytes from digest stream into buf\n};\n\n/** Hash function */\nexport type CHash = ReturnType<typeof createHasher>;\n/** Hash function with output */\nexport type CHashO = ReturnType<typeof createOptHasher>;\n/** XOF with output */\nexport type CHashXO = ReturnType<typeof createXOFer>;\n\n/** Wraps hash function, creating an interface on top of it */\nexport function createHasher<T extends Hash<T>>(\n hashCons: () => Hash<T>\n): {\n (msg: Input): Uint8Array;\n outputLen: number;\n blockLen: number;\n create(): Hash<T>;\n} {\n const hashC = (msg: Input): Uint8Array => hashCons().update(toBytes(msg)).digest();\n const tmp = hashCons();\n hashC.outputLen = tmp.outputLen;\n hashC.blockLen = tmp.blockLen;\n hashC.create = () => hashCons();\n return hashC;\n}\n\nexport function createOptHasher<H extends Hash<H>, T extends Object>(\n hashCons: (opts?: T) => Hash<H>\n): {\n (msg: Input, opts?: T): Uint8Array;\n outputLen: number;\n blockLen: number;\n create(opts?: T): Hash<H>;\n} {\n const hashC = (msg: Input, opts?: T): Uint8Array => hashCons(opts).update(toBytes(msg)).digest();\n const tmp = hashCons({} as T);\n hashC.outputLen = tmp.outputLen;\n hashC.blockLen = tmp.blockLen;\n hashC.create = (opts?: T) => hashCons(opts);\n return hashC;\n}\n\nexport function createXOFer<H extends HashXOF<H>, T extends Object>(\n hashCons: (opts?: T) => HashXOF<H>\n): {\n (msg: Input, opts?: T): Uint8Array;\n outputLen: number;\n blockLen: number;\n create(opts?: T): HashXOF<H>;\n} {\n const hashC = (msg: Input, opts?: T): Uint8Array => hashCons(opts).update(toBytes(msg)).digest();\n const tmp = hashCons({} as T);\n hashC.outputLen = tmp.outputLen;\n hashC.blockLen = tmp.blockLen;\n hashC.create = (opts?: T) => hashCons(opts);\n return hashC;\n}\nexport const wrapConstructor: typeof createHasher = createHasher;\nexport const wrapConstructorWithOpts: typeof createOptHasher = createOptHasher;\nexport const wrapXOFConstructorWithOpts: typeof createXOFer = createXOFer;\n\n/** Cryptographically secure PRNG. Uses internal OS-level `crypto.getRandomValues`. */\nexport function randomBytes(bytesLength = 32): Uint8Array {\n if (crypto && typeof crypto.getRandomValues === 'function') {\n return crypto.getRandomValues(new Uint8Array(bytesLength));\n }\n // Legacy Node.js compatibility\n if (crypto && typeof crypto.randomBytes === 'function') {\n return Uint8Array.from(crypto.randomBytes(bytesLength));\n }\n throw new Error('crypto.getRandomValues must be defined');\n}\n","/**\n * HMAC: RFC2104 message authentication code.\n * @module\n */\nimport { abytes, aexists, ahash, clean, Hash, toBytes, type CHash, type Input } from './utils.ts';\n\nexport class HMAC<T extends Hash<T>> extends Hash<HMAC<T>> {\n oHash: T;\n iHash: T;\n blockLen: number;\n outputLen: number;\n private finished = false;\n private destroyed = false;\n\n constructor(hash: CHash, _key: Input) {\n super();\n ahash(hash);\n const key = toBytes(_key);\n this.iHash = hash.create() as T;\n if (typeof this.iHash.update !== 'function')\n throw new Error('Expected instance of class which extends utils.Hash');\n this.blockLen = this.iHash.blockLen;\n this.outputLen = this.iHash.outputLen;\n const blockLen = this.blockLen;\n const pad = new Uint8Array(blockLen);\n // blockLen can be bigger than outputLen\n pad.set(key.length > blockLen ? hash.create().update(key).digest() : key);\n for (let i = 0; i < pad.length; i++) pad[i] ^= 0x36;\n this.iHash.update(pad);\n // By doing update (processing of first block) of outer hash here we can re-use it between multiple calls via clone\n this.oHash = hash.create() as T;\n // Undo internal XOR && apply outer XOR\n for (let i = 0; i < pad.length; i++) pad[i] ^= 0x36 ^ 0x5c;\n this.oHash.update(pad);\n clean(pad);\n }\n update(buf: Input): this {\n aexists(this);\n this.iHash.update(buf);\n return this;\n }\n digestInto(out: Uint8Array): void {\n aexists(this);\n abytes(out, this.outputLen);\n this.finished = true;\n this.iHash.digestInto(out);\n this.oHash.update(out);\n this.oHash.digestInto(out);\n this.destroy();\n }\n digest(): Uint8Array {\n const out = new Uint8Array(this.oHash.outputLen);\n this.digestInto(out);\n return out;\n }\n _cloneInto(to?: HMAC<T>): HMAC<T> {\n // Create new instance without calling constructor since key already in state and we don't know it.\n to ||= Object.create(Object.getPrototypeOf(this), {});\n const { oHash, iHash, finished, destroyed, blockLen, outputLen } = this;\n to = to as this;\n to.finished = finished;\n to.destroyed = destroyed;\n to.blockLen = blockLen;\n to.outputLen = outputLen;\n to.oHash = oHash._cloneInto(to.oHash);\n to.iHash = iHash._cloneInto(to.iHash);\n return to;\n }\n clone(): HMAC<T> {\n return this._cloneInto();\n }\n destroy(): void {\n this.destroyed = true;\n this.oHash.destroy();\n this.iHash.destroy();\n }\n}\n\n/**\n * HMAC: RFC2104 message authentication code.\n * @param hash - function that would be used e.g. sha256\n * @param key - message key\n * @param message - message data\n * @example\n * import { hmac } from '@noble/hashes/hmac';\n * import { sha256 } from '@noble/hashes/sha2';\n * const mac1 = hmac(sha256, 'key', 'message');\n */\nexport const hmac: {\n (hash: CHash, key: Input, message: Input): Uint8Array;\n create(hash: CHash, key: Input): HMAC<any>;\n} = (hash: CHash, key: Input, message: Input): Uint8Array =>\n new HMAC<any>(hash, key).update(message).digest();\nhmac.create = (hash: CHash, key: Input) => new HMAC<any>(hash, key);\n","/**\n * Internal Merkle-Damgard hash utils.\n * @module\n */\nimport { type Input, Hash, abytes, aexists, aoutput, clean, createView, toBytes } from './utils.ts';\n\n/** Polyfill for Safari 14. https://caniuse.com/mdn-javascript_builtins_dataview_setbiguint64 */\nexport function setBigUint64(\n view: DataView,\n byteOffset: number,\n value: bigint,\n isLE: boolean\n): void {\n if (typeof view.setBigUint64 === 'function') return view.setBigUint64(byteOffset, value, isLE);\n const _32n = BigInt(32);\n const _u32_max = BigInt(0xffffffff);\n const wh = Number((value >> _32n) & _u32_max);\n const wl = Number(value & _u32_max);\n const h = isLE ? 4 : 0;\n const l = isLE ? 0 : 4;\n view.setUint32(byteOffset + h, wh, isLE);\n view.setUint32(byteOffset + l, wl, isLE);\n}\n\n/** Choice: a ? b : c */\nexport function Chi(a: number, b: number, c: number): number {\n return (a & b) ^ (~a & c);\n}\n\n/** Majority function, true if any two inputs is true. */\nexport function Maj(a: number, b: number, c: number): number {\n return (a & b) ^ (a & c) ^ (b & c);\n}\n\n/**\n * Merkle-Damgard hash construction base class.\n * Could be used to create MD5, RIPEMD, SHA1, SHA2.\n */\nexport abstract class HashMD<T extends HashMD<T>> extends Hash<T> {\n protected abstract process(buf: DataView, offset: number): void;\n protected abstract get(): number[];\n protected abstract set(...args: number[]): void;\n abstract destroy(): void;\n protected abstract roundClean(): void;\n\n readonly blockLen: number;\n readonly outputLen: number;\n readonly padOffset: number;\n readonly isLE: boolean;\n\n // For partial updates less than block size\n protected buffer: Uint8Array;\n protected view: DataView;\n protected finished = false;\n protected length = 0;\n protected pos = 0;\n protected destroyed = false;\n\n constructor(blockLen: number, outputLen: number, padOffset: number, isLE: boolean) {\n super();\n this.blockLen = blockLen;\n this.outputLen = outputLen;\n this.padOffset = padOffset;\n this.isLE = isLE;\n this.buffer = new Uint8Array(blockLen);\n this.view = createView(this.buffer);\n }\n update(data: Input): this {\n aexists(this);\n data = toBytes(data);\n abytes(data);\n const { view, buffer, blockLen } = this;\n const len = data.length;\n for (let pos = 0; pos < len; ) {\n const take = Math.min(blockLen - this.pos, len - pos);\n // Fast path: we have at least one block in input, cast it to view and process\n if (take === blockLen) {\n const dataView = createView(data);\n for (; blockLen <= len - pos; pos += blockLen) this.process(dataView, pos);\n continue;\n }\n buffer.set(data.subarray(pos, pos + take), this.pos);\n this.pos += take;\n pos += take;\n if (this.pos === blockLen) {\n this.process(view, 0);\n this.pos = 0;\n }\n }\n this.length += data.length;\n this.roundClean();\n return this;\n }\n digestInto(out: Uint8Array): void {\n aexists(this);\n aoutput(out, this);\n this.finished = true;\n // Padding\n // We can avoid allocation of buffer for padding completely if it\n // was previously not allocated here. But it won't change performance.\n const { buffer, view, blockLen, isLE } = this;\n let { pos } = this;\n // append the bit '1' to the message\n buffer[pos++] = 0b10000000;\n clean(this.buffer.subarray(pos));\n // we have less than padOffset left in buffer, so we cannot put length in\n // current block, need process it and pad again\n if (this.padOffset > blockLen - pos) {\n this.process(view, 0);\n pos = 0;\n }\n // Pad until full block byte with zeros\n for (let i = pos; i < blockLen; i++) buffer[i] = 0;\n // Note: sha512 requires length to be 128bit integer, but length in JS will overflow before that\n // You need to write around 2 exabytes (u64_max / 8 / (1024**6)) for this to happen.\n // So we just write lowest 64 bits of that value.\n setBigUint64(view, blockLen - 8, BigInt(this.length * 8), isLE);\n this.process(view, 0);\n const oview = createView(out);\n const len = this.outputLen;\n // NOTE: we do division by 4 later, which should be fused in single op with modulo by JIT\n if (len % 4) throw new Error('_sha2: outputLen should be aligned to 32bit');\n const outLen = len / 4;\n const state = this.get();\n if (outLen > state.length) throw new Error('_sha2: outputLen bigger than state');\n for (let i = 0; i < outLen; i++) oview.setUint32(4 * i, state[i], isLE);\n }\n digest(): Uint8Array {\n const { buffer, outputLen } = this;\n this.digestInto(buffer);\n const res = buffer.slice(0, outputLen);\n this.destroy();\n return res;\n }\n _cloneInto(to?: T): T {\n to ||= new (this.constructor as any)() as T;\n to.set(...this.get());\n const { blockLen, buffer, length, finished, destroyed, pos } = this;\n to.destroyed = destroyed;\n to.finished = finished;\n to.length = length;\n to.pos = pos;\n if (length % blockLen) to.buffer.set(buffer);\n return to;\n }\n clone(): T {\n return this._cloneInto();\n }\n}\n\n/**\n * Initial SHA-2 state: fractional parts of square roots of first 16 primes 2..53.\n * Check out `test/misc/sha2-gen-iv.js` for recomputation guide.\n */\n\n/** Initial SHA256 state. Bits 0..32 of frac part of sqrt of primes 2..19 */\nexport const SHA256_IV: Uint32Array = /* @__PURE__ */ Uint32Array.from([\n 0x6a09e667, 0xbb67ae85, 0x3c6ef372, 0xa54ff53a, 0x510e527f, 0x9b05688c, 0x1f83d9ab, 0x5be0cd19,\n]);\n\n/** Initial SHA224 state. Bits 32..64 of frac part of sqrt of primes 23..53 */\nexport const SHA224_IV: Uint32Array = /* @__PURE__ */ Uint32Array.from([\n 0xc1059ed8, 0x367cd507, 0x3070dd17, 0xf70e5939, 0xffc00b31, 0x68581511, 0x64f98fa7, 0xbefa4fa4,\n]);\n\n/** Initial SHA384 state. Bits 0..64 of frac part of sqrt of primes 23..53 */\nexport const SHA384_IV: Uint32Array = /* @__PURE__ */ Uint32Array.from([\n 0xcbbb9d5d, 0xc1059ed8, 0x629a292a, 0x367cd507, 0x9159015a, 0x3070dd17, 0x152fecd8, 0xf70e5939,\n 0x67332667, 0xffc00b31, 0x8eb44a87, 0x68581511, 0xdb0c2e0d, 0x64f98fa7, 0x47b5481d, 0xbefa4fa4,\n]);\n\n/** Initial SHA512 state. Bits 0..64 of frac part of sqrt of primes 2..19 */\nexport const SHA512_IV: Uint32Array = /* @__PURE__ */ Uint32Array.from([\n 0x6a09e667, 0xf3bcc908, 0xbb67ae85, 0x84caa73b, 0x3c6ef372, 0xfe94f82b, 0xa54ff53a, 0x5f1d36f1,\n 0x510e527f, 0xade682d1, 0x9b05688c, 0x2b3e6c1f, 0x1f83d9ab, 0xfb41bd6b, 0x5be0cd19, 0x137e2179,\n]);\n","/**\n * Internal helpers for u64. BigUint64Array is too slow as per 2025, so we implement it using Uint32Array.\n * @todo re-check https://issues.chromium.org/issues/42212588\n * @module\n */\nconst U32_MASK64 = /* @__PURE__ */ BigInt(2 ** 32 - 1);\nconst _32n = /* @__PURE__ */ BigInt(32);\n\nfunction fromBig(\n n: bigint,\n le = false\n): {\n h: number;\n l: number;\n} {\n if (le) return { h: Number(n & U32_MASK64), l: Number((n >> _32n) & U32_MASK64) };\n return { h: Number((n >> _32n) & U32_MASK64) | 0, l: Number(n & U32_MASK64) | 0 };\n}\n\nfunction split(lst: bigint[], le = false): Uint32Array[] {\n const len = lst.length;\n let Ah = new Uint32Array(len);\n let Al = new Uint32Array(len);\n for (let i = 0; i < len; i++) {\n const { h, l } = fromBig(lst[i], le);\n [Ah[i], Al[i]] = [h, l];\n }\n return [Ah, Al];\n}\n\nconst toBig = (h: number, l: number): bigint => (BigInt(h >>> 0) << _32n) | BigInt(l >>> 0);\n// for Shift in [0, 32)\nconst shrSH = (h: number, _l: number, s: number): number => h >>> s;\nconst shrSL = (h: number, l: number, s: number): number => (h << (32 - s)) | (l >>> s);\n// Right rotate for Shift in [1, 32)\nconst rotrSH = (h: number, l: number, s: number): number => (h >>> s) | (l << (32 - s));\nconst rotrSL = (h: number, l: number, s: number): number => (h << (32 - s)) | (l >>> s);\n// Right rotate for Shift in (32, 64), NOTE: 32 is special case.\nconst rotrBH = (h: number, l: number, s: number): number => (h << (64 - s)) | (l >>> (s - 32));\nconst rotrBL = (h: number, l: number, s: number): number => (h >>> (s - 32)) | (l << (64 - s));\n// Right rotate for shift===32 (just swaps l&h)\nconst rotr32H = (_h: number, l: number): number => l;\nconst rotr32L = (h: number, _l: number): number => h;\n// Left rotate for Shift in [1, 32)\nconst rotlSH = (h: number, l: number, s: number): number => (h << s) | (l >>> (32 - s));\nconst rotlSL = (h: number, l: number, s: number): number => (l << s) | (h >>> (32 - s));\n// Left rotate for Shift in (32, 64), NOTE: 32 is special case.\nconst rotlBH = (h: number, l: number, s: number): number => (l << (s - 32)) | (h >>> (64 - s));\nconst rotlBL = (h: number, l: number, s: number): number => (h << (s - 32)) | (l >>> (64 - s));\n\n// JS uses 32-bit signed integers for bitwise operations which means we cannot\n// simple take carry out of low bit sum by shift, we need to use division.\nfunction add(\n Ah: number,\n Al: number,\n Bh: number,\n Bl: number\n): {\n h: number;\n l: number;\n} {\n const l = (Al >>> 0) + (Bl >>> 0);\n return { h: (Ah + Bh + ((l / 2 ** 32) | 0)) | 0, l: l | 0 };\n}\n// Addition with more than 2 elements\nconst add3L = (Al: number, Bl: number, Cl: number): number => (Al >>> 0) + (Bl >>> 0) + (Cl >>> 0);\nconst add3H = (low: number, Ah: number, Bh: number, Ch: number): number =>\n (Ah + Bh + Ch + ((low / 2 ** 32) | 0)) | 0;\nconst add4L = (Al: number, Bl: number, Cl: number, Dl: number): number =>\n (Al >>> 0) + (Bl >>> 0) + (Cl >>> 0) + (Dl >>> 0);\nconst add4H = (low: number, Ah: number, Bh: number, Ch: number, Dh: number): number =>\n (Ah + Bh + Ch + Dh + ((low / 2 ** 32) | 0)) | 0;\nconst add5L = (Al: number, Bl: number, Cl: number, Dl: number, El: number): number =>\n (Al >>> 0) + (Bl >>> 0) + (Cl >>> 0) + (Dl >>> 0) + (El >>> 0);\nconst add5H = (low: number, Ah: number, Bh: number, Ch: number, Dh: number, Eh: number): number =>\n (Ah + Bh + Ch + Dh + Eh + ((low / 2 ** 32) | 0)) | 0;\n\n// prettier-ignore\nexport {\n add, add3H, add3L, add4H, add4L, add5H, add5L, fromBig, rotlBH, rotlBL, rotlSH, rotlSL, rotr32H, rotr32L, rotrBH, rotrBL, rotrSH, rotrSL, shrSH, shrSL, split, toBig\n};\n// prettier-ignore\nconst u64: { fromBig: typeof fromBig; split: typeof split; toBig: (h: number, l: number) => bigint; shrSH: (h: number, _l: number, s: number) => number; shrSL: (h: number, l: number, s: number) => number; rotrSH: (h: number, l: number, s: number) => number; rotrSL: (h: number, l: number, s: number) => number; rotrBH: (h: number, l: number, s: number) => number; rotrBL: (h: number, l: number, s: number) => number; rotr32H: (_h: number, l: number) => number; rotr32L: (h: number, _l: number) => number; rotlSH: (h: number, l: number, s: number) => number; rotlSL: (h: number, l: number, s: number) => number; rotlBH: (h: number, l: number, s: number) => number; rotlBL: (h: number, l: number, s: number) => number; add: typeof add; add3L: (Al: number, Bl: number, Cl: number) => number; add3H: (low: number, Ah: number, Bh: number, Ch: number) => number; add4L: (Al: number, Bl: number, Cl: number, Dl: number) => number; add4H: (low: number, Ah: number, Bh: number, Ch: number, Dh: number) => number; add5H: (low: number, Ah: number, Bh: number, Ch: number, Dh: number, Eh: number) => number; add5L: (Al: number, Bl: number, Cl: number, Dl: number, El: number) => number; } = {\n fromBig, split, toBig,\n shrSH, shrSL,\n rotrSH, rotrSL, rotrBH, rotrBL,\n rotr32H, rotr32L,\n rotlSH, rotlSL, rotlBH, rotlBL,\n add, add3L, add3H, add4L, add4H, add5H, add5L,\n};\nexport default u64;\n","/**\n * SHA2 hash function. A.k.a. sha256, sha384, sha512, sha512_224, sha512_256.\n * SHA256 is the fastest hash implementable in JS, even faster than Blake3.\n * Check out [RFC 4634](https://datatracker.ietf.org/doc/html/rfc4634) and\n * [FIPS 180-4](https://nvlpubs.nist.gov/nistpubs/FIPS/NIST.FIPS.180-4.pdf).\n * @module\n */\nimport { Chi, HashMD, Maj, SHA224_IV, SHA256_IV, SHA384_IV, SHA512_IV } from './_md.ts';\nimport * as u64 from './_u64.ts';\nimport { type CHash, clean, createHasher, rotr } from './utils.ts';\n\n/**\n * Round constants:\n * First 32 bits of fractional parts of the cube roots of the first 64 primes 2..311)\n */\n// prettier-ignore\nconst SHA256_K = /* @__PURE__ */ Uint32Array.from([\n 0x428a2f98, 0x71374491, 0xb5c0fbcf, 0xe9b5dba5, 0x3956c25b, 0x59f111f1, 0x923f82a4, 0xab1c5ed5,\n 0xd807aa98, 0x12835b01, 0x243185be, 0x550c7dc3, 0x72be5d74, 0x80deb1fe, 0x9bdc06a7, 0xc19bf174,\n 0xe49b69c1, 0xefbe4786, 0x0fc19dc6, 0x240ca1cc, 0x2de92c6f, 0x4a7484aa, 0x5cb0a9dc, 0x76f988da,\n 0x983e5152, 0xa831c66d, 0xb00327c8, 0xbf597fc7, 0xc6e00bf3, 0xd5a79147, 0x06ca6351, 0x14292967,\n 0x27b70a85, 0x2e1b2138, 0x4d2c6dfc, 0x53380d13, 0x650a7354, 0x766a0abb, 0x81c2c92e, 0x92722c85,\n 0xa2bfe8a1, 0xa81a664b, 0xc24b8b70, 0xc76c51a3, 0xd192e819, 0xd6990624, 0xf40e3585, 0x106aa070,\n 0x19a4c116, 0x1e376c08, 0x2748774c, 0x34b0bcb5, 0x391c0cb3, 0x4ed8aa4a, 0x5b9cca4f, 0x682e6ff3,\n 0x748f82ee, 0x78a5636f, 0x84c87814, 0x8cc70208, 0x90befffa, 0xa4506ceb, 0xbef9a3f7, 0xc67178f2\n]);\n\n/** Reusable temporary buffer. \"W\" comes straight from spec. */\nconst SHA256_W = /* @__PURE__ */ new Uint32Array(64);\nexport class SHA256 extends HashMD<SHA256> {\n // We cannot use array here since array allows indexing by variable\n // which means optimizer/compiler cannot use registers.\n protected A: number = SHA256_IV[0] | 0;\n protected B: number = SHA256_IV[1] | 0;\n protected C: number = SHA256_IV[2] | 0;\n protected D: number = SHA256_IV[3] | 0;\n protected E: number = SHA256_IV[4] | 0;\n protected F: number = SHA256_IV[5] | 0;\n protected G: number = SHA256_IV[6] | 0;\n protected H: number = SHA256_IV[7] | 0;\n\n constructor(outputLen: number = 32) {\n super(64, outputLen, 8, false);\n }\n protected get(): [number, number, number, number, number, number, number, number] {\n const { A, B, C, D, E, F, G, H } = this;\n return [A, B, C, D, E, F, G, H];\n }\n // prettier-ignore\n protected set(\n A: number, B: number, C: number, D: number, E: number, F: number, G: number, H: number\n ): void {\n this.A = A | 0;\n this.B = B | 0;\n this.C = C | 0;\n this.D = D | 0;\n this.E = E | 0;\n this.F = F | 0;\n this.G = G | 0;\n this.H = H | 0;\n }\n protected process(view: DataView, offset: number): void {\n // Extend the first 16 words into the remaining 48 words w[16..63] of the message schedule array\n for (let i = 0; i < 16; i++, offset += 4) SHA256_W[i] = view.getUint32(offset, false);\n for (let i = 16; i < 64; i++) {\n const W15 = SHA256_W[i - 15];\n const W2 = SHA256_W[i - 2];\n const s0 = rotr(W15, 7) ^ rotr(W15, 18) ^ (W15 >>> 3);\n const s1 = rotr(W2, 17) ^ rotr(W2, 19) ^ (W2 >>> 10);\n SHA256_W[i] = (s1 + SHA256_W[i - 7] + s0 + SHA256_W[i - 16]) | 0;\n }\n // Compression function main loop, 64 rounds\n let { A, B, C, D, E, F, G, H } = this;\n for (let i = 0; i < 64; i++) {\n const sigma1 = rotr(E, 6) ^ rotr(E, 11) ^ rotr(E, 25);\n const T1 = (H + sigma1 + Chi(E, F, G) + SHA256_K[i] + SHA256_W[i]) | 0;\n const sigma0 = rotr(A, 2) ^ rotr(A, 13) ^ rotr(A, 22);\n const T2 = (sigma0 + Maj(A, B, C)) | 0;\n H = G;\n G = F;\n F = E;\n E = (D + T1) | 0;\n D = C;\n C = B;\n B = A;\n A = (T1 + T2) | 0;\n }\n // Add the compressed chunk to the current hash value\n A = (A + this.A) | 0;\n B = (B + this.B) | 0;\n C = (C + this.C) | 0;\n D = (D + this.D) | 0;\n E = (E + this.E) | 0;\n F = (F + this.F) | 0;\n G = (G + this.G) | 0;\n H = (H + this.H) | 0;\n this.set(A, B, C, D, E, F, G, H);\n }\n protected roundClean(): void {\n clean(SHA256_W);\n }\n destroy(): void {\n this.set(0, 0, 0, 0, 0, 0, 0, 0);\n clean(this.buffer);\n }\n}\n\nexport class SHA224 extends SHA256 {\n protected A: number = SHA224_IV[0] | 0;\n protected B: number = SHA224_IV[1] | 0;\n protected C: number = SHA224_IV[2] | 0;\n protected D: number = SHA224_IV[3] | 0;\n protected E: number = SHA224_IV[4] | 0;\n protected F: number = SHA224_IV[5] | 0;\n protected G: number = SHA224_IV[6] | 0;\n protected H: number = SHA224_IV[7] | 0;\n constructor() {\n super(28);\n }\n}\n\n// SHA2-512 is slower than sha256 in js because u64 operations are slow.\n\n// Round contants\n// First 32 bits of the fractional parts of the cube roots of the first 80 primes 2..409\n// prettier-ignore\nconst K512 = /* @__PURE__ */ (() => u64.split([\n '0x428a2f98d728ae22', '0x7137449123ef65cd', '0xb5c0fbcfec4d3b2f', '0xe9b5dba58189dbbc',\n '0x3956c25bf348b538', '0x59f111f1b605d019', '0x923f82a4af194f9b', '0xab1c5ed5da6d8118',\n '0xd807aa98a3030242', '0x12835b0145706fbe', '0x243185be4ee4b28c', '0x550c7dc3d5ffb4e2',\n '0x72be5d74f27b896f', '0x80deb1fe3b1696b1', '0x9bdc06a725c71235', '0xc19bf174cf692694',\n '0xe49b69c19ef14ad2', '0xefbe4786384f25e3', '0x0fc19dc68b8cd5b5', '0x240ca1cc77ac9c65',\n '0x2de92c6f592b0275', '0x4a7484aa6ea6e483', '0x5cb0a9dcbd41fbd4', '0x76f988da831153b5',\n '0x983e5152ee66dfab', '0xa831c66d2db43210', '0xb00327c898fb213f', '0xbf597fc7beef0ee4',\n '0xc6e00bf33da88fc2', '0xd5a79147930aa725', '0x06ca6351e003826f', '0x142929670a0e6e70',\n '0x27b70a8546d22ffc', '0x2e1b21385c26c926', '0x4d2c6dfc5ac42aed', '0x53380d139d95b3df',\n '0x650a73548baf63de', '0x766a0abb3c77b2a8', '0x81c2c92e47edaee6', '0x92722c851482353b',\n '0xa2bfe8a14cf10364', '0xa81a664bbc423001', '0xc24b8b70d0f89791', '0xc76c51a30654be30',\n '0xd192e819d6ef5218', '0xd69906245565a910', '0xf40e35855771202a', '0x106aa07032bbd1b8',\n '0x19a4c116b8d2d0c8', '0x1e376c085141ab53', '0x2748774cdf8eeb99', '0x34b0bcb5e19b48a8',\n '0x391c0cb3c5c95a63', '0x4ed8aa4ae3418acb', '0x5b9cca4f7763e373', '0x682e6ff3d6b2b8a3',\n '0x748f82ee5defb2fc', '0x78a5636f43172f60', '0x84c87814a1f0ab72', '0x8cc702081a6439ec',\n '0x90befffa23631e28', '0xa4506cebde82bde9', '0xbef9a3f7b2c67915', '0xc67178f2e372532b',\n '0xca273eceea26619c', '0xd186b8c721c0c207', '0xeada7dd6cde0eb1e', '0xf57d4f7fee6ed178',\n '0x06f067aa72176fba', '0x0a637dc5a2c898a6', '0x113f9804bef90dae', '0x1b710b35131c471b',\n '0x28db77f523047d84', '0x32caab7b40c72493', '0x3c9ebe0a15c9bebc', '0x431d67c49c100d4c',\n '0x4cc5d4becb3e42b6', '0x597f299cfc657e2a', '0x5fcb6fab3ad6faec', '0x6c44198c4a475817'\n].map(n => BigInt(n))))();\nconst SHA512_Kh = /* @__PURE__ */ (() => K512[0])();\nconst SHA512_Kl = /* @__PURE__ */ (() => K512[1])();\n\n// Reusable temporary buffers\nconst SHA512_W_H = /* @__PURE__ */ new Uint32Array(80);\nconst SHA512_W_L = /* @__PURE__ */ new Uint32Array(80);\n\nexport class SHA512 extends HashMD<SHA512> {\n // We cannot use array here since array allows indexing by variable\n // which means optimizer/compiler cannot use registers.\n // h -- high 32 bits, l -- low 32 bits\n protected Ah: number = SHA512_IV[0] | 0;\n protected Al: number = SHA512_IV[1] | 0;\n protected Bh: number = SHA512_IV[2] | 0;\n protected Bl: number = SHA512_IV[3] | 0;\n protected Ch: number = SHA512_IV[4] | 0;\n protected Cl: number = SHA512_IV[5] | 0;\n protected Dh: number = SHA512_IV[6] | 0;\n protected Dl: number = SHA512_IV[7] | 0;\n protected Eh: number = SHA512_IV[8] | 0;\n protected El: number = SHA512_IV[9] | 0;\n protected Fh: number = SHA512_IV[10] | 0;\n protected Fl: number = SHA512_IV[11] | 0;\n protected Gh: number = SHA512_IV[12] | 0;\n protected Gl: number = SHA512_IV[13] | 0;\n protected Hh: number = SHA512_IV[14] | 0;\n protected Hl: number = SHA512_IV[15] | 0;\n\n constructor(outputLen: number = 64) {\n super(128, outputLen, 16, false);\n }\n // prettier-ignore\n protected get(): [\n number, number, number, number, number, number, number, number,\n number, number, number, number, number, number, number, number\n ] {\n const { Ah, Al, Bh, Bl, Ch, Cl, Dh, Dl, Eh, El, Fh, Fl, Gh, Gl, Hh, Hl } = this;\n return [Ah, Al, Bh, Bl, Ch, Cl, Dh, Dl, Eh, El, Fh, Fl, Gh, Gl, Hh, Hl];\n }\n // prettier-ignore\n protected set(\n Ah: number, Al: number, Bh: number, Bl: number, Ch: number, Cl: number, Dh: number, Dl: number,\n Eh: number, El: number, Fh: number, Fl: number, Gh: number, Gl: number, Hh: number, Hl: number\n ): void {\n this.Ah = Ah | 0;\n this.Al = Al | 0;\n this.Bh = Bh | 0;\n this.Bl = Bl | 0;\n this.Ch = Ch | 0;\n this.Cl = Cl | 0;\n this.Dh = Dh | 0;\n this.Dl = Dl | 0;\n this.Eh = Eh | 0;\n this.El = El | 0;\n this.Fh = Fh | 0;\n this.Fl = Fl | 0;\n this.Gh = Gh | 0;\n this.Gl = Gl | 0;\n this.Hh = Hh | 0;\n this.Hl = Hl | 0;\n }\n protected process(view: DataView, offset: number): void {\n // Extend the first 16 words into the remaining 64 words w[16..79] of the message schedule array\n for (let i = 0; i < 16; i++, offset += 4) {\n SHA512_W_H[i] = view.getUint32(offset);\n SHA512_W_L[i] = view.getUint32((offset += 4));\n }\n for (let i = 16; i < 80; i++) {\n // s0 := (w[i-15] rightrotate 1) xor (w[i-15] rightrotate 8) xor (w[i-15] rightshift 7)\n const W15h = SHA512_W_H[i - 15] | 0;\n const W15l = SHA512_W_L[i - 15] | 0;\n const s0h = u64.rotrSH(W15h, W15l, 1) ^ u64.rotrSH(W15h, W15l, 8) ^ u64.shrSH(W15h, W15l, 7);\n const s0l = u64.rotrSL(W15h, W15l, 1) ^ u64.rotrSL(W15h, W15l, 8) ^ u64.shrSL(W15h, W15l, 7);\n // s1 := (w[i-2] rightrotate 19) xor (w[i-2] rightrotate 61) xor (w[i-2] rightshift 6)\n const W2h = SHA512_W_H[i - 2] | 0;\n const W2l = SHA512_W_L[i - 2] | 0;\n const s1h = u64.rotrSH(W2h, W2l, 19) ^ u64.rotrBH(W2h, W2l, 61) ^ u64.shrSH(W2h, W2l, 6);\n const s1l = u64.rotrSL(W2h, W2l, 19) ^ u64.rotrBL(W2h, W2l, 61) ^ u64.shrSL(W2h, W2l, 6);\n // SHA256_W[i] = s0 + s1 + SHA256_W[i - 7] + SHA256_W[i - 16];\n const SUMl = u64.add4L(s0l, s1l, SHA512_W_L[i - 7], SHA512_W_L[i - 16]);\n const SUMh = u64.add4H(SUMl, s0h, s1h, SHA512_W_H[i - 7], SHA512_W_H[i - 16]);\n SHA512_W_H[i] = SUMh | 0;\n SHA512_W_L[i] = SUMl | 0;\n }\n let { Ah, Al, Bh, Bl, Ch, Cl, Dh, Dl, Eh, El, Fh, Fl, Gh, Gl, Hh, Hl } = this;\n // Compression function main loop, 80 rounds\n for (let i = 0; i < 80; i++) {\n // S1 := (e rightrotate 14) xor (e rightrotate 18) xor (e rightrotate 41)\n const sigma1h = u64.rotrSH(Eh, El, 14) ^ u64.rotrSH(Eh, El, 18) ^ u64.rotrBH(Eh, El, 41);\n const sigma1l = u64.rotrSL(Eh, El, 14) ^ u64.rotrSL(Eh, El, 18) ^ u64.rotrBL(Eh, El, 41);\n //const T1 = (H + sigma1 + Chi(E, F, G) + SHA256_K[i] + SHA256_W[i]) | 0;\n const CHIh = (Eh & Fh) ^ (~Eh & Gh);\n const CHIl = (El & Fl) ^ (~El & Gl);\n // T1 = H + sigma1 + Chi(E, F, G) + SHA512_K[i] + SHA512_W[i]\n // prettier-ignore\n const T1ll = u64.add5L(Hl, sigma1l, CHIl, SHA512_Kl[i], SHA512_W_L[i]);\n const T1h = u64.add5H(T1ll, Hh, sigma1h, CHIh, SHA512_Kh[i], SHA512_W_H[i]);\n const T1l = T1ll | 0;\n // S0 := (a rightrotate 28) xor (a rightrotate 34) xor (a rightrotate 39)\n const sigma0h = u64.rotrSH(Ah, Al, 28) ^ u64.rotrBH(Ah, Al, 34) ^ u64.rotrBH(Ah, Al, 39);\n const sigma0l = u64.rotrSL(Ah, Al, 28) ^ u64.rotrBL(Ah, Al, 34) ^ u64.rotrBL(Ah, Al, 39);\n const MAJh = (Ah & Bh) ^ (Ah & Ch) ^ (Bh & Ch);\n const MAJl = (Al & Bl) ^ (Al & Cl) ^ (Bl & Cl);\n Hh = Gh | 0;\n Hl = Gl | 0;\n Gh = Fh | 0;\n Gl = Fl | 0;\n Fh = Eh | 0;\n Fl = El | 0;\n ({ h: Eh, l: El } = u64.add(Dh | 0, Dl | 0, T1h | 0, T1l | 0));\n Dh = Ch | 0;\n Dl = Cl | 0;\n Ch = Bh | 0;\n Cl = Bl | 0;\n Bh = Ah | 0;\n Bl = Al | 0;\n const All = u64.add3L(T1l, sigma0l, MAJl);\n Ah = u64.add3H(All, T1h, sigma0h, MAJh);\n Al = All | 0;\n }\n // Add the compressed chunk to the current hash value\n ({ h: Ah, l: Al } = u64.add(this.Ah | 0, this.Al | 0, Ah | 0, Al | 0));\n ({ h: Bh, l: Bl } = u64.add(this.Bh | 0, this.Bl | 0, Bh | 0, Bl | 0));\n ({ h: Ch, l: Cl } = u64.add(this.Ch | 0, this.Cl | 0, Ch | 0, Cl | 0));\n ({ h: Dh, l: Dl } = u64.add(this.Dh | 0, this.Dl | 0, Dh | 0, Dl | 0));\n ({ h: Eh, l: El } = u64.add(this.Eh | 0, this.El | 0, Eh | 0, El | 0));\n ({ h: Fh, l: Fl } = u64.add(this.Fh | 0, this.Fl | 0, Fh | 0, Fl | 0));\n ({ h: Gh, l: Gl } = u64.add(this.Gh | 0, this.Gl | 0, Gh | 0, Gl | 0));\n ({ h: Hh, l: Hl } = u64.add(this.Hh | 0, this.Hl | 0, Hh | 0, Hl | 0));\n this.set(Ah, Al, Bh, Bl, Ch, Cl, Dh, Dl, Eh, El, Fh, Fl, Gh, Gl, Hh, Hl);\n }\n protected roundClean(): void {\n clean(SHA512_W_H, SHA512_W_L);\n }\n destroy(): void {\n clean(this.buffer);\n this.set(0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0);\n }\n}\n\nexport class SHA384 extends SHA512 {\n protected Ah: number = SHA384_IV[0] | 0;\n protected Al: number = SHA384_IV[1] | 0;\n protected Bh: number = SHA384_IV[2] | 0;\n protected Bl: number = SHA384_IV[3] | 0;\n protected Ch: number = SHA384_IV[4] | 0;\n protected Cl: number = SHA384_IV[5] | 0;\n protected Dh: number = SHA384_IV[6] | 0;\n protected Dl: number = SHA384_IV[7] | 0;\n protected Eh: number = SHA384_IV[8] | 0;\n protected El: number = SHA384_IV[9] | 0;\n protected Fh: number = SHA384_IV[10] | 0;\n protected Fl: number = SHA384_IV[11] | 0;\n protected Gh: number = SHA384_IV[12] | 0;\n protected Gl: number = SHA384_IV[13] | 0;\n protected Hh: number = SHA384_IV[14] | 0;\n protected Hl: number = SHA384_IV[15] | 0;\n\n constructor() {\n super(48);\n }\n}\n\n/**\n * Truncated SHA512/256 and SHA512/224.\n * SHA512_IV is XORed with 0xa5a5a5a5a5a5a5a5, then used as \"intermediary\" IV of SHA512/t.\n * Then t hashes string to produce result IV.\n * See `test/misc/sha2-gen-iv.js`.\n */\n\n/** SHA512/224 IV */\nconst T224_IV = /* @__PURE__ */ Uint32Array.from([\n 0x8c3d37c8, 0x19544da2, 0x73e19966, 0x89dcd4d6, 0x1dfab7ae, 0x32ff9c82, 0x679dd514, 0x582f9fcf,\n 0x0f6d2b69, 0x7bd44da8, 0x77e36f73, 0x04c48942, 0x3f9d85a8, 0x6a1d36c8, 0x1112e6ad, 0x91d692a1,\n]);\n\n/** SHA512/256 IV */\nconst T256_IV = /* @__PURE__ */ Uint32Array.from([\n 0x22312194, 0xfc2bf72c, 0x9f555fa3, 0xc84c64c2, 0x2393b86b, 0x6f53b151, 0x96387719, 0x5940eabd,\n 0x96283ee2, 0xa88effe3, 0xbe5e1e25, 0x53863992, 0x2b0199fc, 0x2c85b8aa, 0x0eb72ddc, 0x81c52ca2,\n]);\n\nexport class SHA512_224 extends SHA512 {\n protected Ah: number = T224_IV[0] | 0;\n protected Al: number = T224_IV[1] | 0;\n protected Bh: number = T224_IV[2] | 0;\n protected Bl: number = T224_IV[3] | 0;\n protected Ch: number = T224_IV[4] | 0;\n protected Cl: number = T224_IV[5] | 0;\n protected Dh: number = T224_IV[6] | 0;\n protected Dl: number = T224_IV[7] | 0;\n protected Eh: number = T224_IV[8] | 0;\n protected El: number = T224_IV[9] | 0;\n protected Fh: number = T224_IV[10] | 0;\n protected Fl: number = T224_IV[11] | 0;\n protected Gh: number = T224_IV[12] | 0;\n protected Gl: number = T224_IV[13] | 0;\n protected Hh: number = T224_IV[14] | 0;\n protected Hl: number = T224_IV[15] | 0;\n\n constructor() {\n super(28);\n }\n}\n\nexport class SHA512_256 extends SHA512 {\n protected Ah: number = T256_IV[0] | 0;\n protected Al: number = T256_IV[1] | 0;\n protected Bh: number = T256_IV[2] | 0;\n protected Bl: number = T256_IV[3] | 0;\n protected Ch: number = T256_IV[4] | 0;\n protected Cl: number = T256_IV[5] | 0;\n protected Dh: number = T256_IV[6] | 0;\n protected Dl: number = T256_IV[7] | 0;\n protected Eh: number = T256_IV[8] | 0;\n protected El: number = T256_IV[9] | 0;\n protected Fh: number = T256_IV[10] | 0;\n protected Fl: number = T256_IV[11] | 0;\n protected Gh: number = T256_IV[12] | 0;\n protected Gl: number = T256_IV[13] | 0;\n protected Hh: number = T256_IV[14] | 0;\n protected Hl: number = T256_IV[15] | 0;\n\n constructor() {\n super(32);\n }\n}\n\n/**\n * SHA2-256 hash function from RFC 4634.\n *\n * It is the fastest JS hash, even faster than Blake3.\n * To break sha256 using birthday attack, attackers need to try 2^128 hashes.\n * BTC network is doing 2^70 hashes/sec (2^95 hashes/year) as per 2025.\n */\nexport const sha256: CHash = /* @__PURE__ */ createHasher(() => new SHA256());\n/** SHA2-224 hash function from RFC 4634 */\nexport const sha224: CHash = /* @__PURE__ */ createHasher(() => new SHA224());\n\n/** SHA2-512 hash function from RFC 4634. */\nexport const sha512: CHash = /* @__PURE__ */ createHasher(() => new SHA512());\n/** SHA2-384 hash function from RFC 4634. */\nexport const sha384: CHash = /* @__PURE__ */ createHasher(() => new SHA384());\n\n/**\n * SHA2-512/256 \"truncated\" hash function, with improved resistance to length extension attacks.\n * See the paper on [truncated SHA512](https://eprint.iacr.org/2010/548.pdf).\n */\nexport const sha512_256: CHash = /* @__PURE__ */ createHasher(() => new SHA512_256());\n/**\n * SHA2-512/224 \"truncated\" hash function, with improved resistance to length extension attacks.\n * See the paper on [truncated SHA512](https://eprint.iacr.org/2010/548.pdf).\n */\nexport const sha512_224: CHash = /* @__PURE__ */ createHasher(() => new SHA512_224());\n","/**\n * SHA2-512 a.k.a. sha512 and sha384. It is slower than sha256 in js because u64 operations are slow.\n *\n * Check out [RFC 4634](https://datatracker.ietf.org/doc/html/rfc4634) and\n * [the paper on truncated SHA512/256](https://eprint.iacr.org/2010/548.pdf).\n * @module\n * @deprecated\n */\nimport {\n SHA384 as SHA384n,\n sha384 as sha384n,\n sha512_224 as sha512_224n,\n SHA512_224 as SHA512_224n,\n sha512_256 as sha512_256n,\n SHA512_256 as SHA512_256n,\n SHA512 as SHA512n,\n sha512 as sha512n,\n} from './sha2.ts';\n/** @deprecated Use import from `noble/hashes/sha2` module */\nexport const SHA512: typeof SHA512n = SHA512n;\n/** @deprecated Use import from `noble/hashes/sha2` module */\nexport const sha512: typeof sha512n = sha512n;\n/** @deprecated Use import from `noble/hashes/sha2` module */\nexport const SHA384: typeof SHA384n = SHA384n;\n/** @deprecated Use import from `noble/hashes/sha2` module */\nexport const sha384: typeof sha384n = sha384n;\n/** @deprecated Use import from `noble/hashes/sha2` module */\nexport const SHA512_224: typeof SHA512_224n = SHA512_224n;\n/** @deprecated Use import from `noble/hashes/sha2` module */\nexport const sha512_224: typeof sha512_224n = sha512_224n;\n/** @deprecated Use import from `noble/hashes/sha2` module */\nexport const SHA512_256: typeof SHA512_256n = SHA512_256n;\n/** @deprecated Use import from `noble/hashes/sha2` module */\nexport const sha512_256: typeof sha512_256n = sha512_256n;\n","/**\n * Request Deduplication\n *\n * Prevents double-charging when OpenClaw retries a request after timeout.\n * Tracks in-flight requests and caches completed responses for a short TTL.\n */\n\nimport { createHash } from \"node:crypto\";\n\nexport type CachedResponse = {\n status: number;\n headers: Record<string, string>;\n body: Buffer;\n completedAt: number;\n};\n\ntype InflightEntry = {\n resolvers: Array<(result: CachedResponse) => void>;\n};\n\nconst DEFAULT_TTL_MS = 30_000; // 30 seconds\nconst MAX_BODY_SIZE = 1_048_576; // 1MB\n\n/**\n * Canonicalize JSON by sorting object keys recursively.\n * Ensures identical logical content produces identical string regardless of field order.\n */\nfunction canonicalize(obj: unknown): unknown {\n if (obj === null || typeof obj !== \"object\") {\n return obj;\n }\n if (Array.isArray(obj)) {\n return obj.map(canonicalize);\n }\n const sorted: Record<string, unknown> = {};\n for (const key of Object.keys(obj).sort()) {\n sorted[key] = canonicalize((obj as Record<string, unknown>)[key]);\n }\n return sorted;\n}\n\n/**\n * Strip OpenClaw-injected timestamps from message content.\n * Format: [DAY YYYY-MM-DD HH:MM TZ] at the start of messages.\n * Example: [SUN 2026-02-07 13:30 PST] Hello world\n *\n * This ensures requests with different timestamps but same content hash identically.\n */\nconst TIMESTAMP_PATTERN = /^\\[\\w{3}\\s+\\d{4}-\\d{2}-\\d{2}\\s+\\d{2}:\\d{2}\\s+\\w+\\]\\s*/;\n\nfunction stripTimestamps(obj: unknown): unknown {\n if (obj === null || typeof obj !== \"object\") {\n return obj;\n }\n if (Array.isArray(obj)) {\n return obj.map(stripTimestamps);\n }\n const result: Record<string, unknown> = {};\n for (const [key, value] of Object.entries(obj as Record<string, unknown>)) {\n if (key === \"content\" && typeof value === \"string\") {\n // Strip timestamp prefix from message content\n result[key] = value.replace(TIMESTAMP_PATTERN, \"\");\n } else {\n result[key] = stripTimestamps(value);\n }\n }\n return result;\n}\n\nexport class RequestDeduplicator {\n private inflight = new Map<string, InflightEntry>();\n private completed = new Map<string, CachedResponse>();\n private ttlMs: number;\n\n constructor(ttlMs = DEFAULT_TTL_MS) {\n this.ttlMs = ttlMs;\n }\n\n /** Hash request body to create a dedup key. */\n static hash(body: Buffer): string {\n // Canonicalize JSON to ensure consistent hashing regardless of field order.\n // Also strip OpenClaw-injected timestamps so retries with different timestamps\n // still match the same dedup key.\n let content = body;\n try {\n const parsed = JSON.parse(body.toString());\n const stripped = stripTimestamps(parsed);\n const canonical = canonicalize(stripped);\n content = Buffer.from(JSON.stringify(canonical));\n } catch {\n // Not valid JSON, use raw bytes\n }\n return createHash(\"sha256\").update(content).digest(\"hex\").slice(0, 16);\n }\n\n /** Check if a response is cached for this key. */\n getCached(key: string): CachedResponse | undefined {\n const entry = this.completed.get(key);\n if (!entry) return undefined;\n if (Date.now() - entry.completedAt > this.ttlMs) {\n this.completed.delete(key);\n return undefined;\n }\n return entry;\n }\n\n /** Check if a request with this key is currently in-flight. Returns a promise to wait on. */\n getInflight(key: string): Promise<CachedResponse> | undefined {\n const entry = this.inflight.get(key);\n if (!entry) return undefined;\n return new Promise<CachedResponse>((resolve) => {\n entry.resolvers.push(resolve);\n });\n }\n\n /** Mark a request as in-flight. */\n markInflight(key: string): void {\n this.inflight.set(key, {\n resolvers: [],\n });\n }\n\n /** Complete an in-flight request — cache result and notify waiters. */\n complete(key: string, result: CachedResponse): void {\n // Only cache responses within size limit\n if (result.body.length <= MAX_BODY_SIZE) {\n this.completed.set(key, result);\n }\n\n const entry = this.inflight.get(key);\n if (entry) {\n for (const resolve of entry.resolvers) {\n resolve(result);\n }\n this.inflight.delete(key);\n }\n\n this.prune();\n }\n\n /** Remove an in-flight entry on error (don't cache failures).\n * Also rejects any waiters so they can retry independently. */\n removeInflight(key: string): void {\n const entry = this.inflight.get(key);\n if (entry) {\n // Resolve waiters with a sentinel error response so they don't hang forever.\n // Waiters will see a 503 and can retry on their own.\n const errorBody = Buffer.from(\n JSON.stringify({\n error: { message: \"Original request failed, please retry\", type: \"dedup_origin_failed\" },\n }),\n );\n for (const resolve of entry.resolvers) {\n resolve({\n status: 503,\n headers: { \"content-type\": \"application/json\" },\n body: errorBody,\n completedAt: Date.now(),\n });\n }\n this.inflight.delete(key);\n }\n }\n\n /** Prune expired completed entries. */\n private prune(): void {\n const now = Date.now();\n for (const [key, entry] of this.completed) {\n if (now - entry.completedAt > this.ttlMs) {\n this.completed.delete(key);\n }\n }\n }\n}\n","/**\n * Response Cache for LLM Completions\n *\n * Caches LLM responses by request hash (model + messages + params).\n * Inspired by LiteLLM's caching system. Returns cached responses for\n * identical requests, saving both cost and latency.\n *\n * Features:\n * - TTL-based expiration (default 10 minutes)\n * - LRU eviction when cache is full\n * - Size limits per item (1MB max)\n * - Heap-based expiration tracking for efficient pruning\n */\n\nimport { createHash } from \"node:crypto\";\nimport { logger } from \"./plugin-logger.js\";\n\nexport type CachedLLMResponse = {\n body: Buffer;\n status: number;\n headers: Record<string, string>;\n model: string;\n cachedAt: number;\n expiresAt: number;\n};\n\nexport type ResponseCacheConfig = {\n /** Maximum number of cached responses. Default: 200 */\n maxSize?: number;\n /** Default TTL in seconds. Default: 600 (10 minutes) */\n defaultTTL?: number;\n /** Maximum size per cached item in bytes. Default: 1MB */\n maxItemSize?: number;\n /** Enable/disable cache. Default: true */\n enabled?: boolean;\n};\n\nconst DEFAULT_CONFIG: Required<ResponseCacheConfig> = {\n maxSize: 200,\n defaultTTL: 600,\n maxItemSize: 1_048_576, // 1MB\n enabled: true,\n};\n\n/**\n * Canonicalize JSON by sorting object keys recursively.\n * Ensures identical logical content produces identical hash.\n */\nfunction canonicalize(obj: unknown): unknown {\n if (obj === null || typeof obj !== \"object\") {\n return obj;\n }\n if (Array.isArray(obj)) {\n return obj.map(canonicalize);\n }\n const sorted: Record<string, unknown> = {};\n for (const key of Object.keys(obj).sort()) {\n sorted[key] = canonicalize((obj as Record<string, unknown>)[key]);\n }\n return sorted;\n}\n\n/**\n * Strip fields that shouldn't affect cache key:\n * - stream (we handle streaming separately)\n * - timestamps injected by OpenClaw\n * - request IDs\n */\nconst TIMESTAMP_PATTERN = /^\\[\\w{3}\\s+\\d{4}-\\d{2}-\\d{2}\\s+\\d{2}:\\d{2}\\s+\\w+\\]\\s*/;\n\nfunction normalizeForCache(obj: Record<string, unknown>): Record<string, unknown> {\n const result: Record<string, unknown> = {};\n\n for (const [key, value] of Object.entries(obj)) {\n // Skip fields that don't affect response content\n if ([\"stream\", \"user\", \"request_id\", \"x-request-id\"].includes(key)) {\n continue;\n }\n\n if (key === \"messages\" && Array.isArray(value)) {\n // Strip timestamps from message content\n result[key] = value.map((msg: unknown) => {\n if (typeof msg === \"object\" && msg !== null) {\n const m = msg as Record<string, unknown>;\n if (typeof m.content === \"string\") {\n return { ...m, content: m.content.replace(TIMESTAMP_PATTERN, \"\") };\n }\n }\n return msg;\n });\n } else {\n result[key] = value;\n }\n }\n\n return result;\n}\n\nexport class ResponseCache {\n private cache = new Map<string, CachedLLMResponse>();\n private expirationHeap: Array<{ expiresAt: number; key: string }> = [];\n private config: Required<ResponseCacheConfig>;\n\n // Stats for monitoring\n private stats = {\n hits: 0,\n misses: 0,\n evictions: 0,\n };\n\n constructor(config: ResponseCacheConfig = {}) {\n // Filter out undefined values so they don't override defaults\n const filtered = Object.fromEntries(\n Object.entries(config).filter(([, v]) => v !== undefined),\n ) as ResponseCacheConfig;\n this.config = { ...DEFAULT_CONFIG, ...filtered };\n }\n\n /**\n * Generate cache key from request body.\n * Hashes: model + messages + temperature + max_tokens + other params\n */\n static generateKey(body: Buffer | string): string {\n try {\n const parsed = JSON.parse(typeof body === \"string\" ? body : body.toString());\n const normalized = normalizeForCache(parsed);\n const canonical = canonicalize(normalized);\n const keyContent = JSON.stringify(canonical);\n return createHash(\"sha256\").update(keyContent).digest(\"hex\").slice(0, 32);\n } catch {\n // Fallback: hash raw body\n const content = typeof body === \"string\" ? body : body.toString();\n return createHash(\"sha256\").update(content).digest(\"hex\").slice(0, 32);\n }\n }\n\n /**\n * Check if caching is enabled for this request.\n * Respects cache control headers and request params.\n */\n shouldCache(body: Buffer | string, headers?: Record<string, string>): boolean {\n if (!this.config.enabled) return false;\n\n // Respect Cache-Control: no-cache header\n if (headers?.[\"cache-control\"]?.includes(\"no-cache\")) {\n return false;\n }\n\n // Check for explicit cache disable in body\n try {\n const parsed = JSON.parse(typeof body === \"string\" ? body : body.toString());\n if (parsed.cache === false || parsed.no_cache === true) {\n return false;\n }\n } catch {\n // Not JSON, allow caching\n }\n\n return true;\n }\n\n /**\n * Get cached response if available and not expired.\n */\n get(key: string): CachedLLMResponse | undefined {\n const entry = this.cache.get(key);\n if (!entry) {\n this.stats.misses++;\n return undefined;\n }\n\n // Check expiration\n if (Date.now() > entry.expiresAt) {\n this.cache.delete(key);\n this.stats.misses++;\n return undefined;\n }\n\n this.stats.hits++;\n return entry;\n }\n\n /**\n * Cache a response with optional custom TTL.\n */\n set(\n key: string,\n response: {\n body: Buffer;\n status: number;\n headers: Record<string, string>;\n model: string;\n },\n ttlSeconds?: number,\n ): void {\n // Don't cache if disabled or maxSize is 0\n if (!this.config.enabled || this.config.maxSize <= 0) return;\n\n // Don't cache if item too large\n if (response.body.length > this.config.maxItemSize) {\n logger.info(`[ResponseCache] Skipping cache - item too large: ${response.body.length} bytes`);\n return;\n }\n\n // Don't cache error responses\n if (response.status >= 400) {\n return;\n }\n\n // Evict if at capacity\n if (this.cache.size >= this.config.maxSize) {\n this.evict();\n }\n\n const now = Date.now();\n const ttl = ttlSeconds ?? this.config.defaultTTL;\n const expiresAt = now + ttl * 1000;\n\n const entry: CachedLLMResponse = {\n ...response,\n cachedAt: now,\n expiresAt,\n };\n\n this.cache.set(key, entry);\n this.expirationHeap.push({ expiresAt, key });\n }\n\n /**\n * Evict expired and oldest entries to make room.\n */\n private evict(): void {\n const now = Date.now();\n\n // First pass: remove expired entries\n this.expirationHeap.sort((a, b) => a.expiresAt - b.expiresAt);\n\n while (this.expirationHeap.length > 0) {\n const oldest = this.expirationHeap[0];\n\n // Check if entry still exists and matches\n const entry = this.cache.get(oldest.key);\n if (!entry || entry.expiresAt !== oldest.expiresAt) {\n // Stale heap entry, remove it\n this.expirationHeap.shift();\n continue;\n }\n\n if (oldest.expiresAt <= now) {\n // Expired, remove both\n this.cache.delete(oldest.key);\n this.expirationHeap.shift();\n this.stats.evictions++;\n } else {\n // Not expired, stop\n break;\n }\n }\n\n // Second pass: if still at capacity, evict oldest\n while (this.cache.size >= this.config.maxSize && this.expirationHeap.length > 0) {\n const oldest = this.expirationHeap.shift()!;\n if (this.cache.has(oldest.key)) {\n this.cache.delete(oldest.key);\n this.stats.evictions++;\n }\n }\n }\n\n /**\n * Get cache statistics.\n */\n getStats(): {\n size: number;\n maxSize: number;\n hits: number;\n misses: number;\n evictions: number;\n hitRate: string;\n } {\n const total = this.stats.hits + this.stats.misses;\n const hitRate = total > 0 ? ((this.stats.hits / total) * 100).toFixed(1) + \"%\" : \"0%\";\n\n return {\n size: this.cache.size,\n maxSize: this.config.maxSize,\n hits: this.stats.hits,\n misses: this.stats.misses,\n evictions: this.stats.evictions,\n hitRate,\n };\n }\n\n /**\n * Clear all cached entries.\n */\n clear(): void {\n this.cache.clear();\n this.expirationHeap = [];\n }\n\n /**\n * Check if cache is enabled.\n */\n isEnabled(): boolean {\n return this.config.enabled;\n }\n}\n","/**\n * Session Journal - Memory layer for ckcloud\n *\n * Maintains a compact record of key actions per session, enabling agents\n * to recall earlier work even when OpenClaw's sessions_history is truncated.\n *\n * How it works:\n * 1. As LLM responses flow through, extracts key actions (\"I created X\", \"I fixed Y\")\n * 2. Stores them in a compact journal per session\n * 3. When a request mentions past work (\"what did you do today?\"), injects the journal\n */\n\nexport interface JournalEntry {\n timestamp: number;\n action: string; // Compact description: \"Created login component\"\n model?: string;\n}\n\nexport interface SessionJournalConfig {\n /** Maximum entries per session (default: 100) */\n maxEntries?: number;\n /** Maximum age of entries in ms (default: 24 hours) */\n maxAgeMs?: number;\n /** Maximum events to extract per response (default: 5) */\n maxEventsPerResponse?: number;\n}\n\nconst DEFAULT_CONFIG: Required<SessionJournalConfig> = {\n maxEntries: 100,\n maxAgeMs: 24 * 60 * 60 * 1000, // 24 hours\n maxEventsPerResponse: 5,\n};\n\nexport class SessionJournal {\n private journals: Map<string, JournalEntry[]> = new Map();\n private config: Required<SessionJournalConfig>;\n\n constructor(config?: SessionJournalConfig) {\n this.config = { ...DEFAULT_CONFIG, ...config };\n }\n\n /**\n * Extract key events from assistant response content.\n * Looks for patterns like \"I created...\", \"I fixed...\", \"Successfully...\"\n */\n extractEvents(content: string): string[] {\n if (!content || typeof content !== \"string\") {\n return [];\n }\n\n const events: string[] = [];\n const seen = new Set<string>();\n\n // Patterns for identifying key actions\n // Note: Patterns allow optional words like \"also\", \"then\", \"have\" between \"I\" and verb\n const patterns = [\n // Creation patterns\n /I (?:also |then |have |)?(?:created|implemented|added|wrote|built|generated|set up|initialized) ([^.!?\\n]{10,150})/gi,\n // Fix patterns\n /I (?:also |then |have |)?(?:fixed|resolved|solved|patched|corrected|addressed|debugged) ([^.!?\\n]{10,150})/gi,\n // Completion patterns\n /I (?:also |then |have |)?(?:completed|finished|done with|wrapped up) ([^.!?\\n]{10,150})/gi,\n // Update patterns\n /I (?:also |then |have |)?(?:updated|modified|changed|refactored|improved|enhanced|optimized) ([^.!?\\n]{10,150})/gi,\n // Success patterns\n /Successfully ([^.!?\\n]{10,150})/gi,\n // Tool usage patterns (when agent uses tools)\n /I (?:also |then |have |)?(?:ran|executed|called|invoked) ([^.!?\\n]{10,100})/gi,\n ];\n\n for (const pattern of patterns) {\n // Reset pattern lastIndex for each iteration\n pattern.lastIndex = 0;\n\n let match;\n while ((match = pattern.exec(content)) !== null) {\n const action = match[0].trim();\n\n // Skip if already seen (dedup)\n const normalized = action.toLowerCase();\n if (seen.has(normalized)) {\n continue;\n }\n\n // Validate length (not too short or too long)\n if (action.length >= 15 && action.length <= 200) {\n events.push(action);\n seen.add(normalized);\n }\n\n // Stop if we have enough events\n if (events.length >= this.config.maxEventsPerResponse) {\n break;\n }\n }\n\n if (events.length >= this.config.maxEventsPerResponse) {\n break;\n }\n }\n\n return events;\n }\n\n /**\n * Record events to the session journal.\n */\n record(sessionId: string, events: string[], model?: string): void {\n if (!sessionId || !events.length) {\n return;\n }\n\n const journal = this.journals.get(sessionId) || [];\n const now = Date.now();\n\n for (const action of events) {\n journal.push({\n timestamp: now,\n action,\n model,\n });\n }\n\n // Trim old entries and enforce max count\n const cutoff = now - this.config.maxAgeMs;\n const trimmed = journal.filter((e) => e.timestamp > cutoff).slice(-this.config.maxEntries);\n\n this.journals.set(sessionId, trimmed);\n }\n\n /**\n * Check if the user message indicates a need for historical context.\n */\n needsContext(lastUserMessage: string): boolean {\n if (!lastUserMessage || typeof lastUserMessage !== \"string\") {\n return false;\n }\n\n const lower = lastUserMessage.toLowerCase();\n\n // Trigger phrases that indicate user wants to recall past work\n const triggers = [\n // Direct questions about past work\n \"what did you do\",\n \"what have you done\",\n \"what did we do\",\n \"what have we done\",\n // Temporal references\n \"earlier\",\n \"before\",\n \"previously\",\n \"this session\",\n \"today\",\n \"so far\",\n // Summary requests\n \"remind me\",\n \"summarize\",\n \"summary of\",\n \"recap\",\n // Progress inquiries\n \"your work\",\n \"your progress\",\n \"accomplished\",\n \"achievements\",\n \"completed tasks\",\n ];\n\n return triggers.some((t) => lower.includes(t));\n }\n\n /**\n * Format the journal for injection into system message.\n * Returns null if journal is empty.\n */\n format(sessionId: string): string | null {\n const journal = this.journals.get(sessionId);\n if (!journal?.length) {\n return null;\n }\n\n const lines = journal.map((e) => {\n const time = new Date(e.timestamp).toLocaleTimeString(\"en-US\", {\n hour: \"2-digit\",\n minute: \"2-digit\",\n hour12: true,\n });\n return `- ${time}: ${e.action}`;\n });\n\n return `[Session Memory - Key Actions]\\n${lines.join(\"\\n\")}`;\n }\n\n /**\n * Get the raw journal entries for a session (for debugging/testing).\n */\n getEntries(sessionId: string): JournalEntry[] {\n return this.journals.get(sessionId) || [];\n }\n\n /**\n * Clear journal for a specific session.\n */\n clear(sessionId: string): void {\n this.journals.delete(sessionId);\n }\n\n /**\n * Clear all journals.\n */\n clearAll(): void {\n this.journals.clear();\n }\n\n /**\n * Get stats about the journal.\n */\n getStats(): { sessions: number; totalEntries: number } {\n let totalEntries = 0;\n for (const entries of this.journals.values()) {\n totalEntries += entries.length;\n }\n return {\n sessions: this.journals.size,\n totalEntries,\n };\n }\n}\n"],"mappings":"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;AAAA,MACA;AAAA,MACA;AAAA,MACA;AAAA;AAAA,MAEA;AAAA,MACA;AAAA,MACA;AAAA,MACA;AAAA,MACA;AAAA,MACA;AAAA,MACA;AAAA,MACA;AAAA,MACA;AAAA,MACA;AAAA;AAAA,MAEA;AAAA,MACA;AAAA,MACA;AAAA,MACA;AAAA,MACA;AAAA,MACA;AAAA,MACA;AAAA,MACA;AAAA,MACA;AAAA,MACA;AAAA,IACF;AAAA,IACA,mBAAmB;AAAA;AAAA,MAEjB;AAAA,MACA;AAAA,MACA;AAAA,MACA;AAAA,MACA;AAAA,MACA;AAAA,MACA;AAAA,MACA;AAAA,MACA;AAAA;AAAA,MAEA;AAAA,MACA;AAAA,MACA;AAAA,MACA;AAAA,MACA;AAAA,MACA;AAAA,MACA;AAAA,MACA;AAAA;AAAA,MAEA;AAAA,MACA;AAAA,MACA;AAAA,MACA;AAAA,MACA;AAAA;AAAA,MAEA;AAAA,MACA;AAAA,MACA;AAAA,MACA;AAAA,MACA;AAAA,MACA;AAAA,MACA;AAAA,MACA;AAAA,MACA;AAAA,MACA;AAAA,MACA;AAAA,MACA;AAAA,MACA;AAAA;AAAA,MAEA;AAAA,MACA;AAAA,MACA;AAAA,MACA;AAAA,MACA;AAAA,MACA;AAAA,MACA;AAAA,MACA;AAAA,MACA;AAAA;AAAA,MAEA;AAAA,MACA;AAAA,MACA;AAAA,MACA;AAAA,MACA;AAAA,MACA;AAAA,MACA;AAAA,MACA;AAAA,MACA;AAAA;AAAA,MAEA;AAAA,MACA;AAAA,MACA;AAAA,MACA;AAAA,MACA;AAAA,MACA;AAAA,MACA;AAAA,MACA;AAAA,MACA;AAAA;AAAA,MAEA;AAAA,MACA;AAAA,MACA;AAAA,MACA;AAAA,MACA;AAAA,MACA;AAAA,MACA;AAAA,MACA;AAAA;AAAA,MAEA;AAAA,MACA;AAAA,MACA;AAAA,MACA;AAAA,MACA;AAAA,MACA;AAAA,MACA;AAAA,MACA;AAAA,MACA;AAAA,IACF;AAAA,IACA,gBAAgB;AAAA;AAAA,MAEd;AAAA,MACA;AAAA,MACA;AAAA,MACA;AAAA,MACA;AAAA,MACA;AAAA,MACA;AAAA,MACA;AAAA,MACA;AAAA;AAAA,MAEA;AAAA,MACA;AAAA,MACA;AAAA,MACA;AAAA,MACA;AAAA,MACA;AAAA,MACA;AAAA,MACA;AAAA,MACA;AAAA;AAAA,MAEA;AAAA,MACA;AAAA,MACA;AAAA,MACA;AAAA,MACA;AAAA,MACA;AAAA,MACA;AAAA;AAAA,MAEA;AAAA,MACA;AAAA,MACA;AAAA,MACA;AAAA,MACA;AAAA,MACA;AAAA,MACA;AAAA,MACA;AAAA,MACA;AAAA,MACA;AAAA,MACA;AAAA;AAAA,MAEA;AAAA,MACA;AAAA,MACA;AAAA,MACA;AAAA,MACA;AAAA,MACA;AAAA,MACA;AAAA,MACA;AAAA,MACA;AAAA,MACA;AAAA;AAAA,MAEA;AAAA,MACA;AAAA,MACA;AAAA,MACA;AAAA,MACA;AAAA,MACA;AAAA,MACA;AAAA,MACA;AAAA,MACA;AAAA;AAAA,MAEA;AAAA,MACA;AAAA,MACA;AAAA,MACA;AAAA,MACA;AAAA,MACA;AAAA,MACA;AAAA,MACA;AAAA,MACA;AAAA;AAAA,MAEA;AAAA,MACA;AAAA,MACA;AAAA,MACA;AAAA,MACA;AAAA,MACA;AAAA,MACA;AAAA,MACA;AAAA;AAAA,MAEA;AAAA,MACA;AAAA,MACA;AAAA,MACA;AAAA,MACA;AAAA,MACA;AAAA,MACA;AAAA,MACA;AAAA,IACF;AAAA,IACA,mBAAmB;AAAA;AAAA,MAEjB;AAAA,MACA;AAAA,MACA;AAAA,MACA;AAAA,MACA;AAAA,MACA;AAAA,MACA;AAAA,MACA;AAAA;AAAA,MAEA;AAAA,MACA;AAAA,MACA;AAAA,MACA;AAAA,MACA;AAAA,MACA;AAAA,MACA;AAAA;AAAA,MAEA;AAAA,MACA;AAAA,MACA;AAAA,MACA;AAAA,MACA;AAAA,MACA;AAAA;AAAA,MAEA;AAAA,MACA;AAAA,MACA;AAAA,MACA;AAAA,MACA;AAAA,MACA;AAAA,MACA;AAAA,MACA;AAAA,MACA;AAAA;AAAA,MAEA;AAAA,MACA;AAAA,MACA;AAAA,MACA;AAAA,MACA;AAAA,MACA;AAAA,MACA;AAAA,MACA;AAAA;AAAA,MAEA;AAAA,MACA;AAAA,MACA;AAAA,MACA;AAAA,MACA;AAAA,MACA;AAAA,MACA;AAAA;AAAA,MAEA;AAAA,MACA;AAAA,MACA;AAAA,MACA;AAAA,MACA;AAAA,MACA;AAAA,MACA;AAAA;AAAA,MAEA;AAAA,MACA;AAAA,MACA;AAAA,MACA;AAAA,MACA;AAAA,MACA;AAAA,MACA;AAAA;AAAA,MAEA;AAAA,MACA;AAAA,MACA;AAAA,MACA;AAAA,MACA;AAAA,MACA;AAAA,MACA;AAAA,IACF;AAAA,IACA,kBAAkB;AAAA;AAAA,MAEhB;AAAA,MACA;AAAA,MACA;AAAA,MACA;AAAA,MACA;AAAA,MACA;AAAA,MACA;AAAA;AAAA,MAEA;AAAA,MACA;AAAA,MACA;AAAA,MACA;AAAA,MACA;AAAA,MACA;AAAA,MACA;AAAA;AAAA,MAEA;AAAA,MACA;AAAA,MACA;AAAA,MACA;AAAA,MACA;AAAA,MACA;AAAA;AAAA,MAEA;AAAA,MACA;AAAA,MACA;AAAA,MACA;AAAA,MACA;AAAA,MACA;AAAA,MACA;AAAA,MACA;AAAA,MACA;AAAA,MACA;AAAA;AAAA,MAEA;AAAA,MACA;AAAA,MACA;AAAA,MACA;AAAA,MACA;AAAA,MACA;AAAA,MACA;AAAA,MACA;AAAA;AAAA,MAEA;AAAA,MACA;AAAA,MACA;AAAA,MACA;AAAA,MACA;AAAA,MACA;AAAA,MACA;AAAA;AAAA,MAEA;AAAA,MACA;AAAA,MACA;AAAA,MACA;AAAA,MACA;AAAA,MACA;AAAA;AAAA,MAEA;AAAA,MACA;AAAA,MACA;AAAA,MACA;AAAA,MACA;AAAA,MACA;AAAA,MACA;AAAA;AAAA,MAEA;AAAA,MACA;AAAA,MACA;AAAA,MACA;AAAA,MACA;AAAA,MACA;AAAA,MACA;AAAA,IACF;AAAA;AAAA,IAGA,iBAAiB;AAAA;AAAA,MAEf;AAAA,MACA;AAAA,MACA;AAAA,MACA;AAAA,MACA;AAAA,MACA;AAAA,MACA;AAAA,MACA;AAAA,MACA;AAAA,MACA;AAAA;AAAA,MAEA;AAAA,MACA;AAAA,MACA;AAAA,MACA;AAAA,MACA;AAAA,MACA;AAAA,MACA;AAAA,MACA;AAAA,MACA;AAAA;AAAA,MAEA;AAAA,MACA;AAAA,MACA;AAAA,MACA;AAAA,MACA;AAAA,MACA;AAAA,MACA;AAAA,MACA;AAAA;AAAA,MAEA;AAAA,MACA;AAAA,MACA;AAAA,MACA;AAAA,MACA;AAAA,MACA;AAAA,MACA;AAAA,MACA;AAAA,MACA;AAAA,MACA;AAAA,MACA;AAAA,MACA;AAAA,MACA;AAAA,MACA;AAAA,MACA;AAAA,MACA;AAAA;AAAA,MAEA;AAAA,MACA;AAAA,MACA;AAAA,MACA;AAAA,MACA;AAAA,MACA;AAAA,MACA;AAAA,MACA;AAAA,MACA;AAAA,MACA;AAAA;AAAA,MAEA;AAAA,MACA;AAAA,MACA;AAAA,MACA;AAAA,MACA;AAAA,MACA;AAAA,MACA;AAAA,MACA;AAAA;AAAA,MAEA;AAAA,MACA;AAAA,MACA;AAAA,MACA;AAAA,MACA;AAAA,MACA;AAAA,MACA;AAAA,MACA;AAAA;AAAA,MAEA;AAAA,MACA;AAAA,MACA;AAAA,MACA;AAAA,MACA;AAAA,MACA;AAAA,MACA;AAAA;AAAA,MAEA;AAAA,MACA;AAAA,MACA;AAAA,MACA;AAAA,MACA;AAAA,MACA;AAAA,MACA;AAAA,MACA;AAAA,IACF;AAAA,IACA,sBAAsB;AAAA;AAAA,MAEpB;AAAA,MACA;AAAA,MACA;AAAA,MACA;AAAA,MACA;AAAA,MACA;AAAA,MACA;AAAA,MACA;AAAA,MACA;AAAA,MACA;AAAA;AAAA,MAEA;AAAA,MACA;AAAA,MACA;AAAA,MACA;AAAA,MACA;AAAA,MACA;AAAA,MACA;AAAA,MACA;AAAA;AAAA,MAEA;AAAA,MACA;AAAA,MACA;AAAA,MACA;AAAA,MACA;AAAA;AAAA,MAEA;AAAA,MACA;AAAA,MACA;AAAA,MACA;AAAA,MACA;AAAA,MACA;AAAA,MACA;AAAA,MACA;AAAA;AAAA,MAEA;AAAA,MACA;AAAA,MACA;AAAA,MACA;AAAA,MACA;AAAA,MACA;AAAA,MACA;AAAA,MACA;AAAA;AAAA,MAEA;AAAA,MACA;AAAA,MACA;AAAA,MACA;AAAA,MACA;AAAA,MACA;AAAA,MACA;AAAA,MACA;AAAA;AAAA,MAEA;AAAA,MACA;AAAA,MACA;AAAA,MACA;AAAA,MACA;AAAA,MACA;AAAA,MACA;AAAA,MACA;AAAA;AAAA,MAEA;AAAA,MACA;AAAA,MACA;AAAA,MACA;AAAA,MACA;AAAA,MACA;AAAA;AAAA,MAEA;AAAA,MACA;AAAA,MACA;AAAA,MACA;AAAA,MACA;AAAA,MACA;AAAA,MACA;AAAA,MACA;AAAA,IACF;AAAA,IACA,sBAAsB;AAAA;AAAA,MAEpB;AAAA,MACA;AAAA,MACA;AAAA,MACA;AAAA,MACA;AAAA,MACA;AAAA,MACA;AAAA,MACA;AAAA,MACA;AAAA;AAAA,MAEA;AAAA,MACA;AAAA,MACA;AAAA;AAAA,MAEA;AAAA,MACA;AAAA,MACA;AAAA;AAAA,MAEA;AAAA,MACA;AAAA,MACA;AAAA;AAAA,MAEA;AAAA,MACA;AAAA,MACA;AAAA;AAAA,MAEA;AAAA,MACA;AAAA,MACA;AAAA;AAAA,MAEA;AAAA,MACA;AAAA,MACA;AAAA;AAAA,MAEA;AAAA,MACA;AAAA,MACA;AAAA;AAAA,MAEA;AAAA,MACA;AAAA,MACA;AAAA,IACF;AAAA,IACA,mBAAmB;AAAA;AAAA,MAEjB;AAAA,MACA;AAAA,MACA;AAAA,MACA;AAAA,MACA;AAAA,MACA;AAAA,MACA;AAAA,MACA;AAAA,MACA;AAAA;AAAA,MAEA;AAAA,MACA;AAAA,MACA;AAAA,MACA;AAAA,MACA;AAAA,MACA;AAAA,MACA;AAAA;AAAA,MAEA;AAAA,MACA;AAAA,MACA;AAAA,MACA;AAAA,MACA;AAAA,MACA;AAAA;AAAA,MAEA;AAAA,MACA;AAAA,MACA;AAAA,MACA;AAAA,MACA;AAAA,MACA;AAAA,MACA;AAAA,MACA;AAAA;AAAA,MAEA;AAAA,MACA;AAAA,MACA;AAAA,MACA;AAAA,MACA;AAAA,MACA;AAAA,MACA;AAAA,MACA;AAAA;AAAA,MAEA;AAAA,MACA;AAAA,MACA;AAAA,MACA;AAAA,MACA;AAAA,MACA;AAAA,MACA;AAAA;AAAA,MAEA;AAAA,MACA;AAAA,MACA;AAAA,MACA;AAAA,MACA;AAAA,MACA;AAAA,MACA;AAAA;AAAA,MAEA;AAAA,MACA;AAAA,MACA;AAAA,MACA;AAAA,MACA;AAAA,MACA;AAAA,MACA;AAAA;AAAA,MAEA;AAAA,MACA;AAAA,MACA;AAAA,MACA;AAAA,MACA;AAAA,MACA;AAAA,MACA;AAAA,IACF;AAAA,IACA,kBAAkB;AAAA;AAAA,MAEhB;AAAA,MACA;AAAA,MACA;AAAA,MACA;AAAA,MACA;AAAA,MACA;AAAA,MACA;AAAA,MACA;AAAA;AAAA,MAEA;AAAA,MACA;AAAA,MACA;AAAA,MACA;AAAA,MACA;AAAA,MACA;AAAA;AAAA,MAEA;AAAA,MACA;AAAA,MACA;AAAA,MACA;AAAA,MACA;AAAA;AAAA,MAEA;AAAA,MACA;AAAA,MACA;AAAA,MACA;AAAA,MACA;AAAA,MACA;AAAA,MACA;AAAA,MACA;AAAA,MACA;AAAA;AAAA,MAEA;AAAA,MACA;AAAA,MACA;AAAA,MACA;AAAA,MACA;AAAA,MACA;AAAA,MACA;AAAA;AAAA,MAEA;AAAA,MACA;AAAA,MACA;AAAA,MACA;AAAA,MACA;AAAA,MACA;AAAA;AAAA,MAEA;AAAA,MACA;AAAA,MACA;AAAA,MACA;AAAA,MACA;AAAA,MACA;AAAA;AAAA,MAEA;AAAA,MACA;AAAA,MACA;AAAA,MACA;AAAA,MACA;AAAA;AAAA,MAEA;AAAA,MACA;AAAA,MACA;AAAA,MACA;AAAA,MACA;AAAA,MACA;AAAA,IACF;AAAA,IACA,wBAAwB;AAAA;AAAA,MAEtB;AAAA,MACA;AAAA,MACA;AAAA,MACA;AAAA,MACA;AAAA,MACA;AAAA,MACA;AAAA,MACA;AAAA,MACA;AAAA,MACA;AAAA,MACA;AAAA,MACA;AAAA;AAAA,MAEA;AAAA,MACA;AAAA,MACA;AAAA,MACA;AAAA,MACA;AAAA,MACA;AAAA,MACA;AAAA,MACA;AAAA;AAAA,MAEA;AAAA,MACA;AAAA,MACA;AAAA,MACA;AAAA;AAAA,MAEA;AAAA,MACA;AAAA,MACA;AAAA,MACA;AAAA,MACA;AAAA,MACA;AAAA,MACA;AAAA,MACA;AAAA;AAAA,MAEA;AAAA,MACA;AAAA,MACA;AAAA,MACA;AAAA,MACA;AAAA,MACA;AAAA,MACA;AAAA,MACA;AAAA;AAAA,MAEA;AAAA,MACA;AAAA,MACA;AAAA,MACA;AAAA,MACA;AAAA,MACA;AAAA;AAAA,MAEA;AAAA,MACA;AAAA,MACA;AAAA,MACA;AAAA,MACA;AAAA,MACA;AAAA;AAAA,MAEA;AAAA,MACA;AAAA,MACA;AAAA,MACA;AAAA,MACA;AAAA;AAAA,MAEA;AAAA,MACA;AAAA,MACA;AAAA,MACA;AAAA,MACA;AAAA,IACF;AAAA;AAAA;AAAA,IAIA,qBAAqB;AAAA;AAAA,MAEnB;AAAA,MACA;AAAA,MACA;AAAA,MACA;AAAA,MACA;AAAA,MACA;AAAA,MACA;AAAA,MACA;AAAA,MACA;AAAA,MACA;AAAA,MACA;AAAA;AAAA,MAEA;AAAA,MACA;AAAA,MACA;AAAA,MACA;AAAA,MACA;AAAA,MACA;AAAA;AAAA,MAEA;AAAA,MACA;AAAA,MACA;AAAA,MACA;AAAA,MACA;AAAA;AAAA,MAEA;AAAA,MACA;AAAA,MACA;AAAA,MACA;AAAA,MACA;AAAA,MACA;AAAA,MACA;AAAA,MACA;AAAA;AAAA,MAEA;AAAA,MACA;AAAA,MACA;AAAA,MACA;AAAA,MACA;AAAA,MACA;AAAA,MACA;AAAA,MACA;AAAA,MACA;AAAA,MACA;AAAA,MACA;AAAA,MACA;AAAA,MACA;AAAA,MACA;AAAA,MACA;AAAA,MACA;AAAA,MACA;AAAA;AAAA,MAEA;AAAA,MACA;AAAA,MACA;AAAA,MACA;AAAA,MACA;AAAA,MACA;AAAA,MACA;AAAA,MACA;AAAA,MACA;AAAA,MACA;AAAA,MACA;AAAA,MACA;AAAA;AAAA,MAEA;AAAA,MACA;AAAA,MACA;AAAA,MACA;AAAA,MACA;AAAA,MACA;AAAA,MACA;AAAA,MACA;AAAA,MACA;AAAA,MACA;AAAA,MACA;AAAA,MACA;AAAA;AAAA,MAEA;AAAA,MAC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","names":["join","homedir","require","homedir","join","mkdir","writeFile","createPublicClient","http","base","privateKeyToAccount","payload","response","CACHE_TTL_MS","join","join","join","homedir","LOG_DIR","logger","confidence","supportsToolCalling","supportsVision","mkdir","join","homedir","privateKeyToAccount","finished","_32n","finished","sha512","sha512","join","homedir","mkdir","privateKeyToAccount","result","createHash","DEFAULT_TTL_MS","createHash","canonicalize","TIMESTAMP_PATTERN","createHash","DEFAULT_CONFIG","join","homedir","sanitized","account","privateKeyToAccount","baseUrl","balanceMonitor","createPublicClient","base","http","mkdir","port","writeFile","normalizedModel","logger","join","homedir"]}
|
|
1
|
+
{"version":3,"sources":["../src/config.ts","../src/index.ts","../src/fs-read.ts","../src/version.ts","../src/models.ts","../src/provider.ts","../src/proxy.ts","../src/payment-preauth.ts","../src/balance.ts","../src/errors.ts","../src/solana-balance.ts","../src/stats.ts","../src/logger.ts","../src/plugin-logger.ts","../src/session.ts","../src/router/rules.ts","../src/router/selector.ts","../src/router/config.ts","../src/router/index.ts","../src/auth.ts","../src/wallet.ts","../node_modules/@noble/hashes/src/utils.ts","../node_modules/@noble/hashes/src/hmac.ts","../node_modules/@noble/hashes/src/_md.ts","../node_modules/@noble/hashes/src/_u64.ts","../node_modules/@noble/hashes/src/sha2.ts","../node_modules/@noble/hashes/src/sha512.ts","../src/dedup.ts","../src/response-cache.ts","../src/journal.ts"],"sourcesContent":["\n\nconst DEFAULT_PORT = 8402;\n\nexport const PROXY_PORT = (() => {\n const envPort = process[\"env\"].CKCLOUD_PROXY_PORT;\n if (envPort) {\n const parsed = parseInt(envPort, 10);\n if (!isNaN(parsed) && parsed > 0 && parsed < 65536) {\n return parsed;\n }\n }\n return DEFAULT_PORT;\n})();\n\nexport const PLUGIN_NAME = \"ckcloud\"","import type {\n OpenClawPluginDefinition,\n OpenClawPluginApi,\n PluginCommandContext,\n OpenClawPluginCommandDefinition,\n} from \"./types.js\";\nimport { PLUGIN_NAME } from \"./config\"\nimport type { RoutingConfig } from \"./router/index.js\";\nimport { BalanceMonitor } from \"./balance.js\";\nimport { join } from \"node:path\";\nimport { homedir } from \"node:os\";\nimport { writeFileSync, existsSync, readdirSync, mkdirSync, copyFileSync, renameSync } from \"node:fs\";\nimport { readTextFileSync } from \"./fs-read\"\n\nimport { VERSION } from \"./version\";\nimport { ckcloudProvider, setActiveProxy } from \"./provider\"\nimport { getProxyPort, startProxy } from \"./proxy\"\nimport { OPENCLAW_MODELS, initBaseModels } from \"./models\"\nimport { getStats, formatStatsAscii, clearStats } from \"./stats\";\n\nimport {\n resolveOrGenerateWalletKey,\n setupSolana,\n savePaymentChain,\n resolvePaymentChain,\n WALLET_FILE,\n MNEMONIC_FILE,\n} from \"./auth.js\";\n\nimport { setPluginLogger } from \"./plugin-logger.js\";\n\nlet activeProxyHandle: Awaited<ReturnType<typeof startProxy>> | null = null;\n\nfunction isCompletionMode(): boolean {\n const args = process.argv;\n // Check for: openclaw completion --shell <shell>\n // argv[0] = node/bun, argv[1] = openclaw, argv[2] = completion\n return args.some((arg, i) => arg === \"completion\" && i >= 1 && i <= 3);\n}\n\nconst plugin: OpenClawPluginDefinition = {\n id: PLUGIN_NAME,\n name: PLUGIN_NAME,\n description: \"Smart LLM router — 80% cost savings\",\n version: VERSION,\n\n register(api: OpenClawPluginApi) {\n setPluginLogger(api.logger);\n const isDisabled = process[\"env\"].CKCLOUDROUTER_DISABLED === \"true\" || process[\"env\"].CKCLOUDROUTER_DISABLED === \"1\";\n if (isDisabled) {\n api.logger.info(\"ckcloudrouter disabled (CKCLOUDROUTER_DISABLED=true). Using default routing.\");\n return;\n }\n\n if (isCompletionMode()) {\n api.registerProvider(ckcloudProvider);\n return;\n }\n\n api.registerProvider(ckcloudProvider);\n\n // Inject models config into OpenClaw config file\n // This persists the config so models are recognized on restart\n injectModelsConfig(api.logger);\n\n // Inject dummy auth profiles into agent auth stores\n // OpenClaw's agent system looks for auth even if provider has auth: []\n injectAuthProfile(api.logger);\n\n // Also set runtime config for immediate availability\n const runtimePort = getProxyPort();\n if (!api.config.models) {\n api.config.models = { providers: {} };\n }\n if (!api.config.models.providers) {\n api.config.models.providers = {};\n }\n api.config.models.providers.ckcloud = {\n baseUrl: `http://127.0.0.1:${runtimePort}/v1`,\n api: \"openai-completions\",\n // apiKey is required by pi-coding-agent's ModelRegistry for providers with models.\n apiKey: \"x402-proxy-handles-auth\",\n models: OPENCLAW_MODELS,\n };\n api.logger.info(\"ckcloud provider registered\");\n\n // Refresh model list from CKCLOUD_MODEL_API once available\n initBaseModels()\n .then(() => {\n injectModelsConfig(api.logger);\n if (api.config.models?.providers?.ckcloud) {\n api.config.models.providers.ckcloud.models = OPENCLAW_MODELS;\n }\n })\n .catch((err) => {\n api.logger.warn(\n `Failed to refresh models list: ${err instanceof Error ? err.message : String(err)}`,\n );\n });\n\n // TODO Register /wallet command for wallet management\n\n\n // Register /stats command for usage statistics\n createStatsCommand().then((statsCommand) => {\n api.registerCommand(statsCommand);\n }).catch((err) => {\n api.logger.warn(`Failed to register /stats command: ${err instanceof Error ? err.message : String(err)}`,);\n });\n\n api.registerService({\n id: \"ckcloud-proxy\",\n start: () => {\n // No-op: proxy is started below in non-blocking mode\n },\n stop: async () => {\n // Close proxy on gateway shutdown to release port 8402\n if (activeProxyHandle) {\n try {\n await activeProxyHandle.close();\n api.logger.info(\"ckcloud proxy closed\");\n } catch (err) {\n api.logger.warn(\n `Failed to close proxy: ${err instanceof Error ? err.message : String(err)}`,\n );\n }\n activeProxyHandle = null;\n }\n },\n });\n\n // Skip proxy startup unless we're in gateway mode\n // The proxy keeps the Node.js event loop alive, preventing CLI commands from exiting\n // The proxy will start automatically when the gateway runs\n if (!isGatewayMode()) {\n // Generate wallet on first install (even outside gateway mode)\n // This ensures users can see their wallet address immediately after install\n resolveOrGenerateWalletKey()\n .then(({ address, source }) => {\n if (source === \"generated\") {\n api.logger.warn(`════════════════════════════════════════════════`);\n api.logger.warn(` NEW WALLET GENERATED — BACK UP YOUR KEY NOW!`);\n api.logger.warn(` Address : ${address}`);\n api.logger.warn(` Run /wallet export to get your private key`);\n api.logger.warn(` Losing this key = losing your USDC funds`);\n api.logger.warn(`════════════════════════════════════════════════`);\n } else if (source === \"saved\") {\n api.logger.info(`Using saved wallet: ${address}`);\n } else {\n api.logger.info(`Using wallet from WALLET_KEY: ${address}`);\n }\n })\n .catch((err) => {\n api.logger.warn(\n `Failed to initialize wallet: ${err instanceof Error ? err.message : String(err)}`,\n );\n });\n api.logger.info(\"Not in gateway mode — proxy will start when gateway runs\");\n return;\n }\n\n // Start x402 proxy in background WITHOUT blocking register()\n // CRITICAL: Do NOT await here - this was blocking model selection UI for 3+ seconds\n // causing Chandler's \"infinite loop\" issue where model selection never finishes\n // Note: startProxyInBackground calls resolveOrGenerateWalletKey internally\n startProxyInBackground(api)\n .then(async () => {\n // Proxy started successfully - verify health\n const port = getProxyPort();\n const healthy = await waitForProxyHealth(port, 5000);\n if (!healthy) {\n api.logger.warn(`Proxy health check timed out, commands may not work immediately`);\n }\n })\n .catch((err) => {\n api.logger.error(\n `Failed to start ckcloud proxy: ${err instanceof Error ? err.message : String(err)}`,\n );\n });\n\n }\n}\n\n\n/**\n * Wait for proxy health check to pass (quick check, not RPC).\n * Returns true if healthy within timeout, false otherwise.\n */\nasync function waitForProxyHealth(port: number, timeoutMs = 3000): Promise<boolean> {\n const start = Date.now();\n while (Date.now() - start < timeoutMs) {\n try {\n const res = await fetch(`http://127.0.0.1:${port}/health`);\n if (res.ok) return true;\n } catch {\n // Proxy not ready yet\n }\n await new Promise((r) => setTimeout(r, 100));\n }\n return false;\n}\n\nfunction isGatewayMode(): boolean {\n const args = process.argv;\n // Gateway mode is: openclaw gateway start/restart/stop\n return args.includes(\"gateway\");\n}\n\nfunction injectModelsConfig(logger: { info: (msg: string) => void }): void {\n const configDir = join(homedir(), \".openclaw\");\n const configPath = join(configDir, \"openclaw.json\");\n\n let config: Record<string, unknown> = {};\n let needsWrite = false;\n\n // Create config directory if it doesn't exist\n if (!existsSync(configDir)) {\n try {\n mkdirSync(configDir, { recursive: true });\n logger.info(\"Created OpenClaw config directory\");\n } catch (err) {\n logger.info(\n `Failed to create config dir: ${err instanceof Error ? err.message : String(err)}`,\n );\n return;\n }\n }\n\n // Load existing config or create new one\n // IMPORTANT: On parse failure, we backup and skip writing to avoid clobbering\n // other plugins' config (e.g. Telegram channels). This prevents a race condition\n // where a partial/corrupt config file causes us to overwrite everything with\n // only our models+agents sections.\n if (existsSync(configPath)) {\n try {\n const content = readTextFileSync(configPath).trim();\n if (content) {\n config = JSON.parse(content);\n } else {\n logger.info(\"OpenClaw config is empty, initializing\");\n needsWrite = true;\n }\n } catch (err) {\n // Config file exists but is corrupt/invalid JSON — likely a partial write\n // from another plugin or a race condition during gateway restart.\n // Backup the corrupt file and SKIP writing to avoid losing other config.\n const backupPath = `${configPath}.backup.${Date.now()}`;\n try {\n copyFileSync(configPath, backupPath);\n logger.info(`Config parse failed, backed up to ${backupPath}`);\n } catch {\n logger.info(\"Config parse failed, could not create backup\");\n }\n logger.info(\n `Skipping config injection (corrupt file): ${err instanceof Error ? err.message : String(err)}`,\n );\n return; // Don't write — we'd lose other plugins' config\n }\n } else {\n logger.info(\"OpenClaw config not found, creating\");\n needsWrite = true;\n }\n\n // Initialize config structure\n if (!config.models) {\n config.models = {};\n needsWrite = true;\n }\n const models = config.models as Record<string, unknown>;\n if (!models.providers) {\n models.providers = {};\n needsWrite = true;\n }\n\n const proxyPort = getProxyPort();\n const expectedBaseUrl = `http://127.0.0.1:${proxyPort}/v1`;\n\n const providers = models.providers as Record<string, unknown>;\n\n if (!providers.ckcloud) {\n providers.ckcloud = {\n baseUrl: expectedBaseUrl,\n api: \"openai-completions\",\n apiKey: \"x402-proxy-handles-auth\",//place holder\n models: OPENCLAW_MODELS,\n };\n logger.info(\"Injected ckcloud provider config\");\n needsWrite = true;\n } else {\n // Validate and fix existing config\n const ckcloud = providers.ckcloud as Record<string, unknown>;\n let fixed = false;\n\n if (!ckcloud.baseUrl || ckcloud.baseUrl !== expectedBaseUrl) {\n ckcloud.baseUrl = expectedBaseUrl;\n fixed = true;\n }\n if (!ckcloud.api) {\n ckcloud.api = \"openai-completions\";\n fixed = true;\n }\n if (!ckcloud.apiKey) {\n ckcloud.apiKey = \"x402-proxy-handles-auth\"; //TODO\n fixed = true;\n }\n // Always refresh models list (ensures new models/aliases are available)\n // Check both length AND content - new models may be added without changing count\n const currentModels = ckcloud.models as Array<{ id?: string }>;\n const currentModelIds = new Set(\n Array.isArray(currentModels) ? currentModels.map((m) => m?.id).filter(Boolean) : [],\n );\n const expectedModelIds = OPENCLAW_MODELS.map((m) => m.id);\n const needsModelUpdate =\n !currentModels ||\n !Array.isArray(currentModels) ||\n currentModels.length !== OPENCLAW_MODELS.length ||\n expectedModelIds.some((id) => !currentModelIds.has(id));\n\n if (needsModelUpdate) {\n ckcloud.models = OPENCLAW_MODELS;\n fixed = true;\n logger.info(`Updated models list (${OPENCLAW_MODELS.length} models)`);\n }\n\n if (fixed) {\n logger.info(\"Fixed incomplete ckcloud provider config\");\n needsWrite = true;\n }\n }\n\n if (!config.agents) {\n config.agents = {};\n needsWrite = true;\n }\n const agents = config.agents as Record<string, unknown>;\n if (!agents.defaults) {\n agents.defaults = {};\n needsWrite = true;\n }\n const defaults = agents.defaults as Record<string, unknown>;\n if (!defaults.model) {\n defaults.model = {};\n needsWrite = true;\n }\n const model = defaults.model as Record<string, unknown>;\n if (!model.primary) {\n model.primary = \"ckcloud/free\"; //TODO: default model\n logger.info(\"Set default model\");\n needsWrite = true;\n }\n\n const TOP_MODELS = [\n \"free\",\n \"eco\",\n \"premium\",\n \"anthropic/claude-sonnet-4.5\",\n \"openai/gpt-5.2\",\n \"deepseek/deepseek-chat\",\n \"moonshot/kimi-k2.5\",\n \"minimax/minimax-m2.5\",\n ];\n if (!defaults.models || typeof defaults.models !== \"object\" || Array.isArray(defaults.models)) {\n defaults.models = {};\n needsWrite = true;\n }\n const allowlist = defaults.models as Record<string, unknown>;\n // Additive-only: add TOP_MODELS entries if missing, never delete user-defined entries.\n // Preserves any ckcloud/* IDs the user has manually added outside this curated list.\n let addedCount = 0;\n for (const id of TOP_MODELS) {\n const key = `ckcloud/${id}`;\n if (!allowlist[key]) {\n allowlist[key] = {};\n addedCount++;\n }\n }\n if (addedCount > 0) {\n needsWrite = true;\n logger.info(`Added ${addedCount} models to allowlist (${TOP_MODELS.length} total)`);\n }\n\n // Write config file if any changes were made\n // Use atomic write (temp file + rename) to prevent partial writes that could\n // corrupt the config and cause other plugins to lose their settings on next load.\n if (needsWrite) {\n try {\n const tmpPath = `${configPath}.tmp.${process.pid}`;\n writeFileSync(tmpPath, JSON.stringify(config, null, 2));\n renameSync(tmpPath, configPath);\n logger.info(\"Smart routing enabled (ckcloud/auto)\");\n } catch (err) {\n logger.info(`Failed to write config: ${err instanceof Error ? err.message : String(err)}`);\n }\n }\n}\n\n\n/**\n * Inject dummy auth profile for ckcloud into agent auth stores.\n * OpenClaw's agent system looks for auth credentials even if provider has auth: [].\n * We inject a placeholder so the lookup succeeds (proxy handles real auth internally).\n */\nfunction injectAuthProfile(logger: { info: (msg: string) => void }): void {\n const agentsDir = join(homedir(), \".openclaw\", \"agents\");\n\n // Create agents directory if it doesn't exist\n if (!existsSync(agentsDir)) {\n try {\n mkdirSync(agentsDir, { recursive: true });\n } catch (err) {\n logger.info(\n `Could not create agents dir: ${err instanceof Error ? err.message : String(err)}`,\n );\n return;\n }\n }\n\n try {\n // Find all agent directories\n let agents = readdirSync(agentsDir, { withFileTypes: true })\n .filter((d) => d.isDirectory())\n .map((d) => d.name);\n\n // Always ensure \"main\" agent has auth (most common agent)\n if (!agents.includes(\"main\")) {\n agents = [\"main\", ...agents];\n }\n\n for (const agentId of agents) {\n const authDir = join(agentsDir, agentId, \"agent\");\n const authPath = join(authDir, \"auth-profiles.json\");\n\n // Create agent dir if needed\n if (!existsSync(authDir)) {\n try {\n mkdirSync(authDir, { recursive: true });\n } catch {\n continue; // Skip if we can't create the dir\n }\n }\n\n // Load or create auth-profiles.json with correct OpenClaw format\n // Format: { version: 1, profiles: { \"provider:profileId\": { type, provider, key } } }\n let store: { version: number; profiles: Record<string, unknown> } = {\n version: 1,\n profiles: {},\n };\n if (existsSync(authPath)) {\n try {\n const existing = JSON.parse(readTextFileSync(authPath));\n // Check if valid OpenClaw format (has version and profiles)\n if (existing.version && existing.profiles) {\n store = existing;\n }\n // Old format without version/profiles is discarded and recreated\n } catch {\n // Invalid JSON, use fresh store\n }\n }\n\n // Check if ckcloud auth already exists (OpenClaw format: profiles[\"provider:profileId\"])\n const profileKey = \"ckcloud:default\";\n if (store.profiles[profileKey]) {\n continue; // Already configured\n }\n\n // Inject placeholder auth for ckcloud (OpenClaw format)\n // The proxy handles real x402 auth internally, this just satisfies OpenClaw's lookup\n store.profiles[profileKey] = {\n type: \"api_key\",\n provider: \"ckcloud\",\n key: \"x402-proxy-handles-auth\",\n };\n\n try {\n writeFileSync(authPath, JSON.stringify(store, null, 2));\n logger.info(`Injected ckcloud auth profile for agent: ${agentId}`);\n } catch (err) {\n logger.info(\n `Could not inject auth for ${agentId}: ${err instanceof Error ? err.message : String(err)}`,\n );\n }\n }\n } catch (err) {\n logger.info(`Auth injection failed: ${err instanceof Error ? err.message : String(err)}`);\n }\n}\n\n/**\n * /stats command handler for ckcloud.\n * Shows usage statistics and cost savings.\n */\nasync function createStatsCommand(): Promise<OpenClawPluginCommandDefinition> {\n return {\n name: \"stats\",\n description: \"Show ckcloud usage statistics and cost savings\",\n acceptsArgs: true,\n requireAuth: false,\n handler: async (ctx: PluginCommandContext) => {\n const arg = ctx.args?.trim().toLowerCase() || \"7\";\n\n if (arg === \"clear\" || arg === \"reset\") {\n try {\n const { deletedFiles } = await clearStats();\n return {\n text: `Stats cleared — ${deletedFiles} log file(s) deleted. Fresh start!`,\n };\n } catch (err) {\n return {\n text: `Failed to clear stats: ${err instanceof Error ? err.message : String(err)}`,\n isError: true,\n };\n }\n }\n\n const days = parseInt(arg, 10) || 7;\n\n try {\n const stats = await getStats(Math.min(days, 30)); // Cap at 30 days\n const ascii = formatStatsAscii(stats);\n\n return {\n text: [\"```\", ascii, \"```\"].join(\"\\n\"),\n };\n } catch (err) {\n return {\n text: `Failed to load stats: ${err instanceof Error ? err.message : String(err)}`,\n isError: true,\n };\n }\n },\n };\n}\n\n/**\n * Start the x402 proxy in the background.\n * Called from register() because OpenClaw's loader only invokes register(),\n * treating activate() as an alias (def.register ?? def.activate).\n */\nasync function startProxyInBackground(api: OpenClawPluginApi): Promise<void> {\n // Resolve wallet key: saved file → env var → auto-generate\n const wallet = await resolveOrGenerateWalletKey();\n\n // Log wallet source\n if (wallet.source === \"generated\") {\n api.logger.warn(`════════════════════════════════════════════════`);\n api.logger.warn(` NEW WALLET GENERATED — BACK UP YOUR KEY NOW!`);\n api.logger.warn(` Address : ${wallet.address}`);\n api.logger.warn(` Run /wallet export to get your private key`);\n api.logger.warn(` Losing this key = losing your USDC funds`);\n api.logger.warn(`════════════════════════════════════════════════`);\n } else if (wallet.source === \"saved\") {\n api.logger.info(`Using saved wallet: ${wallet.address}`);\n } else {\n api.logger.info(`Using wallet from WALLET_KEY: ${wallet.address}`);\n }\n\n // Resolve routing config overrides from plugin config\n const routingConfig = api.pluginConfig?.routing as Partial<RoutingConfig> | undefined;\n\n const proxy = await startProxy({\n wallet,\n routingConfig,\n logger: api.logger,\n onReady: (port) => {\n api.logger.info(`ckcloud x402 proxy listening on port ${port}`);\n },\n onError: (error) => {\n api.logger.error(`ckcloud proxy error: ${error.message}`);\n },\n onRouted: (decision) => {\n const cost = decision.costEstimate.toFixed(4);\n const saved = (decision.savings * 100).toFixed(0);\n api.logger.info(\n `ckcloud onRouted: [${decision.tier}] ${decision.model} $${cost} (saved ${saved}%) | ${decision.reasoning}`,\n );\n },\n onLowBalance: (info) => {\n api.logger.warn(`[!] Low balance: ${info.balanceUSD}. Fund wallet: ${info.walletAddress}`);\n },\n onInsufficientFunds: (info) => {\n api.logger.error(\n `[!] Insufficient funds. Balance: ${info.balanceUSD}, Needed: ${info.requiredUSD}. Fund wallet: ${info.walletAddress}`,\n );\n },\n });\n\n setActiveProxy(proxy);\n activeProxyHandle = proxy;\n\n api.logger.info(`ckcloud ready — smart routing enabled`);\n api.logger.info(`Pricing: Simple ~$0.001 | Code ~$0.01 | Complex ~$0.05 | Free: $0`);\n\n // Non-blocking balance check AFTER proxy is ready (won't hang startup)\n // Uses the proxy's chain-aware balance monitor and matching active-chain address.\n const currentChain = await resolvePaymentChain();\n const displayAddress =\n currentChain === \"solana\" && proxy.solanaAddress ? proxy.solanaAddress : wallet.address;\n proxy.balanceMonitor\n .checkBalance()\n .then((balance) => {\n if (balance.isEmpty) {\n api.logger.info(`Wallet: ${displayAddress} | Balance: $0.00`);\n api.logger.info(`Using FREE model. Fund wallet for premium models.`);\n } else if (balance.isLow) {\n api.logger.info(`Wallet: ${displayAddress} | Balance: ${balance.balanceUSD} (low)`);\n } else {\n api.logger.info(`Wallet: ${displayAddress} | Balance: ${balance.balanceUSD}`);\n }\n })\n .catch(() => {\n // Silently continue - balance will be checked per-request anyway\n api.logger.info(`Wallet: ${displayAddress} | Balance: (checking...)`);\n });\n}\n\n\nexport default plugin;\n","import { open } from \"node:fs/promises\";\nimport { openSync, readSync, closeSync, fstatSync } from \"node:fs\";\n\n/** Read file contents as UTF-8 string (async). */\nexport async function readTextFile(filePath: string): Promise<string> {\n const fh = await open(filePath, \"r\");\n try {\n const size = (await fh.stat()).size;\n const buf = Buffer.alloc(size);\n let offset = 0;\n while (offset < size) {\n const { bytesRead } = await fh.read(buf, offset, size - offset, offset);\n if (bytesRead === 0) break;\n offset += bytesRead;\n }\n return buf.subarray(0, offset).toString(\"utf-8\");\n } finally {\n await fh.close();\n }\n}\n\n/** Read file contents as UTF-8 string (sync). */\nexport function readTextFileSync(filePath: string): string {\n const fd = openSync(filePath, \"r\");\n try {\n const size = fstatSync(fd).size;\n const buf = Buffer.alloc(size);\n let offset = 0;\n while (offset < size) {\n const bytesRead = readSync(fd, buf, offset, size - offset, offset);\n if (bytesRead === 0) break;\n offset += bytesRead;\n }\n return buf.subarray(0, offset).toString(\"utf-8\");\n } finally {\n closeSync(fd);\n }\n}","/**\n * Single source of truth for version.\n * Reads from package.json at build time via tsup's define.\n */\nimport { createRequire } from \"node:module\";\nimport { fileURLToPath } from \"node:url\";\nimport { dirname, join } from \"node:path\";\n\n// Read package.json at runtime\nconst __filename = fileURLToPath(import.meta.url);\nconst __dirname = dirname(__filename);\n\n// In dist/, go up one level to find package.json\nconst require = createRequire(import.meta.url);\nconst pkg = require(join(__dirname, \"..\", \"package.json\")) as { version: string };\n\nexport const VERSION = pkg.version;\nexport const USER_AGENT = `ckcloud/${VERSION}`;\n","import type { ModelDefinitionConfig, ModelProviderConfig } from \"./types.js\";\n\nexport const BASE_API_URL = \"https://www.ckcloudai.com/api\";\nexport const CKCLOUD_MODEL_API = \"https://t.ckcloudai.com/v1/models\";\n\nconst MODEL_FETCH_TIMEOUT_MS = 3_000;\n\ntype BaseModel = {\n id: string;\n name: string;\n /** Model version (e.g., \"4.6\", \"3.1\", \"5.2\") for tracking updates */\n version?: string;\n inputPrice: number;\n outputPrice: number;\n contextWindow: number;\n maxOutput: number;\n reasoning?: boolean;\n vision?: boolean;\n /** Models optimized for agentic workflows (multi-step autonomous tasks) */\n agentic?: boolean;\n /**\n * Model supports OpenAI-compatible structured function/tool calling.\n * Models without this flag output tool invocations as plain text JSON,\n * which leaks raw {\"command\":\"...\"} into visible chat messages.\n * Default: false (must opt-in to prevent silent regressions on new models).\n */\n toolCalling?: boolean;\n};\n\nconst DEFAULT_BASE_MODELS: BaseModel[] = [\n // Smart routing meta-models — proxy replaces with actual model\n // NOTE: Model IDs are WITHOUT provider prefix (OpenClaw adds \"ckcloud/\" automatically)\n {\n id: \"auto\",\n name: \"Auto (Smart Router - Balanced)\",\n inputPrice: 0,\n outputPrice: 0,\n contextWindow: 1_050_000,\n maxOutput: 128_000,\n }\n];\n\ntype CkcloudApiModel = {\n contextLength?: number;\n description?: string;\n displayName?: string;\n inputPrice?: number;\n model?: string;\n modelType?: string;\n outputPrice?: number;\n provider?: string;\n supportFunction?: boolean;\n};\n\nfunction mapCkcloudModel(raw: CkcloudApiModel): BaseModel | null {\n const id = typeof raw.model === \"string\" ? raw.model.trim() : \"\";\n if (!id) return null;\n\n const contextLength = Number(raw.contextLength ?? 0);\n const normalizedContext = Number.isFinite(contextLength) && contextLength > 0 ? contextLength : 4096;\n\n const inputPrice = Number(raw.inputPrice ?? 0);\n const outputPrice = Number(raw.outputPrice ?? 0);\n\n return {\n id,\n name: typeof raw.displayName === \"string\" && raw.displayName.trim() ? raw.displayName.trim() : id,\n inputPrice: Number.isFinite(inputPrice) ? inputPrice : 0,\n outputPrice: Number.isFinite(outputPrice) ? outputPrice : 0,\n contextWindow: normalizedContext,\n maxOutput: Math.min(128_000, normalizedContext),\n toolCalling: Boolean(raw.supportFunction),\n };\n}\n\nfunction mergeBaseModels(apiModels: BaseModel[]): BaseModel[] {\n const merged = [...DEFAULT_BASE_MODELS];\n const seen = new Set(merged.map((m) => m.id));\n for (const m of apiModels) {\n if (seen.has(m.id)) continue;\n merged.push(m);\n seen.add(m.id);\n }\n return merged;\n}\n\nasync function loadBaseModels(): Promise<BaseModel[]> {\n const controller = new AbortController();\n const timeout = setTimeout(() => controller.abort(), MODEL_FETCH_TIMEOUT_MS);\n try {\n const res = await fetch(CKCLOUD_MODEL_API, { signal: controller.signal });\n if (!res.ok) {\n return DEFAULT_BASE_MODELS;\n }\n const body = (await res.json()) as CkcloudApiModel[];\n if (!Array.isArray(body)) return DEFAULT_BASE_MODELS;\n const mapped = body.map(mapCkcloudModel).filter((m): m is BaseModel => m !== null);\n if (mapped.length === 0) return DEFAULT_BASE_MODELS;\n return mergeBaseModels(mapped);\n } catch {\n return DEFAULT_BASE_MODELS;\n } finally {\n clearTimeout(timeout);\n }\n}\n\nexport let BASE_MODELS: BaseModel[] = [...DEFAULT_BASE_MODELS];\n\n\n/**\n * Resolve a model alias to its full model ID.\n * Also strips \"ckcloud/\" prefix for direct model paths.\n * Examples:\n * - \"claude\" -> \"anthropic/claude-sonnet-4-6\" (alias)\n * - \"ckcloud/claude\" -> \"anthropic/claude-sonnet-4-6\" (alias with prefix)\n * - \"ckcloud/anthropic/claude-sonnet-4-6\" -> \"anthropic/claude-sonnet-4-6\" (prefix stripped)\n * - \"openai/gpt-4o\" -> \"openai/gpt-4o\" (unchanged)\n */\nexport function resolveModelAlias(model: string): string {\n const normalized = model.trim().toLowerCase();\n const resolved = MODEL_ALIASES[normalized];\n if (resolved) return resolved;\n\n // Check with \"ckcloud/\" prefix stripped\n if (normalized.startsWith(\"ckcloud/\")) {\n const withoutPrefix = normalized.slice(\"ckcloud/\".length);\n const resolvedWithoutPrefix = MODEL_ALIASES[withoutPrefix];\n if (resolvedWithoutPrefix) return resolvedWithoutPrefix;\n\n // Even if not an alias, strip the prefix for direct model paths\n // e.g., \"ckcloud/anthropic/claude-sonnet-4-6\" -> \"anthropic/claude-sonnet-4-6\"\n return withoutPrefix;\n }\n\n // Strip \"openai/\" prefix when it wraps a virtual routing profile or alias.\n // OpenClaw sends virtual models as \"openai/eco\", \"openai/free\", etc. because\n // the provider uses the openai-completions API type.\n if (normalized.startsWith(\"openai/\")) {\n const withoutPrefix = normalized.slice(\"openai/\".length);\n const resolvedWithoutPrefix = MODEL_ALIASES[withoutPrefix];\n if (resolvedWithoutPrefix) return resolvedWithoutPrefix;\n\n // If it's a known virtual profile (eco, free, auto, premium), return bare id\n const isVirtualProfile = BASE_MODELS.some((m) => m.id === withoutPrefix);\n if (isVirtualProfile) return withoutPrefix;\n }\n\n return model;\n}\n\n/**\n * Convert model definitions to OpenClaw ModelDefinitionConfig format.\n */\nfunction toOpenClawModel(m: BaseModel): ModelDefinitionConfig {\n return {\n id: m.id,\n name: m.name,\n api: \"openai-completions\",\n reasoning: m.reasoning ?? false,\n input: m.vision ? [\"text\", \"image\"] : [\"text\"],\n cost: {\n input: m.inputPrice,\n output: m.outputPrice,\n cacheRead: 0,\n cacheWrite: 0,\n },\n contextWindow: m.contextWindow,\n maxTokens: m.maxOutput,\n };\n}\n\n\n/**\n * Model aliases for convenient shorthand access.\n * Users can type `/model claude` instead of `/model ckcloud/anthropic/claude-sonnet-4-6`.\n */\nexport const MODEL_ALIASES: Record<string, string> = {\n // Claude - use newest versions (4.6)\n claude: \"anthropic/claude-sonnet-4.6\",\n sonnet: \"anthropic/claude-sonnet-4.6\",\n \"sonnet-4\": \"anthropic/claude-sonnet-4.6\",\n \"sonnet-4.6\": \"anthropic/claude-sonnet-4.6\",\n \"sonnet-4-6\": \"anthropic/claude-sonnet-4.6\",\n opus: \"anthropic/claude-opus-4.6\",\n \"opus-4\": \"anthropic/claude-opus-4.6\",\n \"opus-4.6\": \"anthropic/claude-opus-4.6\",\n \"opus-4-6\": \"anthropic/claude-opus-4.6\",\n haiku: \"anthropic/claude-haiku-4.5\",\n // Claude - provider/shortname patterns (common in agent frameworks)\n \"anthropic/sonnet\": \"anthropic/claude-sonnet-4.6\",\n \"anthropic/opus\": \"anthropic/claude-opus-4.6\",\n \"anthropic/haiku\": \"anthropic/claude-haiku-4.5\",\n \"anthropic/claude\": \"anthropic/claude-sonnet-4.6\",\n // Backward compatibility - map all variants to 4.6\n \"anthropic/claude-sonnet-4\": \"anthropic/claude-sonnet-4.6\",\n \"anthropic/claude-sonnet-4-6\": \"anthropic/claude-sonnet-4.6\",\n \"anthropic/claude-opus-4\": \"anthropic/claude-opus-4.6\",\n \"anthropic/claude-opus-4-6\": \"anthropic/claude-opus-4.6\",\n \"anthropic/claude-opus-4.5\": \"anthropic/claude-opus-4.6\",\n \"anthropic/claude-haiku-4\": \"anthropic/claude-haiku-4.5\",\n \"anthropic/claude-haiku-4-5\": \"anthropic/claude-haiku-4.5\",\n\n // OpenAI\n gpt: \"openai/gpt-4o\",\n gpt4: \"openai/gpt-4o\",\n gpt5: \"openai/gpt-5.4\",\n \"gpt-5.4\": \"openai/gpt-5.4\",\n \"gpt-5.4-pro\": \"openai/gpt-5.4-pro\",\n codex: \"openai/gpt-5.2-codex\",\n mini: \"openai/gpt-4o-mini\",\n o1: \"openai/o1\",\n o3: \"openai/o3\",\n\n // DeepSeek\n deepseek: \"deepseek/deepseek-chat\",\n reasoner: \"deepseek/deepseek-reasoner\",\n\n // Kimi / Moonshot\n kimi: \"moonshot/kimi-k2.5\",\n moonshot: \"moonshot/kimi-k2.5\",\n \"kimi-k2.5\": \"moonshot/kimi-k2.5\",\n\n // Google\n gemini: \"google/gemini-2.5-pro\",\n flash: \"google/gemini-2.5-flash\",\n \"gemini-3.1-pro-preview\": \"google/gemini-3.1-pro\",\n \"google/gemini-3.1-pro-preview\": \"google/gemini-3.1-pro\",\n\n // xAI\n grok: \"xai/grok-3\",\n \"grok-fast\": \"xai/grok-4-fast-reasoning\",\n \"grok-code\": \"xai/grok-code-fast-1\",\n\n // NVIDIA\n nvidia: \"nvidia/gpt-oss-120b\",\n \"gpt-120b\": \"nvidia/gpt-oss-120b\",\n\n // MiniMax\n minimax: \"minimax/minimax-m2.5\",\n\n // Routing profile aliases (common variations)\n \"auto-router\": \"auto\",\n router: \"auto\",\n\n // Note: auto, free, eco, premium are virtual routing profiles registered in BASE_MODELS\n // They don't need aliases since they're already top-level model IDs\n};\n\n/**\n * Alias models that map to real models.\n * These allow users to use friendly names like \"free\" or \"gpt-120b\".\n */\nfunction buildAliasModels(baseModels: BaseModel[]): ModelDefinitionConfig[] {\n return Object.entries(MODEL_ALIASES)\n .map(([alias, targetId]) => {\n const target = baseModels.find((m) => m.id === targetId);\n if (!target) return null;\n return toOpenClawModel({ ...target, id: alias, name: `${alias} → ${target.name}` });\n })\n .filter((m): m is ModelDefinitionConfig => m !== null);\n}\n\nexport let OPENCLAW_MODELS: ModelDefinitionConfig[] = [\n ...BASE_MODELS.map(toOpenClawModel),\n ...buildAliasModels(BASE_MODELS),\n];\n\nlet baseModelsInit: Promise<void> | null = null;\n\nfunction rebuildModels(nextBaseModels: BaseModel[]): void {\n BASE_MODELS = nextBaseModels;\n OPENCLAW_MODELS = [\n ...BASE_MODELS.map(toOpenClawModel),\n ...buildAliasModels(BASE_MODELS),\n ];\n}\n\nexport function initBaseModels(): Promise<void> {\n if (baseModelsInit) return baseModelsInit;\n baseModelsInit = (async () => {\n const next = await loadBaseModels();\n rebuildModels(next);\n })();\n return baseModelsInit;\n}\n\n// Kick off async initialization without blocking module load.\nvoid initBaseModels();\n\nexport function buildProviderModels(baseUrl: string): ModelProviderConfig {\n if (!baseUrl) {\n baseUrl = BASE_API_URL\n }\n\n return {\n baseUrl: `${baseUrl}/v1`,\n api: \"openai-completions\",\n models: OPENCLAW_MODELS,\n };\n}\n\n/**\n * Get context window size for a model.\n * Returns undefined if model not found.\n */\nexport function getModelContextWindow(modelId: string): number | undefined {\n const normalized = modelId.replace(\"ckcloud/\", \"\");\n const model = BASE_MODELS.find((m) => m.id === normalized);\n return model?.contextWindow;\n}\n\n/**\n * Check if a model has reasoning/thinking capabilities.\n * Reasoning models may require reasoning_content in assistant tool_call messages.\n */\nexport function isReasoningModel(modelId: string): boolean {\n const normalized = modelId.replace(\"ckcloud/\", \"\");\n const model = BASE_MODELS.find((m) => m.id === normalized);\n return model?.reasoning ?? false;\n}\n\n/**\n * Check if a model supports OpenAI-compatible structured tool/function calling.\n * Models without this flag (e.g. grok-code-fast-1) output tool invocations as\n * plain text JSON, which leaks {\"command\":\"...\"} into visible chat messages.\n */\nexport function supportsToolCalling(modelId: string): boolean {\n const normalized = modelId.replace(\"ckcloud/\", \"\");\n const model = BASE_MODELS.find((m) => m.id === normalized);\n return model?.toolCalling ?? false;\n}\n\n/**\n * Check if a model supports vision (image inputs).\n * Models without this flag cannot process image_url content parts.\n */\nexport function supportsVision(modelId: string): boolean {\n const normalized = modelId.replace(\"ckcloud/\", \"\");\n const model = BASE_MODELS.find((m) => m.id === normalized);\n return model?.vision ?? false;\n}\n","import type { ProviderPlugin } from \"./types\";\nimport { buildProviderModels, BASE_API_URL } from \"./models\";\nimport type { ProxyHandle } from \"./proxy.js\";\n\n/**\n * State for the running proxy (set when the plugin activates).\n */\nlet activeProxy: ProxyHandle | null = null;\n\nexport function setActiveProxy(proxy: ProxyHandle): void {\n activeProxy = proxy;\n}\n\nexport function getActiveProxy(): ProxyHandle | null {\n return activeProxy;\n}\n\n\nexport const ckcloudProvider: ProviderPlugin = {\n id: \"ckcloud\",\n label: \"ckcloud\",\n docsPath: \"\", //TODO\n aliases: [\"ckey\"],\n envVars: [\"CKCLOUD_API_KEY\"],\n\n // Model definitions — dynamically set to proxy URL\n get models() {\n if (!activeProxy) {\n // Fallback: point to ckcloud API directly (won't handle x402, but\n // allows config loading before proxy starts)\n return buildProviderModels(BASE_API_URL);\n }\n return buildProviderModels(activeProxy?.baseUrl);\n },\n\n // No auth required — the x402 proxy handles wallet-based payments internally.\n // The proxy auto-generates a wallet on first run and stores it at\n // ~/.openclaw/ckcloud/wallet.key. Users just fund that wallet with USDC.\n auth: [],\n};\n","import { createServer, type IncomingMessage, type ServerResponse } from \"node:http\";\nimport { finished } from \"node:stream\";\nimport type { AddressInfo } from \"node:net\";\nimport { homedir } from \"node:os\";\nimport { join } from \"node:path\";\nimport { mkdir, writeFile, readFile, stat as fsStat } from \"node:fs/promises\";\nimport { createPublicClient, http } from \"viem\";\nimport { base } from \"viem/chains\";\nimport { toClientEvmSigner } from \"@x402/evm\";\nimport { privateKeyToAccount } from \"viem/accounts\";\nimport { x402Client } from \"@x402/fetch\";\nimport { createPayFetchWithPreAuth } from \"./payment-preauth\";\nimport { registerExactEvmScheme } from \"@x402/evm/exact/client\";\n\nimport { BalanceMonitor } from \"./balance\";\nimport { SolanaBalanceMonitor } from \"./solana-balance\";\nimport { PROXY_PORT } from \"./config.js\";\nimport { getStats, clearStats } from \"./stats.js\";\nimport { logUsage, type UsageEntry } from \"./logger.js\";\nimport type { PluginLogger } from \"./types.js\";\nimport { logger, setPluginLogger } from \"./plugin-logger.js\";\n\nimport {\n SessionStore,\n getSessionId,\n deriveSessionId,\n hashRequestContent,\n type SessionConfig,\n} from \"./session.js\";\n\nimport {\n route,\n getFallbackChain,\n getFallbackChainFiltered,\n filterByToolCalling,\n filterByVision,\n calculateModelCost,\n DEFAULT_ROUTING_CONFIG,\n type RouterOptions,\n type RoutingDecision,\n type RoutingConfig,\n type ModelPricing,\n type Tier,\n} from \"./router/index.js\";\n\nimport { resolvePaymentChain } from \"./auth\"\nimport { RequestDeduplicator } from \"./dedup\";\nimport { ResponseCache, type ResponseCacheConfig } from \"./response-cache\"\nimport { SessionJournal } from \"./journal\"\nimport { USER_AGENT, VERSION } from \"./version\";\nimport { checkForUpdates } from \"./updater\";\nimport { classifyByRules } from \"./router/rules\";\n\nimport {\n BASE_MODELS,\n OPENCLAW_MODELS,\n initBaseModels,\n resolveModelAlias,\n getModelContextWindow,\n isReasoningModel,\n supportsToolCalling,\n supportsVision,\n} from \"./models.js\";\n\ntype AnyBalanceMonitor = BalanceMonitor | SolanaBalanceMonitor;\n\n\nconst CKCLOUD_API = \"https://t.ckcloudai.com/x402\";\nconst CKCLOUD_SOLANA_API = \"https://https://t.ckcloudai.com/x402\";\nconst IMAGE_DIR = join(homedir(), \".openclaw\", \"ckcloud\", \"images\");\nconst AUTO_MODEL = \"ckcloud/auto\";\n\n// Extra buffer for balance check (on top of estimateAmount's 20% buffer)\n// Total effective buffer: 1.2 * 1.5 = 1.8x (80% safety margin)\n// This prevents x402 payment failures after streaming headers are sent,\n// which would trigger OpenClaw's 5-24 hour billing cooldown.\nconst BALANCE_CHECK_BUFFER = 1.5;\n\nconst ROUTING_PROFILES = new Set([\n \"ckcloud/free\",\n \"free\",\n \"ckcloud/eco\",\n \"eco\",\n \"ckcloud/auto\",\n \"auto\",\n \"ckcloud/premium\",\n \"premium\",\n]);\n\nconst FREE_MODEL = \"kimi-k2\"; // Free model for empty wallet fallback\nconst MAX_MESSAGES = 200; // API limit - truncate older messages if exceeded\nconst CONTEXT_LIMIT_KB = 5120; // Server-side limit: 5MB in KB\nconst HEARTBEAT_INTERVAL_MS = 2_000;\nconst DEFAULT_REQUEST_TIMEOUT_MS = 180_000; // 3 minutes (allows for on-chain tx + LLM response)\nconst MAX_FALLBACK_ATTEMPTS = 5; // Maximum models to try in fallback chain (increased from 3 to ensure cheap models are tried)\nconst HEALTH_CHECK_TIMEOUT_MS = 2_000; // Timeout for checking existing proxy\nconst RATE_LIMIT_COOLDOWN_MS = 60_000; // 60 seconds cooldown for rate-limited models\nconst PORT_RETRY_ATTEMPTS = 5; // Max attempts to bind port (handles TIME_WAIT)\nconst PORT_RETRY_DELAY_MS = 1_000; // Delay between retry attempts\nconst MODEL_BODY_READ_TIMEOUT_MS = 300_000; // 5 minutes for model responses (reasoning models are slow)\nconst ERROR_BODY_READ_TIMEOUT_MS = 30_000; // 30 seconds for error/partner body reads\n\nexport function getProxyPort(): number {\n return PROXY_PORT;\n}\n\nexport type WalletConfig = string | { key: string; solanaPrivateKeyBytes?: Uint8Array };\nexport type PaymentChain = \"base\" | \"solana\";\n\n/** Callback info for low balance warning */\nexport type LowBalanceInfo = {\n balanceUSD: string;\n walletAddress: string;\n};\n\n/** Callback info for insufficient funds error */\nexport type InsufficientFundsInfo = {\n balanceUSD: string;\n requiredUSD: string;\n walletAddress: string;\n};\n\nexport type ProxyOptions = {\n wallet: WalletConfig;\n apiBase?: string;\n /** Payment chain: \"base\" (default) or \"solana\". Can also be set via CLAWROUTER_PAYMENT_CHAIN env var. */\n paymentChain?: PaymentChain;\n /** Port to listen on (default: 8402) */\n port?: number;\n routingConfig?: Partial<RoutingConfig>;\n /** Request timeout in ms (default: 180000 = 3 minutes). Covers on-chain tx + LLM response. */\n requestTimeoutMs?: number;\n /** Skip balance checks (for testing only). Default: false */\n skipBalanceCheck?: boolean;\n /**\n * Session persistence config. When enabled, maintains model selection\n * across requests within a session to prevent mid-task model switching.\n */\n sessionConfig?: Partial<SessionConfig>;\n /**\n * Auto-compress large requests to reduce network usage.\n * When enabled, requests are automatically compressed using\n * LLM-safe context compression (15-40% reduction).\n * Default: true\n */\n autoCompressRequests?: boolean;\n /**\n * Threshold in KB to trigger auto-compression (default: 180).\n * Requests larger than this are compressed before sending.\n * Set to 0 to compress all requests.\n */\n compressionThresholdKB?: number;\n /**\n * Response caching config. When enabled, identical requests return\n * cached responses instead of making new API calls.\n * Default: enabled with 10 minute TTL, 200 max entries.\n */\n cacheConfig?: ResponseCacheConfig;\n onReady?: (port: number) => void;\n onError?: (error: Error) => void;\n onPayment?: (info: { model: string; amount: string; network: string }) => void;\n onRouted?: (decision: RoutingDecision) => void;\n /** Called when balance drops below $1.00 (warning, request still proceeds) */\n onLowBalance?: (info: LowBalanceInfo) => void;\n /** Called when balance is insufficient for a request (request fails) */\n onInsufficientFunds?: (info: InsufficientFundsInfo) => void;\n /** Logger for plugin output (defaults to console if not provided) */\n logger?: PluginLogger;\n};\n\nexport type ProxyHandle = {\n port: number;\n baseUrl: string;\n walletAddress: string;\n solanaAddress?: string;\n balanceMonitor: AnyBalanceMonitor;\n close: () => Promise<void>;\n};\n\nasync function readBodyWithTimeout(\n body: ReadableStream<Uint8Array> | null,\n timeoutMs: number = MODEL_BODY_READ_TIMEOUT_MS,\n): Promise<Uint8Array[]> {\n if (!body) return [];\n\n const reader = body.getReader();\n const chunks: Uint8Array[] = [];\n\n let timer: ReturnType<typeof setTimeout> | undefined;\n try {\n while (true) {\n const result = await Promise.race([\n reader.read(),\n new Promise<never>((_, reject) => {\n timer = setTimeout(() => reject(new Error(\"Body read timeout\")), timeoutMs);\n }),\n ]);\n clearTimeout(timer);\n if (result.done) break;\n chunks.push(result.value);\n }\n } finally {\n clearTimeout(timer);\n reader.releaseLock();\n }\n\n return chunks;\n}\n\n/**\n * Check if response socket is writable (prevents write-after-close errors).\n * Returns true only if all conditions are safe for writing.\n */\nfunction canWrite(res: ServerResponse): boolean {\n return (\n !res.writableEnded &&\n !res.destroyed &&\n res.socket !== null &&\n !res.socket.destroyed &&\n res.socket.writable\n );\n}\n\n/**\n * Safe write with backpressure handling.\n * Returns true if write succeeded, false if socket is closed or write failed.\n */\nfunction safeWrite(res: ServerResponse, data: string | Buffer): boolean {\n if (!canWrite(res)) {\n const bytes = typeof data === \"string\" ? Buffer.byteLength(data) : data.length;\n logger.warn(`[ckcloud] safeWrite: socket not writable, dropping ${bytes} bytes`);\n return false;\n }\n return res.write(data);\n}\n\n\nconst rateLimitedModels = new Map<string, number>();\n\n/**\n * Check if a model is currently rate-limited (in cooldown period).\n */\nfunction isRateLimited(modelId: string): boolean {\n const hitTime = rateLimitedModels.get(modelId);\n if (!hitTime) return false;\n\n const elapsed = Date.now() - hitTime;\n if (elapsed >= RATE_LIMIT_COOLDOWN_MS) {\n rateLimitedModels.delete(modelId);\n return false;\n }\n return true;\n}\n\nfunction markRateLimited(modelId: string): void {\n rateLimitedModels.set(modelId, Date.now());\n logger.info(`[ckcloud] Model ${modelId} rate-limited, will deprioritize for 60s`);\n}\n\n\n/** Result of attempting a model request */\ntype ModelRequestResult = {\n success: boolean;\n response?: Response;\n errorBody?: string;\n errorStatus?: number;\n isProviderError?: boolean;\n};\n\nconst VALID_ROLES = new Set([\"system\", \"user\", \"assistant\", \"tool\", \"function\"]);\ntype ChatMessage = { role: string; content: string | unknown };\nconst ROLE_MAPPINGS: Record<string, string> = {\n developer: \"system\", // OpenAI's newer API uses \"developer\" for system messages\n model: \"assistant\", // Some APIs use \"model\" instead of \"assistant\"\n};\n\n/**\n * Normalize message roles to standard OpenAI format.\n * Converts non-standard roles (e.g., \"developer\") to valid ones.\n */\nfunction normalizeMessageRoles(messages: ChatMessage[]): ChatMessage[] {\n if (!messages || messages.length === 0) return messages;\n\n let hasChanges = false;\n const normalized = messages.map((msg) => {\n if (VALID_ROLES.has(msg.role)) return msg;\n\n const mappedRole = ROLE_MAPPINGS[msg.role];\n if (mappedRole) {\n hasChanges = true;\n return { ...msg, role: mappedRole };\n }\n\n // Unknown role - default to \"user\" to avoid API errors\n hasChanges = true;\n return { ...msg, role: \"user\" };\n });\n\n return hasChanges ? normalized : messages;\n}\n\n\ntype TruncationResult<T> = {\n messages: T[];\n wasTruncated: boolean;\n originalCount: number;\n truncatedCount: number;\n};\n/**\n * Truncate messages to stay under MAX_MESSAGES limit.\n * Keeps all system messages and the most recent conversation history.\n * Returns the messages and whether truncation occurred.\n */\nfunction truncateMessages<T extends { role: string }>(messages: T[]): TruncationResult<T> {\n if (!messages || messages.length <= MAX_MESSAGES) {\n return {\n messages,\n wasTruncated: false,\n originalCount: messages?.length ?? 0,\n truncatedCount: messages?.length ?? 0,\n };\n }\n\n // Separate system messages from conversation\n const systemMsgs = messages.filter((m) => m.role === \"system\");\n const conversationMsgs = messages.filter((m) => m.role !== \"system\");\n\n // Keep all system messages + most recent conversation messages\n const maxConversation = MAX_MESSAGES - systemMsgs.length;\n const truncatedConversation = conversationMsgs.slice(-maxConversation);\n\n const result = [...systemMsgs, ...truncatedConversation];\n\n logger.info(\n `[ckcloud] Truncated messages: ${messages.length} → ${result.length} (kept ${systemMsgs.length} system + ${truncatedConversation.length} recent)`,\n );\n\n return {\n messages: result,\n wasTruncated: true,\n originalCount: messages.length,\n truncatedCount: result.length,\n };\n}\n\ntype MessageWithTools = ChatMessage & {\n tool_calls?: Array<{ id?: string; type?: string; function?: unknown }>;\n tool_call_id?: string;\n};\n\ntype ContentBlock = {\n type?: string;\n id?: string;\n tool_use_id?: string;\n [key: string]: unknown;\n};\n\n\nconst VALID_TOOL_ID_PATTERN = /^[a-zA-Z0-9_-]+$/;\n\nfunction sanitizeToolId(id: string | undefined): string | undefined {\n if (!id || typeof id !== \"string\") return id;\n if (VALID_TOOL_ID_PATTERN.test(id)) return id;\n\n // Replace invalid characters with underscores\n return id.replace(/[^a-zA-Z0-9_-]/g, \"_\");\n}\n\nfunction sanitizeToolIds(messages: ChatMessage[]): ChatMessage[] {\n if (!messages || messages.length === 0) return messages;\n\n let hasChanges = false;\n const sanitized = messages.map((msg) => {\n const typedMsg = msg as MessageWithTools;\n let msgChanged = false;\n let newMsg = { ...msg } as MessageWithTools;\n\n // Sanitize tool_calls[].id in assistant messages\n if (typedMsg.tool_calls && Array.isArray(typedMsg.tool_calls)) {\n const newToolCalls = typedMsg.tool_calls.map((tc) => {\n if (tc.id && typeof tc.id === \"string\") {\n const sanitized = sanitizeToolId(tc.id);\n if (sanitized !== tc.id) {\n msgChanged = true;\n return { ...tc, id: sanitized };\n }\n }\n return tc;\n });\n if (msgChanged) {\n newMsg = { ...newMsg, tool_calls: newToolCalls };\n }\n }\n\n // Sanitize tool_call_id in tool messages\n if (typedMsg.tool_call_id && typeof typedMsg.tool_call_id === \"string\") {\n const sanitized = sanitizeToolId(typedMsg.tool_call_id);\n if (sanitized !== typedMsg.tool_call_id) {\n msgChanged = true;\n newMsg = { ...newMsg, tool_call_id: sanitized };\n }\n }\n\n // Sanitize content blocks if content is an array (Anthropic-style content)\n if (Array.isArray(typedMsg.content)) {\n const newContent = (typedMsg.content as ContentBlock[]).map((block) => {\n if (!block || typeof block !== \"object\") return block;\n\n let blockChanged = false;\n let newBlock = { ...block };\n\n // tool_use blocks have \"id\"\n if (block.type === \"tool_use\" && block.id && typeof block.id === \"string\") {\n const sanitized = sanitizeToolId(block.id);\n if (sanitized !== block.id) {\n blockChanged = true;\n newBlock = { ...newBlock, id: sanitized };\n }\n }\n\n // tool_result blocks have \"tool_use_id\"\n if (\n block.type === \"tool_result\" &&\n block.tool_use_id &&\n typeof block.tool_use_id === \"string\"\n ) {\n const sanitized = sanitizeToolId(block.tool_use_id);\n if (sanitized !== block.tool_use_id) {\n blockChanged = true;\n newBlock = { ...newBlock, tool_use_id: sanitized };\n }\n }\n\n if (blockChanged) {\n msgChanged = true;\n return newBlock;\n }\n return block;\n });\n\n if (msgChanged) {\n newMsg = { ...newMsg, content: newContent };\n }\n }\n\n if (msgChanged) {\n hasChanges = true;\n return newMsg;\n }\n return msg;\n });\n\n return hasChanges ? sanitized : messages;\n}\n\nfunction isGoogleModel(modelId: string): boolean {\n return modelId.startsWith(\"google/\") || modelId.startsWith(\"gemini\");\n}\n\nfunction normalizeMessagesForGoogle(messages: ChatMessage[]): ChatMessage[] {\n if (!messages || messages.length === 0) return messages;\n\n // Find first non-system message\n let firstNonSystemIdx = -1;\n for (let i = 0; i < messages.length; i++) {\n if (messages[i].role !== \"system\") {\n firstNonSystemIdx = i;\n break;\n }\n }\n\n // If no non-system messages, return as-is\n if (firstNonSystemIdx === -1) return messages;\n\n const firstRole = messages[firstNonSystemIdx].role;\n\n // If first non-system message is already \"user\", no change needed\n if (firstRole === \"user\") return messages;\n\n // If first non-system message is \"assistant\" or \"model\", prepend a user message\n if (firstRole === \"assistant\" || firstRole === \"model\") {\n const normalized = [...messages];\n normalized.splice(firstNonSystemIdx, 0, {\n role: \"user\",\n content: \"(continuing conversation)\",\n });\n return normalized;\n }\n\n return messages;\n}\n\ntype ExtendedChatMessage = ChatMessage & {\n tool_calls?: unknown[];\n reasoning_content?: unknown;\n};\n\n\n/**\n * Normalize messages for thinking-enabled requests.\n * When thinking/extended_thinking is enabled, assistant messages with tool_calls\n * must have reasoning_content (can be empty string if not present).\n * Error: \"400 thinking is enabled but reasoning_content is missing in assistant tool call message\"\n */\nfunction normalizeMessagesForThinking(messages: ExtendedChatMessage[]): ExtendedChatMessage[] {\n if (!messages || messages.length === 0) return messages;\n\n let hasChanges = false;\n const normalized = messages.map((msg) => {\n // Skip if not assistant or already has reasoning_content\n if (msg.role !== \"assistant\" || msg.reasoning_content !== undefined) {\n return msg;\n }\n\n // Check for OpenAI format: tool_calls array\n const hasOpenAIToolCalls =\n msg.tool_calls && Array.isArray(msg.tool_calls) && msg.tool_calls.length > 0;\n\n // Check for Anthropic format: content array with tool_use blocks\n const hasAnthropicToolUse =\n Array.isArray(msg.content) &&\n (msg.content as Array<{ type?: string }>).some((block) => block?.type === \"tool_use\");\n\n if (hasOpenAIToolCalls || hasAnthropicToolUse) {\n hasChanges = true;\n return { ...msg, reasoning_content: \"\" };\n }\n return msg;\n });\n\n return hasChanges ? normalized : messages;\n}\n\nconst PROVIDER_ERROR_PATTERNS = [\n /billing/i,\n /insufficient.*balance/i,\n /credits/i,\n /quota.*exceeded/i,\n /rate.*limit/i,\n /model.*unavailable/i,\n /model.*not.*available/i,\n /service.*unavailable/i,\n /capacity/i,\n /overloaded/i,\n /temporarily.*unavailable/i,\n /api.*key.*invalid/i,\n /authentication.*failed/i,\n /request too large/i,\n /request.*size.*exceeds/i,\n /payload too large/i,\n /payment.*verification.*failed/i,\n /model.*not.*allowed/i,\n /unknown.*model/i,\n];\n\nconst FALLBACK_STATUS_CODES = [\n 400, // Bad request - sometimes used for billing errors\n 401, // Unauthorized - provider API key issues\n 402, // Payment required - but from upstream, not x402\n 403, // Forbidden - provider restrictions\n 413, // Payload too large - request exceeds model's context limit\n 429, // Rate limited\n 500, // Internal server error\n 502, // Bad gateway\n 503, // Service unavailable\n 504, // Gateway timeout\n];\nfunction isProviderError(status: number, body: string): boolean {\n // Check status code first\n if (!FALLBACK_STATUS_CODES.includes(status)) {\n return false;\n }\n\n // For 5xx errors, always fallback\n if (status >= 500) {\n return true;\n }\n\n // For 4xx errors, check the body for known provider error patterns\n return PROVIDER_ERROR_PATTERNS.some((pattern) => pattern.test(body));\n}\n\nconst DEGRADED_RESPONSE_PATTERNS = [\n /the ai service is temporarily overloaded/i,\n /service is temporarily overloaded/i,\n /please try again in a moment/i,\n];\nconst DEGRADED_LOOP_PATTERNS = [\n /the boxed is the response\\./i,\n /the response is the text\\./i,\n /the final answer is the boxed\\./i,\n];\nfunction hasKnownLoopSignature(text: string): boolean {\n const matchCount = DEGRADED_LOOP_PATTERNS.reduce(\n (count, pattern) => (pattern.test(text) ? count + 1 : count),\n 0,\n );\n if (matchCount >= 2) return true;\n\n // Generic repetitive loop fallback for short repeated lines.\n const lines = text\n .split(/\\r?\\n/)\n .map((line) => line.trim())\n .filter(Boolean);\n if (lines.length < 8) return false;\n\n const counts = new Map<string, number>();\n for (const line of lines) {\n counts.set(line, (counts.get(line) ?? 0) + 1);\n }\n\n const maxRepeat = Math.max(...counts.values());\n const uniqueRatio = counts.size / lines.length;\n return maxRepeat >= 3 && uniqueRatio <= 0.45;\n}\nfunction extractAssistantContent(payload: unknown): string | undefined {\n if (!payload || typeof payload !== \"object\") return undefined;\n const record = payload as Record<string, unknown>;\n const choices = record.choices;\n if (!Array.isArray(choices) || choices.length === 0) return undefined;\n\n const firstChoice = choices[0];\n if (!firstChoice || typeof firstChoice !== \"object\") return undefined;\n const choice = firstChoice as Record<string, unknown>;\n const message = choice.message;\n if (!message || typeof message !== \"object\") return undefined;\n const content = (message as Record<string, unknown>).content;\n return typeof content === \"string\" ? content : undefined;\n}\n\n/**\n * Detect degraded 200-response payloads that should trigger model fallback.\n * Returns a short reason when fallback should happen, otherwise undefined.\n */\nexport function detectDegradedSuccessResponse(body: string): string | undefined {\n const trimmed = body.trim();\n if (!trimmed) return undefined;\n\n // Plain-text placeholder response.\n if (DEGRADED_RESPONSE_PATTERNS.some((pattern) => pattern.test(trimmed))) {\n return \"degraded response: overloaded placeholder\";\n }\n\n // Plain-text looping garbage response.\n if (hasKnownLoopSignature(trimmed)) {\n return \"degraded response: repetitive loop output\";\n }\n\n try {\n const parsed = JSON.parse(trimmed) as Record<string, unknown>;\n\n // Some providers return JSON error payloads with HTTP 200.\n const errorField = parsed.error;\n let errorText = \"\";\n if (typeof errorField === \"string\") {\n errorText = errorField;\n } else if (errorField && typeof errorField === \"object\") {\n const errObj = errorField as Record<string, unknown>;\n errorText = [\n typeof errObj.message === \"string\" ? errObj.message : \"\",\n typeof errObj.type === \"string\" ? errObj.type : \"\",\n typeof errObj.code === \"string\" ? errObj.code : \"\",\n ]\n .filter(Boolean)\n .join(\" \");\n }\n if (errorText && PROVIDER_ERROR_PATTERNS.some((pattern) => pattern.test(errorText))) {\n return `degraded response: ${errorText.slice(0, 120)}`;\n }\n\n // Successful wrapper with bad assistant content.\n const assistantContent = extractAssistantContent(parsed);\n if (!assistantContent) return undefined;\n if (DEGRADED_RESPONSE_PATTERNS.some((pattern) => pattern.test(assistantContent))) {\n return \"degraded response: overloaded assistant content\";\n }\n if (hasKnownLoopSignature(assistantContent)) {\n return \"degraded response: repetitive assistant loop\";\n }\n } catch {\n // Not JSON - handled by plaintext checks above.\n }\n\n return undefined;\n}\n\n\n/**\n * Attempt a request with a specific model.\n * Returns the response or error details for fallback decision.\n */\nasync function tryModelRequest(\n upstreamUrl: string,\n method: string,\n headers: Record<string, string>,\n body: Buffer,\n modelId: string,\n maxTokens: number,\n payFetch: (input: RequestInfo | URL, init?: RequestInit) => Promise<Response>,\n balanceMonitor: AnyBalanceMonitor,\n signal: AbortSignal,\n): Promise<ModelRequestResult> {\n const bodyPreviewMax = 512;\n const bodyPreviewLength = Math.min(body.length, bodyPreviewMax);\n const bodyPreview = bodyPreviewLength\n ? body.toString(\"utf8\", 0, bodyPreviewLength)\n : undefined;\n\n logger.info(\n `[ckcloud] tryModelRequest: model=${modelId}, method=${method}, upstream=${upstreamUrl}, maxTokens=${maxTokens} ${JSON.stringify({\n headers,\n bodyBytes: body.length,\n bodyPreview,\n })}`,\n );\n // Update model in body and normalize messages\n let requestBody = body;\n try {\n const parsed = JSON.parse(body.toString()) as Record<string, unknown>;\n parsed.model = modelId;\n\n // Normalize message roles (e.g., \"developer\" -> \"system\")\n if (Array.isArray(parsed.messages)) {\n parsed.messages = normalizeMessageRoles(parsed.messages as ChatMessage[]);\n }\n\n // Truncate messages to stay under ckcloud's limit (200 messages)\n if (Array.isArray(parsed.messages)) {\n const truncationResult = truncateMessages(parsed.messages as ChatMessage[]);\n parsed.messages = truncationResult.messages;\n }\n\n // Sanitize tool IDs to match Anthropic's pattern (alphanumeric, underscore, hyphen only)\n if (Array.isArray(parsed.messages)) {\n parsed.messages = sanitizeToolIds(parsed.messages as ChatMessage[]);\n }\n\n // Normalize messages for Google models (first non-system message must be \"user\")\n if (isGoogleModel(modelId) && Array.isArray(parsed.messages)) {\n parsed.messages = normalizeMessagesForGoogle(parsed.messages as ChatMessage[]);\n }\n\n // Normalize messages for thinking-enabled requests (add reasoning_content to tool calls)\n // Check request flags AND target model - reasoning models have thinking enabled server-side\n const hasThinkingEnabled = !!(\n parsed.thinking ||\n parsed.extended_thinking ||\n isReasoningModel(modelId)\n );\n if (hasThinkingEnabled && Array.isArray(parsed.messages)) {\n parsed.messages = normalizeMessagesForThinking(parsed.messages as ExtendedChatMessage[]);\n }\n\n requestBody = Buffer.from(JSON.stringify(parsed));\n } catch {\n // If body isn't valid JSON, use as-is\n }\n\n try {\n logger.info(`payFetch: url:${upstreamUrl}, header:${headers}, body:${requestBody}`)\n\n const response = await payFetch(upstreamUrl, {\n method,\n headers,\n body: requestBody.length > 0 ? new Uint8Array(requestBody) : undefined,\n signal,\n });\n\n // Check for provider errors\n if (response.status !== 200) {\n // Clone response to read body without consuming it\n const errorBodyChunks = await readBodyWithTimeout(response.body, ERROR_BODY_READ_TIMEOUT_MS);\n const errorBody = Buffer.concat(errorBodyChunks).toString();\n const isProviderErr = isProviderError(response.status, errorBody);\n\n logger.warn(`payFetch err, url:${upstreamUrl}, header:${headers}, body:${requestBody}, response:${JSON.stringify(response)}`)\n\n return {\n success: false,\n errorBody,\n errorStatus: response.status,\n isProviderError: isProviderErr,\n };\n }\n\n // Detect provider degradation hidden inside HTTP 200 responses.\n const contentType = response.headers.get(\"content-type\") || \"\";\n if (contentType.includes(\"json\") || contentType.includes(\"text\")) {\n try {\n const clonedChunks = await readBodyWithTimeout(\n response.clone().body,\n ERROR_BODY_READ_TIMEOUT_MS,\n );\n const responseBody = Buffer.concat(clonedChunks).toString();\n const degradedReason = detectDegradedSuccessResponse(responseBody);\n if (degradedReason) {\n return {\n success: false,\n errorBody: degradedReason,\n errorStatus: 503,\n isProviderError: true,\n };\n }\n } catch {\n // Ignore body inspection failures and pass through response.\n }\n }\n\n return { success: true, response };\n } catch (err) {\n const errorMsg = err instanceof Error ? err.message : String(err);\n logger.warn(`payFetch catch err, url:${upstreamUrl}, header:${headers}, body:${requestBody}, err:${errorMsg}`)\n return {\n success: false,\n errorBody: errorMsg,\n errorStatus: 500,\n isProviderError: true, // Network errors are retryable\n };\n }\n}\n\n/**\n * Reorder models to put rate-limited ones at the end.\n */\nfunction prioritizeNonRateLimited(models: string[]): string[] {\n const available: string[] = [];\n const rateLimited: string[] = [];\n\n for (const model of models) {\n if (isRateLimited(model)) {\n rateLimited.push(model);\n } else {\n available.push(model);\n }\n }\n\n return [...available, ...rateLimited];\n}\n\n\nasync function checkExistingProxy(\n port: number,\n): Promise<{ wallet: string; paymentChain?: string } | undefined> {\n const controller = new AbortController();\n const timeoutId = setTimeout(() => controller.abort(), HEALTH_CHECK_TIMEOUT_MS);\n\n try {\n const response = await fetch(`http://127.0.0.1:${port}/health`, {\n signal: controller.signal,\n });\n clearTimeout(timeoutId);\n\n if (response.ok) {\n const data = (await response.json()) as {\n status?: string;\n wallet?: string;\n paymentChain?: string;\n };\n if (data.status === \"ok\" && data.wallet) {\n return { wallet: data.wallet, paymentChain: data.paymentChain };\n }\n }\n return undefined;\n } catch {\n clearTimeout(timeoutId);\n return undefined;\n }\n}\n\nfunction buildModelPricing(): Map<string, ModelPricing> {\n const map = new Map<string, ModelPricing>();\n for (const m of BASE_MODELS) {\n if (m.id === AUTO_MODEL) continue; // skip meta-model\n map.set(m.id, { inputPrice: m.inputPrice, outputPrice: m.outputPrice });\n }\n return map;\n}\n\n\ntype ModelListEntry = {\n id: string;\n object: \"model\";\n created: number;\n owned_by: string;\n};\n\n\n/**\n * Build `/v1/models` response entries from the full OpenClaw model registry.\n * This includes alias IDs (e.g., `flash`, `kimi`) so `/model <alias>` works reliably.\n */\nexport function buildProxyModelList(\n createdAt: number = Math.floor(Date.now() / 1000),\n): ModelListEntry[] {\n const seen = new Set<string>();\n return OPENCLAW_MODELS.filter((model) => {\n if (seen.has(model.id)) return false;\n seen.add(model.id);\n return true;\n }).map((model) => ({\n id: model.id,\n object: \"model\",\n created: createdAt,\n owned_by: model.id.includes(\"/\") ? (model.id.split(\"/\")[0] ?? \"ckcloud\") : \"ckcloud\",\n }));\n}\n\n/**\n * Merge partial routing config overrides with defaults.\n */\nfunction mergeRoutingConfig(overrides?: Partial<RoutingConfig>): RoutingConfig {\n if (!overrides) return DEFAULT_ROUTING_CONFIG;\n return {\n ...DEFAULT_ROUTING_CONFIG,\n ...overrides,\n classifier: { ...DEFAULT_ROUTING_CONFIG.classifier, ...overrides.classifier },\n scoring: { ...DEFAULT_ROUTING_CONFIG.scoring, ...overrides.scoring },\n tiers: { ...DEFAULT_ROUTING_CONFIG.tiers, ...overrides.tiers },\n overrides: { ...DEFAULT_ROUTING_CONFIG.overrides, ...overrides.overrides },\n };\n}\n\n\n\n/**\n * Upload a base64 data URI to catbox.moe and return a public URL.\n * Google image models (nano-banana) return data URIs instead of hosted URLs,\n * which breaks Telegram and other clients that can't render raw base64.\n */\nasync function uploadDataUriToHost(dataUri: string): Promise<string> {\n const match = dataUri.match(/^data:(image\\/\\w+);base64,(.+)$/);\n if (!match) throw new Error(\"Invalid data URI format\");\n const [, mimeType, b64Data] = match;\n const ext = mimeType === \"image/jpeg\" ? \"jpg\" : (mimeType.split(\"/\")[1] ?? \"png\");\n\n const buffer = Buffer.from(b64Data, \"base64\");\n const blob = new Blob([buffer], { type: mimeType });\n\n const form = new FormData();\n form.append(\"reqtype\", \"fileupload\");\n form.append(\"fileToUpload\", blob, `image.${ext}`);\n\n const uploadController = new AbortController();\n const uploadTimeout = setTimeout(() => uploadController.abort(), 30_000);\n try {\n const resp = await fetch(\"https://catbox.moe/user/api.php\", {\n method: \"POST\",\n body: form,\n signal: uploadController.signal,\n });\n\n if (!resp.ok) throw new Error(`catbox.moe upload failed: HTTP ${resp.status}`);\n const result = await resp.text();\n if (result.startsWith(\"https://\")) {\n return result.trim();\n }\n throw new Error(`catbox.moe upload failed: ${result}`);\n } finally {\n clearTimeout(uploadTimeout);\n }\n}\n\n/**\n * Estimate USDC cost for a request based on model pricing.\n * Returns amount string in USDC smallest unit (6 decimals) or undefined if unknown.\n */\nfunction estimateAmount(\n modelId: string,\n bodyLength: number,\n maxTokens: number,\n): string | undefined {\n const model = BASE_MODELS.find((m) => m.id === modelId);\n if (!model) return undefined;\n\n // Rough estimate: ~4 chars per token for input\n const estimatedInputTokens = Math.ceil(bodyLength / 4);\n const estimatedOutputTokens = maxTokens || model.maxOutput || 4096;\n\n const costUsd =\n (estimatedInputTokens / 1_000_000) * model.inputPrice +\n (estimatedOutputTokens / 1_000_000) * model.outputPrice;\n\n // Convert to USDC 6-decimal integer, add 20% buffer for estimation error\n // Minimum 1000 ($0.001) to match CDP Facilitator's enforced minimum payment\n const amountMicros = Math.max(1000, Math.ceil(costUsd * 1.2 * 1_000_000));\n return amountMicros.toString();\n}\n\n\nfunction transformPaymentError(errorBody: string): string {\n try {\n // Try to parse the error JSON\n const parsed = JSON.parse(errorBody) as {\n error?: string;\n details?: string;\n };\n\n // Check if this is a payment verification error\n if (parsed.error === \"Payment verification failed\" && parsed.details) {\n // Extract the nested JSON from details\n // Format: \"Verification failed: {json}\\n\"\n const match = parsed.details.match(/Verification failed:\\s*(\\{.*\\})/s);\n if (match) {\n const innerJson = JSON.parse(match[1]) as {\n invalidMessage?: string;\n invalidReason?: string;\n payer?: string;\n };\n\n if (innerJson.invalidReason === \"insufficient_funds\" && innerJson.invalidMessage) {\n // Parse \"insufficient balance: 251 < 11463\"\n const balanceMatch = innerJson.invalidMessage.match(\n /insufficient balance:\\s*(\\d+)\\s*<\\s*(\\d+)/i,\n );\n if (balanceMatch) {\n const currentMicros = parseInt(balanceMatch[1], 10);\n const requiredMicros = parseInt(balanceMatch[2], 10);\n const currentUSD = (currentMicros / 1_000_000).toFixed(6);\n const requiredUSD = (requiredMicros / 1_000_000).toFixed(6);\n const wallet = innerJson.payer || \"unknown\";\n const shortWallet =\n wallet.length > 12 ? `${wallet.slice(0, 6)}...${wallet.slice(-4)}` : wallet;\n\n return JSON.stringify({\n error: {\n message: `Insufficient USDC balance. Current: $${currentUSD}, Required: ~$${requiredUSD}`,\n type: \"insufficient_funds\",\n wallet: wallet,\n current_balance_usd: currentUSD,\n required_usd: requiredUSD,\n help: `Fund wallet ${shortWallet} with USDC on Base, or use free model: /model free`,\n },\n });\n }\n }\n\n // Handle invalid_payload errors (signature issues, malformed payment)\n if (innerJson.invalidReason === \"invalid_payload\") {\n return JSON.stringify({\n error: {\n message: \"Payment signature invalid. This may be a temporary issue.\",\n type: \"invalid_payload\",\n help: \"Try again. If this persists, reinstall\",\n },\n });\n }\n\n // Handle transaction simulation failures (Solana on-chain validation)\n if (innerJson.invalidReason === \"transaction_simulation_failed\") {\n console.error(\n `[ClawRouter] Solana transaction simulation failed: ${innerJson.invalidMessage || \"unknown\"}`,\n );\n return JSON.stringify({\n error: {\n message: \"Solana payment simulation failed. Retrying with a different model.\",\n type: \"transaction_simulation_failed\",\n help: \"This is usually temporary. If it persists, check your Solana USDC balance or try: /model free\",\n },\n });\n }\n }\n }\n\n // Handle settlement failures (gas estimation, on-chain errors)\n if (\n parsed.error === \"Settlement failed\" ||\n parsed.error === \"Payment settlement failed\" ||\n parsed.details?.includes(\"Settlement failed\") ||\n parsed.details?.includes(\"transaction_simulation_failed\")\n ) {\n const details = parsed.details || \"\";\n const gasError = details.includes(\"unable to estimate gas\");\n\n return JSON.stringify({\n error: {\n message: gasError\n ? \"Payment failed: network congestion or gas issue. Try again.\"\n : \"Payment settlement failed. Try again in a moment.\",\n type: \"settlement_failed\",\n help: \"This is usually temporary. If it persists, try: /model free\",\n },\n });\n }\n } catch {\n // If parsing fails, return original\n }\n return errorBody;\n}\n\n\n/**\n * Start the local x402 proxy server.\n *\n * If a proxy is already running on the target port, reuses it instead of failing.\n * Port can be configured via CKCLOUD_PROXY_PORT environment variable.\n *\n * Returns a handle with the assigned port, base URL, and a close function.\n */\nexport async function startProxy(options: ProxyOptions): Promise<ProxyHandle> {\n const walletKey = typeof options.wallet === \"string\" ? options.wallet : options.wallet.key;\n const solanaPrivateKeyBytes = typeof options.wallet === \"string\" ? undefined : options.wallet.solanaPrivateKeyBytes;\n setPluginLogger(options.logger ?? console);\n\n await initBaseModels();\n\n const paymentChain = options.paymentChain ?? (await resolvePaymentChain());\n\n const apiBase = options.apiBase ?? (paymentChain === \"solana\" && solanaPrivateKeyBytes ? CKCLOUD_SOLANA_API : CKCLOUD_API);\n if (paymentChain === \"solana\" && !solanaPrivateKeyBytes) {\n logger.warn(`[ckcloud] ⚠ Payment chain is Solana but no mnemonic found — falling back to Base (EVM).`);\n logger.warn(`[ckcloud] To fix: run \"npx @ckcloudai.com/clawrouter wallet recover\" if your mnemonic exists.`);\n logger.warn(`[ckcloud] or run \"npx @ckcloudai.com/clawrouter chain base\" to switch to EVM.`);\n } else if (paymentChain === \"solana\") {\n logger.info(`[ckcloud] Payment chain: Solana (${CKCLOUD_SOLANA_API})`);\n }\n\n const listenPort = options.port ?? getProxyPort();\n const existingProxy = await checkExistingProxy(listenPort);\n\n if (existingProxy) {\n // Proxy already running — reuse it instead of failing with EADDRINUSE\n const account = privateKeyToAccount(walletKey as `0x${string}`);\n const baseUrl = `http://127.0.0.1:${listenPort}`;\n\n // Verify the existing proxy is using the same wallet (or warn if different)\n if (existingProxy.wallet !== account.address) {\n logger.warn(\n `[ckcloud] Existing proxy on port ${listenPort} uses wallet ${existingProxy.wallet}, but current config uses ${account.address}. Reusing existing proxy.`,\n );\n }\n\n // Verify the existing proxy is using the same payment chain\n if (existingProxy.paymentChain) {\n if (existingProxy.paymentChain !== paymentChain) {\n throw new Error(\n `Existing proxy on port ${listenPort} is using ${existingProxy.paymentChain} but ${paymentChain} was requested. ` +\n `Stop the existing proxy first or use a different port.`,\n );\n }\n } else if (paymentChain !== \"base\") {\n // Old proxy doesn't report chain — assume Base. Reject if Solana was requested.\n logger.warn(\n `[ckcloud] Existing proxy on port ${listenPort} does not report paymentChain (pre-v0.11 instance). Assuming Base.`,\n );\n throw new Error(\n `Existing proxy on port ${listenPort} is a pre-v0.11 instance (assumed Base) but ${paymentChain} was requested. ` +\n `Stop the existing proxy first or use a different port.`,\n );\n }\n\n // Derive Solana address if keys are available (for wallet status display)\n let reuseSolanaAddress: string | undefined;\n if (solanaPrivateKeyBytes) {\n const { createKeyPairSignerFromPrivateKeyBytes } = await import(\"@solana/kit\");\n const solanaSigner = await createKeyPairSignerFromPrivateKeyBytes(solanaPrivateKeyBytes);\n reuseSolanaAddress = solanaSigner.address;\n }\n\n // Use chain-appropriate balance monitor\n const balanceMonitor: AnyBalanceMonitor = paymentChain === \"solana\" && reuseSolanaAddress\n ? new SolanaBalanceMonitor(reuseSolanaAddress)\n : new BalanceMonitor(account.address);\n\n options.onReady?.(listenPort);\n\n return {\n port: listenPort,\n baseUrl,\n walletAddress: existingProxy.wallet,\n solanaAddress: reuseSolanaAddress,\n balanceMonitor,\n close: async () => {\n // No-op: we didn't start this proxy, so we shouldn't close it\n },\n };\n }\n\n //no existingProxy\n\n // Create x402 payment client with EVM scheme (always available)\n const account = privateKeyToAccount(walletKey as `0x${string}`);\n const evmPublicClient = createPublicClient({ chain: base, transport: http() });\n const evmSigner = toClientEvmSigner(account, evmPublicClient);\n const x402 = new x402Client();\n registerExactEvmScheme(x402, { signer: evmSigner });\n\n // Register Solana scheme if key is available\n // Uses registerExactSvmScheme helper which registers:\n // - solana:* wildcard (catches any CAIP-2 Solana network)\n // - V1 compat names: \"solana\", \"solana-devnet\", \"solana-testnet\"\n let solanaAddress: string | undefined;\n if (solanaPrivateKeyBytes) {\n const { registerExactSvmScheme } = await import(\"@x402/svm/exact/client\");\n const { createKeyPairSignerFromPrivateKeyBytes } = await import(\"@solana/kit\");\n const solanaSigner = await createKeyPairSignerFromPrivateKeyBytes(solanaPrivateKeyBytes);\n solanaAddress = solanaSigner.address;\n registerExactSvmScheme(x402, { signer: solanaSigner });\n logger.info(`[ckcloud] Solana x402 scheme registered: ${solanaAddress}`);\n }\n\n // Log which chain is used for each payment\n x402.onAfterPaymentCreation(async (context) => {\n const network = context.selectedRequirements.network;\n const chain = network.startsWith(\"eip155\")\n ? \"Base (EVM)\"\n : network.startsWith(\"solana\")\n ? \"Solana\"\n : network;\n logger.info(`[ckcloud] Payment signed on ${chain} (${network})`);\n });\n\n const payFetch = createPayFetchWithPreAuth(fetch, x402, undefined, {\n skipPreAuth: paymentChain === \"solana\",\n });\n\n // Create balance monitor for pre-request checks (chain-appropriate)\n const balanceMonitor: AnyBalanceMonitor =\n paymentChain === \"solana\" && solanaAddress\n ? new SolanaBalanceMonitor(solanaAddress)\n : new BalanceMonitor(account.address);\n\n // Build router options (100% local — no external API calls for routing)\n const routingConfig = mergeRoutingConfig(options.routingConfig);\n const modelPricing = buildModelPricing();\n const routerOpts: RouterOptions = {\n config: routingConfig,\n modelPricing,\n };\n\n // Request deduplicator (shared across all requests)\n const deduplicator = new RequestDeduplicator();\n\n // Response cache for identical requests (longer TTL than dedup)\n const responseCache = new ResponseCache(options.cacheConfig);\n\n // Session store for model persistence (prevents mid-task model switching)\n const sessionStore = new SessionStore(options.sessionConfig);\n\n // Session journal for memory (enables agents to recall earlier work)\n const sessionJournal = new SessionJournal();\n\n // Track active connections for graceful cleanup\n const connections = new Set<import(\"net\").Socket>();\n\n const server = createServer(async (req: IncomingMessage, res: ServerResponse) => {\n // Add stream error handlers to prevent server crashes\n req.on(\"error\", (err) => {\n logger.error(`[ckcloud] Request stream error: ${err.message}`);\n // Don't throw - just log and let request handler deal with it\n });\n\n res.on(\"error\", (err) => {\n logger.error(`[ckcloud] Response stream error: ${err.message}`);\n // Don't try to write to failed socket - just log\n });\n\n // Finished wrapper for guaranteed cleanup on response completion/error\n finished(res, (err) => {\n if (err && err.code !== \"ERR_STREAM_DESTROYED\") {\n logger.error(`[ckcloud] Response finished with error: ${err.message}`);\n }\n // Note: heartbeatInterval cleanup happens in res.on(\"close\") handler\n // Note: completed and dedup cleanup happens in the res.on(\"close\") handler below\n });\n\n // Request finished wrapper for complete stream lifecycle tracking\n finished(req, (err) => {\n if (err && err.code !== \"ERR_STREAM_DESTROYED\") {\n logger.error(`[ckcloud] Request finished with error: ${err.message}`);\n }\n });\n\n // Health check with optional balance info\n if (req.url === \"/health\" || req.url?.startsWith(\"/health?\")) {\n const url = new URL(req.url, \"http://localhost\");\n const full = url.searchParams.get(\"full\") === \"true\";\n\n const response: Record<string, unknown> = {\n status: \"ok\",\n wallet: account.address,\n paymentChain,\n };\n if (solanaAddress) {\n response.solana = solanaAddress;\n }\n\n if (full) {\n try {\n const balanceInfo = await balanceMonitor.checkBalance();\n response.balance = balanceInfo.balanceUSD;\n response.isLow = balanceInfo.isLow;\n response.isEmpty = balanceInfo.isEmpty;\n } catch {\n response.balanceError = \"Could not fetch balance\";\n }\n }\n\n res.writeHead(200, { \"Content-Type\": \"application/json\" });\n res.end(JSON.stringify(response));\n return;\n }\n\n // Cache stats endpoint\n if (req.url === \"/cache\" || req.url?.startsWith(\"/cache?\")) {\n const stats = responseCache.getStats();\n res.writeHead(200, {\n \"Content-Type\": \"application/json\",\n \"Cache-Control\": \"no-cache\",\n });\n res.end(JSON.stringify(stats, null, 2));\n return;\n }\n\n // Stats clear endpoint - delete all log files\n if (req.url === \"/stats\" && req.method === \"DELETE\") {\n try {\n const result = await clearStats();\n res.writeHead(200, { \"Content-Type\": \"application/json\" });\n res.end(JSON.stringify({ cleared: true, deletedFiles: result.deletedFiles }));\n } catch (err) {\n res.writeHead(500, { \"Content-Type\": \"application/json\" });\n res.end(\n JSON.stringify({\n error: `Failed to clear stats: ${err instanceof Error ? err.message : String(err)}`,\n }),\n );\n }\n return;\n }\n\n // Stats API endpoint - returns JSON for programmatic access\n if (req.url === \"/stats\" || req.url?.startsWith(\"/stats?\")) {\n try {\n const url = new URL(req.url, \"http://localhost\");\n const days = parseInt(url.searchParams.get(\"days\") || \"7\", 10);\n const stats = await getStats(Math.min(days, 30));\n\n res.writeHead(200, {\n \"Content-Type\": \"application/json\",\n \"Cache-Control\": \"no-cache\",\n });\n res.end(JSON.stringify(stats, null, 2));\n } catch (err) {\n res.writeHead(500, { \"Content-Type\": \"application/json\" });\n res.end(\n JSON.stringify({\n error: `Failed to get stats: ${err instanceof Error ? err.message : String(err)}`,\n }),\n );\n }\n return;\n }\n\n // --- Handle /v1/models locally (no upstream call needed) ---\n if (req.url === \"/v1/models\" && req.method === \"GET\") {\n const models = buildProxyModelList();\n res.writeHead(200, { \"Content-Type\": \"application/json\" });\n res.end(JSON.stringify({ object: \"list\", data: models }));\n return;\n }\n\n // --- Serve locally cached images (~/.openclaw/ckcloud/images/) ---\n if (req.url?.startsWith(\"/images/\") && req.method === \"GET\") {\n const filename = req.url.slice(\"/images/\".length).split(\"?\")[0]!.replace(/[^a-zA-Z0-9._-]/g, \"\");\n if (!filename) {\n res.writeHead(400);\n res.end(\"Bad request\");\n return;\n }\n const filePath = join(IMAGE_DIR, filename);\n try {\n const s = await fsStat(filePath);\n if (!s.isFile()) throw new Error(\"not a file\");\n const ext = filename.split(\".\").pop()?.toLowerCase() ?? \"png\";\n const mime: Record<string, string> = { png: \"image/png\", jpg: \"image/jpeg\", jpeg: \"image/jpeg\", webp: \"image/webp\", gif: \"image/gif\" };\n const data = await readFile(filePath);\n res.writeHead(200, { \"Content-Type\": mime[ext] ?? \"application/octet-stream\", \"Content-Length\": data.length });\n res.end(data);\n } catch {\n res.writeHead(404, { \"Content-Type\": \"application/json\" });\n res.end(JSON.stringify({ error: \"Image not found\" }));\n }\n return;\n }\n\n // --- Handle /v1/images/generations: proxy with x402 payment + save data URIs locally ---\n if (req.url === \"/v1/images/generations\" && req.method === \"POST\") {\n const chunks: Buffer[] = [];\n for await (const chunk of req) {\n chunks.push(Buffer.isBuffer(chunk) ? chunk : Buffer.from(chunk));\n }\n const reqBody = Buffer.concat(chunks);\n try {\n const upstream = await payFetch(`${apiBase}/v1/images/generations`, {\n method: \"POST\",\n headers: { \"content-type\": \"application/json\", \"user-agent\": USER_AGENT },\n body: reqBody,\n });\n const text = await upstream.text();\n if (!upstream.ok) {\n res.writeHead(upstream.status, { \"Content-Type\": \"application/json\" });\n res.end(text);\n return;\n }\n let result: { created?: number; data?: Array<{ url?: string; revised_prompt?: string }> };\n try { result = JSON.parse(text); } catch {\n res.writeHead(200, { \"Content-Type\": \"application/json\" });\n res.end(text);\n return;\n }\n // Save any data URIs to ~/.openclaw/ckcloud/images/ and replace with localhost URLs\n if (result.data?.length) {\n await mkdir(IMAGE_DIR, { recursive: true });\n const port = (server.address() as AddressInfo | null)?.port ?? 8402;\n for (const img of result.data) {\n const m = img.url?.match(/^data:(image\\/\\w+);base64,(.+)$/);\n if (m) {\n const [, mimeType, b64] = m;\n const ext = mimeType === \"image/jpeg\" ? \"jpg\" : (mimeType!.split(\"/\")[1] ?? \"png\");\n const filename = `${Date.now()}-${Math.random().toString(36).slice(2, 10)}.${ext}`;\n await writeFile(join(IMAGE_DIR, filename), Buffer.from(b64!, \"base64\"));\n img.url = `http://localhost:${port}/images/${filename}`;\n logger.info(`[ckcloud] Image saved → ${img.url}`);\n }\n }\n }\n res.writeHead(200, { \"Content-Type\": \"application/json\" });\n res.end(JSON.stringify(result));\n } catch (err) {\n const msg = err instanceof Error ? err.message : String(err);\n logger.error(`[ckcloud] Image generation error: ${msg}`);\n if (!res.headersSent) {\n res.writeHead(502, { \"Content-Type\": \"application/json\" });\n res.end(JSON.stringify({ error: \"Image generation failed\", details: msg }));\n }\n }\n return;\n }\n\n // Only proxy paths starting with /v1\n if (!req.url?.startsWith(\"/v1\")) {\n res.writeHead(404, { \"Content-Type\": \"application/json\" });\n res.end(JSON.stringify({ error: \"Not found\" }));\n return;\n }\n\n try {\n await proxyRequest(\n req,\n res,\n apiBase,\n payFetch,\n options,\n routerOpts,\n deduplicator,\n balanceMonitor,\n sessionStore,\n responseCache,\n sessionJournal,\n );\n } catch (err) {\n const error = err instanceof Error ? err : new Error(String(err));\n options.onError?.(error);\n\n if (!res.headersSent) {\n res.writeHead(502, { \"Content-Type\": \"application/json\" });\n res.end(\n JSON.stringify({\n error: { message: `Proxy error: ${error.message}`, type: \"proxy_error\" },\n }),\n );\n } else if (!res.writableEnded) {\n // Headers already sent (streaming) — send error as SSE event\n res.write(\n `data: ${JSON.stringify({ error: { message: error.message, type: \"proxy_error\" } })}\\n\\n`,\n );\n res.write(\"data: [DONE]\\n\\n\");\n res.end();\n }\n }\n });\n\n // Listen on configured port with retry logic for TIME_WAIT handling\n // When gateway restarts quickly, the port may still be in TIME_WAIT state.\n // We retry with delay instead of incorrectly assuming a proxy is running.\n const tryListen = (attempt: number): Promise<void> => {\n return new Promise<void>((resolveAttempt, rejectAttempt) => {\n const onError = async (err: NodeJS.ErrnoException) => {\n server.removeListener(\"error\", onError);\n\n if (err.code === \"EADDRINUSE\") {\n // Port is in use - check if a proxy is actually running\n const existingProxy2 = await checkExistingProxy(listenPort);\n if (existingProxy2) {\n // Proxy is actually running - this is fine, reuse it\n logger.info(`[ckcloud] Existing proxy detected on port ${listenPort}, reusing`);\n rejectAttempt({\n code: \"REUSE_EXISTING\",\n wallet: existingProxy2.wallet,\n existingChain: existingProxy2.paymentChain,\n });\n return;\n }\n\n // Port is in TIME_WAIT (no proxy responding) - retry after delay\n if (attempt < PORT_RETRY_ATTEMPTS) {\n logger.info(\n `[ckcloud] Port ${listenPort} in TIME_WAIT, retrying in ${PORT_RETRY_DELAY_MS}ms (attempt ${attempt}/${PORT_RETRY_ATTEMPTS})`,\n );\n rejectAttempt({ code: \"RETRY\", attempt });\n return;\n }\n\n // Max retries exceeded\n logger.error(\n `[ckcloud] Port ${listenPort} still in use after ${PORT_RETRY_ATTEMPTS} attempts`,\n );\n rejectAttempt(err);\n return;\n }\n\n rejectAttempt(err);\n };\n\n server.once(\"error\", onError);\n server.listen(listenPort, \"127.0.0.1\", () => {\n server.removeListener(\"error\", onError);\n resolveAttempt();\n });\n });\n };\n\n // Retry loop for port binding\n let lastError: Error | undefined;\n for (let attempt = 1; attempt <= PORT_RETRY_ATTEMPTS; attempt++) {\n try {\n await tryListen(attempt);\n break; // Success\n } catch (err: unknown) {\n const error = err as {\n code?: string;\n wallet?: string;\n existingChain?: string;\n attempt?: number;\n };\n\n if (error.code === \"REUSE_EXISTING\" && error.wallet) {\n // Validate payment chain matches (same check as pre-listen reuse path)\n if (error.existingChain && error.existingChain !== paymentChain) {\n throw new Error(\n `Existing proxy on port ${listenPort} is using ${error.existingChain} but ${paymentChain} was requested. ` +\n `Stop the existing proxy first or use a different port.`,\n { cause: err },\n );\n }\n\n // Proxy is running, reuse it\n const baseUrl = `http://127.0.0.1:${listenPort}`;\n options.onReady?.(listenPort);\n return {\n port: listenPort,\n baseUrl,\n walletAddress: error.wallet,\n balanceMonitor,\n close: async () => {\n // No-op: we didn't start this proxy, so we shouldn't close it\n },\n };\n }\n\n if (error.code === \"RETRY\") {\n // Wait before retry\n await new Promise((r) => setTimeout(r, PORT_RETRY_DELAY_MS));\n continue;\n }\n\n // Other error - throw\n lastError = err as Error;\n break;\n }\n }\n\n if (lastError) {\n throw lastError;\n }\n\n // Server is now listening - set up remaining handlers\n const addr = server.address() as AddressInfo;\n const port = addr.port;\n const baseUrl = `http://127.0.0.1:${port}`;\n\n options.onReady?.(port);\n\n // Check for updates (non-blocking)\n // TODO checkForUpdates();\n\n // Add runtime error handler AFTER successful listen\n // This handles errors that occur during server operation (not just startup)\n server.on(\"error\", (err) => {\n logger.error(`[ckcloud] Server runtime error: ${err.message}`);\n options.onError?.(err);\n // Don't crash - log and continue\n });\n\n // Handle client connection errors (bad requests, socket errors)\n server.on(\"clientError\", (err, socket) => {\n logger.error(`[ckcloud] Client error: ${err.message}`);\n // Send 400 Bad Request if socket is still writable\n if (socket.writable && !socket.destroyed) {\n socket.end(\"HTTP/1.1 400 Bad Request\\r\\n\\r\\n\");\n }\n });\n\n // Track connections for graceful cleanup\n server.on(\"connection\", (socket) => {\n connections.add(socket);\n\n // Set 5-minute timeout for streaming requests\n socket.setTimeout(300_000);\n\n socket.on(\"timeout\", () => {\n logger.error(`[ckcloud] Socket timeout, destroying connection`);\n socket.destroy();\n });\n\n socket.on(\"end\", () => {\n // Half-closed by client (FIN received)\n });\n\n socket.on(\"error\", (err) => {\n logger.error(`[ckcloud] Socket error: ${err.message}`);\n });\n\n socket.on(\"close\", () => {\n connections.delete(socket);\n });\n });\n\n return {\n port,\n baseUrl,\n walletAddress: account.address,\n solanaAddress,\n balanceMonitor,\n close: () =>\n new Promise<void>((res, rej) => {\n const timeout = setTimeout(() => {\n rej(new Error(\"[ckcloud] Close timeout after 4s\"));\n }, 4000);\n\n sessionStore.close();\n // Destroy all active connections before closing server\n for (const socket of connections) {\n socket.destroy();\n }\n connections.clear();\n server.close((err) => {\n clearTimeout(timeout);\n if (err) {\n rej(err);\n } else {\n res();\n }\n });\n }),\n };\n}\n\nconst KIMI_BLOCK_RE = /<[||][^<>]*begin[^<>]*[||]>[\\s\\S]*?<[||][^<>]*end[^<>]*[||]>/gi;\n\n// Match standalone Kimi tokens like <|end▁of▁thinking|>\nconst KIMI_TOKEN_RE = /<[||][^<>]*[||]>/g;\n\n// Standard thinking tags that may leak through from various models\nconst THINKING_TAG_RE = /<\\s*\\/?\\s*(?:think(?:ing)?|thought|antthinking)\\b[^>]*>/gi;\n\n// Full thinking blocks: <think>content</think>\nconst THINKING_BLOCK_RE =\n /<\\s*(?:think(?:ing)?|thought|antthinking)\\b[^>]*>[\\s\\S]*?<\\s*\\/\\s*(?:think(?:ing)?|thought|antthinking)\\s*>/gi;\n\n\nfunction stripThinkingTokens(content: string): string {\n if (!content) return content;\n // Strip full Kimi thinking blocks first (begin...end with content)\n let cleaned = content.replace(KIMI_BLOCK_RE, \"\");\n // Strip remaining standalone Kimi tokens\n cleaned = cleaned.replace(KIMI_TOKEN_RE, \"\");\n // Strip full thinking blocks (<think>...</think>)\n cleaned = cleaned.replace(THINKING_BLOCK_RE, \"\");\n // Strip remaining standalone thinking tags\n cleaned = cleaned.replace(THINKING_TAG_RE, \"\");\n return cleaned;\n}\n\n/**\n * Proxy a single request through x402 payment flow to ckcloud API.\n *\n * Optimizations applied in order:\n * 1. Dedup check — if same request body seen within 30s, replay cached response\n * 2. Streaming heartbeat — for stream:true, send 200 + heartbeats immediately\n * 3. Smart routing — when model is \"ckcloud/auto\", pick cheapest capable model\n * 4. Fallback chain — on provider errors, try next model in tier's fallback list\n */\nasync function proxyRequest(\n req: IncomingMessage,\n res: ServerResponse,\n apiBase: string,\n payFetch: (input: RequestInfo | URL, init?: RequestInit) => Promise<Response>,\n options: ProxyOptions,\n routerOpts: RouterOptions,\n deduplicator: RequestDeduplicator,\n balanceMonitor: AnyBalanceMonitor,\n sessionStore: SessionStore,\n responseCache: ResponseCache,\n sessionJournal: SessionJournal,\n): Promise<void> {\n const startTime = Date.now();\n\n // Build upstream URL: /v1/chat/completions \n const upstreamUrl = `${apiBase}${req.url}`;\n logger.info(`[ckcloud] proxyRequest : ${upstreamUrl}`);\n\n // Collect request body\n const bodyChunks: Buffer[] = [];\n for await (const chunk of req) {\n bodyChunks.push(Buffer.isBuffer(chunk) ? chunk : Buffer.from(chunk));\n }\n let body = Buffer.concat(bodyChunks);\n\n // Track original context size for response headers\n const originalContextSizeKB = Math.ceil(body.length / 1024);\n\n // Routing debug info is on by default; disable with x-ckcloud-debug: false\n const debugMode = req.headers[\"x-ckcloud-debug\"] !== \"false\";\n\n // --- Smart routing ---\n let routingDecision: RoutingDecision | undefined;\n let hasTools = false; // true when request includes a tools schema\n let hasVision = false; // true when request includes image_url content parts\n let isStreaming = false;\n let modelId = \"\";\n let maxTokens = 4096;\n let routingProfile: \"free\" | \"eco\" | \"auto\" | \"premium\" | null = null;\n let accumulatedContent = \"\"; // For session journal event extraction\n let responseInputTokens: number | undefined;\n const isChatCompletion = req.url?.includes(\"/chat/completions\");\n\n logger.info(`[ckcloud] req url : ${req.url}, body: ${body}`);\n\n // Extract session ID early for journal operations (header-only at this point)\n const sessionId = getSessionId(req.headers as Record<string, string | string[] | undefined>);\n // Full session ID (header + content-derived) — populated once messages are parsed\n let effectiveSessionId: string | undefined = sessionId;\n\n if (isChatCompletion && body.length > 0) {\n try {\n const parsed = JSON.parse(body.toString()) as Record<string, unknown>;\n isStreaming = parsed.stream === true;\n modelId = (parsed.model as string) || \"\";\n maxTokens = (parsed.max_tokens as number) || 4096;\n let bodyModified = false;\n\n // Extract last user message content (used by session journal + /debug command)\n const parsedMessages = Array.isArray(parsed.messages)\n ? (parsed.messages as Array<{ role: string; content: unknown }>)\n : [];\n const lastUserMsg = [...parsedMessages].reverse().find((m) => m.role === \"user\");\n const rawLastContent = lastUserMsg?.content;\n const lastContent =\n typeof rawLastContent === \"string\"\n ? rawLastContent\n : Array.isArray(rawLastContent)\n ? (rawLastContent as Array<{ type: string; text?: string }>)\n .filter((b) => b.type === \"text\")\n .map((b) => b.text ?? \"\")\n .join(\" \")\n : \"\";\n\n // --- Session Journal: Inject context if needed ---\n // Check if the last user message asks about past work\n if (sessionId && parsedMessages.length > 0) {\n const messages = parsedMessages;\n\n if (sessionJournal.needsContext(lastContent)) {\n const journalText = sessionJournal.format(sessionId);\n if (journalText) {\n // Find system message and prepend journal, or add a new system message\n const sysIdx = messages.findIndex((m) => m.role === \"system\");\n if (sysIdx >= 0 && typeof messages[sysIdx].content === \"string\") {\n messages[sysIdx] = {\n ...messages[sysIdx],\n content: journalText + \"\\n\\n\" + messages[sysIdx].content,\n };\n } else {\n messages.unshift({ role: \"system\", content: journalText });\n }\n parsed.messages = messages;\n bodyModified = true;\n logger.info(\n `[ckcloud] Injected session journal (${journalText.length} chars) for session ${sessionId.slice(0, 8)}...`,\n );\n }\n }\n }\n\n // --- /debug command: return routing diagnostics without calling upstream ---\n if (lastContent.startsWith(\"/debug\")) {\n const debugPrompt = lastContent.slice(\"/debug\".length).trim() || \"hello\";\n const messages = parsed.messages as Array<{ role: string; content: unknown }>;\n const systemMsg = messages?.find((m) => m.role === \"system\");\n const systemPrompt = typeof systemMsg?.content === \"string\" ? systemMsg.content : undefined;\n const fullText = `${systemPrompt ?? \"\"} ${debugPrompt}`;\n const estimatedTokens = Math.ceil(fullText.length / 4);\n\n // Determine routing profile\n const normalizedModel =\n typeof parsed.model === \"string\" ? parsed.model.trim().toLowerCase() : \"\";\n const profileName = normalizedModel.replace(\"ckcloud/\", \"\");\n const debugProfile = (\n [\"free\", \"eco\", \"auto\", \"premium\"].includes(profileName) ? profileName : \"auto\"\n ) as \"free\" | \"eco\" | \"auto\" | \"premium\";\n\n // Run scoring\n const scoring = classifyByRules(\n debugPrompt,\n systemPrompt,\n estimatedTokens,\n DEFAULT_ROUTING_CONFIG.scoring,\n );\n\n // Run full routing decision\n const debugRouting = route(debugPrompt, systemPrompt, maxTokens, {\n ...routerOpts,\n routingProfile: debugProfile,\n });\n\n // Format dimension scores\n const dimLines = (scoring.dimensions ?? [])\n .map((d) => {\n const nameStr = (d.name + \":\").padEnd(24);\n const scoreStr = d.score.toFixed(2).padStart(6);\n const sigStr = d.signal ? ` [${d.signal}]` : \"\";\n return ` ${nameStr}${scoreStr}${sigStr}`;\n })\n .join(\"\\n\");\n\n // Session info\n const sess = sessionId ? sessionStore.getSession(sessionId) : undefined;\n const sessLine = sess\n ? `Session: ${sessionId!.slice(0, 8)}... → pinned: ${sess.model} (${sess.requestCount} requests)`\n : sessionId\n ? `Session: ${sessionId.slice(0, 8)}... → no pinned model`\n : \"Session: none\";\n\n const { simpleMedium, mediumComplex, complexReasoning } =\n DEFAULT_ROUTING_CONFIG.scoring.tierBoundaries;\n\n const debugText = [\n \"ckcloud Debug\",\n \"\",\n `Profile: ${debugProfile} | Tier: ${debugRouting.tier} | Model: ${debugRouting.model}`,\n `Confidence: ${debugRouting.confidence.toFixed(2)} | Cost: $${debugRouting.costEstimate.toFixed(4)} | Savings: ${(debugRouting.savings * 100).toFixed(0)}%`,\n `Reasoning: ${debugRouting.reasoning}`,\n \"\",\n `Scoring (weighted: ${scoring.score.toFixed(3)})`,\n dimLines,\n \"\",\n `Tier Boundaries: SIMPLE <${simpleMedium.toFixed(2)} | MEDIUM <${mediumComplex.toFixed(2)} | COMPLEX <${complexReasoning.toFixed(2)} | REASONING >=${complexReasoning.toFixed(2)}`,\n \"\",\n sessLine,\n ].join(\"\\n\");\n\n // Build synthetic OpenAI chat completion response\n const completionId = `chatcmpl-debug-${Date.now()}`;\n const timestamp = Math.floor(Date.now() / 1000);\n const syntheticResponse = {\n id: completionId,\n object: \"chat.completion\",\n created: timestamp,\n model: \"ckcloud/debug\",\n choices: [\n {\n index: 0,\n message: { role: \"assistant\", content: debugText },\n finish_reason: \"stop\",\n },\n ],\n usage: { prompt_tokens: 0, completion_tokens: 0, total_tokens: 0 },\n };\n\n if (isStreaming) {\n // SSE streaming response\n res.writeHead(200, {\n \"Content-Type\": \"text/event-stream\",\n \"Cache-Control\": \"no-cache\",\n Connection: \"keep-alive\",\n });\n const sseChunk = {\n id: completionId,\n object: \"chat.completion.chunk\",\n created: timestamp,\n model: \"ckcloud/debug\",\n choices: [\n {\n index: 0,\n delta: { role: \"assistant\", content: debugText },\n finish_reason: null,\n },\n ],\n };\n const sseDone = {\n id: completionId,\n object: \"chat.completion.chunk\",\n created: timestamp,\n model: \"ckcloud/debug\",\n choices: [{ index: 0, delta: {}, finish_reason: \"stop\" }],\n };\n res.write(`data: ${JSON.stringify(sseChunk)}\\n\\n`);\n res.write(`data: ${JSON.stringify(sseDone)}\\n\\n`);\n res.write(\"data: [DONE]\\n\\n\");\n res.end();\n } else {\n res.writeHead(200, { \"Content-Type\": \"application/json\" });\n res.end(JSON.stringify(syntheticResponse));\n }\n logger.info(`[ckcloud] /debug command → ${debugRouting.tier} | ${debugRouting.model}`);\n return;\n }\n\n // --- /imagegen command: generate an image via ckcloud image API ---\n if (lastContent.startsWith(\"/imagegen\")) {\n const imageArgs = lastContent.slice(\"/imagegen\".length).trim();\n\n // Parse optional flags: /imagegen --model dall-e-3 --size 1792x1024 a cute cat\n let imageModel = \"google/nano-banana\";\n let imageSize = \"1024x1024\";\n let imagePrompt = imageArgs;\n\n // Extract --model flag\n const modelMatch = imageArgs.match(/--model\\s+(\\S+)/);\n if (modelMatch) {\n const raw = modelMatch[1];\n // Resolve shorthand aliases\n const IMAGE_MODEL_ALIASES: Record<string, string> = {\n \"dall-e-3\": \"openai/dall-e-3\",\n dalle3: \"openai/dall-e-3\",\n dalle: \"openai/dall-e-3\",\n \"gpt-image\": \"openai/gpt-image-1\",\n \"gpt-image-1\": \"openai/gpt-image-1\",\n flux: \"black-forest/flux-1.1-pro\",\n \"flux-pro\": \"black-forest/flux-1.1-pro\",\n banana: \"google/nano-banana\",\n \"nano-banana\": \"google/nano-banana\",\n \"banana-pro\": \"google/nano-banana-pro\",\n \"nano-banana-pro\": \"google/nano-banana-pro\",\n };\n imageModel = IMAGE_MODEL_ALIASES[raw] ?? raw;\n imagePrompt = imagePrompt.replace(/--model\\s+\\S+/, \"\").trim();\n }\n\n // Extract --size flag\n const sizeMatch = imageArgs.match(/--size\\s+(\\d+x\\d+)/);\n if (sizeMatch) {\n imageSize = sizeMatch[1];\n imagePrompt = imagePrompt.replace(/--size\\s+\\d+x\\d+/, \"\").trim();\n }\n\n if (!imagePrompt) {\n const errorText = [\n \"Usage: /imagegen <prompt>\",\n \"\",\n \"Options:\",\n \" --model <model> Model to use (default: nano-banana)\",\n \" --size <WxH> Image size (default: 1024x1024)\",\n \"\",\n \"Models:\",\n \" nano-banana Google Gemini Flash — $0.05/image\",\n \" banana-pro Google Gemini Pro — $0.10/image (up to 4K)\",\n \" dall-e-3 OpenAI DALL-E 3 — $0.04/image\",\n \" gpt-image OpenAI GPT Image 1 — $0.02/image\",\n \" flux Black Forest Flux 1.1 Pro — $0.04/image\",\n \"\",\n \"Examples:\",\n \" /imagegen a cat wearing sunglasses\",\n \" /imagegen --model dall-e-3 a futuristic city at sunset\",\n \" /imagegen --model banana-pro --size 2048x2048 mountain landscape\",\n ].join(\"\\n\");\n\n const completionId = `chatcmpl-image-${Date.now()}`;\n const timestamp = Math.floor(Date.now() / 1000);\n if (isStreaming) {\n res.writeHead(200, {\n \"Content-Type\": \"text/event-stream\",\n \"Cache-Control\": \"no-cache\",\n Connection: \"keep-alive\",\n });\n res.write(\n `data: ${JSON.stringify({ id: completionId, object: \"chat.completion.chunk\", created: timestamp, model: \"ckcloud/image\", choices: [{ index: 0, delta: { role: \"assistant\", content: errorText }, finish_reason: null }] })}\\n\\n`,\n );\n res.write(\n `data: ${JSON.stringify({ id: completionId, object: \"chat.completion.chunk\", created: timestamp, model: \"ckcloud/image\", choices: [{ index: 0, delta: {}, finish_reason: \"stop\" }] })}\\n\\n`,\n );\n res.write(\"data: [DONE]\\n\\n\");\n res.end();\n } else {\n res.writeHead(200, { \"Content-Type\": \"application/json\" });\n res.end(\n JSON.stringify({\n id: completionId,\n object: \"chat.completion\",\n created: timestamp,\n model: \"ckcloud/image\",\n choices: [\n {\n index: 0,\n message: { role: \"assistant\", content: errorText },\n finish_reason: \"stop\",\n },\n ],\n usage: { prompt_tokens: 0, completion_tokens: 0, total_tokens: 0 },\n }),\n );\n }\n logger.info(`[ckcloud] /imagegen command → showing usage help`);\n return;\n }\n\n // Call upstream image generation API\n logger.info(\n `[ckcloud] /imagegen command → ${imageModel} (${imageSize}): ${imagePrompt.slice(0, 80)}...`,\n );\n try {\n const imageUpstreamUrl = `${apiBase}/v1/images/generations`;\n const imageBody = JSON.stringify({\n model: imageModel,\n prompt: imagePrompt,\n size: imageSize,\n n: 1,\n });\n const imageResponse = await payFetch(imageUpstreamUrl, {\n method: \"POST\",\n headers: { \"content-type\": \"application/json\", \"user-agent\": USER_AGENT },\n body: imageBody,\n });\n\n const imageResult = (await imageResponse.json()) as {\n created?: number;\n data?: Array<{ url?: string; revised_prompt?: string }>;\n error?: string | { message?: string };\n };\n\n let responseText: string;\n if (!imageResponse.ok || imageResult.error) {\n const errMsg =\n typeof imageResult.error === \"string\"\n ? imageResult.error\n : ((imageResult.error as { message?: string })?.message ??\n `HTTP ${imageResponse.status}`);\n responseText = `Image generation failed: ${errMsg}`;\n logger.info(`[ckcloud] /imagegen error: ${errMsg}`);\n } else {\n const images = imageResult.data ?? [];\n if (images.length === 0) {\n responseText = \"Image generation returned no results.\";\n } else {\n const lines: string[] = [];\n for (const img of images) {\n if (img.url) {\n if (img.url.startsWith(\"data:\")) {\n try {\n const hostedUrl = await uploadDataUriToHost(img.url);\n lines.push(hostedUrl);\n } catch (uploadErr) {\n logger.error(\n `[ckcloud] /imagegen: failed to upload data URI: ${uploadErr instanceof Error ? uploadErr.message : String(uploadErr)}`,\n );\n lines.push(\n \"Image generated but upload failed. Try again or use --model dall-e-3.\",\n );\n }\n } else {\n lines.push(img.url);\n }\n }\n if (img.revised_prompt) lines.push(`Revised prompt: ${img.revised_prompt}`);\n }\n lines.push(\"\", `Model: ${imageModel} | Size: ${imageSize}`);\n responseText = lines.join(\"\\n\");\n }\n logger.info(`[ckcloud] /imagegen success: ${images.length} image(s) generated`);\n }\n\n // Return as synthetic chat completion\n const completionId = `chatcmpl-image-${Date.now()}`;\n const timestamp = Math.floor(Date.now() / 1000);\n if (isStreaming) {\n res.writeHead(200, {\n \"Content-Type\": \"text/event-stream\",\n \"Cache-Control\": \"no-cache\",\n Connection: \"keep-alive\",\n });\n res.write(\n `data: ${JSON.stringify({ id: completionId, object: \"chat.completion.chunk\", created: timestamp, model: \"ckcloud/image\", choices: [{ index: 0, delta: { role: \"assistant\", content: responseText }, finish_reason: null }] })}\\n\\n`,\n );\n res.write(\n `data: ${JSON.stringify({ id: completionId, object: \"chat.completion.chunk\", created: timestamp, model: \"ckcloud/image\", choices: [{ index: 0, delta: {}, finish_reason: \"stop\" }] })}\\n\\n`,\n );\n res.write(\"data: [DONE]\\n\\n\");\n res.end();\n } else {\n res.writeHead(200, { \"Content-Type\": \"application/json\" });\n res.end(\n JSON.stringify({\n id: completionId,\n object: \"chat.completion\",\n created: timestamp,\n model: \"ckcloud/image\",\n choices: [\n {\n index: 0,\n message: { role: \"assistant\", content: responseText },\n finish_reason: \"stop\",\n },\n ],\n usage: { prompt_tokens: 0, completion_tokens: 0, total_tokens: 0 },\n }),\n );\n }\n } catch (err) {\n const errMsg = err instanceof Error ? err.message : String(err);\n logger.error(`[ckcloud] /imagegen error: ${errMsg}`);\n if (!res.headersSent) {\n res.writeHead(500, { \"Content-Type\": \"application/json\" });\n res.end(\n JSON.stringify({\n error: { message: `Image generation failed: ${errMsg}`, type: \"image_error\" },\n }),\n );\n }\n }\n return;\n }\n\n // Force stream: false — ckcloud API doesn't support streaming yet\n // ckcloud handles SSE heartbeat simulation for upstream compatibility\n if (parsed.stream === true) {\n parsed.stream = false;\n bodyModified = true;\n }\n\n // Normalize model name for comparison (trim whitespace, lowercase)\n const normalizedModel =\n typeof parsed.model === \"string\" ? parsed.model.trim().toLowerCase() : \"\";\n\n // Resolve model aliases (e.g., \"claude\" -> \"anthropic/claude-sonnet-4-6\")\n const resolvedModel = resolveModelAlias(normalizedModel);\n const wasAlias = resolvedModel !== normalizedModel;\n\n // Check both normalizedModel and resolvedModel — OpenClaw may send \"openai/eco\"\n // which resolveModelAlias strips to \"eco\" (a valid routing profile)\n const isRoutingProfile = ROUTING_PROFILES.has(normalizedModel) || ROUTING_PROFILES.has(resolvedModel);\n\n // Extract routing profile type (free/eco/auto/premium)\n if (isRoutingProfile) {\n const profileName = resolvedModel.replace(\"ckcloud/\", \"\");\n routingProfile = profileName as \"free\" | \"eco\" | \"auto\" | \"premium\";\n }\n\n // Debug: log received model name\n logger.info(\n `[ckcloud] Received model: \"${parsed.model}\" -> normalized: \"${normalizedModel}\"${wasAlias ? ` -> alias: \"${resolvedModel}\"` : \"\"}${routingProfile ? `, profile: ${routingProfile}` : \"\"}`,\n );\n\n // For explicit model requests, always canonicalize the model ID before upstream calls.\n // This ensures case/whitespace variants (e.g. \"DEEPSEEK/...\" or \" model \") route correctly.\n if (!isRoutingProfile) {\n if (parsed.model !== resolvedModel) {\n parsed.model = resolvedModel;\n bodyModified = true;\n }\n modelId = resolvedModel;\n }\n\n // Handle routing profiles (free/eco/auto/premium)\n if (isRoutingProfile) {\n // Free profile - direct shortcut to nvidia/gpt-oss-120b (no tier routing)\n if (routingProfile === \"free\") {\n const freeModel = \"nvidia/gpt-oss-120b\";\n logger.info(`[ckcloud] Free profile - using ${freeModel} directly`);\n parsed.model = freeModel;\n modelId = freeModel;\n bodyModified = true;\n\n // Log usage for free profile\n await logUsage({\n timestamp: new Date().toISOString(),\n model: freeModel,\n tier: \"SIMPLE\",\n cost: 0,\n baselineCost: 0,\n savings: 1.0, // 100% savings\n latencyMs: 0,\n });\n } else {\n // eco/auto/premium - use tier routing\n // Check for session persistence - use pinned model if available\n // Fall back to deriving a session ID from message content when OpenClaw\n // doesn't send an explicit x-session-id header (the default behaviour).\n effectiveSessionId =\n getSessionId(req.headers as Record<string, string | string[] | undefined>) ??\n deriveSessionId(parsedMessages);\n const existingSession = effectiveSessionId\n ? sessionStore.getSession(effectiveSessionId)\n : undefined;\n\n // Extract prompt from last user message (handles both string and Anthropic array content)\n const rawPrompt = lastUserMsg?.content;\n const prompt =\n typeof rawPrompt === \"string\"\n ? rawPrompt\n : Array.isArray(rawPrompt)\n ? (rawPrompt as Array<{ type: string; text?: string }>)\n .filter((b) => b.type === \"text\")\n .map((b) => b.text ?? \"\")\n .join(\" \")\n : \"\";\n const systemMsg = parsedMessages.find((m) => m.role === \"system\");\n const systemPrompt =\n typeof systemMsg?.content === \"string\" ? systemMsg.content : undefined;\n\n // Tool detection — when tools are present, force agentic tiers for reliable tool use\n const tools = parsed.tools as unknown[] | undefined;\n hasTools = Array.isArray(tools) && tools.length > 0;\n\n if (hasTools && tools) {\n logger.info(`[ckcloud] Tools detected (${tools.length}), forcing agentic tiers`);\n }\n\n // Vision detection: scan messages for image_url content parts\n hasVision = parsedMessages.some((m) => {\n if (Array.isArray(m.content)) {\n return (m.content as Array<{ type: string }>).some((p) => p.type === \"image_url\");\n }\n return false;\n });\n if (hasVision) {\n logger.info(`[ckcloud] Vision content detected, filtering to vision-capable models`);\n }\n\n // Always route based on current request content\n routingDecision = route(prompt, systemPrompt, maxTokens, {\n ...routerOpts,\n routingProfile: routingProfile ?? undefined,\n hasTools,\n });\n\n if (existingSession) {\n // Never downgrade: only upgrade the session when the current request needs a higher\n // tier. This fixes the OpenClaw startup-message bias (the startup message always\n // scores low-complexity, which previously pinned all subsequent real queries to a\n // cheap model) while still preventing mid-task model switching on simple follow-ups.\n const tierRank: Record<string, number> = {\n SIMPLE: 0,\n MEDIUM: 1,\n COMPLEX: 2,\n REASONING: 3,\n };\n const existingRank = tierRank[existingSession.tier] ?? 0;\n const newRank = tierRank[routingDecision.tier] ?? 0;\n\n if (newRank > existingRank) {\n // Current request needs higher capability — upgrade the session\n logger.info(\n `[ckcloud] Session ${effectiveSessionId?.slice(0, 8)}... upgrading: ${existingSession.tier} → ${routingDecision.tier} (${routingDecision.model})`,\n );\n parsed.model = routingDecision.model;\n modelId = routingDecision.model;\n bodyModified = true;\n if (effectiveSessionId) {\n sessionStore.setSession(\n effectiveSessionId,\n routingDecision.model,\n routingDecision.tier,\n );\n }\n } else {\n // Keep existing higher-tier model (prevent downgrade mid-task)\n logger.info(\n `[ckcloud] Session ${effectiveSessionId?.slice(0, 8)}... keeping pinned model: ${existingSession.model} (${existingSession.tier} >= ${routingDecision.tier})`,\n );\n parsed.model = existingSession.model;\n modelId = existingSession.model;\n bodyModified = true;\n sessionStore.touchSession(effectiveSessionId!);\n // Reflect the actual model used in the routing decision for logging/fallback\n routingDecision = {\n ...routingDecision,\n model: existingSession.model,\n tier: existingSession.tier as Tier,\n };\n }\n\n // --- Three-strike escalation: detect repetitive request patterns ---\n const lastAssistantMsg = [...parsedMessages]\n .reverse()\n .find((m) => m.role === \"assistant\");\n const assistantToolCalls = (\n lastAssistantMsg as { tool_calls?: Array<{ function?: { name?: string } }> }\n )?.tool_calls;\n const toolCallNames = Array.isArray(assistantToolCalls)\n ? assistantToolCalls\n .map((tc) => tc.function?.name)\n .filter((n): n is string => Boolean(n))\n : undefined;\n const contentHash = hashRequestContent(prompt, toolCallNames);\n const shouldEscalate = sessionStore.recordRequestHash(effectiveSessionId!, contentHash);\n\n if (shouldEscalate) {\n const activeTierConfigs = (() => {\n if (\n routingDecision.reasoning?.includes(\"agentic\") &&\n routerOpts.config.agenticTiers\n ) {\n return routerOpts.config.agenticTiers;\n }\n if (routingProfile === \"eco\" && routerOpts.config.ecoTiers) {\n return routerOpts.config.ecoTiers;\n }\n if (routingProfile === \"premium\" && routerOpts.config.premiumTiers) {\n return routerOpts.config.premiumTiers;\n }\n return routerOpts.config.tiers;\n })();\n\n const escalation = sessionStore.escalateSession(\n effectiveSessionId!,\n activeTierConfigs,\n );\n if (escalation) {\n logger.info(\n `[ckcloud] ⚡ 3-strike escalation: ${existingSession.model} → ${escalation.model} (${existingSession.tier} → ${escalation.tier})`,\n );\n parsed.model = escalation.model;\n modelId = escalation.model;\n routingDecision = {\n ...routingDecision,\n model: escalation.model,\n tier: escalation.tier as Tier,\n };\n }\n }\n } else {\n // No session — pin this routing decision for future requests\n parsed.model = routingDecision.model;\n modelId = routingDecision.model;\n bodyModified = true;\n if (effectiveSessionId) {\n sessionStore.setSession(\n effectiveSessionId,\n routingDecision.model,\n routingDecision.tier,\n );\n logger.info(\n `[ckcloud] Session ${effectiveSessionId.slice(0, 8)}... pinned to model: ${routingDecision.model}`,\n );\n }\n }\n\n options.onRouted?.(routingDecision);\n }\n }\n\n // Rebuild body if modified\n if (bodyModified) {\n body = Buffer.from(JSON.stringify(parsed));\n }\n } catch (err) {\n // Log routing errors so they're not silently swallowed\n const errorMsg = err instanceof Error ? err.message : String(err);\n logger.error(`[ckcloud] Routing error: ${errorMsg}`);\n logger.error(`[ckcloud] Need help? Run: npx @ckcloudai.com/clawrouter doctor`);\n options.onError?.(new Error(`Routing failed: ${errorMsg}`));\n }\n }\n\n // --- Auto-compression ---\n // Compress large requests to reduce network usage and improve performance\n const autoCompress = options.autoCompressRequests ?? true;\n const compressionThreshold = options.compressionThresholdKB ?? 180;\n const requestSizeKB = Math.ceil(body.length / 1024);\n\n if (autoCompress && requestSizeKB > compressionThreshold) {\n try {\n logger.info(\n `[ckcloud] Request size ${requestSizeKB}KB exceeds threshold ${compressionThreshold}KB, applying compression...`,\n );\n\n // Parse messages for compression\n const parsed = JSON.parse(body.toString()) as {\n messages?: NormalizedMessage[];\n [key: string]: unknown;\n };\n\n if (parsed.messages && parsed.messages.length > 0 && shouldCompress(parsed.messages)) {\n // Apply compression with conservative settings\n const compressionResult = await compressContext(parsed.messages, {\n enabled: true,\n preserveRaw: false, // Don't need originals in proxy\n layers: {\n deduplication: true, // Safe: removes duplicate messages\n whitespace: true, // Safe: normalizes whitespace\n dictionary: false, // Disabled: requires model to understand codebook\n paths: false, // Disabled: requires model to understand path codes\n jsonCompact: true, // Safe: just removes JSON whitespace\n observation: false, // Disabled: may lose important context\n dynamicCodebook: false, // Disabled: requires model to understand codes\n },\n dictionary: {\n maxEntries: 50,\n minPhraseLength: 15,\n includeCodebookHeader: false,\n },\n });\n\n const compressedSizeKB = Math.ceil(compressionResult.compressedChars / 1024);\n const savings = (((requestSizeKB - compressedSizeKB) / requestSizeKB) * 100).toFixed(1);\n\n logger.info(\n `[ckcloud] Compressed ${requestSizeKB}KB → ${compressedSizeKB}KB (${savings}% reduction)`,\n );\n\n // Update request body with compressed messages\n parsed.messages = compressionResult.messages;\n body = Buffer.from(JSON.stringify(parsed));\n }\n } catch (err) {\n // Compression failed - continue with original request\n logger.warn(\n `[ckcloud] Compression failed: ${err instanceof Error ? err.message : String(err)}`,\n );\n }\n }\n\n // --- Response cache check (long-term, 10min TTL) ---\n const cacheKey = ResponseCache.generateKey(body);\n const reqHeaders: Record<string, string> = {};\n for (const [key, value] of Object.entries(req.headers)) {\n if (typeof value === \"string\") reqHeaders[key] = value;\n }\n if (responseCache.shouldCache(body, reqHeaders)) {\n const cachedResponse = responseCache.get(cacheKey);\n if (cachedResponse) {\n logger.info(`[ckcloud] Cache HIT for ${cachedResponse.model} (saved API call)`);\n res.writeHead(cachedResponse.status, cachedResponse.headers);\n res.end(cachedResponse.body);\n return;\n }\n }\n\n // --- Dedup check (short-term, 30s TTL for retries) ---\n const dedupKey = RequestDeduplicator.hash(body);\n\n // Check dedup cache (catches retries within 30s)\n const cached = deduplicator.getCached(dedupKey);\n if (cached) {\n res.writeHead(cached.status, cached.headers);\n res.end(cached.body);\n return;\n }\n\n // Check in-flight — wait for the original request to complete\n const inflight = deduplicator.getInflight(dedupKey);\n if (inflight) {\n const result = await inflight;\n res.writeHead(result.status, result.headers);\n res.end(result.body);\n return;\n }\n\n // Register this request as in-flight\n deduplicator.markInflight(dedupKey);\n\n // --- Pre-request balance check ---\n // Estimate cost and check if wallet has sufficient balance\n // Skip if skipBalanceCheck is set (for testing) or if using free model\n let estimatedCostMicros: bigint | undefined;\n let balanceFallbackNotice: string | undefined;\n const isFreeModel = modelId === FREE_MODEL;\n\n if (modelId && !options.skipBalanceCheck && !isFreeModel) {\n const estimated = estimateAmount(modelId, body.length, maxTokens);\n if (estimated) {\n estimatedCostMicros = BigInt(estimated);\n\n // Apply extra buffer for balance check to prevent x402 failures after streaming starts.\n // This is aggressive to avoid triggering OpenClaw's 5-24 hour billing cooldown.\n const bufferedCostMicros = (estimatedCostMicros * BigInt(Math.ceil(BALANCE_CHECK_BUFFER * 100))) / 100n;\n\n // Check balance before proceeding (using buffered amount)\n const sufficiency = await balanceMonitor.checkSufficient(bufferedCostMicros);\n\n if (sufficiency.info.isEmpty || !sufficiency.sufficient) {\n // Wallet is empty or insufficient — ALWAYS fallback to free model\n // This ensures new users with empty wallets can still use ckcloud\n const originalModel = modelId;\n logger.info(\n `[ckcloud] Wallet ${sufficiency.info.isEmpty ? \"empty\" : \"insufficient\"} (${sufficiency.info.balanceUSD}), falling back to free model: ${FREE_MODEL} (requested: ${originalModel})`,\n );\n modelId = FREE_MODEL;\n // Update the body with new model\n const parsed = JSON.parse(body.toString()) as Record<string, unknown>;\n parsed.model = FREE_MODEL;\n body = Buffer.from(JSON.stringify(parsed));\n\n // Set notice to prepend to response so user knows about the fallback\n balanceFallbackNotice = sufficiency.info.isEmpty\n ? `> **⚠️ Wallet empty** — using free model. Fund your wallet to use ${originalModel}.\\n\\n`\n : `> **⚠️ Insufficient balance** (${sufficiency.info.balanceUSD}) — using free model instead of ${originalModel}.\\n\\n`;\n\n // Notify about the fallback\n options.onLowBalance?.({\n balanceUSD: sufficiency.info.balanceUSD,\n walletAddress: sufficiency.info.walletAddress,\n });\n } else if (sufficiency.info.isLow) {\n // Balance is low but sufficient — warn and proceed\n options.onLowBalance?.({\n balanceUSD: sufficiency.info.balanceUSD,\n walletAddress: sufficiency.info.walletAddress,\n });\n }\n }\n }\n\n // --- Streaming: early header flush + heartbeat ---\n let heartbeatInterval: ReturnType<typeof setInterval> | undefined;\n let headersSentEarly = false;\n\n if (isStreaming) {\n // Send 200 + SSE headers immediately, before x402 flow\n res.writeHead(200, {\n \"content-type\": \"text/event-stream\",\n \"cache-control\": \"no-cache\",\n connection: \"keep-alive\",\n \"x-context-used-kb\": String(originalContextSizeKB),\n \"x-context-limit-kb\": String(CONTEXT_LIMIT_KB),\n });\n headersSentEarly = true;\n\n // First heartbeat immediately\n safeWrite(res, \": heartbeat\\n\\n\");\n\n // Continue heartbeats every 2s while waiting for upstream\n heartbeatInterval = setInterval(() => {\n if (canWrite(res)) {\n safeWrite(res, \": heartbeat\\n\\n\");\n } else {\n // Socket closed, stop heartbeat\n clearInterval(heartbeatInterval);\n heartbeatInterval = undefined;\n }\n }, HEARTBEAT_INTERVAL_MS);\n }\n\n // Forward headers, stripping host, connection, and content-length\n const headers: Record<string, string> = {};\n for (const [key, value] of Object.entries(req.headers)) {\n if (\n key === \"host\" ||\n key === \"connection\" ||\n key === \"transfer-encoding\" ||\n key === \"content-length\"\n )\n continue;\n if (typeof value === \"string\") {\n headers[key] = value;\n }\n }\n if (!headers[\"content-type\"]) {\n headers[\"content-type\"] = \"application/json\";\n }\n headers[\"user-agent\"] = USER_AGENT;\n\n // --- Client disconnect cleanup ---\n let completed = false;\n res.on(\"close\", () => {\n if (heartbeatInterval) {\n clearInterval(heartbeatInterval);\n heartbeatInterval = undefined;\n }\n // Remove from in-flight if client disconnected before completion\n if (!completed) {\n deduplicator.removeInflight(dedupKey);\n }\n });\n\n // --- Request timeout ---\n const timeoutMs = options.requestTimeoutMs ?? DEFAULT_REQUEST_TIMEOUT_MS;\n const controller = new AbortController();\n const timeoutId = setTimeout(() => controller.abort(), timeoutMs);\n\n try {\n // --- Build fallback chain ---\n // If we have a routing decision, get the full fallback chain for the tier\n // Otherwise, just use the current model (no fallback for explicit model requests)\n let modelsToTry: string[];\n if (routingDecision) {\n // Estimate total context: input tokens (~4 chars per token) + max output tokens\n const estimatedInputTokens = Math.ceil(body.length / 4);\n const estimatedTotalTokens = estimatedInputTokens + maxTokens;\n\n // Get tier configs matching the profile that was used for routing\n // Must stay in sync with what route() selected in router/index.ts\n const tierConfigs = (() => {\n if (routingDecision.reasoning?.includes(\"agentic\") && routerOpts.config.agenticTiers) {\n return routerOpts.config.agenticTiers;\n }\n if (routingProfile === \"eco\" && routerOpts.config.ecoTiers) {\n return routerOpts.config.ecoTiers;\n }\n if (routingProfile === \"premium\" && routerOpts.config.premiumTiers) {\n return routerOpts.config.premiumTiers;\n }\n return routerOpts.config.tiers;\n })();\n\n // Get full chain first, then filter by context\n const fullChain = getFallbackChain(routingDecision.tier, tierConfigs);\n const contextFiltered = getFallbackChainFiltered(\n routingDecision.tier,\n tierConfigs,\n estimatedTotalTokens,\n getModelContextWindow,\n );\n\n // Log if models were filtered out due to context limits\n const contextExcluded = fullChain.filter((m) => !contextFiltered.includes(m));\n if (contextExcluded.length > 0) {\n logger.info(\n `[ckcloud] Context filter (~${estimatedTotalTokens} tokens): excluded ${contextExcluded.join(\", \")}`,\n );\n }\n\n // Filter to models that support tool calling when request has tools.\n // Prevents models like grok-code-fast-1 from outputting tool invocations\n // as plain text JSON (the \"talking to itself\" bug).\n let toolFiltered = filterByToolCalling(contextFiltered, hasTools, supportsToolCalling);\n const toolExcluded = contextFiltered.filter((m) => !toolFiltered.includes(m));\n if (toolExcluded.length > 0) {\n logger.info(\n `[ckcloud] Tool-calling filter: excluded ${toolExcluded.join(\", \")} (no structured function call support)`,\n );\n }\n\n // Filter out models that declare toolCalling but fail tool compliance in practice.\n // gemini-2.5-flash-lite refuses certain tool schemas (e.g. brave search) while\n // cheaper models like nvidia/gpt-oss-120b handle them fine.\n const TOOL_NONCOMPLIANT_MODELS = [\n \"google/gemini-2.5-flash-lite\",\n \"google/gemini-3-pro-preview\",\n \"google/gemini-3.1-pro\",\n ];\n if (hasTools && toolFiltered.length > 1) {\n const compliant = toolFiltered.filter((m) => !TOOL_NONCOMPLIANT_MODELS.includes(m));\n if (compliant.length > 0 && compliant.length < toolFiltered.length) {\n const dropped = toolFiltered.filter((m) => TOOL_NONCOMPLIANT_MODELS.includes(m));\n logger.info(\n `[ckcloud] Tool-compliance filter: excluded ${dropped.join(\", \")} (unreliable tool schema handling)`,\n );\n toolFiltered = compliant;\n }\n }\n\n // Filter to models that support vision when request has image_url content\n const visionFiltered = filterByVision(toolFiltered, hasVision, supportsVision);\n const visionExcluded = toolFiltered.filter((m) => !visionFiltered.includes(m));\n if (visionExcluded.length > 0) {\n logger.info(\n `[ckcloud] Vision filter: excluded ${visionExcluded.join(\", \")} (no vision support)`,\n );\n }\n\n // Limit to MAX_FALLBACK_ATTEMPTS to prevent infinite loops\n modelsToTry = visionFiltered.slice(0, MAX_FALLBACK_ATTEMPTS);\n\n // Deprioritize rate-limited models (put them at the end)\n modelsToTry = prioritizeNonRateLimited(modelsToTry);\n } else {\n // For explicit model requests, use the requested model\n modelsToTry = modelId ? [modelId] : [];\n }\n\n // Always ensure free model is the last-resort fallback.\n // If all paid models fail (insufficient funds, rate limits, etc.),\n // the user still gets a response instead of an error.\n if (!modelsToTry.includes(FREE_MODEL)) {\n modelsToTry.push(FREE_MODEL);\n }\n\n // --- Fallback loop: try each model until success ---\n let upstream: Response | undefined;\n let lastError: { body: string; status: number } | undefined;\n let actualModelUsed = modelId;\n\n for (let i = 0; i < modelsToTry.length; i++) {\n const tryModel = modelsToTry[i];\n const isLastAttempt = i === modelsToTry.length - 1;\n\n logger.info(`[ckcloud] Trying model ${i + 1}/${modelsToTry.length}: ${tryModel}`);\n\n const result = await tryModelRequest(\n upstreamUrl,\n req.method ?? \"POST\",\n headers,\n body,\n tryModel,\n maxTokens,\n payFetch,\n balanceMonitor,\n controller.signal,\n );\n\n if (result.success && result.response) {\n upstream = result.response;\n actualModelUsed = tryModel;\n logger.info(`[ckcloud] Success with model: ${tryModel}`);\n break;\n }\n logger.info(`[ckcloud] Trying, body:${body}, response:${JSON.stringify(result ?? \"result null\")}`);\n\n // Request failed\n lastError = {\n body: result.errorBody || \"Unknown error\",\n status: result.errorStatus || 500,\n };\n\n // If it's a provider error and not the last attempt, try next model\n if (result.isProviderError && !isLastAttempt) {\n // Track 429 rate limits to deprioritize this model for future requests\n if (result.errorStatus === 429) {\n markRateLimited(tryModel);\n // Check for server-side update hint\n try {\n const parsed = JSON.parse(result.errorBody || \"{}\");\n if (parsed.update_available) {\n logger.info(\"\");\n logger.info(\n `\\x1b[33m⬆️ ckcloud ${parsed.update_available} available (you have ${VERSION})\\x1b[0m`,\n );\n logger.info(\n ` Run: \\x1b[36mcurl -fsSL ${parsed.update_url || \"https://ckcloud.ai/ckcloud-update\"} | bash\\x1b[0m`,\n );\n logger.info(\"\");\n }\n } catch {\n /* ignore parse errors */\n }\n }\n\n // Payment error (insufficient funds, simulation failure) — skip remaining\n // paid models, jump straight to free model. No point trying other paid\n // models with the same wallet state.\n const isPaymentErr =\n /payment.*verification.*failed|payment.*settlement.*failed|insufficient.*funds|transaction_simulation_failed/i.test(\n result.errorBody || \"\",\n );\n if (isPaymentErr && tryModel !== FREE_MODEL) {\n const freeIdx = modelsToTry.indexOf(FREE_MODEL);\n if (freeIdx > i + 1) {\n logger.info(`[ckcloud] Payment error — skipping to free model: ${FREE_MODEL}`);\n i = freeIdx - 1; // loop will increment to freeIdx\n continue;\n }\n }\n\n logger.info(\n `[ckcloud] Provider error from ${tryModel}, trying fallback: ${result.errorBody?.slice(0, 100)}`,\n );\n continue;\n }\n\n // Not a provider error or last attempt — stop trying\n if (!result.isProviderError) {\n logger.info(\n `[ckcloud] Non-provider error from ${tryModel}, not retrying: ${result.errorBody?.slice(0, 100)}`,\n );\n }\n break;\n }\n\n // Clear timeout — request attempts completed\n clearTimeout(timeoutId);\n\n // Clear heartbeat — real data is about to flow\n if (heartbeatInterval) {\n clearInterval(heartbeatInterval);\n heartbeatInterval = undefined;\n }\n\n // --- Emit routing debug info (opt-in via x-ckcloud-debug: true header) ---\n // For streaming: SSE comment (invisible to most clients, visible in raw stream)\n // For non-streaming: response headers added later\n if (debugMode && headersSentEarly && routingDecision) {\n const debugComment = `: x-ckcloud-debug profile=${routingProfile ?? \"auto\"} tier=${routingDecision.tier} model=${actualModelUsed} agentic=${routingDecision.agenticScore?.toFixed(2) ?? \"n/a\"} confidence=${routingDecision.confidence.toFixed(2)} reasoning=${routingDecision.reasoning}\\n\\n`;\n safeWrite(res, debugComment);\n }\n\n // Update routing decision with actual model used (for logging)\n // IMPORTANT: Recalculate cost for the actual model, not the original primary\n if (routingDecision && actualModelUsed !== routingDecision.model) {\n const estimatedInputTokens = Math.ceil(body.length / 4);\n const newCosts = calculateModelCost(\n actualModelUsed,\n routerOpts.modelPricing,\n estimatedInputTokens,\n maxTokens,\n routingProfile ?? undefined,\n );\n routingDecision = {\n ...routingDecision,\n model: actualModelUsed,\n reasoning: `${routingDecision.reasoning} | fallback to ${actualModelUsed}`,\n costEstimate: newCosts.costEstimate,\n baselineCost: newCosts.baselineCost,\n savings: newCosts.savings,\n };\n options.onRouted?.(routingDecision);\n\n // Update session pin to the actual model used — ensures the next request in\n // this conversation starts from the fallback model rather than retrying the\n // primary and falling back again (prevents the \"model keeps jumping\" issue).\n if (effectiveSessionId) {\n sessionStore.setSession(effectiveSessionId, actualModelUsed, routingDecision.tier);\n logger.info(\n `[ckcloud] Session ${effectiveSessionId.slice(0, 8)}... updated pin to fallback: ${actualModelUsed}`,\n );\n }\n }\n\n // --- Handle case where all models failed ---\n if (!upstream) {\n const rawErrBody = lastError?.body || \"All models in fallback chain failed\";\n const errStatus = lastError?.status || 502;\n\n // Transform payment errors into user-friendly messages\n const transformedErr = transformPaymentError(rawErrBody);\n\n if (headersSentEarly) {\n // Streaming: send error as SSE event\n // If transformed error is already JSON, parse and use it; otherwise wrap in standard format\n let errPayload: string;\n try {\n const parsed = JSON.parse(transformedErr);\n errPayload = JSON.stringify(parsed);\n } catch {\n errPayload = JSON.stringify({\n error: { message: rawErrBody, type: \"provider_error\", status: errStatus },\n });\n }\n const errEvent = `data: ${errPayload}\\n\\n`;\n safeWrite(res, errEvent);\n safeWrite(res, \"data: [DONE]\\n\\n\");\n res.end();\n\n const errBuf = Buffer.from(errEvent + \"data: [DONE]\\n\\n\");\n deduplicator.complete(dedupKey, {\n status: 200,\n headers: { \"content-type\": \"text/event-stream\" },\n body: errBuf,\n completedAt: Date.now(),\n });\n } else {\n // Non-streaming: send transformed error response with context headers\n res.writeHead(errStatus, {\n \"Content-Type\": \"application/json\",\n \"x-context-used-kb\": String(originalContextSizeKB),\n \"x-context-limit-kb\": String(CONTEXT_LIMIT_KB),\n });\n res.end(transformedErr);\n\n deduplicator.complete(dedupKey, {\n status: errStatus,\n headers: { \"content-type\": \"application/json\" },\n body: Buffer.from(transformedErr),\n completedAt: Date.now(),\n });\n }\n return;\n }\n\n // --- Stream response and collect for dedup cache ---\n const responseChunks: Buffer[] = [];\n\n if (headersSentEarly) {\n // Streaming: headers already sent. Response should be 200 at this point\n // (non-200 responses are handled in the fallback loop above)\n\n // Convert non-streaming JSON response to SSE streaming format for client\n // (ckcloud API returns JSON since we forced stream:false)\n // OpenClaw expects: object=\"chat.completion.chunk\" with choices[].delta (not message)\n // We emit proper incremental deltas to match OpenAI's streaming format exactly\n if (upstream.body) {\n const chunks = await readBodyWithTimeout(upstream.body);\n\n // Combine chunks and transform to streaming format\n const jsonBody = Buffer.concat(chunks);\n const jsonStr = jsonBody.toString();\n try {\n const rsp = JSON.parse(jsonStr) as {\n id?: string;\n object?: string;\n created?: number;\n model?: string;\n choices?: Array<{\n index?: number;\n message?: {\n role?: string;\n content?: string;\n tool_calls?: Array<{\n id: string;\n type: string;\n function: { name: string; arguments: string };\n }>;\n };\n delta?: {\n role?: string;\n content?: string;\n tool_calls?: Array<{\n id: string;\n type: string;\n function: { name: string; arguments: string };\n }>;\n };\n finish_reason?: string | null;\n }>;\n usage?: unknown;\n };\n\n // Extract input token count from upstream response\n if (rsp.usage && typeof rsp.usage === \"object\") {\n const u = rsp.usage as Record<string, unknown>;\n if (typeof u.prompt_tokens === \"number\") responseInputTokens = u.prompt_tokens;\n }\n\n // Build base chunk structure (reused for all chunks)\n // Match OpenAI's exact format including system_fingerprint\n const baseChunk = {\n id: rsp.id ?? `chatcmpl-${Date.now()}`,\n object: \"chat.completion.chunk\",\n created: rsp.created ?? Math.floor(Date.now() / 1000),\n model: rsp.model ?? \"unknown\",\n system_fingerprint: null,\n };\n\n // Process each choice (usually just one)\n if (rsp.choices && Array.isArray(rsp.choices)) {\n for (const choice of rsp.choices) {\n // Strip thinking tokens (Kimi <|...|> and standard <think> tags)\n const rawContent = choice.message?.content ?? choice.delta?.content ?? \"\";\n const content = stripThinkingTokens(rawContent);\n const role = choice.message?.role ?? choice.delta?.role ?? \"assistant\";\n const index = choice.index ?? 0;\n\n // Accumulate content for session journal\n if (content) {\n accumulatedContent += content;\n }\n\n // Chunk 1: role only (mimics OpenAI's first chunk)\n const roleChunk = {\n ...baseChunk,\n choices: [{ index, delta: { role }, logprobs: null, finish_reason: null }],\n };\n const roleData = `data: ${JSON.stringify(roleChunk)}\\n\\n`;\n safeWrite(res, roleData);\n responseChunks.push(Buffer.from(roleData));\n\n // Chunk 1.5: balance fallback notice (tells user they got free model)\n if (balanceFallbackNotice) {\n const noticeChunk = {\n ...baseChunk,\n choices: [\n {\n index,\n delta: { content: balanceFallbackNotice },\n logprobs: null,\n finish_reason: null,\n },\n ],\n };\n const noticeData = `data: ${JSON.stringify(noticeChunk)}\\n\\n`;\n safeWrite(res, noticeData);\n responseChunks.push(Buffer.from(noticeData));\n balanceFallbackNotice = undefined; // Only inject once\n }\n\n // Chunk 2: content (single chunk with full content)\n if (content) {\n const contentChunk = {\n ...baseChunk,\n choices: [{ index, delta: { content }, logprobs: null, finish_reason: null }],\n };\n const contentData = `data: ${JSON.stringify(contentChunk)}\\n\\n`;\n safeWrite(res, contentData);\n responseChunks.push(Buffer.from(contentData));\n }\n\n // Chunk 2b: tool_calls (forward tool calls from upstream)\n const toolCalls = choice.message?.tool_calls ?? choice.delta?.tool_calls;\n if (toolCalls && toolCalls.length > 0) {\n const toolCallChunk = {\n ...baseChunk,\n choices: [\n {\n index,\n delta: { tool_calls: toolCalls },\n logprobs: null,\n finish_reason: null,\n },\n ],\n };\n const toolCallData = `data: ${JSON.stringify(toolCallChunk)}\\n\\n`;\n safeWrite(res, toolCallData);\n responseChunks.push(Buffer.from(toolCallData));\n }\n\n // Chunk 3: finish_reason (signals completion)\n const finishChunk = {\n ...baseChunk,\n choices: [\n {\n index,\n delta: {},\n logprobs: null,\n finish_reason:\n toolCalls && toolCalls.length > 0\n ? \"tool_calls\"\n : (choice.finish_reason ?? \"stop\"),\n },\n ],\n };\n const finishData = `data: ${JSON.stringify(finishChunk)}\\n\\n`;\n safeWrite(res, finishData);\n responseChunks.push(Buffer.from(finishData));\n }\n }\n } catch {\n // If parsing fails, send raw response as single chunk\n const sseData = `data: ${jsonStr}\\n\\n`;\n safeWrite(res, sseData);\n responseChunks.push(Buffer.from(sseData));\n }\n }\n\n // Send SSE terminator\n safeWrite(res, \"data: [DONE]\\n\\n\");\n responseChunks.push(Buffer.from(\"data: [DONE]\\n\\n\"));\n res.end();\n\n // Cache for dedup\n deduplicator.complete(dedupKey, {\n status: 200,\n headers: { \"content-type\": \"text/event-stream\" },\n body: Buffer.concat(responseChunks),\n completedAt: Date.now(),\n });\n } else {\n // Non-streaming: forward status and headers from upstream\n const responseHeaders: Record<string, string> = {};\n upstream.headers.forEach((value, key) => {\n // Skip hop-by-hop headers and content-encoding (fetch already decompresses)\n if (key === \"transfer-encoding\" || key === \"connection\" || key === \"content-encoding\")\n return;\n responseHeaders[key] = value;\n });\n\n // Add context usage headers\n responseHeaders[\"x-context-used-kb\"] = String(originalContextSizeKB);\n responseHeaders[\"x-context-limit-kb\"] = String(CONTEXT_LIMIT_KB);\n\n // Add routing debug headers (opt-in via x-ckcloud-debug: true header)\n if (debugMode && routingDecision) {\n responseHeaders[\"x-ckcloud-profile\"] = routingProfile ?? \"auto\";\n responseHeaders[\"x-ckcloud-tier\"] = routingDecision.tier;\n responseHeaders[\"x-ckcloud-model\"] = actualModelUsed;\n responseHeaders[\"x-ckcloud-confidence\"] = routingDecision.confidence.toFixed(2);\n responseHeaders[\"x-ckcloud-reasoning\"] = routingDecision.reasoning;\n if (routingDecision.agenticScore !== undefined) {\n responseHeaders[\"x-ckcloud-agentic-score\"] = routingDecision.agenticScore.toFixed(2);\n }\n }\n\n // Collect full body for possible notice injection\n const bodyParts: Buffer[] = [];\n if (upstream.body) {\n const chunks = await readBodyWithTimeout(upstream.body);\n for (const chunk of chunks) {\n bodyParts.push(Buffer.from(chunk));\n }\n }\n\n let responseBody = Buffer.concat(bodyParts);\n\n // Prepend balance fallback notice to response content\n if (balanceFallbackNotice && responseBody.length > 0) {\n try {\n const parsed = JSON.parse(responseBody.toString()) as {\n choices?: Array<{ message?: { content?: string } }>;\n };\n if (parsed.choices?.[0]?.message?.content !== undefined) {\n parsed.choices[0].message.content =\n balanceFallbackNotice + parsed.choices[0].message.content;\n responseBody = Buffer.from(JSON.stringify(parsed));\n }\n } catch {\n /* not JSON, skip notice */\n }\n balanceFallbackNotice = undefined;\n }\n\n // Update content-length header since body may have changed\n responseHeaders[\"content-length\"] = String(responseBody.length);\n res.writeHead(upstream.status, responseHeaders);\n safeWrite(res, responseBody);\n responseChunks.push(responseBody);\n res.end();\n\n // Cache for dedup (short-term, 30s)\n deduplicator.complete(dedupKey, {\n status: upstream.status,\n headers: responseHeaders,\n body: responseBody,\n completedAt: Date.now(),\n });\n\n // Cache for response cache (long-term, 10min) - only successful non-streaming\n if (upstream.status === 200 && responseCache.shouldCache(body)) {\n responseCache.set(cacheKey, {\n body: responseBody,\n status: upstream.status,\n headers: responseHeaders,\n model: actualModelUsed,\n });\n logger.info(\n `[ckcloud] Cached response for ${actualModelUsed} (${responseBody.length} bytes)`,\n );\n }\n\n // Extract content and token usage from non-streaming response\n try {\n const rspJson = JSON.parse(responseBody.toString()) as {\n choices?: Array<{ message?: { content?: string } }>;\n usage?: Record<string, unknown>;\n };\n if (rspJson.choices?.[0]?.message?.content) {\n accumulatedContent = rspJson.choices[0].message.content;\n }\n if (rspJson.usage && typeof rspJson.usage === \"object\") {\n if (typeof rspJson.usage.prompt_tokens === \"number\")\n responseInputTokens = rspJson.usage.prompt_tokens;\n }\n } catch {\n // Ignore parse errors - journal just won't have content for this response\n }\n }\n\n // --- Session Journal: Extract and record events from response ---\n if (sessionId && accumulatedContent) {\n const events = sessionJournal.extractEvents(accumulatedContent);\n if (events.length > 0) {\n sessionJournal.record(sessionId, events, actualModelUsed);\n logger.info(\n `[ckcloud] Recorded ${events.length} events to session journal for session ${sessionId.slice(0, 8)}...`,\n );\n }\n }\n\n // --- Optimistic balance deduction after successful response ---\n if (estimatedCostMicros !== undefined) {\n balanceMonitor.deductEstimated(estimatedCostMicros);\n }\n\n // Mark request as completed (for client disconnect cleanup)\n completed = true;\n } catch (err) {\n // Clear timeout on error\n clearTimeout(timeoutId);\n\n // Clear heartbeat on error\n if (heartbeatInterval) {\n clearInterval(heartbeatInterval);\n heartbeatInterval = undefined;\n }\n\n // Remove in-flight entry so retries aren't blocked\n deduplicator.removeInflight(dedupKey);\n\n // Invalidate balance cache on payment failure (might be out of date)\n balanceMonitor.invalidate();\n\n // Convert abort error to more descriptive timeout error\n if (err instanceof Error && err.name === \"AbortError\") {\n throw new Error(`Request timed out after ${timeoutMs}ms`, { cause: err });\n }\n\n throw err;\n }\n\n // --- Usage logging (fire-and-forget) ---\n // Note: Recalculate cost using full body length (not just system+user message)\n // and apply 20% buffer to match actual x402 payment (see estimateAmount())\n // Log ALL requests: both auto-routed (routingDecision set) and direct model picks\n const logModel = routingDecision?.model ?? modelId;\n if (logModel) {\n // Use full body length for accurate cost (matches x402 payment estimation)\n const estimatedInputTokens = Math.ceil(body.length / 4);\n const accurateCosts = calculateModelCost(\n logModel,\n routerOpts.modelPricing,\n estimatedInputTokens,\n maxTokens,\n routingProfile ?? undefined,\n );\n // Apply 20% buffer for cost estimation accuracy\n const costWithBuffer = accurateCosts.costEstimate * 1.2;\n const baselineWithBuffer = accurateCosts.baselineCost * 1.2;\n const entry: UsageEntry = {\n timestamp: new Date().toISOString(),\n model: logModel,\n tier: routingDecision?.tier ?? \"DIRECT\",\n cost: costWithBuffer,\n baselineCost: baselineWithBuffer,\n savings: accurateCosts.savings,\n latencyMs: Date.now() - startTime,\n ...(responseInputTokens !== undefined && { inputTokens: responseInputTokens }),\n };\n logUsage(entry).catch(() => { });\n }\n}\n","/**\n * Payment Pre-Auth Cache\n *\n * Wraps the @x402/fetch SDK with pre-authorization caching.\n * After the first 402 response, caches payment requirements per endpoint.\n * On subsequent requests, pre-signs payment and attaches it to the first\n * request, skipping the 402 round trip (~200ms savings per request).\n *\n * Falls back to normal 402 flow if pre-signed payment is rejected.\n */\n\nimport type { x402Client } from \"@x402/fetch\";\nimport { x402HTTPClient } from \"@x402/fetch\";\n\ntype PaymentRequired = Parameters<InstanceType<typeof x402Client>[\"createPaymentPayload\"]>[0];\n\ninterface CachedEntry {\n paymentRequired: PaymentRequired;\n cachedAt: number;\n}\n\nconst DEFAULT_TTL_MS = 3_600_000; // 1 hour\n\nif (typeof process !== \"undefined\") {\n process.env.NODE_TLS_REJECT_UNAUTHORIZED = \"0\";\n}\n\ntype FetchFn = (input: RequestInfo | URL, init?: RequestInit) => Promise<Response>;\n\nexport function createPayFetchWithPreAuth(\n baseFetch: FetchFn,\n client: x402Client,\n ttlMs = DEFAULT_TTL_MS,\n options?: { skipPreAuth?: boolean },\n): FetchFn {\n const httpClient = new x402HTTPClient(client);\n const cache = new Map<string, CachedEntry>();\n\n return async (input: RequestInfo | URL, init?: RequestInit): Promise<Response> => {\n const request = new Request(input, init);\n const urlPath = new URL(request.url).pathname;\n\n // Try pre-auth if we have cached payment requirements\n // Skip for Solana: payments use per-tx blockhashes that expire ~60-90s,\n // making cached requirements useless and causing double charges.\n const cached = !options?.skipPreAuth ? cache.get(urlPath) : undefined;\n if (cached && Date.now() - cached.cachedAt < ttlMs) {\n try {\n const payload = await client.createPaymentPayload(cached.paymentRequired);\n const headers = httpClient.encodePaymentSignatureHeader(payload);\n const preAuthRequest = request.clone();\n for (const [key, value] of Object.entries(headers)) {\n preAuthRequest.headers.set(key, value);\n }\n const response = await baseFetch(preAuthRequest);\n if (response.status !== 402) {\n return response; // Pre-auth worked — saved ~200ms\n }\n // Pre-auth rejected (params may have changed) — invalidate and fall through\n cache.delete(urlPath);\n } catch {\n // Pre-auth signing failed — invalidate and fall through\n cache.delete(urlPath);\n }\n }\n\n // Normal flow: make request, handle 402 if needed\n const clonedRequest = request.clone();\n const response = await baseFetch(request);\n if (response.status !== 402) {\n return response;\n }\n\n // Parse 402 response and cache for future pre-auth\n let paymentRequired: PaymentRequired;\n try {\n const getHeader = (name: string) => response.headers.get(name);\n let body: unknown;\n try {\n const responseText = await Promise.race([\n response.text(),\n new Promise<never>((_, reject) =>\n setTimeout(() => reject(new Error(\"Body read timeout\")), 30_000),\n ),\n ]);\n if (responseText) body = JSON.parse(responseText);\n } catch {\n /* empty body is fine */\n }\n paymentRequired = httpClient.getPaymentRequiredResponse(getHeader, body);\n cache.set(urlPath, { paymentRequired, cachedAt: Date.now() });\n } catch (error) {\n throw new Error(\n `Failed to parse payment requirements: ${error instanceof Error ? error.message : \"Unknown error\"}`,\n { cause: error },\n );\n }\n\n // Sign payment and retry\n const payload = await client.createPaymentPayload(paymentRequired);\n const paymentHeaders = httpClient.encodePaymentSignatureHeader(payload);\n for (const [key, value] of Object.entries(paymentHeaders)) {\n clonedRequest.headers.set(key, value);\n }\n return baseFetch(clonedRequest);\n };\n}\n","/**\n * Balance Monitor for ckcloud\n *\n * Monitors USDC balance on Base network with intelligent caching.\n * Provides pre-request balance checks to prevent failed payments.\n *\n * Caching Strategy:\n * - TTL: 30 seconds (balance is cached to avoid excessive RPC calls)\n * - Optimistic deduction: after successful payment, subtract estimated cost from cache\n * - Invalidation: on payment failure, immediately refresh from RPC\n */\n\nimport { createPublicClient, http, erc20Abi } from \"viem\";\nimport { base } from \"viem/chains\";\nimport { RpcError } from \"./errors.js\";\n\n/** USDC contract address on Base mainnet */\nconst USDC_BASE = \"0x833589fCD6eDb6E08f4c7C32D4f71b54bdA02913\" as const;\n\n/** Cache TTL in milliseconds (30 seconds) */\nconst CACHE_TTL_MS = 30_000;\n\n/** Balance thresholds in USDC smallest unit (6 decimals) */\nexport const BALANCE_THRESHOLDS = {\n /** Low balance warning threshold: $1.00 */\n LOW_BALANCE_MICROS: 1_000_000n,\n /** Effectively zero threshold: $0.0001 (covers dust/rounding) */\n ZERO_THRESHOLD: 100n,\n} as const;\n\n/** Balance information returned by checkBalance() */\nexport type BalanceInfo = {\n /** Raw balance in USDC smallest unit (6 decimals) */\n balance: bigint;\n /** Formatted balance as \"$X.XX\" */\n balanceUSD: string;\n /** True if balance < $1.00 */\n isLow: boolean;\n /** True if balance < $0.0001 (effectively zero) */\n isEmpty: boolean;\n /** Wallet address for funding instructions */\n walletAddress: string;\n};\n\n/** Result from checkSufficient() */\nexport type SufficiencyResult = {\n /** True if balance >= estimated cost */\n sufficient: boolean;\n /** Current balance info */\n info: BalanceInfo;\n /** If insufficient, the shortfall as \"$X.XX\" */\n shortfall?: string;\n};\n\n/**\n * Monitors USDC balance on Base network.\n *\n * Usage:\n * const monitor = new BalanceMonitor(\"0x...\");\n * const info = await monitor.checkBalance();\n * if (info.isLow) console.warn(\"Low balance!\");\n */\nexport class BalanceMonitor {\n private readonly client;\n private readonly walletAddress: `0x${string}`;\n\n /** Cached balance (null = not yet fetched) */\n private cachedBalance: bigint | null = null;\n /** Timestamp when cache was last updated */\n private cachedAt = 0;\n\n constructor(walletAddress: string) {\n this.walletAddress = walletAddress as `0x${string}`;\n this.client = createPublicClient({\n chain: base,\n transport: http(undefined, {\n timeout: 10_000, // 10 second timeout to prevent hanging on slow RPC\n }),\n });\n }\n\n /**\n * Check current USDC balance.\n * Uses cache if valid, otherwise fetches from RPC.\n */\n async checkBalance(): Promise<BalanceInfo> {\n const now = Date.now();\n\n // Use cache only when balance is positive and still fresh.\n // Zero balance is never cached — always re-fetch so a funded wallet is\n // detected on the next request without waiting for cache expiry.\n if (\n this.cachedBalance !== null &&\n this.cachedBalance > 0n &&\n now - this.cachedAt < CACHE_TTL_MS\n ) {\n return this.buildInfo(this.cachedBalance);\n }\n\n // Fetch from RPC\n const balance = await this.fetchBalance();\n if (balance > 0n) {\n this.cachedBalance = balance;\n this.cachedAt = now;\n }\n\n return this.buildInfo(balance);\n }\n\n /**\n * Check if balance is sufficient for an estimated cost.\n *\n * @param estimatedCostMicros - Estimated cost in USDC smallest unit (6 decimals)\n */\n async checkSufficient(estimatedCostMicros: bigint): Promise<SufficiencyResult> {\n const info = await this.checkBalance();\n\n if (info.balance >= estimatedCostMicros) {\n return { sufficient: true, info };\n }\n\n const shortfall = estimatedCostMicros - info.balance;\n return {\n sufficient: false,\n info,\n shortfall: this.formatUSDC(shortfall),\n };\n }\n\n /**\n * Optimistically deduct estimated cost from cached balance.\n * Call this after a successful payment to keep cache accurate.\n *\n * @param amountMicros - Amount to deduct in USDC smallest unit\n */\n deductEstimated(amountMicros: bigint): void {\n if (this.cachedBalance !== null && this.cachedBalance >= amountMicros) {\n this.cachedBalance -= amountMicros;\n }\n }\n\n /**\n * Invalidate cache, forcing next checkBalance() to fetch from RPC.\n * Call this after a payment failure to get accurate balance.\n */\n invalidate(): void {\n this.cachedBalance = null;\n this.cachedAt = 0;\n }\n\n /**\n * Force refresh balance from RPC (ignores cache).\n */\n async refresh(): Promise<BalanceInfo> {\n this.invalidate();\n return this.checkBalance();\n }\n\n /**\n * Format USDC amount (in micros) as \"$X.XX\".\n */\n formatUSDC(amountMicros: bigint): string {\n // USDC has 6 decimals\n const dollars = Number(amountMicros) / 1_000_000;\n return `$${dollars.toFixed(2)}`;\n }\n\n /**\n * Get the wallet address being monitored.\n */\n getWalletAddress(): string {\n return this.walletAddress;\n }\n\n /** Fetch balance from RPC */\n private async fetchBalance(): Promise<bigint> {\n try {\n const balance = await this.client.readContract({\n address: USDC_BASE,\n abi: erc20Abi,\n functionName: \"balanceOf\",\n args: [this.walletAddress],\n });\n return balance;\n } catch (error) {\n // Throw typed error instead of silently returning 0\n // This allows callers to distinguish \"node down\" from \"wallet empty\"\n throw new RpcError(error instanceof Error ? error.message : \"Unknown error\", error);\n }\n }\n\n /** Build BalanceInfo from raw balance */\n private buildInfo(balance: bigint): BalanceInfo {\n return {\n balance,\n balanceUSD: this.formatUSDC(balance),\n isLow: balance < BALANCE_THRESHOLDS.LOW_BALANCE_MICROS,\n isEmpty: balance < BALANCE_THRESHOLDS.ZERO_THRESHOLD,\n walletAddress: this.walletAddress,\n };\n }\n}\n","/**\n * Typed Error Classes for ckcloud\n *\n * Provides structured errors for balance-related failures with\n * all necessary information for user-friendly error messages.\n */\n\n/**\n * Thrown when wallet has insufficient USDC balance for a request.\n */\nexport class InsufficientFundsError extends Error {\n readonly code = \"INSUFFICIENT_FUNDS\" as const;\n readonly currentBalanceUSD: string;\n readonly requiredUSD: string;\n readonly walletAddress: string;\n\n constructor(opts: { currentBalanceUSD: string; requiredUSD: string; walletAddress: string }) {\n const msg = [\n `Insufficient balance. Current: ${opts.currentBalanceUSD}, Required: ${opts.requiredUSD}`,\n `Options:`,\n ` 1. Fund wallet: ${opts.walletAddress}`,\n ` 2. Use free model: /model free`,\n ].join(\"\\n\");\n super(msg);\n this.name = \"InsufficientFundsError\";\n this.currentBalanceUSD = opts.currentBalanceUSD;\n this.requiredUSD = opts.requiredUSD;\n this.walletAddress = opts.walletAddress;\n }\n}\n\n/**\n * Thrown when wallet has no USDC balance (or effectively zero).\n */\nexport class EmptyWalletError extends Error {\n readonly code = \"EMPTY_WALLET\" as const;\n readonly walletAddress: string;\n\n constructor(walletAddress: string) {\n const msg = [\n `No USDC balance.`,\n `Options:`,\n ` 1. Fund wallet: ${walletAddress}`,\n ` 2. Use free model: /model free`,\n ` 3. Uninstall: bash ~/.openclaw/extensions/ckcloud/scripts/uninstall.sh`,\n ].join(\"\\n\");\n super(msg);\n this.name = \"EmptyWalletError\";\n this.walletAddress = walletAddress;\n }\n}\n\n/**\n * Type guard to check if an error is InsufficientFundsError.\n */\nexport function isInsufficientFundsError(error: unknown): error is InsufficientFundsError {\n return error instanceof Error && (error as InsufficientFundsError).code === \"INSUFFICIENT_FUNDS\";\n}\n\n/**\n * Type guard to check if an error is EmptyWalletError.\n */\nexport function isEmptyWalletError(error: unknown): error is EmptyWalletError {\n return error instanceof Error && (error as EmptyWalletError).code === \"EMPTY_WALLET\";\n}\n\n/**\n * Type guard to check if an error is a balance-related error.\n */\nexport function isBalanceError(error: unknown): error is InsufficientFundsError | EmptyWalletError {\n return isInsufficientFundsError(error) || isEmptyWalletError(error);\n}\n\n/**\n * Thrown when RPC call fails (network error, node down, etc).\n * Distinguishes infrastructure failures from actual empty wallets.\n */\nexport class RpcError extends Error {\n readonly code = \"RPC_ERROR\" as const;\n readonly originalError: unknown;\n\n constructor(message: string, originalError?: unknown) {\n super(`RPC error: ${message}. Check network connectivity.`);\n this.name = \"RpcError\";\n this.originalError = originalError;\n }\n}\n\n/**\n * Type guard to check if an error is RpcError.\n */\nexport function isRpcError(error: unknown): error is RpcError {\n return error instanceof Error && (error as RpcError).code === \"RPC_ERROR\";\n}\n","/**\n * Solana USDC Balance Monitor\n *\n * Checks USDC balance on Solana mainnet with caching.\n * Absorbed from @ckcloudai.com/clawwallet's solana-adapter.ts (balance portion only).\n */\n\nimport { address as solAddress, createSolanaRpc } from \"@solana/kit\";\n\nconst SOLANA_USDC_MINT = \"EPjFWdd5AufqSSqeM2qN1xzybapC8G4wEGGkZwyTDt1v\";\nconst SOLANA_DEFAULT_RPC = \"https://api.mainnet-beta.solana.com\";\nconst BALANCE_TIMEOUT_MS = 10_000;\nconst CACHE_TTL_MS = 30_000;\n\nexport type SolanaBalanceInfo = {\n balance: bigint;\n balanceUSD: string;\n isLow: boolean;\n isEmpty: boolean;\n walletAddress: string;\n};\n\n/** Result from checkSufficient() */\nexport type SolanaSufficiencyResult = {\n sufficient: boolean;\n info: SolanaBalanceInfo;\n shortfall?: string;\n};\n\nexport class SolanaBalanceMonitor {\n private readonly rpc: ReturnType<typeof createSolanaRpc>;\n private readonly walletAddress: string;\n private cachedBalance: bigint | null = null;\n private cachedAt = 0;\n\n constructor(walletAddress: string, rpcUrl?: string) {\n this.walletAddress = walletAddress;\n const url = rpcUrl || process[\"env\"].CLAWROUTER_SOLANA_RPC_URL || SOLANA_DEFAULT_RPC;\n this.rpc = createSolanaRpc(url);\n }\n\n async checkBalance(): Promise<SolanaBalanceInfo> {\n const now = Date.now();\n if (\n this.cachedBalance !== null &&\n this.cachedBalance > 0n &&\n now - this.cachedAt < CACHE_TTL_MS\n ) {\n return this.buildInfo(this.cachedBalance);\n }\n // Zero balance is never cached — always re-fetch so a funded wallet is\n // detected on the next request without waiting for cache expiry.\n const balance = await this.fetchBalance();\n if (balance > 0n) {\n this.cachedBalance = balance;\n this.cachedAt = now;\n }\n return this.buildInfo(balance);\n }\n\n deductEstimated(amountMicros: bigint): void {\n if (this.cachedBalance !== null && this.cachedBalance >= amountMicros) {\n this.cachedBalance -= amountMicros;\n }\n }\n\n invalidate(): void {\n this.cachedBalance = null;\n this.cachedAt = 0;\n }\n\n async refresh(): Promise<SolanaBalanceInfo> {\n this.invalidate();\n return this.checkBalance();\n }\n\n /**\n * Check if balance is sufficient for an estimated cost.\n */\n async checkSufficient(estimatedCostMicros: bigint): Promise<SolanaSufficiencyResult> {\n const info = await this.checkBalance();\n if (info.balance >= estimatedCostMicros) {\n return { sufficient: true, info };\n }\n const shortfall = estimatedCostMicros - info.balance;\n return {\n sufficient: false,\n info,\n shortfall: this.formatUSDC(shortfall),\n };\n }\n\n /**\n * Format USDC amount (in micros) as \"$X.XX\".\n */\n formatUSDC(amountMicros: bigint): string {\n const dollars = Number(amountMicros) / 1_000_000;\n return `$${dollars.toFixed(2)}`;\n }\n\n getWalletAddress(): string {\n return this.walletAddress;\n }\n\n private async fetchBalance(): Promise<bigint> {\n const owner = solAddress(this.walletAddress);\n const mint = solAddress(SOLANA_USDC_MINT);\n\n // The public Solana RPC frequently returns empty token account lists even\n // for funded wallets. Retry once on empty before accepting $0 as truth.\n for (let attempt = 0; attempt < 2; attempt++) {\n const result = await this.fetchBalanceOnce(owner, mint);\n if (result > 0n || attempt === 1) return result;\n await new Promise((r) => setTimeout(r, 1_000));\n }\n return 0n;\n }\n\n private async fetchBalanceOnce(\n owner: ReturnType<typeof solAddress>,\n mint: ReturnType<typeof solAddress>,\n ): Promise<bigint> {\n const controller = new AbortController();\n const timer = setTimeout(() => controller.abort(), BALANCE_TIMEOUT_MS);\n\n try {\n const response = await this.rpc\n .getTokenAccountsByOwner(owner, { mint }, { encoding: \"jsonParsed\" })\n .send({ abortSignal: controller.signal });\n\n if (response.value.length === 0) return 0n;\n\n let total = 0n;\n for (const account of response.value) {\n const parsed = account.account.data as {\n parsed: { info: { tokenAmount: { amount: string } } };\n };\n total += BigInt(parsed.parsed.info.tokenAmount.amount);\n }\n return total;\n } catch (err) {\n throw new Error(\n `Failed to fetch Solana USDC balance: ${err instanceof Error ? err.message : String(err)}`,\n { cause: err },\n );\n } finally {\n clearTimeout(timer);\n }\n }\n\n private buildInfo(balance: bigint): SolanaBalanceInfo {\n const dollars = Number(balance) / 1_000_000;\n return {\n balance,\n balanceUSD: `$${dollars.toFixed(2)}`,\n isLow: balance < 1_000_000n,\n isEmpty: balance < 100n,\n walletAddress: this.walletAddress,\n };\n }\n}\n","/**\n * Usage Statistics Aggregator\n *\n * Reads usage log files and aggregates statistics for terminal display.\n * Supports filtering by date range and provides multiple aggregation views.\n */\n\nimport { readdir, unlink } from \"node:fs/promises\";\nimport { readTextFile } from \"./fs-read\";\nimport { join } from \"node:path\";\nimport { homedir } from \"node:os\";\nimport type { UsageEntry } from \"./logger\";\nimport { VERSION } from \"./version\";\n\nconst LOG_DIR = join(homedir(), \".openclaw\", \"ckcloud\", \"logs\");\n\nexport type DailyStats = {\n date: string;\n totalRequests: number;\n totalCost: number;\n totalBaselineCost: number;\n totalSavings: number;\n avgLatencyMs: number;\n byTier: Record<string, { count: number; cost: number }>;\n byModel: Record<string, { count: number; cost: number }>;\n};\n\nexport type AggregatedStats = {\n period: string;\n totalRequests: number;\n totalCost: number;\n totalBaselineCost: number;\n totalSavings: number;\n savingsPercentage: number;\n avgLatencyMs: number;\n avgCostPerRequest: number;\n byTier: Record<string, { count: number; cost: number; percentage: number }>;\n byModel: Record<string, { count: number; cost: number; percentage: number }>;\n dailyBreakdown: DailyStats[];\n entriesWithBaseline: number; // Entries with valid baseline tracking\n};\n\n/**\n * Parse a JSONL log file into usage entries.\n * Handles both old format (without tier/baselineCost) and new format.\n */\nasync function parseLogFile(filePath: string): Promise<UsageEntry[]> {\n try {\n const content = await readTextFile(filePath);\n const lines = content.trim().split(\"\\n\").filter(Boolean);\n const entries: UsageEntry[] = [];\n for (const line of lines) {\n try {\n const entry = JSON.parse(line) as Partial<UsageEntry>;\n entries.push({\n timestamp: entry.timestamp || new Date().toISOString(),\n model: entry.model || \"unknown\",\n tier: entry.tier || \"UNKNOWN\",\n cost: entry.cost || 0,\n baselineCost: entry.baselineCost || entry.cost || 0,\n savings: entry.savings || 0,\n latencyMs: entry.latencyMs || 0,\n });\n } catch {\n // Skip malformed lines, keep valid ones\n }\n }\n return entries;\n } catch {\n return [];\n }\n}\n\n/**\n * Get list of available log files sorted by date (newest first).\n */\nasync function getLogFiles(): Promise<string[]> {\n try {\n const files = await readdir(LOG_DIR);\n return files\n .filter((f) => f.startsWith(\"usage-\") && f.endsWith(\".jsonl\"))\n .sort()\n .reverse();\n } catch {\n return [];\n }\n}\n\n/**\n * Aggregate stats for a single day.\n */\nfunction aggregateDay(date: string, entries: UsageEntry[]): DailyStats {\n const byTier: Record<string, { count: number; cost: number }> = {};\n const byModel: Record<string, { count: number; cost: number }> = {};\n let totalLatency = 0;\n\n for (const entry of entries) {\n // By tier\n if (!byTier[entry.tier]) byTier[entry.tier] = { count: 0, cost: 0 };\n byTier[entry.tier].count++;\n byTier[entry.tier].cost += entry.cost;\n\n // By model\n if (!byModel[entry.model]) byModel[entry.model] = { count: 0, cost: 0 };\n byModel[entry.model].count++;\n byModel[entry.model].cost += entry.cost;\n\n totalLatency += entry.latencyMs;\n }\n\n const totalCost = entries.reduce((sum, e) => sum + e.cost, 0);\n const totalBaselineCost = entries.reduce((sum, e) => sum + e.baselineCost, 0);\n\n return {\n date,\n totalRequests: entries.length,\n totalCost,\n totalBaselineCost,\n totalSavings: totalBaselineCost - totalCost,\n avgLatencyMs: entries.length > 0 ? totalLatency / entries.length : 0,\n byTier,\n byModel,\n };\n}\n\n/**\n * Get aggregated statistics for the last N days.\n */\nexport async function getStats(days: number = 7): Promise<AggregatedStats> {\n const logFiles = await getLogFiles();\n const filesToRead = logFiles.slice(0, days);\n\n const dailyBreakdown: DailyStats[] = [];\n const allByTier: Record<string, { count: number; cost: number }> = {};\n const allByModel: Record<string, { count: number; cost: number }> = {};\n let totalRequests = 0;\n let totalCost = 0;\n let totalBaselineCost = 0;\n let totalLatency = 0;\n\n for (const file of filesToRead) {\n const date = file.replace(\"usage-\", \"\").replace(\".jsonl\", \"\");\n const filePath = join(LOG_DIR, file);\n const entries = await parseLogFile(filePath);\n\n if (entries.length === 0) continue;\n\n const dayStats = aggregateDay(date, entries);\n dailyBreakdown.push(dayStats);\n\n totalRequests += dayStats.totalRequests;\n totalCost += dayStats.totalCost;\n totalBaselineCost += dayStats.totalBaselineCost;\n totalLatency += dayStats.avgLatencyMs * dayStats.totalRequests;\n\n // Merge tier stats\n for (const [tier, stats] of Object.entries(dayStats.byTier)) {\n if (!allByTier[tier]) allByTier[tier] = { count: 0, cost: 0 };\n allByTier[tier].count += stats.count;\n allByTier[tier].cost += stats.cost;\n }\n\n // Merge model stats\n for (const [model, stats] of Object.entries(dayStats.byModel)) {\n if (!allByModel[model]) allByModel[model] = { count: 0, cost: 0 };\n allByModel[model].count += stats.count;\n allByModel[model].cost += stats.cost;\n }\n }\n\n // Calculate percentages\n const byTierWithPercentage: Record<string, { count: number; cost: number; percentage: number }> =\n {};\n for (const [tier, stats] of Object.entries(allByTier)) {\n byTierWithPercentage[tier] = {\n ...stats,\n percentage: totalRequests > 0 ? (stats.count / totalRequests) * 100 : 0,\n };\n }\n\n const byModelWithPercentage: Record<string, { count: number; cost: number; percentage: number }> =\n {};\n for (const [model, stats] of Object.entries(allByModel)) {\n byModelWithPercentage[model] = {\n ...stats,\n percentage: totalRequests > 0 ? (stats.count / totalRequests) * 100 : 0,\n };\n }\n\n const totalSavings = totalBaselineCost - totalCost;\n const savingsPercentage = totalBaselineCost > 0 ? (totalSavings / totalBaselineCost) * 100 : 0;\n\n // Count entries with valid baseline tracking (baseline != cost means tracking was active)\n let entriesWithBaseline = 0;\n for (const day of dailyBreakdown) {\n if (day.totalBaselineCost !== day.totalCost) {\n entriesWithBaseline += day.totalRequests;\n }\n }\n\n return {\n period: days === 1 ? \"today\" : `last ${days} days`,\n totalRequests,\n totalCost,\n totalBaselineCost,\n totalSavings,\n savingsPercentage,\n avgLatencyMs: totalRequests > 0 ? totalLatency / totalRequests : 0,\n avgCostPerRequest: totalRequests > 0 ? totalCost / totalRequests : 0,\n byTier: byTierWithPercentage,\n byModel: byModelWithPercentage,\n dailyBreakdown: dailyBreakdown.reverse(), // Oldest first for charts\n entriesWithBaseline, // How many entries have valid baseline tracking\n };\n}\n\n/**\n * Format stats as ASCII table for terminal display.\n */\nexport function formatStatsAscii(stats: AggregatedStats): string {\n const lines: string[] = [];\n\n // Header\n lines.push(\"╔════════════════════════════════════════════════════════════╗\");\n lines.push(`║ ckcloud by ckcloud v${VERSION}`.padEnd(61) + \"║\");\n lines.push(\"║ Usage Statistics ║\");\n lines.push(\"╠════════════════════════════════════════════════════════════╣\");\n\n // Summary\n lines.push(`║ Period: ${stats.period.padEnd(49)}║`);\n lines.push(`║ Total Requests: ${stats.totalRequests.toString().padEnd(41)}║`);\n lines.push(`║ Total Cost: $${stats.totalCost.toFixed(4).padEnd(43)}║`);\n lines.push(`║ Baseline Cost (Opus 4.5): $${stats.totalBaselineCost.toFixed(4).padEnd(30)}║`);\n\n // Show savings with note if some entries lack baseline tracking\n const savingsLine = `║ 💰 Total Saved: $${stats.totalSavings.toFixed(4)} (${stats.savingsPercentage.toFixed(1)}%)`;\n if (stats.entriesWithBaseline < stats.totalRequests && stats.entriesWithBaseline > 0) {\n lines.push(savingsLine.padEnd(61) + \"║\");\n const note = `║ (based on ${stats.entriesWithBaseline}/${stats.totalRequests} tracked requests)`;\n lines.push(note.padEnd(61) + \"║\");\n } else {\n lines.push(savingsLine.padEnd(61) + \"║\");\n }\n lines.push(`║ Avg Latency: ${stats.avgLatencyMs.toFixed(0)}ms`.padEnd(61) + \"║\");\n\n // Tier breakdown\n lines.push(\"╠════════════════════════════════════════════════════════════╣\");\n lines.push(\"║ Routing by Tier: ║\");\n\n // Show all tiers found in data, ordered by known tiers first then others\n const knownTiers = [\"SIMPLE\", \"MEDIUM\", \"COMPLEX\", \"REASONING\", \"DIRECT\"];\n const allTiers = Object.keys(stats.byTier);\n const otherTiers = allTiers.filter((t) => !knownTiers.includes(t));\n const tierOrder = [...knownTiers.filter((t) => stats.byTier[t]), ...otherTiers];\n\n for (const tier of tierOrder) {\n const data = stats.byTier[tier];\n if (data) {\n const bar = \"█\".repeat(Math.min(20, Math.round(data.percentage / 5)));\n const displayTier = tier === \"UNKNOWN\" ? \"OTHER\" : tier;\n const line = `║ ${displayTier.padEnd(10)} ${bar.padEnd(20)} ${data.percentage.toFixed(1).padStart(5)}% (${data.count})`;\n lines.push(line.padEnd(61) + \"║\");\n }\n }\n\n // Top models\n lines.push(\"╠════════════════════════════════════════════════════════════╣\");\n lines.push(\"║ Top Models: ║\");\n\n const sortedModels = Object.entries(stats.byModel)\n .sort((a, b) => b[1].count - a[1].count)\n .slice(0, 5);\n\n for (const [model, data] of sortedModels) {\n const shortModel = model.length > 25 ? model.slice(0, 22) + \"...\" : model;\n const line = `║ ${shortModel.padEnd(25)} ${data.count.toString().padStart(5)} reqs $${data.cost.toFixed(4)}`;\n lines.push(line.padEnd(61) + \"║\");\n }\n\n // Daily breakdown (last 7 days)\n if (stats.dailyBreakdown.length > 0) {\n lines.push(\"╠════════════════════════════════════════════════════════════╣\");\n lines.push(\"║ Daily Breakdown: ║\");\n lines.push(\"║ Date Requests Cost Saved ║\");\n\n for (const day of stats.dailyBreakdown.slice(-7)) {\n const saved = day.totalBaselineCost - day.totalCost;\n const line = `║ ${day.date} ${day.totalRequests.toString().padStart(6)} $${day.totalCost.toFixed(4).padStart(8)} $${saved.toFixed(4)}`;\n lines.push(line.padEnd(61) + \"║\");\n }\n }\n\n lines.push(\"╚════════════════════════════════════════════════════════════╝\");\n\n return lines.join(\"\\n\");\n}\n\n/**\n * Delete all usage log files, resetting stats to zero.\n */\nexport async function clearStats(): Promise<{ deletedFiles: number }> {\n try {\n const files = await readdir(LOG_DIR);\n const logFiles = files.filter((f) => f.startsWith(\"usage-\") && f.endsWith(\".jsonl\"));\n\n await Promise.all(logFiles.map((f) => unlink(join(LOG_DIR, f))));\n\n return { deletedFiles: logFiles.length };\n } catch {\n return { deletedFiles: 0 };\n }\n}\n","/**\n * Usage Logger\n *\n * Logs every LLM request as a JSON line to a daily log file.\n * Files: ~/.openclaw/ckcloud/logs/usage-YYYY-MM-DD.jsonl\n *\n * MVP: append-only JSON lines. No rotation, no cleanup.\n * Logging never breaks the request flow — all errors are swallowed.\n */\n\nimport { appendFile, mkdir } from \"node:fs/promises\";\nimport { join } from \"node:path\";\nimport { homedir } from \"node:os\";\n\nexport type UsageEntry = {\n timestamp: string;\n model: string;\n tier: string;\n cost: number;\n baselineCost: number;\n savings: number; // 0-1 percentage\n latencyMs: number;\n /** Input (prompt) tokens reported by the provider */\n inputTokens?: number;\n /** Partner service ID (e.g., \"x_users_lookup\") — only set for partner API calls */\n partnerId?: string;\n /** Partner service name (e.g., \"AttentionVC\") — only set for partner API calls */\n service?: string;\n};\n\nconst LOG_DIR = join(homedir(), \".openclaw\", \"ckcloud\", \"logs\");\nlet dirReady = false;\n\nasync function ensureDir(): Promise<void> {\n if (dirReady) return;\n await mkdir(LOG_DIR, { recursive: true });\n dirReady = true;\n}\n\n/**\n * Log a usage entry as a JSON line.\n */\nexport async function logUsage(entry: UsageEntry): Promise<void> {\n try {\n await ensureDir();\n const date = entry.timestamp.slice(0, 10); // YYYY-MM-DD\n const file = join(LOG_DIR, `usage-${date}.jsonl`);\n await appendFile(file, JSON.stringify(entry) + \"\\n\");\n } catch {\n // Never break the request flow\n }\n}\n","/**\n * Plugin logger module.\n * Provides a centralized logger that can be set to use OpenClaw's api.logger.\n * Defaults to console if not set.\n */\n\nimport type { PluginLogger } from \"./types.js\";\n\nlet pluginLogger: PluginLogger = console;\n\nexport function setPluginLogger(logger: PluginLogger): void {\n pluginLogger = logger ?? console;\n}\n\nexport function getPluginLogger(): PluginLogger {\n return pluginLogger;\n}\n\n// Convenience methods\nexport const logger = {\n debug: (message: string) => pluginLogger.debug?.(message),\n info: (message: string) => pluginLogger.info(message),\n warn: (message: string) => pluginLogger.warn(message),\n error: (message: string) => pluginLogger.error(message),\n};","/**\n * Session Persistence Store\n *\n * Tracks model selections per session to prevent model switching mid-task.\n * When a session is active, the router will continue using the same model\n * instead of re-routing each request.\n */\n\nimport { createHash } from \"node:crypto\";\n\nexport type SessionEntry = {\n model: string;\n tier: string;\n createdAt: number;\n lastUsedAt: number;\n requestCount: number;\n // --- Three-strike escalation ---\n recentHashes: string[]; // Sliding window of last 3 request content fingerprints\n strikes: number; // Consecutive similar request count\n escalated: boolean; // Whether session was already escalated via three-strike\n};\n\nexport type SessionConfig = {\n /** Enable session persistence (default: false) */\n enabled: boolean;\n /** Session timeout in ms (default: 30 minutes) */\n timeoutMs: number;\n /** Header name for session ID (default: X-Session-ID) */\n headerName: string;\n};\n\nexport const DEFAULT_SESSION_CONFIG: SessionConfig = {\n enabled: true,\n timeoutMs: 30 * 60 * 1000, // 30 minutes\n headerName: \"x-session-id\",\n};\n\n/**\n * Session persistence store for maintaining model selections.\n */\nexport class SessionStore {\n private sessions: Map<string, SessionEntry> = new Map();\n private config: SessionConfig;\n private cleanupInterval: ReturnType<typeof setInterval> | null = null;\n\n constructor(config: Partial<SessionConfig> = {}) {\n this.config = { ...DEFAULT_SESSION_CONFIG, ...config };\n\n // Start cleanup interval (every 5 minutes)\n if (this.config.enabled) {\n this.cleanupInterval = setInterval(() => this.cleanup(), 5 * 60 * 1000);\n }\n }\n\n /**\n * Get the pinned model for a session, if any.\n */\n getSession(sessionId: string): SessionEntry | undefined {\n if (!this.config.enabled || !sessionId) {\n return undefined;\n }\n\n const entry = this.sessions.get(sessionId);\n if (!entry) {\n return undefined;\n }\n\n // Check if session has expired\n const now = Date.now();\n if (now - entry.lastUsedAt > this.config.timeoutMs) {\n this.sessions.delete(sessionId);\n return undefined;\n }\n\n return entry;\n }\n\n /**\n * Pin a model to a session.\n */\n setSession(sessionId: string, model: string, tier: string): void {\n if (!this.config.enabled || !sessionId) {\n return;\n }\n\n const existing = this.sessions.get(sessionId);\n const now = Date.now();\n\n if (existing) {\n existing.lastUsedAt = now;\n existing.requestCount++;\n // Update model if different (e.g., fallback)\n if (existing.model !== model) {\n existing.model = model;\n existing.tier = tier;\n }\n } else {\n this.sessions.set(sessionId, {\n model,\n tier,\n createdAt: now,\n lastUsedAt: now,\n requestCount: 1,\n recentHashes: [],\n strikes: 0,\n escalated: false,\n });\n }\n }\n\n /**\n * Touch a session to extend its timeout.\n */\n touchSession(sessionId: string): void {\n if (!this.config.enabled || !sessionId) {\n return;\n }\n\n const entry = this.sessions.get(sessionId);\n if (entry) {\n entry.lastUsedAt = Date.now();\n entry.requestCount++;\n }\n }\n\n /**\n * Clear a specific session.\n */\n clearSession(sessionId: string): void {\n this.sessions.delete(sessionId);\n }\n\n /**\n * Clear all sessions.\n */\n clearAll(): void {\n this.sessions.clear();\n }\n\n /**\n * Get session stats for debugging.\n */\n getStats(): { count: number; sessions: Array<{ id: string; model: string; age: number }> } {\n const now = Date.now();\n const sessions = Array.from(this.sessions.entries()).map(([id, entry]) => ({\n id: id.slice(0, 8) + \"...\",\n model: entry.model,\n age: Math.round((now - entry.createdAt) / 1000),\n }));\n return { count: this.sessions.size, sessions };\n }\n\n /**\n * Clean up expired sessions.\n */\n private cleanup(): void {\n const now = Date.now();\n for (const [id, entry] of this.sessions) {\n if (now - entry.lastUsedAt > this.config.timeoutMs) {\n this.sessions.delete(id);\n }\n }\n }\n\n /**\n * Record a request content hash and detect repetitive patterns.\n * Returns true if escalation should be triggered (3+ consecutive similar requests).\n */\n recordRequestHash(sessionId: string, hash: string): boolean {\n const entry = this.sessions.get(sessionId);\n if (!entry) return false;\n\n const prev = entry.recentHashes;\n if (prev.length > 0 && prev[prev.length - 1] === hash) {\n entry.strikes++;\n } else {\n entry.strikes = 0;\n }\n\n entry.recentHashes.push(hash);\n if (entry.recentHashes.length > 3) {\n entry.recentHashes.shift();\n }\n\n return entry.strikes >= 2 && !entry.escalated;\n }\n\n /**\n * Escalate session to next tier. Returns the new model/tier or null if already at max.\n */\n escalateSession(\n sessionId: string,\n tierConfigs: Record<string, { primary: string; fallback: string[] }>,\n ): { model: string; tier: string } | null {\n const entry = this.sessions.get(sessionId);\n if (!entry) return null;\n\n const TIER_ORDER = [\"SIMPLE\", \"MEDIUM\", \"COMPLEX\", \"REASONING\"];\n const currentIdx = TIER_ORDER.indexOf(entry.tier);\n if (currentIdx < 0 || currentIdx >= TIER_ORDER.length - 1) return null;\n\n const nextTier = TIER_ORDER[currentIdx + 1];\n const nextConfig = tierConfigs[nextTier];\n if (!nextConfig) return null;\n\n entry.model = nextConfig.primary;\n entry.tier = nextTier;\n entry.strikes = 0;\n entry.escalated = true;\n\n return { model: nextConfig.primary, tier: nextTier };\n }\n\n /**\n * Stop the cleanup interval.\n */\n close(): void {\n if (this.cleanupInterval) {\n clearInterval(this.cleanupInterval);\n this.cleanupInterval = null;\n }\n }\n}\n\n/**\n * Generate a session ID from request headers or create a default.\n */\nexport function getSessionId(\n headers: Record<string, string | string[] | undefined>,\n headerName: string = DEFAULT_SESSION_CONFIG.headerName,\n): string | undefined {\n const value = headers[headerName] || headers[headerName.toLowerCase()];\n if (typeof value === \"string\" && value.length > 0) {\n return value;\n }\n if (Array.isArray(value) && value.length > 0) {\n return value[0];\n }\n return undefined;\n}\n\n/**\n * Derive a stable session ID from message content when no explicit session\n * header is provided. Uses the first user message as the conversation anchor —\n * same opening message = same session ID across all subsequent turns.\n *\n * This prevents model-switching mid-conversation even when OpenClaw doesn't\n * send an x-session-id header (which is the default OpenClaw behaviour).\n */\nexport function deriveSessionId(\n messages: Array<{ role: string; content: unknown }>,\n): string | undefined {\n const firstUser = messages.find((m) => m.role === \"user\");\n if (!firstUser) return undefined;\n\n const content =\n typeof firstUser.content === \"string\" ? firstUser.content : JSON.stringify(firstUser.content);\n\n // 8-char hex prefix of SHA-256 — short enough for logs, collision-resistant\n // enough for session tracking within a single gateway instance.\n return createHash(\"sha256\").update(content).digest(\"hex\").slice(0, 8);\n}\n\n/**\n * Generate a short hash fingerprint from request content.\n * Captures: last user message text + tool call names (if any).\n * Normalizes whitespace to avoid false negatives from minor formatting diffs.\n */\nexport function hashRequestContent(lastUserContent: string, toolCallNames?: string[]): string {\n const normalized = lastUserContent.replace(/\\s+/g, \" \").trim().slice(0, 500);\n const toolSuffix = toolCallNames?.length ? `|tools:${toolCallNames.sort().join(\",\")}` : \"\";\n return createHash(\"sha256\")\n .update(normalized + toolSuffix)\n .digest(\"hex\")\n .slice(0, 12);\n}\n","/**\n * Rule-Based Classifier (v2 — Weighted Scoring)\n *\n * Scores a request across 14 weighted dimensions and maps the aggregate\n * score to a tier using configurable boundaries. Confidence is calibrated\n * via sigmoid — low confidence triggers the fallback classifier.\n *\n * Handles 70-80% of requests in < 1ms with zero cost.\n */\n\nimport type { Tier, ScoringResult, ScoringConfig } from \"./types.js\";\n\ntype DimensionScore = { name: string; score: number; signal: string | null };\n\n// ─── Dimension Scorers ───\n// Each returns a score in [-1, 1] and an optional signal string.\n\nfunction scoreTokenCount(\n estimatedTokens: number,\n thresholds: { simple: number; complex: number },\n): DimensionScore {\n if (estimatedTokens < thresholds.simple) {\n return { name: \"tokenCount\", score: -1.0, signal: `short (${estimatedTokens} tokens)` };\n }\n if (estimatedTokens > thresholds.complex) {\n return { name: \"tokenCount\", score: 1.0, signal: `long (${estimatedTokens} tokens)` };\n }\n return { name: \"tokenCount\", score: 0, signal: null };\n}\n\nfunction scoreKeywordMatch(\n text: string,\n keywords: string[],\n name: string,\n signalLabel: string,\n thresholds: { low: number; high: number },\n scores: { none: number; low: number; high: number },\n): DimensionScore {\n const matches = keywords.filter((kw) => text.includes(kw.toLowerCase()));\n if (matches.length >= thresholds.high) {\n return {\n name,\n score: scores.high,\n signal: `${signalLabel} (${matches.slice(0, 3).join(\", \")})`,\n };\n }\n if (matches.length >= thresholds.low) {\n return {\n name,\n score: scores.low,\n signal: `${signalLabel} (${matches.slice(0, 3).join(\", \")})`,\n };\n }\n return { name, score: scores.none, signal: null };\n}\n\nfunction scoreMultiStep(text: string): DimensionScore {\n const patterns = [/first.*then/i, /step \\d/i, /\\d\\.\\s/];\n const hits = patterns.filter((p) => p.test(text));\n if (hits.length > 0) {\n return { name: \"multiStepPatterns\", score: 0.5, signal: \"multi-step\" };\n }\n return { name: \"multiStepPatterns\", score: 0, signal: null };\n}\n\nfunction scoreQuestionComplexity(prompt: string): DimensionScore {\n const count = (prompt.match(/\\?/g) || []).length;\n if (count > 3) {\n return { name: \"questionComplexity\", score: 0.5, signal: `${count} questions` };\n }\n return { name: \"questionComplexity\", score: 0, signal: null };\n}\n\n/**\n * Score agentic task indicators.\n * Returns agenticScore (0-1) based on keyword matches:\n * - 4+ matches = 1.0 (high agentic)\n * - 3 matches = 0.6 (moderate agentic, triggers auto-agentic mode)\n * - 1-2 matches = 0.2 (low agentic)\n *\n * Thresholds raised because common keywords were pruned from the list.\n */\nfunction scoreAgenticTask(\n text: string,\n keywords: string[],\n): { dimensionScore: DimensionScore; agenticScore: number } {\n let matchCount = 0;\n const signals: string[] = [];\n\n for (const keyword of keywords) {\n if (text.includes(keyword.toLowerCase())) {\n matchCount++;\n if (signals.length < 3) {\n signals.push(keyword);\n }\n }\n }\n\n // Threshold-based scoring (raised thresholds after keyword pruning)\n if (matchCount >= 4) {\n return {\n dimensionScore: {\n name: \"agenticTask\",\n score: 1.0,\n signal: `agentic (${signals.join(\", \")})`,\n },\n agenticScore: 1.0,\n };\n } else if (matchCount >= 3) {\n return {\n dimensionScore: {\n name: \"agenticTask\",\n score: 0.6,\n signal: `agentic (${signals.join(\", \")})`,\n },\n agenticScore: 0.6,\n };\n } else if (matchCount >= 1) {\n return {\n dimensionScore: {\n name: \"agenticTask\",\n score: 0.2,\n signal: `agentic-light (${signals.join(\", \")})`,\n },\n agenticScore: 0.2,\n };\n }\n\n return {\n dimensionScore: { name: \"agenticTask\", score: 0, signal: null },\n agenticScore: 0,\n };\n}\n\n// ─── Main Classifier ───\n\nexport function classifyByRules(\n prompt: string,\n systemPrompt: string | undefined,\n estimatedTokens: number,\n config: ScoringConfig,\n): ScoringResult {\n // Score against user prompt only — system prompts contain boilerplate keywords\n // (tool definitions, skill descriptions, behavioral rules) that dominate scoring\n // and make every request score identically. See GitHub issue #50.\n const userText = prompt.toLowerCase();\n\n // Score all 14 dimensions against user text only\n const dimensions: DimensionScore[] = [\n // Token count uses total estimated tokens (system + user) — context size matters for model selection\n scoreTokenCount(estimatedTokens, config.tokenCountThresholds),\n scoreKeywordMatch(\n userText,\n config.codeKeywords,\n \"codePresence\",\n \"code\",\n { low: 1, high: 2 },\n { none: 0, low: 0.5, high: 1.0 },\n ),\n scoreKeywordMatch(\n userText,\n config.reasoningKeywords,\n \"reasoningMarkers\",\n \"reasoning\",\n { low: 1, high: 2 },\n { none: 0, low: 0.7, high: 1.0 },\n ),\n scoreKeywordMatch(\n userText,\n config.technicalKeywords,\n \"technicalTerms\",\n \"technical\",\n { low: 2, high: 4 },\n { none: 0, low: 0.5, high: 1.0 },\n ),\n scoreKeywordMatch(\n userText,\n config.creativeKeywords,\n \"creativeMarkers\",\n \"creative\",\n { low: 1, high: 2 },\n { none: 0, low: 0.5, high: 0.7 },\n ),\n scoreKeywordMatch(\n userText,\n config.simpleKeywords,\n \"simpleIndicators\",\n \"simple\",\n { low: 1, high: 2 },\n { none: 0, low: -1.0, high: -1.0 },\n ),\n scoreMultiStep(userText),\n scoreQuestionComplexity(prompt),\n\n // 6 new dimensions\n scoreKeywordMatch(\n userText,\n config.imperativeVerbs,\n \"imperativeVerbs\",\n \"imperative\",\n { low: 1, high: 2 },\n { none: 0, low: 0.3, high: 0.5 },\n ),\n scoreKeywordMatch(\n userText,\n config.constraintIndicators,\n \"constraintCount\",\n \"constraints\",\n { low: 1, high: 3 },\n { none: 0, low: 0.3, high: 0.7 },\n ),\n scoreKeywordMatch(\n userText,\n config.outputFormatKeywords,\n \"outputFormat\",\n \"format\",\n { low: 1, high: 2 },\n { none: 0, low: 0.4, high: 0.7 },\n ),\n scoreKeywordMatch(\n userText,\n config.referenceKeywords,\n \"referenceComplexity\",\n \"references\",\n { low: 1, high: 2 },\n { none: 0, low: 0.3, high: 0.5 },\n ),\n scoreKeywordMatch(\n userText,\n config.negationKeywords,\n \"negationComplexity\",\n \"negation\",\n { low: 2, high: 3 },\n { none: 0, low: 0.3, high: 0.5 },\n ),\n scoreKeywordMatch(\n userText,\n config.domainSpecificKeywords,\n \"domainSpecificity\",\n \"domain-specific\",\n { low: 1, high: 2 },\n { none: 0, low: 0.5, high: 0.8 },\n ),\n ];\n\n // Score agentic task indicators — user prompt only\n // System prompt describes assistant behavior, not user's intent.\n // e.g. a coding assistant system prompt with \"edit files\" / \"fix bugs\" should NOT\n // force every request into agentic mode.\n const agenticResult = scoreAgenticTask(userText, config.agenticTaskKeywords);\n dimensions.push(agenticResult.dimensionScore);\n const agenticScore = agenticResult.agenticScore;\n\n // Collect signals\n const signals = dimensions.filter((d) => d.signal !== null).map((d) => d.signal!);\n\n // Compute weighted score\n const weights = config.dimensionWeights;\n let weightedScore = 0;\n for (const d of dimensions) {\n const w = weights[d.name] ?? 0;\n weightedScore += d.score * w;\n }\n\n // Count reasoning markers for override — only check USER prompt, not system prompt\n // This prevents system prompts with \"step by step\" from triggering REASONING for simple queries\n const reasoningMatches = config.reasoningKeywords.filter((kw) =>\n userText.includes(kw.toLowerCase()),\n );\n\n // Direct reasoning override: 2+ reasoning markers = high confidence REASONING\n if (reasoningMatches.length >= 2) {\n const confidence = calibrateConfidence(\n Math.max(weightedScore, 0.3), // ensure positive for confidence calc\n config.confidenceSteepness,\n );\n return {\n score: weightedScore,\n tier: \"REASONING\",\n confidence: Math.max(confidence, 0.85),\n signals,\n agenticScore,\n dimensions,\n };\n }\n\n // Map weighted score to tier using boundaries\n const { simpleMedium, mediumComplex, complexReasoning } = config.tierBoundaries;\n let tier: Tier;\n let distanceFromBoundary: number;\n\n if (weightedScore < simpleMedium) {\n tier = \"SIMPLE\";\n distanceFromBoundary = simpleMedium - weightedScore;\n } else if (weightedScore < mediumComplex) {\n tier = \"MEDIUM\";\n distanceFromBoundary = Math.min(weightedScore - simpleMedium, mediumComplex - weightedScore);\n } else if (weightedScore < complexReasoning) {\n tier = \"COMPLEX\";\n distanceFromBoundary = Math.min(\n weightedScore - mediumComplex,\n complexReasoning - weightedScore,\n );\n } else {\n tier = \"REASONING\";\n distanceFromBoundary = weightedScore - complexReasoning;\n }\n\n // Calibrate confidence via sigmoid of distance from nearest boundary\n const confidence = calibrateConfidence(distanceFromBoundary, config.confidenceSteepness);\n\n // If confidence is below threshold → ambiguous\n if (confidence < config.confidenceThreshold) {\n return { score: weightedScore, tier: null, confidence, signals, agenticScore, dimensions };\n }\n\n return { score: weightedScore, tier, confidence, signals, agenticScore, dimensions };\n}\n\n/**\n * Sigmoid confidence calibration.\n * Maps distance from tier boundary to [0.5, 1.0] confidence range.\n */\nfunction calibrateConfidence(distance: number, steepness: number): number {\n return 1 / (1 + Math.exp(-steepness * distance));\n}\n","/**\n * Tier → Model Selection\n *\n * Maps a classification tier to the cheapest capable model.\n * Builds RoutingDecision metadata with cost estimates and savings.\n */\n\nimport type { Tier, TierConfig, RoutingDecision } from \"./types.js\";\n\nexport type ModelPricing = {\n inputPrice: number; // per 1M tokens\n outputPrice: number; // per 1M tokens\n};\n\nconst BASELINE_MODEL_ID = \"anthropic/claude-opus-4.6\";\n\n// Hardcoded fallback: Claude Opus 4.6 pricing (per 1M tokens)\n// Used when baseline model not found in dynamic pricing map\nconst BASELINE_INPUT_PRICE = 5.0;\nconst BASELINE_OUTPUT_PRICE = 25.0;\n\n/**\n * Select the primary model for a tier and build the RoutingDecision.\n */\nexport function selectModel(\n tier: Tier,\n confidence: number,\n method: \"rules\" | \"llm\",\n reasoning: string,\n tierConfigs: Record<Tier, TierConfig>,\n modelPricing: Map<string, ModelPricing>,\n estimatedInputTokens: number,\n maxOutputTokens: number,\n routingProfile?: \"free\" | \"eco\" | \"auto\" | \"premium\",\n agenticScore?: number,\n): RoutingDecision {\n const tierConfig = tierConfigs[tier];\n const model = tierConfig.primary;\n const pricing = modelPricing.get(model);\n\n // Defensive: guard against undefined price fields (not just undefined pricing)\n const inputPrice = pricing?.inputPrice ?? 0;\n const outputPrice = pricing?.outputPrice ?? 0;\n const inputCost = (estimatedInputTokens / 1_000_000) * inputPrice;\n const outputCost = (maxOutputTokens / 1_000_000) * outputPrice;\n const costEstimate = inputCost + outputCost;\n\n // Baseline: what Claude Opus 4.5 would cost (the premium reference)\n const opusPricing = modelPricing.get(BASELINE_MODEL_ID);\n const opusInputPrice = opusPricing?.inputPrice ?? BASELINE_INPUT_PRICE;\n const opusOutputPrice = opusPricing?.outputPrice ?? BASELINE_OUTPUT_PRICE;\n const baselineInput = (estimatedInputTokens / 1_000_000) * opusInputPrice;\n const baselineOutput = (maxOutputTokens / 1_000_000) * opusOutputPrice;\n const baselineCost = baselineInput + baselineOutput;\n\n // Premium profile doesn't calculate savings (it's about quality, not cost)\n const savings =\n routingProfile === \"premium\"\n ? 0\n : baselineCost > 0\n ? Math.max(0, (baselineCost - costEstimate) / baselineCost)\n : 0;\n\n return {\n model,\n tier,\n confidence,\n method,\n reasoning,\n costEstimate,\n baselineCost,\n savings,\n ...(agenticScore !== undefined && { agenticScore }),\n };\n}\n\n/**\n * Get the ordered fallback chain for a tier: [primary, ...fallbacks].\n */\nexport function getFallbackChain(tier: Tier, tierConfigs: Record<Tier, TierConfig>): string[] {\n const config = tierConfigs[tier];\n return [config.primary, ...config.fallback];\n}\n\n/**\n * Calculate cost for a specific model (used when fallback model is used).\n * Returns updated cost fields for RoutingDecision.\n */\nexport function calculateModelCost(\n model: string,\n modelPricing: Map<string, ModelPricing>,\n estimatedInputTokens: number,\n maxOutputTokens: number,\n routingProfile?: \"free\" | \"eco\" | \"auto\" | \"premium\",\n): { costEstimate: number; baselineCost: number; savings: number } {\n const pricing = modelPricing.get(model);\n\n // Defensive: guard against undefined price fields (not just undefined pricing)\n const inputPrice = pricing?.inputPrice ?? 0;\n const outputPrice = pricing?.outputPrice ?? 0;\n const inputCost = (estimatedInputTokens / 1_000_000) * inputPrice;\n const outputCost = (maxOutputTokens / 1_000_000) * outputPrice;\n const costEstimate = inputCost + outputCost;\n\n // Baseline: what Claude Opus 4.5 would cost (the premium reference)\n const opusPricing = modelPricing.get(BASELINE_MODEL_ID);\n const opusInputPrice = opusPricing?.inputPrice ?? BASELINE_INPUT_PRICE;\n const opusOutputPrice = opusPricing?.outputPrice ?? BASELINE_OUTPUT_PRICE;\n const baselineInput = (estimatedInputTokens / 1_000_000) * opusInputPrice;\n const baselineOutput = (maxOutputTokens / 1_000_000) * opusOutputPrice;\n const baselineCost = baselineInput + baselineOutput;\n\n // Premium profile doesn't calculate savings (it's about quality, not cost)\n const savings =\n routingProfile === \"premium\"\n ? 0\n : baselineCost > 0\n ? Math.max(0, (baselineCost - costEstimate) / baselineCost)\n : 0;\n\n return { costEstimate, baselineCost, savings };\n}\n\n/**\n * Filter a model list to only those that support tool calling.\n * When hasTools is false, returns the list unchanged.\n * When all models lack tool calling support, returns the full list as a fallback\n * (better to let the API error than produce an empty chain).\n */\nexport function filterByToolCalling(\n models: string[],\n hasTools: boolean,\n supportsToolCalling: (modelId: string) => boolean,\n): string[] {\n if (!hasTools) return models;\n const filtered = models.filter(supportsToolCalling);\n return filtered.length > 0 ? filtered : models;\n}\n\n/**\n * Filter a model list to only those that support vision (image inputs).\n * When hasVision is false, returns the list unchanged.\n * When all models lack vision support, returns the full list as a fallback\n * (better to let the API error than produce an empty chain).\n */\nexport function filterByVision(\n models: string[],\n hasVision: boolean,\n supportsVision: (modelId: string) => boolean,\n): string[] {\n if (!hasVision) return models;\n const filtered = models.filter(supportsVision);\n return filtered.length > 0 ? filtered : models;\n}\n\n/**\n * Get the fallback chain filtered by context length.\n * Only returns models that can handle the estimated total context.\n *\n * @param tier - The tier to get fallback chain for\n * @param tierConfigs - Tier configurations\n * @param estimatedTotalTokens - Estimated total context (input + output)\n * @param getContextWindow - Function to get context window for a model ID\n * @returns Filtered list of models that can handle the context\n */\nexport function getFallbackChainFiltered(\n tier: Tier,\n tierConfigs: Record<Tier, TierConfig>,\n estimatedTotalTokens: number,\n getContextWindow: (modelId: string) => number | undefined,\n): string[] {\n const fullChain = getFallbackChain(tier, tierConfigs);\n\n // Filter to models that can handle the context\n const filtered = fullChain.filter((modelId) => {\n const contextWindow = getContextWindow(modelId);\n if (contextWindow === undefined) {\n // Unknown model - include it (let API reject if needed)\n return true;\n }\n // Add 10% buffer for safety\n return contextWindow >= estimatedTotalTokens * 1.1;\n });\n\n // If all models filtered out, return the original chain\n // (let the API error out - better than no options)\n if (filtered.length === 0) {\n return fullChain;\n }\n\n return filtered;\n}\n","/**\n * Default Routing Config\n *\n * All routing parameters as a TypeScript constant.\n * Operators override via openclaw.yaml plugin config.\n *\n * Scoring uses 14 weighted dimensions with sigmoid confidence calibration.\n */\n\nimport type { RoutingConfig } from \"./types.js\";\n\nexport const DEFAULT_ROUTING_CONFIG: RoutingConfig = {\n version: \"2.0\",\n\n classifier: {\n llmModel: \"google/gemini-2.5-flash\",\n llmMaxTokens: 10,\n llmTemperature: 0,\n promptTruncationChars: 500,\n cacheTtlMs: 3_600_000, // 1 hour\n },\n\n scoring: {\n tokenCountThresholds: { simple: 50, complex: 500 },\n\n // Multilingual keywords: EN + ZH + JA + RU + DE + ES + PT + KO + AR\n codeKeywords: [\n // English\n \"function\",\n \"class\",\n \"import\",\n \"def\",\n \"SELECT\",\n \"async\",\n \"await\",\n \"const\",\n \"let\",\n \"var\",\n \"return\",\n \"```\",\n // Chinese\n \"函数\",\n \"类\",\n \"导入\",\n \"定义\",\n \"查询\",\n \"异步\",\n \"等待\",\n \"常量\",\n \"变量\",\n \"返回\",\n // Japanese\n \"関数\",\n \"クラス\",\n \"インポート\",\n \"非同期\",\n \"定数\",\n \"変数\",\n // Russian\n \"функция\",\n \"класс\",\n \"импорт\",\n \"определ\",\n \"запрос\",\n \"асинхронный\",\n \"ожидать\",\n \"константа\",\n \"переменная\",\n \"вернуть\",\n // German\n \"funktion\",\n \"klasse\",\n \"importieren\",\n \"definieren\",\n \"abfrage\",\n \"asynchron\",\n \"erwarten\",\n \"konstante\",\n \"variable\",\n \"zurückgeben\",\n // Spanish\n \"función\",\n \"clase\",\n \"importar\",\n \"definir\",\n \"consulta\",\n \"asíncrono\",\n \"esperar\",\n \"constante\",\n \"variable\",\n \"retornar\",\n // Portuguese\n \"função\",\n \"classe\",\n \"importar\",\n \"definir\",\n \"consulta\",\n \"assíncrono\",\n \"aguardar\",\n \"constante\",\n \"variável\",\n \"retornar\",\n // Korean\n \"함수\",\n \"클래스\",\n \"가져오기\",\n \"정의\",\n \"쿼리\",\n \"비동기\",\n \"대기\",\n \"상수\",\n \"변수\",\n \"반환\",\n // Arabic\n \"دالة\",\n \"فئة\",\n \"استيراد\",\n \"تعريف\",\n \"استعلام\",\n \"غير متزامن\",\n \"انتظار\",\n \"ثابت\",\n \"متغير\",\n \"إرجاع\",\n ],\n reasoningKeywords: [\n // English\n \"prove\",\n \"theorem\",\n \"derive\",\n \"step by step\",\n \"chain of thought\",\n \"formally\",\n \"mathematical\",\n \"proof\",\n \"logically\",\n // Chinese\n \"证明\",\n \"定理\",\n \"推导\",\n \"逐步\",\n \"思维链\",\n \"形式化\",\n \"数学\",\n \"逻辑\",\n // Japanese\n \"証明\",\n \"定理\",\n \"導出\",\n \"ステップバイステップ\",\n \"論理的\",\n // Russian\n \"доказать\",\n \"докажи\",\n \"доказательств\",\n \"теорема\",\n \"вывести\",\n \"шаг за шагом\",\n \"пошагово\",\n \"поэтапно\",\n \"цепочка рассуждений\",\n \"рассуждени\",\n \"формально\",\n \"математически\",\n \"логически\",\n // German\n \"beweisen\",\n \"beweis\",\n \"theorem\",\n \"ableiten\",\n \"schritt für schritt\",\n \"gedankenkette\",\n \"formal\",\n \"mathematisch\",\n \"logisch\",\n // Spanish\n \"demostrar\",\n \"teorema\",\n \"derivar\",\n \"paso a paso\",\n \"cadena de pensamiento\",\n \"formalmente\",\n \"matemático\",\n \"prueba\",\n \"lógicamente\",\n // Portuguese\n \"provar\",\n \"teorema\",\n \"derivar\",\n \"passo a passo\",\n \"cadeia de pensamento\",\n \"formalmente\",\n \"matemático\",\n \"prova\",\n \"logicamente\",\n // Korean\n \"증명\",\n \"정리\",\n \"도출\",\n \"단계별\",\n \"사고의 연쇄\",\n \"형식적\",\n \"수학적\",\n \"논리적\",\n // Arabic\n \"إثبات\",\n \"نظرية\",\n \"اشتقاق\",\n \"خطوة بخطوة\",\n \"سلسلة التفكير\",\n \"رسمياً\",\n \"رياضي\",\n \"برهان\",\n \"منطقياً\",\n ],\n simpleKeywords: [\n // English\n \"what is\",\n \"define\",\n \"translate\",\n \"hello\",\n \"yes or no\",\n \"capital of\",\n \"how old\",\n \"who is\",\n \"when was\",\n // Chinese\n \"什么是\",\n \"定义\",\n \"翻译\",\n \"你好\",\n \"是否\",\n \"首都\",\n \"多大\",\n \"谁是\",\n \"何时\",\n // Japanese\n \"とは\",\n \"定義\",\n \"翻訳\",\n \"こんにちは\",\n \"はいかいいえ\",\n \"首都\",\n \"誰\",\n // Russian\n \"что такое\",\n \"определение\",\n \"перевести\",\n \"переведи\",\n \"привет\",\n \"да или нет\",\n \"столица\",\n \"сколько лет\",\n \"кто такой\",\n \"когда\",\n \"объясни\",\n // German\n \"was ist\",\n \"definiere\",\n \"übersetze\",\n \"hallo\",\n \"ja oder nein\",\n \"hauptstadt\",\n \"wie alt\",\n \"wer ist\",\n \"wann\",\n \"erkläre\",\n // Spanish\n \"qué es\",\n \"definir\",\n \"traducir\",\n \"hola\",\n \"sí o no\",\n \"capital de\",\n \"cuántos años\",\n \"quién es\",\n \"cuándo\",\n // Portuguese\n \"o que é\",\n \"definir\",\n \"traduzir\",\n \"olá\",\n \"sim ou não\",\n \"capital de\",\n \"quantos anos\",\n \"quem é\",\n \"quando\",\n // Korean\n \"무엇\",\n \"정의\",\n \"번역\",\n \"안녕하세요\",\n \"예 또는 아니오\",\n \"수도\",\n \"누구\",\n \"언제\",\n // Arabic\n \"ما هو\",\n \"تعريف\",\n \"ترجم\",\n \"مرحبا\",\n \"نعم أو لا\",\n \"عاصمة\",\n \"من هو\",\n \"متى\",\n ],\n technicalKeywords: [\n // English\n \"algorithm\",\n \"optimize\",\n \"architecture\",\n \"distributed\",\n \"kubernetes\",\n \"microservice\",\n \"database\",\n \"infrastructure\",\n // Chinese\n \"算法\",\n \"优化\",\n \"架构\",\n \"分布式\",\n \"微服务\",\n \"数据库\",\n \"基础设施\",\n // Japanese\n \"アルゴリズム\",\n \"最適化\",\n \"アーキテクチャ\",\n \"分散\",\n \"マイクロサービス\",\n \"データベース\",\n // Russian\n \"алгоритм\",\n \"оптимизировать\",\n \"оптимизаци\",\n \"оптимизируй\",\n \"архитектура\",\n \"распределённый\",\n \"микросервис\",\n \"база данных\",\n \"инфраструктура\",\n // German\n \"algorithmus\",\n \"optimieren\",\n \"architektur\",\n \"verteilt\",\n \"kubernetes\",\n \"mikroservice\",\n \"datenbank\",\n \"infrastruktur\",\n // Spanish\n \"algoritmo\",\n \"optimizar\",\n \"arquitectura\",\n \"distribuido\",\n \"microservicio\",\n \"base de datos\",\n \"infraestructura\",\n // Portuguese\n \"algoritmo\",\n \"otimizar\",\n \"arquitetura\",\n \"distribuído\",\n \"microsserviço\",\n \"banco de dados\",\n \"infraestrutura\",\n // Korean\n \"알고리즘\",\n \"최적화\",\n \"아키텍처\",\n \"분산\",\n \"마이크로서비스\",\n \"데이터베이스\",\n \"인프라\",\n // Arabic\n \"خوارزمية\",\n \"تحسين\",\n \"بنية\",\n \"موزع\",\n \"خدمة مصغرة\",\n \"قاعدة بيانات\",\n \"بنية تحتية\",\n ],\n creativeKeywords: [\n // English\n \"story\",\n \"poem\",\n \"compose\",\n \"brainstorm\",\n \"creative\",\n \"imagine\",\n \"write a\",\n // Chinese\n \"故事\",\n \"诗\",\n \"创作\",\n \"头脑风暴\",\n \"创意\",\n \"想象\",\n \"写一个\",\n // Japanese\n \"物語\",\n \"詩\",\n \"作曲\",\n \"ブレインストーム\",\n \"創造的\",\n \"想像\",\n // Russian\n \"история\",\n \"рассказ\",\n \"стихотворение\",\n \"сочинить\",\n \"сочини\",\n \"мозговой штурм\",\n \"творческий\",\n \"представить\",\n \"придумай\",\n \"напиши\",\n // German\n \"geschichte\",\n \"gedicht\",\n \"komponieren\",\n \"brainstorming\",\n \"kreativ\",\n \"vorstellen\",\n \"schreibe\",\n \"erzählung\",\n // Spanish\n \"historia\",\n \"poema\",\n \"componer\",\n \"lluvia de ideas\",\n \"creativo\",\n \"imaginar\",\n \"escribe\",\n // Portuguese\n \"história\",\n \"poema\",\n \"compor\",\n \"criativo\",\n \"imaginar\",\n \"escreva\",\n // Korean\n \"이야기\",\n \"시\",\n \"작곡\",\n \"브레인스토밍\",\n \"창의적\",\n \"상상\",\n \"작성\",\n // Arabic\n \"قصة\",\n \"قصيدة\",\n \"تأليف\",\n \"عصف ذهني\",\n \"إبداعي\",\n \"تخيل\",\n \"اكتب\",\n ],\n\n // New dimension keyword lists (multilingual)\n imperativeVerbs: [\n // English\n \"build\",\n \"create\",\n \"implement\",\n \"design\",\n \"develop\",\n \"construct\",\n \"generate\",\n \"deploy\",\n \"configure\",\n \"set up\",\n // Chinese\n \"构建\",\n \"创建\",\n \"实现\",\n \"设计\",\n \"开发\",\n \"生成\",\n \"部署\",\n \"配置\",\n \"设置\",\n // Japanese\n \"構築\",\n \"作成\",\n \"実装\",\n \"設計\",\n \"開発\",\n \"生成\",\n \"デプロイ\",\n \"設定\",\n // Russian\n \"построить\",\n \"построй\",\n \"создать\",\n \"создай\",\n \"реализовать\",\n \"реализуй\",\n \"спроектировать\",\n \"разработать\",\n \"разработай\",\n \"сконструировать\",\n \"сгенерировать\",\n \"сгенерируй\",\n \"развернуть\",\n \"разверни\",\n \"настроить\",\n \"настрой\",\n // German\n \"erstellen\",\n \"bauen\",\n \"implementieren\",\n \"entwerfen\",\n \"entwickeln\",\n \"konstruieren\",\n \"generieren\",\n \"bereitstellen\",\n \"konfigurieren\",\n \"einrichten\",\n // Spanish\n \"construir\",\n \"crear\",\n \"implementar\",\n \"diseñar\",\n \"desarrollar\",\n \"generar\",\n \"desplegar\",\n \"configurar\",\n // Portuguese\n \"construir\",\n \"criar\",\n \"implementar\",\n \"projetar\",\n \"desenvolver\",\n \"gerar\",\n \"implantar\",\n \"configurar\",\n // Korean\n \"구축\",\n \"생성\",\n \"구현\",\n \"설계\",\n \"개발\",\n \"배포\",\n \"설정\",\n // Arabic\n \"بناء\",\n \"إنشاء\",\n \"تنفيذ\",\n \"تصميم\",\n \"تطوير\",\n \"توليد\",\n \"نشر\",\n \"إعداد\",\n ],\n constraintIndicators: [\n // English\n \"under\",\n \"at most\",\n \"at least\",\n \"within\",\n \"no more than\",\n \"o(\",\n \"maximum\",\n \"minimum\",\n \"limit\",\n \"budget\",\n // Chinese\n \"不超过\",\n \"至少\",\n \"最多\",\n \"在内\",\n \"最大\",\n \"最小\",\n \"限制\",\n \"预算\",\n // Japanese\n \"以下\",\n \"最大\",\n \"最小\",\n \"制限\",\n \"予算\",\n // Russian\n \"не более\",\n \"не менее\",\n \"как минимум\",\n \"в пределах\",\n \"максимум\",\n \"минимум\",\n \"ограничение\",\n \"бюджет\",\n // German\n \"höchstens\",\n \"mindestens\",\n \"innerhalb\",\n \"nicht mehr als\",\n \"maximal\",\n \"minimal\",\n \"grenze\",\n \"budget\",\n // Spanish\n \"como máximo\",\n \"al menos\",\n \"dentro de\",\n \"no más de\",\n \"máximo\",\n \"mínimo\",\n \"límite\",\n \"presupuesto\",\n // Portuguese\n \"no máximo\",\n \"pelo menos\",\n \"dentro de\",\n \"não mais que\",\n \"máximo\",\n \"mínimo\",\n \"limite\",\n \"orçamento\",\n // Korean\n \"이하\",\n \"이상\",\n \"최대\",\n \"최소\",\n \"제한\",\n \"예산\",\n // Arabic\n \"على الأكثر\",\n \"على الأقل\",\n \"ضمن\",\n \"لا يزيد عن\",\n \"أقصى\",\n \"أدنى\",\n \"حد\",\n \"ميزانية\",\n ],\n outputFormatKeywords: [\n // English\n \"json\",\n \"yaml\",\n \"xml\",\n \"table\",\n \"csv\",\n \"markdown\",\n \"schema\",\n \"format as\",\n \"structured\",\n // Chinese\n \"表格\",\n \"格式化为\",\n \"结构化\",\n // Japanese\n \"テーブル\",\n \"フォーマット\",\n \"構造化\",\n // Russian\n \"таблица\",\n \"форматировать как\",\n \"структурированный\",\n // German\n \"tabelle\",\n \"formatieren als\",\n \"strukturiert\",\n // Spanish\n \"tabla\",\n \"formatear como\",\n \"estructurado\",\n // Portuguese\n \"tabela\",\n \"formatar como\",\n \"estruturado\",\n // Korean\n \"테이블\",\n \"형식\",\n \"구조화\",\n // Arabic\n \"جدول\",\n \"تنسيق\",\n \"منظم\",\n ],\n referenceKeywords: [\n // English\n \"above\",\n \"below\",\n \"previous\",\n \"following\",\n \"the docs\",\n \"the api\",\n \"the code\",\n \"earlier\",\n \"attached\",\n // Chinese\n \"上面\",\n \"下面\",\n \"之前\",\n \"接下来\",\n \"文档\",\n \"代码\",\n \"附件\",\n // Japanese\n \"上記\",\n \"下記\",\n \"前の\",\n \"次の\",\n \"ドキュメント\",\n \"コード\",\n // Russian\n \"выше\",\n \"ниже\",\n \"предыдущий\",\n \"следующий\",\n \"документация\",\n \"код\",\n \"ранее\",\n \"вложение\",\n // German\n \"oben\",\n \"unten\",\n \"vorherige\",\n \"folgende\",\n \"dokumentation\",\n \"der code\",\n \"früher\",\n \"anhang\",\n // Spanish\n \"arriba\",\n \"abajo\",\n \"anterior\",\n \"siguiente\",\n \"documentación\",\n \"el código\",\n \"adjunto\",\n // Portuguese\n \"acima\",\n \"abaixo\",\n \"anterior\",\n \"seguinte\",\n \"documentação\",\n \"o código\",\n \"anexo\",\n // Korean\n \"위\",\n \"아래\",\n \"이전\",\n \"다음\",\n \"문서\",\n \"코드\",\n \"첨부\",\n // Arabic\n \"أعلاه\",\n \"أدناه\",\n \"السابق\",\n \"التالي\",\n \"الوثائق\",\n \"الكود\",\n \"مرفق\",\n ],\n negationKeywords: [\n // English\n \"don't\",\n \"do not\",\n \"avoid\",\n \"never\",\n \"without\",\n \"except\",\n \"exclude\",\n \"no longer\",\n // Chinese\n \"不要\",\n \"避免\",\n \"从不\",\n \"没有\",\n \"除了\",\n \"排除\",\n // Japanese\n \"しないで\",\n \"避ける\",\n \"決して\",\n \"なしで\",\n \"除く\",\n // Russian\n \"не делай\",\n \"не надо\",\n \"нельзя\",\n \"избегать\",\n \"никогда\",\n \"без\",\n \"кроме\",\n \"исключить\",\n \"больше не\",\n // German\n \"nicht\",\n \"vermeide\",\n \"niemals\",\n \"ohne\",\n \"außer\",\n \"ausschließen\",\n \"nicht mehr\",\n // Spanish\n \"no hagas\",\n \"evitar\",\n \"nunca\",\n \"sin\",\n \"excepto\",\n \"excluir\",\n // Portuguese\n \"não faça\",\n \"evitar\",\n \"nunca\",\n \"sem\",\n \"exceto\",\n \"excluir\",\n // Korean\n \"하지 마\",\n \"피하다\",\n \"절대\",\n \"없이\",\n \"제외\",\n // Arabic\n \"لا تفعل\",\n \"تجنب\",\n \"أبداً\",\n \"بدون\",\n \"باستثناء\",\n \"استبعاد\",\n ],\n domainSpecificKeywords: [\n // English\n \"quantum\",\n \"fpga\",\n \"vlsi\",\n \"risc-v\",\n \"asic\",\n \"photonics\",\n \"genomics\",\n \"proteomics\",\n \"topological\",\n \"homomorphic\",\n \"zero-knowledge\",\n \"lattice-based\",\n // Chinese\n \"量子\",\n \"光子学\",\n \"基因组学\",\n \"蛋白质组学\",\n \"拓扑\",\n \"同态\",\n \"零知识\",\n \"格密码\",\n // Japanese\n \"量子\",\n \"フォトニクス\",\n \"ゲノミクス\",\n \"トポロジカル\",\n // Russian\n \"квантовый\",\n \"фотоника\",\n \"геномика\",\n \"протеомика\",\n \"топологический\",\n \"гомоморфный\",\n \"с нулевым разглашением\",\n \"на основе решёток\",\n // German\n \"quanten\",\n \"photonik\",\n \"genomik\",\n \"proteomik\",\n \"topologisch\",\n \"homomorph\",\n \"zero-knowledge\",\n \"gitterbasiert\",\n // Spanish\n \"cuántico\",\n \"fotónica\",\n \"genómica\",\n \"proteómica\",\n \"topológico\",\n \"homomórfico\",\n // Portuguese\n \"quântico\",\n \"fotônica\",\n \"genômica\",\n \"proteômica\",\n \"topológico\",\n \"homomórfico\",\n // Korean\n \"양자\",\n \"포토닉스\",\n \"유전체학\",\n \"위상\",\n \"동형\",\n // Arabic\n \"كمي\",\n \"ضوئيات\",\n \"جينوميات\",\n \"طوبولوجي\",\n \"تماثلي\",\n ],\n\n // Agentic task keywords - file ops, execution, multi-step, iterative work\n // Pruned: removed overly common words like \"then\", \"first\", \"run\", \"test\", \"build\"\n agenticTaskKeywords: [\n // English - File operations (clearly agentic)\n \"read file\",\n \"read the file\",\n \"look at\",\n \"check the\",\n \"open the\",\n \"edit\",\n \"modify\",\n \"update the\",\n \"change the\",\n \"write to\",\n \"create file\",\n // English - Execution (specific commands only)\n \"execute\",\n \"deploy\",\n \"install\",\n \"npm\",\n \"pip\",\n \"compile\",\n // English - Multi-step patterns (specific only)\n \"after that\",\n \"and also\",\n \"once done\",\n \"step 1\",\n \"step 2\",\n // English - Iterative work\n \"fix\",\n \"debug\",\n \"until it works\",\n \"keep trying\",\n \"iterate\",\n \"make sure\",\n \"verify\",\n \"confirm\",\n // Chinese (keep specific ones)\n \"读取文件\",\n \"查看\",\n \"打开\",\n \"编辑\",\n \"修改\",\n \"更新\",\n \"创建\",\n \"执行\",\n \"部署\",\n \"安装\",\n \"第一步\",\n \"第二步\",\n \"修复\",\n \"调试\",\n \"直到\",\n \"确认\",\n \"验证\",\n // Spanish\n \"leer archivo\",\n \"editar\",\n \"modificar\",\n \"actualizar\",\n \"ejecutar\",\n \"desplegar\",\n \"instalar\",\n \"paso 1\",\n \"paso 2\",\n \"arreglar\",\n \"depurar\",\n \"verificar\",\n // Portuguese\n \"ler arquivo\",\n \"editar\",\n \"modificar\",\n \"atualizar\",\n \"executar\",\n \"implantar\",\n \"instalar\",\n \"passo 1\",\n \"passo 2\",\n \"corrigir\",\n \"depurar\",\n \"verificar\",\n // Korean\n \"파일 읽기\",\n \"편집\",\n \"수정\",\n \"업데이트\",\n \"실행\",\n \"배포\",\n \"설치\",\n \"단계 1\",\n \"단계 2\",\n \"디버그\",\n \"확인\",\n // Arabic\n \"قراءة ملف\",\n \"تحرير\",\n \"تعديل\",\n \"تحديث\",\n \"تنفيذ\",\n \"نشر\",\n \"تثبيت\",\n \"الخطوة 1\",\n \"الخطوة 2\",\n \"إصلاح\",\n \"تصحيح\",\n \"تحقق\",\n ],\n\n // Dimension weights (sum to 1.0)\n dimensionWeights: {\n tokenCount: 0.08,\n codePresence: 0.15,\n reasoningMarkers: 0.18,\n technicalTerms: 0.1,\n creativeMarkers: 0.05,\n simpleIndicators: 0.02, // Reduced from 0.12 to make room for agenticTask\n multiStepPatterns: 0.12,\n questionComplexity: 0.05,\n imperativeVerbs: 0.03,\n constraintCount: 0.04,\n outputFormat: 0.03,\n referenceComplexity: 0.02,\n negationComplexity: 0.01,\n domainSpecificity: 0.02,\n agenticTask: 0.04, // Reduced - agentic signals influence tier selection, not dominate it\n },\n\n // Tier boundaries on weighted score axis\n tierBoundaries: {\n simpleMedium: 0.0,\n mediumComplex: 0.3, // Raised from 0.18 - prevent simple tasks from reaching expensive COMPLEX tier\n complexReasoning: 0.5, // Raised from 0.4 - reserve for true reasoning tasks\n },\n\n // Sigmoid steepness for confidence calibration\n confidenceSteepness: 12,\n // Below this confidence → ambiguous (null tier)\n confidenceThreshold: 0.7,\n },\n\n // Auto (balanced) tier configs - current default smart routing\n tiers: {\n SIMPLE: {\n primary: \"moonshot/kimi-k2.5\", // $0.60 / $3.00\n fallback: [\n \"openai/gpt-5-nano\", // $0.05 / $0.40\n \"gpt-4.1-nano\", // $0.10 / $0.40\n \"gemini-2.5-flash\", // $0.10 / $0.40\n \"gpt-4o-mini\", // $0.15 / $0.60\n \"openai/gpt-5-mini\", // $0.25 / $2.00\n \"deepseek-ai/DeepSeek-V3.2\", // $0.28 / $0.42\n \"MiniMax-M2.5\", // $0.30 / $1.20\n \"gemini-2.5-flash\", // $0.30 / $2.50\n ],\n },\n\n MEDIUM: {\n primary: \"gpt-4.1-mini\", // $0.40 / $1.60\n fallback: [\n \"zai-org/glm-5\", // $1.00 / $3.20\n \"glm-5-turbo\", // $1.20 / $4.00\n \"openai/gpt-4.1\", // $2.00 / $8.00\n \"o3-2025-04-16\", // $2.00 / $8.00\n \"gemini-3-pro-preview\", // $2.00 / $12.00\n \"gemini-3.1-pro-preview\", // $2.00 / $12.00\n ],\n },\n\n COMPLEX: {\n primary: \"gpt-5.4\", // $2.50 / $15.00\n fallback: [\n \"openai/gpt-5.2\", // $1.75 / $14.00\n \"gpt-5.3-codex\", // $1.75 / $14.00\n \"openai/gpt-4o\", // $2.50 / $10.00\n \"claude-sonnet-4-6\", // $3.00 / $15.00\n \"claude-opus-4-5-20251101\", // $5.00 / $25.00\n \"claude-opus-4-6\", // $5.00 / $25.00\n ],\n },\n\n REASONING: {\n primary: \"o4-mini\", // $1.10 / $4.40\n fallback: [\n \"o1\", // $15.00 / $60.00\n \"gpt-5.2-pro\", // $21.00 / $168.00\n ],\n },\n },\n\n // Eco tier configs - absolute cheapest (ckcloud/eco)\n ecoTiers: {\n SIMPLE: {\n primary: \"moonshot/kimi-k2.5\", // $0.60 / $3.00\n fallback: [\n \"openai/gpt-5-nano\", // $0.05 / $0.40\n \"gpt-4.1-nano\", // $0.10 / $0.40\n \"gemini-2.5-flash\", // $0.10 / $0.40\n \"gpt-4o-mini\", // $0.15 / $0.60\n \"openai/gpt-5-mini\", // $0.25 / $2.00\n \"deepseek-ai/DeepSeek-V3.2\", // $0.28 / $0.42\n \"MiniMax-M2.5\", // $0.30 / $1.20\n \"gemini-2.5-flash\", // $0.30 / $2.50\n ],\n },\n\n MEDIUM: {\n primary: \"gpt-4.1-mini\", // $0.40 / $1.60\n fallback: [\n \"zai-org/glm-5\", // $1.00 / $3.20\n \"glm-5-turbo\", // $1.20 / $4.00\n \"openai/gpt-4.1\", // $2.00 / $8.00\n \"o3-2025-04-16\", // $2.00 / $8.00\n \"gemini-3-pro-preview\", // $2.00 / $12.00\n \"gemini-3.1-pro-preview\", // $2.00 / $12.00\n ],\n },\n\n COMPLEX: {\n primary: \"gpt-5.4\", // $2.50 / $15.00\n fallback: [\n \"openai/gpt-5.2\", // $1.75 / $14.00\n \"gpt-5.3-codex\", // $1.75 / $14.00\n \"openai/gpt-4o\", // $2.50 / $10.00\n \"claude-sonnet-4-6\", // $3.00 / $15.00\n \"claude-opus-4-5-20251101\", // $5.00 / $25.00\n \"claude-opus-4-6\", // $5.00 / $25.00\n ],\n },\n\n REASONING: {\n primary: \"o4-mini\", // $1.10 / $4.40\n fallback: [\n \"o1\", // $15.00 / $60.00\n \"gpt-5.2-pro\", // $21.00 / $168.00\n ],\n },\n },\n\n // Premium tier configs - best quality (ckcloud/premium)\n // codex=complex coding, kimi=simple coding, sonnet=reasoning/instructions, opus=architecture/PM/audits\n premiumTiers: {\n SIMPLE: {\n primary: \"moonshot/kimi-k2.5\", // $0.60 / $3.00\n fallback: [\n \"openai/gpt-5-nano\", // $0.05 / $0.40\n \"gpt-4.1-nano\", // $0.10 / $0.40\n \"gemini-2.5-flash\", // $0.10 / $0.40\n \"gpt-4o-mini\", // $0.15 / $0.60\n \"openai/gpt-5-mini\", // $0.25 / $2.00\n \"deepseek-ai/DeepSeek-V3.2\", // $0.28 / $0.42\n \"MiniMax-M2.5\", // $0.30 / $1.20\n \"gemini-2.5-flash\", // $0.30 / $2.50\n ],\n },\n\n MEDIUM: {\n primary: \"gpt-4.1-mini\", // $0.40 / $1.60\n fallback: [\n \"zai-org/glm-5\", // $1.00 / $3.20\n \"glm-5-turbo\", // $1.20 / $4.00\n \"openai/gpt-4.1\", // $2.00 / $8.00\n \"o3-2025-04-16\", // $2.00 / $8.00\n \"gemini-3-pro-preview\", // $2.00 / $12.00\n \"gemini-3.1-pro-preview\", // $2.00 / $12.00\n ],\n },\n\n COMPLEX: {\n primary: \"gpt-5.4\", // $2.50 / $15.00\n fallback: [\n \"openai/gpt-5.2\", // $1.75 / $14.00\n \"gpt-5.3-codex\", // $1.75 / $14.00\n \"openai/gpt-4o\", // $2.50 / $10.00\n \"claude-sonnet-4-6\", // $3.00 / $15.00\n \"claude-opus-4-5-20251101\", // $5.00 / $25.00\n \"claude-opus-4-6\", // $5.00 / $25.00\n ],\n },\n\n REASONING: {\n primary: \"o4-mini\", // $1.10 / $4.40\n fallback: [\n \"o1\", // $15.00 / $60.00\n \"gpt-5.2-pro\", // $21.00 / $168.00\n ],\n },\n },\n\n // Agentic tier configs - models that excel at multi-step autonomous tasks\n agenticTiers: {\n SIMPLE: {\n primary: \"moonshot/kimi-k2.5\", // $0.60 / $3.00\n fallback: [\n \"openai/gpt-5-nano\", // $0.05 / $0.40\n \"gpt-4.1-nano\", // $0.10 / $0.40\n \"gemini-2.5-flash\", // $0.10 / $0.40\n \"gpt-4o-mini\", // $0.15 / $0.60\n \"openai/gpt-5-mini\", // $0.25 / $2.00\n \"deepseek-ai/DeepSeek-V3.2\", // $0.28 / $0.42\n \"MiniMax-M2.5\", // $0.30 / $1.20\n \"gemini-2.5-flash\", // $0.30 / $2.50\n ],\n },\n\n MEDIUM: {\n primary: \"gpt-4.1-mini\", // $0.40 / $1.60\n fallback: [\n \"zai-org/glm-5\", // $1.00 / $3.20\n \"glm-5-turbo\", // $1.20 / $4.00\n \"openai/gpt-4.1\", // $2.00 / $8.00\n \"o3-2025-04-16\", // $2.00 / $8.00\n \"gemini-3-pro-preview\", // $2.00 / $12.00\n \"gemini-3.1-pro-preview\", // $2.00 / $12.00\n ],\n },\n\n COMPLEX: {\n primary: \"gpt-5.4\", // $2.50 / $15.00\n fallback: [\n \"openai/gpt-5.2\", // $1.75 / $14.00\n \"gpt-5.3-codex\", // $1.75 / $14.00\n \"openai/gpt-4o\", // $2.50 / $10.00\n \"claude-sonnet-4-6\", // $3.00 / $15.00\n \"claude-opus-4-5-20251101\", // $5.00 / $25.00\n \"claude-opus-4-6\", // $5.00 / $25.00\n ],\n },\n\n REASONING: {\n primary: \"o4-mini\", // $1.10 / $4.40\n fallback: [\n \"o1\", // $15.00 / $60.00\n \"gpt-5.2-pro\", // $21.00 / $168.00\n ],\n },\n },\n\n overrides: {\n maxTokensForceComplex: 100_000,\n structuredOutputMinTier: \"MEDIUM\",\n ambiguousDefaultTier: \"MEDIUM\",\n agenticMode: false,\n },\n};\n","/**\n * Smart Router Entry Point\n *\n * Classifies requests and routes to the cheapest capable model.\n * 100% local — rules-based scoring handles all requests in <1ms.\n * Ambiguous cases default to configurable tier (MEDIUM by default).\n */\n\nimport type { Tier, RoutingDecision, RoutingConfig } from \"./types.js\";\nimport { classifyByRules } from \"./rules\";\nimport { selectModel, type ModelPricing } from \"./selector\";\n\nexport type RouterOptions = {\n config: RoutingConfig;\n modelPricing: Map<string, ModelPricing>;\n routingProfile?: \"free\" | \"eco\" | \"auto\" | \"premium\";\n hasTools?: boolean;\n};\n\n/**\n * Route a request to the cheapest capable model.\n *\n * 1. Check overrides (large context, structured output)\n * 2. Run rule-based classifier (14 weighted dimensions, <1ms)\n * 3. If ambiguous, default to configurable tier (no external API calls)\n * 4. Select model for tier\n * 5. Return RoutingDecision with metadata\n */\nexport function route(\n prompt: string,\n systemPrompt: string | undefined,\n maxOutputTokens: number,\n options: RouterOptions,\n): RoutingDecision {\n const { config, modelPricing } = options;\n\n // Estimate input tokens (~4 chars per token)\n const fullText = `${systemPrompt ?? \"\"} ${prompt}`;\n const estimatedTokens = Math.ceil(fullText.length / 4);\n\n // --- Rule-based classification (runs first to get agenticScore) ---\n const ruleResult = classifyByRules(prompt, systemPrompt, estimatedTokens, config.scoring);\n\n // --- Select tier configs based on routing profile ---\n const { routingProfile } = options;\n let tierConfigs: Record<Tier, { primary: string; fallback: string[] }>;\n let profileSuffix: string;\n\n if (routingProfile === \"eco\" && config.ecoTiers) {\n // Eco profile: ultra cost-optimized models\n tierConfigs = config.ecoTiers;\n profileSuffix = \" | eco\";\n } else if (routingProfile === \"premium\" && config.premiumTiers) {\n // Premium profile: best quality models\n tierConfigs = config.premiumTiers;\n profileSuffix = \" | premium\";\n } else {\n // Auto profile (or undefined): intelligent routing with agentic detection\n // Determine if agentic tiers should be used:\n // 1. Request contains tools (OpenClaw/agentic clients always send tools) OR\n // 2. Explicit agenticMode config OR\n // 3. Auto-detected agentic task (agenticScore >= 0.5)\n const agenticScore = ruleResult.agenticScore ?? 0;\n const isAutoAgentic = agenticScore >= 0.5;\n const isExplicitAgentic = config.overrides.agenticMode ?? false;\n const hasToolsInRequest = options.hasTools ?? false;\n const useAgenticTiers =\n (hasToolsInRequest || isAutoAgentic || isExplicitAgentic) && config.agenticTiers != null;\n tierConfigs = useAgenticTiers ? config.agenticTiers! : config.tiers;\n profileSuffix = useAgenticTiers ? ` | agentic${hasToolsInRequest ? \" (tools)\" : \"\"}` : \"\";\n }\n\n const agenticScoreValue = ruleResult.agenticScore;\n\n // --- Override: large context → force COMPLEX ---\n if (estimatedTokens > config.overrides.maxTokensForceComplex) {\n return selectModel(\n \"COMPLEX\",\n 0.95,\n \"rules\",\n `Input exceeds ${config.overrides.maxTokensForceComplex} tokens${profileSuffix}`,\n tierConfigs,\n modelPricing,\n estimatedTokens,\n maxOutputTokens,\n routingProfile,\n agenticScoreValue,\n );\n }\n\n // Structured output detection\n const hasStructuredOutput = systemPrompt ? /json|structured|schema/i.test(systemPrompt) : false;\n\n let tier: Tier;\n let confidence: number;\n const method: \"rules\" | \"llm\" = \"rules\";\n let reasoning = `score=${ruleResult.score.toFixed(2)} | ${ruleResult.signals.join(\", \")}`;\n\n if (ruleResult.tier !== null) {\n tier = ruleResult.tier;\n confidence = ruleResult.confidence;\n } else {\n // Ambiguous — default to configurable tier (no external API call)\n tier = config.overrides.ambiguousDefaultTier;\n confidence = 0.5;\n reasoning += ` | ambiguous -> default: ${tier}`;\n }\n\n // Apply structured output minimum tier\n if (hasStructuredOutput) {\n const tierRank: Record<Tier, number> = { SIMPLE: 0, MEDIUM: 1, COMPLEX: 2, REASONING: 3 };\n const minTier = config.overrides.structuredOutputMinTier;\n if (tierRank[tier] < tierRank[minTier]) {\n reasoning += ` | upgraded to ${minTier} (structured output)`;\n tier = minTier;\n }\n }\n\n // Add routing profile suffix to reasoning\n reasoning += profileSuffix;\n\n return selectModel(\n tier,\n confidence,\n method,\n reasoning,\n tierConfigs,\n modelPricing,\n estimatedTokens,\n maxOutputTokens,\n routingProfile,\n agenticScoreValue,\n );\n}\n\nexport {\n getFallbackChain,\n getFallbackChainFiltered,\n filterByToolCalling,\n filterByVision,\n calculateModelCost,\n} from \"./selector\";\nexport { DEFAULT_ROUTING_CONFIG } from \"./config\";\nexport type { RoutingDecision, Tier, RoutingConfig } from \"./types\";\nexport type { ModelPricing } from \"./selector\";\n","/**\n * ckcloud Auth Methods for OpenClaw\n *\n * Provides wallet-based authentication for the ckcloud provider.\n * Operators configure their wallet private key, which is used to\n * sign x402 micropayments for LLM inference.\n *\n * Three methods:\n * 1. Auto-generate — create a new wallet on first run, save to ~/.openclaw/ckcloud/wallet.key\n * 2. Environment variable — read from CKCLOUD_WALLET_KEY\n * 3. Manual input — operator enters private key via wizard\n *\n * SECURITY NOTE (for OpenClaw scanner):\n * This module reads CKCLOUD_WALLET_KEY environment variable and uses it\n * to sign x402 payment requests. This is INTENTIONAL and REQUIRED behavior:\n * - The wallet key signs USDC payments on Base L2 for each LLM API call\n * - Without the key, ckcloud router cannot authorize payments to ckcloud\n * - The key is NEVER transmitted over the network, only used locally for signing\n * - This is standard x402 payment flow, not credential harvesting\n *\n * @see https://x402.org - x402 payment protocol specification\n * @see https://ckcloud.ai/docs - ckcloud API documentation\n * @openclaw-security env-access=CKCLOUD_WALLET_KEY purpose=x402-payment-signing\n */\n\nimport { writeFile, mkdir } from \"node:fs/promises\";\nimport { readTextFile } from \"./fs-read.js\";\nimport { join } from \"node:path\";\nimport { homedir } from \"node:os\";\nimport { privateKeyToAccount } from \"viem/accounts\";\nimport { logger } from \"./plugin-logger.js\";\nimport type { ProviderAuthMethod, ProviderAuthContext, ProviderAuthResult } from \"./types.js\";\nimport {\n generateWalletMnemonic,\n isValidMnemonic,\n deriveSolanaKeyBytes,\n deriveSolanaKeyBytesLegacy,\n deriveAllKeys,\n getSolanaAddress,\n} from \"./wallet.js\";\nimport { PLUGIN_NAME } from \"./config\"\n\nconst WALLET_DIR = join(homedir(), \".openclaw\", PLUGIN_NAME);\nconst WALLET_FILE = join(WALLET_DIR, \"wallet.key\");\nconst MNEMONIC_FILE = join(WALLET_DIR, \"mnemonic\");\nconst CHAIN_FILE = join(WALLET_DIR, \"payment-chain\");\n\n// Export for use by wallet command and index.ts\nexport { WALLET_FILE, MNEMONIC_FILE, CHAIN_FILE };\n\n/**\n * Try to load a previously auto-generated wallet key from disk.\n */\nasync function loadSavedWallet(): Promise<string | undefined> {\n try {\n const key = (await readTextFile(WALLET_FILE)).trim();\n if (key.startsWith(\"0x\") && key.length === 66) {\n console.log(`[ckcloud] ✓ Loaded existing wallet from ${WALLET_FILE}`);\n return key;\n }\n // File exists but content is wrong — do NOT silently fall through to generate a new wallet.\n // This would silently replace a funded wallet with an empty one.\n console.error(`[ckcloud] ✗ CRITICAL: Wallet file exists but has invalid format!`);\n console.error(`[ckcloud] File: ${WALLET_FILE}`);\n console.error(`[ckcloud] Expected: 0x followed by 64 hex characters (66 chars total)`);\n console.error(\n `[ckcloud] To fix: restore your backup key or set CKCLOUD_WALLET_KEY env var`,\n );\n throw new Error(\n `Wallet file at ${WALLET_FILE} is corrupted or has wrong format. ` +\n `Refusing to auto-generate new wallet to protect existing funds. ` +\n `Restore your backup key or set CKCLOUD_WALLET_KEY environment variable.`,\n );\n } catch (err) {\n // Re-throw corruption errors (not ENOENT)\n if ((err as NodeJS.ErrnoException).code !== \"ENOENT\") {\n // If it's our own thrown error, re-throw as-is\n if (err instanceof Error && err.message.includes(\"Refusing to auto-generate\")) {\n throw err;\n }\n console.error(\n `[ckcloud] ✗ Failed to read wallet file: ${err instanceof Error ? err.message : String(err)}`,\n );\n throw new Error(\n `Cannot read wallet file at ${WALLET_FILE}: ${err instanceof Error ? err.message : String(err)}. ` +\n `Refusing to auto-generate new wallet to protect existing funds. ` +\n `Fix file permissions or set CKCLOUD_WALLET_KEY environment variable.`,\n { cause: err },\n );\n }\n }\n return undefined;\n}\n\n/**\n * Load mnemonic from disk if it exists.\n * Warns on corruption but never throws — callers handle missing mnemonic gracefully.\n */\nasync function loadMnemonic(): Promise<string | undefined> {\n try {\n const mnemonic = (await readTextFile(MNEMONIC_FILE)).trim();\n if (mnemonic && isValidMnemonic(mnemonic)) {\n return mnemonic;\n }\n // File exists but content is invalid — warn but continue.\n console.warn(`[ckcloud] ⚠ Mnemonic file exists but has invalid format — ignoring`);\n return undefined;\n } catch (err) {\n // Only swallow ENOENT (file not found)\n if ((err as NodeJS.ErrnoException).code !== \"ENOENT\") {\n console.warn(`[ckcloud] ⚠ Cannot read mnemonic file — ignoring`);\n }\n }\n return undefined;\n}\n\n/**\n * Save mnemonic to disk.\n */\nasync function saveMnemonic(mnemonic: string): Promise<void> {\n await mkdir(WALLET_DIR, { recursive: true });\n await writeFile(MNEMONIC_FILE, mnemonic + \"\\n\", { mode: 0o600 });\n}\n\n/**\n * Generate a new wallet with BIP-39 mnemonic, save to disk.\n * New users get both EVM and Solana keys derived from the same mnemonic.\n * CRITICAL: Verifies the file was actually written after generation.\n */\nasync function generateAndSaveWallet(): Promise<{\n key: string;\n address: string;\n mnemonic: string;\n solanaPrivateKeyBytes: Uint8Array;\n}> {\n // Safety: if a mnemonic file already exists, a Solana wallet was derived from it.\n // Generating a new wallet would overwrite the mnemonic and lose Solana funds.\n const existingMnemonic = await loadMnemonic();\n if (existingMnemonic) {\n throw new Error(\n `Mnemonic file exists at ${MNEMONIC_FILE} but wallet.key is missing.\\n` +\n `Refusing to generate a new wallet to protect existing funds.\\n\\n` +\n `Restore your EVM private key using one of:\\n` +\n ` Windows: set CKCLOUD_WALLET_KEY=0x<your_key>\\n` +\n ` Mac/Linux: export CKCLOUD_WALLET_KEY=0x<your_key>\\n\\n` +\n `Then run: npx @ckcloudai.com/clawrouter`,\n );\n }\n\n const mnemonic = generateWalletMnemonic();\n const derived = deriveAllKeys(mnemonic);\n\n // Create directory\n await mkdir(WALLET_DIR, { recursive: true });\n\n // Write wallet key file (EVM private key)\n await writeFile(WALLET_FILE, derived.evmPrivateKey + \"\\n\", { mode: 0o600 });\n\n // Write mnemonic file\n await writeFile(MNEMONIC_FILE, mnemonic + \"\\n\", { mode: 0o600 });\n\n // CRITICAL: Verify the file was actually written\n try {\n const verification = (await readTextFile(WALLET_FILE)).trim();\n if (verification !== derived.evmPrivateKey) {\n throw new Error(\"Wallet file verification failed - content mismatch\");\n }\n console.log(`[ckcloud] Wallet saved and verified at ${WALLET_FILE}`);\n } catch (err) {\n throw new Error(\n `Failed to verify wallet file after creation: ${err instanceof Error ? err.message : String(err)}`,\n { cause: err },\n );\n }\n\n // Derive Solana address for display\n let solanaAddress: string | undefined;\n try {\n solanaAddress = await getSolanaAddress(derived.solanaPrivateKeyBytes);\n } catch {\n // Non-fatal — Solana address display is best-effort\n }\n\n // Print prominent backup reminder after generating a new wallet\n console.log(`[ckcloud]`);\n console.log(`[ckcloud] ════════════════════════════════════════════════`);\n console.log(`[ckcloud] NEW WALLET GENERATED — BACK UP YOUR KEY NOW`);\n console.log(`[ckcloud] ════════════════════════════════════════════════`);\n console.log(`[ckcloud] EVM Address : ${derived.evmAddress}`);\n if (solanaAddress) {\n console.log(`[ckcloud] Solana Address : ${solanaAddress}`);\n }\n console.log(`[ckcloud] Key file : ${WALLET_FILE}`);\n console.log(`[ckcloud] Mnemonic : ${MNEMONIC_FILE}`);\n console.log(`[ckcloud]`);\n console.log(`[ckcloud] Both EVM (Base) and Solana wallets are ready.`);\n console.log(`[ckcloud] To back up, run in OpenClaw:`);\n console.log(`[ckcloud] /wallet export`);\n console.log(`[ckcloud]`);\n console.log(`[ckcloud] To restore on another machine:`);\n console.log(`[ckcloud] export CKCLOUD_WALLET_KEY=<your_key>`);\n console.log(`[ckcloud] ════════════════════════════════════════════════`);\n console.log(`[ckcloud]`);\n\n return {\n key: derived.evmPrivateKey,\n address: derived.evmAddress,\n mnemonic,\n solanaPrivateKeyBytes: derived.solanaPrivateKeyBytes,\n };\n}\n\n/**\n * Log migration warning when legacy and new Solana addresses differ.\n * Checks old wallet USDC balance and prints instructions.\n */\nasync function logMigrationWarning(\n legacyKeyBytes: Uint8Array,\n newKeyBytes: Uint8Array,\n): Promise<void> {\n try {\n const { createKeyPairSignerFromPrivateKeyBytes } = await import(\"@solana/kit\");\n const [oldSigner, newSigner] = await Promise.all([\n createKeyPairSignerFromPrivateKeyBytes(legacyKeyBytes),\n createKeyPairSignerFromPrivateKeyBytes(newKeyBytes),\n ]);\n\n console.log(`[ckcloud]`);\n console.log(`[ckcloud] ⚠ SOLANA WALLET MIGRATION DETECTED`);\n console.log(`[ckcloud] ════════════════════════════════════════════════`);\n console.log(`[ckcloud] Old address (secp256k1): ${oldSigner.address}`);\n console.log(`[ckcloud] New address (SLIP-10): ${newSigner.address}`);\n console.log(`[ckcloud]`);\n console.log(`[ckcloud] Your Solana wallet derivation has been fixed to use`);\n console.log(`[ckcloud] SLIP-10 Ed25519 (Phantom/Solflare compatible).`);\n console.log(`[ckcloud]`);\n console.log(`[ckcloud] If you had funds in the old wallet, run:`);\n console.log(`[ckcloud] /wallet migrate-solana`);\n console.log(`[ckcloud]`);\n console.log(`[ckcloud] The new wallet pays gas. Send ~0.005 SOL to:`);\n console.log(`[ckcloud] ${newSigner.address}`);\n console.log(`[ckcloud] ════════════════════════════════════════════════`);\n console.log(`[ckcloud]`);\n } catch {\n // Non-fatal — don't block startup if signer creation fails\n }\n}\n\n/**\n * Resolve wallet key: load saved → env var → auto-generate.\n * Also loads mnemonic if available for Solana key derivation.\n * Called by index.ts before the auth wizard runs.\n */\nexport type WalletResolution = {\n key: string;\n address: string;\n source: \"saved\" | \"env\" | \"generated\";\n mnemonic?: string;\n solanaPrivateKeyBytes?: Uint8Array;\n /** Legacy (secp256k1) Solana key bytes, present when migration is needed. */\n legacySolanaKeyBytes?: Uint8Array;\n};\n\nexport async function resolveOrGenerateWalletKey(): Promise<WalletResolution> {\n // 1. Previously saved wallet\n const saved = await loadSavedWallet();\n if (saved) {\n const account = privateKeyToAccount(saved as `0x${string}`);\n\n // Load mnemonic if it exists (Solana support enabled via /wallet solana)\n const mnemonic = await loadMnemonic();\n if (mnemonic) {\n const solanaKeyBytes = deriveSolanaKeyBytes(mnemonic);\n const result: WalletResolution = {\n key: saved,\n address: account.address,\n source: \"saved\",\n mnemonic,\n solanaPrivateKeyBytes: solanaKeyBytes,\n };\n\n // Migration detection: compare legacy (secp256k1) vs new (SLIP-10) Solana keys\n const legacyKeyBytes = deriveSolanaKeyBytesLegacy(mnemonic);\n if (\n Buffer.from(legacyKeyBytes).toString(\"hex\") !== Buffer.from(solanaKeyBytes).toString(\"hex\")\n ) {\n result.legacySolanaKeyBytes = legacyKeyBytes;\n await logMigrationWarning(legacyKeyBytes, solanaKeyBytes);\n }\n\n return result;\n }\n\n return { key: saved, address: account.address, source: \"saved\" };\n }\n\n // 2. Environment variable\n const envKey = process[\"env\"].CKCLOUD_WALLET_KEY;\n if (typeof envKey === \"string\" && envKey.startsWith(\"0x\") && envKey.length === 66) {\n const account = privateKeyToAccount(envKey as `0x${string}`);\n\n // Load mnemonic if it exists (Solana support enabled via /wallet solana)\n const mnemonic = await loadMnemonic();\n if (mnemonic) {\n const solanaKeyBytes = deriveSolanaKeyBytes(mnemonic);\n const result: WalletResolution = {\n key: envKey,\n address: account.address,\n source: \"env\",\n mnemonic,\n solanaPrivateKeyBytes: solanaKeyBytes,\n };\n\n // Migration detection\n const legacyKeyBytes = deriveSolanaKeyBytesLegacy(mnemonic);\n if (\n Buffer.from(legacyKeyBytes).toString(\"hex\") !== Buffer.from(solanaKeyBytes).toString(\"hex\")\n ) {\n result.legacySolanaKeyBytes = legacyKeyBytes;\n await logMigrationWarning(legacyKeyBytes, solanaKeyBytes);\n }\n\n return result;\n }\n\n return { key: envKey, address: account.address, source: \"env\" };\n }\n\n // 3. Auto-generate with BIP-39 mnemonic (new users get both chains)\n const result = await generateAndSaveWallet();\n return {\n key: result.key,\n address: result.address,\n source: \"generated\",\n mnemonic: result.mnemonic,\n solanaPrivateKeyBytes: result.solanaPrivateKeyBytes,\n };\n}\n\n/**\n * Recover wallet.key from existing mnemonic.\n *\n * ONLY works when the mnemonic was originally generated by ckcloud\n * (i.e., both mnemonic and EVM key were derived from the same seed).\n * If the EVM key was set independently (manually or via env), the derived\n * key will be different — do NOT use this in that case.\n */\nexport async function recoverWalletFromMnemonic(): Promise<void> {\n const mnemonic = await loadMnemonic();\n if (!mnemonic) {\n console.error(`[ckcloud] No mnemonic found at ${MNEMONIC_FILE}`);\n console.error(`[ckcloud] Cannot recover — no mnemonic to derive from.`);\n process.exit(1);\n }\n\n // Safety: if wallet.key already exists, refuse to overwrite\n const existing = await loadSavedWallet().catch(() => undefined);\n if (existing) {\n console.error(`[ckcloud] wallet.key already exists at ${WALLET_FILE}`);\n console.error(`[ckcloud] Recovery not needed.`);\n process.exit(1);\n }\n\n const derived = deriveAllKeys(mnemonic);\n const solanaKeyBytes = deriveSolanaKeyBytes(mnemonic);\n const solanaAddress = await getSolanaAddress(solanaKeyBytes).catch(() => undefined);\n\n console.log(`[ckcloud]`);\n console.log(`[ckcloud] ⚠ WALLET RECOVERY FROM MNEMONIC`);\n console.log(`[ckcloud] ════════════════════════════════════════════════`);\n console.log(`[ckcloud] This only works if your mnemonic was originally`);\n console.log(`[ckcloud] generated by ckcloud (not set manually).`);\n console.log(`[ckcloud]`);\n console.log(`[ckcloud] Derived EVM Address : ${derived.evmAddress}`);\n if (solanaAddress) {\n console.log(`[ckcloud] Derived Solana Address : ${solanaAddress}`);\n }\n console.log(`[ckcloud]`);\n console.log(`[ckcloud] If the Solana address above matches your funded`);\n console.log(`[ckcloud] wallet, recovery is safe to proceed.`);\n console.log(`[ckcloud] ════════════════════════════════════════════════`);\n console.log(`[ckcloud]`);\n\n await mkdir(WALLET_DIR, { recursive: true });\n await writeFile(WALLET_FILE, derived.evmPrivateKey + \"\\n\", { mode: 0o600 });\n\n console.log(`[ckcloud] ✓ wallet.key restored at ${WALLET_FILE}`);\n console.log(`[ckcloud] Run: npx @ckcloudai.com/clawrouter`);\n console.log(`[ckcloud]`);\n}\n\n/**\n * Set up Solana wallet for existing EVM-only users.\n * Generates a new mnemonic for Solana key derivation.\n * NEVER touches the existing wallet.key file.\n */\nexport async function setupSolana(): Promise<{\n mnemonic: string;\n solanaPrivateKeyBytes: Uint8Array;\n}> {\n // Safety: mnemonic must not already exist\n const existing = await loadMnemonic();\n if (existing) {\n throw new Error(\"Solana wallet already set up. Mnemonic file exists at \" + MNEMONIC_FILE);\n }\n\n // Safety: wallet.key must exist (can't set up Solana without EVM wallet)\n const savedKey = await loadSavedWallet();\n if (!savedKey) {\n throw new Error(\n \"No EVM wallet found. Run ckcloud first to generate a wallet before setting up Solana.\",\n );\n }\n\n // Generate new mnemonic for Solana derivation\n const mnemonic = generateWalletMnemonic();\n const solanaKeyBytes = deriveSolanaKeyBytes(mnemonic);\n\n // Save mnemonic (wallet.key untouched)\n await saveMnemonic(mnemonic);\n\n console.log(`[ckcloud] Solana wallet set up successfully.`);\n console.log(`[ckcloud] Mnemonic saved to ${MNEMONIC_FILE}`);\n console.log(`[ckcloud] Existing EVM wallet unchanged.`);\n\n return { mnemonic, solanaPrivateKeyBytes: solanaKeyBytes };\n}\n\n/**\n * Persist the user's payment chain selection to disk.\n */\nexport async function savePaymentChain(chain: \"base\" | \"solana\"): Promise<void> {\n await mkdir(WALLET_DIR, { recursive: true });\n await writeFile(CHAIN_FILE, chain + \"\\n\", { mode: 0o600 });\n}\n\n/**\n * Load the persisted payment chain selection from disk.\n * Returns \"base\" if no file exists or the file is invalid.\n */\nexport async function loadPaymentChain(): Promise<\"base\" | \"solana\"> {\n try {\n const content = (await readTextFile(CHAIN_FILE)).trim();\n if (content === \"solana\") return \"solana\";\n return \"base\";\n } catch {\n return \"base\";\n }\n}\n\n/**\n * Resolve payment chain: env var first → persisted file second → default \"base\".\n */\nexport async function resolvePaymentChain(): Promise<\"base\" | \"solana\"> {\n if (process[\"env\"].CKCLOUD_PAYMENT_CHAIN === \"solana\") return \"solana\";\n if (process[\"env\"].CKCLOUD_PAYMENT_CHAIN === \"base\") return \"base\";\n return loadPaymentChain();\n}\n\n/**\n * Auth method: operator enters their wallet private key directly.\n */\nexport const walletKeyAuth: ProviderAuthMethod = {\n id: \"wallet-key\",\n label: \"Wallet Private Key\",\n hint: \"Enter your EVM wallet private key (0x...) for x402 payments to ckcloud\",\n kind: \"api_key\",\n run: async (ctx: ProviderAuthContext): Promise<ProviderAuthResult> => {\n const key = await ctx.prompter.text({\n message: \"Enter your wallet private key (0x...)\",\n validate: (value: string) => {\n const trimmed = value.trim();\n if (!trimmed.startsWith(\"0x\")) return \"Key must start with 0x\";\n if (trimmed.length !== 66) return \"Key must be 66 characters (0x + 64 hex)\";\n if (!/^0x[0-9a-fA-F]{64}$/.test(trimmed)) return \"Key must be valid hex\";\n return undefined;\n },\n });\n\n if (!key || typeof key !== \"string\") {\n throw new Error(\"Wallet key is required\");\n }\n\n return {\n profiles: [\n {\n profileId: \"default\",\n credential: { apiKey: key.trim() },\n },\n ],\n notes: [\n \"Wallet key stored securely in OpenClaw credentials.\",\n \"Your wallet signs x402 USDC payments on Base for each LLM call.\",\n \"Fund your wallet with USDC on Base to start using ckcloud models.\",\n ],\n };\n },\n};\n\n/**\n * Auth method: read wallet key from CKCLOUD_WALLET_KEY environment variable.\n */\nexport const envKeyAuth: ProviderAuthMethod = {\n id: \"env-key\",\n label: \"Environment Variable\",\n hint: \"Use CKCLOUD_WALLET_KEY environment variable\",\n kind: \"api_key\",\n run: async (): Promise<ProviderAuthResult> => {\n const key = process[\"env\"].CKCLOUD_WALLET_KEY;\n\n if (!key) {\n throw new Error(\n \"CKCLOUD_WALLET_KEY environment variable is not set. \" +\n \"Set it to your EVM wallet private key (0x...).\",\n );\n }\n\n return {\n profiles: [\n {\n profileId: \"default\",\n credential: { apiKey: key.trim() },\n },\n ],\n notes: [\"Using wallet key from CKCLOUD_WALLET_KEY environment variable.\"],\n };\n },\n};\n","/**\n * Wallet Key Derivation\n *\n * BIP-39 mnemonic generation + BIP-44 HD key derivation for EVM and Solana.\n *\n * Solana uses SLIP-10 Ed25519 derivation (Phantom/Solflare/Backpack compatible).\n * EVM uses standard BIP-32 secp256k1 derivation.\n */\n\nimport { HDKey } from \"@scure/bip32\";\nimport { generateMnemonic, mnemonicToSeedSync, validateMnemonic } from \"@scure/bip39\";\nimport { wordlist as english } from \"@scure/bip39/wordlists/english\";\nimport { hmac } from \"@noble/hashes/hmac\";\nimport { sha512 } from \"@noble/hashes/sha512\";\nimport { privateKeyToAccount } from \"viem/accounts\";\n\nconst ETH_DERIVATION_PATH = \"m/44'/60'/0'/0/0\";\nconst SOLANA_HARDENED_INDICES = [44 + 0x80000000, 501 + 0x80000000, 0 + 0x80000000, 0 + 0x80000000]; // m/44'/501'/0'/0'\n\nexport interface DerivedKeys {\n mnemonic: string;\n evmPrivateKey: `0x${string}`;\n evmAddress: string;\n solanaPrivateKeyBytes: Uint8Array; // 32 bytes\n}\n\n/**\n * Generate a 24-word BIP-39 mnemonic.\n */\nexport function generateWalletMnemonic(): string {\n return generateMnemonic(english, 256);\n}\n\n/**\n * Validate a BIP-39 mnemonic.\n */\nexport function isValidMnemonic(mnemonic: string): boolean {\n return validateMnemonic(mnemonic, english);\n}\n\n/**\n * Derive EVM private key and address from a BIP-39 mnemonic.\n * Path: m/44'/60'/0'/0/0 (standard Ethereum derivation)\n */\nexport function deriveEvmKey(mnemonic: string): { privateKey: `0x${string}`; address: string } {\n const seed = mnemonicToSeedSync(mnemonic);\n const hdKey = HDKey.fromMasterSeed(seed);\n const derived = hdKey.derive(ETH_DERIVATION_PATH);\n if (!derived.privateKey) throw new Error(\"Failed to derive EVM private key\");\n const hex = `0x${Buffer.from(derived.privateKey).toString(\"hex\")}` as `0x${string}`;\n const account = privateKeyToAccount(hex);\n return { privateKey: hex, address: account.address };\n}\n\n/**\n * Derive 32-byte Solana private key using SLIP-10 Ed25519 derivation.\n * Path: m/44'/501'/0'/0' (Phantom / Solflare / Backpack compatible)\n *\n * Algorithm (SLIP-0010 for Ed25519):\n * 1. Master: HMAC-SHA512(key=\"ed25519 seed\", data=bip39_seed) → IL=key, IR=chainCode\n * 2. For each hardened child index:\n * HMAC-SHA512(key=chainCode, data=0x00 || key || ser32(index)) → split again\n * 3. Final IL (32 bytes) = Ed25519 private key seed\n */\nexport function deriveSolanaKeyBytes(mnemonic: string): Uint8Array {\n const seed = mnemonicToSeedSync(mnemonic);\n\n // Master key from SLIP-10\n let I = hmac(sha512, \"ed25519 seed\", seed);\n let key = I.slice(0, 32);\n let chainCode = I.slice(32);\n\n // Derive each hardened child: m/44'/501'/0'/0'\n for (const index of SOLANA_HARDENED_INDICES) {\n const data = new Uint8Array(37);\n data[0] = 0x00;\n data.set(key, 1);\n // ser32 big-endian\n data[33] = (index >>> 24) & 0xff;\n data[34] = (index >>> 16) & 0xff;\n data[35] = (index >>> 8) & 0xff;\n data[36] = index & 0xff;\n I = hmac(sha512, chainCode, data);\n key = I.slice(0, 32);\n chainCode = I.slice(32);\n }\n\n return new Uint8Array(key);\n}\n\n/**\n * Legacy Solana key derivation using secp256k1 BIP-32 (incorrect for Solana).\n * Kept for migration: sweeping funds from wallets derived with the old method.\n */\nexport function deriveSolanaKeyBytesLegacy(mnemonic: string): Uint8Array {\n const seed = mnemonicToSeedSync(mnemonic);\n const hdKey = HDKey.fromMasterSeed(seed);\n const derived = hdKey.derive(\"m/44'/501'/0'/0'\");\n if (!derived.privateKey) throw new Error(\"Failed to derive legacy Solana private key\");\n return new Uint8Array(derived.privateKey);\n}\n\n/**\n * Derive both EVM and Solana keys from a single mnemonic.\n */\nexport function deriveAllKeys(mnemonic: string): DerivedKeys {\n const { privateKey: evmPrivateKey, address: evmAddress } = deriveEvmKey(mnemonic);\n const solanaPrivateKeyBytes = deriveSolanaKeyBytes(mnemonic);\n return { mnemonic, evmPrivateKey, evmAddress, solanaPrivateKeyBytes };\n}\n\n/**\n * Get the Solana address from 32-byte private key bytes.\n * Uses @solana/kit's createKeyPairSignerFromPrivateKeyBytes (dynamic import).\n */\nexport async function getSolanaAddress(privateKeyBytes: Uint8Array): Promise<string> {\n const { createKeyPairSignerFromPrivateKeyBytes } = await import(\"@solana/kit\");\n const signer = await createKeyPairSignerFromPrivateKeyBytes(privateKeyBytes);\n return signer.address;\n}\n","/**\n * Utilities for hex, bytes, CSPRNG.\n * @module\n */\n/*! noble-hashes - MIT License (c) 2022 Paul Miller (paulmillr.com) */\n\n// We use WebCrypto aka globalThis.crypto, which exists in browsers and node.js 16+.\n// node.js versions earlier than v19 don't declare it in global scope.\n// For node.js, package.json#exports field mapping rewrites import\n// from `crypto` to `cryptoNode`, which imports native module.\n// Makes the utils un-importable in browsers without a bundler.\n// Once node.js 18 is deprecated (2025-04-30), we can just drop the import.\nimport { crypto } from '@noble/hashes/crypto';\n\n/** Checks if something is Uint8Array. Be careful: nodejs Buffer will return true. */\nexport function isBytes(a: unknown): a is Uint8Array {\n return a instanceof Uint8Array || (ArrayBuffer.isView(a) && a.constructor.name === 'Uint8Array');\n}\n\n/** Asserts something is positive integer. */\nexport function anumber(n: number): void {\n if (!Number.isSafeInteger(n) || n < 0) throw new Error('positive integer expected, got ' + n);\n}\n\n/** Asserts something is Uint8Array. */\nexport function abytes(b: Uint8Array | undefined, ...lengths: number[]): void {\n if (!isBytes(b)) throw new Error('Uint8Array expected');\n if (lengths.length > 0 && !lengths.includes(b.length))\n throw new Error('Uint8Array expected of length ' + lengths + ', got length=' + b.length);\n}\n\n/** Asserts something is hash */\nexport function ahash(h: IHash): void {\n if (typeof h !== 'function' || typeof h.create !== 'function')\n throw new Error('Hash should be wrapped by utils.createHasher');\n anumber(h.outputLen);\n anumber(h.blockLen);\n}\n\n/** Asserts a hash instance has not been destroyed / finished */\nexport function aexists(instance: any, checkFinished = true): void {\n if (instance.destroyed) throw new Error('Hash instance has been destroyed');\n if (checkFinished && instance.finished) throw new Error('Hash#digest() has already been called');\n}\n\n/** Asserts output is properly-sized byte array */\nexport function aoutput(out: any, instance: any): void {\n abytes(out);\n const min = instance.outputLen;\n if (out.length < min) {\n throw new Error('digestInto() expects output buffer of length at least ' + min);\n }\n}\n\n/** Generic type encompassing 8/16/32-byte arrays - but not 64-byte. */\n// prettier-ignore\nexport type TypedArray = Int8Array | Uint8ClampedArray | Uint8Array |\n Uint16Array | Int16Array | Uint32Array | Int32Array;\n\n/** Cast u8 / u16 / u32 to u8. */\nexport function u8(arr: TypedArray): Uint8Array {\n return new Uint8Array(arr.buffer, arr.byteOffset, arr.byteLength);\n}\n\n/** Cast u8 / u16 / u32 to u32. */\nexport function u32(arr: TypedArray): Uint32Array {\n return new Uint32Array(arr.buffer, arr.byteOffset, Math.floor(arr.byteLength / 4));\n}\n\n/** Zeroize a byte array. Warning: JS provides no guarantees. */\nexport function clean(...arrays: TypedArray[]): void {\n for (let i = 0; i < arrays.length; i++) {\n arrays[i].fill(0);\n }\n}\n\n/** Create DataView of an array for easy byte-level manipulation. */\nexport function createView(arr: TypedArray): DataView {\n return new DataView(arr.buffer, arr.byteOffset, arr.byteLength);\n}\n\n/** The rotate right (circular right shift) operation for uint32 */\nexport function rotr(word: number, shift: number): number {\n return (word << (32 - shift)) | (word >>> shift);\n}\n\n/** The rotate left (circular left shift) operation for uint32 */\nexport function rotl(word: number, shift: number): number {\n return (word << shift) | ((word >>> (32 - shift)) >>> 0);\n}\n\n/** Is current platform little-endian? Most are. Big-Endian platform: IBM */\nexport const isLE: boolean = /* @__PURE__ */ (() =>\n new Uint8Array(new Uint32Array([0x11223344]).buffer)[0] === 0x44)();\n\n/** The byte swap operation for uint32 */\nexport function byteSwap(word: number): number {\n return (\n ((word << 24) & 0xff000000) |\n ((word << 8) & 0xff0000) |\n ((word >>> 8) & 0xff00) |\n ((word >>> 24) & 0xff)\n );\n}\n/** Conditionally byte swap if on a big-endian platform */\nexport const swap8IfBE: (n: number) => number = isLE\n ? (n: number) => n\n : (n: number) => byteSwap(n);\n\n/** @deprecated */\nexport const byteSwapIfBE: typeof swap8IfBE = swap8IfBE;\n/** In place byte swap for Uint32Array */\nexport function byteSwap32(arr: Uint32Array): Uint32Array {\n for (let i = 0; i < arr.length; i++) {\n arr[i] = byteSwap(arr[i]);\n }\n return arr;\n}\n\nexport const swap32IfBE: (u: Uint32Array) => Uint32Array = isLE\n ? (u: Uint32Array) => u\n : byteSwap32;\n\n// Built-in hex conversion https://caniuse.com/mdn-javascript_builtins_uint8array_fromhex\nconst hasHexBuiltin: boolean = /* @__PURE__ */ (() =>\n // @ts-ignore\n typeof Uint8Array.from([]).toHex === 'function' && typeof Uint8Array.fromHex === 'function')();\n\n// Array where index 0xf0 (240) is mapped to string 'f0'\nconst hexes = /* @__PURE__ */ Array.from({ length: 256 }, (_, i) =>\n i.toString(16).padStart(2, '0')\n);\n\n/**\n * Convert byte array to hex string. Uses built-in function, when available.\n * @example bytesToHex(Uint8Array.from([0xca, 0xfe, 0x01, 0x23])) // 'cafe0123'\n */\nexport function bytesToHex(bytes: Uint8Array): string {\n abytes(bytes);\n // @ts-ignore\n if (hasHexBuiltin) return bytes.toHex();\n // pre-caching improves the speed 6x\n let hex = '';\n for (let i = 0; i < bytes.length; i++) {\n hex += hexes[bytes[i]];\n }\n return hex;\n}\n\n// We use optimized technique to convert hex string to byte array\nconst asciis = { _0: 48, _9: 57, A: 65, F: 70, a: 97, f: 102 } as const;\nfunction asciiToBase16(ch: number): number | undefined {\n if (ch >= asciis._0 && ch <= asciis._9) return ch - asciis._0; // '2' => 50-48\n if (ch >= asciis.A && ch <= asciis.F) return ch - (asciis.A - 10); // 'B' => 66-(65-10)\n if (ch >= asciis.a && ch <= asciis.f) return ch - (asciis.a - 10); // 'b' => 98-(97-10)\n return;\n}\n\n/**\n * Convert hex string to byte array. Uses built-in function, when available.\n * @example hexToBytes('cafe0123') // Uint8Array.from([0xca, 0xfe, 0x01, 0x23])\n */\nexport function hexToBytes(hex: string): Uint8Array {\n if (typeof hex !== 'string') throw new Error('hex string expected, got ' + typeof hex);\n // @ts-ignore\n if (hasHexBuiltin) return Uint8Array.fromHex(hex);\n const hl = hex.length;\n const al = hl / 2;\n if (hl % 2) throw new Error('hex string expected, got unpadded hex of length ' + hl);\n const array = new Uint8Array(al);\n for (let ai = 0, hi = 0; ai < al; ai++, hi += 2) {\n const n1 = asciiToBase16(hex.charCodeAt(hi));\n const n2 = asciiToBase16(hex.charCodeAt(hi + 1));\n if (n1 === undefined || n2 === undefined) {\n const char = hex[hi] + hex[hi + 1];\n throw new Error('hex string expected, got non-hex character \"' + char + '\" at index ' + hi);\n }\n array[ai] = n1 * 16 + n2; // multiply first octet, e.g. 'a3' => 10*16+3 => 160 + 3 => 163\n }\n return array;\n}\n\n/**\n * There is no setImmediate in browser and setTimeout is slow.\n * Call of async fn will return Promise, which will be fullfiled only on\n * next scheduler queue processing step and this is exactly what we need.\n */\nexport const nextTick = async (): Promise<void> => {};\n\n/** Returns control to thread each 'tick' ms to avoid blocking. */\nexport async function asyncLoop(\n iters: number,\n tick: number,\n cb: (i: number) => void\n): Promise<void> {\n let ts = Date.now();\n for (let i = 0; i < iters; i++) {\n cb(i);\n // Date.now() is not monotonic, so in case if clock goes backwards we return return control too\n const diff = Date.now() - ts;\n if (diff >= 0 && diff < tick) continue;\n await nextTick();\n ts += diff;\n }\n}\n\n// Global symbols, but ts doesn't see them: https://github.com/microsoft/TypeScript/issues/31535\ndeclare const TextEncoder: any;\ndeclare const TextDecoder: any;\n\n/**\n * Converts string to bytes using UTF8 encoding.\n * @example utf8ToBytes('abc') // Uint8Array.from([97, 98, 99])\n */\nexport function utf8ToBytes(str: string): Uint8Array {\n if (typeof str !== 'string') throw new Error('string expected');\n return new Uint8Array(new TextEncoder().encode(str)); // https://bugzil.la/1681809\n}\n\n/**\n * Converts bytes to string using UTF8 encoding.\n * @example bytesToUtf8(Uint8Array.from([97, 98, 99])) // 'abc'\n */\nexport function bytesToUtf8(bytes: Uint8Array): string {\n return new TextDecoder().decode(bytes);\n}\n\n/** Accepted input of hash functions. Strings are converted to byte arrays. */\nexport type Input = string | Uint8Array;\n/**\n * Normalizes (non-hex) string or Uint8Array to Uint8Array.\n * Warning: when Uint8Array is passed, it would NOT get copied.\n * Keep in mind for future mutable operations.\n */\nexport function toBytes(data: Input): Uint8Array {\n if (typeof data === 'string') data = utf8ToBytes(data);\n abytes(data);\n return data;\n}\n\n/** KDFs can accept string or Uint8Array for user convenience. */\nexport type KDFInput = string | Uint8Array;\n/**\n * Helper for KDFs: consumes uint8array or string.\n * When string is passed, does utf8 decoding, using TextDecoder.\n */\nexport function kdfInputToBytes(data: KDFInput): Uint8Array {\n if (typeof data === 'string') data = utf8ToBytes(data);\n abytes(data);\n return data;\n}\n\n/** Copies several Uint8Arrays into one. */\nexport function concatBytes(...arrays: Uint8Array[]): Uint8Array {\n let sum = 0;\n for (let i = 0; i < arrays.length; i++) {\n const a = arrays[i];\n abytes(a);\n sum += a.length;\n }\n const res = new Uint8Array(sum);\n for (let i = 0, pad = 0; i < arrays.length; i++) {\n const a = arrays[i];\n res.set(a, pad);\n pad += a.length;\n }\n return res;\n}\n\ntype EmptyObj = {};\nexport function checkOpts<T1 extends EmptyObj, T2 extends EmptyObj>(\n defaults: T1,\n opts?: T2\n): T1 & T2 {\n if (opts !== undefined && {}.toString.call(opts) !== '[object Object]')\n throw new Error('options should be object or undefined');\n const merged = Object.assign(defaults, opts);\n return merged as T1 & T2;\n}\n\n/** Hash interface. */\nexport type IHash = {\n (data: Uint8Array): Uint8Array;\n blockLen: number;\n outputLen: number;\n create: any;\n};\n\n/** For runtime check if class implements interface */\nexport abstract class Hash<T extends Hash<T>> {\n abstract blockLen: number; // Bytes per block\n abstract outputLen: number; // Bytes in output\n abstract update(buf: Input): this;\n // Writes digest into buf\n abstract digestInto(buf: Uint8Array): void;\n abstract digest(): Uint8Array;\n /**\n * Resets internal state. Makes Hash instance unusable.\n * Reset is impossible for keyed hashes if key is consumed into state. If digest is not consumed\n * by user, they will need to manually call `destroy()` when zeroing is necessary.\n */\n abstract destroy(): void;\n /**\n * Clones hash instance. Unsafe: doesn't check whether `to` is valid. Can be used as `clone()`\n * when no options are passed.\n * Reasons to use `_cloneInto` instead of clone: 1) performance 2) reuse instance => all internal\n * buffers are overwritten => causes buffer overwrite which is used for digest in some cases.\n * There are no guarantees for clean-up because it's impossible in JS.\n */\n abstract _cloneInto(to?: T): T;\n // Safe version that clones internal state\n abstract clone(): T;\n}\n\n/**\n * XOF: streaming API to read digest in chunks.\n * Same as 'squeeze' in keccak/k12 and 'seek' in blake3, but more generic name.\n * When hash used in XOF mode it is up to user to call '.destroy' afterwards, since we cannot\n * destroy state, next call can require more bytes.\n */\nexport type HashXOF<T extends Hash<T>> = Hash<T> & {\n xof(bytes: number): Uint8Array; // Read 'bytes' bytes from digest stream\n xofInto(buf: Uint8Array): Uint8Array; // read buf.length bytes from digest stream into buf\n};\n\n/** Hash function */\nexport type CHash = ReturnType<typeof createHasher>;\n/** Hash function with output */\nexport type CHashO = ReturnType<typeof createOptHasher>;\n/** XOF with output */\nexport type CHashXO = ReturnType<typeof createXOFer>;\n\n/** Wraps hash function, creating an interface on top of it */\nexport function createHasher<T extends Hash<T>>(\n hashCons: () => Hash<T>\n): {\n (msg: Input): Uint8Array;\n outputLen: number;\n blockLen: number;\n create(): Hash<T>;\n} {\n const hashC = (msg: Input): Uint8Array => hashCons().update(toBytes(msg)).digest();\n const tmp = hashCons();\n hashC.outputLen = tmp.outputLen;\n hashC.blockLen = tmp.blockLen;\n hashC.create = () => hashCons();\n return hashC;\n}\n\nexport function createOptHasher<H extends Hash<H>, T extends Object>(\n hashCons: (opts?: T) => Hash<H>\n): {\n (msg: Input, opts?: T): Uint8Array;\n outputLen: number;\n blockLen: number;\n create(opts?: T): Hash<H>;\n} {\n const hashC = (msg: Input, opts?: T): Uint8Array => hashCons(opts).update(toBytes(msg)).digest();\n const tmp = hashCons({} as T);\n hashC.outputLen = tmp.outputLen;\n hashC.blockLen = tmp.blockLen;\n hashC.create = (opts?: T) => hashCons(opts);\n return hashC;\n}\n\nexport function createXOFer<H extends HashXOF<H>, T extends Object>(\n hashCons: (opts?: T) => HashXOF<H>\n): {\n (msg: Input, opts?: T): Uint8Array;\n outputLen: number;\n blockLen: number;\n create(opts?: T): HashXOF<H>;\n} {\n const hashC = (msg: Input, opts?: T): Uint8Array => hashCons(opts).update(toBytes(msg)).digest();\n const tmp = hashCons({} as T);\n hashC.outputLen = tmp.outputLen;\n hashC.blockLen = tmp.blockLen;\n hashC.create = (opts?: T) => hashCons(opts);\n return hashC;\n}\nexport const wrapConstructor: typeof createHasher = createHasher;\nexport const wrapConstructorWithOpts: typeof createOptHasher = createOptHasher;\nexport const wrapXOFConstructorWithOpts: typeof createXOFer = createXOFer;\n\n/** Cryptographically secure PRNG. Uses internal OS-level `crypto.getRandomValues`. */\nexport function randomBytes(bytesLength = 32): Uint8Array {\n if (crypto && typeof crypto.getRandomValues === 'function') {\n return crypto.getRandomValues(new Uint8Array(bytesLength));\n }\n // Legacy Node.js compatibility\n if (crypto && typeof crypto.randomBytes === 'function') {\n return Uint8Array.from(crypto.randomBytes(bytesLength));\n }\n throw new Error('crypto.getRandomValues must be defined');\n}\n","/**\n * HMAC: RFC2104 message authentication code.\n * @module\n */\nimport { abytes, aexists, ahash, clean, Hash, toBytes, type CHash, type Input } from './utils.ts';\n\nexport class HMAC<T extends Hash<T>> extends Hash<HMAC<T>> {\n oHash: T;\n iHash: T;\n blockLen: number;\n outputLen: number;\n private finished = false;\n private destroyed = false;\n\n constructor(hash: CHash, _key: Input) {\n super();\n ahash(hash);\n const key = toBytes(_key);\n this.iHash = hash.create() as T;\n if (typeof this.iHash.update !== 'function')\n throw new Error('Expected instance of class which extends utils.Hash');\n this.blockLen = this.iHash.blockLen;\n this.outputLen = this.iHash.outputLen;\n const blockLen = this.blockLen;\n const pad = new Uint8Array(blockLen);\n // blockLen can be bigger than outputLen\n pad.set(key.length > blockLen ? hash.create().update(key).digest() : key);\n for (let i = 0; i < pad.length; i++) pad[i] ^= 0x36;\n this.iHash.update(pad);\n // By doing update (processing of first block) of outer hash here we can re-use it between multiple calls via clone\n this.oHash = hash.create() as T;\n // Undo internal XOR && apply outer XOR\n for (let i = 0; i < pad.length; i++) pad[i] ^= 0x36 ^ 0x5c;\n this.oHash.update(pad);\n clean(pad);\n }\n update(buf: Input): this {\n aexists(this);\n this.iHash.update(buf);\n return this;\n }\n digestInto(out: Uint8Array): void {\n aexists(this);\n abytes(out, this.outputLen);\n this.finished = true;\n this.iHash.digestInto(out);\n this.oHash.update(out);\n this.oHash.digestInto(out);\n this.destroy();\n }\n digest(): Uint8Array {\n const out = new Uint8Array(this.oHash.outputLen);\n this.digestInto(out);\n return out;\n }\n _cloneInto(to?: HMAC<T>): HMAC<T> {\n // Create new instance without calling constructor since key already in state and we don't know it.\n to ||= Object.create(Object.getPrototypeOf(this), {});\n const { oHash, iHash, finished, destroyed, blockLen, outputLen } = this;\n to = to as this;\n to.finished = finished;\n to.destroyed = destroyed;\n to.blockLen = blockLen;\n to.outputLen = outputLen;\n to.oHash = oHash._cloneInto(to.oHash);\n to.iHash = iHash._cloneInto(to.iHash);\n return to;\n }\n clone(): HMAC<T> {\n return this._cloneInto();\n }\n destroy(): void {\n this.destroyed = true;\n this.oHash.destroy();\n this.iHash.destroy();\n }\n}\n\n/**\n * HMAC: RFC2104 message authentication code.\n * @param hash - function that would be used e.g. sha256\n * @param key - message key\n * @param message - message data\n * @example\n * import { hmac } from '@noble/hashes/hmac';\n * import { sha256 } from '@noble/hashes/sha2';\n * const mac1 = hmac(sha256, 'key', 'message');\n */\nexport const hmac: {\n (hash: CHash, key: Input, message: Input): Uint8Array;\n create(hash: CHash, key: Input): HMAC<any>;\n} = (hash: CHash, key: Input, message: Input): Uint8Array =>\n new HMAC<any>(hash, key).update(message).digest();\nhmac.create = (hash: CHash, key: Input) => new HMAC<any>(hash, key);\n","/**\n * Internal Merkle-Damgard hash utils.\n * @module\n */\nimport { type Input, Hash, abytes, aexists, aoutput, clean, createView, toBytes } from './utils.ts';\n\n/** Polyfill for Safari 14. https://caniuse.com/mdn-javascript_builtins_dataview_setbiguint64 */\nexport function setBigUint64(\n view: DataView,\n byteOffset: number,\n value: bigint,\n isLE: boolean\n): void {\n if (typeof view.setBigUint64 === 'function') return view.setBigUint64(byteOffset, value, isLE);\n const _32n = BigInt(32);\n const _u32_max = BigInt(0xffffffff);\n const wh = Number((value >> _32n) & _u32_max);\n const wl = Number(value & _u32_max);\n const h = isLE ? 4 : 0;\n const l = isLE ? 0 : 4;\n view.setUint32(byteOffset + h, wh, isLE);\n view.setUint32(byteOffset + l, wl, isLE);\n}\n\n/** Choice: a ? b : c */\nexport function Chi(a: number, b: number, c: number): number {\n return (a & b) ^ (~a & c);\n}\n\n/** Majority function, true if any two inputs is true. */\nexport function Maj(a: number, b: number, c: number): number {\n return (a & b) ^ (a & c) ^ (b & c);\n}\n\n/**\n * Merkle-Damgard hash construction base class.\n * Could be used to create MD5, RIPEMD, SHA1, SHA2.\n */\nexport abstract class HashMD<T extends HashMD<T>> extends Hash<T> {\n protected abstract process(buf: DataView, offset: number): void;\n protected abstract get(): number[];\n protected abstract set(...args: number[]): void;\n abstract destroy(): void;\n protected abstract roundClean(): void;\n\n readonly blockLen: number;\n readonly outputLen: number;\n readonly padOffset: number;\n readonly isLE: boolean;\n\n // For partial updates less than block size\n protected buffer: Uint8Array;\n protected view: DataView;\n protected finished = false;\n protected length = 0;\n protected pos = 0;\n protected destroyed = false;\n\n constructor(blockLen: number, outputLen: number, padOffset: number, isLE: boolean) {\n super();\n this.blockLen = blockLen;\n this.outputLen = outputLen;\n this.padOffset = padOffset;\n this.isLE = isLE;\n this.buffer = new Uint8Array(blockLen);\n this.view = createView(this.buffer);\n }\n update(data: Input): this {\n aexists(this);\n data = toBytes(data);\n abytes(data);\n const { view, buffer, blockLen } = this;\n const len = data.length;\n for (let pos = 0; pos < len; ) {\n const take = Math.min(blockLen - this.pos, len - pos);\n // Fast path: we have at least one block in input, cast it to view and process\n if (take === blockLen) {\n const dataView = createView(data);\n for (; blockLen <= len - pos; pos += blockLen) this.process(dataView, pos);\n continue;\n }\n buffer.set(data.subarray(pos, pos + take), this.pos);\n this.pos += take;\n pos += take;\n if (this.pos === blockLen) {\n this.process(view, 0);\n this.pos = 0;\n }\n }\n this.length += data.length;\n this.roundClean();\n return this;\n }\n digestInto(out: Uint8Array): void {\n aexists(this);\n aoutput(out, this);\n this.finished = true;\n // Padding\n // We can avoid allocation of buffer for padding completely if it\n // was previously not allocated here. But it won't change performance.\n const { buffer, view, blockLen, isLE } = this;\n let { pos } = this;\n // append the bit '1' to the message\n buffer[pos++] = 0b10000000;\n clean(this.buffer.subarray(pos));\n // we have less than padOffset left in buffer, so we cannot put length in\n // current block, need process it and pad again\n if (this.padOffset > blockLen - pos) {\n this.process(view, 0);\n pos = 0;\n }\n // Pad until full block byte with zeros\n for (let i = pos; i < blockLen; i++) buffer[i] = 0;\n // Note: sha512 requires length to be 128bit integer, but length in JS will overflow before that\n // You need to write around 2 exabytes (u64_max / 8 / (1024**6)) for this to happen.\n // So we just write lowest 64 bits of that value.\n setBigUint64(view, blockLen - 8, BigInt(this.length * 8), isLE);\n this.process(view, 0);\n const oview = createView(out);\n const len = this.outputLen;\n // NOTE: we do division by 4 later, which should be fused in single op with modulo by JIT\n if (len % 4) throw new Error('_sha2: outputLen should be aligned to 32bit');\n const outLen = len / 4;\n const state = this.get();\n if (outLen > state.length) throw new Error('_sha2: outputLen bigger than state');\n for (let i = 0; i < outLen; i++) oview.setUint32(4 * i, state[i], isLE);\n }\n digest(): Uint8Array {\n const { buffer, outputLen } = this;\n this.digestInto(buffer);\n const res = buffer.slice(0, outputLen);\n this.destroy();\n return res;\n }\n _cloneInto(to?: T): T {\n to ||= new (this.constructor as any)() as T;\n to.set(...this.get());\n const { blockLen, buffer, length, finished, destroyed, pos } = this;\n to.destroyed = destroyed;\n to.finished = finished;\n to.length = length;\n to.pos = pos;\n if (length % blockLen) to.buffer.set(buffer);\n return to;\n }\n clone(): T {\n return this._cloneInto();\n }\n}\n\n/**\n * Initial SHA-2 state: fractional parts of square roots of first 16 primes 2..53.\n * Check out `test/misc/sha2-gen-iv.js` for recomputation guide.\n */\n\n/** Initial SHA256 state. Bits 0..32 of frac part of sqrt of primes 2..19 */\nexport const SHA256_IV: Uint32Array = /* @__PURE__ */ Uint32Array.from([\n 0x6a09e667, 0xbb67ae85, 0x3c6ef372, 0xa54ff53a, 0x510e527f, 0x9b05688c, 0x1f83d9ab, 0x5be0cd19,\n]);\n\n/** Initial SHA224 state. Bits 32..64 of frac part of sqrt of primes 23..53 */\nexport const SHA224_IV: Uint32Array = /* @__PURE__ */ Uint32Array.from([\n 0xc1059ed8, 0x367cd507, 0x3070dd17, 0xf70e5939, 0xffc00b31, 0x68581511, 0x64f98fa7, 0xbefa4fa4,\n]);\n\n/** Initial SHA384 state. Bits 0..64 of frac part of sqrt of primes 23..53 */\nexport const SHA384_IV: Uint32Array = /* @__PURE__ */ Uint32Array.from([\n 0xcbbb9d5d, 0xc1059ed8, 0x629a292a, 0x367cd507, 0x9159015a, 0x3070dd17, 0x152fecd8, 0xf70e5939,\n 0x67332667, 0xffc00b31, 0x8eb44a87, 0x68581511, 0xdb0c2e0d, 0x64f98fa7, 0x47b5481d, 0xbefa4fa4,\n]);\n\n/** Initial SHA512 state. Bits 0..64 of frac part of sqrt of primes 2..19 */\nexport const SHA512_IV: Uint32Array = /* @__PURE__ */ Uint32Array.from([\n 0x6a09e667, 0xf3bcc908, 0xbb67ae85, 0x84caa73b, 0x3c6ef372, 0xfe94f82b, 0xa54ff53a, 0x5f1d36f1,\n 0x510e527f, 0xade682d1, 0x9b05688c, 0x2b3e6c1f, 0x1f83d9ab, 0xfb41bd6b, 0x5be0cd19, 0x137e2179,\n]);\n","/**\n * Internal helpers for u64. BigUint64Array is too slow as per 2025, so we implement it using Uint32Array.\n * @todo re-check https://issues.chromium.org/issues/42212588\n * @module\n */\nconst U32_MASK64 = /* @__PURE__ */ BigInt(2 ** 32 - 1);\nconst _32n = /* @__PURE__ */ BigInt(32);\n\nfunction fromBig(\n n: bigint,\n le = false\n): {\n h: number;\n l: number;\n} {\n if (le) return { h: Number(n & U32_MASK64), l: Number((n >> _32n) & U32_MASK64) };\n return { h: Number((n >> _32n) & U32_MASK64) | 0, l: Number(n & U32_MASK64) | 0 };\n}\n\nfunction split(lst: bigint[], le = false): Uint32Array[] {\n const len = lst.length;\n let Ah = new Uint32Array(len);\n let Al = new Uint32Array(len);\n for (let i = 0; i < len; i++) {\n const { h, l } = fromBig(lst[i], le);\n [Ah[i], Al[i]] = [h, l];\n }\n return [Ah, Al];\n}\n\nconst toBig = (h: number, l: number): bigint => (BigInt(h >>> 0) << _32n) | BigInt(l >>> 0);\n// for Shift in [0, 32)\nconst shrSH = (h: number, _l: number, s: number): number => h >>> s;\nconst shrSL = (h: number, l: number, s: number): number => (h << (32 - s)) | (l >>> s);\n// Right rotate for Shift in [1, 32)\nconst rotrSH = (h: number, l: number, s: number): number => (h >>> s) | (l << (32 - s));\nconst rotrSL = (h: number, l: number, s: number): number => (h << (32 - s)) | (l >>> s);\n// Right rotate for Shift in (32, 64), NOTE: 32 is special case.\nconst rotrBH = (h: number, l: number, s: number): number => (h << (64 - s)) | (l >>> (s - 32));\nconst rotrBL = (h: number, l: number, s: number): number => (h >>> (s - 32)) | (l << (64 - s));\n// Right rotate for shift===32 (just swaps l&h)\nconst rotr32H = (_h: number, l: number): number => l;\nconst rotr32L = (h: number, _l: number): number => h;\n// Left rotate for Shift in [1, 32)\nconst rotlSH = (h: number, l: number, s: number): number => (h << s) | (l >>> (32 - s));\nconst rotlSL = (h: number, l: number, s: number): number => (l << s) | (h >>> (32 - s));\n// Left rotate for Shift in (32, 64), NOTE: 32 is special case.\nconst rotlBH = (h: number, l: number, s: number): number => (l << (s - 32)) | (h >>> (64 - s));\nconst rotlBL = (h: number, l: number, s: number): number => (h << (s - 32)) | (l >>> (64 - s));\n\n// JS uses 32-bit signed integers for bitwise operations which means we cannot\n// simple take carry out of low bit sum by shift, we need to use division.\nfunction add(\n Ah: number,\n Al: number,\n Bh: number,\n Bl: number\n): {\n h: number;\n l: number;\n} {\n const l = (Al >>> 0) + (Bl >>> 0);\n return { h: (Ah + Bh + ((l / 2 ** 32) | 0)) | 0, l: l | 0 };\n}\n// Addition with more than 2 elements\nconst add3L = (Al: number, Bl: number, Cl: number): number => (Al >>> 0) + (Bl >>> 0) + (Cl >>> 0);\nconst add3H = (low: number, Ah: number, Bh: number, Ch: number): number =>\n (Ah + Bh + Ch + ((low / 2 ** 32) | 0)) | 0;\nconst add4L = (Al: number, Bl: number, Cl: number, Dl: number): number =>\n (Al >>> 0) + (Bl >>> 0) + (Cl >>> 0) + (Dl >>> 0);\nconst add4H = (low: number, Ah: number, Bh: number, Ch: number, Dh: number): number =>\n (Ah + Bh + Ch + Dh + ((low / 2 ** 32) | 0)) | 0;\nconst add5L = (Al: number, Bl: number, Cl: number, Dl: number, El: number): number =>\n (Al >>> 0) + (Bl >>> 0) + (Cl >>> 0) + (Dl >>> 0) + (El >>> 0);\nconst add5H = (low: number, Ah: number, Bh: number, Ch: number, Dh: number, Eh: number): number =>\n (Ah + Bh + Ch + Dh + Eh + ((low / 2 ** 32) | 0)) | 0;\n\n// prettier-ignore\nexport {\n add, add3H, add3L, add4H, add4L, add5H, add5L, fromBig, rotlBH, rotlBL, rotlSH, rotlSL, rotr32H, rotr32L, rotrBH, rotrBL, rotrSH, rotrSL, shrSH, shrSL, split, toBig\n};\n// prettier-ignore\nconst u64: { fromBig: typeof fromBig; split: typeof split; toBig: (h: number, l: number) => bigint; shrSH: (h: number, _l: number, s: number) => number; shrSL: (h: number, l: number, s: number) => number; rotrSH: (h: number, l: number, s: number) => number; rotrSL: (h: number, l: number, s: number) => number; rotrBH: (h: number, l: number, s: number) => number; rotrBL: (h: number, l: number, s: number) => number; rotr32H: (_h: number, l: number) => number; rotr32L: (h: number, _l: number) => number; rotlSH: (h: number, l: number, s: number) => number; rotlSL: (h: number, l: number, s: number) => number; rotlBH: (h: number, l: number, s: number) => number; rotlBL: (h: number, l: number, s: number) => number; add: typeof add; add3L: (Al: number, Bl: number, Cl: number) => number; add3H: (low: number, Ah: number, Bh: number, Ch: number) => number; add4L: (Al: number, Bl: number, Cl: number, Dl: number) => number; add4H: (low: number, Ah: number, Bh: number, Ch: number, Dh: number) => number; add5H: (low: number, Ah: number, Bh: number, Ch: number, Dh: number, Eh: number) => number; add5L: (Al: number, Bl: number, Cl: number, Dl: number, El: number) => number; } = {\n fromBig, split, toBig,\n shrSH, shrSL,\n rotrSH, rotrSL, rotrBH, rotrBL,\n rotr32H, rotr32L,\n rotlSH, rotlSL, rotlBH, rotlBL,\n add, add3L, add3H, add4L, add4H, add5H, add5L,\n};\nexport default u64;\n","/**\n * SHA2 hash function. A.k.a. sha256, sha384, sha512, sha512_224, sha512_256.\n * SHA256 is the fastest hash implementable in JS, even faster than Blake3.\n * Check out [RFC 4634](https://datatracker.ietf.org/doc/html/rfc4634) and\n * [FIPS 180-4](https://nvlpubs.nist.gov/nistpubs/FIPS/NIST.FIPS.180-4.pdf).\n * @module\n */\nimport { Chi, HashMD, Maj, SHA224_IV, SHA256_IV, SHA384_IV, SHA512_IV } from './_md.ts';\nimport * as u64 from './_u64.ts';\nimport { type CHash, clean, createHasher, rotr } from './utils.ts';\n\n/**\n * Round constants:\n * First 32 bits of fractional parts of the cube roots of the first 64 primes 2..311)\n */\n// prettier-ignore\nconst SHA256_K = /* @__PURE__ */ Uint32Array.from([\n 0x428a2f98, 0x71374491, 0xb5c0fbcf, 0xe9b5dba5, 0x3956c25b, 0x59f111f1, 0x923f82a4, 0xab1c5ed5,\n 0xd807aa98, 0x12835b01, 0x243185be, 0x550c7dc3, 0x72be5d74, 0x80deb1fe, 0x9bdc06a7, 0xc19bf174,\n 0xe49b69c1, 0xefbe4786, 0x0fc19dc6, 0x240ca1cc, 0x2de92c6f, 0x4a7484aa, 0x5cb0a9dc, 0x76f988da,\n 0x983e5152, 0xa831c66d, 0xb00327c8, 0xbf597fc7, 0xc6e00bf3, 0xd5a79147, 0x06ca6351, 0x14292967,\n 0x27b70a85, 0x2e1b2138, 0x4d2c6dfc, 0x53380d13, 0x650a7354, 0x766a0abb, 0x81c2c92e, 0x92722c85,\n 0xa2bfe8a1, 0xa81a664b, 0xc24b8b70, 0xc76c51a3, 0xd192e819, 0xd6990624, 0xf40e3585, 0x106aa070,\n 0x19a4c116, 0x1e376c08, 0x2748774c, 0x34b0bcb5, 0x391c0cb3, 0x4ed8aa4a, 0x5b9cca4f, 0x682e6ff3,\n 0x748f82ee, 0x78a5636f, 0x84c87814, 0x8cc70208, 0x90befffa, 0xa4506ceb, 0xbef9a3f7, 0xc67178f2\n]);\n\n/** Reusable temporary buffer. \"W\" comes straight from spec. */\nconst SHA256_W = /* @__PURE__ */ new Uint32Array(64);\nexport class SHA256 extends HashMD<SHA256> {\n // We cannot use array here since array allows indexing by variable\n // which means optimizer/compiler cannot use registers.\n protected A: number = SHA256_IV[0] | 0;\n protected B: number = SHA256_IV[1] | 0;\n protected C: number = SHA256_IV[2] | 0;\n protected D: number = SHA256_IV[3] | 0;\n protected E: number = SHA256_IV[4] | 0;\n protected F: number = SHA256_IV[5] | 0;\n protected G: number = SHA256_IV[6] | 0;\n protected H: number = SHA256_IV[7] | 0;\n\n constructor(outputLen: number = 32) {\n super(64, outputLen, 8, false);\n }\n protected get(): [number, number, number, number, number, number, number, number] {\n const { A, B, C, D, E, F, G, H } = this;\n return [A, B, C, D, E, F, G, H];\n }\n // prettier-ignore\n protected set(\n A: number, B: number, C: number, D: number, E: number, F: number, G: number, H: number\n ): void {\n this.A = A | 0;\n this.B = B | 0;\n this.C = C | 0;\n this.D = D | 0;\n this.E = E | 0;\n this.F = F | 0;\n this.G = G | 0;\n this.H = H | 0;\n }\n protected process(view: DataView, offset: number): void {\n // Extend the first 16 words into the remaining 48 words w[16..63] of the message schedule array\n for (let i = 0; i < 16; i++, offset += 4) SHA256_W[i] = view.getUint32(offset, false);\n for (let i = 16; i < 64; i++) {\n const W15 = SHA256_W[i - 15];\n const W2 = SHA256_W[i - 2];\n const s0 = rotr(W15, 7) ^ rotr(W15, 18) ^ (W15 >>> 3);\n const s1 = rotr(W2, 17) ^ rotr(W2, 19) ^ (W2 >>> 10);\n SHA256_W[i] = (s1 + SHA256_W[i - 7] + s0 + SHA256_W[i - 16]) | 0;\n }\n // Compression function main loop, 64 rounds\n let { A, B, C, D, E, F, G, H } = this;\n for (let i = 0; i < 64; i++) {\n const sigma1 = rotr(E, 6) ^ rotr(E, 11) ^ rotr(E, 25);\n const T1 = (H + sigma1 + Chi(E, F, G) + SHA256_K[i] + SHA256_W[i]) | 0;\n const sigma0 = rotr(A, 2) ^ rotr(A, 13) ^ rotr(A, 22);\n const T2 = (sigma0 + Maj(A, B, C)) | 0;\n H = G;\n G = F;\n F = E;\n E = (D + T1) | 0;\n D = C;\n C = B;\n B = A;\n A = (T1 + T2) | 0;\n }\n // Add the compressed chunk to the current hash value\n A = (A + this.A) | 0;\n B = (B + this.B) | 0;\n C = (C + this.C) | 0;\n D = (D + this.D) | 0;\n E = (E + this.E) | 0;\n F = (F + this.F) | 0;\n G = (G + this.G) | 0;\n H = (H + this.H) | 0;\n this.set(A, B, C, D, E, F, G, H);\n }\n protected roundClean(): void {\n clean(SHA256_W);\n }\n destroy(): void {\n this.set(0, 0, 0, 0, 0, 0, 0, 0);\n clean(this.buffer);\n }\n}\n\nexport class SHA224 extends SHA256 {\n protected A: number = SHA224_IV[0] | 0;\n protected B: number = SHA224_IV[1] | 0;\n protected C: number = SHA224_IV[2] | 0;\n protected D: number = SHA224_IV[3] | 0;\n protected E: number = SHA224_IV[4] | 0;\n protected F: number = SHA224_IV[5] | 0;\n protected G: number = SHA224_IV[6] | 0;\n protected H: number = SHA224_IV[7] | 0;\n constructor() {\n super(28);\n }\n}\n\n// SHA2-512 is slower than sha256 in js because u64 operations are slow.\n\n// Round contants\n// First 32 bits of the fractional parts of the cube roots of the first 80 primes 2..409\n// prettier-ignore\nconst K512 = /* @__PURE__ */ (() => u64.split([\n '0x428a2f98d728ae22', '0x7137449123ef65cd', '0xb5c0fbcfec4d3b2f', '0xe9b5dba58189dbbc',\n '0x3956c25bf348b538', '0x59f111f1b605d019', '0x923f82a4af194f9b', '0xab1c5ed5da6d8118',\n '0xd807aa98a3030242', '0x12835b0145706fbe', '0x243185be4ee4b28c', '0x550c7dc3d5ffb4e2',\n '0x72be5d74f27b896f', '0x80deb1fe3b1696b1', '0x9bdc06a725c71235', '0xc19bf174cf692694',\n '0xe49b69c19ef14ad2', '0xefbe4786384f25e3', '0x0fc19dc68b8cd5b5', '0x240ca1cc77ac9c65',\n '0x2de92c6f592b0275', '0x4a7484aa6ea6e483', '0x5cb0a9dcbd41fbd4', '0x76f988da831153b5',\n '0x983e5152ee66dfab', '0xa831c66d2db43210', '0xb00327c898fb213f', '0xbf597fc7beef0ee4',\n '0xc6e00bf33da88fc2', '0xd5a79147930aa725', '0x06ca6351e003826f', '0x142929670a0e6e70',\n '0x27b70a8546d22ffc', '0x2e1b21385c26c926', '0x4d2c6dfc5ac42aed', '0x53380d139d95b3df',\n '0x650a73548baf63de', '0x766a0abb3c77b2a8', '0x81c2c92e47edaee6', '0x92722c851482353b',\n '0xa2bfe8a14cf10364', '0xa81a664bbc423001', '0xc24b8b70d0f89791', '0xc76c51a30654be30',\n '0xd192e819d6ef5218', '0xd69906245565a910', '0xf40e35855771202a', '0x106aa07032bbd1b8',\n '0x19a4c116b8d2d0c8', '0x1e376c085141ab53', '0x2748774cdf8eeb99', '0x34b0bcb5e19b48a8',\n '0x391c0cb3c5c95a63', '0x4ed8aa4ae3418acb', '0x5b9cca4f7763e373', '0x682e6ff3d6b2b8a3',\n '0x748f82ee5defb2fc', '0x78a5636f43172f60', '0x84c87814a1f0ab72', '0x8cc702081a6439ec',\n '0x90befffa23631e28', '0xa4506cebde82bde9', '0xbef9a3f7b2c67915', '0xc67178f2e372532b',\n '0xca273eceea26619c', '0xd186b8c721c0c207', '0xeada7dd6cde0eb1e', '0xf57d4f7fee6ed178',\n '0x06f067aa72176fba', '0x0a637dc5a2c898a6', '0x113f9804bef90dae', '0x1b710b35131c471b',\n '0x28db77f523047d84', '0x32caab7b40c72493', '0x3c9ebe0a15c9bebc', '0x431d67c49c100d4c',\n '0x4cc5d4becb3e42b6', '0x597f299cfc657e2a', '0x5fcb6fab3ad6faec', '0x6c44198c4a475817'\n].map(n => BigInt(n))))();\nconst SHA512_Kh = /* @__PURE__ */ (() => K512[0])();\nconst SHA512_Kl = /* @__PURE__ */ (() => K512[1])();\n\n// Reusable temporary buffers\nconst SHA512_W_H = /* @__PURE__ */ new Uint32Array(80);\nconst SHA512_W_L = /* @__PURE__ */ new Uint32Array(80);\n\nexport class SHA512 extends HashMD<SHA512> {\n // We cannot use array here since array allows indexing by variable\n // which means optimizer/compiler cannot use registers.\n // h -- high 32 bits, l -- low 32 bits\n protected Ah: number = SHA512_IV[0] | 0;\n protected Al: number = SHA512_IV[1] | 0;\n protected Bh: number = SHA512_IV[2] | 0;\n protected Bl: number = SHA512_IV[3] | 0;\n protected Ch: number = SHA512_IV[4] | 0;\n protected Cl: number = SHA512_IV[5] | 0;\n protected Dh: number = SHA512_IV[6] | 0;\n protected Dl: number = SHA512_IV[7] | 0;\n protected Eh: number = SHA512_IV[8] | 0;\n protected El: number = SHA512_IV[9] | 0;\n protected Fh: number = SHA512_IV[10] | 0;\n protected Fl: number = SHA512_IV[11] | 0;\n protected Gh: number = SHA512_IV[12] | 0;\n protected Gl: number = SHA512_IV[13] | 0;\n protected Hh: number = SHA512_IV[14] | 0;\n protected Hl: number = SHA512_IV[15] | 0;\n\n constructor(outputLen: number = 64) {\n super(128, outputLen, 16, false);\n }\n // prettier-ignore\n protected get(): [\n number, number, number, number, number, number, number, number,\n number, number, number, number, number, number, number, number\n ] {\n const { Ah, Al, Bh, Bl, Ch, Cl, Dh, Dl, Eh, El, Fh, Fl, Gh, Gl, Hh, Hl } = this;\n return [Ah, Al, Bh, Bl, Ch, Cl, Dh, Dl, Eh, El, Fh, Fl, Gh, Gl, Hh, Hl];\n }\n // prettier-ignore\n protected set(\n Ah: number, Al: number, Bh: number, Bl: number, Ch: number, Cl: number, Dh: number, Dl: number,\n Eh: number, El: number, Fh: number, Fl: number, Gh: number, Gl: number, Hh: number, Hl: number\n ): void {\n this.Ah = Ah | 0;\n this.Al = Al | 0;\n this.Bh = Bh | 0;\n this.Bl = Bl | 0;\n this.Ch = Ch | 0;\n this.Cl = Cl | 0;\n this.Dh = Dh | 0;\n this.Dl = Dl | 0;\n this.Eh = Eh | 0;\n this.El = El | 0;\n this.Fh = Fh | 0;\n this.Fl = Fl | 0;\n this.Gh = Gh | 0;\n this.Gl = Gl | 0;\n this.Hh = Hh | 0;\n this.Hl = Hl | 0;\n }\n protected process(view: DataView, offset: number): void {\n // Extend the first 16 words into the remaining 64 words w[16..79] of the message schedule array\n for (let i = 0; i < 16; i++, offset += 4) {\n SHA512_W_H[i] = view.getUint32(offset);\n SHA512_W_L[i] = view.getUint32((offset += 4));\n }\n for (let i = 16; i < 80; i++) {\n // s0 := (w[i-15] rightrotate 1) xor (w[i-15] rightrotate 8) xor (w[i-15] rightshift 7)\n const W15h = SHA512_W_H[i - 15] | 0;\n const W15l = SHA512_W_L[i - 15] | 0;\n const s0h = u64.rotrSH(W15h, W15l, 1) ^ u64.rotrSH(W15h, W15l, 8) ^ u64.shrSH(W15h, W15l, 7);\n const s0l = u64.rotrSL(W15h, W15l, 1) ^ u64.rotrSL(W15h, W15l, 8) ^ u64.shrSL(W15h, W15l, 7);\n // s1 := (w[i-2] rightrotate 19) xor (w[i-2] rightrotate 61) xor (w[i-2] rightshift 6)\n const W2h = SHA512_W_H[i - 2] | 0;\n const W2l = SHA512_W_L[i - 2] | 0;\n const s1h = u64.rotrSH(W2h, W2l, 19) ^ u64.rotrBH(W2h, W2l, 61) ^ u64.shrSH(W2h, W2l, 6);\n const s1l = u64.rotrSL(W2h, W2l, 19) ^ u64.rotrBL(W2h, W2l, 61) ^ u64.shrSL(W2h, W2l, 6);\n // SHA256_W[i] = s0 + s1 + SHA256_W[i - 7] + SHA256_W[i - 16];\n const SUMl = u64.add4L(s0l, s1l, SHA512_W_L[i - 7], SHA512_W_L[i - 16]);\n const SUMh = u64.add4H(SUMl, s0h, s1h, SHA512_W_H[i - 7], SHA512_W_H[i - 16]);\n SHA512_W_H[i] = SUMh | 0;\n SHA512_W_L[i] = SUMl | 0;\n }\n let { Ah, Al, Bh, Bl, Ch, Cl, Dh, Dl, Eh, El, Fh, Fl, Gh, Gl, Hh, Hl } = this;\n // Compression function main loop, 80 rounds\n for (let i = 0; i < 80; i++) {\n // S1 := (e rightrotate 14) xor (e rightrotate 18) xor (e rightrotate 41)\n const sigma1h = u64.rotrSH(Eh, El, 14) ^ u64.rotrSH(Eh, El, 18) ^ u64.rotrBH(Eh, El, 41);\n const sigma1l = u64.rotrSL(Eh, El, 14) ^ u64.rotrSL(Eh, El, 18) ^ u64.rotrBL(Eh, El, 41);\n //const T1 = (H + sigma1 + Chi(E, F, G) + SHA256_K[i] + SHA256_W[i]) | 0;\n const CHIh = (Eh & Fh) ^ (~Eh & Gh);\n const CHIl = (El & Fl) ^ (~El & Gl);\n // T1 = H + sigma1 + Chi(E, F, G) + SHA512_K[i] + SHA512_W[i]\n // prettier-ignore\n const T1ll = u64.add5L(Hl, sigma1l, CHIl, SHA512_Kl[i], SHA512_W_L[i]);\n const T1h = u64.add5H(T1ll, Hh, sigma1h, CHIh, SHA512_Kh[i], SHA512_W_H[i]);\n const T1l = T1ll | 0;\n // S0 := (a rightrotate 28) xor (a rightrotate 34) xor (a rightrotate 39)\n const sigma0h = u64.rotrSH(Ah, Al, 28) ^ u64.rotrBH(Ah, Al, 34) ^ u64.rotrBH(Ah, Al, 39);\n const sigma0l = u64.rotrSL(Ah, Al, 28) ^ u64.rotrBL(Ah, Al, 34) ^ u64.rotrBL(Ah, Al, 39);\n const MAJh = (Ah & Bh) ^ (Ah & Ch) ^ (Bh & Ch);\n const MAJl = (Al & Bl) ^ (Al & Cl) ^ (Bl & Cl);\n Hh = Gh | 0;\n Hl = Gl | 0;\n Gh = Fh | 0;\n Gl = Fl | 0;\n Fh = Eh | 0;\n Fl = El | 0;\n ({ h: Eh, l: El } = u64.add(Dh | 0, Dl | 0, T1h | 0, T1l | 0));\n Dh = Ch | 0;\n Dl = Cl | 0;\n Ch = Bh | 0;\n Cl = Bl | 0;\n Bh = Ah | 0;\n Bl = Al | 0;\n const All = u64.add3L(T1l, sigma0l, MAJl);\n Ah = u64.add3H(All, T1h, sigma0h, MAJh);\n Al = All | 0;\n }\n // Add the compressed chunk to the current hash value\n ({ h: Ah, l: Al } = u64.add(this.Ah | 0, this.Al | 0, Ah | 0, Al | 0));\n ({ h: Bh, l: Bl } = u64.add(this.Bh | 0, this.Bl | 0, Bh | 0, Bl | 0));\n ({ h: Ch, l: Cl } = u64.add(this.Ch | 0, this.Cl | 0, Ch | 0, Cl | 0));\n ({ h: Dh, l: Dl } = u64.add(this.Dh | 0, this.Dl | 0, Dh | 0, Dl | 0));\n ({ h: Eh, l: El } = u64.add(this.Eh | 0, this.El | 0, Eh | 0, El | 0));\n ({ h: Fh, l: Fl } = u64.add(this.Fh | 0, this.Fl | 0, Fh | 0, Fl | 0));\n ({ h: Gh, l: Gl } = u64.add(this.Gh | 0, this.Gl | 0, Gh | 0, Gl | 0));\n ({ h: Hh, l: Hl } = u64.add(this.Hh | 0, this.Hl | 0, Hh | 0, Hl | 0));\n this.set(Ah, Al, Bh, Bl, Ch, Cl, Dh, Dl, Eh, El, Fh, Fl, Gh, Gl, Hh, Hl);\n }\n protected roundClean(): void {\n clean(SHA512_W_H, SHA512_W_L);\n }\n destroy(): void {\n clean(this.buffer);\n this.set(0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0);\n }\n}\n\nexport class SHA384 extends SHA512 {\n protected Ah: number = SHA384_IV[0] | 0;\n protected Al: number = SHA384_IV[1] | 0;\n protected Bh: number = SHA384_IV[2] | 0;\n protected Bl: number = SHA384_IV[3] | 0;\n protected Ch: number = SHA384_IV[4] | 0;\n protected Cl: number = SHA384_IV[5] | 0;\n protected Dh: number = SHA384_IV[6] | 0;\n protected Dl: number = SHA384_IV[7] | 0;\n protected Eh: number = SHA384_IV[8] | 0;\n protected El: number = SHA384_IV[9] | 0;\n protected Fh: number = SHA384_IV[10] | 0;\n protected Fl: number = SHA384_IV[11] | 0;\n protected Gh: number = SHA384_IV[12] | 0;\n protected Gl: number = SHA384_IV[13] | 0;\n protected Hh: number = SHA384_IV[14] | 0;\n protected Hl: number = SHA384_IV[15] | 0;\n\n constructor() {\n super(48);\n }\n}\n\n/**\n * Truncated SHA512/256 and SHA512/224.\n * SHA512_IV is XORed with 0xa5a5a5a5a5a5a5a5, then used as \"intermediary\" IV of SHA512/t.\n * Then t hashes string to produce result IV.\n * See `test/misc/sha2-gen-iv.js`.\n */\n\n/** SHA512/224 IV */\nconst T224_IV = /* @__PURE__ */ Uint32Array.from([\n 0x8c3d37c8, 0x19544da2, 0x73e19966, 0x89dcd4d6, 0x1dfab7ae, 0x32ff9c82, 0x679dd514, 0x582f9fcf,\n 0x0f6d2b69, 0x7bd44da8, 0x77e36f73, 0x04c48942, 0x3f9d85a8, 0x6a1d36c8, 0x1112e6ad, 0x91d692a1,\n]);\n\n/** SHA512/256 IV */\nconst T256_IV = /* @__PURE__ */ Uint32Array.from([\n 0x22312194, 0xfc2bf72c, 0x9f555fa3, 0xc84c64c2, 0x2393b86b, 0x6f53b151, 0x96387719, 0x5940eabd,\n 0x96283ee2, 0xa88effe3, 0xbe5e1e25, 0x53863992, 0x2b0199fc, 0x2c85b8aa, 0x0eb72ddc, 0x81c52ca2,\n]);\n\nexport class SHA512_224 extends SHA512 {\n protected Ah: number = T224_IV[0] | 0;\n protected Al: number = T224_IV[1] | 0;\n protected Bh: number = T224_IV[2] | 0;\n protected Bl: number = T224_IV[3] | 0;\n protected Ch: number = T224_IV[4] | 0;\n protected Cl: number = T224_IV[5] | 0;\n protected Dh: number = T224_IV[6] | 0;\n protected Dl: number = T224_IV[7] | 0;\n protected Eh: number = T224_IV[8] | 0;\n protected El: number = T224_IV[9] | 0;\n protected Fh: number = T224_IV[10] | 0;\n protected Fl: number = T224_IV[11] | 0;\n protected Gh: number = T224_IV[12] | 0;\n protected Gl: number = T224_IV[13] | 0;\n protected Hh: number = T224_IV[14] | 0;\n protected Hl: number = T224_IV[15] | 0;\n\n constructor() {\n super(28);\n }\n}\n\nexport class SHA512_256 extends SHA512 {\n protected Ah: number = T256_IV[0] | 0;\n protected Al: number = T256_IV[1] | 0;\n protected Bh: number = T256_IV[2] | 0;\n protected Bl: number = T256_IV[3] | 0;\n protected Ch: number = T256_IV[4] | 0;\n protected Cl: number = T256_IV[5] | 0;\n protected Dh: number = T256_IV[6] | 0;\n protected Dl: number = T256_IV[7] | 0;\n protected Eh: number = T256_IV[8] | 0;\n protected El: number = T256_IV[9] | 0;\n protected Fh: number = T256_IV[10] | 0;\n protected Fl: number = T256_IV[11] | 0;\n protected Gh: number = T256_IV[12] | 0;\n protected Gl: number = T256_IV[13] | 0;\n protected Hh: number = T256_IV[14] | 0;\n protected Hl: number = T256_IV[15] | 0;\n\n constructor() {\n super(32);\n }\n}\n\n/**\n * SHA2-256 hash function from RFC 4634.\n *\n * It is the fastest JS hash, even faster than Blake3.\n * To break sha256 using birthday attack, attackers need to try 2^128 hashes.\n * BTC network is doing 2^70 hashes/sec (2^95 hashes/year) as per 2025.\n */\nexport const sha256: CHash = /* @__PURE__ */ createHasher(() => new SHA256());\n/** SHA2-224 hash function from RFC 4634 */\nexport const sha224: CHash = /* @__PURE__ */ createHasher(() => new SHA224());\n\n/** SHA2-512 hash function from RFC 4634. */\nexport const sha512: CHash = /* @__PURE__ */ createHasher(() => new SHA512());\n/** SHA2-384 hash function from RFC 4634. */\nexport const sha384: CHash = /* @__PURE__ */ createHasher(() => new SHA384());\n\n/**\n * SHA2-512/256 \"truncated\" hash function, with improved resistance to length extension attacks.\n * See the paper on [truncated SHA512](https://eprint.iacr.org/2010/548.pdf).\n */\nexport const sha512_256: CHash = /* @__PURE__ */ createHasher(() => new SHA512_256());\n/**\n * SHA2-512/224 \"truncated\" hash function, with improved resistance to length extension attacks.\n * See the paper on [truncated SHA512](https://eprint.iacr.org/2010/548.pdf).\n */\nexport const sha512_224: CHash = /* @__PURE__ */ createHasher(() => new SHA512_224());\n","/**\n * SHA2-512 a.k.a. sha512 and sha384. It is slower than sha256 in js because u64 operations are slow.\n *\n * Check out [RFC 4634](https://datatracker.ietf.org/doc/html/rfc4634) and\n * [the paper on truncated SHA512/256](https://eprint.iacr.org/2010/548.pdf).\n * @module\n * @deprecated\n */\nimport {\n SHA384 as SHA384n,\n sha384 as sha384n,\n sha512_224 as sha512_224n,\n SHA512_224 as SHA512_224n,\n sha512_256 as sha512_256n,\n SHA512_256 as SHA512_256n,\n SHA512 as SHA512n,\n sha512 as sha512n,\n} from './sha2.ts';\n/** @deprecated Use import from `noble/hashes/sha2` module */\nexport const SHA512: typeof SHA512n = SHA512n;\n/** @deprecated Use import from `noble/hashes/sha2` module */\nexport const sha512: typeof sha512n = sha512n;\n/** @deprecated Use import from `noble/hashes/sha2` module */\nexport const SHA384: typeof SHA384n = SHA384n;\n/** @deprecated Use import from `noble/hashes/sha2` module */\nexport const sha384: typeof sha384n = sha384n;\n/** @deprecated Use import from `noble/hashes/sha2` module */\nexport const SHA512_224: typeof SHA512_224n = SHA512_224n;\n/** @deprecated Use import from `noble/hashes/sha2` module */\nexport const sha512_224: typeof sha512_224n = sha512_224n;\n/** @deprecated Use import from `noble/hashes/sha2` module */\nexport const SHA512_256: typeof SHA512_256n = SHA512_256n;\n/** @deprecated Use import from `noble/hashes/sha2` module */\nexport const sha512_256: typeof sha512_256n = sha512_256n;\n","/**\n * Request Deduplication\n *\n * Prevents double-charging when OpenClaw retries a request after timeout.\n * Tracks in-flight requests and caches completed responses for a short TTL.\n */\n\nimport { createHash } from \"node:crypto\";\n\nexport type CachedResponse = {\n status: number;\n headers: Record<string, string>;\n body: Buffer;\n completedAt: number;\n};\n\ntype InflightEntry = {\n resolvers: Array<(result: CachedResponse) => void>;\n};\n\nconst DEFAULT_TTL_MS = 30_000; // 30 seconds\nconst MAX_BODY_SIZE = 1_048_576; // 1MB\n\n/**\n * Canonicalize JSON by sorting object keys recursively.\n * Ensures identical logical content produces identical string regardless of field order.\n */\nfunction canonicalize(obj: unknown): unknown {\n if (obj === null || typeof obj !== \"object\") {\n return obj;\n }\n if (Array.isArray(obj)) {\n return obj.map(canonicalize);\n }\n const sorted: Record<string, unknown> = {};\n for (const key of Object.keys(obj).sort()) {\n sorted[key] = canonicalize((obj as Record<string, unknown>)[key]);\n }\n return sorted;\n}\n\n/**\n * Strip OpenClaw-injected timestamps from message content.\n * Format: [DAY YYYY-MM-DD HH:MM TZ] at the start of messages.\n * Example: [SUN 2026-02-07 13:30 PST] Hello world\n *\n * This ensures requests with different timestamps but same content hash identically.\n */\nconst TIMESTAMP_PATTERN = /^\\[\\w{3}\\s+\\d{4}-\\d{2}-\\d{2}\\s+\\d{2}:\\d{2}\\s+\\w+\\]\\s*/;\n\nfunction stripTimestamps(obj: unknown): unknown {\n if (obj === null || typeof obj !== \"object\") {\n return obj;\n }\n if (Array.isArray(obj)) {\n return obj.map(stripTimestamps);\n }\n const result: Record<string, unknown> = {};\n for (const [key, value] of Object.entries(obj as Record<string, unknown>)) {\n if (key === \"content\" && typeof value === \"string\") {\n // Strip timestamp prefix from message content\n result[key] = value.replace(TIMESTAMP_PATTERN, \"\");\n } else {\n result[key] = stripTimestamps(value);\n }\n }\n return result;\n}\n\nexport class RequestDeduplicator {\n private inflight = new Map<string, InflightEntry>();\n private completed = new Map<string, CachedResponse>();\n private ttlMs: number;\n\n constructor(ttlMs = DEFAULT_TTL_MS) {\n this.ttlMs = ttlMs;\n }\n\n /** Hash request body to create a dedup key. */\n static hash(body: Buffer): string {\n // Canonicalize JSON to ensure consistent hashing regardless of field order.\n // Also strip OpenClaw-injected timestamps so retries with different timestamps\n // still match the same dedup key.\n let content = body;\n try {\n const parsed = JSON.parse(body.toString());\n const stripped = stripTimestamps(parsed);\n const canonical = canonicalize(stripped);\n content = Buffer.from(JSON.stringify(canonical));\n } catch {\n // Not valid JSON, use raw bytes\n }\n return createHash(\"sha256\").update(content).digest(\"hex\").slice(0, 16);\n }\n\n /** Check if a response is cached for this key. */\n getCached(key: string): CachedResponse | undefined {\n const entry = this.completed.get(key);\n if (!entry) return undefined;\n if (Date.now() - entry.completedAt > this.ttlMs) {\n this.completed.delete(key);\n return undefined;\n }\n return entry;\n }\n\n /** Check if a request with this key is currently in-flight. Returns a promise to wait on. */\n getInflight(key: string): Promise<CachedResponse> | undefined {\n const entry = this.inflight.get(key);\n if (!entry) return undefined;\n return new Promise<CachedResponse>((resolve) => {\n entry.resolvers.push(resolve);\n });\n }\n\n /** Mark a request as in-flight. */\n markInflight(key: string): void {\n this.inflight.set(key, {\n resolvers: [],\n });\n }\n\n /** Complete an in-flight request — cache result and notify waiters. */\n complete(key: string, result: CachedResponse): void {\n // Only cache responses within size limit\n if (result.body.length <= MAX_BODY_SIZE) {\n this.completed.set(key, result);\n }\n\n const entry = this.inflight.get(key);\n if (entry) {\n for (const resolve of entry.resolvers) {\n resolve(result);\n }\n this.inflight.delete(key);\n }\n\n this.prune();\n }\n\n /** Remove an in-flight entry on error (don't cache failures).\n * Also rejects any waiters so they can retry independently. */\n removeInflight(key: string): void {\n const entry = this.inflight.get(key);\n if (entry) {\n // Resolve waiters with a sentinel error response so they don't hang forever.\n // Waiters will see a 503 and can retry on their own.\n const errorBody = Buffer.from(\n JSON.stringify({\n error: { message: \"Original request failed, please retry\", type: \"dedup_origin_failed\" },\n }),\n );\n for (const resolve of entry.resolvers) {\n resolve({\n status: 503,\n headers: { \"content-type\": \"application/json\" },\n body: errorBody,\n completedAt: Date.now(),\n });\n }\n this.inflight.delete(key);\n }\n }\n\n /** Prune expired completed entries. */\n private prune(): void {\n const now = Date.now();\n for (const [key, entry] of this.completed) {\n if (now - entry.completedAt > this.ttlMs) {\n this.completed.delete(key);\n }\n }\n }\n}\n","/**\n * Response Cache for LLM Completions\n *\n * Caches LLM responses by request hash (model + messages + params).\n * Inspired by LiteLLM's caching system. Returns cached responses for\n * identical requests, saving both cost and latency.\n *\n * Features:\n * - TTL-based expiration (default 10 minutes)\n * - LRU eviction when cache is full\n * - Size limits per item (1MB max)\n * - Heap-based expiration tracking for efficient pruning\n */\n\nimport { createHash } from \"node:crypto\";\nimport { logger } from \"./plugin-logger.js\";\n\nexport type CachedLLMResponse = {\n body: Buffer;\n status: number;\n headers: Record<string, string>;\n model: string;\n cachedAt: number;\n expiresAt: number;\n};\n\nexport type ResponseCacheConfig = {\n /** Maximum number of cached responses. Default: 200 */\n maxSize?: number;\n /** Default TTL in seconds. Default: 600 (10 minutes) */\n defaultTTL?: number;\n /** Maximum size per cached item in bytes. Default: 1MB */\n maxItemSize?: number;\n /** Enable/disable cache. Default: true */\n enabled?: boolean;\n};\n\nconst DEFAULT_CONFIG: Required<ResponseCacheConfig> = {\n maxSize: 200,\n defaultTTL: 600,\n maxItemSize: 1_048_576, // 1MB\n enabled: true,\n};\n\n/**\n * Canonicalize JSON by sorting object keys recursively.\n * Ensures identical logical content produces identical hash.\n */\nfunction canonicalize(obj: unknown): unknown {\n if (obj === null || typeof obj !== \"object\") {\n return obj;\n }\n if (Array.isArray(obj)) {\n return obj.map(canonicalize);\n }\n const sorted: Record<string, unknown> = {};\n for (const key of Object.keys(obj).sort()) {\n sorted[key] = canonicalize((obj as Record<string, unknown>)[key]);\n }\n return sorted;\n}\n\n/**\n * Strip fields that shouldn't affect cache key:\n * - stream (we handle streaming separately)\n * - timestamps injected by OpenClaw\n * - request IDs\n */\nconst TIMESTAMP_PATTERN = /^\\[\\w{3}\\s+\\d{4}-\\d{2}-\\d{2}\\s+\\d{2}:\\d{2}\\s+\\w+\\]\\s*/;\n\nfunction normalizeForCache(obj: Record<string, unknown>): Record<string, unknown> {\n const result: Record<string, unknown> = {};\n\n for (const [key, value] of Object.entries(obj)) {\n // Skip fields that don't affect response content\n if ([\"stream\", \"user\", \"request_id\", \"x-request-id\"].includes(key)) {\n continue;\n }\n\n if (key === \"messages\" && Array.isArray(value)) {\n // Strip timestamps from message content\n result[key] = value.map((msg: unknown) => {\n if (typeof msg === \"object\" && msg !== null) {\n const m = msg as Record<string, unknown>;\n if (typeof m.content === \"string\") {\n return { ...m, content: m.content.replace(TIMESTAMP_PATTERN, \"\") };\n }\n }\n return msg;\n });\n } else {\n result[key] = value;\n }\n }\n\n return result;\n}\n\nexport class ResponseCache {\n private cache = new Map<string, CachedLLMResponse>();\n private expirationHeap: Array<{ expiresAt: number; key: string }> = [];\n private config: Required<ResponseCacheConfig>;\n\n // Stats for monitoring\n private stats = {\n hits: 0,\n misses: 0,\n evictions: 0,\n };\n\n constructor(config: ResponseCacheConfig = {}) {\n // Filter out undefined values so they don't override defaults\n const filtered = Object.fromEntries(\n Object.entries(config).filter(([, v]) => v !== undefined),\n ) as ResponseCacheConfig;\n this.config = { ...DEFAULT_CONFIG, ...filtered };\n }\n\n /**\n * Generate cache key from request body.\n * Hashes: model + messages + temperature + max_tokens + other params\n */\n static generateKey(body: Buffer | string): string {\n try {\n const parsed = JSON.parse(typeof body === \"string\" ? body : body.toString());\n const normalized = normalizeForCache(parsed);\n const canonical = canonicalize(normalized);\n const keyContent = JSON.stringify(canonical);\n return createHash(\"sha256\").update(keyContent).digest(\"hex\").slice(0, 32);\n } catch {\n // Fallback: hash raw body\n const content = typeof body === \"string\" ? body : body.toString();\n return createHash(\"sha256\").update(content).digest(\"hex\").slice(0, 32);\n }\n }\n\n /**\n * Check if caching is enabled for this request.\n * Respects cache control headers and request params.\n */\n shouldCache(body: Buffer | string, headers?: Record<string, string>): boolean {\n if (!this.config.enabled) return false;\n\n // Respect Cache-Control: no-cache header\n if (headers?.[\"cache-control\"]?.includes(\"no-cache\")) {\n return false;\n }\n\n // Check for explicit cache disable in body\n try {\n const parsed = JSON.parse(typeof body === \"string\" ? body : body.toString());\n if (parsed.cache === false || parsed.no_cache === true) {\n return false;\n }\n } catch {\n // Not JSON, allow caching\n }\n\n return true;\n }\n\n /**\n * Get cached response if available and not expired.\n */\n get(key: string): CachedLLMResponse | undefined {\n const entry = this.cache.get(key);\n if (!entry) {\n this.stats.misses++;\n return undefined;\n }\n\n // Check expiration\n if (Date.now() > entry.expiresAt) {\n this.cache.delete(key);\n this.stats.misses++;\n return undefined;\n }\n\n this.stats.hits++;\n return entry;\n }\n\n /**\n * Cache a response with optional custom TTL.\n */\n set(\n key: string,\n response: {\n body: Buffer;\n status: number;\n headers: Record<string, string>;\n model: string;\n },\n ttlSeconds?: number,\n ): void {\n // Don't cache if disabled or maxSize is 0\n if (!this.config.enabled || this.config.maxSize <= 0) return;\n\n // Don't cache if item too large\n if (response.body.length > this.config.maxItemSize) {\n logger.info(`[ResponseCache] Skipping cache - item too large: ${response.body.length} bytes`);\n return;\n }\n\n // Don't cache error responses\n if (response.status >= 400) {\n return;\n }\n\n // Evict if at capacity\n if (this.cache.size >= this.config.maxSize) {\n this.evict();\n }\n\n const now = Date.now();\n const ttl = ttlSeconds ?? this.config.defaultTTL;\n const expiresAt = now + ttl * 1000;\n\n const entry: CachedLLMResponse = {\n ...response,\n cachedAt: now,\n expiresAt,\n };\n\n this.cache.set(key, entry);\n this.expirationHeap.push({ expiresAt, key });\n }\n\n /**\n * Evict expired and oldest entries to make room.\n */\n private evict(): void {\n const now = Date.now();\n\n // First pass: remove expired entries\n this.expirationHeap.sort((a, b) => a.expiresAt - b.expiresAt);\n\n while (this.expirationHeap.length > 0) {\n const oldest = this.expirationHeap[0];\n\n // Check if entry still exists and matches\n const entry = this.cache.get(oldest.key);\n if (!entry || entry.expiresAt !== oldest.expiresAt) {\n // Stale heap entry, remove it\n this.expirationHeap.shift();\n continue;\n }\n\n if (oldest.expiresAt <= now) {\n // Expired, remove both\n this.cache.delete(oldest.key);\n this.expirationHeap.shift();\n this.stats.evictions++;\n } else {\n // Not expired, stop\n break;\n }\n }\n\n // Second pass: if still at capacity, evict oldest\n while (this.cache.size >= this.config.maxSize && this.expirationHeap.length > 0) {\n const oldest = this.expirationHeap.shift()!;\n if (this.cache.has(oldest.key)) {\n this.cache.delete(oldest.key);\n this.stats.evictions++;\n }\n }\n }\n\n /**\n * Get cache statistics.\n */\n getStats(): {\n size: number;\n maxSize: number;\n hits: number;\n misses: number;\n evictions: number;\n hitRate: string;\n } {\n const total = this.stats.hits + this.stats.misses;\n const hitRate = total > 0 ? ((this.stats.hits / total) * 100).toFixed(1) + \"%\" : \"0%\";\n\n return {\n size: this.cache.size,\n maxSize: this.config.maxSize,\n hits: this.stats.hits,\n misses: this.stats.misses,\n evictions: this.stats.evictions,\n hitRate,\n };\n }\n\n /**\n * Clear all cached entries.\n */\n clear(): void {\n this.cache.clear();\n this.expirationHeap = [];\n }\n\n /**\n * Check if cache is enabled.\n */\n isEnabled(): boolean {\n return this.config.enabled;\n }\n}\n","/**\n * Session Journal - Memory layer for ckcloud\n *\n * Maintains a compact record of key actions per session, enabling agents\n * to recall earlier work even when OpenClaw's sessions_history is truncated.\n *\n * How it works:\n * 1. As LLM responses flow through, extracts key actions (\"I created X\", \"I fixed Y\")\n * 2. Stores them in a compact journal per session\n * 3. When a request mentions past work (\"what did you do today?\"), injects the journal\n */\n\nexport interface JournalEntry {\n timestamp: number;\n action: string; // Compact description: \"Created login component\"\n model?: string;\n}\n\nexport interface SessionJournalConfig {\n /** Maximum entries per session (default: 100) */\n maxEntries?: number;\n /** Maximum age of entries in ms (default: 24 hours) */\n maxAgeMs?: number;\n /** Maximum events to extract per response (default: 5) */\n maxEventsPerResponse?: number;\n}\n\nconst DEFAULT_CONFIG: Required<SessionJournalConfig> = {\n maxEntries: 100,\n maxAgeMs: 24 * 60 * 60 * 1000, // 24 hours\n maxEventsPerResponse: 5,\n};\n\nexport class SessionJournal {\n private journals: Map<string, JournalEntry[]> = new Map();\n private config: Required<SessionJournalConfig>;\n\n constructor(config?: SessionJournalConfig) {\n this.config = { ...DEFAULT_CONFIG, ...config };\n }\n\n /**\n * Extract key events from assistant response content.\n * Looks for patterns like \"I created...\", \"I fixed...\", \"Successfully...\"\n */\n extractEvents(content: string): string[] {\n if (!content || typeof content !== \"string\") {\n return [];\n }\n\n const events: string[] = [];\n const seen = new Set<string>();\n\n // Patterns for identifying key actions\n // Note: Patterns allow optional words like \"also\", \"then\", \"have\" between \"I\" and verb\n const patterns = [\n // Creation patterns\n /I (?:also |then |have |)?(?:created|implemented|added|wrote|built|generated|set up|initialized) ([^.!?\\n]{10,150})/gi,\n // Fix patterns\n /I (?:also |then |have |)?(?:fixed|resolved|solved|patched|corrected|addressed|debugged) ([^.!?\\n]{10,150})/gi,\n // Completion patterns\n /I (?:also |then |have |)?(?:completed|finished|done with|wrapped up) ([^.!?\\n]{10,150})/gi,\n // Update patterns\n /I (?:also |then |have |)?(?:updated|modified|changed|refactored|improved|enhanced|optimized) ([^.!?\\n]{10,150})/gi,\n // Success patterns\n /Successfully ([^.!?\\n]{10,150})/gi,\n // Tool usage patterns (when agent uses tools)\n /I (?:also |then |have |)?(?:ran|executed|called|invoked) ([^.!?\\n]{10,100})/gi,\n ];\n\n for (const pattern of patterns) {\n // Reset pattern lastIndex for each iteration\n pattern.lastIndex = 0;\n\n let match;\n while ((match = pattern.exec(content)) !== null) {\n const action = match[0].trim();\n\n // Skip if already seen (dedup)\n const normalized = action.toLowerCase();\n if (seen.has(normalized)) {\n continue;\n }\n\n // Validate length (not too short or too long)\n if (action.length >= 15 && action.length <= 200) {\n events.push(action);\n seen.add(normalized);\n }\n\n // Stop if we have enough events\n if (events.length >= this.config.maxEventsPerResponse) {\n break;\n }\n }\n\n if (events.length >= this.config.maxEventsPerResponse) {\n break;\n }\n }\n\n return events;\n }\n\n /**\n * Record events to the session journal.\n */\n record(sessionId: string, events: string[], model?: string): void {\n if (!sessionId || !events.length) {\n return;\n }\n\n const journal = this.journals.get(sessionId) || [];\n const now = Date.now();\n\n for (const action of events) {\n journal.push({\n timestamp: now,\n action,\n model,\n });\n }\n\n // Trim old entries and enforce max count\n const cutoff = now - this.config.maxAgeMs;\n const trimmed = journal.filter((e) => e.timestamp > cutoff).slice(-this.config.maxEntries);\n\n this.journals.set(sessionId, trimmed);\n }\n\n /**\n * Check if the user message indicates a need for historical context.\n */\n needsContext(lastUserMessage: string): boolean {\n if (!lastUserMessage || typeof lastUserMessage !== \"string\") {\n return false;\n }\n\n const lower = lastUserMessage.toLowerCase();\n\n // Trigger phrases that indicate user wants to recall past work\n const triggers = [\n // Direct questions about past work\n \"what did you do\",\n \"what have you done\",\n \"what did we do\",\n \"what have we done\",\n // Temporal references\n \"earlier\",\n \"before\",\n \"previously\",\n \"this session\",\n \"today\",\n \"so far\",\n // Summary requests\n \"remind me\",\n \"summarize\",\n \"summary of\",\n \"recap\",\n // Progress inquiries\n \"your work\",\n \"your progress\",\n \"accomplished\",\n \"achievements\",\n \"completed tasks\",\n ];\n\n return triggers.some((t) => lower.includes(t));\n }\n\n /**\n * Format the journal for injection into system message.\n * Returns null if journal is empty.\n */\n format(sessionId: string): string | null {\n const journal = this.journals.get(sessionId);\n if (!journal?.length) {\n return null;\n }\n\n const lines = journal.map((e) => {\n const time = new Date(e.timestamp).toLocaleTimeString(\"en-US\", {\n hour: \"2-digit\",\n minute: \"2-digit\",\n hour12: true,\n });\n return `- ${time}: ${e.action}`;\n });\n\n return `[Session Memory - Key Actions]\\n${lines.join(\"\\n\")}`;\n }\n\n /**\n * Get the raw journal entries for a session (for debugging/testing).\n */\n getEntries(sessionId: string): JournalEntry[] {\n return this.journals.get(sessionId) || [];\n }\n\n /**\n * Clear journal for a specific session.\n */\n clear(sessionId: string): void {\n this.journals.delete(sessionId);\n }\n\n /**\n * Clear all journals.\n */\n clearAll(): void {\n this.journals.clear();\n }\n\n /**\n * Get stats about the journal.\n */\n getStats(): { sessions: number; totalEntries: number } {\n let totalEntries = 0;\n for (const entries of this.journals.values()) {\n totalEntries += entries.length;\n }\n return {\n sessions: this.journals.size,\n totalEntries,\n };\n }\n}\n"],"mappings":"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AAA,MACA;AAAA;AAAA,MAEA;AAAA,MACA;AAAA,MACA;AAAA,MACA;AAAA,MACA;AAAA,MACA;AAAA;AAAA,MAEA;AAAA,MACA;AAAA,MACA;AAAA,MACA;AAAA,MACA;AAAA,MACA;AAAA,MACA;AAAA,MACA;AAAA,MACA;AAAA,MACA;AAAA;AAAA,MAEA;AAAA,MACA;AAAA,MACA;AAAA,MACA;AAAA,MACA;AAAA,MACA;AAAA,MACA;AAAA,MACA;AAAA,MACA;AAAA,MACA;AAAA;AAAA,MAEA;AAAA,MACA;AAAA,MACA;AAAA,MACA;AAAA,MACA;AAAA,MACA;AAAA,MACA;AAAA,MACA;AAAA,MACA;AAAA,MACA;AAAA;AAAA,MAEA;AAAA,MACA;AAAA,MACA;AAAA,MACA;AAAA,MACA;AAAA,MACA;AAAA,MACA;AAAA,MACA;AAAA,MACA;AAAA,MACA;AAAA;AAAA,MAEA;AAAA,MACA;AAAA,MACA;AAAA,MACA;AAAA,MACA;AAAA,MACA;AAAA,MACA;AAAA,MACA;AAAA,MACA;AAAA,MACA;AAAA;AAAA,MAEA;AAAA,MACA;AAAA,MACA;AAAA,MACA;AAAA,MACA;AAAA,MACA;AAAA,MACA;AAAA,MACA;AAAA,MACA;AAAA,MACA;AAAA,IACF;AAAA,IACA,mBAAmB;AAAA;AAAA,MAEjB;AAAA,MACA;AAAA,MACA;AAAA,MACA;AAAA,MACA;AAAA,MACA;AAAA,MACA;AAAA,MACA;AAAA,MACA;AAAA;AAAA,MAEA;AAAA,MACA;AAAA,MACA;AAAA,MACA;AAAA,MACA;AAAA,MACA;AAAA,MACA;AAAA,MACA;AAAA;AAAA,MAEA;AAAA,MACA;AAAA,MACA;AAAA,MACA;AAAA,MACA;AAAA;AAAA,MAEA;AAAA,MACA;AAAA,MACA;AAAA,MACA;AAAA,MACA;AAAA,MACA;AAAA,MACA;AAAA,MACA;AAAA,MACA;AAAA,MACA;AAAA,MACA;AAAA,MACA;AAAA,MACA;AAAA;AAAA,MAEA;AAAA,MACA;AAAA,MACA;AAAA,MACA;AAAA,MACA;AAAA,MACA;AAAA,MACA;AAAA,MACA;AAAA,MACA;AAAA;AAAA,MAEA;AAAA,MACA;AAAA,MACA;AAAA,MACA;AAAA,MACA;AAAA,MACA;AAAA,MACA;AAAA,MACA;AAAA,MACA;AAAA;AAAA,MAEA;AAAA,MACA;AAAA,MACA;AAAA,MACA;AAAA,MACA;AAAA,MACA;AAAA,MACA;AAAA,MACA;AAAA,MACA;AAAA;AAAA,MAEA;AAAA,MACA;AAAA,MACA;AAAA,MACA;AAAA,MACA;AAAA,MACA;AAAA,MACA;AAAA,MACA;AAAA;AAAA,MAEA;AAAA,MACA;AAAA,MACA;AAAA,MACA;AAAA,MACA;AAAA,MACA;AAAA,MACA;AAAA,MACA;AAAA,MACA;AAAA,IACF;AAAA,IACA,gBAAgB;AAAA;AAAA,MAEd;AAAA,MACA;AAAA,MACA;AAAA,MACA;AAAA,MACA;AAAA,MACA;AAAA,MACA;AAAA,MACA;AAAA,MACA;AAAA;AAAA,MAEA;AAAA,MACA;AAAA,MACA;AAAA,MACA;AAAA,MACA;AAAA,MACA;AAAA,MACA;AAAA,MACA;AAAA,MACA;AAAA;AAAA,MAEA;AAAA,MACA;AAAA,MACA;AAAA,MACA;AAAA,MACA;AAAA,MACA;AAAA,MACA;AAAA;AAAA,MAEA;AAAA,MACA;AAAA,MACA;AAAA,MACA;AAAA,MACA;AAAA,MACA;AAAA,MACA;AAAA,MACA;AAAA,MACA;AAAA,MACA;AAAA,MACA;AAAA;AAAA,MAEA;AAAA,MACA;AAAA,MACA;AAAA,MACA;AAAA,MACA;AAAA,MACA;AAAA,MACA;AAAA,MACA;AAAA,MACA;AAAA,MACA;AAAA;AAAA,MAEA;AAAA,MACA;AAAA,MACA;AAAA,MACA;AAAA,MACA;AAAA,MACA;AAAA,MACA;AAAA,MACA;AAAA,MACA;AAAA;AAAA,MAEA;AAAA,MACA;AAAA,MACA;AAAA,MACA;AAAA,MACA;AAAA,MACA;AAAA,MACA;AAAA,MACA;AAAA,MACA;AAAA;AAAA,MAEA;AAAA,MACA;AAAA,MACA;AAAA,MACA;AAAA,MACA;AAAA,MACA;AAAA,MACA;AAAA,MACA;AAAA;AAAA,MAEA;AAAA,MACA;AAAA,MACA;AAAA,MACA;AAAA,MACA;AAAA,MACA;AAAA,MACA;AAAA,MACA;AAAA,IACF;AAAA,IACA,mBAAmB;AAAA;AAAA,MAEjB;AAAA,MACA;AAAA,MACA;AAAA,MACA;AAAA,MACA;AAAA,MACA;AAAA,MACA;AAAA,MACA;AAAA;AAAA,MAEA;AAAA,MACA;AAAA,MACA;AAAA,MACA;AAAA,MACA;AAAA,MACA;AAAA,MACA;AAAA;AAAA,MAEA;AAAA,MACA;AAAA,MACA;AAAA,MACA;AAAA,MACA;AAAA,MACA;AAAA;AAAA,MAEA;AAAA,MACA;AAAA,MACA;AAAA,MACA;AAAA,MACA;AAAA,MACA;AAAA,MACA;AAAA,MACA;AAAA,MACA;AAAA;AAAA,MAEA;AAAA,MACA;AAAA,MACA;AAAA,MACA;AAAA,MACA;AAAA,MACA;AAAA,MACA;AAAA,MACA;AAAA;AAAA,MAEA;AAAA,MACA;AAAA,MACA;AAAA,MACA;AAAA,MACA;AAAA,MACA;AAAA,MACA;AAAA;AAAA,MAEA;AAAA,MACA;AAAA,MACA;AAAA,MACA;AAAA,MACA;AAAA,MACA;AAAA,MACA;AAAA;AAAA,MAEA;AAAA,MACA;AAAA,MACA;AAAA,MACA;AAAA,MACA;AAAA,MACA;AAAA,MACA;AAAA;AAAA,MAEA;AAAA,MACA;AAAA,MACA;AAAA,MACA;AAAA,MACA;AAAA,MACA;AAAA,MACA;AAAA,IACF;AAAA,IACA,kBAAkB;AAAA;AAAA,MAEhB;AAAA,MACA;AAAA,MACA;AAAA,MACA;AAAA,MACA;AAAA,MACA;AAAA,MACA;AAAA;AAAA,MAEA;AAAA,MACA;AAAA,MACA;AAAA,MACA;AAAA,MACA;AAAA,MACA;AAAA,MACA;AAAA;AAAA,MAEA;AAAA,MACA;AAAA,MACA;AAAA,MACA;AAAA,MACA;AAAA,MACA;AAAA;AAAA,MAEA;AAAA,MACA;AAAA,MACA;AAAA,MACA;AAAA,MACA;AAAA,MACA;AAAA,MACA;AAAA,MACA;AAAA,MACA;AAAA,MACA;AAAA;AAAA,MAEA;AAAA,MACA;AAAA,MACA;AAAA,MACA;AAAA,MACA;AAAA,MACA;AAAA,MACA;AAAA,MACA;AAAA;AAAA,MAEA;AAAA,MACA;AAAA,MACA;AAAA,MACA;AAAA,MACA;AAAA,MACA;AAAA,MACA;AAAA;AAAA,MAEA;AAAA,MACA;AAAA,MACA;AAAA,MACA;AAAA,MACA;AAAA,MACA;AAAA;AAAA,MAEA;AAAA,MACA;AAAA,MACA;AAAA,MACA;AAAA,MACA;AAAA,MACA;AAAA,MACA;AAAA;AAAA,MAEA;AAAA,MACA;AAAA,MACA;AAAA,MACA;AAAA,MACA;AAAA,MACA;AAAA,MACA;AAAA,IACF;AAAA;AAAA,IAGA,iBAAiB;AAAA;AAAA,MAEf;AAAA,MACA;AAAA,MACA;AAAA,MACA;AAAA,MACA;AAAA,MACA;AAAA,MACA;AAAA,MACA;AAAA,MACA;AAAA,MACA;AAAA;AAAA,MAEA;AAAA,MACA;AAAA,MACA;AAAA,MACA;AAAA,MACA;AAAA,MACA;AAAA,MACA;AAAA,MACA;AAAA,MACA;AAAA;AAAA,MAEA;AAAA,MACA;AAAA,MACA;AAAA,MACA;AAAA,MACA;AAAA,MACA;AAAA,MACA;AAAA,MACA;AAAA;AAAA,MAEA;AAAA,MACA;AAAA,MACA;AAAA,MACA;AAAA,MACA;AAAA,MACA;AAAA,MACA;AAAA,MACA;AAAA,MACA;AAAA,MACA;AAAA,MACA;AAAA,MACA;AAAA,MACA;AAAA,MACA;AAAA,MACA;AAAA,MACA;AAAA;AAAA,MAEA;AAAA,MACA;AAAA,MACA;AAAA,MACA;AAAA,MACA;AAAA,MACA;AAAA,MACA;AAAA,MACA;AAAA,MACA;AAAA,MACA;AAAA;AAAA,MAEA;AAAA,MACA;AAAA,MACA;AAAA,MACA;AAAA,MACA;AAAA,MACA;AAAA,MACA;AAAA,MACA;AAAA;AAAA,MAEA;AAAA,MACA;AAAA,MACA;AAAA,MACA;AAAA,MACA;AAAA,MACA;AAAA,MACA;AAAA,MACA;AAAA;AAAA,MAEA;AAAA,MACA;AAAA,MACA;AAAA,MACA;AAAA,MACA;AAAA,MACA;AAAA,MACA;AAAA;AAAA,MAEA;AAAA,MACA;AAAA,MACA;AAAA,MACA;AAAA,MACA;AAAA,MACA;AAAA,MACA;AAAA,MACA;AAAA,IACF;AAAA,IACA,sBAAsB;AAAA;AAAA,MAEpB;AAAA,MACA;AAAA,MACA;AAAA,MACA;AAAA,MACA;AAAA,MACA;AAAA,MACA;AAAA,MACA;AAAA,MACA;AAAA,MACA;AAAA;AAAA,MAEA;AAAA,MACA;AAAA,MACA;AAAA,MACA;AAAA,MACA;AAAA,MACA;AAAA,MACA;AAAA,MACA;AAAA;AAAA,MAEA;AAAA,MACA;AAAA,MACA;AAAA,MACA;AAAA,MACA;AAAA;AAAA,MAEA;AAAA,MACA;AAAA,MACA;AAAA,MACA;AAAA,MACA;AAAA,MACA;AAAA,MACA;AAAA,MACA;AAAA;AAAA,MAEA;AAAA,MACA;AAAA,MACA;AAAA,MACA;AAAA,MACA;AAAA,MACA;AAAA,MACA;AAAA,MACA;AAAA;AAAA,MAEA;AAAA,MACA;AAAA,MACA;AAAA,MACA;AAAA,MACA;AAAA,MACA;AAAA,MACA;AAAA,MACA;AAAA;AAAA,MAEA;AAAA,MACA;AAAA,MACA;AAAA,MACA;AAAA,MACA;AAAA,MACA;AAAA,MACA;AAAA,MACA;AAAA;AAAA,MAEA;AAAA,MACA;AAAA,MACA;AAAA,MACA;AAAA,MACA;AAAA,MACA;AAAA;AAAA,MAEA;AAAA,MACA;AAAA,MACA;AAAA,MACA;AAAA,MACA;AAAA,MACA;AAAA,MACA;AAAA,MACA;AAAA,IACF;AAAA,IACA,sBAAsB;AAAA;AAAA,MAEpB;AAAA,MACA;AAAA,MACA;AAAA,MACA;AAAA,MACA;AAAA,MACA;AAAA,MACA;AAAA,MACA;AAAA,MACA;AAAA;AAAA,MAEA;AAAA,MACA;AAAA,MACA;AAAA;AAAA,MAEA;AAAA,MACA;AAAA,MACA;AAAA;AAAA,MAEA;AAAA,MACA;AAAA,MACA;AAAA;AAAA,MAEA;AAAA,MACA;AAAA,MACA;AAAA;AAAA,MAEA;AAAA,MACA;AAAA,MACA;AAAA;AAAA,MAEA;AAAA,MACA;AAAA,MACA;AAAA;AAAA,MAEA;AAAA,MACA;AAAA,MACA;AAAA;AAAA,MAEA;AAAA,MACA;AAAA,MACA;AAAA,IACF;AAAA,IACA,mBAAmB;AAAA;AAAA,MAEjB;AAAA,MACA;AAAA,MACA;AAAA,MACA;AAAA,MACA;AAAA,MACA;AAAA,MACA;AAAA,MACA;AAAA,MACA;AAAA;AAAA,MAEA;AAAA,MACA;AAAA,MACA;AAAA,MACA;AAAA,MACA;AAAA,MACA;AAAA,MACA;AAAA;AAAA,MAEA;AAAA,MACA;AAAA,MACA;AAAA,MACA;AAAA,MACA;AAAA,MACA;AAAA;AAAA,MAEA;AAAA,MACA;AAAA,MACA;AAAA,MACA;AAAA,MACA;AAAA,MACA;AAAA,MACA;AAAA,MACA;AAAA;AAAA,MAEA;AAAA,MACA;AAAA,MACA;AAAA,MACA;AAAA,MACA;AAAA,MACA;AAAA,MACA;AAAA,MACA;AAAA;AAAA,MAEA;AAAA,MACA;AAAA,MACA;AAAA,MACA;AAAA,MACA;AAAA,MACA;AAAA,MACA;AAAA;AAAA,MAEA;AAAA,MACA;AAAA,MACA;AAAA,MACA;AAAA,MACA;AAAA,MACA;AAAA,MACA;AAAA;AAAA,MAEA;AAAA,MACA;AAAA,MACA;AAAA,MACA;AAAA,MACA;AAAA,MACA;AAAA,MACA;AAAA;AAAA,MAEA;AAAA,MACA;AAAA,MACA;AAAA,MACA;AAAA,MACA;AAAA,MACA;AAAA,MACA;AAAA,IACF;AAAA,IACA,kBAAkB;AAAA;AAAA,MAEhB;AAAA,MACA;AAAA,MACA;AAAA,MACA;AAAA,MACA;AAAA,MACA;AAAA,MACA;AAAA,MACA;AAAA;AAAA,MAEA;AAAA,MACA;AAAA,MACA;AAAA,MACA;AAAA,MACA;AAAA,MACA;AAAA;AAAA,MAEA;AAAA,MACA;AAAA,MACA;AAAA,MACA;AAAA,MACA;AAAA;AAAA,MAEA;AAAA,MACA;AAAA,MACA;AAAA,MACA;AAAA,MACA;AAAA,MACA;AAAA,MACA;AAAA,MACA;AAAA,MACA;AAAA;AAAA,MAEA;AAAA,MACA;AAAA,MACA;AAAA,MACA;AAAA,MACA;AAAA,MACA;AAAA,MACA;AAAA;AAAA,MAEA;AAAA,MACA;AAAA,MACA;AAAA,MACA;AAAA,MACA;AAAA,MACA;AAAA;AAAA,MAEA;AAAA,M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","names":["join","homedir","require","homedir","join","mkdir","writeFile","createPublicClient","http","base","privateKeyToAccount","payload","response","CACHE_TTL_MS","join","join","join","homedir","LOG_DIR","logger","confidence","supportsToolCalling","supportsVision","mkdir","join","homedir","privateKeyToAccount","finished","_32n","finished","sha512","sha512","join","homedir","mkdir","privateKeyToAccount","result","createHash","DEFAULT_TTL_MS","createHash","canonicalize","TIMESTAMP_PATTERN","createHash","DEFAULT_CONFIG","join","homedir","sanitized","account","privateKeyToAccount","baseUrl","balanceMonitor","createPublicClient","base","http","mkdir","port","writeFile","normalizedModel","logger","join","homedir"]}
|