@wy51ai/clawzenmux 0.1.4 → 0.1.5
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/README.md +1 -1
- package/dist/index.d.ts +2 -3
- package/dist/index.js +12 -16
- package/dist/index.js.map +1 -1
- package/openclaw.plugin.json +1 -1
- package/package.json +2 -2
package/README.md
CHANGED
|
@@ -2,7 +2,7 @@
|
|
|
2
2
|
|
|
3
3
|
**[English](README_EN.md)** | 中文
|
|
4
4
|
|
|
5
|
-
OpenClaw 智能 LLM 路由插件 —— 通过 [ZenMux](https://zenmux.ai) 统一网关调用
|
|
5
|
+
OpenClaw 智能 LLM 路由插件 —— 通过 [ZenMux](https://zenmux.ai) 统一网关调用 100+ 模型,自动选择最便宜的模型处理请求,节省 78-96% 的 token 费用。
|
|
6
6
|
|
|
7
7
|
> **注意**:这是一个社区第三方插件,非 OpenClaw 或 ZenMux 官方出品。欢迎各位大佬提交PR改进。
|
|
8
8
|
>
|
package/dist/index.d.ts
CHANGED
|
@@ -144,7 +144,6 @@ type RoutingDecision = {
|
|
|
144
144
|
};
|
|
145
145
|
type TierConfig = {
|
|
146
146
|
primary: string;
|
|
147
|
-
fallback: string[];
|
|
148
147
|
};
|
|
149
148
|
type ScoringConfig = {
|
|
150
149
|
tokenCountThresholds: {
|
|
@@ -314,7 +313,7 @@ declare const zenmuxProvider: ProviderPlugin;
|
|
|
314
313
|
/**
|
|
315
314
|
* ZenMux Model Definitions for OpenClaw
|
|
316
315
|
*
|
|
317
|
-
* Maps ZenMux's
|
|
316
|
+
* Maps ZenMux's 100+ AI models to OpenClaw's ModelDefinitionConfig format.
|
|
318
317
|
* All models use the "openai-completions" API since ZenMux is OpenAI-compatible.
|
|
319
318
|
*
|
|
320
319
|
* Pricing is in USD per 1M tokens.
|
|
@@ -501,7 +500,7 @@ declare function isInvalidApiKeyError(error: unknown): error is InvalidApiKeyErr
|
|
|
501
500
|
/**
|
|
502
501
|
* @wy51ai/clawzenmux
|
|
503
502
|
*
|
|
504
|
-
* Smart LLM router for OpenClaw via ZenMux —
|
|
503
|
+
* Smart LLM router for OpenClaw via ZenMux — 100+ models, AI-powered routing,
|
|
505
504
|
* multi-language support, token cost savings.
|
|
506
505
|
*
|
|
507
506
|
* Usage:
|
package/dist/index.js
CHANGED
|
@@ -216,8 +216,8 @@ var ZENMUX_MODELS = [
|
|
|
216
216
|
{
|
|
217
217
|
id: "google/gemini-3-flash-preview",
|
|
218
218
|
name: "Gemini 3 Flash Preview",
|
|
219
|
-
inputPrice: 0,
|
|
220
|
-
outputPrice:
|
|
219
|
+
inputPrice: 0.5,
|
|
220
|
+
outputPrice: 3,
|
|
221
221
|
contextWindow: 105e4,
|
|
222
222
|
maxOutput: 65536,
|
|
223
223
|
vision: true
|
|
@@ -251,8 +251,8 @@ var ZENMUX_MODELS = [
|
|
|
251
251
|
},
|
|
252
252
|
// ─── DeepSeek ───
|
|
253
253
|
{
|
|
254
|
-
id: "deepseek/deepseek-
|
|
255
|
-
name: "DeepSeek
|
|
254
|
+
id: "deepseek/deepseek-chat",
|
|
255
|
+
name: "DeepSeek Chat",
|
|
256
256
|
inputPrice: 0.28,
|
|
257
257
|
outputPrice: 0.43,
|
|
258
258
|
contextWindow: 128e3,
|
|
@@ -260,10 +260,10 @@ var ZENMUX_MODELS = [
|
|
|
260
260
|
reasoning: true
|
|
261
261
|
},
|
|
262
262
|
{
|
|
263
|
-
id: "deepseek/deepseek-
|
|
264
|
-
name: "DeepSeek
|
|
263
|
+
id: "deepseek/deepseek-reasoner",
|
|
264
|
+
name: "DeepSeek Reasoner",
|
|
265
265
|
inputPrice: 0.28,
|
|
266
|
-
outputPrice: 0.
|
|
266
|
+
outputPrice: 0.42,
|
|
267
267
|
contextWindow: 128e3,
|
|
268
268
|
maxOutput: 8192,
|
|
269
269
|
reasoning: true
|
|
@@ -1323,20 +1323,16 @@ var DEFAULT_ROUTING_CONFIG = {
|
|
|
1323
1323
|
},
|
|
1324
1324
|
tiers: {
|
|
1325
1325
|
SIMPLE: {
|
|
1326
|
-
primary: "deepseek/deepseek-
|
|
1327
|
-
fallback: ["google/gemini-2.5-flash"]
|
|
1326
|
+
primary: "deepseek/deepseek-chat"
|
|
1328
1327
|
},
|
|
1329
1328
|
MEDIUM: {
|
|
1330
|
-
primary: "google/gemini-3-flash-preview"
|
|
1331
|
-
fallback: ["deepseek/deepseek-v3.2"]
|
|
1329
|
+
primary: "google/gemini-3-flash-preview"
|
|
1332
1330
|
},
|
|
1333
1331
|
COMPLEX: {
|
|
1334
|
-
primary: "anthropic/claude-sonnet-4.5"
|
|
1335
|
-
fallback: ["anthropic/claude-sonnet-4", "openai/gpt-4o"]
|
|
1332
|
+
primary: "anthropic/claude-sonnet-4.5"
|
|
1336
1333
|
},
|
|
1337
1334
|
REASONING: {
|
|
1338
|
-
primary: "deepseek/deepseek-
|
|
1339
|
-
fallback: ["openai/gpt-5.2"]
|
|
1335
|
+
primary: "deepseek/deepseek-reasoner"
|
|
1340
1336
|
}
|
|
1341
1337
|
},
|
|
1342
1338
|
overrides: {
|
|
@@ -2119,7 +2115,7 @@ async function startProxyInBackground(api) {
|
|
|
2119
2115
|
var plugin = {
|
|
2120
2116
|
id: "clawzenmux",
|
|
2121
2117
|
name: "ClawZenMux",
|
|
2122
|
-
description: "Smart LLM router via ZenMux \u2014
|
|
2118
|
+
description: "Smart LLM router via ZenMux \u2014 100+ models, rules-based routing, token cost savings",
|
|
2123
2119
|
version: "0.1.0",
|
|
2124
2120
|
register(api) {
|
|
2125
2121
|
api.registerProvider(zenmuxProvider);
|
package/dist/index.js.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"sources":["../src/models.ts","../src/auth.ts","../src/provider.ts","../src/proxy.ts","../src/router/rules.ts","../src/router/selector.ts","../src/router/config.ts","../src/router/index.ts","../src/model-sync.ts","../src/logger.ts","../src/dedup.ts","../src/retry.ts","../src/errors.ts","../src/index.ts"],"sourcesContent":["/**\n * ZenMux Model Definitions for OpenClaw\n *\n * Maps ZenMux's 90+ AI models to OpenClaw's ModelDefinitionConfig format.\n * All models use the \"openai-completions\" API since ZenMux is OpenAI-compatible.\n *\n * Pricing is in USD per 1M tokens.\n */\n\nimport type { ModelDefinitionConfig, ModelProviderConfig } from \"./types.js\";\n\nexport type ZenMuxModel = {\n id: string;\n name: string;\n inputPrice: number;\n outputPrice: number;\n contextWindow: number;\n maxOutput: number;\n reasoning?: boolean;\n vision?: boolean;\n};\n\nexport const ZENMUX_MODELS: ZenMuxModel[] = [\n // Smart routing meta-model — proxy replaces with actual model\n {\n id: \"clawzenmux/auto\",\n name: \"ZenMux Smart Router\",\n inputPrice: 0,\n outputPrice: 0,\n contextWindow: 1_050_000,\n maxOutput: 128_000,\n },\n\n // ─── OpenAI GPT-5 Family ───\n {\n id: \"openai/gpt-5.2-pro\",\n name: \"GPT-5.2 Pro\",\n inputPrice: 21.0,\n outputPrice: 168.0,\n contextWindow: 400_000,\n maxOutput: 128_000,\n reasoning: true,\n },\n {\n id: \"openai/gpt-5.2\",\n name: \"GPT-5.2\",\n inputPrice: 1.75,\n outputPrice: 14.0,\n contextWindow: 400_000,\n maxOutput: 128_000,\n reasoning: true,\n vision: true,\n },\n {\n id: \"openai/gpt-5.1\",\n name: \"GPT-5.1\",\n inputPrice: 1.5,\n outputPrice: 12.0,\n contextWindow: 400_000,\n maxOutput: 128_000,\n reasoning: true,\n vision: true,\n },\n {\n id: \"openai/gpt-5\",\n name: \"GPT-5\",\n inputPrice: 1.0,\n outputPrice: 8.0,\n contextWindow: 400_000,\n maxOutput: 128_000,\n reasoning: true,\n },\n {\n id: \"openai/gpt-5-mini\",\n name: \"GPT-5 Mini\",\n inputPrice: 0.25,\n outputPrice: 2.0,\n contextWindow: 200_000,\n maxOutput: 65_536,\n },\n {\n id: \"openai/gpt-5-nano\",\n name: \"GPT-5 Nano\",\n inputPrice: 0.05,\n outputPrice: 0.4,\n contextWindow: 128_000,\n maxOutput: 32_768,\n },\n\n // ─── OpenAI GPT-4 Family ───\n {\n id: \"openai/gpt-4.1\",\n name: \"GPT-4.1\",\n inputPrice: 2.0,\n outputPrice: 8.0,\n contextWindow: 128_000,\n maxOutput: 16_384,\n vision: true,\n },\n {\n id: \"openai/gpt-4.1-mini\",\n name: \"GPT-4.1 Mini\",\n inputPrice: 0.4,\n outputPrice: 1.6,\n contextWindow: 128_000,\n maxOutput: 16_384,\n },\n {\n id: \"openai/gpt-4.1-nano\",\n name: \"GPT-4.1 Nano\",\n inputPrice: 0.1,\n outputPrice: 0.4,\n contextWindow: 128_000,\n maxOutput: 16_384,\n },\n {\n id: \"openai/gpt-4o\",\n name: \"GPT-4o\",\n inputPrice: 2.5,\n outputPrice: 10.0,\n contextWindow: 128_000,\n maxOutput: 16_384,\n vision: true,\n },\n {\n id: \"openai/gpt-4o-mini\",\n name: \"GPT-4o Mini\",\n inputPrice: 0.15,\n outputPrice: 0.6,\n contextWindow: 128_000,\n maxOutput: 16_384,\n },\n\n // ─── OpenAI O-series (Reasoning) ───\n {\n id: \"openai/o3\",\n name: \"o3\",\n inputPrice: 2.0,\n outputPrice: 8.0,\n contextWindow: 200_000,\n maxOutput: 100_000,\n reasoning: true,\n },\n {\n id: \"openai/o3-mini\",\n name: \"o3-mini\",\n inputPrice: 1.1,\n outputPrice: 4.4,\n contextWindow: 128_000,\n maxOutput: 65_536,\n reasoning: true,\n },\n {\n id: \"openai/o4-mini\",\n name: \"o4-mini\",\n inputPrice: 1.1,\n outputPrice: 4.4,\n contextWindow: 128_000,\n maxOutput: 65_536,\n reasoning: true,\n },\n\n // ─── OpenAI Codex ───\n {\n id: \"openai/codex-mini\",\n name: \"Codex Mini\",\n inputPrice: 1.5,\n outputPrice: 6.0,\n contextWindow: 200_000,\n maxOutput: 100_000,\n reasoning: true,\n },\n\n // ─── Anthropic ───\n {\n id: \"anthropic/claude-opus-4.6\",\n name: \"Claude Opus 4.6\",\n inputPrice: 5.0,\n outputPrice: 25.0,\n contextWindow: 1_000_000,\n maxOutput: 32_000,\n reasoning: true,\n vision: true,\n },\n {\n id: \"anthropic/claude-opus-4.5\",\n name: \"Claude Opus 4.5\",\n inputPrice: 5.0,\n outputPrice: 25.0,\n contextWindow: 200_000,\n maxOutput: 32_000,\n reasoning: true,\n vision: true,\n },\n {\n id: \"anthropic/claude-opus-4\",\n name: \"Claude Opus 4\",\n inputPrice: 15.0,\n outputPrice: 75.0,\n contextWindow: 200_000,\n maxOutput: 32_000,\n reasoning: true,\n },\n {\n id: \"anthropic/claude-sonnet-4.5\",\n name: \"Claude Sonnet 4.5\",\n inputPrice: 3.0,\n outputPrice: 15.0,\n contextWindow: 200_000,\n maxOutput: 64_000,\n reasoning: true,\n vision: true,\n },\n {\n id: \"anthropic/claude-sonnet-4\",\n name: \"Claude Sonnet 4\",\n inputPrice: 3.0,\n outputPrice: 15.0,\n contextWindow: 200_000,\n maxOutput: 64_000,\n reasoning: true,\n },\n {\n id: \"anthropic/claude-haiku-4.5\",\n name: \"Claude Haiku 4.5\",\n inputPrice: 1.0,\n outputPrice: 5.0,\n contextWindow: 200_000,\n maxOutput: 8_192,\n },\n\n // ─── Google Gemini ───\n {\n id: \"google/gemini-3-pro-preview\",\n name: \"Gemini 3 Pro Preview\",\n inputPrice: 2.0,\n outputPrice: 12.0,\n contextWindow: 1_050_000,\n maxOutput: 65_536,\n reasoning: true,\n vision: true,\n },\n {\n id: \"google/gemini-3-flash-preview\",\n name: \"Gemini 3 Flash Preview\",\n inputPrice: 0.0,\n outputPrice: 0.0,\n contextWindow: 1_050_000,\n maxOutput: 65_536,\n vision: true,\n },\n {\n id: \"google/gemini-2.5-pro\",\n name: \"Gemini 2.5 Pro\",\n inputPrice: 1.25,\n outputPrice: 10.0,\n contextWindow: 1_050_000,\n maxOutput: 65_536,\n reasoning: true,\n vision: true,\n },\n {\n id: \"google/gemini-2.5-flash\",\n name: \"Gemini 2.5 Flash\",\n inputPrice: 0.15,\n outputPrice: 0.6,\n contextWindow: 1_000_000,\n maxOutput: 65_536,\n },\n {\n id: \"google/gemini-2.5-flash-lite\",\n name: \"Gemini 2.5 Flash Lite\",\n inputPrice: 0.1,\n outputPrice: 0.4,\n contextWindow: 1_050_000,\n maxOutput: 65_536,\n vision: true,\n },\n\n // ─── DeepSeek ───\n {\n id: \"deepseek/deepseek-v3.2\",\n name: \"DeepSeek V3.2\",\n inputPrice: 0.28,\n outputPrice: 0.43,\n contextWindow: 128_000,\n maxOutput: 8_192,\n reasoning: true,\n },\n {\n id: \"deepseek/deepseek-v3.2-thinking\",\n name: \"DeepSeek V3.2 Thinking\",\n inputPrice: 0.28,\n outputPrice: 0.43,\n contextWindow: 128_000,\n maxOutput: 8_192,\n reasoning: true,\n },\n\n // ─── xAI / Grok ───\n {\n id: \"x-ai/grok-4.1-fast\",\n name: \"Grok 4.1 Fast\",\n inputPrice: 0.2,\n outputPrice: 0.5,\n contextWindow: 2_000_000,\n maxOutput: 30_000,\n reasoning: true,\n vision: true,\n },\n {\n id: \"x-ai/grok-4-fast\",\n name: \"Grok 4 Fast\",\n inputPrice: 0.4,\n outputPrice: 1.0,\n contextWindow: 2_000_000,\n maxOutput: 30_000,\n reasoning: true,\n vision: true,\n },\n {\n id: \"x-ai/grok-3\",\n name: \"Grok 3\",\n inputPrice: 3.0,\n outputPrice: 15.0,\n contextWindow: 131_072,\n maxOutput: 16_384,\n reasoning: true,\n },\n {\n id: \"x-ai/grok-3-mini\",\n name: \"Grok 3 Mini\",\n inputPrice: 0.3,\n outputPrice: 0.5,\n contextWindow: 131_072,\n maxOutput: 16_384,\n },\n\n // ─── Alibaba / Qwen ───\n {\n id: \"qwen/qwen3-max\",\n name: \"Qwen3-Max\",\n inputPrice: 1.2,\n outputPrice: 6.0,\n contextWindow: 256_000,\n maxOutput: 32_000,\n reasoning: true,\n },\n {\n id: \"qwen/qwen3-coder-plus\",\n name: \"Qwen3-Coder-Plus\",\n inputPrice: 1.0,\n outputPrice: 5.0,\n contextWindow: 1_000_000,\n maxOutput: 65_536,\n reasoning: true,\n },\n {\n id: \"qwen/qwen3-vl-plus\",\n name: \"Qwen3-VL-Plus\",\n inputPrice: 0.8,\n outputPrice: 4.0,\n contextWindow: 128_000,\n maxOutput: 32_000,\n vision: true,\n },\n\n // ─── Z.AI / GLM ───\n {\n id: \"z-ai/glm-4.7\",\n name: \"GLM 4.7\",\n inputPrice: 0.28,\n outputPrice: 1.14,\n contextWindow: 200_000,\n maxOutput: 128_000,\n reasoning: true,\n },\n {\n id: \"z-ai/glm-4.6\",\n name: \"GLM 4.6\",\n inputPrice: 0.28,\n outputPrice: 1.14,\n contextWindow: 200_000,\n maxOutput: 128_000,\n reasoning: true,\n },\n {\n id: \"z-ai/glm-4.6v-flash-free\",\n name: \"GLM 4.6V Flash (Free)\",\n inputPrice: 0.0,\n outputPrice: 0.0,\n contextWindow: 200_000,\n maxOutput: 128_000,\n vision: true,\n },\n\n // ─── Moonshot / Kimi ───\n {\n id: \"moonshotai/kimi-k2-thinking\",\n name: \"Kimi K2 Thinking\",\n inputPrice: 0.6,\n outputPrice: 2.5,\n contextWindow: 262_144,\n maxOutput: 262_144,\n reasoning: true,\n },\n {\n id: \"moonshotai/kimi-k2.5\",\n name: \"Kimi K2.5\",\n inputPrice: 0.5,\n outputPrice: 2.4,\n contextWindow: 262_144,\n maxOutput: 8_192,\n reasoning: true,\n vision: true,\n },\n\n // ─── Mistral ───\n {\n id: \"mistralai/mistral-large-2512\",\n name: \"Mistral Large 3\",\n inputPrice: 0.5,\n outputPrice: 1.5,\n contextWindow: 256_000,\n maxOutput: 256_000,\n vision: true,\n },\n\n // ─── Baidu / ERNIE ───\n {\n id: \"baidu/ernie-5.0-thinking-preview\",\n name: \"ERNIE-5.0 Thinking Preview\",\n inputPrice: 0.84,\n outputPrice: 3.37,\n contextWindow: 128_000,\n maxOutput: 64_000,\n reasoning: true,\n vision: true,\n },\n\n // ─── Volcengine / Doubao ───\n {\n id: \"volcengine/doubao-seed-code\",\n name: \"Doubao-Seed-Code\",\n inputPrice: 0.17,\n outputPrice: 1.12,\n contextWindow: 256_000,\n maxOutput: 32_000,\n },\n\n // ─── inclusionAI ───\n {\n id: \"inclusionai/ling-1t\",\n name: \"Ling-1T\",\n inputPrice: 0.56,\n outputPrice: 2.24,\n contextWindow: 128_000,\n maxOutput: 32_000,\n reasoning: true,\n },\n\n // ─── Xiaomi ───\n {\n id: \"xiaomi/mimo-v2-flash\",\n name: \"MiMo-V2-Flash\",\n inputPrice: 0.0,\n outputPrice: 0.0,\n contextWindow: 262_144,\n maxOutput: 262_144,\n reasoning: true,\n },\n\n // ─── Kuaishou ───\n {\n id: \"kuaishou/kat-coder-pro-v1\",\n name: \"KAT-Coder-Pro V1\",\n inputPrice: 0.0,\n outputPrice: 0.0,\n contextWindow: 256_000,\n maxOutput: 32_000,\n },\n];\n\n/**\n * Convert ZenMux model definitions to OpenClaw ModelDefinitionConfig format.\n */\nfunction toOpenClawModel(m: ZenMuxModel): 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 * All ZenMux models in OpenClaw format.\n */\nexport const OPENCLAW_MODELS: ModelDefinitionConfig[] = ZENMUX_MODELS.map(toOpenClawModel);\n\n/**\n * Build a ModelProviderConfig for ZenMux.\n *\n * @param baseUrl - The proxy's local base URL (e.g., \"http://127.0.0.1:8403\")\n */\nexport function buildProviderModels(baseUrl: string): ModelProviderConfig {\n return {\n baseUrl: `${baseUrl}/v1`,\n api: \"openai-completions\",\n models: OPENCLAW_MODELS,\n };\n}\n","/**\n * ZenMux API Key Resolution\n *\n * Resolves the ZenMux API key from multiple sources:\n * 1. Plugin config (explicit apiKey field)\n * 2. Saved file (~/.openclaw/zenmux/api.key)\n * 3. Environment variable (ZENMUX_API_KEY)\n *\n * Also provides a ProviderAuthMethod for the interactive wizard.\n */\n\nimport { readFileSync, writeFileSync, existsSync, mkdirSync } from \"node:fs\";\nimport { join } from \"node:path\";\nimport { homedir } from \"node:os\";\nimport type { ProviderAuthMethod, ProviderAuthContext } from \"./types.js\";\n\nconst ZENMUX_DIR = join(homedir(), \".openclaw\", \"zenmux\");\nconst KEY_PATH = join(ZENMUX_DIR, \"api.key\");\n\nexport type ApiKeyResult = {\n key: string;\n source: \"config\" | \"saved\" | \"env\";\n};\n\n/**\n * Resolve API key from available sources.\n * Returns null if no key is found (user needs to configure one).\n */\nexport function resolveApiKey(pluginConfig?: Record<string, unknown>): ApiKeyResult | null {\n // 1. Plugin config\n if (pluginConfig?.apiKey && typeof pluginConfig.apiKey === \"string\") {\n return { key: pluginConfig.apiKey, source: \"config\" };\n }\n\n // 2. Saved file\n if (existsSync(KEY_PATH)) {\n try {\n const key = readFileSync(KEY_PATH, \"utf-8\").trim();\n if (key) {\n return { key, source: \"saved\" };\n }\n } catch {\n // Fall through\n }\n }\n\n // 3. Environment variable\n const envKey = process.env.ZENMUX_API_KEY;\n if (envKey) {\n return { key: envKey, source: \"env\" };\n }\n\n return null;\n}\n\n/**\n * Save API key to persistent storage.\n */\nexport function saveApiKey(key: string): void {\n if (!existsSync(ZENMUX_DIR)) {\n mkdirSync(ZENMUX_DIR, { recursive: true });\n }\n writeFileSync(KEY_PATH, key, { mode: 0o600 });\n}\n\n/**\n * Interactive auth method — prompts user to enter their ZenMux API key.\n */\nexport const zenmuxApiKeyAuth: ProviderAuthMethod = {\n id: \"api_key\",\n label: \"ZenMux API Key\",\n hint: \"Get your API key from https://zenmux.ai/console/api-keys\",\n kind: \"api_key\",\n\n async run(ctx: ProviderAuthContext) {\n ctx.prompter.note(\n \"Sign in at https://zenmux.ai and create an API key from Console > API Keys.\",\n );\n\n const key = await ctx.prompter.text({\n message: \"Enter your ZenMux API key:\",\n validate: (value: string) => {\n if (!value.trim()) return \"API key is required\";\n return undefined;\n },\n });\n\n if (typeof key === \"symbol\") {\n return { profiles: [] }; // Cancelled\n }\n\n // Save the key for future use\n saveApiKey(key.trim());\n\n return {\n profiles: [\n {\n profileId: \"default\",\n credential: { apiKey: key.trim() },\n },\n ],\n notes: [\"API key saved to ~/.openclaw/zenmux/api.key\"],\n };\n },\n};\n","/**\n * ZenMux ProviderPlugin for OpenClaw\n *\n * Registers ZenMux as an LLM provider in OpenClaw.\n * Uses a local proxy to add smart routing and deduplication —\n * pi-ai sees a standard OpenAI-compatible API at localhost.\n */\n\nimport type { ProviderPlugin } from \"./types.js\";\nimport { buildProviderModels } from \"./models.js\";\nimport { zenmuxApiKeyAuth } from \"./auth.js\";\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\n/**\n * Update the proxy handle (called from index.ts when the proxy starts).\n */\nexport function setActiveProxy(proxy: ProxyHandle): void {\n activeProxy = proxy;\n}\n\nexport function getActiveProxy(): ProxyHandle | null {\n return activeProxy;\n}\n\n/**\n * ZenMux provider plugin definition.\n */\nexport const zenmuxProvider: ProviderPlugin = {\n id: \"clawzenmux\",\n label: \"ClawZenMux\",\n docsPath: \"https://docs.zenmux.ai\",\n aliases: [\"czm\", \"zenmux\"],\n envVars: [\"ZENMUX_API_KEY\"],\n\n // Model definitions — dynamically set to proxy URL\n get models() {\n if (!activeProxy) {\n // Fallback: point to ZenMux API directly\n return buildProviderModels(\"https://zenmux.ai/api\");\n }\n return buildProviderModels(activeProxy.baseUrl);\n },\n\n // Auth via API key (interactive wizard)\n auth: [zenmuxApiKeyAuth],\n\n // Extract API key from stored credential for Authorization header\n formatApiKey(cred) {\n return cred.apiKey as string;\n },\n};\n","/**\n * Local Proxy Server for ZenMux\n *\n * Sits between OpenClaw's pi-ai (which makes standard OpenAI-format requests)\n * and ZenMux's API (which uses Bearer token auth).\n *\n * Flow:\n * pi-ai → http://localhost:{port}/v1/chat/completions\n * → proxy adds auth + smart routing\n * → forwards to https://zenmux.ai/api/v1/chat/completions\n * → streams response back to pi-ai\n *\n * Features:\n * - Smart routing: \"clawzenmux/auto\" → rules-based scoring picks cheapest model\n * - Dynamic models: fetches latest models/pricing from ZenMux API\n * - SSE heartbeat: prevents OpenClaw's timeout for streaming requests\n * - Response dedup: prevents double-charging on retries\n * - Usage logging: JSON line logs to ~/.openclaw/zenmux/logs/\n */\n\nimport { createServer, type IncomingMessage, type ServerResponse } from \"node:http\";\nimport type { AddressInfo } from \"node:net\";\nimport {\n route,\n DEFAULT_ROUTING_CONFIG,\n type RouterOptions,\n type RoutingDecision,\n type RoutingConfig,\n type ModelPricing,\n type Tier,\n} from \"./router/index.js\";\nimport { ZENMUX_MODELS } from \"./models.js\";\nimport type { ZenMuxModel } from \"./models.js\";\nimport { fetchModels } from \"./model-sync.js\";\nimport { logUsage, type UsageEntry } from \"./logger.js\";\nimport { RequestDeduplicator } from \"./dedup.js\";\nimport { fetchWithRetry } from \"./retry.js\";\n\nconst ZENMUX_API = \"https://zenmux.ai/api\";\nconst AUTO_MODEL = \"clawzenmux/auto\";\nconst AUTO_MODEL_SHORT = \"auto\";\nconst USER_AGENT = \"clawzenmux/0.1.0\";\nconst HEARTBEAT_INTERVAL_MS = 2_000;\nconst DEFAULT_REQUEST_TIMEOUT_MS = 180_000; // 3 minutes\nconst DEFAULT_PORT = 8403;\nconst TIER_OVERRIDE_REGEX = /\\bUSE\\s+(SIMPLE|MEDIUM|COMPLEX|REASONING)\\b/i;\nconst TIER_OVERRIDE_REGEX_GLOBAL = /\\bUSE\\s+(SIMPLE|MEDIUM|COMPLEX|REASONING)\\b/gi;\n\ntype ContentPart = { type: string; text?: string };\ntype ChatMessage = { role: string; content?: string | ContentPart[] };\n\nfunction extractText(content: string | ContentPart[] | undefined): string {\n if (typeof content === \"string\") return content;\n if (Array.isArray(content)) {\n return content\n .filter((p) => p.type === \"text\" && typeof p.text === \"string\")\n .map((p) => p.text!)\n .join(\"\\n\");\n }\n return \"\";\n}\n\nfunction parseForcedTier(text: string): Tier | undefined {\n const match = text.match(TIER_OVERRIDE_REGEX);\n if (!match) return undefined;\n return match[1].toUpperCase() as Tier;\n}\n\nfunction stripForcedTierDirective(text: string): string {\n return text.replace(TIER_OVERRIDE_REGEX_GLOBAL, \"\").replace(/[ \\t]{2,}/g, \" \").trim();\n}\n\nfunction extractAndStripForcedTier(message: ChatMessage | undefined): Tier | undefined {\n if (!message || message.content === undefined) return undefined;\n\n if (typeof message.content === \"string\") {\n const forcedTier = parseForcedTier(message.content);\n if (forcedTier) {\n message.content = stripForcedTierDirective(message.content);\n }\n return forcedTier;\n }\n\n if (Array.isArray(message.content)) {\n let forcedTier: Tier | undefined;\n message.content = message.content.map((part) => {\n if (part.type !== \"text\" || typeof part.text !== \"string\") return part;\n\n const partForcedTier = parseForcedTier(part.text);\n if (!forcedTier && partForcedTier) {\n forcedTier = partForcedTier;\n }\n if (!partForcedTier) return part;\n\n return {\n ...part,\n text: stripForcedTierDirective(part.text),\n };\n });\n return forcedTier;\n }\n\n return undefined;\n}\n\nexport type ProxyOptions = {\n apiKey: string;\n apiBase?: string;\n /** Port to listen on (default: 8403) */\n port?: number;\n routingConfig?: Partial<RoutingConfig>;\n /** Request timeout in ms (default: 180000 = 3 minutes). */\n requestTimeoutMs?: number;\n onReady?: (port: number) => void;\n onError?: (error: Error) => void;\n onRouted?: (decision: RoutingDecision) => void;\n onModelsSynced?: (count: number) => void;\n};\n\nexport type ProxyHandle = {\n port: number;\n baseUrl: string;\n close: () => Promise<void>;\n};\n\n/**\n * Build model pricing map from a models array.\n */\nfunction buildModelPricing(models: ZenMuxModel[]): Map<string, ModelPricing> {\n const map = new Map<string, ModelPricing>();\n for (const m of models) {\n if (m.id === AUTO_MODEL) continue;\n map.set(m.id, { inputPrice: m.inputPrice, outputPrice: m.outputPrice });\n }\n return map;\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 * Start the local proxy server.\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 apiBase = options.apiBase ?? ZENMUX_API;\n const apiKey = options.apiKey;\n\n // Build router options\n const routingConfig = mergeRoutingConfig(options.routingConfig);\n\n // Try to fetch dynamic models, fall back to static catalog\n let models: ZenMuxModel[];\n try {\n models = await fetchModels(apiKey);\n options.onModelsSynced?.(models.length);\n } catch {\n models = ZENMUX_MODELS;\n }\n\n const modelPricing = buildModelPricing(models);\n\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 const server = createServer(async (req: IncomingMessage, res: ServerResponse) => {\n // Health check\n if (req.url === \"/health\" || req.url?.startsWith(\"/health?\")) {\n res.writeHead(200, { \"Content-Type\": \"application/json\" });\n res.end(\n JSON.stringify({\n status: \"ok\",\n provider: \"zenmux\",\n models: models.length,\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(req, res, apiBase, apiKey, options, routerOpts, deduplicator);\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 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 requested port (default: 8403)\n const listenPort = options.port ?? DEFAULT_PORT;\n\n return new Promise<ProxyHandle>((resolve, reject) => {\n server.on(\"error\", reject);\n\n server.listen(listenPort, \"127.0.0.1\", () => {\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 resolve({\n port,\n baseUrl,\n close: () =>\n new Promise<void>((res, rej) => {\n server.close((err) => (err ? rej(err) : res()));\n }),\n });\n });\n });\n}\n\n/**\n * Proxy a single request to ZenMux API with smart routing and dedup.\n */\nasync function proxyRequest(\n req: IncomingMessage,\n res: ServerResponse,\n apiBase: string,\n apiKey: string,\n options: ProxyOptions,\n routerOpts: RouterOptions,\n deduplicator: RequestDeduplicator,\n): Promise<void> {\n const startTime = Date.now();\n\n // Build upstream URL\n const upstreamUrl = `${apiBase}${req.url}`;\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 // --- Smart routing ---\n let routingDecision: RoutingDecision | undefined;\n let isStreaming = false;\n let modelId = \"\";\n const isChatCompletion = req.url?.includes(\"/chat/completions\");\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 const maxTokens =\n typeof parsed.max_completion_tokens === \"number\"\n ? parsed.max_completion_tokens\n : typeof parsed.max_tokens === \"number\"\n ? parsed.max_tokens\n : 4096;\n\n if (parsed.model === AUTO_MODEL || parsed.model === AUTO_MODEL_SHORT) {\n // Extract prompt from messages\n const messages = Array.isArray(parsed.messages)\n ? (parsed.messages as ChatMessage[])\n : undefined;\n\n let lastUserMsg: ChatMessage | undefined;\n if (messages) {\n for (let i = messages.length - 1; i >= 0; i--) {\n if (messages[i].role === \"user\") {\n lastUserMsg = messages[i];\n break;\n }\n }\n }\n const systemMsg = messages?.find((m: ChatMessage) => m.role === \"system\");\n const forcedTier = extractAndStripForcedTier(lastUserMsg);\n const prompt = extractText(lastUserMsg?.content);\n const systemPrompt = extractText(systemMsg?.content) || undefined;\n const allMessageText =\n messages\n ?.map((m) => extractText(m.content))\n .filter((s) => s.length > 0)\n .join(\"\\n\") ?? \"\";\n const estimatedInputTokens =\n allMessageText.length > 0 ? Math.ceil(allMessageText.length / 4) : undefined;\n const structuredOutputRequired =\n typeof parsed.response_format === \"object\" && parsed.response_format !== null;\n\n routingDecision = route(prompt, systemPrompt, maxTokens, routerOpts, {\n estimatedInputTokens,\n forcedTier,\n structuredOutputRequired,\n });\n\n // Replace model in body\n parsed.model = routingDecision.model;\n modelId = routingDecision.model;\n body = Buffer.from(JSON.stringify(parsed));\n\n options.onRouted?.(routingDecision);\n }\n } catch {\n // JSON parse error — forward body as-is\n }\n }\n\n // --- Dedup check ---\n const dedupKey = RequestDeduplicator.hash(body);\n\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 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 deduplicator.markInflight(dedupKey);\n\n // --- Streaming: early header flush + heartbeat ---\n let heartbeatInterval: ReturnType<typeof setInterval> | undefined;\n let headersSentEarly = false;\n\n if (isStreaming) {\n res.writeHead(200, {\n \"content-type\": \"text/event-stream\",\n \"cache-control\": \"no-cache\",\n connection: \"keep-alive\",\n });\n headersSentEarly = true;\n\n res.write(\": heartbeat\\n\\n\");\n\n heartbeatInterval = setInterval(() => {\n if (!res.writableEnded) {\n res.write(\": heartbeat\\n\\n\");\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 headers[\"authorization\"] = `Bearer ${apiKey}`;\n\n // --- Client disconnect cleanup ---\n let completed = false;\n res.on(\"close\", () => {\n if (heartbeatInterval) {\n clearInterval(heartbeatInterval);\n heartbeatInterval = undefined;\n }\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 const upstream = await fetchWithRetry(\n (url, init) => fetch(url, init),\n upstreamUrl,\n {\n method: req.method ?? \"POST\",\n headers,\n body: body.length > 0 ? body : undefined,\n signal: controller.signal,\n },\n );\n\n clearTimeout(timeoutId);\n\n if (heartbeatInterval) {\n clearInterval(heartbeatInterval);\n heartbeatInterval = undefined;\n }\n\n // --- Stream response and collect for dedup cache ---\n const responseChunks: Buffer[] = [];\n\n if (headersSentEarly) {\n // Streaming: headers already sent. Check for upstream errors.\n if (upstream.status !== 200) {\n const errBody = await upstream.text();\n const errEvent = `data: ${JSON.stringify({ error: { message: errBody, type: \"upstream_error\", status: upstream.status } })}\\n\\n`;\n res.write(errEvent);\n res.write(\"data: [DONE]\\n\\n\");\n res.end();\n\n deduplicator.complete(dedupKey, {\n status: 200,\n headers: { \"content-type\": \"text/event-stream\" },\n body: Buffer.from(errEvent + \"data: [DONE]\\n\\n\"),\n completedAt: Date.now(),\n });\n return;\n }\n\n // Pipe upstream SSE data to client\n if (upstream.body) {\n const reader = upstream.body.getReader();\n try {\n while (true) {\n const { done, value } = await reader.read();\n if (done) break;\n res.write(value);\n responseChunks.push(Buffer.from(value));\n }\n } finally {\n reader.releaseLock();\n }\n }\n\n res.end();\n\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 if (key === \"transfer-encoding\" || key === \"connection\") return;\n responseHeaders[key] = value;\n });\n\n res.writeHead(upstream.status, responseHeaders);\n\n if (upstream.body) {\n const reader = upstream.body.getReader();\n try {\n while (true) {\n const { done, value } = await reader.read();\n if (done) break;\n res.write(value);\n responseChunks.push(Buffer.from(value));\n }\n } finally {\n reader.releaseLock();\n }\n }\n\n res.end();\n\n deduplicator.complete(dedupKey, {\n status: upstream.status,\n headers: responseHeaders,\n body: Buffer.concat(responseChunks),\n completedAt: Date.now(),\n });\n }\n\n completed = true;\n } catch (err) {\n clearTimeout(timeoutId);\n\n if (heartbeatInterval) {\n clearInterval(heartbeatInterval);\n heartbeatInterval = undefined;\n }\n\n deduplicator.removeInflight(dedupKey);\n\n if (err instanceof Error && err.name === \"AbortError\") {\n throw new Error(`Request timed out after ${timeoutMs}ms`);\n }\n\n throw err;\n }\n\n // --- Usage logging (fire-and-forget) ---\n if (routingDecision) {\n const entry: UsageEntry = {\n timestamp: new Date().toISOString(),\n model: routingDecision.model,\n cost: routingDecision.costEstimate,\n latencyMs: Date.now() - startTime,\n };\n logUsage(entry).catch(() => {});\n }\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 // Keep a mild \"short prompt\" penalty, but avoid overpowering technical intent.\n return { name: \"tokenCount\", score: -0.6, 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 hasArchitectureComplexitySignal(text: string): boolean {\n const architectureNouns = [\n \"architecture\",\n \"system architecture\",\n \"solution architecture\",\n \"platform architecture\",\n \"event-driven architecture\",\n \"system design\",\n \"design a system\",\n \"distributed system\",\n \"topology\",\n \"架构\",\n \"架构设计\",\n \"系统架构\",\n \"平台架构\",\n \"事件驱动架构\",\n \"微服务架构\",\n \"系统拓扑\",\n \"系统设计\",\n \"消息队列\",\n \"message queue\",\n \"event bus\",\n ];\n const scaleSignals = [\n \"distributed\",\n \"scalable\",\n \"scale\",\n \"high concurrency\",\n \"qps\",\n \"rps\",\n \"latency\",\n \"durability\",\n \"reliability\",\n \"availability\",\n \"shard\",\n \"sharding\",\n \"partition\",\n \"replica\",\n \"replication\",\n \"failover\",\n \"multi-region\",\n \"multi-tenant\",\n \"idempotent\",\n \"exactly-once\",\n \"at-least-once\",\n \"eventual consistency\",\n \"backpressure\",\n \"dead letter\",\n \"dlq\",\n \"分布式\",\n \"高并发\",\n \"并发\",\n \"延迟\",\n \"低延迟\",\n \"可扩展\",\n \"扩展性\",\n \"吞吐量\",\n \"可用性\",\n \"可靠性\",\n \"分片\",\n \"分区\",\n \"副本\",\n \"复制\",\n \"容灾\",\n \"多活\",\n \"多租户\",\n \"幂等\",\n \"最终一致性\",\n \"一致性\",\n \"故障转移\",\n \"削峰\",\n \"背压\",\n \"死信\",\n \"死信队列\",\n \"microservice\",\n \"kubernetes\",\n \"consistency\",\n \"fault tolerance\",\n \"high availability\",\n \"高可用\",\n \"吞吐\",\n \"throughput\",\n ];\n const designVerbs = [\n \"design\",\n \"architect\",\n \"build\",\n \"implement\",\n \"propose\",\n \"plan\",\n \"draft\",\n \"outline\",\n \"设计\",\n \"构建\",\n \"搭建\",\n \"实现\",\n \"规划\",\n \"给出\",\n \"制定\",\n ];\n\n const hasArchitectureNoun = architectureNouns.some((kw) => text.includes(kw));\n const hasScaleSignal = scaleSignals.some((kw) => text.includes(kw));\n const hasDesignVerb = designVerbs.some((kw) => text.includes(kw));\n\n return hasArchitectureNoun && (hasScaleSignal || hasDesignVerb);\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// ─── Main Classifier ───\n\nexport function classifyByRules(\n prompt: string,\n estimatedTokens: number,\n config: ScoringConfig,\n): ScoringResult {\n // Complexity scoring should be driven by user intent, not static system prompts.\n const text = prompt.toLowerCase();\n // User prompt only — used for reasoning markers.\n const userText = prompt.toLowerCase();\n\n // Score all 14 dimensions\n const dimensions: DimensionScore[] = [\n // Original 8 dimensions\n scoreTokenCount(estimatedTokens, config.tokenCountThresholds),\n scoreKeywordMatch(\n text,\n config.codeKeywords,\n \"codePresence\",\n \"code\",\n { low: 1, high: 2 },\n { none: 0, low: 0.5, high: 1.0 },\n ),\n // Reasoning markers use USER prompt only — system prompt \"step by step\" shouldn't trigger reasoning\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 text,\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 text,\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 text,\n config.simpleKeywords,\n \"simpleIndicators\",\n \"simple\",\n { low: 1, high: 2 },\n { none: 0, low: -1.0, high: -1.0 },\n ),\n scoreMultiStep(text),\n scoreQuestionComplexity(prompt),\n\n // 6 new dimensions\n scoreKeywordMatch(\n text,\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 text,\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 text,\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 text,\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 text,\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 text,\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 // 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 };\n }\n\n // Architecture/system-design prompts are typically high-complexity even when short.\n // Route these directly to COMPLEX to avoid under-classifying into MEDIUM.\n if (hasArchitectureComplexitySignal(userText)) {\n return {\n score: Math.max(weightedScore, config.tierBoundaries.mediumComplex + 0.03),\n tier: \"COMPLEX\",\n confidence: 0.82,\n signals: [...signals, \"architecture-design\"],\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 };\n }\n\n return { score: weightedScore, tier, confidence, signals };\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\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): RoutingDecision {\n const tierConfig = tierConfigs[tier];\n const model = tierConfig.primary;\n const pricing = modelPricing.get(model);\n\n const inputCost = pricing ? (estimatedInputTokens / 1_000_000) * pricing.inputPrice : 0;\n const outputCost = pricing ? (maxOutputTokens / 1_000_000) * pricing.outputPrice : 0;\n const costEstimate = inputCost + outputCost;\n\n // Baseline: what Claude Opus 4.6 would cost (the premium default)\n const opusPricing = modelPricing.get(\"anthropic/claude-opus-4.6\");\n const baselineInput = opusPricing\n ? (estimatedInputTokens / 1_000_000) * opusPricing.inputPrice\n : 0;\n const baselineOutput = opusPricing ? (maxOutputTokens / 1_000_000) * opusPricing.outputPrice : 0;\n const baselineCost = baselineInput + baselineOutput;\n\n const savings = baselineCost > 0 ? Math.max(0, (baselineCost - costEstimate) / baselineCost) : 0;\n\n return {\n model,\n tier,\n confidence,\n method,\n reasoning,\n costEstimate,\n baselineCost,\n savings,\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 * 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 * Tier models updated for ZenMux's catalog.\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: English + Chinese (中文) + Japanese (日本語) + Russian (Русский)\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 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 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 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 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 // 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 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 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 ],\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 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 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\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.12,\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 },\n\n // Tier boundaries on weighted score axis\n tierBoundaries: {\n simpleMedium: 0.0,\n mediumComplex: 0.15,\n complexReasoning: 0.25,\n },\n\n // Sigmoid steepness for confidence calibration\n confidenceSteepness: 12,\n // Below this confidence → ambiguous (null tier)\n confidenceThreshold: 0.6,\n },\n\n tiers: {\n SIMPLE: {\n primary: \"deepseek/deepseek-v3.2\",\n fallback: [\"google/gemini-2.5-flash\"],\n },\n MEDIUM: {\n primary: \"google/gemini-3-flash-preview\",\n fallback: [\"deepseek/deepseek-v3.2\"],\n },\n COMPLEX: {\n primary: \"anthropic/claude-sonnet-4.5\",\n fallback: [\"anthropic/claude-sonnet-4\", \"openai/gpt-4o\"],\n },\n REASONING: {\n primary: \"deepseek/deepseek-v3.2-thinking\",\n fallback: [\"openai/gpt-5.2\"],\n },\n },\n\n overrides: {\n maxTokensForceComplex: 100_000,\n structuredOutputMinTier: \"MEDIUM\",\n ambiguousDefaultTier: \"MEDIUM\",\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.js\";\nimport { selectModel, type ModelPricing } from \"./selector.js\";\n\nexport type RouterOptions = {\n config: RoutingConfig;\n modelPricing: Map<string, ModelPricing>;\n};\n\nexport type RouteContext = {\n /**\n * Estimated total input tokens for the full request payload.\n * Falls back to `systemPrompt + prompt` estimate when omitted.\n */\n estimatedInputTokens?: number;\n /**\n * Force a tier (prompt-level override), e.g. \"USE COMPLEX\".\n */\n forcedTier?: Tier;\n /**\n * Whether the request explicitly requires structured output (e.g. response_format).\n */\n structuredOutputRequired?: 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 context?: RouteContext,\n): RoutingDecision {\n const { config, modelPricing } = options;\n\n // Token estimates (~4 chars/token): scoring should use user prompt only,\n // while cost/override should use full request estimate.\n const userEstimatedTokens = Math.ceil(prompt.length / 4);\n const fallbackEstimatedTokens = Math.ceil(`${systemPrompt ?? \"\"} ${prompt}`.length / 4);\n const estimatedTokens = context?.estimatedInputTokens ?? fallbackEstimatedTokens;\n\n // --- Prompt override: explicit tier force ---\n if (context?.forcedTier) {\n return selectModel(\n context.forcedTier,\n 1.0,\n \"rules\",\n `forced tier override: ${context.forcedTier}`,\n config.tiers,\n modelPricing,\n estimatedTokens,\n maxOutputTokens,\n );\n }\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`,\n config.tiers,\n modelPricing,\n estimatedTokens,\n maxOutputTokens,\n );\n }\n\n // Structured output detection:\n // prioritize explicit request signal (from proxy), then user prompt hints.\n const hasStructuredOutput =\n context?.structuredOutputRequired ?? /json|structured|schema|yaml|xml|csv|table/i.test(prompt);\n\n // --- Rule-based classification ---\n const ruleResult = classifyByRules(prompt, userEstimatedTokens, config.scoring);\n\n let tier: Tier;\n let confidence: number;\n const method: \"rules\" | \"llm\" = \"rules\";\n let reasoning = `score=${ruleResult.score} | ${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 return selectModel(\n tier,\n confidence,\n method,\n reasoning,\n config.tiers,\n modelPricing,\n estimatedTokens,\n maxOutputTokens,\n );\n}\n\nexport { getFallbackChain } from \"./selector.js\";\nexport { DEFAULT_ROUTING_CONFIG } from \"./config.js\";\nexport type { RoutingDecision, Tier, RoutingConfig } from \"./types.js\";\nexport type { ModelPricing } from \"./selector.js\";\n","/**\n * Dynamic Model Sync\n *\n * Fetches the latest model catalog and pricing from ZenMux's /v1/models API.\n * Caches results in memory with a configurable TTL to avoid excessive API calls.\n * Falls back to the built-in static catalog if the API is unreachable.\n */\n\nimport { ZENMUX_MODELS, type ZenMuxModel } from \"./models.js\";\n\nconst MODELS_ENDPOINT = \"https://zenmux.ai/api/v1/models\";\nconst DEFAULT_CACHE_TTL_MS = 30 * 60 * 1000; // 30 minutes\n\ntype PricingEntry = {\n value: number;\n unit: string;\n currency: string;\n conditions?: Record<string, unknown>;\n};\n\ntype ApiModel = {\n id: string;\n display_name?: string;\n owned_by?: string;\n input_modalities?: string[];\n output_modalities?: string[];\n capabilities?: { reasoning?: boolean };\n context_length?: number;\n pricings?: {\n prompt?: PricingEntry[];\n completion?: PricingEntry[];\n };\n};\n\ntype ApiResponse = {\n data: ApiModel[];\n object: string;\n};\n\ntype CacheEntry = {\n models: ZenMuxModel[];\n fetchedAt: number;\n};\n\nlet cache: CacheEntry | null = null;\n\n/**\n * Extract price per 1M tokens from pricing array.\n * Looks for \"perMTokens\" unit, falls back to 0.\n */\nfunction extractPrice(entries?: PricingEntry[]): number {\n if (!entries || entries.length === 0) return 0;\n // Prefer perMTokens entry\n const perM = entries.find((e) => e.unit === \"perMTokens\");\n if (perM) return perM.value;\n // Fallback: first entry\n return entries[0].value;\n}\n\n/**\n * Convert API model to our internal format.\n */\nfunction toZenMuxModel(api: ApiModel): ZenMuxModel {\n const hasVision =\n api.input_modalities?.includes(\"image\") || api.input_modalities?.includes(\"video\");\n\n return {\n id: api.id,\n name: api.display_name || api.id,\n inputPrice: extractPrice(api.pricings?.prompt),\n outputPrice: extractPrice(api.pricings?.completion),\n contextWindow: api.context_length || 128_000,\n maxOutput: 65_536, // API doesn't expose this; use sensible default\n reasoning: api.capabilities?.reasoning ?? false,\n vision: hasVision ?? false,\n };\n}\n\n/**\n * Fetch latest models from ZenMux API.\n *\n * @param apiKey - ZenMux API key for authentication\n * @param cacheTtlMs - Cache TTL in ms (default: 30 minutes)\n * @returns Array of ZenMuxModel with latest pricing\n */\nexport async function fetchModels(\n apiKey: string,\n cacheTtlMs = DEFAULT_CACHE_TTL_MS,\n): Promise<ZenMuxModel[]> {\n // Return cached if fresh\n if (cache && Date.now() - cache.fetchedAt < cacheTtlMs) {\n return cache.models;\n }\n\n try {\n const response = await fetch(MODELS_ENDPOINT, {\n headers: {\n authorization: `Bearer ${apiKey}`,\n \"user-agent\": \"clawzenmux/0.1.0\",\n },\n signal: AbortSignal.timeout(10_000), // 10s timeout\n });\n\n if (!response.ok) {\n throw new Error(`API returned ${response.status}`);\n }\n\n const data = (await response.json()) as ApiResponse;\n if (!data.data || !Array.isArray(data.data)) {\n throw new Error(\"Invalid API response format\");\n }\n\n const models = data.data.map(toZenMuxModel);\n\n // Add the auto meta-model\n models.unshift({\n id: \"clawzenmux/auto\",\n name: \"ZenMux Smart Router\",\n inputPrice: 0,\n outputPrice: 0,\n contextWindow: 1_050_000,\n maxOutput: 128_000,\n });\n\n cache = { models, fetchedAt: Date.now() };\n return models;\n } catch {\n // Fallback to static catalog\n return ZENMUX_MODELS;\n }\n}\n\n/**\n * Invalidate the model cache (e.g., after config change).\n */\nexport function invalidateModelCache(): void {\n cache = null;\n}\n","/**\n * Usage Logger\n *\n * Logs every LLM request as a JSON line to a daily log file.\n * Files: ~/.openclaw/zenmux/logs/usage-YYYY-MM-DD.jsonl\n *\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 cost: number;\n latencyMs: number;\n};\n\nconst LOG_DIR = join(homedir(), \".openclaw\", \"zenmux\", \"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 * 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 resolve: (result: CachedResponse) => void;\n waiters: Promise<CachedResponse>[];\n};\n\nconst DEFAULT_TTL_MS = 30_000; // 30 seconds\nconst MAX_BODY_SIZE = 1_048_576; // 1MB\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 return createHash(\"sha256\").update(body).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 const promise = new Promise<CachedResponse>((resolve) => {\n entry.waiters.push(\n new Promise<CachedResponse>((r) => {\n const orig = entry.resolve;\n entry.resolve = (result) => {\n orig(result);\n resolve(result);\n r(result);\n };\n }),\n );\n });\n return promise;\n }\n\n /** Mark a request as in-flight. */\n markInflight(key: string): void {\n this.inflight.set(key, {\n resolve: () => {},\n waiters: [],\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 entry.resolve(result);\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 removeInflight(key: string): void {\n this.inflight.delete(key);\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 * Retry Logic for ClawZenMux\n *\n * Provides fetch wrapper with exponential backoff for transient errors.\n * Retries on 429 (rate limit), 502, 503, 504 (server errors).\n */\n\n/** Configuration for retry behavior */\nexport type RetryConfig = {\n /** Maximum number of retries (default: 2) */\n maxRetries: number;\n /** Base delay in ms for exponential backoff (default: 500) */\n baseDelayMs: number;\n /** HTTP status codes that trigger a retry (default: [429, 502, 503, 504]) */\n retryableCodes: number[];\n};\n\n/** Default retry configuration */\nexport const DEFAULT_RETRY_CONFIG: RetryConfig = {\n maxRetries: 2,\n baseDelayMs: 500,\n retryableCodes: [429, 502, 503, 504],\n};\n\n/** Sleep for a given number of milliseconds */\nfunction sleep(ms: number): Promise<void> {\n return new Promise((resolve) => setTimeout(resolve, ms));\n}\n\n/**\n * Wrap a fetch-like function with retry logic and exponential backoff.\n */\nexport async function fetchWithRetry(\n fetchFn: (url: string, init?: RequestInit) => Promise<Response>,\n url: string,\n init?: RequestInit,\n config?: Partial<RetryConfig>,\n): Promise<Response> {\n const cfg: RetryConfig = {\n ...DEFAULT_RETRY_CONFIG,\n ...config,\n };\n\n let lastError: Error | undefined;\n let lastResponse: Response | undefined;\n\n for (let attempt = 0; attempt <= cfg.maxRetries; attempt++) {\n try {\n const response = await fetchFn(url, init);\n\n // Success or non-retryable status — return immediately\n if (!cfg.retryableCodes.includes(response.status)) {\n return response;\n }\n\n // Retryable status — save response and maybe retry\n lastResponse = response;\n\n // Check for Retry-After header (common with 429)\n const retryAfter = response.headers.get(\"retry-after\");\n let delay: number;\n\n if (retryAfter) {\n const seconds = parseInt(retryAfter, 10);\n delay = isNaN(seconds) ? cfg.baseDelayMs * Math.pow(2, attempt) : seconds * 1000;\n } else {\n delay = cfg.baseDelayMs * Math.pow(2, attempt);\n }\n\n // Only retry if we have attempts left\n if (attempt < cfg.maxRetries) {\n await sleep(delay);\n }\n } catch (err) {\n lastError = err instanceof Error ? err : new Error(String(err));\n\n // Network errors are retryable\n if (attempt < cfg.maxRetries) {\n const delay = cfg.baseDelayMs * Math.pow(2, attempt);\n await sleep(delay);\n }\n }\n }\n\n // All retries exhausted — return last response or throw last error\n if (lastResponse) {\n return lastResponse;\n }\n\n throw lastError ?? new Error(\"Max retries exceeded\");\n}\n\n/**\n * Check if an error or response indicates a retryable condition.\n */\nexport function isRetryable(\n errorOrResponse: Error | Response,\n config?: Partial<RetryConfig>,\n): boolean {\n const retryableCodes = config?.retryableCodes ?? DEFAULT_RETRY_CONFIG.retryableCodes;\n\n if (errorOrResponse instanceof Response) {\n return retryableCodes.includes(errorOrResponse.status);\n }\n\n // Network errors are generally retryable\n const message = errorOrResponse.message.toLowerCase();\n return (\n message.includes(\"network\") ||\n message.includes(\"timeout\") ||\n message.includes(\"econnreset\") ||\n message.includes(\"econnrefused\") ||\n message.includes(\"socket hang up\")\n );\n}\n","/**\n * Typed Error Classes for ClawZenMux\n *\n * Provides structured errors for authentication and proxy failures.\n */\n\n/**\n * Thrown when no ZenMux API key is configured.\n */\nexport class AuthenticationError extends Error {\n readonly code = \"AUTHENTICATION_ERROR\" as const;\n\n constructor(message?: string) {\n super(\n message ??\n \"No ZenMux API key configured. Set ZENMUX_API_KEY env var or configure via plugin settings.\",\n );\n this.name = \"AuthenticationError\";\n }\n}\n\n/**\n * Thrown when the API key is invalid (401 from ZenMux).\n */\nexport class InvalidApiKeyError extends Error {\n readonly code = \"INVALID_API_KEY\" as const;\n\n constructor() {\n super(\"Invalid ZenMux API key. Check your key at https://zenmux.ai/console/api-keys\");\n this.name = \"InvalidApiKeyError\";\n }\n}\n\n/**\n * Type guard to check if an error is AuthenticationError.\n */\nexport function isAuthenticationError(error: unknown): error is AuthenticationError {\n return error instanceof Error && (error as AuthenticationError).code === \"AUTHENTICATION_ERROR\";\n}\n\n/**\n * Type guard to check if an error is InvalidApiKeyError.\n */\nexport function isInvalidApiKeyError(error: unknown): error is InvalidApiKeyError {\n return error instanceof Error && (error as InvalidApiKeyError).code === \"INVALID_API_KEY\";\n}\n","/**\n * @wy51ai/clawzenmux\n *\n * Smart LLM router for OpenClaw via ZenMux — 90+ models, AI-powered routing,\n * multi-language support, token cost savings.\n *\n * Usage:\n * # Install the plugin\n * openclaw plugin install @wy51ai/clawzenmux\n *\n * # Set your ZenMux API key\n * export ZENMUX_API_KEY=your-key-here\n *\n * # Use smart routing (auto-picks cheapest model)\n * openclaw models set clawzenmux/auto\n *\n * # Or use any specific ZenMux model\n * openclaw models set openai/gpt-5.2\n */\n\nimport type { OpenClawPluginDefinition, OpenClawPluginApi } from \"./types.js\";\nimport { zenmuxProvider, setActiveProxy } from \"./provider.js\";\nimport { startProxy } from \"./proxy.js\";\nimport { resolveApiKey } from \"./auth.js\";\nimport type { RoutingConfig } from \"./router/index.js\";\nimport { OPENCLAW_MODELS } from \"./models.js\";\nimport { AuthenticationError } from \"./errors.js\";\nimport { readFileSync, writeFileSync, existsSync, readdirSync, mkdirSync } from \"node:fs\";\nimport { homedir } from \"node:os\";\nimport { join } from \"node:path\";\n\n/**\n * Inject ZenMux models config into OpenClaw config file.\n */\nfunction injectModelsConfig(logger: { info: (msg: string) => void }, apiKey?: string): void {\n const configPath = join(homedir(), \".openclaw\", \"openclaw.json\");\n if (!existsSync(configPath)) {\n logger.info(\"OpenClaw config not found, skipping models injection\");\n return;\n }\n\n try {\n const config = JSON.parse(readFileSync(configPath, \"utf-8\"));\n\n // Clean up old \"zenmux\" key if present\n if (config.models?.providers?.zenmux) {\n delete config.models.providers.zenmux;\n }\n\n if (config.models?.providers?.clawzenmux) {\n return; // Already configured\n }\n\n if (!config.models) config.models = {};\n if (!config.models.providers) config.models.providers = {};\n\n config.models.providers.clawzenmux = {\n baseUrl: \"http://127.0.0.1:8403/v1\",\n api: \"openai-completions\",\n ...(apiKey ? { apiKey } : {}),\n models: OPENCLAW_MODELS,\n };\n\n writeFileSync(configPath, JSON.stringify(config, null, 2));\n logger.info(\"Injected ClawZenMux models into OpenClaw config\");\n } catch {\n // Silently fail — config injection is best-effort\n }\n}\n\n/**\n * Inject auth profile for ZenMux into agent auth stores.\n */\nfunction injectAuthProfile(\n logger: { info: (msg: string) => void },\n apiKey: string,\n): void {\n const agentsDir = join(homedir(), \".openclaw\", \"agents\");\n if (!existsSync(agentsDir)) {\n return;\n }\n\n try {\n const agents = readdirSync(agentsDir, { withFileTypes: true })\n .filter((d) => d.isDirectory())\n .map((d) => d.name);\n\n for (const agentId of agents) {\n const authDir = join(agentsDir, agentId, \"agent\");\n const authPath = join(authDir, \"auth-profiles.json\");\n\n if (!existsSync(authDir)) {\n mkdirSync(authDir, { recursive: true });\n }\n\n let authProfiles: Record<string, unknown> = {};\n if (existsSync(authPath)) {\n try {\n authProfiles = JSON.parse(readFileSync(authPath, \"utf-8\"));\n } catch {\n authProfiles = {};\n }\n }\n\n if (authProfiles.clawzenmux) {\n continue;\n }\n\n authProfiles.clawzenmux = {\n profileId: \"default\",\n credential: {\n apiKey: apiKey,\n },\n };\n\n writeFileSync(authPath, JSON.stringify(authProfiles, null, 2));\n logger.info(`Injected ZenMux auth profile for agent: ${agentId}`);\n }\n } catch {\n // Silently fail — auth injection is best-effort\n }\n}\n\n/**\n * Start the proxy in the background.\n */\nasync function startProxyInBackground(api: OpenClawPluginApi): Promise<void> {\n // Resolve API key\n const keyResult = resolveApiKey(api.pluginConfig);\n\n if (!keyResult) {\n throw new AuthenticationError();\n }\n\n const { key: apiKey, source } = keyResult;\n\n if (source === \"config\") {\n api.logger.info(\"Using API key from plugin config\");\n } else if (source === \"saved\") {\n api.logger.info(\"Using saved API key from ~/.openclaw/zenmux/api.key\");\n } else {\n api.logger.info(\"Using API key from ZENMUX_API_KEY env var\");\n }\n\n // Inject auth profiles with the resolved key\n injectAuthProfile(api.logger, apiKey);\n\n // Resolve config overrides from plugin config\n const routingConfig = api.pluginConfig?.routing as Partial<RoutingConfig> | undefined;\n\n const proxy = await startProxy({\n apiKey,\n routingConfig,\n onReady: (port) => {\n api.logger.info(`ZenMux proxy listening on port ${port}`);\n },\n onError: (error) => {\n api.logger.error(`ZenMux 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(`${decision.tier} → ${decision.model} $${cost} (saved ${saved}%) | ${decision.reasoning}`);\n },\n onModelsSynced: (count) => {\n api.logger.info(`Synced ${count} models from ZenMux API`);\n },\n });\n\n setActiveProxy(proxy);\n\n api.logger.info(\n `ZenMux provider active — ${proxy.baseUrl}/v1 (routing: rules only)`,\n );\n}\n\nconst plugin: OpenClawPluginDefinition = {\n id: \"clawzenmux\",\n name: \"ClawZenMux\",\n description:\n \"Smart LLM router via ZenMux — 90+ models, rules-based routing, token cost savings\",\n version: \"0.1.0\",\n\n register(api: OpenClawPluginApi) {\n // Register ZenMux as a provider (sync — available immediately)\n api.registerProvider(zenmuxProvider);\n\n // Resolve API key early so we can inject it into configs\n const keyResult = resolveApiKey(api.pluginConfig);\n const apiKey = keyResult?.key;\n\n // Inject models config into OpenClaw config file\n injectModelsConfig(api.logger, apiKey);\n\n // Set runtime config for immediate availability\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.clawzenmux = {\n baseUrl: \"http://127.0.0.1:8403/v1\",\n api: \"openai-completions\",\n ...(apiKey ? { apiKey } : {}),\n models: OPENCLAW_MODELS,\n };\n\n api.logger.info(`ClawZenMux provider registered (${OPENCLAW_MODELS.length} models)`);\n api.logger.info(`Registered model IDs: ${OPENCLAW_MODELS.slice(0, 5).map(m => m.id).join(\", \")}...`);\n\n // Start proxy in background (fire-and-forget)\n startProxyInBackground(api).catch((err) => {\n api.logger.error(\n `Failed to start ZenMux proxy: ${err instanceof Error ? err.message : String(err)}`,\n );\n });\n },\n};\n\nexport default plugin;\n\n// Re-export for programmatic use\nexport { startProxy } from \"./proxy.js\";\nexport type { ProxyOptions, ProxyHandle } from \"./proxy.js\";\nexport { zenmuxProvider } from \"./provider.js\";\nexport { OPENCLAW_MODELS, ZENMUX_MODELS, buildProviderModels } from \"./models.js\";\nexport type { ZenMuxModel } from \"./models.js\";\nexport { route, DEFAULT_ROUTING_CONFIG } from \"./router/index.js\";\nexport type { RoutingDecision, RoutingConfig, Tier } from \"./router/index.js\";\nexport { fetchModels, invalidateModelCache } from \"./model-sync.js\";\nexport { logUsage } from \"./logger.js\";\nexport type { UsageEntry } from \"./logger.js\";\nexport { RequestDeduplicator } from \"./dedup.js\";\nexport type { CachedResponse } from \"./dedup.js\";\nexport { resolveApiKey, saveApiKey, zenmuxApiKeyAuth } from \"./auth.js\";\nexport { fetchWithRetry, isRetryable, DEFAULT_RETRY_CONFIG } from \"./retry.js\";\nexport type { RetryConfig } from \"./retry.js\";\nexport {\n AuthenticationError,\n InvalidApiKeyError,\n isAuthenticationError,\n isInvalidApiKeyError,\n} from \"./errors.js\";\n"],"mappings":"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","names":["confidence","join","homedir","readFileSync","writeFileSync","existsSync","mkdirSync","homedir","join"]}
|
|
1
|
+
{"version":3,"sources":["../src/models.ts","../src/auth.ts","../src/provider.ts","../src/proxy.ts","../src/router/rules.ts","../src/router/selector.ts","../src/router/config.ts","../src/router/index.ts","../src/model-sync.ts","../src/logger.ts","../src/dedup.ts","../src/retry.ts","../src/errors.ts","../src/index.ts"],"sourcesContent":["/**\n * ZenMux Model Definitions for OpenClaw\n *\n * Maps ZenMux's 100+ AI models to OpenClaw's ModelDefinitionConfig format.\n * All models use the \"openai-completions\" API since ZenMux is OpenAI-compatible.\n *\n * Pricing is in USD per 1M tokens.\n */\n\nimport type { ModelDefinitionConfig, ModelProviderConfig } from \"./types.js\";\n\nexport type ZenMuxModel = {\n id: string;\n name: string;\n inputPrice: number;\n outputPrice: number;\n contextWindow: number;\n maxOutput: number;\n reasoning?: boolean;\n vision?: boolean;\n};\n\nexport const ZENMUX_MODELS: ZenMuxModel[] = [\n // Smart routing meta-model — proxy replaces with actual model\n {\n id: \"clawzenmux/auto\",\n name: \"ZenMux Smart Router\",\n inputPrice: 0,\n outputPrice: 0,\n contextWindow: 1_050_000,\n maxOutput: 128_000,\n },\n\n // ─── OpenAI GPT-5 Family ───\n {\n id: \"openai/gpt-5.2-pro\",\n name: \"GPT-5.2 Pro\",\n inputPrice: 21.0,\n outputPrice: 168.0,\n contextWindow: 400_000,\n maxOutput: 128_000,\n reasoning: true,\n },\n {\n id: \"openai/gpt-5.2\",\n name: \"GPT-5.2\",\n inputPrice: 1.75,\n outputPrice: 14.0,\n contextWindow: 400_000,\n maxOutput: 128_000,\n reasoning: true,\n vision: true,\n },\n {\n id: \"openai/gpt-5.1\",\n name: \"GPT-5.1\",\n inputPrice: 1.5,\n outputPrice: 12.0,\n contextWindow: 400_000,\n maxOutput: 128_000,\n reasoning: true,\n vision: true,\n },\n {\n id: \"openai/gpt-5\",\n name: \"GPT-5\",\n inputPrice: 1.0,\n outputPrice: 8.0,\n contextWindow: 400_000,\n maxOutput: 128_000,\n reasoning: true,\n },\n {\n id: \"openai/gpt-5-mini\",\n name: \"GPT-5 Mini\",\n inputPrice: 0.25,\n outputPrice: 2.0,\n contextWindow: 200_000,\n maxOutput: 65_536,\n },\n {\n id: \"openai/gpt-5-nano\",\n name: \"GPT-5 Nano\",\n inputPrice: 0.05,\n outputPrice: 0.4,\n contextWindow: 128_000,\n maxOutput: 32_768,\n },\n\n // ─── OpenAI GPT-4 Family ───\n {\n id: \"openai/gpt-4.1\",\n name: \"GPT-4.1\",\n inputPrice: 2.0,\n outputPrice: 8.0,\n contextWindow: 128_000,\n maxOutput: 16_384,\n vision: true,\n },\n {\n id: \"openai/gpt-4.1-mini\",\n name: \"GPT-4.1 Mini\",\n inputPrice: 0.4,\n outputPrice: 1.6,\n contextWindow: 128_000,\n maxOutput: 16_384,\n },\n {\n id: \"openai/gpt-4.1-nano\",\n name: \"GPT-4.1 Nano\",\n inputPrice: 0.1,\n outputPrice: 0.4,\n contextWindow: 128_000,\n maxOutput: 16_384,\n },\n {\n id: \"openai/gpt-4o\",\n name: \"GPT-4o\",\n inputPrice: 2.5,\n outputPrice: 10.0,\n contextWindow: 128_000,\n maxOutput: 16_384,\n vision: true,\n },\n {\n id: \"openai/gpt-4o-mini\",\n name: \"GPT-4o Mini\",\n inputPrice: 0.15,\n outputPrice: 0.6,\n contextWindow: 128_000,\n maxOutput: 16_384,\n },\n\n // ─── OpenAI O-series (Reasoning) ───\n {\n id: \"openai/o3\",\n name: \"o3\",\n inputPrice: 2.0,\n outputPrice: 8.0,\n contextWindow: 200_000,\n maxOutput: 100_000,\n reasoning: true,\n },\n {\n id: \"openai/o3-mini\",\n name: \"o3-mini\",\n inputPrice: 1.1,\n outputPrice: 4.4,\n contextWindow: 128_000,\n maxOutput: 65_536,\n reasoning: true,\n },\n {\n id: \"openai/o4-mini\",\n name: \"o4-mini\",\n inputPrice: 1.1,\n outputPrice: 4.4,\n contextWindow: 128_000,\n maxOutput: 65_536,\n reasoning: true,\n },\n\n // ─── OpenAI Codex ───\n {\n id: \"openai/codex-mini\",\n name: \"Codex Mini\",\n inputPrice: 1.5,\n outputPrice: 6.0,\n contextWindow: 200_000,\n maxOutput: 100_000,\n reasoning: true,\n },\n\n // ─── Anthropic ───\n {\n id: \"anthropic/claude-opus-4.6\",\n name: \"Claude Opus 4.6\",\n inputPrice: 5.0,\n outputPrice: 25.0,\n contextWindow: 1_000_000,\n maxOutput: 32_000,\n reasoning: true,\n vision: true,\n },\n {\n id: \"anthropic/claude-opus-4.5\",\n name: \"Claude Opus 4.5\",\n inputPrice: 5.0,\n outputPrice: 25.0,\n contextWindow: 200_000,\n maxOutput: 32_000,\n reasoning: true,\n vision: true,\n },\n {\n id: \"anthropic/claude-opus-4\",\n name: \"Claude Opus 4\",\n inputPrice: 15.0,\n outputPrice: 75.0,\n contextWindow: 200_000,\n maxOutput: 32_000,\n reasoning: true,\n },\n {\n id: \"anthropic/claude-sonnet-4.5\",\n name: \"Claude Sonnet 4.5\",\n inputPrice: 3.0,\n outputPrice: 15.0,\n contextWindow: 200_000,\n maxOutput: 64_000,\n reasoning: true,\n vision: true,\n },\n {\n id: \"anthropic/claude-sonnet-4\",\n name: \"Claude Sonnet 4\",\n inputPrice: 3.0,\n outputPrice: 15.0,\n contextWindow: 200_000,\n maxOutput: 64_000,\n reasoning: true,\n },\n {\n id: \"anthropic/claude-haiku-4.5\",\n name: \"Claude Haiku 4.5\",\n inputPrice: 1.0,\n outputPrice: 5.0,\n contextWindow: 200_000,\n maxOutput: 8_192,\n },\n\n // ─── Google Gemini ───\n {\n id: \"google/gemini-3-pro-preview\",\n name: \"Gemini 3 Pro Preview\",\n inputPrice: 2.0,\n outputPrice: 12.0,\n contextWindow: 1_050_000,\n maxOutput: 65_536,\n reasoning: true,\n vision: true,\n },\n {\n id: \"google/gemini-3-flash-preview\",\n name: \"Gemini 3 Flash Preview\",\n inputPrice: 0.5,\n outputPrice: 3.0,\n contextWindow: 1_050_000,\n maxOutput: 65_536,\n vision: true,\n },\n {\n id: \"google/gemini-2.5-pro\",\n name: \"Gemini 2.5 Pro\",\n inputPrice: 1.25,\n outputPrice: 10.0,\n contextWindow: 1_050_000,\n maxOutput: 65_536,\n reasoning: true,\n vision: true,\n },\n {\n id: \"google/gemini-2.5-flash\",\n name: \"Gemini 2.5 Flash\",\n inputPrice: 0.15,\n outputPrice: 0.6,\n contextWindow: 1_000_000,\n maxOutput: 65_536,\n },\n {\n id: \"google/gemini-2.5-flash-lite\",\n name: \"Gemini 2.5 Flash Lite\",\n inputPrice: 0.1,\n outputPrice: 0.4,\n contextWindow: 1_050_000,\n maxOutput: 65_536,\n vision: true,\n },\n\n // ─── DeepSeek ───\n {\n id: \"deepseek/deepseek-chat\",\n name: \"DeepSeek Chat\",\n inputPrice: 0.28,\n outputPrice: 0.43,\n contextWindow: 128_000,\n maxOutput: 8_192,\n reasoning: true,\n },\n {\n id: \"deepseek/deepseek-reasoner\",\n name: \"DeepSeek Reasoner\",\n inputPrice: 0.28,\n outputPrice: 0.42,\n contextWindow: 128_000,\n maxOutput: 8_192,\n reasoning: true,\n },\n\n // ─── xAI / Grok ───\n {\n id: \"x-ai/grok-4.1-fast\",\n name: \"Grok 4.1 Fast\",\n inputPrice: 0.2,\n outputPrice: 0.5,\n contextWindow: 2_000_000,\n maxOutput: 30_000,\n reasoning: true,\n vision: true,\n },\n {\n id: \"x-ai/grok-4-fast\",\n name: \"Grok 4 Fast\",\n inputPrice: 0.4,\n outputPrice: 1.0,\n contextWindow: 2_000_000,\n maxOutput: 30_000,\n reasoning: true,\n vision: true,\n },\n {\n id: \"x-ai/grok-3\",\n name: \"Grok 3\",\n inputPrice: 3.0,\n outputPrice: 15.0,\n contextWindow: 131_072,\n maxOutput: 16_384,\n reasoning: true,\n },\n {\n id: \"x-ai/grok-3-mini\",\n name: \"Grok 3 Mini\",\n inputPrice: 0.3,\n outputPrice: 0.5,\n contextWindow: 131_072,\n maxOutput: 16_384,\n },\n\n // ─── Alibaba / Qwen ───\n {\n id: \"qwen/qwen3-max\",\n name: \"Qwen3-Max\",\n inputPrice: 1.2,\n outputPrice: 6.0,\n contextWindow: 256_000,\n maxOutput: 32_000,\n reasoning: true,\n },\n {\n id: \"qwen/qwen3-coder-plus\",\n name: \"Qwen3-Coder-Plus\",\n inputPrice: 1.0,\n outputPrice: 5.0,\n contextWindow: 1_000_000,\n maxOutput: 65_536,\n reasoning: true,\n },\n {\n id: \"qwen/qwen3-vl-plus\",\n name: \"Qwen3-VL-Plus\",\n inputPrice: 0.8,\n outputPrice: 4.0,\n contextWindow: 128_000,\n maxOutput: 32_000,\n vision: true,\n },\n\n // ─── Z.AI / GLM ───\n {\n id: \"z-ai/glm-4.7\",\n name: \"GLM 4.7\",\n inputPrice: 0.28,\n outputPrice: 1.14,\n contextWindow: 200_000,\n maxOutput: 128_000,\n reasoning: true,\n },\n {\n id: \"z-ai/glm-4.6\",\n name: \"GLM 4.6\",\n inputPrice: 0.28,\n outputPrice: 1.14,\n contextWindow: 200_000,\n maxOutput: 128_000,\n reasoning: true,\n },\n {\n id: \"z-ai/glm-4.6v-flash-free\",\n name: \"GLM 4.6V Flash (Free)\",\n inputPrice: 0.0,\n outputPrice: 0.0,\n contextWindow: 200_000,\n maxOutput: 128_000,\n vision: true,\n },\n\n // ─── Moonshot / Kimi ───\n {\n id: \"moonshotai/kimi-k2-thinking\",\n name: \"Kimi K2 Thinking\",\n inputPrice: 0.6,\n outputPrice: 2.5,\n contextWindow: 262_144,\n maxOutput: 262_144,\n reasoning: true,\n },\n {\n id: \"moonshotai/kimi-k2.5\",\n name: \"Kimi K2.5\",\n inputPrice: 0.5,\n outputPrice: 2.4,\n contextWindow: 262_144,\n maxOutput: 8_192,\n reasoning: true,\n vision: true,\n },\n\n // ─── Mistral ───\n {\n id: \"mistralai/mistral-large-2512\",\n name: \"Mistral Large 3\",\n inputPrice: 0.5,\n outputPrice: 1.5,\n contextWindow: 256_000,\n maxOutput: 256_000,\n vision: true,\n },\n\n // ─── Baidu / ERNIE ───\n {\n id: \"baidu/ernie-5.0-thinking-preview\",\n name: \"ERNIE-5.0 Thinking Preview\",\n inputPrice: 0.84,\n outputPrice: 3.37,\n contextWindow: 128_000,\n maxOutput: 64_000,\n reasoning: true,\n vision: true,\n },\n\n // ─── Volcengine / Doubao ───\n {\n id: \"volcengine/doubao-seed-code\",\n name: \"Doubao-Seed-Code\",\n inputPrice: 0.17,\n outputPrice: 1.12,\n contextWindow: 256_000,\n maxOutput: 32_000,\n },\n\n // ─── inclusionAI ───\n {\n id: \"inclusionai/ling-1t\",\n name: \"Ling-1T\",\n inputPrice: 0.56,\n outputPrice: 2.24,\n contextWindow: 128_000,\n maxOutput: 32_000,\n reasoning: true,\n },\n\n // ─── Xiaomi ───\n {\n id: \"xiaomi/mimo-v2-flash\",\n name: \"MiMo-V2-Flash\",\n inputPrice: 0.0,\n outputPrice: 0.0,\n contextWindow: 262_144,\n maxOutput: 262_144,\n reasoning: true,\n },\n\n // ─── Kuaishou ───\n {\n id: \"kuaishou/kat-coder-pro-v1\",\n name: \"KAT-Coder-Pro V1\",\n inputPrice: 0.0,\n outputPrice: 0.0,\n contextWindow: 256_000,\n maxOutput: 32_000,\n },\n];\n\n/**\n * Convert ZenMux model definitions to OpenClaw ModelDefinitionConfig format.\n */\nfunction toOpenClawModel(m: ZenMuxModel): 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 * All ZenMux models in OpenClaw format.\n */\nexport const OPENCLAW_MODELS: ModelDefinitionConfig[] = ZENMUX_MODELS.map(toOpenClawModel);\n\n/**\n * Build a ModelProviderConfig for ZenMux.\n *\n * @param baseUrl - The proxy's local base URL (e.g., \"http://127.0.0.1:8403\")\n */\nexport function buildProviderModels(baseUrl: string): ModelProviderConfig {\n return {\n baseUrl: `${baseUrl}/v1`,\n api: \"openai-completions\",\n models: OPENCLAW_MODELS,\n };\n}\n","/**\n * ZenMux API Key Resolution\n *\n * Resolves the ZenMux API key from multiple sources:\n * 1. Plugin config (explicit apiKey field)\n * 2. Saved file (~/.openclaw/zenmux/api.key)\n * 3. Environment variable (ZENMUX_API_KEY)\n *\n * Also provides a ProviderAuthMethod for the interactive wizard.\n */\n\nimport { readFileSync, writeFileSync, existsSync, mkdirSync } from \"node:fs\";\nimport { join } from \"node:path\";\nimport { homedir } from \"node:os\";\nimport type { ProviderAuthMethod, ProviderAuthContext } from \"./types.js\";\n\nconst ZENMUX_DIR = join(homedir(), \".openclaw\", \"zenmux\");\nconst KEY_PATH = join(ZENMUX_DIR, \"api.key\");\n\nexport type ApiKeyResult = {\n key: string;\n source: \"config\" | \"saved\" | \"env\";\n};\n\n/**\n * Resolve API key from available sources.\n * Returns null if no key is found (user needs to configure one).\n */\nexport function resolveApiKey(pluginConfig?: Record<string, unknown>): ApiKeyResult | null {\n // 1. Plugin config\n if (pluginConfig?.apiKey && typeof pluginConfig.apiKey === \"string\") {\n return { key: pluginConfig.apiKey, source: \"config\" };\n }\n\n // 2. Saved file\n if (existsSync(KEY_PATH)) {\n try {\n const key = readFileSync(KEY_PATH, \"utf-8\").trim();\n if (key) {\n return { key, source: \"saved\" };\n }\n } catch {\n // Fall through\n }\n }\n\n // 3. Environment variable\n const envKey = process.env.ZENMUX_API_KEY;\n if (envKey) {\n return { key: envKey, source: \"env\" };\n }\n\n return null;\n}\n\n/**\n * Save API key to persistent storage.\n */\nexport function saveApiKey(key: string): void {\n if (!existsSync(ZENMUX_DIR)) {\n mkdirSync(ZENMUX_DIR, { recursive: true });\n }\n writeFileSync(KEY_PATH, key, { mode: 0o600 });\n}\n\n/**\n * Interactive auth method — prompts user to enter their ZenMux API key.\n */\nexport const zenmuxApiKeyAuth: ProviderAuthMethod = {\n id: \"api_key\",\n label: \"ZenMux API Key\",\n hint: \"Get your API key from https://zenmux.ai/console/api-keys\",\n kind: \"api_key\",\n\n async run(ctx: ProviderAuthContext) {\n ctx.prompter.note(\n \"Sign in at https://zenmux.ai and create an API key from Console > API Keys.\",\n );\n\n const key = await ctx.prompter.text({\n message: \"Enter your ZenMux API key:\",\n validate: (value: string) => {\n if (!value.trim()) return \"API key is required\";\n return undefined;\n },\n });\n\n if (typeof key === \"symbol\") {\n return { profiles: [] }; // Cancelled\n }\n\n // Save the key for future use\n saveApiKey(key.trim());\n\n return {\n profiles: [\n {\n profileId: \"default\",\n credential: { apiKey: key.trim() },\n },\n ],\n notes: [\"API key saved to ~/.openclaw/zenmux/api.key\"],\n };\n },\n};\n","/**\n * ZenMux ProviderPlugin for OpenClaw\n *\n * Registers ZenMux as an LLM provider in OpenClaw.\n * Uses a local proxy to add smart routing and deduplication —\n * pi-ai sees a standard OpenAI-compatible API at localhost.\n */\n\nimport type { ProviderPlugin } from \"./types.js\";\nimport { buildProviderModels } from \"./models.js\";\nimport { zenmuxApiKeyAuth } from \"./auth.js\";\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\n/**\n * Update the proxy handle (called from index.ts when the proxy starts).\n */\nexport function setActiveProxy(proxy: ProxyHandle): void {\n activeProxy = proxy;\n}\n\nexport function getActiveProxy(): ProxyHandle | null {\n return activeProxy;\n}\n\n/**\n * ZenMux provider plugin definition.\n */\nexport const zenmuxProvider: ProviderPlugin = {\n id: \"clawzenmux\",\n label: \"ClawZenMux\",\n docsPath: \"https://docs.zenmux.ai\",\n aliases: [\"czm\", \"zenmux\"],\n envVars: [\"ZENMUX_API_KEY\"],\n\n // Model definitions — dynamically set to proxy URL\n get models() {\n if (!activeProxy) {\n // Fallback: point to ZenMux API directly\n return buildProviderModels(\"https://zenmux.ai/api\");\n }\n return buildProviderModels(activeProxy.baseUrl);\n },\n\n // Auth via API key (interactive wizard)\n auth: [zenmuxApiKeyAuth],\n\n // Extract API key from stored credential for Authorization header\n formatApiKey(cred) {\n return cred.apiKey as string;\n },\n};\n","/**\n * Local Proxy Server for ZenMux\n *\n * Sits between OpenClaw's pi-ai (which makes standard OpenAI-format requests)\n * and ZenMux's API (which uses Bearer token auth).\n *\n * Flow:\n * pi-ai → http://localhost:{port}/v1/chat/completions\n * → proxy adds auth + smart routing\n * → forwards to https://zenmux.ai/api/v1/chat/completions\n * → streams response back to pi-ai\n *\n * Features:\n * - Smart routing: \"clawzenmux/auto\" → rules-based scoring picks cheapest model\n * - Dynamic models: fetches latest models/pricing from ZenMux API\n * - SSE heartbeat: prevents OpenClaw's timeout for streaming requests\n * - Response dedup: prevents double-charging on retries\n * - Usage logging: JSON line logs to ~/.openclaw/zenmux/logs/\n */\n\nimport { createServer, type IncomingMessage, type ServerResponse } from \"node:http\";\nimport type { AddressInfo } from \"node:net\";\nimport {\n route,\n DEFAULT_ROUTING_CONFIG,\n type RouterOptions,\n type RoutingDecision,\n type RoutingConfig,\n type ModelPricing,\n type Tier,\n} from \"./router/index.js\";\nimport { ZENMUX_MODELS } from \"./models.js\";\nimport type { ZenMuxModel } from \"./models.js\";\nimport { fetchModels } from \"./model-sync.js\";\nimport { logUsage, type UsageEntry } from \"./logger.js\";\nimport { RequestDeduplicator } from \"./dedup.js\";\nimport { fetchWithRetry } from \"./retry.js\";\n\nconst ZENMUX_API = \"https://zenmux.ai/api\";\nconst AUTO_MODEL = \"clawzenmux/auto\";\nconst AUTO_MODEL_SHORT = \"auto\";\nconst USER_AGENT = \"clawzenmux/0.1.0\";\nconst HEARTBEAT_INTERVAL_MS = 2_000;\nconst DEFAULT_REQUEST_TIMEOUT_MS = 180_000; // 3 minutes\nconst DEFAULT_PORT = 8403;\nconst TIER_OVERRIDE_REGEX = /\\bUSE\\s+(SIMPLE|MEDIUM|COMPLEX|REASONING)\\b/i;\nconst TIER_OVERRIDE_REGEX_GLOBAL = /\\bUSE\\s+(SIMPLE|MEDIUM|COMPLEX|REASONING)\\b/gi;\n\ntype ContentPart = { type: string; text?: string };\ntype ChatMessage = { role: string; content?: string | ContentPart[] };\n\nfunction extractText(content: string | ContentPart[] | undefined): string {\n if (typeof content === \"string\") return content;\n if (Array.isArray(content)) {\n return content\n .filter((p) => p.type === \"text\" && typeof p.text === \"string\")\n .map((p) => p.text!)\n .join(\"\\n\");\n }\n return \"\";\n}\n\nfunction parseForcedTier(text: string): Tier | undefined {\n const match = text.match(TIER_OVERRIDE_REGEX);\n if (!match) return undefined;\n return match[1].toUpperCase() as Tier;\n}\n\nfunction stripForcedTierDirective(text: string): string {\n return text.replace(TIER_OVERRIDE_REGEX_GLOBAL, \"\").replace(/[ \\t]{2,}/g, \" \").trim();\n}\n\nfunction extractAndStripForcedTier(message: ChatMessage | undefined): Tier | undefined {\n if (!message || message.content === undefined) return undefined;\n\n if (typeof message.content === \"string\") {\n const forcedTier = parseForcedTier(message.content);\n if (forcedTier) {\n message.content = stripForcedTierDirective(message.content);\n }\n return forcedTier;\n }\n\n if (Array.isArray(message.content)) {\n let forcedTier: Tier | undefined;\n message.content = message.content.map((part) => {\n if (part.type !== \"text\" || typeof part.text !== \"string\") return part;\n\n const partForcedTier = parseForcedTier(part.text);\n if (!forcedTier && partForcedTier) {\n forcedTier = partForcedTier;\n }\n if (!partForcedTier) return part;\n\n return {\n ...part,\n text: stripForcedTierDirective(part.text),\n };\n });\n return forcedTier;\n }\n\n return undefined;\n}\n\nexport type ProxyOptions = {\n apiKey: string;\n apiBase?: string;\n /** Port to listen on (default: 8403) */\n port?: number;\n routingConfig?: Partial<RoutingConfig>;\n /** Request timeout in ms (default: 180000 = 3 minutes). */\n requestTimeoutMs?: number;\n onReady?: (port: number) => void;\n onError?: (error: Error) => void;\n onRouted?: (decision: RoutingDecision) => void;\n onModelsSynced?: (count: number) => void;\n};\n\nexport type ProxyHandle = {\n port: number;\n baseUrl: string;\n close: () => Promise<void>;\n};\n\n/**\n * Build model pricing map from a models array.\n */\nfunction buildModelPricing(models: ZenMuxModel[]): Map<string, ModelPricing> {\n const map = new Map<string, ModelPricing>();\n for (const m of models) {\n if (m.id === AUTO_MODEL) continue;\n map.set(m.id, { inputPrice: m.inputPrice, outputPrice: m.outputPrice });\n }\n return map;\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 * Start the local proxy server.\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 apiBase = options.apiBase ?? ZENMUX_API;\n const apiKey = options.apiKey;\n\n // Build router options\n const routingConfig = mergeRoutingConfig(options.routingConfig);\n\n // Try to fetch dynamic models, fall back to static catalog\n let models: ZenMuxModel[];\n try {\n models = await fetchModels(apiKey);\n options.onModelsSynced?.(models.length);\n } catch {\n models = ZENMUX_MODELS;\n }\n\n const modelPricing = buildModelPricing(models);\n\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 const server = createServer(async (req: IncomingMessage, res: ServerResponse) => {\n // Health check\n if (req.url === \"/health\" || req.url?.startsWith(\"/health?\")) {\n res.writeHead(200, { \"Content-Type\": \"application/json\" });\n res.end(\n JSON.stringify({\n status: \"ok\",\n provider: \"zenmux\",\n models: models.length,\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(req, res, apiBase, apiKey, options, routerOpts, deduplicator);\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 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 requested port (default: 8403)\n const listenPort = options.port ?? DEFAULT_PORT;\n\n return new Promise<ProxyHandle>((resolve, reject) => {\n server.on(\"error\", reject);\n\n server.listen(listenPort, \"127.0.0.1\", () => {\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 resolve({\n port,\n baseUrl,\n close: () =>\n new Promise<void>((res, rej) => {\n server.close((err) => (err ? rej(err) : res()));\n }),\n });\n });\n });\n}\n\n/**\n * Proxy a single request to ZenMux API with smart routing and dedup.\n */\nasync function proxyRequest(\n req: IncomingMessage,\n res: ServerResponse,\n apiBase: string,\n apiKey: string,\n options: ProxyOptions,\n routerOpts: RouterOptions,\n deduplicator: RequestDeduplicator,\n): Promise<void> {\n const startTime = Date.now();\n\n // Build upstream URL\n const upstreamUrl = `${apiBase}${req.url}`;\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 // --- Smart routing ---\n let routingDecision: RoutingDecision | undefined;\n let isStreaming = false;\n let modelId = \"\";\n const isChatCompletion = req.url?.includes(\"/chat/completions\");\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 const maxTokens =\n typeof parsed.max_completion_tokens === \"number\"\n ? parsed.max_completion_tokens\n : typeof parsed.max_tokens === \"number\"\n ? parsed.max_tokens\n : 4096;\n\n if (parsed.model === AUTO_MODEL || parsed.model === AUTO_MODEL_SHORT) {\n // Extract prompt from messages\n const messages = Array.isArray(parsed.messages)\n ? (parsed.messages as ChatMessage[])\n : undefined;\n\n let lastUserMsg: ChatMessage | undefined;\n if (messages) {\n for (let i = messages.length - 1; i >= 0; i--) {\n if (messages[i].role === \"user\") {\n lastUserMsg = messages[i];\n break;\n }\n }\n }\n const systemMsg = messages?.find((m: ChatMessage) => m.role === \"system\");\n const forcedTier = extractAndStripForcedTier(lastUserMsg);\n const prompt = extractText(lastUserMsg?.content);\n const systemPrompt = extractText(systemMsg?.content) || undefined;\n const allMessageText =\n messages\n ?.map((m) => extractText(m.content))\n .filter((s) => s.length > 0)\n .join(\"\\n\") ?? \"\";\n const estimatedInputTokens =\n allMessageText.length > 0 ? Math.ceil(allMessageText.length / 4) : undefined;\n const structuredOutputRequired =\n typeof parsed.response_format === \"object\" && parsed.response_format !== null;\n\n routingDecision = route(prompt, systemPrompt, maxTokens, routerOpts, {\n estimatedInputTokens,\n forcedTier,\n structuredOutputRequired,\n });\n\n // Replace model in body\n parsed.model = routingDecision.model;\n modelId = routingDecision.model;\n body = Buffer.from(JSON.stringify(parsed));\n\n options.onRouted?.(routingDecision);\n }\n } catch {\n // JSON parse error — forward body as-is\n }\n }\n\n // --- Dedup check ---\n const dedupKey = RequestDeduplicator.hash(body);\n\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 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 deduplicator.markInflight(dedupKey);\n\n // --- Streaming: early header flush + heartbeat ---\n let heartbeatInterval: ReturnType<typeof setInterval> | undefined;\n let headersSentEarly = false;\n\n if (isStreaming) {\n res.writeHead(200, {\n \"content-type\": \"text/event-stream\",\n \"cache-control\": \"no-cache\",\n connection: \"keep-alive\",\n });\n headersSentEarly = true;\n\n res.write(\": heartbeat\\n\\n\");\n\n heartbeatInterval = setInterval(() => {\n if (!res.writableEnded) {\n res.write(\": heartbeat\\n\\n\");\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 headers[\"authorization\"] = `Bearer ${apiKey}`;\n\n // --- Client disconnect cleanup ---\n let completed = false;\n res.on(\"close\", () => {\n if (heartbeatInterval) {\n clearInterval(heartbeatInterval);\n heartbeatInterval = undefined;\n }\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 const upstream = await fetchWithRetry(\n (url, init) => fetch(url, init),\n upstreamUrl,\n {\n method: req.method ?? \"POST\",\n headers,\n body: body.length > 0 ? body : undefined,\n signal: controller.signal,\n },\n );\n\n clearTimeout(timeoutId);\n\n if (heartbeatInterval) {\n clearInterval(heartbeatInterval);\n heartbeatInterval = undefined;\n }\n\n // --- Stream response and collect for dedup cache ---\n const responseChunks: Buffer[] = [];\n\n if (headersSentEarly) {\n // Streaming: headers already sent. Check for upstream errors.\n if (upstream.status !== 200) {\n const errBody = await upstream.text();\n const errEvent = `data: ${JSON.stringify({ error: { message: errBody, type: \"upstream_error\", status: upstream.status } })}\\n\\n`;\n res.write(errEvent);\n res.write(\"data: [DONE]\\n\\n\");\n res.end();\n\n deduplicator.complete(dedupKey, {\n status: 200,\n headers: { \"content-type\": \"text/event-stream\" },\n body: Buffer.from(errEvent + \"data: [DONE]\\n\\n\"),\n completedAt: Date.now(),\n });\n return;\n }\n\n // Pipe upstream SSE data to client\n if (upstream.body) {\n const reader = upstream.body.getReader();\n try {\n while (true) {\n const { done, value } = await reader.read();\n if (done) break;\n res.write(value);\n responseChunks.push(Buffer.from(value));\n }\n } finally {\n reader.releaseLock();\n }\n }\n\n res.end();\n\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 if (key === \"transfer-encoding\" || key === \"connection\") return;\n responseHeaders[key] = value;\n });\n\n res.writeHead(upstream.status, responseHeaders);\n\n if (upstream.body) {\n const reader = upstream.body.getReader();\n try {\n while (true) {\n const { done, value } = await reader.read();\n if (done) break;\n res.write(value);\n responseChunks.push(Buffer.from(value));\n }\n } finally {\n reader.releaseLock();\n }\n }\n\n res.end();\n\n deduplicator.complete(dedupKey, {\n status: upstream.status,\n headers: responseHeaders,\n body: Buffer.concat(responseChunks),\n completedAt: Date.now(),\n });\n }\n\n completed = true;\n } catch (err) {\n clearTimeout(timeoutId);\n\n if (heartbeatInterval) {\n clearInterval(heartbeatInterval);\n heartbeatInterval = undefined;\n }\n\n deduplicator.removeInflight(dedupKey);\n\n if (err instanceof Error && err.name === \"AbortError\") {\n throw new Error(`Request timed out after ${timeoutMs}ms`);\n }\n\n throw err;\n }\n\n // --- Usage logging (fire-and-forget) ---\n if (routingDecision) {\n const entry: UsageEntry = {\n timestamp: new Date().toISOString(),\n model: routingDecision.model,\n cost: routingDecision.costEstimate,\n latencyMs: Date.now() - startTime,\n };\n logUsage(entry).catch(() => {});\n }\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 LLM 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 // Keep a mild \"short prompt\" penalty, but avoid overpowering technical intent.\n return { name: \"tokenCount\", score: -0.6, 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 hasArchitectureComplexitySignal(text: string): boolean {\n const architectureNouns = [\n \"architecture\",\n \"system architecture\",\n \"solution architecture\",\n \"platform architecture\",\n \"event-driven architecture\",\n \"system design\",\n \"design a system\",\n \"distributed system\",\n \"topology\",\n \"架构\",\n \"架构设计\",\n \"系统架构\",\n \"平台架构\",\n \"事件驱动架构\",\n \"微服务架构\",\n \"系统拓扑\",\n \"系统设计\",\n \"消息队列\",\n \"message queue\",\n \"event bus\",\n ];\n const scaleSignals = [\n \"distributed\",\n \"scalable\",\n \"scale\",\n \"high concurrency\",\n \"qps\",\n \"rps\",\n \"latency\",\n \"durability\",\n \"reliability\",\n \"availability\",\n \"shard\",\n \"sharding\",\n \"partition\",\n \"replica\",\n \"replication\",\n \"failover\",\n \"multi-region\",\n \"multi-tenant\",\n \"idempotent\",\n \"exactly-once\",\n \"at-least-once\",\n \"eventual consistency\",\n \"backpressure\",\n \"dead letter\",\n \"dlq\",\n \"分布式\",\n \"高并发\",\n \"并发\",\n \"延迟\",\n \"低延迟\",\n \"可扩展\",\n \"扩展性\",\n \"吞吐量\",\n \"可用性\",\n \"可靠性\",\n \"分片\",\n \"分区\",\n \"副本\",\n \"复制\",\n \"容灾\",\n \"多活\",\n \"多租户\",\n \"幂等\",\n \"最终一致性\",\n \"一致性\",\n \"故障转移\",\n \"削峰\",\n \"背压\",\n \"死信\",\n \"死信队列\",\n \"microservice\",\n \"kubernetes\",\n \"consistency\",\n \"fault tolerance\",\n \"high availability\",\n \"高可用\",\n \"吞吐\",\n \"throughput\",\n ];\n const designVerbs = [\n \"design\",\n \"architect\",\n \"build\",\n \"implement\",\n \"propose\",\n \"plan\",\n \"draft\",\n \"outline\",\n \"设计\",\n \"构建\",\n \"搭建\",\n \"实现\",\n \"规划\",\n \"给出\",\n \"制定\",\n ];\n\n const hasArchitectureNoun = architectureNouns.some((kw) => text.includes(kw));\n const hasScaleSignal = scaleSignals.some((kw) => text.includes(kw));\n const hasDesignVerb = designVerbs.some((kw) => text.includes(kw));\n\n return hasArchitectureNoun && (hasScaleSignal || hasDesignVerb);\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// ─── Main Classifier ───\n\nexport function classifyByRules(\n prompt: string,\n estimatedTokens: number,\n config: ScoringConfig,\n): ScoringResult {\n // Complexity scoring should be driven by user intent, not static system prompts.\n const text = prompt.toLowerCase();\n // User prompt only — used for reasoning markers.\n const userText = prompt.toLowerCase();\n\n // Score all 14 dimensions\n const dimensions: DimensionScore[] = [\n // Original 8 dimensions\n scoreTokenCount(estimatedTokens, config.tokenCountThresholds),\n scoreKeywordMatch(\n text,\n config.codeKeywords,\n \"codePresence\",\n \"code\",\n { low: 1, high: 2 },\n { none: 0, low: 0.5, high: 1.0 },\n ),\n // Reasoning markers use USER prompt only — system prompt \"step by step\" shouldn't trigger reasoning\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 text,\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 text,\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 text,\n config.simpleKeywords,\n \"simpleIndicators\",\n \"simple\",\n { low: 1, high: 2 },\n { none: 0, low: -1.0, high: -1.0 },\n ),\n scoreMultiStep(text),\n scoreQuestionComplexity(prompt),\n\n // 6 new dimensions\n scoreKeywordMatch(\n text,\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 text,\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 text,\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 text,\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 text,\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 text,\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 // 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 };\n }\n\n // Architecture/system-design prompts are typically high-complexity even when short.\n // Route these directly to COMPLEX to avoid under-classifying into MEDIUM.\n if (hasArchitectureComplexitySignal(userText)) {\n return {\n score: Math.max(weightedScore, config.tierBoundaries.mediumComplex + 0.03),\n tier: \"COMPLEX\",\n confidence: 0.82,\n signals: [...signals, \"architecture-design\"],\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 };\n }\n\n return { score: weightedScore, tier, confidence, signals };\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\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): RoutingDecision {\n const tierConfig = tierConfigs[tier];\n const model = tierConfig.primary;\n const pricing = modelPricing.get(model);\n\n const inputCost = pricing ? (estimatedInputTokens / 1_000_000) * pricing.inputPrice : 0;\n const outputCost = pricing ? (maxOutputTokens / 1_000_000) * pricing.outputPrice : 0;\n const costEstimate = inputCost + outputCost;\n\n // Baseline: what Claude Opus 4.6 would cost (the premium default)\n const opusPricing = modelPricing.get(\"anthropic/claude-opus-4.6\");\n const baselineInput = opusPricing\n ? (estimatedInputTokens / 1_000_000) * opusPricing.inputPrice\n : 0;\n const baselineOutput = opusPricing ? (maxOutputTokens / 1_000_000) * opusPricing.outputPrice : 0;\n const baselineCost = baselineInput + baselineOutput;\n\n const savings = baselineCost > 0 ? Math.max(0, (baselineCost - costEstimate) / baselineCost) : 0;\n\n return {\n model,\n tier,\n confidence,\n method,\n reasoning,\n costEstimate,\n baselineCost,\n savings,\n };\n}\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 * Tier models updated for ZenMux's catalog.\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: English + Chinese (中文) + Japanese (日本語) + Russian (Русский)\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 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 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 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 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 // 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 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 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 ],\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 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 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\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.12,\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 },\n\n // Tier boundaries on weighted score axis\n tierBoundaries: {\n simpleMedium: 0.0,\n mediumComplex: 0.15,\n complexReasoning: 0.25,\n },\n\n // Sigmoid steepness for confidence calibration\n confidenceSteepness: 12,\n // Below this confidence → ambiguous (null tier)\n confidenceThreshold: 0.6,\n },\n\n tiers: {\n SIMPLE: {\n primary: \"deepseek/deepseek-chat\",\n },\n MEDIUM: {\n primary: \"google/gemini-3-flash-preview\",\n },\n COMPLEX: {\n primary: \"anthropic/claude-sonnet-4.5\",\n },\n REASONING: {\n primary: \"deepseek/deepseek-reasoner\",\n },\n },\n\n overrides: {\n maxTokensForceComplex: 100_000,\n structuredOutputMinTier: \"MEDIUM\",\n ambiguousDefaultTier: \"MEDIUM\",\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.js\";\nimport { selectModel, type ModelPricing } from \"./selector.js\";\n\nexport type RouterOptions = {\n config: RoutingConfig;\n modelPricing: Map<string, ModelPricing>;\n};\n\nexport type RouteContext = {\n /**\n * Estimated total input tokens for the full request payload.\n * Falls back to `systemPrompt + prompt` estimate when omitted.\n */\n estimatedInputTokens?: number;\n /**\n * Force a tier (prompt-level override), e.g. \"USE COMPLEX\".\n */\n forcedTier?: Tier;\n /**\n * Whether the request explicitly requires structured output (e.g. response_format).\n */\n structuredOutputRequired?: 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 context?: RouteContext,\n): RoutingDecision {\n const { config, modelPricing } = options;\n\n // Token estimates (~4 chars/token): scoring should use user prompt only,\n // while cost/override should use full request estimate.\n const userEstimatedTokens = Math.ceil(prompt.length / 4);\n const fallbackEstimatedTokens = Math.ceil(`${systemPrompt ?? \"\"} ${prompt}`.length / 4);\n const estimatedTokens = context?.estimatedInputTokens ?? fallbackEstimatedTokens;\n\n // --- Prompt override: explicit tier force ---\n if (context?.forcedTier) {\n return selectModel(\n context.forcedTier,\n 1.0,\n \"rules\",\n `forced tier override: ${context.forcedTier}`,\n config.tiers,\n modelPricing,\n estimatedTokens,\n maxOutputTokens,\n );\n }\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`,\n config.tiers,\n modelPricing,\n estimatedTokens,\n maxOutputTokens,\n );\n }\n\n // Structured output detection:\n // prioritize explicit request signal (from proxy), then user prompt hints.\n const hasStructuredOutput =\n context?.structuredOutputRequired ?? /json|structured|schema|yaml|xml|csv|table/i.test(prompt);\n\n // --- Rule-based classification ---\n const ruleResult = classifyByRules(prompt, userEstimatedTokens, config.scoring);\n\n let tier: Tier;\n let confidence: number;\n const method: \"rules\" | \"llm\" = \"rules\";\n let reasoning = `score=${ruleResult.score} | ${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 return selectModel(\n tier,\n confidence,\n method,\n reasoning,\n config.tiers,\n modelPricing,\n estimatedTokens,\n maxOutputTokens,\n );\n}\n\nexport { DEFAULT_ROUTING_CONFIG } from \"./config.js\";\nexport type { RoutingDecision, Tier, RoutingConfig } from \"./types.js\";\nexport type { ModelPricing } from \"./selector.js\";\n","/**\n * Dynamic Model Sync\n *\n * Fetches the latest model catalog and pricing from ZenMux's /v1/models API.\n * Caches results in memory with a configurable TTL to avoid excessive API calls.\n * Falls back to the built-in static catalog if the API is unreachable.\n */\n\nimport { ZENMUX_MODELS, type ZenMuxModel } from \"./models.js\";\n\nconst MODELS_ENDPOINT = \"https://zenmux.ai/api/v1/models\";\nconst DEFAULT_CACHE_TTL_MS = 30 * 60 * 1000; // 30 minutes\n\ntype PricingEntry = {\n value: number;\n unit: string;\n currency: string;\n conditions?: Record<string, unknown>;\n};\n\ntype ApiModel = {\n id: string;\n display_name?: string;\n owned_by?: string;\n input_modalities?: string[];\n output_modalities?: string[];\n capabilities?: { reasoning?: boolean };\n context_length?: number;\n pricings?: {\n prompt?: PricingEntry[];\n completion?: PricingEntry[];\n };\n};\n\ntype ApiResponse = {\n data: ApiModel[];\n object: string;\n};\n\ntype CacheEntry = {\n models: ZenMuxModel[];\n fetchedAt: number;\n};\n\nlet cache: CacheEntry | null = null;\n\n/**\n * Extract price per 1M tokens from pricing array.\n * Looks for \"perMTokens\" unit, falls back to 0.\n */\nfunction extractPrice(entries?: PricingEntry[]): number {\n if (!entries || entries.length === 0) return 0;\n // Prefer perMTokens entry\n const perM = entries.find((e) => e.unit === \"perMTokens\");\n if (perM) return perM.value;\n // Fallback: first entry\n return entries[0].value;\n}\n\n/**\n * Convert API model to our internal format.\n */\nfunction toZenMuxModel(api: ApiModel): ZenMuxModel {\n const hasVision =\n api.input_modalities?.includes(\"image\") || api.input_modalities?.includes(\"video\");\n\n return {\n id: api.id,\n name: api.display_name || api.id,\n inputPrice: extractPrice(api.pricings?.prompt),\n outputPrice: extractPrice(api.pricings?.completion),\n contextWindow: api.context_length || 128_000,\n maxOutput: 65_536, // API doesn't expose this; use sensible default\n reasoning: api.capabilities?.reasoning ?? false,\n vision: hasVision ?? false,\n };\n}\n\n/**\n * Fetch latest models from ZenMux API.\n *\n * @param apiKey - ZenMux API key for authentication\n * @param cacheTtlMs - Cache TTL in ms (default: 30 minutes)\n * @returns Array of ZenMuxModel with latest pricing\n */\nexport async function fetchModels(\n apiKey: string,\n cacheTtlMs = DEFAULT_CACHE_TTL_MS,\n): Promise<ZenMuxModel[]> {\n // Return cached if fresh\n if (cache && Date.now() - cache.fetchedAt < cacheTtlMs) {\n return cache.models;\n }\n\n try {\n const response = await fetch(MODELS_ENDPOINT, {\n headers: {\n authorization: `Bearer ${apiKey}`,\n \"user-agent\": \"clawzenmux/0.1.0\",\n },\n signal: AbortSignal.timeout(10_000), // 10s timeout\n });\n\n if (!response.ok) {\n throw new Error(`API returned ${response.status}`);\n }\n\n const data = (await response.json()) as ApiResponse;\n if (!data.data || !Array.isArray(data.data)) {\n throw new Error(\"Invalid API response format\");\n }\n\n const models = data.data.map(toZenMuxModel);\n\n // Add the auto meta-model\n models.unshift({\n id: \"clawzenmux/auto\",\n name: \"ZenMux Smart Router\",\n inputPrice: 0,\n outputPrice: 0,\n contextWindow: 1_050_000,\n maxOutput: 128_000,\n });\n\n cache = { models, fetchedAt: Date.now() };\n return models;\n } catch {\n // Fallback to static catalog\n return ZENMUX_MODELS;\n }\n}\n\n/**\n * Invalidate the model cache (e.g., after config change).\n */\nexport function invalidateModelCache(): void {\n cache = null;\n}\n","/**\n * Usage Logger\n *\n * Logs every LLM request as a JSON line to a daily log file.\n * Files: ~/.openclaw/zenmux/logs/usage-YYYY-MM-DD.jsonl\n *\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 cost: number;\n latencyMs: number;\n};\n\nconst LOG_DIR = join(homedir(), \".openclaw\", \"zenmux\", \"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 * 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 resolve: (result: CachedResponse) => void;\n waiters: Promise<CachedResponse>[];\n};\n\nconst DEFAULT_TTL_MS = 30_000; // 30 seconds\nconst MAX_BODY_SIZE = 1_048_576; // 1MB\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 return createHash(\"sha256\").update(body).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 const promise = new Promise<CachedResponse>((resolve) => {\n entry.waiters.push(\n new Promise<CachedResponse>((r) => {\n const orig = entry.resolve;\n entry.resolve = (result) => {\n orig(result);\n resolve(result);\n r(result);\n };\n }),\n );\n });\n return promise;\n }\n\n /** Mark a request as in-flight. */\n markInflight(key: string): void {\n this.inflight.set(key, {\n resolve: () => {},\n waiters: [],\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 entry.resolve(result);\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 removeInflight(key: string): void {\n this.inflight.delete(key);\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 * Retry Logic for ClawZenMux\n *\n * Provides fetch wrapper with exponential backoff for transient errors.\n * Retries on 429 (rate limit), 502, 503, 504 (server errors).\n */\n\n/** Configuration for retry behavior */\nexport type RetryConfig = {\n /** Maximum number of retries (default: 2) */\n maxRetries: number;\n /** Base delay in ms for exponential backoff (default: 500) */\n baseDelayMs: number;\n /** HTTP status codes that trigger a retry (default: [429, 502, 503, 504]) */\n retryableCodes: number[];\n};\n\n/** Default retry configuration */\nexport const DEFAULT_RETRY_CONFIG: RetryConfig = {\n maxRetries: 2,\n baseDelayMs: 500,\n retryableCodes: [429, 502, 503, 504],\n};\n\n/** Sleep for a given number of milliseconds */\nfunction sleep(ms: number): Promise<void> {\n return new Promise((resolve) => setTimeout(resolve, ms));\n}\n\n/**\n * Wrap a fetch-like function with retry logic and exponential backoff.\n */\nexport async function fetchWithRetry(\n fetchFn: (url: string, init?: RequestInit) => Promise<Response>,\n url: string,\n init?: RequestInit,\n config?: Partial<RetryConfig>,\n): Promise<Response> {\n const cfg: RetryConfig = {\n ...DEFAULT_RETRY_CONFIG,\n ...config,\n };\n\n let lastError: Error | undefined;\n let lastResponse: Response | undefined;\n\n for (let attempt = 0; attempt <= cfg.maxRetries; attempt++) {\n try {\n const response = await fetchFn(url, init);\n\n // Success or non-retryable status — return immediately\n if (!cfg.retryableCodes.includes(response.status)) {\n return response;\n }\n\n // Retryable status — save response and maybe retry\n lastResponse = response;\n\n // Check for Retry-After header (common with 429)\n const retryAfter = response.headers.get(\"retry-after\");\n let delay: number;\n\n if (retryAfter) {\n const seconds = parseInt(retryAfter, 10);\n delay = isNaN(seconds) ? cfg.baseDelayMs * Math.pow(2, attempt) : seconds * 1000;\n } else {\n delay = cfg.baseDelayMs * Math.pow(2, attempt);\n }\n\n // Only retry if we have attempts left\n if (attempt < cfg.maxRetries) {\n await sleep(delay);\n }\n } catch (err) {\n lastError = err instanceof Error ? err : new Error(String(err));\n\n // Network errors are retryable\n if (attempt < cfg.maxRetries) {\n const delay = cfg.baseDelayMs * Math.pow(2, attempt);\n await sleep(delay);\n }\n }\n }\n\n // All retries exhausted — return last response or throw last error\n if (lastResponse) {\n return lastResponse;\n }\n\n throw lastError ?? new Error(\"Max retries exceeded\");\n}\n\n/**\n * Check if an error or response indicates a retryable condition.\n */\nexport function isRetryable(\n errorOrResponse: Error | Response,\n config?: Partial<RetryConfig>,\n): boolean {\n const retryableCodes = config?.retryableCodes ?? DEFAULT_RETRY_CONFIG.retryableCodes;\n\n if (errorOrResponse instanceof Response) {\n return retryableCodes.includes(errorOrResponse.status);\n }\n\n // Network errors are generally retryable\n const message = errorOrResponse.message.toLowerCase();\n return (\n message.includes(\"network\") ||\n message.includes(\"timeout\") ||\n message.includes(\"econnreset\") ||\n message.includes(\"econnrefused\") ||\n message.includes(\"socket hang up\")\n );\n}\n","/**\n * Typed Error Classes for ClawZenMux\n *\n * Provides structured errors for authentication and proxy failures.\n */\n\n/**\n * Thrown when no ZenMux API key is configured.\n */\nexport class AuthenticationError extends Error {\n readonly code = \"AUTHENTICATION_ERROR\" as const;\n\n constructor(message?: string) {\n super(\n message ??\n \"No ZenMux API key configured. Set ZENMUX_API_KEY env var or configure via plugin settings.\",\n );\n this.name = \"AuthenticationError\";\n }\n}\n\n/**\n * Thrown when the API key is invalid (401 from ZenMux).\n */\nexport class InvalidApiKeyError extends Error {\n readonly code = \"INVALID_API_KEY\" as const;\n\n constructor() {\n super(\"Invalid ZenMux API key. Check your key at https://zenmux.ai/console/api-keys\");\n this.name = \"InvalidApiKeyError\";\n }\n}\n\n/**\n * Type guard to check if an error is AuthenticationError.\n */\nexport function isAuthenticationError(error: unknown): error is AuthenticationError {\n return error instanceof Error && (error as AuthenticationError).code === \"AUTHENTICATION_ERROR\";\n}\n\n/**\n * Type guard to check if an error is InvalidApiKeyError.\n */\nexport function isInvalidApiKeyError(error: unknown): error is InvalidApiKeyError {\n return error instanceof Error && (error as InvalidApiKeyError).code === \"INVALID_API_KEY\";\n}\n","/**\n * @wy51ai/clawzenmux\n *\n * Smart LLM router for OpenClaw via ZenMux — 100+ models, AI-powered routing,\n * multi-language support, token cost savings.\n *\n * Usage:\n * # Install the plugin\n * openclaw plugin install @wy51ai/clawzenmux\n *\n * # Set your ZenMux API key\n * export ZENMUX_API_KEY=your-key-here\n *\n * # Use smart routing (auto-picks cheapest model)\n * openclaw models set clawzenmux/auto\n *\n * # Or use any specific ZenMux model\n * openclaw models set openai/gpt-5.2\n */\n\nimport type { OpenClawPluginDefinition, OpenClawPluginApi } from \"./types.js\";\nimport { zenmuxProvider, setActiveProxy } from \"./provider.js\";\nimport { startProxy } from \"./proxy.js\";\nimport { resolveApiKey } from \"./auth.js\";\nimport type { RoutingConfig } from \"./router/index.js\";\nimport { OPENCLAW_MODELS } from \"./models.js\";\nimport { AuthenticationError } from \"./errors.js\";\nimport { readFileSync, writeFileSync, existsSync, readdirSync, mkdirSync } from \"node:fs\";\nimport { homedir } from \"node:os\";\nimport { join } from \"node:path\";\n\n/**\n * Inject ZenMux models config into OpenClaw config file.\n */\nfunction injectModelsConfig(logger: { info: (msg: string) => void }, apiKey?: string): void {\n const configPath = join(homedir(), \".openclaw\", \"openclaw.json\");\n if (!existsSync(configPath)) {\n logger.info(\"OpenClaw config not found, skipping models injection\");\n return;\n }\n\n try {\n const config = JSON.parse(readFileSync(configPath, \"utf-8\"));\n\n // Clean up old \"zenmux\" key if present\n if (config.models?.providers?.zenmux) {\n delete config.models.providers.zenmux;\n }\n\n if (config.models?.providers?.clawzenmux) {\n return; // Already configured\n }\n\n if (!config.models) config.models = {};\n if (!config.models.providers) config.models.providers = {};\n\n config.models.providers.clawzenmux = {\n baseUrl: \"http://127.0.0.1:8403/v1\",\n api: \"openai-completions\",\n ...(apiKey ? { apiKey } : {}),\n models: OPENCLAW_MODELS,\n };\n\n writeFileSync(configPath, JSON.stringify(config, null, 2));\n logger.info(\"Injected ClawZenMux models into OpenClaw config\");\n } catch {\n // Silently fail — config injection is best-effort\n }\n}\n\n/**\n * Inject auth profile for ZenMux into agent auth stores.\n */\nfunction injectAuthProfile(\n logger: { info: (msg: string) => void },\n apiKey: string,\n): void {\n const agentsDir = join(homedir(), \".openclaw\", \"agents\");\n if (!existsSync(agentsDir)) {\n return;\n }\n\n try {\n const agents = readdirSync(agentsDir, { withFileTypes: true })\n .filter((d) => d.isDirectory())\n .map((d) => d.name);\n\n for (const agentId of agents) {\n const authDir = join(agentsDir, agentId, \"agent\");\n const authPath = join(authDir, \"auth-profiles.json\");\n\n if (!existsSync(authDir)) {\n mkdirSync(authDir, { recursive: true });\n }\n\n let authProfiles: Record<string, unknown> = {};\n if (existsSync(authPath)) {\n try {\n authProfiles = JSON.parse(readFileSync(authPath, \"utf-8\"));\n } catch {\n authProfiles = {};\n }\n }\n\n if (authProfiles.clawzenmux) {\n continue;\n }\n\n authProfiles.clawzenmux = {\n profileId: \"default\",\n credential: {\n apiKey: apiKey,\n },\n };\n\n writeFileSync(authPath, JSON.stringify(authProfiles, null, 2));\n logger.info(`Injected ZenMux auth profile for agent: ${agentId}`);\n }\n } catch {\n // Silently fail — auth injection is best-effort\n }\n}\n\n/**\n * Start the proxy in the background.\n */\nasync function startProxyInBackground(api: OpenClawPluginApi): Promise<void> {\n // Resolve API key\n const keyResult = resolveApiKey(api.pluginConfig);\n\n if (!keyResult) {\n throw new AuthenticationError();\n }\n\n const { key: apiKey, source } = keyResult;\n\n if (source === \"config\") {\n api.logger.info(\"Using API key from plugin config\");\n } else if (source === \"saved\") {\n api.logger.info(\"Using saved API key from ~/.openclaw/zenmux/api.key\");\n } else {\n api.logger.info(\"Using API key from ZENMUX_API_KEY env var\");\n }\n\n // Inject auth profiles with the resolved key\n injectAuthProfile(api.logger, apiKey);\n\n // Resolve config overrides from plugin config\n const routingConfig = api.pluginConfig?.routing as Partial<RoutingConfig> | undefined;\n\n const proxy = await startProxy({\n apiKey,\n routingConfig,\n onReady: (port) => {\n api.logger.info(`ZenMux proxy listening on port ${port}`);\n },\n onError: (error) => {\n api.logger.error(`ZenMux 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(`${decision.tier} → ${decision.model} $${cost} (saved ${saved}%) | ${decision.reasoning}`);\n },\n onModelsSynced: (count) => {\n api.logger.info(`Synced ${count} models from ZenMux API`);\n },\n });\n\n setActiveProxy(proxy);\n\n api.logger.info(\n `ZenMux provider active — ${proxy.baseUrl}/v1 (routing: rules only)`,\n );\n}\n\nconst plugin: OpenClawPluginDefinition = {\n id: \"clawzenmux\",\n name: \"ClawZenMux\",\n description:\n \"Smart LLM router via ZenMux — 100+ models, rules-based routing, token cost savings\",\n version: \"0.1.0\",\n\n register(api: OpenClawPluginApi) {\n // Register ZenMux as a provider (sync — available immediately)\n api.registerProvider(zenmuxProvider);\n\n // Resolve API key early so we can inject it into configs\n const keyResult = resolveApiKey(api.pluginConfig);\n const apiKey = keyResult?.key;\n\n // Inject models config into OpenClaw config file\n injectModelsConfig(api.logger, apiKey);\n\n // Set runtime config for immediate availability\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.clawzenmux = {\n baseUrl: \"http://127.0.0.1:8403/v1\",\n api: \"openai-completions\",\n ...(apiKey ? { apiKey } : {}),\n models: OPENCLAW_MODELS,\n };\n\n api.logger.info(`ClawZenMux provider registered (${OPENCLAW_MODELS.length} models)`);\n api.logger.info(`Registered model IDs: ${OPENCLAW_MODELS.slice(0, 5).map(m => m.id).join(\", \")}...`);\n\n // Start proxy in background (fire-and-forget)\n startProxyInBackground(api).catch((err) => {\n api.logger.error(\n `Failed to start ZenMux proxy: ${err instanceof Error ? err.message : String(err)}`,\n );\n });\n },\n};\n\nexport default plugin;\n\n// Re-export for programmatic use\nexport { startProxy } from \"./proxy.js\";\nexport type { ProxyOptions, ProxyHandle } from \"./proxy.js\";\nexport { zenmuxProvider } from \"./provider.js\";\nexport { OPENCLAW_MODELS, ZENMUX_MODELS, buildProviderModels } from \"./models.js\";\nexport type { ZenMuxModel } from \"./models.js\";\nexport { route, DEFAULT_ROUTING_CONFIG } from \"./router/index.js\";\nexport type { RoutingDecision, RoutingConfig, Tier } from \"./router/index.js\";\nexport { fetchModels, invalidateModelCache } from \"./model-sync.js\";\nexport { logUsage } from \"./logger.js\";\nexport type { UsageEntry } from \"./logger.js\";\nexport { RequestDeduplicator } from \"./dedup.js\";\nexport type { CachedResponse } from \"./dedup.js\";\nexport { resolveApiKey, saveApiKey, zenmuxApiKeyAuth } from \"./auth.js\";\nexport { fetchWithRetry, isRetryable, DEFAULT_RETRY_CONFIG } from \"./retry.js\";\nexport type { RetryConfig } from \"./retry.js\";\nexport {\n AuthenticationError,\n InvalidApiKeyError,\n isAuthenticationError,\n isInvalidApiKeyError,\n} from \"./errors.js\";\n"],"mappings":";AAsBO,IAAM,gBAA+B;AAAA;AAAA,EAE1C;AAAA,IACE,IAAI;AAAA,IACJ,MAAM;AAAA,IACN,YAAY;AAAA,IACZ,aAAa;AAAA,IACb,eAAe;AAAA,IACf,WAAW;AAAA,EACb;AAAA;AAAA,EAGA;AAAA,IACE,IAAI;AAAA,IACJ,MAAM;AAAA,IACN,YAAY;AAAA,IACZ,aAAa;AAAA,IACb,eAAe;AAAA,IACf,WAAW;AAAA,IACX,WAAW;AAAA,EACb;AAAA,EACA;AAAA,IACE,IAAI;AAAA,IACJ,MAAM;AAAA,IACN,YAAY;AAAA,IACZ,aAAa;AAAA,IACb,eAAe;AAAA,IACf,WAAW;AAAA,IACX,WAAW;AAAA,IACX,QAAQ;AAAA,EACV;AAAA,EACA;AAAA,IACE,IAAI;AAAA,IACJ,MAAM;AAAA,IACN,YAAY;AAAA,IACZ,aAAa;AAAA,IACb,eAAe;AAAA,IACf,WAAW;AAAA,IACX,WAAW;AAAA,IACX,QAAQ;AAAA,EACV;AAAA,EACA;AAAA,IACE,IAAI;AAAA,IACJ,MAAM;AAAA,IACN,YAAY;AAAA,IACZ,aAAa;AAAA,IACb,eAAe;AAAA,IACf,WAAW;AAAA,IACX,WAAW;AAAA,EACb;AAAA,EACA;AAAA,IACE,IAAI;AAAA,IACJ,MAAM;AAAA,IACN,YAAY;AAAA,IACZ,aAAa;AAAA,IACb,eAAe;AAAA,IACf,WAAW;AAAA,EACb;AAAA,EACA;AAAA,IACE,IAAI;AAAA,IACJ,MAAM;AAAA,IACN,YAAY;AAAA,IACZ,aAAa;AAAA,IACb,eAAe;AAAA,IACf,WAAW;AAAA,EACb;AAAA;AAAA,EAGA;AAAA,IACE,IAAI;AAAA,IACJ,MAAM;AAAA,IACN,YAAY;AAAA,IACZ,aAAa;AAAA,IACb,eAAe;AAAA,IACf,WAAW;AAAA,IACX,QAAQ;AAAA,EACV;AAAA,EACA;AAAA,IACE,IAAI;AAAA,IACJ,MAAM;AAAA,IACN,YAAY;AAAA,IACZ,aAAa;AAAA,IACb,eAAe;AAAA,IACf,WAAW;AAAA,EACb;AAAA,EACA;AAAA,IACE,IAAI;AAAA,IACJ,MAAM;AAAA,IACN,YAAY;AAAA,IACZ,aAAa;AAAA,IACb,eAAe;AAAA,IACf,WAAW;AAAA,EACb;AAAA,EACA;AAAA,IACE,IAAI;AAAA,IACJ,MAAM;AAAA,IACN,YAAY;AAAA,IACZ,aAAa;AAAA,IACb,eAAe;AAAA,IACf,WAAW;AAAA,IACX,QAAQ;AAAA,EACV;AAAA,EACA;AAAA,IACE,IAAI;AAAA,IACJ,MAAM;AAAA,IACN,YAAY;AAAA,IACZ,aAAa;AAAA,IACb,eAAe;AAAA,IACf,WAAW;AAAA,EACb;AAAA;AAAA,EAGA;AAAA,IACE,IAAI;AAAA,IACJ,MAAM;AAAA,IACN,YAAY;AAAA,IACZ,aAAa;AAAA,IACb,eAAe;AAAA,IACf,WAAW;AAAA,IACX,WAAW;AAAA,EACb;AAAA,EACA;AAAA,IACE,IAAI;AAAA,IACJ,MAAM;AAAA,IACN,YAAY;AAAA,IACZ,aAAa;AAAA,IACb,eAAe;AAAA,IACf,WAAW;AAAA,IACX,WAAW;AAAA,EACb;AAAA,EACA;AAAA,IACE,IAAI;AAAA,IACJ,MAAM;AAAA,IACN,YAAY;AAAA,IACZ,aAAa;AAAA,IACb,eAAe;AAAA,IACf,WAAW;AAAA,IACX,WAAW;AAAA,EACb;AAAA;AAAA,EAGA;AAAA,IACE,IAAI;AAAA,IACJ,MAAM;AAAA,IACN,YAAY;AAAA,IACZ,aAAa;AAAA,IACb,eAAe;AAAA,IACf,WAAW;AAAA,IACX,WAAW;AAAA,EACb;AAAA;AAAA,EAGA;AAAA,IACE,IAAI;AAAA,IACJ,MAAM;AAAA,IACN,YAAY;AAAA,IACZ,aAAa;AAAA,IACb,eAAe;AAAA,IACf,WAAW;AAAA,IACX,WAAW;AAAA,IACX,QAAQ;AAAA,EACV;AAAA,EACA;AAAA,IACE,IAAI;AAAA,IACJ,MAAM;AAAA,IACN,YAAY;AAAA,IACZ,aAAa;AAAA,IACb,eAAe;AAAA,IACf,WAAW;AAAA,IACX,WAAW;AAAA,IACX,QAAQ;AAAA,EACV;AAAA,EACA;AAAA,IACE,IAAI;AAAA,IACJ,MAAM;AAAA,IACN,YAAY;AAAA,IACZ,aAAa;AAAA,IACb,eAAe;AAAA,IACf,WAAW;AAAA,IACX,WAAW;AAAA,EACb;AAAA,EACA;AAAA,IACE,IAAI;AAAA,IACJ,MAAM;AAAA,IACN,YAAY;AAAA,IACZ,aAAa;AAAA,IACb,eAAe;AAAA,IACf,WAAW;AAAA,IACX,WAAW;AAAA,IACX,QAAQ;AAAA,EACV;AAAA,EACA;AAAA,IACE,IAAI;AAAA,IACJ,MAAM;AAAA,IACN,YAAY;AAAA,IACZ,aAAa;AAAA,IACb,eAAe;AAAA,IACf,WAAW;AAAA,IACX,WAAW;AAAA,EACb;AAAA,EACA;AAAA,IACE,IAAI;AAAA,IACJ,MAAM;AAAA,IACN,YAAY;AAAA,IACZ,aAAa;AAAA,IACb,eAAe;AAAA,IACf,WAAW;AAAA,EACb;AAAA;AAAA,EAGA;AAAA,IACE,IAAI;AAAA,IACJ,MAAM;AAAA,IACN,YAAY;AAAA,IACZ,aAAa;AAAA,IACb,eAAe;AAAA,IACf,WAAW;AAAA,IACX,WAAW;AAAA,IACX,QAAQ;AAAA,EACV;AAAA,EACA;AAAA,IACE,IAAI;AAAA,IACJ,MAAM;AAAA,IACN,YAAY;AAAA,IACZ,aAAa;AAAA,IACb,eAAe;AAAA,IACf,WAAW;AAAA,IACX,QAAQ;AAAA,EACV;AAAA,EACA;AAAA,IACE,IAAI;AAAA,IACJ,MAAM;AAAA,IACN,YAAY;AAAA,IACZ,aAAa;AAAA,IACb,eAAe;AAAA,IACf,WAAW;AAAA,IACX,WAAW;AAAA,IACX,QAAQ;AAAA,EACV;AAAA,EACA;AAAA,IACE,IAAI;AAAA,IACJ,MAAM;AAAA,IACN,YAAY;AAAA,IACZ,aAAa;AAAA,IACb,eAAe;AAAA,IACf,WAAW;AAAA,EACb;AAAA,EACA;AAAA,IACE,IAAI;AAAA,IACJ,MAAM;AAAA,IACN,YAAY;AAAA,IACZ,aAAa;AAAA,IACb,eAAe;AAAA,IACf,WAAW;AAAA,IACX,QAAQ;AAAA,EACV;AAAA;AAAA,EAGA;AAAA,IACE,IAAI;AAAA,IACJ,MAAM;AAAA,IACN,YAAY;AAAA,IACZ,aAAa;AAAA,IACb,eAAe;AAAA,IACf,WAAW;AAAA,IACX,WAAW;AAAA,EACb;AAAA,EACA;AAAA,IACE,IAAI;AAAA,IACJ,MAAM;AAAA,IACN,YAAY;AAAA,IACZ,aAAa;AAAA,IACb,eAAe;AAAA,IACf,WAAW;AAAA,IACX,WAAW;AAAA,EACb;AAAA;AAAA,EAGA;AAAA,IACE,IAAI;AAAA,IACJ,MAAM;AAAA,IACN,YAAY;AAAA,IACZ,aAAa;AAAA,IACb,eAAe;AAAA,IACf,WAAW;AAAA,IACX,WAAW;AAAA,IACX,QAAQ;AAAA,EACV;AAAA,EACA;AAAA,IACE,IAAI;AAAA,IACJ,MAAM;AAAA,IACN,YAAY;AAAA,IACZ,aAAa;AAAA,IACb,eAAe;AAAA,IACf,WAAW;AAAA,IACX,WAAW;AAAA,IACX,QAAQ;AAAA,EACV;AAAA,EACA;AAAA,IACE,IAAI;AAAA,IACJ,MAAM;AAAA,IACN,YAAY;AAAA,IACZ,aAAa;AAAA,IACb,eAAe;AAAA,IACf,WAAW;AAAA,IACX,WAAW;AAAA,EACb;AAAA,EACA;AAAA,IACE,IAAI;AAAA,IACJ,MAAM;AAAA,IACN,YAAY;AAAA,IACZ,aAAa;AAAA,IACb,eAAe;AAAA,IACf,WAAW;AAAA,EACb;AAAA;AAAA,EAGA;AAAA,IACE,IAAI;AAAA,IACJ,MAAM;AAAA,IACN,YAAY;AAAA,IACZ,aAAa;AAAA,IACb,eAAe;AAAA,IACf,WAAW;AAAA,IACX,WAAW;AAAA,EACb;AAAA,EACA;AAAA,IACE,IAAI;AAAA,IACJ,MAAM;AAAA,IACN,YAAY;AAAA,IACZ,aAAa;AAAA,IACb,eAAe;AAAA,IACf,WAAW;AAAA,IACX,WAAW;AAAA,EACb;AAAA,EACA;AAAA,IACE,IAAI;AAAA,IACJ,MAAM;AAAA,IACN,YAAY;AAAA,IACZ,aAAa;AAAA,IACb,eAAe;AAAA,IACf,WAAW;AAAA,IACX,QAAQ;AAAA,EACV;AAAA;AAAA,EAGA;AAAA,IACE,IAAI;AAAA,IACJ,MAAM;AAAA,IACN,YAAY;AAAA,IACZ,aAAa;AAAA,IACb,eAAe;AAAA,IACf,WAAW;AAAA,IACX,WAAW;AAAA,EACb;AAAA,EACA;AAAA,IACE,IAAI;AAAA,IACJ,MAAM;AAAA,IACN,YAAY;AAAA,IACZ,aAAa;AAAA,IACb,eAAe;AAAA,IACf,WAAW;AAAA,IACX,WAAW;AAAA,EACb;AAAA,EACA;AAAA,IACE,IAAI;AAAA,IACJ,MAAM;AAAA,IACN,YAAY;AAAA,IACZ,aAAa;AAAA,IACb,eAAe;AAAA,IACf,WAAW;AAAA,IACX,QAAQ;AAAA,EACV;AAAA;AAAA,EAGA;AAAA,IACE,IAAI;AAAA,IACJ,MAAM;AAAA,IACN,YAAY;AAAA,IACZ,aAAa;AAAA,IACb,eAAe;AAAA,IACf,WAAW;AAAA,IACX,WAAW;AAAA,EACb;AAAA,EACA;AAAA,IACE,IAAI;AAAA,IACJ,MAAM;AAAA,IACN,YAAY;AAAA,IACZ,aAAa;AAAA,IACb,eAAe;AAAA,IACf,WAAW;AAAA,IACX,WAAW;AAAA,IACX,QAAQ;AAAA,EACV;AAAA;AAAA,EAGA;AAAA,IACE,IAAI;AAAA,IACJ,MAAM;AAAA,IACN,YAAY;AAAA,IACZ,aAAa;AAAA,IACb,eAAe;AAAA,IACf,WAAW;AAAA,IACX,QAAQ;AAAA,EACV;AAAA;AAAA,EAGA;AAAA,IACE,IAAI;AAAA,IACJ,MAAM;AAAA,IACN,YAAY;AAAA,IACZ,aAAa;AAAA,IACb,eAAe;AAAA,IACf,WAAW;AAAA,IACX,WAAW;AAAA,IACX,QAAQ;AAAA,EACV;AAAA;AAAA,EAGA;AAAA,IACE,IAAI;AAAA,IACJ,MAAM;AAAA,IACN,YAAY;AAAA,IACZ,aAAa;AAAA,IACb,eAAe;AAAA,IACf,WAAW;AAAA,EACb;AAAA;AAAA,EAGA;AAAA,IACE,IAAI;AAAA,IACJ,MAAM;AAAA,IACN,YAAY;AAAA,IACZ,aAAa;AAAA,IACb,eAAe;AAAA,IACf,WAAW;AAAA,IACX,WAAW;AAAA,EACb;AAAA;AAAA,EAGA;AAAA,IACE,IAAI;AAAA,IACJ,MAAM;AAAA,IACN,YAAY;AAAA,IACZ,aAAa;AAAA,IACb,eAAe;AAAA,IACf,WAAW;AAAA,IACX,WAAW;AAAA,EACb;AAAA;AAAA,EAGA;AAAA,IACE,IAAI;AAAA,IACJ,MAAM;AAAA,IACN,YAAY;AAAA,IACZ,aAAa;AAAA,IACb,eAAe;AAAA,IACf,WAAW;AAAA,EACb;AACF;AAKA,SAAS,gBAAgB,GAAuC;AAC9D,SAAO;AAAA,IACL,IAAI,EAAE;AAAA,IACN,MAAM,EAAE;AAAA,IACR,KAAK;AAAA,IACL,WAAW,EAAE,aAAa;AAAA,IAC1B,OAAO,EAAE,SAAS,CAAC,QAAQ,OAAO,IAAI,CAAC,MAAM;AAAA,IAC7C,MAAM;AAAA,MACJ,OAAO,EAAE;AAAA,MACT,QAAQ,EAAE;AAAA,MACV,WAAW;AAAA,MACX,YAAY;AAAA,IACd;AAAA,IACA,eAAe,EAAE;AAAA,IACjB,WAAW,EAAE;AAAA,EACf;AACF;AAKO,IAAM,kBAA2C,cAAc,IAAI,eAAe;AAOlF,SAAS,oBAAoB,SAAsC;AACxE,SAAO;AAAA,IACL,SAAS,GAAG,OAAO;AAAA,IACnB,KAAK;AAAA,IACL,QAAQ;AAAA,EACV;AACF;;;AC7fA,SAAS,cAAc,eAAe,YAAY,iBAAiB;AACnE,SAAS,YAAY;AACrB,SAAS,eAAe;AAGxB,IAAM,aAAa,KAAK,QAAQ,GAAG,aAAa,QAAQ;AACxD,IAAM,WAAW,KAAK,YAAY,SAAS;AAWpC,SAAS,cAAc,cAA6D;AAEzF,MAAI,cAAc,UAAU,OAAO,aAAa,WAAW,UAAU;AACnE,WAAO,EAAE,KAAK,aAAa,QAAQ,QAAQ,SAAS;AAAA,EACtD;AAGA,MAAI,WAAW,QAAQ,GAAG;AACxB,QAAI;AACF,YAAM,MAAM,aAAa,UAAU,OAAO,EAAE,KAAK;AACjD,UAAI,KAAK;AACP,eAAO,EAAE,KAAK,QAAQ,QAAQ;AAAA,MAChC;AAAA,IACF,QAAQ;AAAA,IAER;AAAA,EACF;AAGA,QAAM,SAAS,QAAQ,IAAI;AAC3B,MAAI,QAAQ;AACV,WAAO,EAAE,KAAK,QAAQ,QAAQ,MAAM;AAAA,EACtC;AAEA,SAAO;AACT;AAKO,SAAS,WAAW,KAAmB;AAC5C,MAAI,CAAC,WAAW,UAAU,GAAG;AAC3B,cAAU,YAAY,EAAE,WAAW,KAAK,CAAC;AAAA,EAC3C;AACA,gBAAc,UAAU,KAAK,EAAE,MAAM,IAAM,CAAC;AAC9C;AAKO,IAAM,mBAAuC;AAAA,EAClD,IAAI;AAAA,EACJ,OAAO;AAAA,EACP,MAAM;AAAA,EACN,MAAM;AAAA,EAEN,MAAM,IAAI,KAA0B;AAClC,QAAI,SAAS;AAAA,MACX;AAAA,IACF;AAEA,UAAM,MAAM,MAAM,IAAI,SAAS,KAAK;AAAA,MAClC,SAAS;AAAA,MACT,UAAU,CAAC,UAAkB;AAC3B,YAAI,CAAC,MAAM,KAAK,EAAG,QAAO;AAC1B,eAAO;AAAA,MACT;AAAA,IACF,CAAC;AAED,QAAI,OAAO,QAAQ,UAAU;AAC3B,aAAO,EAAE,UAAU,CAAC,EAAE;AAAA,IACxB;AAGA,eAAW,IAAI,KAAK,CAAC;AAErB,WAAO;AAAA,MACL,UAAU;AAAA,QACR;AAAA,UACE,WAAW;AAAA,UACX,YAAY,EAAE,QAAQ,IAAI,KAAK,EAAE;AAAA,QACnC;AAAA,MACF;AAAA,MACA,OAAO,CAAC,6CAA6C;AAAA,IACvD;AAAA,EACF;AACF;;;ACxFA,IAAI,cAAkC;AAK/B,SAAS,eAAe,OAA0B;AACvD,gBAAc;AAChB;AASO,IAAM,iBAAiC;AAAA,EAC5C,IAAI;AAAA,EACJ,OAAO;AAAA,EACP,UAAU;AAAA,EACV,SAAS,CAAC,OAAO,QAAQ;AAAA,EACzB,SAAS,CAAC,gBAAgB;AAAA;AAAA,EAG1B,IAAI,SAAS;AACX,QAAI,CAAC,aAAa;AAEhB,aAAO,oBAAoB,uBAAuB;AAAA,IACpD;AACA,WAAO,oBAAoB,YAAY,OAAO;AAAA,EAChD;AAAA;AAAA,EAGA,MAAM,CAAC,gBAAgB;AAAA;AAAA,EAGvB,aAAa,MAAM;AACjB,WAAO,KAAK;AAAA,EACd;AACF;;;ACnCA,SAAS,oBAA+D;;;ACHxE,SAAS,gBACP,iBACA,YACgB;AAChB,MAAI,kBAAkB,WAAW,QAAQ;AAEvC,WAAO,EAAE,MAAM,cAAc,OAAO,MAAM,QAAQ,UAAU,eAAe,WAAW;AAAA,EACxF;AACA,MAAI,kBAAkB,WAAW,SAAS;AACxC,WAAO,EAAE,MAAM,cAAc,OAAO,GAAK,QAAQ,SAAS,eAAe,WAAW;AAAA,EACtF;AACA,SAAO,EAAE,MAAM,cAAc,OAAO,GAAG,QAAQ,KAAK;AACtD;AAEA,SAAS,gCAAgC,MAAuB;AAC9D,QAAM,oBAAoB;AAAA,IACxB;AAAA,IACA;AAAA,IACA;AAAA,IACA;AAAA,IACA;AAAA,IACA;AAAA,IACA;AAAA,IACA;AAAA,IACA;AAAA,IACA;AAAA,IACA;AAAA,IACA;AAAA,IACA;AAAA,IACA;AAAA,IACA;AAAA,IACA;AAAA,IACA;AAAA,IACA;AAAA,IACA;AAAA,IACA;AAAA,EACF;AACA,QAAM,eAAe;AAAA,IACnB;AAAA,IACA;AAAA,IACA;AAAA,IACA;AAAA,IACA;AAAA,IACA;AAAA,IACA;AAAA,IACA;AAAA,IACA;AAAA,IACA;AAAA,IACA;AAAA,IACA;AAAA,IACA;AAAA,IACA;AAAA,IACA;AAAA,IACA;AAAA,IACA;AAAA,IACA;AAAA,IACA;AAAA,IACA;AAAA,IACA;AAAA,IACA;AAAA,IACA;AAAA,IACA;AAAA,IACA;AAAA,IACA;AAAA,IACA;AAAA,IACA;AAAA,IACA;AAAA,IACA;AAAA,IACA;AAAA,IACA;AAAA,IACA;AAAA,IACA;AAAA,IACA;AAAA,IACA;AAAA,IACA;AAAA,IACA;AAAA,IACA;AAAA,IACA;AAAA,IACA;AAAA,IACA;AAAA,IACA;AAAA,IACA;AAAA,IACA;AAAA,IACA;AAAA,IACA;AAAA,IACA;AAAA,IACA;AAAA,IACA;AAAA,IACA;AAAA,IACA;AAAA,IACA;AAAA,IACA;AAAA,IACA;AAAA,IACA;AAAA,IACA;AAAA,IACA;AAAA,EACF;AACA,QAAM,cAAc;AAAA,IAClB;AAAA,IACA;AAAA,IACA;AAAA,IACA;AAAA,IACA;AAAA,IACA;AAAA,IACA;AAAA,IACA;AAAA,IACA;AAAA,IACA;AAAA,IACA;AAAA,IACA;AAAA,IACA;AAAA,IACA;AAAA,IACA;AAAA,EACF;AAEA,QAAM,sBAAsB,kBAAkB,KAAK,CAAC,OAAO,KAAK,SAAS,EAAE,CAAC;AAC5E,QAAM,iBAAiB,aAAa,KAAK,CAAC,OAAO,KAAK,SAAS,EAAE,CAAC;AAClE,QAAM,gBAAgB,YAAY,KAAK,CAAC,OAAO,KAAK,SAAS,EAAE,CAAC;AAEhE,SAAO,wBAAwB,kBAAkB;AACnD;AAEA,SAAS,kBACP,MACA,UACA,MACA,aACA,YACA,QACgB;AAChB,QAAM,UAAU,SAAS,OAAO,CAAC,OAAO,KAAK,SAAS,GAAG,YAAY,CAAC,CAAC;AACvE,MAAI,QAAQ,UAAU,WAAW,MAAM;AACrC,WAAO;AAAA,MACL;AAAA,MACA,OAAO,OAAO;AAAA,MACd,QAAQ,GAAG,WAAW,KAAK,QAAQ,MAAM,GAAG,CAAC,EAAE,KAAK,IAAI,CAAC;AAAA,IAC3D;AAAA,EACF;AACA,MAAI,QAAQ,UAAU,WAAW,KAAK;AACpC,WAAO;AAAA,MACL;AAAA,MACA,OAAO,OAAO;AAAA,MACd,QAAQ,GAAG,WAAW,KAAK,QAAQ,MAAM,GAAG,CAAC,EAAE,KAAK,IAAI,CAAC;AAAA,IAC3D;AAAA,EACF;AACA,SAAO,EAAE,MAAM,OAAO,OAAO,MAAM,QAAQ,KAAK;AAClD;AAEA,SAAS,eAAe,MAA8B;AACpD,QAAM,WAAW,CAAC,gBAAgB,YAAY,QAAQ;AACtD,QAAM,OAAO,SAAS,OAAO,CAAC,MAAM,EAAE,KAAK,IAAI,CAAC;AAChD,MAAI,KAAK,SAAS,GAAG;AACnB,WAAO,EAAE,MAAM,qBAAqB,OAAO,KAAK,QAAQ,aAAa;AAAA,EACvE;AACA,SAAO,EAAE,MAAM,qBAAqB,OAAO,GAAG,QAAQ,KAAK;AAC7D;AAEA,SAAS,wBAAwB,QAAgC;AAC/D,QAAM,SAAS,OAAO,MAAM,KAAK,KAAK,CAAC,GAAG;AAC1C,MAAI,QAAQ,GAAG;AACb,WAAO,EAAE,MAAM,sBAAsB,OAAO,KAAK,QAAQ,GAAG,KAAK,aAAa;AAAA,EAChF;AACA,SAAO,EAAE,MAAM,sBAAsB,OAAO,GAAG,QAAQ,KAAK;AAC9D;AAIO,SAAS,gBACd,QACA,iBACA,QACe;AAEf,QAAM,OAAO,OAAO,YAAY;AAEhC,QAAM,WAAW,OAAO,YAAY;AAGpC,QAAM,aAA+B;AAAA;AAAA,IAEnC,gBAAgB,iBAAiB,OAAO,oBAAoB;AAAA,IAC5D;AAAA,MACE;AAAA,MACA,OAAO;AAAA,MACP;AAAA,MACA;AAAA,MACA,EAAE,KAAK,GAAG,MAAM,EAAE;AAAA,MAClB,EAAE,MAAM,GAAG,KAAK,KAAK,MAAM,EAAI;AAAA,IACjC;AAAA;AAAA,IAEA;AAAA,MACE;AAAA,MACA,OAAO;AAAA,MACP;AAAA,MACA;AAAA,MACA,EAAE,KAAK,GAAG,MAAM,EAAE;AAAA,MAClB,EAAE,MAAM,GAAG,KAAK,KAAK,MAAM,EAAI;AAAA,IACjC;AAAA,IACA;AAAA,MACE;AAAA,MACA,OAAO;AAAA,MACP;AAAA,MACA;AAAA,MACA,EAAE,KAAK,GAAG,MAAM,EAAE;AAAA,MAClB,EAAE,MAAM,GAAG,KAAK,KAAK,MAAM,EAAI;AAAA,IACjC;AAAA,IACA;AAAA,MACE;AAAA,MACA,OAAO;AAAA,MACP;AAAA,MACA;AAAA,MACA,EAAE,KAAK,GAAG,MAAM,EAAE;AAAA,MAClB,EAAE,MAAM,GAAG,KAAK,KAAK,MAAM,IAAI;AAAA,IACjC;AAAA,IACA;AAAA,MACE;AAAA,MACA,OAAO;AAAA,MACP;AAAA,MACA;AAAA,MACA,EAAE,KAAK,GAAG,MAAM,EAAE;AAAA,MAClB,EAAE,MAAM,GAAG,KAAK,IAAM,MAAM,GAAK;AAAA,IACnC;AAAA,IACA,eAAe,IAAI;AAAA,IACnB,wBAAwB,MAAM;AAAA;AAAA,IAG9B;AAAA,MACE;AAAA,MACA,OAAO;AAAA,MACP;AAAA,MACA;AAAA,MACA,EAAE,KAAK,GAAG,MAAM,EAAE;AAAA,MAClB,EAAE,MAAM,GAAG,KAAK,KAAK,MAAM,IAAI;AAAA,IACjC;AAAA,IACA;AAAA,MACE;AAAA,MACA,OAAO;AAAA,MACP;AAAA,MACA;AAAA,MACA,EAAE,KAAK,GAAG,MAAM,EAAE;AAAA,MAClB,EAAE,MAAM,GAAG,KAAK,KAAK,MAAM,IAAI;AAAA,IACjC;AAAA,IACA;AAAA,MACE;AAAA,MACA,OAAO;AAAA,MACP;AAAA,MACA;AAAA,MACA,EAAE,KAAK,GAAG,MAAM,EAAE;AAAA,MAClB,EAAE,MAAM,GAAG,KAAK,KAAK,MAAM,IAAI;AAAA,IACjC;AAAA,IACA;AAAA,MACE;AAAA,MACA,OAAO;AAAA,MACP;AAAA,MACA;AAAA,MACA,EAAE,KAAK,GAAG,MAAM,EAAE;AAAA,MAClB,EAAE,MAAM,GAAG,KAAK,KAAK,MAAM,IAAI;AAAA,IACjC;AAAA,IACA;AAAA,MACE;AAAA,MACA,OAAO;AAAA,MACP;AAAA,MACA;AAAA,MACA,EAAE,KAAK,GAAG,MAAM,EAAE;AAAA,MAClB,EAAE,MAAM,GAAG,KAAK,KAAK,MAAM,IAAI;AAAA,IACjC;AAAA,IACA;AAAA,MACE;AAAA,MACA,OAAO;AAAA,MACP;AAAA,MACA;AAAA,MACA,EAAE,KAAK,GAAG,MAAM,EAAE;AAAA,MAClB,EAAE,MAAM,GAAG,KAAK,KAAK,MAAM,IAAI;AAAA,IACjC;AAAA,EACF;AAGA,QAAM,UAAU,WAAW,OAAO,CAAC,MAAM,EAAE,WAAW,IAAI,EAAE,IAAI,CAAC,MAAM,EAAE,MAAO;AAGhF,QAAM,UAAU,OAAO;AACvB,MAAI,gBAAgB;AACpB,aAAW,KAAK,YAAY;AAC1B,UAAM,IAAI,QAAQ,EAAE,IAAI,KAAK;AAC7B,qBAAiB,EAAE,QAAQ;AAAA,EAC7B;AAIA,QAAM,mBAAmB,OAAO,kBAAkB;AAAA,IAAO,CAAC,OACxD,SAAS,SAAS,GAAG,YAAY,CAAC;AAAA,EACpC;AAGA,MAAI,iBAAiB,UAAU,GAAG;AAChC,UAAMA,cAAa;AAAA,MACjB,KAAK,IAAI,eAAe,GAAG;AAAA;AAAA,MAC3B,OAAO;AAAA,IACT;AACA,WAAO;AAAA,MACL,OAAO;AAAA,MACP,MAAM;AAAA,MACN,YAAY,KAAK,IAAIA,aAAY,IAAI;AAAA,MACrC;AAAA,IACF;AAAA,EACF;AAIA,MAAI,gCAAgC,QAAQ,GAAG;AAC7C,WAAO;AAAA,MACL,OAAO,KAAK,IAAI,eAAe,OAAO,eAAe,gBAAgB,IAAI;AAAA,MACzE,MAAM;AAAA,MACN,YAAY;AAAA,MACZ,SAAS,CAAC,GAAG,SAAS,qBAAqB;AAAA,IAC7C;AAAA,EACF;AAGA,QAAM,EAAE,cAAc,eAAe,iBAAiB,IAAI,OAAO;AACjE,MAAI;AACJ,MAAI;AAEJ,MAAI,gBAAgB,cAAc;AAChC,WAAO;AACP,2BAAuB,eAAe;AAAA,EACxC,WAAW,gBAAgB,eAAe;AACxC,WAAO;AACP,2BAAuB,KAAK,IAAI,gBAAgB,cAAc,gBAAgB,aAAa;AAAA,EAC7F,WAAW,gBAAgB,kBAAkB;AAC3C,WAAO;AACP,2BAAuB,KAAK;AAAA,MAC1B,gBAAgB;AAAA,MAChB,mBAAmB;AAAA,IACrB;AAAA,EACF,OAAO;AACL,WAAO;AACP,2BAAuB,gBAAgB;AAAA,EACzC;AAGA,QAAM,aAAa,oBAAoB,sBAAsB,OAAO,mBAAmB;AAGvF,MAAI,aAAa,OAAO,qBAAqB;AAC3C,WAAO,EAAE,OAAO,eAAe,MAAM,MAAM,YAAY,QAAQ;AAAA,EACjE;AAEA,SAAO,EAAE,OAAO,eAAe,MAAM,YAAY,QAAQ;AAC3D;AAMA,SAAS,oBAAoB,UAAkB,WAA2B;AACxE,SAAO,KAAK,IAAI,KAAK,IAAI,CAAC,YAAY,QAAQ;AAChD;;;ACrWO,SAAS,YACd,MACA,YACA,QACA,WACA,aACA,cACA,sBACA,iBACiB;AACjB,QAAM,aAAa,YAAY,IAAI;AACnC,QAAM,QAAQ,WAAW;AACzB,QAAM,UAAU,aAAa,IAAI,KAAK;AAEtC,QAAM,YAAY,UAAW,uBAAuB,MAAa,QAAQ,aAAa;AACtF,QAAM,aAAa,UAAW,kBAAkB,MAAa,QAAQ,cAAc;AACnF,QAAM,eAAe,YAAY;AAGjC,QAAM,cAAc,aAAa,IAAI,2BAA2B;AAChE,QAAM,gBAAgB,cACjB,uBAAuB,MAAa,YAAY,aACjD;AACJ,QAAM,iBAAiB,cAAe,kBAAkB,MAAa,YAAY,cAAc;AAC/F,QAAM,eAAe,gBAAgB;AAErC,QAAM,UAAU,eAAe,IAAI,KAAK,IAAI,IAAI,eAAe,gBAAgB,YAAY,IAAI;AAE/F,SAAO;AAAA,IACL;AAAA,IACA;AAAA,IACA;AAAA,IACA;AAAA,IACA;AAAA,IACA;AAAA,IACA;AAAA,IACA;AAAA,EACF;AACF;;;AC3CO,IAAM,yBAAwC;AAAA,EACnD,SAAS;AAAA,EAET,YAAY;AAAA,IACV,UAAU;AAAA,IACV,cAAc;AAAA,IACd,gBAAgB;AAAA,IAChB,uBAAuB;AAAA,IACvB,YAAY;AAAA;AAAA,EACd;AAAA,EAEA,SAAS;AAAA,IACP,sBAAsB,EAAE,QAAQ,IAAI,SAAS,IAAI;AAAA;AAAA,IAGjD,cAAc;AAAA;AAAA,MAEZ;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;AAAA,MAEA;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,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,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,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,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,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,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,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,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,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,IACF;AAAA;AAAA,IAGA,kBAAkB;AAAA,MAChB,YAAY;AAAA,MACZ,cAAc;AAAA,MACd,kBAAkB;AAAA,MAClB,gBAAgB;AAAA,MAChB,iBAAiB;AAAA,MACjB,kBAAkB;AAAA,MAClB,mBAAmB;AAAA,MACnB,oBAAoB;AAAA,MACpB,iBAAiB;AAAA,MACjB,iBAAiB;AAAA,MACjB,cAAc;AAAA,MACd,qBAAqB;AAAA,MACrB,oBAAoB;AAAA,MACpB,mBAAmB;AAAA,IACrB;AAAA;AAAA,IAGA,gBAAgB;AAAA,MACd,cAAc;AAAA,MACd,eAAe;AAAA,MACf,kBAAkB;AAAA,IACpB;AAAA;AAAA,IAGA,qBAAqB;AAAA;AAAA,IAErB,qBAAqB;AAAA,EACvB;AAAA,EAEA,OAAO;AAAA,IACL,QAAQ;AAAA,MACN,SAAS;AAAA,IACX;AAAA,IACA,QAAQ;AAAA,MACN,SAAS;AAAA,IACX;AAAA,IACA,SAAS;AAAA,MACP,SAAS;AAAA,IACX;AAAA,IACA,WAAW;AAAA,MACT,SAAS;AAAA,IACX;AAAA,EACF;AAAA,EAEA,WAAW;AAAA,IACT,uBAAuB;AAAA,IACvB,yBAAyB;AAAA,IACzB,sBAAsB;AAAA,EACxB;AACF;;;ACzaO,SAAS,MACd,QACA,cACA,iBACA,SACA,SACiB;AACjB,QAAM,EAAE,QAAQ,aAAa,IAAI;AAIjC,QAAM,sBAAsB,KAAK,KAAK,OAAO,SAAS,CAAC;AACvD,QAAM,0BAA0B,KAAK,KAAK,GAAG,gBAAgB,EAAE,IAAI,MAAM,GAAG,SAAS,CAAC;AACtF,QAAM,kBAAkB,SAAS,wBAAwB;AAGzD,MAAI,SAAS,YAAY;AACvB,WAAO;AAAA,MACL,QAAQ;AAAA,MACR;AAAA,MACA;AAAA,MACA,yBAAyB,QAAQ,UAAU;AAAA,MAC3C,OAAO;AAAA,MACP;AAAA,MACA;AAAA,MACA;AAAA,IACF;AAAA,EACF;AAGA,MAAI,kBAAkB,OAAO,UAAU,uBAAuB;AAC5D,WAAO;AAAA,MACL;AAAA,MACA;AAAA,MACA;AAAA,MACA,iBAAiB,OAAO,UAAU,qBAAqB;AAAA,MACvD,OAAO;AAAA,MACP;AAAA,MACA;AAAA,MACA;AAAA,IACF;AAAA,EACF;AAIA,QAAM,sBACJ,SAAS,4BAA4B,6CAA6C,KAAK,MAAM;AAG/F,QAAM,aAAa,gBAAgB,QAAQ,qBAAqB,OAAO,OAAO;AAE9E,MAAI;AACJ,MAAI;AACJ,QAAM,SAA0B;AAChC,MAAI,YAAY,SAAS,WAAW,KAAK,MAAM,WAAW,QAAQ,KAAK,IAAI,CAAC;AAE5E,MAAI,WAAW,SAAS,MAAM;AAC5B,WAAO,WAAW;AAClB,iBAAa,WAAW;AAAA,EAC1B,OAAO;AAEL,WAAO,OAAO,UAAU;AACxB,iBAAa;AACb,iBAAa,4BAA4B,IAAI;AAAA,EAC/C;AAGA,MAAI,qBAAqB;AACvB,UAAM,WAAiC,EAAE,QAAQ,GAAG,QAAQ,GAAG,SAAS,GAAG,WAAW,EAAE;AACxF,UAAM,UAAU,OAAO,UAAU;AACjC,QAAI,SAAS,IAAI,IAAI,SAAS,OAAO,GAAG;AACtC,mBAAa,kBAAkB,OAAO;AACtC,aAAO;AAAA,IACT;AAAA,EACF;AAEA,SAAO;AAAA,IACL;AAAA,IACA;AAAA,IACA;AAAA,IACA;AAAA,IACA,OAAO;AAAA,IACP;AAAA,IACA;AAAA,IACA;AAAA,EACF;AACF;;;ACtHA,IAAM,kBAAkB;AACxB,IAAM,uBAAuB,KAAK,KAAK;AAiCvC,IAAI,QAA2B;AAM/B,SAAS,aAAa,SAAkC;AACtD,MAAI,CAAC,WAAW,QAAQ,WAAW,EAAG,QAAO;AAE7C,QAAM,OAAO,QAAQ,KAAK,CAAC,MAAM,EAAE,SAAS,YAAY;AACxD,MAAI,KAAM,QAAO,KAAK;AAEtB,SAAO,QAAQ,CAAC,EAAE;AACpB;AAKA,SAAS,cAAc,KAA4B;AACjD,QAAM,YACJ,IAAI,kBAAkB,SAAS,OAAO,KAAK,IAAI,kBAAkB,SAAS,OAAO;AAEnF,SAAO;AAAA,IACL,IAAI,IAAI;AAAA,IACR,MAAM,IAAI,gBAAgB,IAAI;AAAA,IAC9B,YAAY,aAAa,IAAI,UAAU,MAAM;AAAA,IAC7C,aAAa,aAAa,IAAI,UAAU,UAAU;AAAA,IAClD,eAAe,IAAI,kBAAkB;AAAA,IACrC,WAAW;AAAA;AAAA,IACX,WAAW,IAAI,cAAc,aAAa;AAAA,IAC1C,QAAQ,aAAa;AAAA,EACvB;AACF;AASA,eAAsB,YACpB,QACA,aAAa,sBACW;AAExB,MAAI,SAAS,KAAK,IAAI,IAAI,MAAM,YAAY,YAAY;AACtD,WAAO,MAAM;AAAA,EACf;AAEA,MAAI;AACF,UAAM,WAAW,MAAM,MAAM,iBAAiB;AAAA,MAC5C,SAAS;AAAA,QACP,eAAe,UAAU,MAAM;AAAA,QAC/B,cAAc;AAAA,MAChB;AAAA,MACA,QAAQ,YAAY,QAAQ,GAAM;AAAA;AAAA,IACpC,CAAC;AAED,QAAI,CAAC,SAAS,IAAI;AAChB,YAAM,IAAI,MAAM,gBAAgB,SAAS,MAAM,EAAE;AAAA,IACnD;AAEA,UAAM,OAAQ,MAAM,SAAS,KAAK;AAClC,QAAI,CAAC,KAAK,QAAQ,CAAC,MAAM,QAAQ,KAAK,IAAI,GAAG;AAC3C,YAAM,IAAI,MAAM,6BAA6B;AAAA,IAC/C;AAEA,UAAM,SAAS,KAAK,KAAK,IAAI,aAAa;AAG1C,WAAO,QAAQ;AAAA,MACb,IAAI;AAAA,MACJ,MAAM;AAAA,MACN,YAAY;AAAA,MACZ,aAAa;AAAA,MACb,eAAe;AAAA,MACf,WAAW;AAAA,IACb,CAAC;AAED,YAAQ,EAAE,QAAQ,WAAW,KAAK,IAAI,EAAE;AACxC,WAAO;AAAA,EACT,QAAQ;AAEN,WAAO;AAAA,EACT;AACF;AAKO,SAAS,uBAA6B;AAC3C,UAAQ;AACV;;;AChIA,SAAS,YAAY,aAAa;AAClC,SAAS,QAAAC,aAAY;AACrB,SAAS,WAAAC,gBAAe;AASxB,IAAM,UAAUD,MAAKC,SAAQ,GAAG,aAAa,UAAU,MAAM;AAC7D,IAAI,WAAW;AAEf,eAAe,YAA2B;AACxC,MAAI,SAAU;AACd,QAAM,MAAM,SAAS,EAAE,WAAW,KAAK,CAAC;AACxC,aAAW;AACb;AAKA,eAAsB,SAAS,OAAkC;AAC/D,MAAI;AACF,UAAM,UAAU;AAChB,UAAM,OAAO,MAAM,UAAU,MAAM,GAAG,EAAE;AACxC,UAAM,OAAOD,MAAK,SAAS,SAAS,IAAI,QAAQ;AAChD,UAAM,WAAW,MAAM,KAAK,UAAU,KAAK,IAAI,IAAI;AAAA,EACrD,QAAQ;AAAA,EAER;AACF;;;AClCA,SAAS,kBAAkB;AAc3B,IAAM,iBAAiB;AACvB,IAAM,gBAAgB;AAEf,IAAM,sBAAN,MAA0B;AAAA,EACvB,WAAW,oBAAI,IAA2B;AAAA,EAC1C,YAAY,oBAAI,IAA4B;AAAA,EAC5C;AAAA,EAER,YAAY,QAAQ,gBAAgB;AAClC,SAAK,QAAQ;AAAA,EACf;AAAA;AAAA,EAGA,OAAO,KAAK,MAAsB;AAChC,WAAO,WAAW,QAAQ,EAAE,OAAO,IAAI,EAAE,OAAO,KAAK,EAAE,MAAM,GAAG,EAAE;AAAA,EACpE;AAAA;AAAA,EAGA,UAAU,KAAyC;AACjD,UAAM,QAAQ,KAAK,UAAU,IAAI,GAAG;AACpC,QAAI,CAAC,MAAO,QAAO;AACnB,QAAI,KAAK,IAAI,IAAI,MAAM,cAAc,KAAK,OAAO;AAC/C,WAAK,UAAU,OAAO,GAAG;AACzB,aAAO;AAAA,IACT;AACA,WAAO;AAAA,EACT;AAAA;AAAA,EAGA,YAAY,KAAkD;AAC5D,UAAM,QAAQ,KAAK,SAAS,IAAI,GAAG;AACnC,QAAI,CAAC,MAAO,QAAO;AACnB,UAAM,UAAU,IAAI,QAAwB,CAAC,YAAY;AACvD,YAAM,QAAQ;AAAA,QACZ,IAAI,QAAwB,CAAC,MAAM;AACjC,gBAAM,OAAO,MAAM;AACnB,gBAAM,UAAU,CAAC,WAAW;AAC1B,iBAAK,MAAM;AACX,oBAAQ,MAAM;AACd,cAAE,MAAM;AAAA,UACV;AAAA,QACF,CAAC;AAAA,MACH;AAAA,IACF,CAAC;AACD,WAAO;AAAA,EACT;AAAA;AAAA,EAGA,aAAa,KAAmB;AAC9B,SAAK,SAAS,IAAI,KAAK;AAAA,MACrB,SAAS,MAAM;AAAA,MAAC;AAAA,MAChB,SAAS,CAAC;AAAA,IACZ,CAAC;AAAA,EACH;AAAA;AAAA,EAGA,SAAS,KAAa,QAA8B;AAElD,QAAI,OAAO,KAAK,UAAU,eAAe;AACvC,WAAK,UAAU,IAAI,KAAK,MAAM;AAAA,IAChC;AAEA,UAAM,QAAQ,KAAK,SAAS,IAAI,GAAG;AACnC,QAAI,OAAO;AACT,YAAM,QAAQ,MAAM;AACpB,WAAK,SAAS,OAAO,GAAG;AAAA,IAC1B;AAEA,SAAK,MAAM;AAAA,EACb;AAAA;AAAA,EAGA,eAAe,KAAmB;AAChC,SAAK,SAAS,OAAO,GAAG;AAAA,EAC1B;AAAA;AAAA,EAGQ,QAAc;AACpB,UAAM,MAAM,KAAK,IAAI;AACrB,eAAW,CAAC,KAAK,KAAK,KAAK,KAAK,WAAW;AACzC,UAAI,MAAM,MAAM,cAAc,KAAK,OAAO;AACxC,aAAK,UAAU,OAAO,GAAG;AAAA,MAC3B;AAAA,IACF;AAAA,EACF;AACF;;;ACxFO,IAAM,uBAAoC;AAAA,EAC/C,YAAY;AAAA,EACZ,aAAa;AAAA,EACb,gBAAgB,CAAC,KAAK,KAAK,KAAK,GAAG;AACrC;AAGA,SAAS,MAAM,IAA2B;AACxC,SAAO,IAAI,QAAQ,CAAC,YAAY,WAAW,SAAS,EAAE,CAAC;AACzD;AAKA,eAAsB,eACpB,SACA,KACA,MACA,QACmB;AACnB,QAAM,MAAmB;AAAA,IACvB,GAAG;AAAA,IACH,GAAG;AAAA,EACL;AAEA,MAAI;AACJ,MAAI;AAEJ,WAAS,UAAU,GAAG,WAAW,IAAI,YAAY,WAAW;AAC1D,QAAI;AACF,YAAM,WAAW,MAAM,QAAQ,KAAK,IAAI;AAGxC,UAAI,CAAC,IAAI,eAAe,SAAS,SAAS,MAAM,GAAG;AACjD,eAAO;AAAA,MACT;AAGA,qBAAe;AAGf,YAAM,aAAa,SAAS,QAAQ,IAAI,aAAa;AACrD,UAAI;AAEJ,UAAI,YAAY;AACd,cAAM,UAAU,SAAS,YAAY,EAAE;AACvC,gBAAQ,MAAM,OAAO,IAAI,IAAI,cAAc,KAAK,IAAI,GAAG,OAAO,IAAI,UAAU;AAAA,MAC9E,OAAO;AACL,gBAAQ,IAAI,cAAc,KAAK,IAAI,GAAG,OAAO;AAAA,MAC/C;AAGA,UAAI,UAAU,IAAI,YAAY;AAC5B,cAAM,MAAM,KAAK;AAAA,MACnB;AAAA,IACF,SAAS,KAAK;AACZ,kBAAY,eAAe,QAAQ,MAAM,IAAI,MAAM,OAAO,GAAG,CAAC;AAG9D,UAAI,UAAU,IAAI,YAAY;AAC5B,cAAM,QAAQ,IAAI,cAAc,KAAK,IAAI,GAAG,OAAO;AACnD,cAAM,MAAM,KAAK;AAAA,MACnB;AAAA,IACF;AAAA,EACF;AAGA,MAAI,cAAc;AAChB,WAAO;AAAA,EACT;AAEA,QAAM,aAAa,IAAI,MAAM,sBAAsB;AACrD;AAKO,SAAS,YACd,iBACA,QACS;AACT,QAAM,iBAAiB,QAAQ,kBAAkB,qBAAqB;AAEtE,MAAI,2BAA2B,UAAU;AACvC,WAAO,eAAe,SAAS,gBAAgB,MAAM;AAAA,EACvD;AAGA,QAAM,UAAU,gBAAgB,QAAQ,YAAY;AACpD,SACE,QAAQ,SAAS,SAAS,KAC1B,QAAQ,SAAS,SAAS,KAC1B,QAAQ,SAAS,YAAY,KAC7B,QAAQ,SAAS,cAAc,KAC/B,QAAQ,SAAS,gBAAgB;AAErC;;;AR5EA,IAAM,aAAa;AACnB,IAAM,aAAa;AACnB,IAAM,mBAAmB;AACzB,IAAM,aAAa;AACnB,IAAM,wBAAwB;AAC9B,IAAM,6BAA6B;AACnC,IAAM,eAAe;AACrB,IAAM,sBAAsB;AAC5B,IAAM,6BAA6B;AAKnC,SAAS,YAAY,SAAqD;AACxE,MAAI,OAAO,YAAY,SAAU,QAAO;AACxC,MAAI,MAAM,QAAQ,OAAO,GAAG;AAC1B,WAAO,QACJ,OAAO,CAAC,MAAM,EAAE,SAAS,UAAU,OAAO,EAAE,SAAS,QAAQ,EAC7D,IAAI,CAAC,MAAM,EAAE,IAAK,EAClB,KAAK,IAAI;AAAA,EACd;AACA,SAAO;AACT;AAEA,SAAS,gBAAgB,MAAgC;AACvD,QAAM,QAAQ,KAAK,MAAM,mBAAmB;AAC5C,MAAI,CAAC,MAAO,QAAO;AACnB,SAAO,MAAM,CAAC,EAAE,YAAY;AAC9B;AAEA,SAAS,yBAAyB,MAAsB;AACtD,SAAO,KAAK,QAAQ,4BAA4B,EAAE,EAAE,QAAQ,cAAc,GAAG,EAAE,KAAK;AACtF;AAEA,SAAS,0BAA0B,SAAoD;AACrF,MAAI,CAAC,WAAW,QAAQ,YAAY,OAAW,QAAO;AAEtD,MAAI,OAAO,QAAQ,YAAY,UAAU;AACvC,UAAM,aAAa,gBAAgB,QAAQ,OAAO;AAClD,QAAI,YAAY;AACd,cAAQ,UAAU,yBAAyB,QAAQ,OAAO;AAAA,IAC5D;AACA,WAAO;AAAA,EACT;AAEA,MAAI,MAAM,QAAQ,QAAQ,OAAO,GAAG;AAClC,QAAI;AACJ,YAAQ,UAAU,QAAQ,QAAQ,IAAI,CAAC,SAAS;AAC9C,UAAI,KAAK,SAAS,UAAU,OAAO,KAAK,SAAS,SAAU,QAAO;AAElE,YAAM,iBAAiB,gBAAgB,KAAK,IAAI;AAChD,UAAI,CAAC,cAAc,gBAAgB;AACjC,qBAAa;AAAA,MACf;AACA,UAAI,CAAC,eAAgB,QAAO;AAE5B,aAAO;AAAA,QACL,GAAG;AAAA,QACH,MAAM,yBAAyB,KAAK,IAAI;AAAA,MAC1C;AAAA,IACF,CAAC;AACD,WAAO;AAAA,EACT;AAEA,SAAO;AACT;AAyBA,SAAS,kBAAkB,QAAkD;AAC3E,QAAM,MAAM,oBAAI,IAA0B;AAC1C,aAAW,KAAK,QAAQ;AACtB,QAAI,EAAE,OAAO,WAAY;AACzB,QAAI,IAAI,EAAE,IAAI,EAAE,YAAY,EAAE,YAAY,aAAa,EAAE,YAAY,CAAC;AAAA,EACxE;AACA,SAAO;AACT;AAKA,SAAS,mBAAmB,WAAmD;AAC7E,MAAI,CAAC,UAAW,QAAO;AACvB,SAAO;AAAA,IACL,GAAG;AAAA,IACH,GAAG;AAAA,IACH,YAAY,EAAE,GAAG,uBAAuB,YAAY,GAAG,UAAU,WAAW;AAAA,IAC5E,SAAS,EAAE,GAAG,uBAAuB,SAAS,GAAG,UAAU,QAAQ;AAAA,IACnE,OAAO,EAAE,GAAG,uBAAuB,OAAO,GAAG,UAAU,MAAM;AAAA,IAC7D,WAAW,EAAE,GAAG,uBAAuB,WAAW,GAAG,UAAU,UAAU;AAAA,EAC3E;AACF;AAOA,eAAsB,WAAW,SAA6C;AAC5E,QAAM,UAAU,QAAQ,WAAW;AACnC,QAAM,SAAS,QAAQ;AAGvB,QAAM,gBAAgB,mBAAmB,QAAQ,aAAa;AAG9D,MAAI;AACJ,MAAI;AACF,aAAS,MAAM,YAAY,MAAM;AACjC,YAAQ,iBAAiB,OAAO,MAAM;AAAA,EACxC,QAAQ;AACN,aAAS;AAAA,EACX;AAEA,QAAM,eAAe,kBAAkB,MAAM;AAE7C,QAAM,aAA4B;AAAA,IAChC,QAAQ;AAAA,IACR;AAAA,EACF;AAGA,QAAM,eAAe,IAAI,oBAAoB;AAE7C,QAAM,SAAS,aAAa,OAAO,KAAsB,QAAwB;AAE/E,QAAI,IAAI,QAAQ,aAAa,IAAI,KAAK,WAAW,UAAU,GAAG;AAC5D,UAAI,UAAU,KAAK,EAAE,gBAAgB,mBAAmB,CAAC;AACzD,UAAI;AAAA,QACF,KAAK,UAAU;AAAA,UACb,QAAQ;AAAA,UACR,UAAU;AAAA,UACV,QAAQ,OAAO;AAAA,QACjB,CAAC;AAAA,MACH;AACA;AAAA,IACF;AAGA,QAAI,CAAC,IAAI,KAAK,WAAW,KAAK,GAAG;AAC/B,UAAI,UAAU,KAAK,EAAE,gBAAgB,mBAAmB,CAAC;AACzD,UAAI,IAAI,KAAK,UAAU,EAAE,OAAO,YAAY,CAAC,CAAC;AAC9C;AAAA,IACF;AAEA,QAAI;AACF,YAAM,aAAa,KAAK,KAAK,SAAS,QAAQ,SAAS,YAAY,YAAY;AAAA,IACjF,SAAS,KAAK;AACZ,YAAM,QAAQ,eAAe,QAAQ,MAAM,IAAI,MAAM,OAAO,GAAG,CAAC;AAChE,cAAQ,UAAU,KAAK;AAEvB,UAAI,CAAC,IAAI,aAAa;AACpB,YAAI,UAAU,KAAK,EAAE,gBAAgB,mBAAmB,CAAC;AACzD,YAAI;AAAA,UACF,KAAK,UAAU;AAAA,YACb,OAAO,EAAE,SAAS,gBAAgB,MAAM,OAAO,IAAI,MAAM,cAAc;AAAA,UACzE,CAAC;AAAA,QACH;AAAA,MACF,WAAW,CAAC,IAAI,eAAe;AAC7B,YAAI;AAAA,UACF,SAAS,KAAK,UAAU,EAAE,OAAO,EAAE,SAAS,MAAM,SAAS,MAAM,cAAc,EAAE,CAAC,CAAC;AAAA;AAAA;AAAA,QACrF;AACA,YAAI,MAAM,kBAAkB;AAC5B,YAAI,IAAI;AAAA,MACV;AAAA,IACF;AAAA,EACF,CAAC;AAGD,QAAM,aAAa,QAAQ,QAAQ;AAEnC,SAAO,IAAI,QAAqB,CAAC,SAAS,WAAW;AACnD,WAAO,GAAG,SAAS,MAAM;AAEzB,WAAO,OAAO,YAAY,aAAa,MAAM;AAC3C,YAAM,OAAO,OAAO,QAAQ;AAC5B,YAAM,OAAO,KAAK;AAClB,YAAM,UAAU,oBAAoB,IAAI;AAExC,cAAQ,UAAU,IAAI;AAEtB,cAAQ;AAAA,QACN;AAAA,QACA;AAAA,QACA,OAAO,MACL,IAAI,QAAc,CAAC,KAAK,QAAQ;AAC9B,iBAAO,MAAM,CAAC,QAAS,MAAM,IAAI,GAAG,IAAI,IAAI,CAAE;AAAA,QAChD,CAAC;AAAA,MACL,CAAC;AAAA,IACH,CAAC;AAAA,EACH,CAAC;AACH;AAKA,eAAe,aACb,KACA,KACA,SACA,QACA,SACA,YACA,cACe;AACf,QAAM,YAAY,KAAK,IAAI;AAG3B,QAAM,cAAc,GAAG,OAAO,GAAG,IAAI,GAAG;AAGxC,QAAM,aAAuB,CAAC;AAC9B,mBAAiB,SAAS,KAAK;AAC7B,eAAW,KAAK,OAAO,SAAS,KAAK,IAAI,QAAQ,OAAO,KAAK,KAAK,CAAC;AAAA,EACrE;AACA,MAAI,OAAO,OAAO,OAAO,UAAU;AAGnC,MAAI;AACJ,MAAI,cAAc;AAClB,MAAI,UAAU;AACd,QAAM,mBAAmB,IAAI,KAAK,SAAS,mBAAmB;AAE9D,MAAI,oBAAoB,KAAK,SAAS,GAAG;AACvC,QAAI;AACF,YAAM,SAAS,KAAK,MAAM,KAAK,SAAS,CAAC;AACzC,oBAAc,OAAO,WAAW;AAChC,gBAAW,OAAO,SAAoB;AACtC,YAAM,YACJ,OAAO,OAAO,0BAA0B,WACpC,OAAO,wBACP,OAAO,OAAO,eAAe,WAC3B,OAAO,aACP;AAER,UAAI,OAAO,UAAU,cAAc,OAAO,UAAU,kBAAkB;AAEpE,cAAM,WAAW,MAAM,QAAQ,OAAO,QAAQ,IACzC,OAAO,WACR;AAEJ,YAAI;AACJ,YAAI,UAAU;AACZ,mBAAS,IAAI,SAAS,SAAS,GAAG,KAAK,GAAG,KAAK;AAC7C,gBAAI,SAAS,CAAC,EAAE,SAAS,QAAQ;AAC/B,4BAAc,SAAS,CAAC;AACxB;AAAA,YACF;AAAA,UACF;AAAA,QACF;AACA,cAAM,YAAY,UAAU,KAAK,CAAC,MAAmB,EAAE,SAAS,QAAQ;AACxE,cAAM,aAAa,0BAA0B,WAAW;AACxD,cAAM,SAAS,YAAY,aAAa,OAAO;AAC/C,cAAM,eAAe,YAAY,WAAW,OAAO,KAAK;AACxD,cAAM,iBACJ,UACI,IAAI,CAAC,MAAM,YAAY,EAAE,OAAO,CAAC,EAClC,OAAO,CAAC,MAAM,EAAE,SAAS,CAAC,EAC1B,KAAK,IAAI,KAAK;AACnB,cAAM,uBACJ,eAAe,SAAS,IAAI,KAAK,KAAK,eAAe,SAAS,CAAC,IAAI;AACrE,cAAM,2BACJ,OAAO,OAAO,oBAAoB,YAAY,OAAO,oBAAoB;AAE3E,0BAAkB,MAAM,QAAQ,cAAc,WAAW,YAAY;AAAA,UACnE;AAAA,UACA;AAAA,UACA;AAAA,QACF,CAAC;AAGD,eAAO,QAAQ,gBAAgB;AAC/B,kBAAU,gBAAgB;AAC1B,eAAO,OAAO,KAAK,KAAK,UAAU,MAAM,CAAC;AAEzC,gBAAQ,WAAW,eAAe;AAAA,MACpC;AAAA,IACF,QAAQ;AAAA,IAER;AAAA,EACF;AAGA,QAAM,WAAW,oBAAoB,KAAK,IAAI;AAE9C,QAAM,SAAS,aAAa,UAAU,QAAQ;AAC9C,MAAI,QAAQ;AACV,QAAI,UAAU,OAAO,QAAQ,OAAO,OAAO;AAC3C,QAAI,IAAI,OAAO,IAAI;AACnB;AAAA,EACF;AAEA,QAAM,WAAW,aAAa,YAAY,QAAQ;AAClD,MAAI,UAAU;AACZ,UAAM,SAAS,MAAM;AACrB,QAAI,UAAU,OAAO,QAAQ,OAAO,OAAO;AAC3C,QAAI,IAAI,OAAO,IAAI;AACnB;AAAA,EACF;AAEA,eAAa,aAAa,QAAQ;AAGlC,MAAI;AACJ,MAAI,mBAAmB;AAEvB,MAAI,aAAa;AACf,QAAI,UAAU,KAAK;AAAA,MACjB,gBAAgB;AAAA,MAChB,iBAAiB;AAAA,MACjB,YAAY;AAAA,IACd,CAAC;AACD,uBAAmB;AAEnB,QAAI,MAAM,iBAAiB;AAE3B,wBAAoB,YAAY,MAAM;AACpC,UAAI,CAAC,IAAI,eAAe;AACtB,YAAI,MAAM,iBAAiB;AAAA,MAC7B;AAAA,IACF,GAAG,qBAAqB;AAAA,EAC1B;AAGA,QAAM,UAAkC,CAAC;AACzC,aAAW,CAAC,KAAK,KAAK,KAAK,OAAO,QAAQ,IAAI,OAAO,GAAG;AACtD,QACE,QAAQ,UACR,QAAQ,gBACR,QAAQ,uBACR,QAAQ;AAER;AACF,QAAI,OAAO,UAAU,UAAU;AAC7B,cAAQ,GAAG,IAAI;AAAA,IACjB;AAAA,EACF;AACA,MAAI,CAAC,QAAQ,cAAc,GAAG;AAC5B,YAAQ,cAAc,IAAI;AAAA,EAC5B;AACA,UAAQ,YAAY,IAAI;AACxB,UAAQ,eAAe,IAAI,UAAU,MAAM;AAG3C,MAAI,YAAY;AAChB,MAAI,GAAG,SAAS,MAAM;AACpB,QAAI,mBAAmB;AACrB,oBAAc,iBAAiB;AAC/B,0BAAoB;AAAA,IACtB;AACA,QAAI,CAAC,WAAW;AACd,mBAAa,eAAe,QAAQ;AAAA,IACtC;AAAA,EACF,CAAC;AAGD,QAAM,YAAY,QAAQ,oBAAoB;AAC9C,QAAM,aAAa,IAAI,gBAAgB;AACvC,QAAM,YAAY,WAAW,MAAM,WAAW,MAAM,GAAG,SAAS;AAEhE,MAAI;AACF,UAAM,WAAW,MAAM;AAAA,MACrB,CAAC,KAAK,SAAS,MAAM,KAAK,IAAI;AAAA,MAC9B;AAAA,MACA;AAAA,QACE,QAAQ,IAAI,UAAU;AAAA,QACtB;AAAA,QACA,MAAM,KAAK,SAAS,IAAI,OAAO;AAAA,QAC/B,QAAQ,WAAW;AAAA,MACrB;AAAA,IACF;AAEA,iBAAa,SAAS;AAEtB,QAAI,mBAAmB;AACrB,oBAAc,iBAAiB;AAC/B,0BAAoB;AAAA,IACtB;AAGA,UAAM,iBAA2B,CAAC;AAElC,QAAI,kBAAkB;AAEpB,UAAI,SAAS,WAAW,KAAK;AAC3B,cAAM,UAAU,MAAM,SAAS,KAAK;AACpC,cAAM,WAAW,SAAS,KAAK,UAAU,EAAE,OAAO,EAAE,SAAS,SAAS,MAAM,kBAAkB,QAAQ,SAAS,OAAO,EAAE,CAAC,CAAC;AAAA;AAAA;AAC1H,YAAI,MAAM,QAAQ;AAClB,YAAI,MAAM,kBAAkB;AAC5B,YAAI,IAAI;AAER,qBAAa,SAAS,UAAU;AAAA,UAC9B,QAAQ;AAAA,UACR,SAAS,EAAE,gBAAgB,oBAAoB;AAAA,UAC/C,MAAM,OAAO,KAAK,WAAW,kBAAkB;AAAA,UAC/C,aAAa,KAAK,IAAI;AAAA,QACxB,CAAC;AACD;AAAA,MACF;AAGA,UAAI,SAAS,MAAM;AACjB,cAAM,SAAS,SAAS,KAAK,UAAU;AACvC,YAAI;AACF,iBAAO,MAAM;AACX,kBAAM,EAAE,MAAM,MAAM,IAAI,MAAM,OAAO,KAAK;AAC1C,gBAAI,KAAM;AACV,gBAAI,MAAM,KAAK;AACf,2BAAe,KAAK,OAAO,KAAK,KAAK,CAAC;AAAA,UACxC;AAAA,QACF,UAAE;AACA,iBAAO,YAAY;AAAA,QACrB;AAAA,MACF;AAEA,UAAI,IAAI;AAER,mBAAa,SAAS,UAAU;AAAA,QAC9B,QAAQ;AAAA,QACR,SAAS,EAAE,gBAAgB,oBAAoB;AAAA,QAC/C,MAAM,OAAO,OAAO,cAAc;AAAA,QAClC,aAAa,KAAK,IAAI;AAAA,MACxB,CAAC;AAAA,IACH,OAAO;AAEL,YAAM,kBAA0C,CAAC;AACjD,eAAS,QAAQ,QAAQ,CAAC,OAAO,QAAQ;AACvC,YAAI,QAAQ,uBAAuB,QAAQ,aAAc;AACzD,wBAAgB,GAAG,IAAI;AAAA,MACzB,CAAC;AAED,UAAI,UAAU,SAAS,QAAQ,eAAe;AAE9C,UAAI,SAAS,MAAM;AACjB,cAAM,SAAS,SAAS,KAAK,UAAU;AACvC,YAAI;AACF,iBAAO,MAAM;AACX,kBAAM,EAAE,MAAM,MAAM,IAAI,MAAM,OAAO,KAAK;AAC1C,gBAAI,KAAM;AACV,gBAAI,MAAM,KAAK;AACf,2BAAe,KAAK,OAAO,KAAK,KAAK,CAAC;AAAA,UACxC;AAAA,QACF,UAAE;AACA,iBAAO,YAAY;AAAA,QACrB;AAAA,MACF;AAEA,UAAI,IAAI;AAER,mBAAa,SAAS,UAAU;AAAA,QAC9B,QAAQ,SAAS;AAAA,QACjB,SAAS;AAAA,QACT,MAAM,OAAO,OAAO,cAAc;AAAA,QAClC,aAAa,KAAK,IAAI;AAAA,MACxB,CAAC;AAAA,IACH;AAEA,gBAAY;AAAA,EACd,SAAS,KAAK;AACZ,iBAAa,SAAS;AAEtB,QAAI,mBAAmB;AACrB,oBAAc,iBAAiB;AAC/B,0BAAoB;AAAA,IACtB;AAEA,iBAAa,eAAe,QAAQ;AAEpC,QAAI,eAAe,SAAS,IAAI,SAAS,cAAc;AACrD,YAAM,IAAI,MAAM,2BAA2B,SAAS,IAAI;AAAA,IAC1D;AAEA,UAAM;AAAA,EACR;AAGA,MAAI,iBAAiB;AACnB,UAAM,QAAoB;AAAA,MACxB,YAAW,oBAAI,KAAK,GAAE,YAAY;AAAA,MAClC,OAAO,gBAAgB;AAAA,MACvB,MAAM,gBAAgB;AAAA,MACtB,WAAW,KAAK,IAAI,IAAI;AAAA,IAC1B;AACA,aAAS,KAAK,EAAE,MAAM,MAAM;AAAA,IAAC,CAAC;AAAA,EAChC;AACF;;;ASvhBO,IAAM,sBAAN,cAAkC,MAAM;AAAA,EACpC,OAAO;AAAA,EAEhB,YAAY,SAAkB;AAC5B;AAAA,MACE,WACE;AAAA,IACJ;AACA,SAAK,OAAO;AAAA,EACd;AACF;AAKO,IAAM,qBAAN,cAAiC,MAAM;AAAA,EACnC,OAAO;AAAA,EAEhB,cAAc;AACZ,UAAM,8EAA8E;AACpF,SAAK,OAAO;AAAA,EACd;AACF;AAKO,SAAS,sBAAsB,OAA8C;AAClF,SAAO,iBAAiB,SAAU,MAA8B,SAAS;AAC3E;AAKO,SAAS,qBAAqB,OAA6C;AAChF,SAAO,iBAAiB,SAAU,MAA6B,SAAS;AAC1E;;;AClBA,SAAS,gBAAAE,eAAc,iBAAAC,gBAAe,cAAAC,aAAY,aAAa,aAAAC,kBAAiB;AAChF,SAAS,WAAAC,gBAAe;AACxB,SAAS,QAAAC,aAAY;AAKrB,SAAS,mBAAmB,QAAyC,QAAuB;AAC1F,QAAM,aAAaA,MAAKD,SAAQ,GAAG,aAAa,eAAe;AAC/D,MAAI,CAACF,YAAW,UAAU,GAAG;AAC3B,WAAO,KAAK,sDAAsD;AAClE;AAAA,EACF;AAEA,MAAI;AACF,UAAM,SAAS,KAAK,MAAMF,cAAa,YAAY,OAAO,CAAC;AAG3D,QAAI,OAAO,QAAQ,WAAW,QAAQ;AACpC,aAAO,OAAO,OAAO,UAAU;AAAA,IACjC;AAEA,QAAI,OAAO,QAAQ,WAAW,YAAY;AACxC;AAAA,IACF;AAEA,QAAI,CAAC,OAAO,OAAQ,QAAO,SAAS,CAAC;AACrC,QAAI,CAAC,OAAO,OAAO,UAAW,QAAO,OAAO,YAAY,CAAC;AAEzD,WAAO,OAAO,UAAU,aAAa;AAAA,MACnC,SAAS;AAAA,MACT,KAAK;AAAA,MACL,GAAI,SAAS,EAAE,OAAO,IAAI,CAAC;AAAA,MAC3B,QAAQ;AAAA,IACV;AAEA,IAAAC,eAAc,YAAY,KAAK,UAAU,QAAQ,MAAM,CAAC,CAAC;AACzD,WAAO,KAAK,iDAAiD;AAAA,EAC/D,QAAQ;AAAA,EAER;AACF;AAKA,SAAS,kBACP,QACA,QACM;AACN,QAAM,YAAYI,MAAKD,SAAQ,GAAG,aAAa,QAAQ;AACvD,MAAI,CAACF,YAAW,SAAS,GAAG;AAC1B;AAAA,EACF;AAEA,MAAI;AACF,UAAM,SAAS,YAAY,WAAW,EAAE,eAAe,KAAK,CAAC,EAC1D,OAAO,CAAC,MAAM,EAAE,YAAY,CAAC,EAC7B,IAAI,CAAC,MAAM,EAAE,IAAI;AAEpB,eAAW,WAAW,QAAQ;AAC5B,YAAM,UAAUG,MAAK,WAAW,SAAS,OAAO;AAChD,YAAM,WAAWA,MAAK,SAAS,oBAAoB;AAEnD,UAAI,CAACH,YAAW,OAAO,GAAG;AACxB,QAAAC,WAAU,SAAS,EAAE,WAAW,KAAK,CAAC;AAAA,MACxC;AAEA,UAAI,eAAwC,CAAC;AAC7C,UAAID,YAAW,QAAQ,GAAG;AACxB,YAAI;AACF,yBAAe,KAAK,MAAMF,cAAa,UAAU,OAAO,CAAC;AAAA,QAC3D,QAAQ;AACN,yBAAe,CAAC;AAAA,QAClB;AAAA,MACF;AAEA,UAAI,aAAa,YAAY;AAC3B;AAAA,MACF;AAEA,mBAAa,aAAa;AAAA,QACxB,WAAW;AAAA,QACX,YAAY;AAAA,UACV;AAAA,QACF;AAAA,MACF;AAEA,MAAAC,eAAc,UAAU,KAAK,UAAU,cAAc,MAAM,CAAC,CAAC;AAC7D,aAAO,KAAK,2CAA2C,OAAO,EAAE;AAAA,IAClE;AAAA,EACF,QAAQ;AAAA,EAER;AACF;AAKA,eAAe,uBAAuB,KAAuC;AAE3E,QAAM,YAAY,cAAc,IAAI,YAAY;AAEhD,MAAI,CAAC,WAAW;AACd,UAAM,IAAI,oBAAoB;AAAA,EAChC;AAEA,QAAM,EAAE,KAAK,QAAQ,OAAO,IAAI;AAEhC,MAAI,WAAW,UAAU;AACvB,QAAI,OAAO,KAAK,kCAAkC;AAAA,EACpD,WAAW,WAAW,SAAS;AAC7B,QAAI,OAAO,KAAK,qDAAqD;AAAA,EACvE,OAAO;AACL,QAAI,OAAO,KAAK,2CAA2C;AAAA,EAC7D;AAGA,oBAAkB,IAAI,QAAQ,MAAM;AAGpC,QAAM,gBAAgB,IAAI,cAAc;AAExC,QAAM,QAAQ,MAAM,WAAW;AAAA,IAC7B;AAAA,IACA;AAAA,IACA,SAAS,CAAC,SAAS;AACjB,UAAI,OAAO,KAAK,kCAAkC,IAAI,EAAE;AAAA,IAC1D;AAAA,IACA,SAAS,CAAC,UAAU;AAClB,UAAI,OAAO,MAAM,uBAAuB,MAAM,OAAO,EAAE;AAAA,IACzD;AAAA,IACA,UAAU,CAAC,aAAa;AACtB,YAAM,OAAO,SAAS,aAAa,QAAQ,CAAC;AAC5C,YAAM,SAAS,SAAS,UAAU,KAAK,QAAQ,CAAC;AAChD,UAAI,OAAO,KAAK,GAAG,SAAS,IAAI,WAAM,SAAS,KAAK,KAAK,IAAI,WAAW,KAAK,QAAQ,SAAS,SAAS,EAAE;AAAA,IAC3G;AAAA,IACA,gBAAgB,CAAC,UAAU;AACzB,UAAI,OAAO,KAAK,UAAU,KAAK,yBAAyB;AAAA,IAC1D;AAAA,EACF,CAAC;AAED,iBAAe,KAAK;AAEpB,MAAI,OAAO;AAAA,IACT,iCAA4B,MAAM,OAAO;AAAA,EAC3C;AACF;AAEA,IAAM,SAAmC;AAAA,EACvC,IAAI;AAAA,EACJ,MAAM;AAAA,EACN,aACE;AAAA,EACF,SAAS;AAAA,EAET,SAAS,KAAwB;AAE/B,QAAI,iBAAiB,cAAc;AAGnC,UAAM,YAAY,cAAc,IAAI,YAAY;AAChD,UAAM,SAAS,WAAW;AAG1B,uBAAmB,IAAI,QAAQ,MAAM;AAGrC,QAAI,CAAC,IAAI,OAAO,QAAQ;AACtB,UAAI,OAAO,SAAS,EAAE,WAAW,CAAC,EAAE;AAAA,IACtC;AACA,QAAI,CAAC,IAAI,OAAO,OAAO,WAAW;AAChC,UAAI,OAAO,OAAO,YAAY,CAAC;AAAA,IACjC;AACA,QAAI,OAAO,OAAO,UAAU,aAAa;AAAA,MACvC,SAAS;AAAA,MACT,KAAK;AAAA,MACL,GAAI,SAAS,EAAE,OAAO,IAAI,CAAC;AAAA,MAC3B,QAAQ;AAAA,IACV;AAEA,QAAI,OAAO,KAAK,mCAAmC,gBAAgB,MAAM,UAAU;AACnF,QAAI,OAAO,KAAK,yBAAyB,gBAAgB,MAAM,GAAG,CAAC,EAAE,IAAI,OAAK,EAAE,EAAE,EAAE,KAAK,IAAI,CAAC,KAAK;AAGnG,2BAAuB,GAAG,EAAE,MAAM,CAAC,QAAQ;AACzC,UAAI,OAAO;AAAA,QACT,iCAAiC,eAAe,QAAQ,IAAI,UAAU,OAAO,GAAG,CAAC;AAAA,MACnF;AAAA,IACF,CAAC;AAAA,EACH;AACF;AAEA,IAAO,gBAAQ;","names":["confidence","join","homedir","readFileSync","writeFileSync","existsSync","mkdirSync","homedir","join"]}
|
package/openclaw.plugin.json
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
{
|
|
2
2
|
"id": "clawzenmux",
|
|
3
3
|
"name": "ClawZenMux",
|
|
4
|
-
"description": "Smart LLM router via ZenMux —
|
|
4
|
+
"description": "Smart LLM router via ZenMux — 100+ models, rules-based routing, token cost savings",
|
|
5
5
|
"configSchema": {
|
|
6
6
|
"type": "object",
|
|
7
7
|
"properties": {
|
package/package.json
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@wy51ai/clawzenmux",
|
|
3
|
-
"version": "0.1.
|
|
4
|
-
"description": "Smart LLM router via ZenMux —
|
|
3
|
+
"version": "0.1.5",
|
|
4
|
+
"description": "Smart LLM router via ZenMux — 100+ models, intelligent routing, token cost savings.",
|
|
5
5
|
"type": "module",
|
|
6
6
|
"main": "dist/index.js",
|
|
7
7
|
"types": "dist/index.d.ts",
|