All notable changes to ClawRouter.
Add Z.AI's new flagship GLM-5.2 (launched 2026-06-16), aligning with BlockRun's source-of-truth catalog (zai/glm-5.2, first in the GLM lineup).
zai/glm-5.2added to the catalog — 1M-token context (262K max output), paid per-token at $1.40/$4.40 (same rate as GLM-5.1, cached $0.26). Z.AI's newest flagship: beats GPT-5.5 on long-horizon coding at a fraction of the cost. Categories: chat, reasoning, coding.- Bare
glmalias retargeted GLM-5.1 → GLM-5.2 (bare alias always tracks the newest flagship). Newglm-5.2explicit shorthand added.glm-5.1explicit pin preserved as the 200K-context predecessor (identical price, so no cost-stability tradeoff — kept for behavioral parity). - Picker visibility — added to
top-models.json(head of the GLM group), so it surfaces in the OpenClaw/modelpicker and the allowlist sync on next provider refresh. README Mid-Range pricing table updated. - No router-tier changes: GLM models are accessed by alias/direct call, not wired into any auto/eco/premium tier chain — GLM-5.2 follows the same path. All 619 tests pass.
Align the free tier with BlockRun's 2026-06-14 free-tier refresh (blockrun commit 5817ecd: self-healing health gate + probe-verified NVIDIA lineup). BlockRun found only 7 of 17 "available" free models were actually being served and replaced the stale manual redirect list with a per-model circuit breaker.
free/qwen3-coder-480bretired — NVIDIA EOL'd it on 2026-06-14; BlockRun now redirectsqwen3-coder→seed-oss-36bserver-side. Dropped from the auto-pick cascade (FREE_MODELS), the picker (top-models.json), and the router COMPLEX backstops. The catalog entry + explicitnvidia/qwen3-coder-480balias stay for pinned callers (BlockRun still resolves them via redirect); the generic coding shorthands (qwen-coder,glm-free,devstral, …) now point at the live successorfree/seed-oss-36b.free/deepseek-v4-flashremoved from the eco SIMPLE fallback — NVIDIA upstream hung; BlockRun redirects it. Replaced with the livefree/qwen3-next-80b-a3b-instruct. Catalog entry kept (still direct-callable, redirects server-side).- 6 new live free models added to the catalog + aliases (probe-verified by BlockRun):
free/qwen3-next-80b-a3b-instruct(262K ctx, reasoning + coding),free/seed-oss-36b(coding),free/mistral-nemotron,free/step-3.7-flash(reasoning),free/nemotron-nano-9b-v2(fast lightweight),free/nemotron-nano-12b-v2-vl(vision-language). - Auto-pick cascade 7 → 12, gpt-oss kept at the head (heavy-user default — never retired). Picker free set 7 → 8 (
qwen3-coder-480b→qwen3-next-80b-a3b-instruct+seed-oss-36b). README/SKILL free-count synced 7 → 8; install-script/modelhelp echoes refreshed to live models.
Updater: clean stale OpenClaw install metadata (#186, thanks @0xCheetah1)
scripts/update.shnow removes ClawRouter's stale record from~/.openclaw/plugins/installs.jsonafter a verified update. OpenClaw 2026.6 migrates its plugin install index toward shared SQLite; a leftover ClawRouterinstallRecordsentry that no longer matches the installed version/path madeopenclaw doctorwarn about conflicting install metadata on every run. The updater now compares the legacy record against the current package across theextensions/, project-scoped, and global npm layouts, and removes only ClawRouter's record (other plugins untouched) when it is stale — guarded by a full try/catch and an atomic write.
Registry realignment with the 2026-06-13 → 06-14 BlockRun catalog sweep: Fable 5 delisting reverted, Kimi K2.7 promoted, free tier strengthened. 619 tests passing.
anthropic/claude-fable-5DELISTED by Anthropic 2026-06-13 (offer withdrawn upstream — no longer served on direct Anthropic or Bedrock). BlockRun removed the catalog entry and redirects fable →opus-4.8(route.tsMODEL_REDIRECTS). v0.12.208's same-day promotion of Fable 5 to premium COMPLEX primary was therefore pointing default premium-tier complex traffic at a now-dead model. Reverted: catalog entry removed, allfable*aliases (fable,fable-5,fable-5.0,anthropic/fable,anthropic/claude-fable-5[.0]) now resolve toanthropic/claude-opus-4.8, and premium COMPLEX primary restored toopus-4.8(its first fallback before the promotion). Pinned callers silently land on opus-4.8, matching the gateway.
moonshot/kimi-k2.7added — Moonshot's new flagship: 256K context, multi-modal (image + video input), returnsreasoning_content. AT-COST pricing $0.95/$4.00 — identical to K2.6 (BlockRun serves it via the OpenRouter credit pool failing over to direct Moonshot; zero margin by design). Bare aliases (kimi,moonshot,kimi-k2) retargeted K2.6 → K2.7; explicitkimi-k2.6/kimi-k2.5pins preserved. K2.6 marked superseded (hidden on BlockRun) but stays fully routable as an identical-cost first fallback.- Router primaries promoted K2.6 → K2.7 (same price, so cost-neutral):
auto.MEDIUM,agentic.MEDIUM,premium.SIMPLE. Each keeps K2.6 as its first fallback (in-family hot swap). K2.7 also prepended ahead of K2.6 in the premium MEDIUM/COMPLEX and agentic COMPLEX fallback chains. Picker (top-models.json) swapped K2.6 → K2.7.
- Auto-pick set 6 → 7, gpt-oss kept at the head (heavy-user default, deliberately retained despite BlockRun hiding it). Mid/back strengthened with two BlockRun-re-featured free flagships:
free/mistral-large-3-675b(675B general, un-retired — NVIDIA upstream recovered) andfree/qwen3.5-122b-a10b(newest-gen Qwen).free/deepseek-v4-flashdropped from the auto-pick set + picker (BlockRun hid it) but stays catalog-routable for direct$0calls. New free shorthands:mistral-large,qwen3.5-122b. eco SIMPLE fallback chain extended with both new models. README/SKILL free-count synced (6 → 7).
Stop non-English prompts from crashing paid responses via the x-clawrouter-reasoning header.
- Non-ASCII routing reasoning crashed
res.writeHeadafter settlement (src/proxy.ts). The routing reasoning string embeds matched keywords from the multilingual lists insrc/router/config.ts(Cyrillic, CJK, …). Debug headers are on by default, so for e.g. Russian prompts the raw Cyrillic keywords landed in thex-clawrouter-reasoningresponse header and Node rejected the write withERR_INVALID_CHAR— after the upstream call had completed and the x402 payment had settled. The client never received the body and retried, signing a fresh payment each round: a paid retry loop. Header values are now percent-encoded outside printable ASCII (sanitizeHeaderValue, reversible viadecodeURIComponent), and as defense in depth a rejectedwriteHeadsanitizes all header values and still delivers the paid body instead of throwing. (Test:proxy.reasoning-header.test.ts, 13 cases, including a live Russian-prompt repro throughclassifyByRulesvalidated against Node'svalidateHeaderValue.) CLAWROUTER_DEBUG_HEADERS=off|false|0— new env kill switch for thex-clawrouter-*debug headers, for clients that can't set the per-requestx-clawrouter-debug: falseheader. Comments claiming the headers were "opt-in" corrected (they are on by default).
Honor standard proxy environment variables for upstream traffic.
HTTPS_PROXY/HTTP_PROXY/ALL_PROXYfallback (src/upstream-proxy.ts). Node's fetch (undici) ignores the standard proxy env vars, so users whose system traffic is meant to flow through a local proxy (mihomo/clash without TUN mode, corporate proxies) had ClawRouter connecting directly while theircurltests went through the proxy — on throttled routes (e.g. RU → Google-hosted gateway) this surfaced as instant 500s on large request bodies,Premature close, and per-model timeouts, while small requests slipped through. WhenBLOCKRUN_UPSTREAM_PROXYis unset, ClawRouter now applies the standard env vars via undici'sEnvHttpProxyAgent.NO_PROXYis honored, and loopback hosts (localhost,127.0.0.1,::1) are always excluded so local health checks and sibling proxies stay direct.BLOCKRUN_UPSTREAM_PROXYstill wins when set; SOCKS URLs in the standard env vars are not auto-applied (a warning points toBLOCKRUN_UPSTREAM_PROXY=socks5://…). (Test:test/upstream-proxy.test.ts, 9 cases, dependency-injected — no process-global mutation in tests.)
End-to-end audit sweep: 4 proxy reliability fixes (each TDD'd with a new regression test), abort/teardown hardening, registry realignment with the gateway, and doc/count sync. 596 tests passing (8 new).
- Process-crash fix: escaped rejections from the request handler. The
paymentStore.run(async () => …)promise wrapping every request was never.catch()ed, and the media endpoints (/v1/images/generations,image2image,audio,videos) read the request body outside theirtryblocks — a client aborting mid-upload rejected the body iterator, escaped the handler, and became anunhandledRejection, which kills the whole proxy under Node's default semantics. A safety-net.catch()now logs, replies 500 when possible, and never lets a rejection escape. (Test:proxy.aborted-upload.test.ts.) - Partner-API corruption:
content-lengthforwarded after fetch decompression.proxyPaidApiRequeststrippedcontent-encodingbut keptcontent-length, so any gzipped upstream response (pm/exa/surf/phone/…) reached the client with the compressed length and decompressed bytes → truncated JSON.content-lengthjoins the skip list; Node chunks instead. (Test:proxy.partner-gzip.test.ts.) - Client abort now cancels upstream work in the media + partner paths. The image/video 202-poll loops kept polling after the client disconnected — and the first
completedpoll settles the x402 payment, charging the user for a clip nobody will receive. Both loops (and the partner proxy + media submit calls) now thread anAbortControllertied toresclose, bail before the next poll, and passsignalintopayFetch. (Test:proxy.poll-abort.test.ts.) - Streaming dedup waiters get heartbeats. A streaming retry that attached to an in-flight identical request waited in silence (no headers, no bytes) for up to minutes — recreating the OpenClaw ~10-15s timeout/retry storm the heartbeat mechanism exists to prevent, and stacking more waiters each round. Waiters now receive SSE headers +
: heartbeatcomments immediately and replay the original's transcript when it lands. (Test:proxy.dedup-streaming.test.ts.) - Balance check time-bounded at 2.5s (
BALANCE_CHECK_TIMEOUT_MS). The pre-request balance check runs before SSE headers; a slow RPC (Solana retry ladder ≈ 34s worst case, and zero balances are never cached) starved streaming clients of their first byte. On expiry the request proceeds optimistically; the in-flight RPC still warms the monitor cache. (Test:proxy.balance-check-latency.test.ts, via the existing_balanceMonitorOverrideseam.) - Teardown/leak batch: partner proxy now
res.end()s after a mid-stream body-read timeout instead of hanging the client until socket timeout;readBodyWithTimeoutcancels the stream on timeout (was leaking the undici connection until GC); the budget second-pass 429 path releases the global timeout + close listener; the empty-wallet fallback writes the exclude-awarefreeFallbackpick into the body instead of the hardcodedFREE_MODEL(latent exclude-list bypass); the 429-retry success path usesFREE_MODELS.has()like its siblings (phantom ~$0.001 session-budget entries); the video poll loop tracks an explicitcompletedflag so a completed-but-empty job no longer reports as "timed out";payment-preauth.tsreuses the rejected pre-auth 402 (which already carries fresh requirements) instead of buying an identical 402 with an extra unpaid round trip. - Hot-path perf:
estimateAmountnow uses a module-levelMap(the budget pre-check scannedBLOCKRUN_MODELSlinearly per model → O(n²) per request);loadExcludeList(src/exclude-models.ts) gained an mtime-validated cache.
anthropic/claude-sonnet-4.5added ($3/$15, 200K ctx, vision) — public upstream since the 4.6 launch but missing here entirely; same gap class v0.12.167 fixed for opus-4.5. Pins:sonnet-4.5,sonnet-4-5,anthropic/claude-sonnet-4-5. Baresonnetstays on 4.6; not picker-listed (superseded tier).- Seedance i2v telemetry rates un-discounted — blockrun
403e61e(2026-06-01) removed the image-to-video discount; the stalepricePerSecondImageInputrows (0.13369/0.1742) under-logged i2v cost ~41%. i2v now logs at the text rate. Telemetry-only (payments are server-dictated). Known remaining gap, documented in the comment: blockrun'sRESOLUTION_TOKEN_FACTOR(1080p = 2.25×) still isn't modeled. azure/sora-2added toVIDEO_PRICING($0.10/s flat, 4s default — a 12s clip was falling back to the generic ~$0.42 telemetry row) andopenai/gpt-image-2added toIMAGE_PRICING($0.06 / $0.12 by size). Both added to README + SKILL docs.- Duplicate-id picker entries eliminated (
src/models.ts): catalog entries shadowed by an identically-keyed alias (free,openai/o1-mini,google/gemini-3-pro-preview,nvidia/kimi-k2.5) are now excluded fromOPENCLAW_MODELS—resolveModelAliaschecks aliases first, so those catalog entries were unreachable and advertised the old model's metadata while callers got the redirect target. The picker's doublefreerow is gone (39 → 38 =top-models.json), and the survivingfreeentry finally says GPT-OSS 120B instead of the retired "Nemotron Ultra 253B". (Tests added inmodels.test.ts.)
- Free-model count corrected everywhere: 6 (was variously 8, 9, and 10 across README badges/prose and SKILL.md — stale since the 2026-06-07 sweep). README profile table AUTO·MEDIUM cell synced to
kimi-k2.6 ($0.95/$4.00)(changed in v0.12.174); ECO·REASONING cell named the actual primary (grok-4-1-fast-reasoning); doctor sample output and CLAUDE.md now say Node 22 (floor raised in #183). - Dead code removed:
src/router/llm-classifier.ts(designed LLM-fallback classifier, never wired), the vestigialwalletKeyAuth/envKeyAuthinteractive auth methods insrc/auth.ts,decompressContent(codebook),generatePathMapHeader(paths); two internal-only functions un-exported. @noble/hashesdeclared as a direct dependency —src/wallet.tsimports it directly but it only resolved via@scure/*hoisting (phantom dep; masked at runtime by tsup bundling). Stale tsconfigexcludeoferror-classification.test.tsdropped (it typechecks fine).
Finished de-listing nvidia/mistral-small-4-119b after the gateway hid + redirected it (2026-06-08).
nvidia/mistral-small-4-119bfully de-listed — the gateway now marks ithiddenand server-redirects it tonvidia/llama-4-maverick(NVIDIA upstream timing out, 3/3 probes >60s). All five alias targets that still resolved tofree/mistral-small-4-119b(nvidia/mistral-small-4-119b,nvidia/mistral-large-3-675b,free/mistral-large-3-675b,mistral-free,mistral-small) now resolve tofree/llama-4-maverick, matching the gateway. Removed from the model catalog and the/modelpicker (top-models.json); README budget row dropped. (Test pricing fixture kept as a generic $0 entry.)
Free-tier routing realigned to the backend's 2026-06-07 model sweep.
nvidia/qwen3-next-80b-a3b-thinkingremoved — NVIDIA end-of-life 2026-05-21 (HTTP 410; server redirects tonvidia/llama-4-maverick). Dropped from the auto-pick set, the/modelpicker (top-models.json), the eco-tier fallback chain, and the model catalog. All 15 alias/redirect targets that pointed at it (the nemotron family,qwen-thinking,qwen3-next, thenvidia/qwen3-next…identity) now resolve tofree/llama-4-maverick, matching the gateway.nvidia/glm-4.7de-listed from auto-pick + picker — NVIDIA NIM deployment hung; the gateway redirects it tonvidia/qwen3-coder-480b. Its aliases (nvidia/glm-4.7,glm-free) now resolve tofree/qwen3-coder-480b. (Catalog entry kept so directfree/glm-4.7calls still price at $0.)nvidia/mistral-small-4-119bdropped from auto-pick + eco fallback — upstream timing out (3/3 probes >60s). Still directly callable (alias resolution intact, officiallyavailableserver-side); just no longer a smart-routing target. README annotated.
- GLM flat pricing fully retired (backend d840de7). Z.AI's remaining flat $0.001/call promos ended 2026-06-06:
zai/glm-5now bills per-token at $0.60/$1.92 andzai/glm-5-turboat $1.20/$4.00 (glm-5.1 stays $1.40/$4.40). Their permanentflatPricefields are removed so payment pre-estimation sizes per-token again; theflatPricemechanism itself stays for any future flat-billed SKU. README pricing rows updated.
- Upstream delistings mirrored (gateway health probe 2026-06-06).
openai/o1-mini404s at OpenAI andgoogle/gemini-3-pro-preview404s at Google; the gateway hid both and redirects them (o1-mini→o4-mini,gemini-3-pro-preview→gemini-3.1-pro). ClawRouter mirrors the redirects inMODEL_ALIASES(pinned callers land on the successor instead of an upstream error), drops gemini-3-pro-preview from the picker, and removes it from the AUTO COMPLEX fallback chain (it would have silently resolved to the tier primary anyway).
- Catalog sync with BlockRun backend (2026-06-04/05 model drops + repricing).
- New xAI models (
src/models.ts,src/top-models.json):xai/grok-4.3($1.50/$4.00, 1M ctx, reasoning + vision + agentic) andxai/grok-build-0.1($1.50/$3.00, 256K, agentic coding) — both resold via BlockRun's OpenRouter credit pool and public in the backend catalog, so both are picker-visible. Aliases: baregrokpromotedxai/grok-3→xai/grok-4.3(grok-3 and the 4-fast/4-1-fast families are now hidden on BlockRun; explicit IDs still resolve).grok-coderepointeddeepseek/deepseek-chat→xai/grok-build-0.1(xAI again has a real coding SKU); new pinsgrok-4.3,grok-build. The delistedgrok-code-fast-1redirects stay on cheap chat. deepseek/deepseek-v4-proadded to the catalog ($0.435/$0.87 — the 75% launch promo became DeepSeek's permanent list price after 2026-05-31; 1M ctx, reasoning + agentic). Fixes a latent picker bug:top-models.jsonalready listed it, but with noBLOCKRUN_MODELSentry theVISIBLE_OPENCLAW_MODELSfilter silently dropped it.deepseek-chat/deepseek-reasonerentries refreshed from stale V3.2 ($0.28/$0.42, 128K) to V4 Flash ($0.20/$0.40, 1M).- GLM flat pricing modeled correctly (
src/models.ts): new permanentflatPricefield onBlockRunModel(backendbillingMode: "flat"; takes precedence ingetActivePromoPrice).zai/glm-5andzai/glm-5-turboswitch from an expired promo (ended 2026-04-15 in our metadata) to permanent flat $0.001/request — they had been mis-estimated per-token for 7 weeks.zai/glm-5.1's promo end corrected to 2026-06-05 (when BlockRun actually ended it); it now bills per-token $1.40/$4.40. - Router untouched: tier primaries/fallbacks in
src/router/config.tsare benchmark-driven; grok-4.3 / grok-build-0.1 / v4-pro enter routing only after they get benchmark rows. - Docs: README pricing tables refreshed (deepseek V4 rows, glm flat rows, grok-4.3 / grok-build-0.1 / minimax-m3 / glm-5.1 added);
skills/clawrouter/SKILL.mdmodel list updated.
- New xAI models (
- Claude Opus 4.8 is now the Anthropic flagship. BlockRun's source-of-truth model registry (
blockrun/src/lib/models.ts) shippedanthropic/claude-opus-4.8as its current featured flagship — $5/$25 per 1M (identical to 4.7), 1M context, 128K output, adaptive thinking,fallbackModel: claude-opus-4.7. This release aligns ClawRouter:- Model registry (
src/models.ts): addedanthropic/claude-opus-4.8toBLOCKRUN_MODELS(mirrors the 4.7 spec — 1M ctx, 128K out, reasoning/vision/agentic/tools). - Aliases (
src/models.ts): bareopus,opus-4,anthropic/opus, and genericanthropic/claude-opus-4now resolve to 4.8, matching BlockRun (where bare opus /clawrouter-premiumredirect to 4.8). New explicit pinsopus-4.8/opus-4-8/anthropic/claude-opus-4-8. Explicitopus-4.7/opus-4.6/opus-4.5pins stay routable on their own version for cost-stability callers. - Router (
src/router/config.ts):premiumTiers.COMPLEXprimary promotedclaude-opus-4.7→claude-opus-4.8(cost-neutral — same $5/$25), with 4.7 inserted as the first in-family fallback. 4.8 also inserted ahead of 4.7 in the premium REASONING, agentic COMPLEX, and agentic REASONING fallback chains.selector.tsbaseline left on 4.7 (pricing-identical; no savings-math change). - Picker (
src/top-models.json): added 4.8, removed 4.6 (already hidden on BlockRun). Picker now shows opus-4.8 + opus-4.7; 4.6 stays resolvable via explicit alias. Note: existing users carry stalecfg.models.providers.blockrun.modelsarrays (OpenClaw merges, never deletes), so the 4.6 removal only takes effect on a fresh prune/re-install — same caveat as v0.12.175. - Diagnostics (
src/doctor.ts):doctor opusdeep-analysis model bumped to 4.8 (identical cost). - Docs: README pricing tables/examples and
skills/clawrouter/SKILL.mdmodel list refreshed. - No provider-routing or
thinking-block changes: 4.8's adaptive-thinking contract is identical to 4.7's, which ClawRouter has routed in production without injecting explicit thinking blocks.
- Model registry (
-
Plugin now loads at gateway boot (manifest capability declarations). OpenClaw 2026.5.x's strict gateway-boot plugin loader requires the manifest to declare the capabilities a plugin provides.
openclaw.plugin.jsondeclared none (Shape: non-capability), so afteropenclaw gateway restartthe loader silently skipped ClawRouter: the x402 proxy never bound:8402, the BlockRun provider/web-search/partner tools never registered, and/wallet,/blockrun,/statsetc. returned "no such command" inside the TUI. Install-time hot-reload is lenient and still loaded the plugin, which masked the regression —openclaw plugins doctorwas the tell, repeatingclawrouter: plugin must declare contracts.tools before registering agent tools26×. Fix adds the four declarations the strict loader needs:contracts.tools— the 26 partner tools registered at runtime (blockrun_predexon_*,blockrun_stock_*,blockrun_crypto_*/fx_*/commodity_*,blockrun_image_*,blockrun_video_generation,blockrun_phone_*,blockrun_voice_*). Verified to be an exact match tosrc/partners/registry.tsruntime registration — no missing, no extra.contracts.webSearchProviders: ["blockrun-exa"]— the Exa-backed web search provider (src/web-search-provider.ts).providers: ["blockrun"]— declares ownership of theblockrun/*model IDs (src/provider.ts), same pattern asanthropic/openai.activation.onStartup: true+enabledByDefault: true— opt into the trusted boot-load path so the proxy comes up at gateway start instead of lazy-loading.
Manifest-only change (static JSON read directly by the loader, not bundled into
dist/); it does not touch the runtime config-write path, so it cannot trip OpenClaw'sbaseHashConfigMutationConflictError. Closes the gateway-restart load failure on OpenClaw 2026.5.19+. Contributor credit: PR #171 by @bogdan-velicu — first-time contributor, thorough repro + verification writeup. 🎉 -
Ships v0.12.195's Seedance pricing fix (latent stale-
dist/). v0.12.195 updatedsrc/proxy.tsto the 720p+audio per-second rates (e.g.seedance-1.5-pro$0.04375/sec→$0.0875/sec), but the committeddist/bundle at v0.12.195 and v0.12.196 was never rebuilt from that source — both releases shipped the old 480p-baseline pricing, so the localestimateVideoCosttelemetry kept under-reporting Seedance usage by ~2× (payment is server-dictated, so no overcharge — telemetry only). This release rebuildsdist/from current source, so the corrected Seedance per-second rates finally land in the published bundle.
- Updater recovers from OpenClaw size-drop rejection. OpenClaw v2026.4.5+ refuses to write a config that would shrink the file by a large amount (data-loss guard). Users on a pre-v0.12.175 install carry ~175 entries in
models.providers.blockrun.models; upgrading to a current ClawRouter legitimately trims that to ~38 (≈90 KB → 25 KB), tripping OpenClaw's guard. The updater previously surfaced this as a hard failure and rolled back, stranding users on the old version. Fix inscripts/update.sh: pipe the install output to a captured log, detect theConfig write rejected: …size-drop:signature, validate the rejected payload against a conservative checklist (top-level keys unchanged, required sections present, model count actually shrank, curated count in [20, 100], non-model sections drift ≤ 2 KB, residual models section ≤ 4 KB, ≥ 65% of the drop comes from the model list), apply just the scoped model-list trim atomically (tmp.PID→ rename), then fall through to a directnpm packinstall of the latest version. The EXIT/INT/TERM rollback trap stays active across the fallback path so Ctrl+C still restores the previous install. Tested on a real VPS reproducing the 90728 → 25514 rejection. - Contributor credit. PR #170 by @0xCheetah1.
- Seedance 720p + audio defaults aligned with blockrun re-enable. Blockrun took the three Seedance entries offline on 2026-05-21 (
available:false, returning400 "not currently available"on POST) after user reports of (1) 480p output without audio, visibly worse than JiMeng on the same prompt, and (2) the missing real-person enrollment flow. On 2026-05-22 (commite6dc1f1) they re-enabled all three withresolution=720p+generate_audio=true(t2v) / false(i2v)defaults in the videos route, doubling the per-second token count from10128→20256. ClawRouter'sVIDEO_PRICINGtable was sized for the 480p baseline, so the localestimateVideoCostwas under-reporting walletlogUsageby ~2× for the past day (payment is fully server-dictated, so no overcharge — telemetry only, perfeedback_telemetry_vs_payment). Updatedsrc/proxy.ts:- 1.5 Pro:
$0.04375/sec→$0.0875/sec(flat — no image discount; token360 prices text and image inputs at the same per-M rate). - 2.0 Fast: text
$0.11343/sec→$0.22687/sec, image$0.06684/sec→$0.13369/sec. - 2.0 Pro: text
$0.14179/sec→$0.28358/sec, image$0.08710/sec→$0.17420/sec. - Header comment refreshed to call out the 720p+audio default and the doubled tokens/sec.
- 1.5 Pro:
- 5s default-call telemetry now lands at: 1.5 Pro ~$0.46 (was $0.23), 2.0 Fast ~$1.19 text / ~$0.70 image (was $0.60 / $0.35), 2.0 Pro ~$1.49 text / ~$0.91 image (was $0.74 / $0.46). All within ~1% of blockrun's quote at the new 720p settings.
- Discovery surfaces refreshed.
src/partners/registry.tsvideo_generationentry now advertises the 720p+audio defaults, declaresimage_url+real_face_asset_idas explicit params (both already worked via raw body passthrough — this just makes them discoverable to agents and the/v1/partnerslisting), and updates the pricing display to the new$0.46–$2.98range.README.mdpricing table + explanatory paragraph andskills/clawrouter/SKILL.mdheadline rewritten in the same shape — the old "480p, ~10,128 tokens/sec, $0.23–$0.74 / 5s" copy from v0.12.194 is now stale on every surface. - No proxy whitelist or routing change. Seedance was already in the video proxy path; the re-enable on blockrun's side restored POST without ClawRouter needing to flip any flag. Aliases (
seedance,seedance-1.5,seedance-2-fast,seedance-2) and the/videogenslash command continue to work as before.
-
Seedance video pricing aligned with blockrun's token-priced model. Last week blockrun replaced the flat per-second Seedance pricing with
duration × tokens/sec × $/1M tokens × 1.05 marginafter a verification call againstbytedance/seedance-2.0-fastmeasured 10,128 tokens/sec at 480p (token360's default, not the 720p we'd guessed). The old ClawRouterVIDEO_PRICINGtable was both wrong-shaped and ~3–4× off on the high side. Updatedsrc/proxy.ts:VIDEO_PRICINGnow stores base$/sec(no margin baked in —estimateVideoCoststill applies the 5% margin to match server'sMARGIN_PERCENT). Per-second values are derived from10128 × $/1M tokens / 1e6.- New optional
pricePerSecondImageInputfield per model. 2.0 Fast and 2.0 Pro charge ~40% less per token on image-to-video (token360's published image rate); 1.5 Pro stays flat because its audio-generation toggle isn't yet wired to a request param, and undercharging when audio is on by default would be silent loss. estimateVideoCost(model, durationSeconds, hasImageInput)picks the cheaper image rate when the request body hasimage_url. The video route now parsesimage_urlpresence alongsidemodel+duration_secondsand threads it into the cost callsite (src/proxy.ts:2706, 2876).- Net effect on the default 5s call telemetry: 1.5 Pro $0.16 → $0.23, 2.0 Fast $0.79 → $0.60 text / $0.35 image, 2.0 Pro $1.58 → $0.74 text / $0.46 image. Matches blockrun's quoted prices to within rounding. This is telemetry-only — payment is fully server-dictated via x402 (
feedback_telemetry_vs_payment).
-
BytePlus RealFace passthrough documented (no code change needed). blockrun added an optional
real_face_asset_idbody field (formatta_xxxxxxxx) on Seedance 2.0 variants for real-person character consistency across frames. The ClawRouter video route already forwards the raw request body to blockrun as-is, so RealFace works transparently — but the README +skills/clawrouter/SKILL.mdheadline didn't mention it. Updated both with usage notes, the per-1M-token pricing model, and the constraint that RealFace +image_urlare mutually exclusive (both seed the first frame; pick one). -
Surf skill refreshed against blockrun's real
/gateway/v1catalog (83 endpoints). The first Surf skill (v0.12.193) was drafted in parallel with blockrun's integration and ended up out of sync once blockrun:- Switched to
api.asksurf.ai/gateway/v1(real public gateway, 82–83 real endpoints) and dropped 15 invented routes the skill had described. - Pre-validates required query params per endpoint before settling payment — call with a missing param and you get
400 { missing_params, all_required, docs }and the wallet isn't charged. 56 of 83 endpoints have required params. - Dropped surf-1.5 chat (
/surf/chat/completions) again pending per-token billing — calling it now returns 404 without taking payment.
Updated
skills/surf/SKILL.md:- Endpoint count 84 → 83, removed the Chat section, added the required-param pre-check note up front.
- Fixed param names that the agent would otherwise feed incorrectly and trip the pre-check 400:
social/mindshareisq+interval(notproject+window),search/*family isq(notquery),token/holders+token/transfersneedaddressANDchain,onchain/gas-priceneedschain,onchain/txneedshash+chain, exchange family universally needspair, market family usessymbol, prediction-market endpoints use their specific identifier params (market_slug,event_slug,condition_id,market_ticker,event_ticker,ticker,address), andfund/ranking+project/defi/*needmetric. - Reworded the example flows that previously used wrong param names (
search/project?query=ethena→?q=ethena, mindshare example fixed).
- Switched to
-
Phone skill — voice/call
fromis now optional with server-side auto-pick. blockrun movedfromfrom required → optional on/v1/voice/call. After payment verification the server picks a caller-ID from the wallet's owned numbers: 0 active →403 no_active_numberwith buy-first hint, exactly 1 → auto-used, 2+ →400 ambiguous_fromlisting all candidates. The prior skill said "Otherwise Bland picks one" — wrong, and would have made agents leavefromoff and confuse users with the 403/400 responses. Updatedskills/phone/SKILL.mdwith the actual auto-pick rule table and the ownership-mismatch 403 behavior. -
No code change for
real_face_asset_id, no new partner tools, no proxy whitelist change. Surf + Phone are both base+skill integrations (per the v0.12.193 rule). All blockrun upstream changes here flow through the existingproxyPaidApiRequestpath transparently.
- Surf integration — first skill-only marketplace API. BlockRun launched the Surf unified crypto data API (blockrun.ai/marketplace/surf) — 84 endpoints across 13 domains: CEX/DEX markets, on-chain SQL over 80+ ClickHouse tables (Ethereum, Base, Arbitrum, BSC, TRON, HyperEVM, Tempo), 100M+ labeled wallets, prediction markets (Polymarket + Kalshi), social/CT mindshare, news, project/DeFi metrics, token analytics, unified search, VC fund intelligence. Settles directly to Surf's Base treasury in USDC; no Surf account or API key required.
- New release pattern: base whitelist + skill, no typed wrappers. Earlier integrations (Predexon, Phone/Voice) wrote 200–400 lines of TypeScript per partner in
src/partners/registry.ts— hand-authored summaries of each endpoint exposed asblockrun_*tools. That pattern doesn't scale: Surf alone has 84 endpoints, and the next BlockRun-marketplace API will have more. From this release forward, new partner APIs ship as a skill (markdown the agent reads on demand) plus a one-line addition to the proxy namespace whitelist. The agent readsskills/<api>/SKILL.md, crafts the HTTP call, and gets paid x402 settlement transparently. Adding a new Surf endpoint requires zero ClawRouter release. This matches the Anthropic Skills convention (github.com/anthropics/skills) and aligns with how Claude Code is designed to consume capability surfaces. - Proxy whitelist. Extended the partner-route regex at
src/proxy.tsto match/v1/surf/*. Requests flow through the existingproxyPaidApiRequest(x402 handled transparently). NewisSurfbranch in the telemetry hook emitstier: "SURF"withmodel = "surf/<operation>"soclawrouter statsandclawrouter reportsee Surf usage as a distinct line — distinct from LLM, generic Partner, and Phone tiers. UpdatedproxyPaidApiRequestJSDoc + the inline route comment to document the new namespace. - No registry entries — no
blockrun_surf_*tools. Deliberate. The agent readsskills/surf/SKILL.mdfor the endpoint catalog and crafts calls tohttp://127.0.0.1:8402/v1/surf/...directly. Skip the duplication. skills/surf/SKILL.md(new). Full endpoint reference grouped by domain (Exchange, Market Overview, News, On-Chain, Prediction Markets, Project + DeFi, Social/CT, Token Analytics, Unified Search, VC Fund, Wallet Intelligence, Web, Chat). Pricing tier table ($0.001 / $0.005 / $0.020). Four worked example flows (wallet ID, token concentration, custom on-chain SQL with schema-fetch pattern, project mindshare lookup). Frontmatter triggers cover the natural-language queries an agent would phrase to find this skill ("onchain sql query","wallet labels api","crypto mindshare", etc.).skills/clawrouter/SKILL.mdheadline update — per thefeedback_skill_dual_layerrule. Added "Crypto Data (Surf) — skill-only integration" section after Prediction Markets, explaining the new base+skill pattern and pointing at the dedicatedsurfskill. Frontmatterdescriptionandtriggersextended to surface Surf capabilities. Without this headline update, agents reasoning about crypto-data tasks would skip ClawRouter even with the dedicatedsurfskill present.- README — new "Crypto Data (Surf)" section between Phone & Voice and Models & Pricing, with the pricing table, three curl examples (price, batch wallet labels, on-chain SQL), and a link to
skills/surf/SKILL.md. Notes that this is the new pattern for marketplace APIs. openclaw.plugin.jsondescription — mentions Surf so the OpenClaw plugin browser surfaces the capability.- Tests — new
src/proxy.surf-routing.test.tsmirrors the partner-path regex literal and adds 10 assertions: positive matches for/v1/surf/{market/price,onchain/sql,wallet/labels/batch,prediction-market/polymarket/markets,chat/completions}, negative guards against/v1/surfer/*,/v1/surfaces/*, and bare/v1/surf(no trailing slash), plus regression guards for existing partner paths (/v1/pm/*,/v1/exa/*,/v1/phone/*,/v1/voice/*,/v1/stocks/*) and non-partner/v1routes (/v1/chat/completions,/v1/models,/v1/images/generations). Mirroring the regex literal here means any silent regex edit fails loudly in CI. - Aborted course-correction in the same session (process note worth recording): the first pass of this integration also added 11 typed
blockrun_surf_*tools tosrc/partners/registry.ts(~470 lines) and generalized the__dynamic__handler insrc/partners/tools.ts. Reverted both before commit on user feedback — Surf doesn't belong inregistry.ts, and generalizing the dynamic handler without a second user would have been speculative. Lesson: mirroring the Predexon/Phone pattern by reflex skips the question of whether the pattern itself still scales. With Surf at 84 endpoints, it doesn't. New rule: typed partner wrappers are reserved for narrow, high-leverage APIs (≤12 endpoints, agent-facing tools that benefit from JSON-schema validation in OpenClaw). Everything else is base + skill.
- Phone & Voice integration — BlockRun's phone capability stack is now first-class in ClawRouter. BlockRun shipped 8 phone endpoints earlier this cycle (Twilio for number intelligence + provisioning, Bland.ai for AI-powered outbound voice calls), all x402-gated behind
blockrun.ai/api/v1/phone/*andblockrun.ai/api/v1/voice/*. ClawRouter had zero integration — agents reasoning about phone tasks would skip ClawRouter entirely (per thefeedback_skill_dual_layerrule: ifskills/clawrouter/SKILL.mddoesn't list a BlockRun capability, AI agents ignore the local proxy and hit the gateway directly, losing wallet/telemetry/local visibility). This release closes the gap on every surface. - Proxy paths. Extended the partner-route regex at
src/proxy.ts:2782to match/v1/phone/*and/v1/voice/*. Both flow through the existingproxyPaidApiRequest(x402 handled transparently). NewisPhonebranch in the telemetry hook emitstier: "PHONE"with model =phone/<operation>(soclawrouter statsandclawrouter reportsee phone usage as a distinct line).PHONE_PRICINGtable mirrors server-sidetwilio.ts+bland.tspricing (longest-prefix match handles/voice/call/{id}poll URLs correctly) and is used only as the telemetry fallback when the x402 paymentStore is empty — actual settlement is always server-dictated. - Tool registry. Eight new entries in
src/partners/registry.ts(PartnerCategoryunion extended with"Communications"):blockrun_phone_lookup($0.01) — carrier + line typeblockrun_phone_lookup_fraud($0.05) — SIM-swap + call-forwarding signalsblockrun_phone_numbers_buy($5.00 / 30 days) — provision a US/CA number tied to the walletblockrun_phone_numbers_renew($5.00 / +30 days) — extend leaseblockrun_phone_numbers_list($0.001) — wallet's active numbersblockrun_phone_numbers_release(free) — release a number back to the poolblockrun_voice_call($0.54 flat, ≤30 min) — outbound AI voice call via Bland.aiblockrun_voice_status(free) — poll call status / transcript / recording- Voice-call tool description carries an explicit safety guardrail: "places a REAL outbound phone call to a real number — only invoke when the user has explicitly asked." Server enforces an emergency-number blocklist; ClawRouter trusts upstream rather than duplicating the list.
/cr-callslash command insrc/index.ts, registered alongside/cr-imagegenand/videogen. Syntax:/cr-call +1<E.164> "<task>" [--voice nat] [--max-duration 5] [--from +1<owned-number>] [--language en-US]. NewparseCallArgshelper handles both--key=valueand--key valueflag forms, recognizes the first+E.164-shaped token as the destination, and packs the rest as the natural-language task. Mode is fire-and-forget: the command POSTs to/v1/voice/call, returnscall_id+poll_urlimmediately, and tells the user to poll for transcript when the call completes. Thecr-prefix is mandatory —/calland/phoneare even more commonly reserved by chat platforms than/imagegenwas when v0.12.190 had to rename it; we don't register either bare form.clawrouter phoneCLI subcommand insrc/cli.tscovers the wallet-resource operations that don't make sense as chat slash commands:clawrouter phone numbers list— formatted table with E.164, country, expiry-in-days,⚠ renew soonflag for ≤2 days remainingclawrouter phone numbers buy <US|CA> [--area-code <code>]— provisionclawrouter phone numbers renew <+E.164>— extend leaseclawrouter phone numbers release <+E.164>— releaseclawrouter phone lookup <+E.164>— quick carrier checkclawrouter phone fraud <+E.164>— quick SIM-swap check- All subcommands POST to the running proxy at
127.0.0.1:8402; payment flows through the existing wallet. 402 errors render with a friendly "fund your wallet" hint.
- SKILL.md double-layer update, per
feedback_skill_dual_layerrule:skills/clawrouter/SKILL.md— added "Phone & Voice (Twilio + Bland.ai)" section after Image & Video, with the full 8-tool table; updated frontmatterdescriptionandtriggersto mention phone capabilities. Without this headline update, AI agents would route around ClawRouter when reasoning about phone tasks even with the partner registry populated — they need to see the capability surfaced where they're already looking.skills/phone/SKILL.md(new) — dedicated reference: full HTTP API for each endpoint, parameter tables, fire-and-forget polling explanation, three example agentic flows (verify-before-text, appointment confirmation, acquire-caller-ID).
- README — new "Phone & Voice Calls" section between Image Editing and Models & Pricing, with the pricing table, slash command + CLI examples, raw
curlHTTP usage, and the same safety guardrail surfaced in the tool description. openclaw.plugin.jsondescription bump — mentions phone + voice capability so the OpenClaw plugin browser surfaces it.- Out of scope (deferred): local recording/transcript download (recordings can be large; returning Bland.ai's hosted URL is sufficient for v1), auto-polling voice-call status to completion in the slash command (user opted for fire-and-forget so the chat experience returns immediately), SMS/MMS (BlockRun hasn't exposed yet), auto-renew on lease expiry (CLI surfaces the warning, user decides).
- Two telemetry bugs surfaced and fixed during real-call smoke testing (placed an actual $0.54 call to
+15707043521via the patched dist; tx0xfe6c6b5e...settled on Base; wallet reconciliation correct: $84.49 → $83.95 = exactly one $0.54 debit). Both bugs were pure logging artifacts — wallet was never wrongly debited — but they would have given misleading numbers inclawrouter statsandclawrouter report. Both fixes consolidated into a new exported pure helperresolvePhoneTelemetryCost(insrc/proxy.ts) with 8 unit tests locking down the gates:- Bug 1 — phantom $0.54 charge on 4xx voice POST. First smoke test POSTed
/v1/voice/callwith empty{}body to exercise routing without spending money. BlockRun returned 400 (Zod validation: "expected string, received undefined"). The wallet wasn't charged, but the telemetry hook sawpaymentStore.amountUsd = 0and fell back toestimatePhoneCost("/v1/voice/call") = $0.54. Stats would record a phantom voice call. Fix: gate the fallback onupstream.statusbeing 2xx — any 4xx/5xx skips the fallback and logs$0. - Bug 2 — GET poll miscounted as another $0.54 voice call. After placing a real call, polling
GET /v1/voice/call/{call_id}for transcript status (free upstream) was being logged at $0.54 because the longest-prefix match onvoice/call/triggered the same fallback row as the initiating POST. Every 30s poll would inflate stats by $0.54. Fix: also gate the fallback onreq.method === "POST"— GET polls log$0. - Refactor: gate logic was originally inline inside
proxyPaidApiRequest. Pulled it out intoresolvePhoneTelemetryCost(args)so the rules are independently testable (the call site is now four lines passing an args bag through the helper). Adds 8 vitest cases covering: paid-amount-wins, 4xx phantom guard, GET poll guard, 5xx guard, missing-method guard, non-phone-passthrough, and the original "successful POST with empty paymentStore → fallback" path. Without the helper extraction, locking these gates in tests would have required a full integration test with a mocked upstream — too heavy for telemetry-only logic.
- Bug 1 — phantom $0.54 charge on 4xx voice POST. First smoke test POSTed
- Tests — new
src/proxy.phone-routing.test.ts(regex matching for /v1/phone/*, /v1/voice/*, /v1/voice/call/{id} poll, plus negative case for /v1/phonebook),src/proxy.phone-pricing.test.ts(longest-prefix matching + the 8resolvePhoneTelemetryCostgate cases above),src/parse-call-args.test.ts(both flag forms, quoted task spans, E.164 first-token detection). Total 31 new test cases; all 569 vitest tests green; typecheck + lint clean. - Smoke test record (free-tier verification before the real call): list-numbers ($0.001) returned an existing wallet-owned number
+15707043521(PA, expires 2026-06-15); lookup ($0.01) on that same number returned full Twilio carrier metadata (type: nonFixedVoip,carrier_name: Twilio - SMS/MMS-SVR); negative test/v1/phonebook/testcorrectly rejected by the partner regex (502 from chat-completion fallback rather than partner routing); CLI table formatting + expiry-warning logic verified byclawrouter phone numbers list.
free/deepseek-v4-prodelisted from the model picker — NVIDIA's V4 Pro deployment has been hung since 2026-04-30 (verified: connection hangs indefinitely, no bytes returned in 300s). The model was still showing in the OpenClaw picker as[Free] DeepSeek V4 Pro, misleading users who selected it into getting V4 Flash via BlockRun's server-side redirect. Fix: removed fromsrc/top-models.json(picker) andBLOCKRUN_MODELSregistry; all aliases that previously pointed at it (free/deepseek-v4-pro,nvidia/deepseek-v4-pro,nvidia/deepseek-v3.2,free/deepseek-v3.2,deepseek-free,deepseek-v4-pro,v4-pro) now redirect directly tofree/deepseek-v4-flashat the ClawRouter level, skipping the double-hop through BlockRun's redirect.free/deepseek-v4-flash(1M context, MMLU-Pro 86.2) remains the active free DeepSeek option. The entry will be restored if and when NVIDIA brings the V4 Pro deployment back online.
/imagegenslash command renamed to/cr-imagegento resolve Telegram channel-command collision (#165). Telegram bot integrations reserve/imagegenfor their own image-gen bots (Hugging Face Spaces et al.), and OpenClaw's runtime emitsPlugin command "/imagegen" conflicts with an existing Telegram commandwhen ClawRouter registered the same name. Theapi.registerCommandatsrc/index.ts:1768now registerscr-imagegenso OpenClaw's command registry no longer fights the channel. Backward compatibility preserved: typing legacy/imagegen <prompt>in chat still works — thesrc/proxy.tschat-prefix interceptor accepts both/cr-imagegenand/imagegen(slice length adjusts to whichever prefix matched). User-facing help text, partner-tool footer, README,docs/image-generation.md, andskills/imagegen/SKILL.mdall updated to lead with the new name while noting the legacy form remains accepted./videogenleft untouched — no collision reported in the field yet, and unnecessary churn is unnecessary churn.
- Dependency refresh: x402 2.9 → 2.11, viem 2.47 → 2.48, openclaw devDep 2026.5.4 → 2026.5.7. Routine in-range upgrade pass — no API breakage, all 531 tests green, typecheck + lint clean. Bumps via
npm update(semver-safe) covered:@x402/core,@x402/evm,@x402/fetch,@x402/svm→ 2.11.0 (the payment-protocol stack; 2.10 + 2.11 are bugfix-only over the 2.9 line we shipped in v0.12.182).viem→ 2.48.11 (Ethereum RPC client used for Base USDC balance checks; themainnet.base.orgRPC failures visible in~/.openclaw/logs/gateway.err.logare external network reliability, not viem bugs — but staying on tip-of-2.x means we pick up any improved retry/timeout logic when it ships).openclaw(devDep) → 2026.5.7 (no plugin API surface changes affecting us; we still declarecompat.minGatewayVersion = 2026.5.2for the strict-validation regime we adapted to in v0.12.184/186).@scure/bip322.0.1 → 2.2.0,prettier3.8.1 → 3.8.3,eslint10.2.0 → 10.3.0,typescript-eslint8.58.1 → 8.59.3,vitest4.1.3 → 4.1.6 — all in-range.
@solana/kitdeliberately held at v5.5.1.npm viewshows v6.9.0 available, but@x402/svm@2.11.0's nested transitive dependency tree still pins to@solana/kit@5.5.1(deduped to a single copy innpm ls). Bumping ClawRouter's top-level pin to v6 would re-introduce the dual-version split that causedtransaction_simulation_failedon Solana payments (root-caused on 2026-03-06; see memoryfeedback_solana_kit_version_split). When@x402/svmupdates its nested pin, we follow — not before.- Test fix for OpenClaw 2026.5.7 dist layout.
test/integration/security-scanner.test.tswas crashing withCannot read properties of undefined (reading 'length')against the new openclaw build. Root cause: 2026.5.7 ships twoskill-scanner-*.jschunks innode_modules/openclaw/dist/— one minified (with mangled exportsa, i, n, r, t) and one with proper names (scanDirectoryWithSummaryet al.). The test'sfiles.find((f) => f.startsWith("skill-scanner"))picked the FIRST one alphabetically (skill-scanner-DP5fYVFn.js, the mangled one), found noscanDirectoryWithSummarynamed export, fell through to "first function export" — which returned the wrong function (something likeclearSkillScanCacheForTest), returningundefined. Fixed by iterating allskill-scanner-*chunks and picking the one that actually exportsscanDirectoryWithSummary. The pre-2026.5.4 "first function export" fallback path is preserved for older builds (Docker e2e harness still tests against the long tail). - No runtime changes; no shipped behavior changes. Pure dependency hygiene + one test-harness fix. Existing users see identical proxy behavior; the upgrade matters mainly for users on bare
npm install -g(who get the newer x402 client when they reinstall) and for Docker/CI environments running the e2e tests against fresh OpenClaw versions.
clawrouter share— convert the most recent assistant response into IM-flavored markdown for paste-and-share. The pain point: OpenClaw renders gorgeous markdown via Warp+SSH, but copy-paste to IM mangles tables /###headings / bold. This is a real community ask — upstream openclaw#7909 "Add plain text copy option" has been OPEN since 2026-02-03 with 4 comments and a volunteer (juliabush) but no merged fix; codex review on 2026-04-30 confirms maintainers haven't given UX direction. ClawRouter sits at a unique vantage point — it sees every response body the model emits — so we can ship a CLI-side fix in days while the upstream UI fix waits. Six IM presets, each tuned to the target dialect:feishu— Lark / 飞书. The headline issue: Feishu desktop renders**bold**, tables, emoji, lists, code blocks correctly, but treats### fooas literal text. Thefeishupreset converts# / ## / ###headings to**bold**and strips---horizontal rules (which Feishu also doesn't render). Markdown tables stay intact (Feishu renders them natively).slack— Slack mrkdwn dialect. Distinct from CommonMark: Slack uses*single-star*for bold (not**double-star**) and_underscore_for italic. Headings →*bold*. Markdown links[text](url)→ Slack's<url|text>syntax.&<>get HTML-entity escaped but not inside the link tokens. Strikethrough~~x~~→~x~. Bullet-→•for visual polish. Tables → fixed-width text inside```code fences (Slack doesn't render markdown tables natively).discord— CommonMark-compatible (Discord supports# ## ###headings since 2023, plus bold/italic/strike/link). The only conversion: tables → fixed-width fenced blocks (Discord doesn't render tables natively).telegram— MarkdownV2. The strict one: any unescaped_*[]()~``>#+-=|{}.!in body text causes the Telegram bot API to reject the message withBad Request: can't parse entities. The preset tokenizes the input, hard-escapes every reserved character in plain-text spans, preserves formatting tokens (*bold*,_italic_,`code`,[text](url)), and packs tables into```pre-blocks (where escaping is unnecessary). Headings →*bold*. Output >4096 chars is split at line boundaries with(i/N)continuation suffix viatransformForTelegramSplit().whatsapp— Same single-star bold + underscore italic dialect as Slack/Telegram. Strikethrough~~x~~→~x~. Links[text](url)→text\nurl(lets WhatsApp auto-preview the URL on its own line). Tables → fenced fixed-width text.plain— Strips all markdown for IMs that render text as-is (WeChat / QQ / iMessage / LINE / Signal). Headings:# Foounderlined with===,## Foounderlined with---(visible hierarchy that survives plaintext),###+ stripped to body. Bold/italic/strike markers removed. Tables converted tolabel: value\nlabel: valuelines (multi-column tables produce header-prefixed blocks separated by blank lines). Links →text (url). Inline code ticks stripped, content kept. Horizontal rules removed.
- The hard parts that needed real care, not just regex sprawl:
- Asterisk dialect collision (Slack/WhatsApp/Telegram). Source has CommonMark
**bold** *italic*, target wants*bold* _italic_. If you naively run "double-star → single-star" first, the next pass's "single-star → underscore" eats the just-converted bold. Fix: extract**bold**into placeholder strings (__CR_PH_BOLD_0__) before italic conversion, then restore as*bold*afterward. Same trick for converting markdown links to Slack's<url|text>so the angle brackets aren't HTML-entity-escaped in the next stage. - Heading conversion ordering. First implementation converted
### foodirectly to single-star*foo*(for Slack/WhatsApp), which then got eaten by the italic regex. Fix: heading regex always emits double-star**foo**, which gets scooped into the bold-protection placeholder along with naturally-occurring bold, and restored to single-star at the end. - Code-fence protection. Two passes around
splitByFences(): first, run table-to-fence conversion only on prose segments (so existing code blocks with stray|characters aren't misparsed as tables); second, re-split the result (the table conversion just generated new fences) and apply per-preset text rules only to prose, never to fence content. Otherwise the bold/italic regex would eat across fence boundaries when tables happen to contain**or*. - CJK column widths. The user's actual content is Chinese — table headers like
指标/数值. CJK characters take 2 monospace columns, not 1. The plain-text table renderer counts visible width by codepoint range (CJK Unified, Hangul, Fullwidth, etc) and pads accordingly so columns stay aligned in non-tabular IMs. - Plain-text horizontal-rule order. First implementation stripped HRs (
^-{3,}$) AFTER adding## foounderlines — those underlines are themselves dashes, so longer headings (≥3 chars) were getting their underlines vaporized. Fix: strip HRs FIRST, add heading underlines second.
- Asterisk dialect collision (Slack/WhatsApp/Telegram). Source has CommonMark
- Persistence:
~/.openclaw/blockrun/responses/responses-YYYY-MM-DD.jsonl. Mirrors the existing usage-log path layout (src/logger.ts). Each JSONL entry:{ id, timestamp, sessionId, model, requestSummary, responseText }. Theidisresp_<ms>_<hex6>so users can refer to specific responses inclawrouter share <id>.requestSummaryis the user's last message truncated to 80 chars, surfaced inshare listso people can identify which response is which. Persistence is fire-and-forget from the request handler — errors are swallowed insideappendResponseso they never affect the request flow. Privacy opt-out: setBLOCKRUN_RESPONSE_STORE=offto disable. (Default on; future v0.12.x release may add a TTL or auto-prune, deliberately deferred until usage signal arrives.) - Hooks into
src/proxy.ts. The chat-completion handler already accumulates the full assistant text intoaccumulatedContentfor the session journal (lines 5219–5221 streaming, 5599 non-streaming). Both branches converge at the journalrecordcall near line 5635 — the response-store append fires immediately after, gated onaccumulatedContent && isChatCompletion. The user-prompt summary is captured up front into a new outer-scoperequestSummaryForStorevariable fromlastUserMsg.content(handles both string and multimodal content arrays). - Four new HTTP routes on the proxy (added next to
/v1/models):GET /share/list?limit=20— paginated metadata index (id, timestamp, model, sessionId, summary, responseLength).GET /share/last?as=<preset>&sessionId=<sid>— most-recent entry, optionally pre-rendered for a preset;sessionIdfilter prefers entries from the same OpenClaw session.GET /share/:id— fetch a specific entry by id.GET /share/:id/render?as=<preset>— fetch + render in one call.
clawrouter shareCLI subcommand:clawrouter share last— render most recent response (default preset =feishu, override withBLOCKRUN_DEFAULT_SHARE_PRESETenv or--as=<preset>), print to stdout, copy to clipboard.clawrouter share list [--limit=20]— recent entries with id, timestamp, model, prompt summary.clawrouter share <id> [--as=<preset>]— render specific entry.clawrouter share last --all— write all 6 preset variants to/tmp/claw-share-<id>-<preset>.txtand print paths (lets users compare side-by-side and pick).
- Cross-platform clipboard with zero new npm dependencies. Spawns the platform-native binary: macOS
pbcopy, Linuxwl-copy/xclip/xsel(probed in order), Windowsclip.exe. If none work, prints a friendly hint and continues — the rendered text is still on stdout so the user can manually copy it. - Test coverage:
src/share-formatters.test.tsadds 58 tests grouped by preset plus integration tests against a real-world equivalent of the user's screenshot (semiconductor-bubble analysis with### 1. 估值已进入极端区域heading + a CJK-content table). Each preset's headline behavior is asserted:feishuconverts###→**,slackdoes the asterisk-dialect dance without corrupting bold-when-italic-is-also-present,discordpreserves###(Discord supports headings),telegramescapes.-(correctly and leaves pre-block content un-escaped,whatsappuses single-star bold + underscore italic,plainstrips everything and produceskey: valuetable renderings. Edge cases: code-block protection (markdown patterns inside```aren't transformed), tables with escaped|, Telegram >4096 split with(i/N)suffix, CJK width calculation. Total test count 457 → 515 (+58), all green; typecheck + lint clean. - What we deliberately did NOT do. No PNG render (would require puppeteer ≈150MB or satori+resvg ≈30MB; the
--allflag plus future Phase 2 hosted share both cover that need without the install bloat). No hosted share-link endpoint (depends on BlockRun server-side/v1/sharework; a future Phase 2). No automatic share-hint injection at the end of every response (would pollute every assistant message; release-notes communication is enough). No IM auto-detection (would require telemetry; user picks via--asor setsBLOCKRUN_DEFAULT_SHARE_PRESET). No upstream OpenClaw PR yet — theshare-formatters.tsmodule is a strict superset of openclaw#7909's plain-text request and is portable; future PR opportunity once we have user signal. - Web search opt-out:
BLOCKRUN_WEB_SEARCH=offenv var ortools.web.search.enabled = falsein~/.openclaw/openclaw.jsonnow respected. Two users (Mark, baconvalley) reportedblockrun-exakeeps reappearing in their config after they edit it out. Root cause:register()calledregisterWebSearchProvider()unconditionally andinjectModelsConfig()flippedenabledback totrueon every plugin load — so any user opt-out got clobbered. AddedisBlockrunWebSearchDisabled()helper consulted at both sites: when disabled,register()skips registration (so OpenClaw's auto-detect won't pick blockrun-exa as the active provider) andinjectModelsConfig()leavesenableduntouched on disk. The legacy-provider-stripping migration from v0.12.186 still runs regardless — that's correctness against OpenClaw's known-providers validator, not opt-in. Log lineBlockRun web search disabled (BLOCKRUN_WEB_SEARCH=off or tools.web.search.enabled=false)confirms the opt-out took effect.docs/configuration.mdupdated. 16 new unit tests insrc/web-search-disable.test.tscovering env precedence over config, case-insensitive matching, defensive nesting against malformedtools.web.search; total test count 515 → 531. - Repository hygiene: removed 5 stale root-level smoke scripts (
final-test.mjs,test-auto-connection.mjs,test-config-changes.mjs,test-profiles.mjs,test-routing-changes.mjs— superseded bysrc/**/*.test.tssince v0.12.79) plus the long-deadblockrun-clawrouter-0.8.25.tgzpackage artifact.AGENTS.md(untracked, byte-identical toCLAUDE.md) also removed. Net −659 lines from the repo.
- Predexon v2 spec alignment. BlockRun shipped Predexon v2 today (commit
ffa22d4 refactor(predexon): align endpoint registry with Predexon v2 spec) — adds 9 new endpoints, changes the path shape of 3 wallet endpoints, and retirespolymarket/wallet/identities-batch(the old GET-with-csv form falls through to the wildcard route, harmless if hit). Total endpoint count: 48 → 57. Confirmed live against prod viacurl https://blockrun.ai/api/v1/pm/{markets,markets/listings,sports/categories,sports/markets,polymarket/markets/keyset,polymarket/wallet/identity/0xabc,outcomes/abc}— all return 402 ✓;POST polymarket/wallet/identitieswith{addresses:[..]}body also 402 ✓. Trading API (a separate Predexon spec) intentionally not exposed — confirmed with @1bcMax. Changes in ClawRouter:blockrun_predexon_endpoint_calldescription refreshed insrc/partners/registry.ts: full 57-endpoint catalog grouped as Polymarket Tier 1 / Polymarket Tier 2 wallet analytics / Polymarket Wallet Identity (v2 paths) / Cross-venue canonical (v2:markets,markets/listings,outcomes/{predexon_id}) / Sports (v2:categories,markets,markets/{game_id},outcomes/{predexon_id}) / Kalshi / Limitless·Opinion·Predict.Fun / dFlow / Binance Futures / Matching. Keyset pagination variants (polymarket/markets/keyset,polymarket/events/keyset) and trade-activity (polymarket/activity,polymarket/markets/{tokenId}/volume,polymarket/markets/{conditionId}/open_interest) listed too.- POST + body support added to the tool runner (
src/partners/tools.ts): two new optional paramsmethod('GET' default, 'POST' for bulk identities) andbody(JSON object as string, e.g.'{"addresses":["0x1","0x2"]}'). GET + query unchanged. POST defaults body to{}when unspecified. Method validated to'GET'|'POST'only. Body parses through JSON.parse with cause-attached error. - Wallet identity v2 path shapes propagated to the description:
/pm/polymarket/wallet/identity/{wallet}(path param, was?wallet=),POST /pm/polymarket/wallet/identities(replacesidentities-batch; body shape{addresses:[..]}, ≤200),/pm/polymarket/wallet/{address}/cluster(path param, was?wallet=). skills/predexon/SKILL.mdFull Endpoint Reference rewritten: 57 rows organized by category, marks POST endpoint, notes "Responses are raw upstream JSON (no{ data: ... }wrapper)" — the wrapper was removed in BlockRun commit4530941("fix: remove { data } wrapper from Predexon proxy response, return raw upstream JSON"); our skill had been silently telling agents to readresponse.dataeven though prod stopped wrapping. Fixed.skills/clawrouter/SKILL.mdcount refresh: "57 endpoints (Predexon v2)" + endpoint_call row updated to mentionmethod+bodyparams.
- No Trading API exposure.
polymarket/trades,kalshi/trades,dflow/trades,polymarket/orderbooksetc. are historical/read-only data endpoints, not trading interfaces. No order placement, no signing, no transaction submission — confirmed withgrepover the registry. - Unit-tested the new dynamic branch with a mock-fetch harness: GET+query assembles URL params, POST+body sets request body, path-param substitution works on
/pm/polymarket/wallet/identity/{wallet}, keyset paths route correctly, DELETE method rejected, malformed-JSON body rejected. 457 vitest tests pass; typecheck + lint clean.
- Predexon agent tool surface expanded from 8 → 9 tools, covering the full 48-endpoint catalog. ClawRouter previously exposed only 8 named
predexon_*tools to LLM agents (events, leaderboard, markets, smart_money, smart_activity, wallet, wallet_pnl, matching_markets) — but BlockRun's source-of-truth (predexon.ts) and the marketing site atblockrun.ai/marketplace/predexonalready list 48 endpoints across Polymarket Tier 1 (markets/events/orderbooks/candlesticks/leaderboard/cohorts/top-holders/UMA oracle), Polymarket Tier 2 wallet analytics (PnL/positions/profiles/filter/smart-money/identity/cluster), Kalshi/Limitless/Opinion/Predict.Fun (markets + orderbooks each), dFlow (trades + wallet), Binance Futures (candles + ticks), and cross-platform matching/search. The existing 8 named tools stay (well-tuned for the most common paths); a newblockrun_predexon_endpoint_callis added as a catch-all withpath+queryparams and the full endpoint directory in its description (LLMs read this as the schema'sdescriptionfield). Skill files (skills/predexon/SKILL.md+skills/clawrouter/SKILL.md) updated to point at the new tool — the 48-row reference table in the predexon skill was already complete. - Tool runner extended for dynamic-path services (
src/partners/tools.ts): whenservice.proxyPath === "/pm/__dynamic__"the runner readspathfrom args (validated to start with/pm/and reject..traversal), parsesqueryas JSON, and assembles the URL. Existing fixed-path tools are unaffected. - OpenClaw devDep bumped
^2026.4.21→^2026.5.4;minGatewayVersionbumped2026.4.5→2026.5.2. This is the version where strict provider/baseHash validation shipped; we now declare compat with the regime we've adapted to instead of pretending to support older permissive runtimes. - Fixed the v0.12.185 deferred follow-up: ClawRouter no longer mutates
tools.web.search.{provider,enabled}onapi.config(runtime) or~/.openclaw/openclaw.json(disk) inside the plugin install path. Root cause discovered via Docker e2e on a clean OpenClaw 2026.5.4 image: OpenClaw runs a strict known-providers validator ontools.web.search.providerat TWO points — (a) config-load time beforeregister()runs, and (b)replaceConfigFilewhen the install commit persists the runtime config to disk. Both rejectblockrun-exabecause the validator's known-providers list is independent of plugin registrations, causingunknown web_search provider: blockrun-exaand install rollback. Fix:- Removed the disk write of
providerininjectModelsConfig(previouslysrc/index.ts:449–457). Wrote a forward-migration in its place: whenprovider === "blockrun-exa"is found on disk, it's deleted on the next file write — picked up automatically byclawrouter setup --forceWriteor first gateway start. - Removed all runtime writes to
api.config.tools.web.search.*insideregister(). Earlier attempts gated them ontypeof api.registerWebSearchProvider === "function", but OpenClaw 2026.5.4 still auto-injects the registered provider id during install commit. Net: ClawRouter'sregister()only callsapi.registerWebSearchProvider(blockrunExaWebSearchProvider)and lets OpenClaw's auto-detection pick it up via "Auto-detected from available API keys if omitted" (per OpenClaw schema). tools.web.search.enabled = trueis set only via the file-write path ininjectModelsConfig(gated to gateway mode or--forceWrite), so it lands on disk without touching the validator-flaggedproviderfield.- Migration in install scripts (
scripts/update.sh,scripts/reinstall.sh) strips legacyprovider: blockrun-exaBEFORE runningopenclaw plugins install. Combined with the in-config migration, existing v0.12.185 users are cleaned up via either path. - The deactivate hook (
src/index.ts:2043) already removes the field on uninstall — kept as belt-and-suspenders.
- Removed the disk write of
- Test fix:
test/integration/security-scanner.test.tspreviously found the scanner via "first function export" heuristic, which worked when OpenClaw minified its names. The 2026.5.4skill-scanner-*.jschunk re-exports under proper names, so the heuristic returned the wrong function (one ofclearSkillScanCacheForTest/isScannable/scanDirectory/scanSource) and the test crashed on undefined fields. Test now prefers thescanDirectoryWithSummarynamed export, falling back to "first function" for older builds. - New Docker e2e harness:
test/docker-install/Dockerfile.openclaw-2026.5+run-openclaw-e2e.shbuild a clean Debian + Node 22 + OpenClaw 2026.5.4 image and exercise the full install flow — fresh install on empty config,clawrouter setup, validator collision repro, migration + reinstall. All assertions pass on this fresh path. Run withdocker buildthendocker run --rm. - Net behavior on OpenClaw 2026.5.4: clean install with no validator failures;
clawrouter setupno longer needs to work around the web_search collision (still useful for barenpm install -gusers to sync allowlist). Existing v0.12.185 users withprovider: blockrun-exaon disk get cleaned up automatically byscripts/update.sh/scripts/reinstall.shbefore install runs. - Edge case noted (out of scope for this fix): re-running
openclaw plugins install --forceafter a previously failed install on a setup-populated config triggers an OpenClaw 2026.5.4 internal auto-injection that re-emitsprovider: blockrun-exaand trips its own validator. The triggering log line[plugins] Forced web_search provider to blockrun-exadoes not appear in any deployed file (verified via exhaustivefind / | xargs grepin the Docker container) — it's emitted from somewhere inside the OpenClaw runtime not reachable from a clean filesystem search. Not ascripts/update.shflow, no user impact in normal upgrades.
clawrouter setup— new CLI command for users who installed via barenpm install -g. A user reported/modelsin their Telegram bot showing only 7 entries despite having@blockrun/clawrouter@0.12.184installed and the gateway restarted. Investigation: barenpm install -g @blockrun/clawrouterputs the package on disk and adds theclawrouterbinary to PATH but performs zero OpenClaw integration — noplugins.entries.clawrouterregistration, no models allowlist sync, no auth profile injection. The user's bot showed OpenClaw's hardcoded fallback default models (which includegpt-5-nanoandgemini-2.5-flash— neither in ourtop-models.json) instead of our 38-entry list. Confirmed by reproducing locally on OpenClaw 2026.5.2 (8b2a6e5):npm install -galone leavesmodels listshowing 1 default entry; onlyopenclaw plugins install @blockrun/clawroutertriggers ourregister()callback.- Fix:
clawrouter setupruns the missing integration steps:- Detect
openclawon PATH (refuse to proceed if missing). openclaw plugins install --force @blockrun/clawrouterto register the plugin.- Direct call to
injectModelsConfig({ forceWrite: true })andinjectAuthProfile()to populateagents.defaults.models(the 38-entry allowlist),models.providers.blockrun.models(picker),tools.web.search.provider = "blockrun-exa", andagents/<id>/agent/auth-profiles.jsonwith theblockrun:defaultplaceholder. - Tell the user to
openclaw gateway restartto pick up the new plugin code.
- Detect
- Resilient against OpenClaw 2026.5.2's stricter validation: 2026.5.2 added a
tools.web.search.providervalidator that rejectsblockrun-exauntil that provider is actually registered (chicken-and-egg: we register it inside our plugin, but validation runs on the openclaw.json file before plugin code executes). When this trips, OpenClaw rolls back its install record. The setup command continues anyway and runs the manual config sync — even if registration didn't stick, the user's openclaw.json gets the full 38-entry allowlist, and the bot will see all models on next gateway start. A warning prints suggesting a manualopenclaw plugins install --force @blockrun/clawrouterretry post-gateway-start if needed. injectModelsConfiggained anoptions.forceWriteparameter (src/index.ts:214). Defaultfalsepreserves the v0.12.184 deferred-write behavior for plugin-activation hooks;forceWrite: trueis only used by the newsetupCLI command since it's an explicit user action outside any install transaction. Plugin lifecycle paths (theregister()callback atsrc/index.ts:1602) keep the unconditional defer.- Both
injectModelsConfigandinjectAuthProfileare now exported from the package entry (src/index.ts:2074) so the CLI can call them directly without re-implementing the logic. - README updated with explicit guidance on the two install paths: A1 (
curl … clawrouter-install.sh | bash— recommended) and A2 (npm install -g … && clawrouter setup— required two-step). The pure-npm path now has a prominent warning that skippingsetupcauses the 7-models symptom. - End-to-end verified locally:
clawrouter setupran against my own~/.openclawpopulatedagents.defaults.modelswith 39blockrun/*entries (vs the prior partial state); themodels.providers.blockrun.modelspicker plane synced to 39 too; auth profile written. Hit OpenClaw 2026.5.2's web_search validation as expected, but the manual sync ran around it.
Followup (deferred): OpenClaw 2026.5.2's tools.web.search.provider validator running before plugin activation is a structural mismatch — we register blockrun-exa inside our plugin, but validation expects the provider to be known statically. Either OpenClaw needs to relax this check post-plugin-load, or ClawRouter should declare the web_search provider via the plugin manifest rather than at runtime. Tracked separately; today's setup workaround unblocks users.
- Plugin install no longer crashes OpenClaw with
ConfigMutationConflictError. v0.12.183 fixed the install script soopenclaw plugins install --force @blockrun/clawrouteractually executes instead of bouncing on "plugin already exists". But once the install proceeded, OpenClaw 2026.5.2 crashed insidecommitPluginInstallRecordsWithConfig→replaceConfigFile→assertBaseHashMatches: ClawRouter's plugin activation hook (injectModelsConfig) reads~/.openclaw/openclaw.jsondirectly from disk and writes it back atomically (viatmp + rename) during activation. OpenClaw's install flow holds a baseHash on that exact file from before activation; when our hook bumped the hash, OpenClaw's own commit step refused to write its install record, threw, and the install rolled back. Two fixes in two releases, same user, same Vultr box, same rollback banner — no progress. - Fix:
injectModelsConfignow skips the disk write when not in gateway mode (isGatewayMode()returns false duringopenclaw plugins install,openclaw plugins list, etc. — only true foropenclaw gateway start/restart/stop). The in-memory mutations still compute, the info logs still print, but thewriteFileSync(tmpPath) + renameSync(configPath)is deferred. The same hook re-runs on firstopenclaw gateway start(gateway mode = true, no install transaction in flight) and persists the changes cleanly there. New log line:Deferring config write to first gateway start (outside gateway mode). - No regression on the gateway path. The guard at
src/index.ts:477only short-circuits whenprocess.argvdoes not containgateway. Sanity-tested locally: started clawrouter vianode dist/cli.js, hit/v1/chat/completionswithfree/gpt-oss-120b, returned 200 in 0.6s — same as v0.12.183. - Why this didn't surface before today: OpenClaw 2026.5.2 (commit
8b2a6e5, the version on the field-reporting Vultr box) added theassertBaseHashMatchesstrict check insidereplaceConfigFile. Earlier OpenClaw versions silently allowed plugin-side disk writes to clobber the install transaction; the conflict went unnoticed because the install record was lost but the plugin still appeared installed. With the new strict check, the conflict surfaces as a hardConfigMutationConflictErrorand the install genuinely rolls back. The bug has been latent ininjectModelsConfigsince v0.12.176 (when active config writes from this hook were introduced); it only became user-visible with OpenClaw 2026.5.2. - No
scripts/changes — no blockrun re-deploy required. The fix is insrc/index.ts, bundled into the v0.12.184 npm tarball. The install script atblockrun.ai/clawrouter-install.shis already correct as of v0.12.183; running it again now pulls the new tarball, plugin activation skips the conflicting write, OpenClaw commits its install record, gateway starts cleanly.
- Install/update scripts no longer roll back when the plugin is already installed.
scripts/update.sh:321andscripts/reinstall.sh:422ranopenclaw plugins install @blockrun/clawrouterwithout--force. On any machine where the plugin already lives at~/.openclaw/npm/node_modules/@blockrun/clawrouter(i.e. every existing user running an upgrade), OpenClaw rejects the install withplugin already exists: ... (delete it first)and a non-zero, non-124 exit code. The script's|| { ... exit $exit_code; }guard then fires, the EXIT trap rolls back to the prior install (✗ Reinstall failed. Restoring previous ClawRouter install...), and the user is silently stranded on the version they had — never reaching the new release. - Fix: both shell scripts now invoke
openclaw plugins install --force @blockrun/clawrouter. Per OpenClaw's own error message ("rerun install with--forceto replace it"),--forceis the documented and idempotent way to handle both fresh-install and upgrade flows. Applied at all four call sites (timeout-wrapped + non-timeout paths in each script). - PowerShell counterpart
scripts/update.ps1already uses a different approach — it manuallynpm packs +Remove-Item -Recurse -Forcethe plugin dir + extracts (lines 112-129), bypassingopenclaw plugins installentirely. No bug there, no change needed. - Field reproduction: a Vultr-hosted user attempted to update to v0.12.182 and saw the rollback banner. Without the manual workaround
openclaw plugins update @blockrun/clawrouter, they would have stayed on v0.12.181 indefinitely — defeating every prior fix in this session (image polling, predexon SKILL sync, reasoning-aware timeout). - Note for users currently stranded: this fix lives on npm
@blockrun/clawrouter@0.12.183but reaches users only vianpm install -g,openclaw plugins update, or the self-hostedblockrun.ai/clawrouter-install.sh. The self-hosted install script copy atblockrun/public/clawrouter-install.shshould be re-synced from this release before the next user attempts an upgrade — until that sync, a user pulling the install script via curl from blockrun.ai will still hit the broken behavior.
- Reasoning models no longer get aborted before they emit their first token.
PER_MODEL_TIMEOUT_MSwas hard-coded to 60s for every model. Reasoning/thinking-mode models (o-series, GPT-5 reasoning, Claude opus thinking, Gemini Pro, Grok reasoning, DeepSeek V4 Pro / reasoner, Kimi K2.x, Qwen3-thinking, etc. — 37 IDs total flagged withreasoning: trueinBLOCKRUN_MODELS) routinely take 60–120s to produce the first token on a cold cache. ClawRouter was firing the per-attempt abort right at the moment the model was about to start streaming, so a hard-pinned reasoning model would 100% time out, andauto-routed reasoning fallbacks chained more reasoning timeouts back-to-back. End user surfaces this asLLM request failed: network connection errorfrom the agent's HTTP client. - Fix: per-attempt timeout is now model-aware:
REASONING_MODEL_TIMEOUT_MS = 180_000(3 min) for any model withreasoning: truePER_MODEL_TIMEOUT_MS = 60_000(unchanged) for everything elsetimeoutForModel(id)helper looks up the flag fromBLOCKRUN_MODELS(computed once into a Set at module init for O(1) lookup)- All three AbortController setup sites updated: primary attempt loop (
src/proxy.ts:4694), explicit-pin retry (src/proxy.ts:4827), and 429 backoff retry (src/proxy.ts:4897).
DEFAULT_REQUEST_TIMEOUT_MS180s → 300s (5 min). The global deadline now leaves headroom for one reasoning attempt (180s) + a non-reasoning fallback (60s) + on-chain settlement (~30s buffer). Was 180s, which would have collided exactly with a single reasoning attempt and starved fallback.- Heartbeat path unchanged. Streaming requests already get an immediate
: heartbeat\n\nfollowed by 2s-cadence keep-alive (src/proxy.ts:4378-4389). Non-streaming clients can't be helped by heartbeats over HTTP/1.1; they need to extend their own client-side HTTP timeouts (or switch to streaming). - Diagnosed in the field: a Telegram bot user reported
LLM request failed: network connection errorafter pinning their default model toclawrouter/free/deepseek-v4-pro. Reproduced locally on v0.12.181 with $36 balance: V4 Pro upstream took >30s for first token, client-side curl--max-time 30gave up, and ClawRouter's 60s per-model abort would have fired at 60s if the upstream hadn't returned by then. New 180s window covers normal V4 Pro cold-start. (Today V4 Pro is also experiencing an upstream NIM outage that's unrelated to this fix;autoprofile correctly routes around it to other free models.)
- Main
clawrouterSKILL caught up to multi-venue scope. v0.12.180 expanded the dedicatedpredexonSKILL to BlockRun's 49-endpoint registry, but the headlineclawrouterSKILL (the one OpenClaw and AI agents read first to decide whether ClawRouter is relevant) still said "Polymarket prediction market data" + "8 tools, Polymarket ↔ Kalshi". That description would have steered agents away from prediction-market questions about Kalshi/Limitless/Opinion/Predict.Fun, UMA resolution status, and wallet identity — even though the proxy and the predexon SKILL handle them. - Updates:
- Front-matter
description: now lists Polymarket, Kalshi, Limitless, Opinion, Predict.Fun, dFlow + UMA oracle + wallet identity & clustering — so the discovery layer matches the actual capability. - Section
### Polymarket (Predexon)→ renamed### Prediction Markets (Predexon). Body rewritten as a 4-bucket summary (Markets & trading, Leaderboard & smart money, Wallet analytics, UMA oracle + wallet identity) with 49-endpoint count and accurate pricing tiers. Pointer to the dedicatedpredexonskill for the full reference.
- Front-matter
- No code changes, no other SKILLs changed. The
predexonskill itself was already complete in v0.12.180. Pure visibility/triage fix on the headline SKILL.
- Predexon skill catches up to BlockRun's 49-endpoint registry. BlockRun shipped 10 new prediction-market endpoints on 2026-05-03 (commits
9640528+a06c652, prod revisions00442-jqfand00443-45g); ClawRouter's/v1/pm/*catch-all whitelist already proxied them silently, butskills/predexon/SKILL.mddocumented none — so OpenClaw users and AI agents using the skill couldn't discover them. - New endpoints documented:
- Cross-venue search —
markets/search?q=...($0.005) — single call across Polymarket, Kalshi, Limitless, Opinion, Predict.Fun - Other venues markets list —
limitless/markets,opinion/markets,predictfun/markets($0.001 each) — closes the prior gap where only orderbooks were exposed - UMA oracle resolution —
polymarket/uma/markets?state=...andpolymarket/uma/market/{conditionId}($0.001 each) — track proposal/dispute/resolution lifecycle - Wallet identity & clustering —
polymarket/wallet/identity?wallet=...,polymarket/wallet/identities-batch?wallets=...(GET, not POST — upstream docs are wrong),polymarket/wallet/cluster?wallet=...($0.005 each) - Per-token candlesticks —
polymarket/candlesticks/token/{tokenId}($0.001) — OHLCV for a single outcome token (sibling to the existing market-levelcandlesticks/{conditionId})
- Cross-venue search —
- SKILL.md additions: 4 new section blocks (Search Across All Venues, Other Venues, UMA Oracle Resolution Status, Wallet Identity & Clustering), 5 new example interactions, 10 new rows in the endpoint reference table (36 → 46 documented; 3 long-standing gaps from BlockRun's 49 —
polymarket/activity, per-market volume, open_interest — deliberately left for a follow-up). Front-matterdescriptionand 8 new triggers for the new categories (limitless / opinion markets / predict.fun / uma oracle / wallet identity / wallet cluster / cross-venue search). - No code changes. Proxy whitelist (
src/proxy.ts:2669) already matches/v1/pm/*; no new path needed. Pure docs/skill release.
- Slow image generation no longer silently breaks.
openai/gpt-image-2(and any future model whose generation exceeds BlockRun's 30s inline window) returns202 + { id, poll_url, poll_instructions }fromPOST /v1/images/generations. ClawRouter previously took that 202 body and replied to the client with200 OK+ the queued-job stub — nodataarray, no images, no error signal. The client (OpenClaw, SDK callers, curl) saw "success" with nothing usable. - Fix: mirror the existing video polling loop into
/v1/images/generations. After the initialpayFetchPOST, if the response is 202 withpoll_url, ClawRouter now pollsGET /v1/images/generations/{id}every 3s (after a 2s warmup) for up to 5 minutes — exactly the pattern used for/v1/videos/generationssince 2026-04-23. Onstatus=completedthe response is rewritten to the final{ data: [...] }body and flows through the same image-saving / localhost-rewrite path as fast models. Onfailed→ 502 with details. On 5min timeout → 504 (no payment settled — server only settles on first completed poll). Client still sees a single blocking POST. /v1/images/image2imagedeliberately untouched. BlockRun'simage2imageroute has no[id]poll endpoint and noINLINE_GEN_TIMEOUT— it's fully synchronous server-side, so there's no 202 path to handle. Adding speculative polling there would be dead code.- No payment-flow change.
payFetchhandles wallet signing for the initial POST and each subsequent poll GET; BlockRun's[id]route binds the job to the payer wallet and settles idempotently on the first completed poll, identical to the video flow.paymentStore.amountUsdstill reflects the verified-then-settled amount forlogUsage.
- DeepSeek V4 Pro added to REASONING fallbacks (auto + eco). Backend shipped
deepseek/deepseek-v4-pro(1.6T MoE / 49B active, 1M context — strongest open-weight reasoner; MMLU-Pro 87.5, GPQA 90.1, SWE-bench 80.6, LiveCodeBench 93.5) at $0.50 in / $1.00 out per 1M under the 75% promo through 2026-05-31 (list $2.00/$4.00 after). Wired intoauto.tiers.REASONING.fallbackafterdeepseek-reasoner/grok-4-fast-reasoningand intoeco.REASONING.fallbackafterdeepseek-reasoner. V4 Flash thinking (deepseek-reasoner, $0.20/$0.40) stays primary because it's cheaper; V4 Pro is the harder-task escape hatch. - DeepSeek chat/reasoner now V4 Flash semantics.
deepseek/deepseek-chatanddeepseek/deepseek-reasoner(already in tier configs) had their upstream rerouted to V4 Flash non-thinking / thinking modes — repriced from $0.28/$0.42 to $0.20/$0.40 with 1M context (was 128K). No SDK source change needed — pricing fetched from/v1/modelsat runtime; tier configs got comment refresh to note the V4 Flash repricing. deepseek/deepseek-v4-proadded totop-models.jsonso the OpenClaw/modelpicker surfaces the new flagship.- No
FREE_MODELSchanges.nvidia/gpt-oss-120bandnvidia/gpt-oss-20bwere briefly delisted 2026-04-28 but re-enabled 2026-04-30 withavailable: true+hidden: true— they no longer appear in/v1/models(so the picker hides them) but ClawRouter'sFREE_MODELSset still uses them as the historical free defaults; direct calls work.
- Picker actually filtered now via the right layer. v0.12.175 + v0.12.176 both targeted
cfg.models.providers.blockrun.models, but per v0.11.8's checked-in design (src/index.ts:379), the OpenClaw/modelpicker is whitelisted bycfg.agents.defaults.models— that's the canonical filter. The path-based-plugin install case (where users install ClawRouter from a local checkout viainstallPath = sourcePath = ...) never runsscripts/update.sh/scripts/reinstall.sh, so the install-script prune-and-add never fires.injectModelsConfiginsrc/index.tsonly added entries — never pruned — so retired models accumulated forever in the allowlist. - Fix:
injectModelsConfignow actively syncsblockrun/*allowlist entries to TOP_MODELS exactly — adds missing AND removes stale. Mirrors the install-script behavior so plugin-load-only users (no install-script flow) get correct picker visibility on next OpenClaw restart. Non-blockrun/*entries (other providers like OpenRouter) are preserved. /v1/modelsHTTP endpoint deliberately unchanged — keeps the full ~175-entry list including aliases, so API-level discovery and/model <alias>resolution stay open. Filter only applies to picker UI.- v0.12.175 + v0.12.176 changes retained as defense-in-depth:
buildProviderModelsstill returnsVISIBLE_OPENCLAW_MODELS, andindex.tsstill writesVISIBLE_OPENCLAW_MODELStocfg.models.providers.blockrun.models. Even though the picker filter is allowlist-driven, keeping these aligned costs nothing.
- Picker filter v0.12.175 didn't actually take effect. Root cause:
src/index.tsindependently writescfg.models.providers.blockrun.modelsat plugin startup (lines 293, 331, 1582), and it referenced the unfilteredOPENCLAW_MODELS(~175 entries) — so on every plugin activate it overwrote any pruned array with the full list, completely bypassing the v0.12.175 fix atbuildProviderModels. Users updating to v0.12.175 still saw 50–58+ entries becauseindex.tsre-injected the full set right after my filter ran. - Fix:
src/index.tsnow importsVISIBLE_OPENCLAW_MODELSand writes that tocfg.models.providers.blockrun.modelsat all three injection points (provider config injection, validation refresh, runtime port re-injection). The validation logic also gained a "stale superset" check — if the on-disk array contains IDs NOT inVISIBLE_OPENCLAW_MODELS, it triggers a rewrite to actively shrink the array (was previously additive-only). This means existing users with stale 159+ entry arrays get their picker auto-pruned on first plugin activate after upgrading. - No registry, alias, or routing changes.
OPENCLAW_MODELS(full set) remains the resolution layer for proxy routing and alias matching; only the picker-advertisement layer (provider.modelsgetter +index.tswrites) is filtered.
- Picker filter actually works now. v0.12.173's
top-models.jsontrim was supposed to slim the OpenClaw/modelpicker but didn't, because the picker reads fromcfg.models.providers.blockrun.models— populated by ClawRouter'sprovider.modelsgetter (src/provider.ts:43) →buildProviderModels()(src/models.ts:1163) — which returned the FULLOPENCLAW_MODELSarray (~175 entries: 68 BLOCKRUN_MODELS + 107 ALIAS_MODELS).top-models.jsononly droveagents.defaults.models(a separate allowlist that controls "which models can be set as default", NOT what shows in the picker). Net effect for users on v0.12.173/v0.12.174: their picker still showed 50–58+ entries including long-retired models (gpt-5.2,gpt-4.1,o1,o1-mini,o3-mini,nvidia/kimi-k2.5,xai/grok-2-vision,free/nemotron-ultra-253b, etc.). - Fix:
buildProviderModelsnow filtersOPENCLAW_MODELSthrough aTOP_MODELS_SETderived fromsrc/top-models.json. Picker drops to ~38 visible entries on next OpenClaw refresh of the provider models. NewVISIBLE_OPENCLAW_MODELSexport insrc/models.tsis the canonical "what the picker advertises" list. - /v1/models HTTP endpoint deliberately unchanged — still returns the full ~175-entry list for API-level discovery (per Your Majesty's original v0.12.173 intent: "hide from list, but still callable"). Direct ID + alias resolution unaffected; router fallbacks unaffected; proxy routing unaffected.
- Migration note for existing users: OpenClaw merges, never deletes, from
cfg.models.providers.blockrun.models. So users who installed v0.12.174 or earlier still have their old 159-entry array on disk; they'll need either a fresh OpenClaw plugin re-install (which re-readsprovider.models) or manual openclaw.json cleanup. Future install/update scripts should add a prune step here, similar to the existingagents.defaults.modelsprune — tracked as a follow-up.
profile=autoandprofile=agenticMEDIUM-tier primary swapped from Kimi K2.5 → K2.6. Per-call cost on these MEDIUM routes goes from $0.60/$3.00 → $0.95/$4.00 — that's +58% on input tokens, +33% on output tokens for default-profile users whose classifier returns MEDIUM. The decision deliberately reverses v0.12.170's "tier primaries unchanged pending K2.6 retention/IQ data" stance. The trigger: BlockRun hid K2.5 from its public UI on 2026-04-28 (commitbfbdedf) and we hid it from ClawRouter's picker in v0.12.173, so the trajectory toward server-side K2.5 retirement is clear. Promoting K2.6 now is future-proofing — if BlockRun pulls K2.5 server-side later, every MEDIUM call would otherwise 400 → fallback-second-choice silently, which is harder to debug than a clean primary that is already on the still-supported model.- Cost-stability opt-out: users who prefer K2.5's pricing can pin
model: "moonshot/kimi-k2.5"directly (or use thekimi-k2.5alias). K2.5 stays inBLOCKRUN_MODELS, the alias map, and is now wired in as the first fallback in bothautoTiers.MEDIUMandagenticTiers.MEDIUMchains — so even on the auto path, if K2.6 has an infra hiccup the next attempt is K2.5 (same model, same cost as the v0.12.173 default). Profilesecoandpremiumare unaffected (eco MEDIUM =gemini-3.1-flash-lite, premium SIMPLE was already K2.6). - Registry, picker, and other tier primaries unchanged. Both Kimi versions remain in
src/models.ts,src/top-models.jsonis identical to v0.12.173, and no other auto/agentic/eco/premium primaries moved. The two known "hidden but still primary" inconsistencies (autoTiers.SIMPLE=google/gemini-2.5-flash,agenticTiers.SIMPLE=openai/gpt-4o-mini) are tracked but deferred — they don't have the same urgency signal (BlockRun hasn't pulled them from its UI).
- Picker decluttered: 12 superseded long-tail models hidden from OpenClaw
/modelUI.src/top-models.jsontrimmed from 50 → 38 entries. Hidden:anthropic/claude-opus-4.5,openai/gpt-5.3,openai/gpt-5-mini,openai/gpt-5-nano,openai/gpt-4o,openai/gpt-4o-mini,openai/o3,openai/o4-mini,google/gemini-2.5-pro,google/gemini-2.5-flash,google/gemini-2.5-flash-lite,moonshot/kimi-k2.5. Picker count drops from "55 available" to ~43 once users runclawrouter updateor reinstall. - No callability regression and no fallback impact. This is a UX-only change:
BLOCKRUN_MODELSregistry,MODEL_ALIASES, andsrc/router/config.tsfallback chains are all untouched. Direct calls (model: "openai/gpt-4o") and aliases (gpt,gpt4,mini,o3,gemini,flash,kimi-k2.5,nvidia/kimi-k2.5,anthropic/claude-opus-4-5,minimax-m2.5) continue to resolve and route normally. The/v1/modelsHTTP endpoint still advertises all 175 entries (registry + aliases) for API-level model discovery — only the OpenClaw picker is filtered. openai/gpt-5.3-codexdeliberately kept visible. The codex variant is treated as a distinct developer-targeted entry and stays in the picker.minimax/minimax-m2.5already absent fromtop-models.json(onlyminimax/minimax-m2.7was listed); no action needed and theminimax-m2.5alias still works.
- Three new free NVIDIA-hosted models added. BlockRun refreshed the free catalog on 2026-04-29 with three additions, all wired into ClawRouter as
free/-prefixed entries:free/deepseek-v4-pro— 1.6T MoE / 49B active, 1M context, MMLU-Pro 87.5, GPQA 90.1, SWE-bench 80.6, LiveCodeBench 93.5. NIM ~150 tok/s on Blackwell. Strongest free reasoning model.free/deepseek-v4-flash— 284B / 13B active MoE, 1M context, ~5x faster than v4-pro. Strong on chat/summarization (MMLU-Pro 86.2). Weaker factual recall (SimpleQA 34% vs Pro's 58%) — pick v4-pro for fact-heavy agentic loops.free/nemotron-3-nano-omni-30b-a3b-reasoning— 31B / 3.2B active MoE, 256K context. First vision-capable free model in the catalog. Accepts text, images, video (up to 2min), audio (up to 1hr). ChartQA 90.3, DocVQA 95.6, MMMU 70.8.
free/deepseek-v3.2phased out in favor offree/deepseek-v4-pro(strict-superset replacement: same family, larger context, higher benchmarks). Removed fromBLOCKRUN_MODELS,FREE_MODELSset,top-models.jsonpicker, README pricing table, and SKILL.md model list. Aliases kept and redirected:nvidia/deepseek-v3.2,free/deepseek-v3.2, anddeepseek-freenow all resolve tofree/deepseek-v4-proso existing pins continue to work and silently get the upgrade.gpt-oss-120b/gpt-oss-20bdeliberately kept as defaults despite BlockRun's 2026-04-28 retirement (available:falseserver-side). Heavy user demand outweighs the source-of-truth alignment for these specific IDs —free/nvidia/gpt-120b/gpt-20baliases all still resolve tofree/gpt-oss-120b(or 20b),FREE_MODELconstant still points atfree/gpt-oss-120b, andecoTiers.SIMPLEprimary stays unchanged. ClawRouter's existing fallback-chain logic handles any 400 ("Model not available") from BlockRun by trying the next chain entry, so failures degrade gracefully rather than break user workflows.- New shorthand aliases for the additions:
deepseek-v4-pro,deepseek-v4-flash,v4-pro,v4-flash,nemotron-omni,nano-omni,vision-free— chosen to mirror BlockRun's bare-name aliases atroute.ts:639-640plus avision-freediscovery shortcut for the new vision-capable model. ecoTiers.SIMPLEfallback chain extended with the three new free models (mistral-small, deepseek-v4-flash, qwen3-next) inserted before the paid Gemini fallbacks, so eco-profile users get more all-free chain depth before paid models kick in. Primary is unchanged (free/gpt-oss-120b).- Provider routing safety note. BlockRun's
NVIDIA_MODEL_MAPinsrc/lib/ai-providers.ts:2094-2111does NOT have explicit entries for the 3 new models, butcallOpenAICompatiblefalls through to the bare model name (modelMap[k] || k), so ClawRouter sendingnvidia/deepseek-v4-proreaches NVIDIA NIM as baredeepseek-v4-pro— which is what NIM expects. Documented in the BLOCKRUN_MODELS comment block insrc/models.ts. If BlockRun later adds explicit map entries with different upstream names, this side needs no change. - Net free-model count: 8 → 10 (8 originals + 3 added - 1 phased out). README badge, tagline, "Quick Start" sections, and SKILL.md description all updated to reflect "10 free NVIDIA models". Pricing table in README adds three new rows in benchmark order.
- Test fixtures.
src/router/strategy.test.tsMODEL_PRICINGmap gains entries for the 3 new free models. No assertion changes anywhere else — gpt-oss-120b stays the asserted default insrc/exclude-models.test.ts,src/models.test.ts,test/fallback.ts, andtest/integration/exclude-models.test.ts.
- Bare
kimi/moonshotaliases now resolve to Kimi K2.6. BlockRun hid Kimi K2.5 from its public model UI on 2026-04-28 (commitbfbdedf) and now features K2.6 as the Moonshot flagship. ClawRouter's local alias map followed the old direction and still pointedkimiandmoonshotat K2.5, which created a quiet drift from the source-of-truth registry: agents asking for "kimi" got the previous-gen model while BlockRun's homepage advertised K2.6. The aliases now resolve tomoonshot/kimi-k2.6and a new barekimi-k2alias is added for the same target. Users who explicitly pinnedkimi-k2.5continue to get K2.5 — the explicit pin is preserved as a cost-stability opt-in ($0.60/$3.00 vs K2.6's $0.95/$4.00). NVIDIA-hosted K2.5 (retired 2026-04-21) still redirects tomoonshot/kimi-k2.5. - Routing tier primaries deliberately unchanged.
autoTiers.MEDIUMandagenticTiers.MEDIUMcontinue to anchor onmoonshot/kimi-k2.5. Promoting them to K2.6 would silently raise per-call cost +58% on input / +33% on output for every default user — that's a separate decision tracked outside this release, ideally with measured retention/IQ data on K2.6 vs K2.5.premiumTiers.SIMPLEwas alreadymoonshot/kimi-k2.6and is unchanged. Net effect: behavior shift is opt-in via thekimialias /kimi-k2shorthand, not forced through default routing. - Doc and test fixture refresh. README's profile-overview table now shows
kimi-k2.6in the PREMIUM column (matchingdocs/routing-profiles.mdandsrc/router/config.ts:1134).src/router/strategy.test.tsgains a K2.6 pricing fixture so cost-calc tests stay honest if K2.6 ever appears in test scenarios.src/proxy.models-endpoint.test.tsnow asserts bothkimi-k2.6andmoonshot/kimi-k2.6are discoverable through the/modelsendpoint.test/fallback.ts's "Unknown model" example list leads withmoonshot/kimi-k2.6.
- Synthesize structured
tool_callsfrom XML/text formats some models emit incontent. Earlier tool-call hardening (v0.12.165, v0.12.166) handled the case where upstream returned a structuredtool_callsarray (or signaledfinish_reason: "tool_calls") and the model also leaked planning prose intocontent. This release closes a third gap where upstream returns no structured tool calls at all and the model's actual tool invocations live as XML/text insidecontent— typical when a downstream client (OpenClaw is the visible offender) prompt-engineers tool instructions instead of sending a structuredtools[]schema, so the model dutifully honors the prompt format and emits the call as text. Two formats observed in the wild are now recognized and converted to OpenAI-shapedtool_calls:- OpenClaw-style —
<tool_call>NAME<arg_key>K1</arg_key><arg_value>V1</arg_value>...<arg_key>Kn</arg_key><arg_value>Vn</arg_value></tool_call>. Requires at least onearg_key/arg_valuepair so prose like<tool_call>name</tool_call>in documentation does not mis-fire. Surfaced via a real ClawRouter→OpenClaw session where the agent emitted six identical<tool_call>web_search<arg_key>...</arg_key>...blocks in 60 seconds, none executed, then hallucinated "I need a Brave API key" as the failure explanation. - Anthropic-style —
<function_calls><invoke name="NAME"><parameter name="K">V</parameter>...</invoke></function_calls>. Reproduction confirmed Moonshot Kimi K2.6 emits this format when given prompt-engineered tool instructions without a structuredtools[]schema. - Values are best-effort coerced via
JSON.parseso<arg_value>5</arg_value>becomes5(number) and<arg_value>true</arg_value>becomestrue(boolean); strings that don't parse stay as strings. Synthesized IDs are OpenAI-shaped (call_<base64url>). - Wired into both response paths: the SSE conversion path (
src/proxy.ts:5081+) and the non-streaming JSON path (src/proxy.ts:5325+). When extraction succeeds,contentis blanked,message.tool_callsis populated, andfinish_reasonflips to"tool_calls"— matching exactly the shape downstream tool executors already handle from the v0.12.165/166 paths. - New module
src/textual-tool-calls.tsplussrc/textual-tool-calls.test.ts(13 unit tests) and four new integration tests insrc/proxy.tool-forwarding.test.tscovering OpenClaw format / non-streaming, OpenClaw format / SSE, Anthropic format / non-streaming, and a negative test (plain prose passes through unchanged withfinish_reason: "stop").
- OpenClaw-style —
/modelpicker allowlist now lives insrc/top-models.json(single source of truth, loaded bysrc/top-models.ts). PreviouslyinjectModelsConfig()insrc/index.tscarried a literal array that drifted from the install scripts'TOP_MODELS(which carry their own copies inscripts/reinstall.sh+scripts/update.sh). The JSON file is the version anyone actually edits going forward; both runtime (src/index.ts) and the test suite (src/top-models.test.ts) read from it. The install scripts still carry their own embedded copies because they run before npm dependencies are resolved — but now there's one canonical list to copy from when adding a new model.- Alias adds.
br-sonnet→anthropic/claude-sonnet-4.6(matching the existingbr-partner shorthand pattern), andgpt5now resolves toopenai/gpt-5.5instead ofopenai/gpt-5.4(following v0.12.167's GPT-5.5 promotion as BlockRun's newest visible flagship).
-
Propagate
openai/gpt-5.5everywhere it should appear. v0.12.167 added the model toBLOCKRUN_MODELS, thegpt-5.5alias, and the install-scriptTOP_MODELSallowlist — but every other place ClawRouter advertises a flagship still pointed atgpt-5.4. This release closes the gap so 5.5 is a first-class citizen across routing, the picker, marketing, and the OpenClaw skill page.-
src/router/config.ts— three fallback-chain insertions, no primary changes.openai/gpt-5.5slots in immediately beforeopenai/gpt-5.4inauto.COMPLEX.fallback,premiumTiers.COMPLEX.fallback, andagenticTiers.COMPLEX.fallback. Both stay reachable; 5.5 gets preference when the chain reaches OpenAI. Comments updated so 5.5 is "newest flagship — 1M+ ctx, native agent + computer use" and 5.4 is "previous flagship — benchmarked at 6,213ms, IQ 57". Tier primaries are unchanged: promoting 5.5 to a primary slot needs measured latency/IQ data, which we don't have yet — that's a separate decision tracked outside this release. -
src/index.ts—/modelpicker allowlist updated.src/index.tscarries its own copy ofTOP_MODELS(separate from the install scripts' identical-but-distinct list — both populate the OpenClaw allowlist depending on install path). Addedopenai/gpt-5.5andanthropic/claude-opus-4.5(also missed in v0.12.167'sBLOCKRUN_MODELSadd for opus-4.5), and replaced the now-deprecatedminimax/minimax-m2.5withminimax/minimax-m2.7so the picker matches the deprecation we landed yesterday. -
README.md— Premium Models pricing table. Added theopenai/gpt-5.5row at $5.00/$30.00 per 1M tokens (~$0.0175 per 0.5K-in-0.5K-out request), 1M context, full feature set. Placed betweenclaude-opus-4.6($0.0150) ando1($0.0375) so the table stays sorted by approximate $ /request. -
skills/clawrouter/SKILL.md— model list line. The "55+ models including..." line now leadsgpt-5.5, gpt-5.4, ...and includesclaude-opus-4.5alongside 4.7/4.6.
-
-
Files deliberately not touched:
docs/smart-llm-router-14-dimension-classifier.mdanddocs/llm-router-benchmark-46-models-sub-1ms-routing.mdare frozen benchmark archives — adding 5.5 to a benchmark table without measured numbers would falsify the document. Theposts/*.mdmarketing content is similarly point-in-time. Those will be refreshed if/when 5.5 gets benchmarked.
-
Realign the model registry to BlockRun source-of-truth. Audit found three drifts where ClawRouter's
BLOCKRUN_MODELStable didn't match whatblockrun/src/lib/models.tsactually exposes. The server is the source of truth for which models exist and what they cost; the proxy's local view should mirror that 1:1 so cost estimation, the/modelpicker, and routing tier selection all see the same world the server does.-
Add
openai/gpt-5.5. BlockRun's newest visible OpenAI flagship — first fully retrained base since GPT-4.5, 1M+ context, 128K output, native agent + computer use. Pricing $5/$30 per 1M tokens. Added toBLOCKRUN_MODELS, thegpt-5.5alias, and theTOP_MODELSallowlist in both install scripts. Routing tiers insrc/router/config.tscontinue to anchor ongpt-5.4because that's what's benchmarked; users can pin5.5explicitly. Routing change is a separate decision. -
Add
anthropic/claude-opus-4.5as a distinct model. Previously ClawRouter'sMODEL_ALIASESsilently rewroteanthropic/claude-opus-4.5to4.7, making 4.5 unreachable through ClawRouter even though BlockRun lists it as a separate visible model with its own pricing and 200K context (vs 4.6/4.7's 1M). Removed the alias, added 4.5 toBLOCKRUN_MODELSwith its real 200K/32K shape, and added ananthropic/claude-opus-4-5(dashed) alias for the slug variant. Test insrc/models.test.tswas codifying the old upgrade-to-4.7 behavior — flipped to assert the pin is preserved end-to-end. -
Mark
minimax/minimax-m2.5deprecated → fallbackminimax/minimax-m2.7. BlockRun retired m2.5 entirely (only m2.7 is in theirMODELStable). ClawRouter still listed both; m2.5 now flips todeprecated: truewith the m2.7 fallback so existing pins keep working. -
scripts/reinstall.sh+scripts/update.sh: dropminimax/minimax-m2.5from theTOP_MODELSpicker allowlist (still reachable, just hidden from the picker) and addopenai/gpt-5.5+anthropic/claude-opus-4.5.
-
Add
- Tool-call planning prose suppressed even when
finish_reasonis the only signal (thanks @0xCheetah1, #162). Follow-up to v0.12.165's #161 fix. Live Telegram/OpenClaw testing caught one more shape the planning-prose leak could wriggle through: some upstreams (Moonshot Kimi K2.6 again) mark a turn withfinish_reason: "tool_calls"without exposingmessage.tool_calls/delta.tool_callsat the same inspection point. The #161 gate (toolCalls.length > 0) saw no array and let the prose through. The gate is nowendsWithToolCalls || toolCalls.length > 0— applied consistently across the non-streaming JSON path and the SSE emission path, plus the finish-reason override in the SSE terminal chunk. Two new regression tests insrc/proxy.tool-forwarding.test.ts— one per response shape — lock the behavior in: a response withfinish_reason: "tool_calls"and no tool_calls array has itscontentblanked and thetool_callsfinish_reason preserved. User-visible impact: fewer "I should look up X before replying" preambles sneaking into agent chat surfaces for turns that are supposed to be pure tool invocations.
- Tool-call planning prose no longer leaks to chat surfaces (thanks @0xCheetah1, #161). Some OpenAI-compatible providers — Moonshot's Kimi K2.6 was the visible offender through OpenClaw Telegram — return
{ content: "The user wants the current time. I should call get_current_time with Chicago.", tool_calls: [...] }. Tool execution only needstool_calls; thecontentfield is internal planning that the upstream should have hidden behind a<think>tag but didn't. ClawRouter now suppressescontentwhenevertool_calls.length > 0, in both the non-streaming JSON response path and the SSE-conversion path that clients like OpenClaw hit withstream: true. Tool execution is unaffected; only the user-visible planning prose goes away. Covered by two regression tests insrc/proxy.tool-forwarding.test.ts(one per response shape). - Plugin restart loop killed.
injectModelsConfig()insrc/index.tswrites ClawRouter-owned keys into~/.openclaw/openclaw.jsonon every plugin load. OpenClaw's config watcher has a catch-all rule — any change with no matching plugin-declared prefix triggers a full gateway restart — somcp.servers.blockrunwrites kept ping-ponging the gateway. The plugin definition now exposesreload: { noopPrefixes: ["mcp.servers.blockrun"] }(new optional field onOpenClawPluginDefinition) to tell OpenClaw's loader that ClawRouter self-manages that prefix. Silently ignored on OpenClaw runtimes that predate thereloadfield. - Dedup + response cache now isolate streaming and non-streaming callers. Discovered while adding the SSE regression test for the tool-call fix: a
stream: truerequest that followed an identical-bodystream: falserequest was gettingcontent-type: application/jsoninstead oftext/event-stream. Two compounding bugs. ClawRouter rewritesparsed.stream = falsebefore the upstream call (BlockRun API doesn't support streaming), and bothRequestDeduplicator.hash(body)andResponseCache.generateKey(body)ran AFTER that rewrite — so astream:trueandstream:falserequest hashed identically. Worse,response-cache.ts'snormalizeForCacheexplicitly strippedstreamfrom the key with the comment "we handle streaming separately" (it never did). Fix: (1) prefix bothdedupKeyandcacheKeyinsrc/proxy.tswith the originalisStreamingintent ("sse:"vs"json:"), so the two shapes never share a cache slot; (2) stop strippingstreaminnormalizeForCache. Latent bug — real-world impact was small because the exact scenario (identical body, different stream flag, within 30s/10min TTL) is rare in practice — but a correctness bug nonetheless. Regression test added (isolates dedup cache between streaming and non-streaming requests with identical bodies); the existingresponse-cache.test.tsexpectation was inverted (it was codifying the broken behavior).
-
Video generation switched to async submit + poll (tracks BlockRun server commit 654cd35). The server-side
/v1/videos/generationsendpoint no longer blocks for the full 60–180s upstream generation — POST now returns202 { id, poll_url }in ~3–20s, and a separate GET on thepoll_url(same x-payment header) returns202while the job is queued/in_progress and200with the final video on completion. Server settles only on the first completed poll, so upstream failure or caller disconnect = zero USDC charged. ClawRouter's proxy handler insrc/proxy.tsnow collapses this back into a single blocking POST for the client: submit upstream, poll thepoll_urlevery 5s (initial 3s grace) up to a 5-min deadline, then backup + serve locally as before. Legacy sync-shaped server responses still work — the handler checks forpoll_urlbefore switching to the poll loop. Client-side timeouts bumped:buildVideoGenerationProvider.timeoutMs200s → 330s;/videogenslash 200s → 330s; both sit above the 5-min internal poll deadline so the lastdata[0].urlfinishes streaming back. User-facing impact: same blocking POST as before, but Cloudflare's 100s edge timeout no longer kills long-running Seedance 2.0 jobs. -
Image/video plumbing parity — four exposure surfaces now match the backend. The BlockRun server has supported 8 image models (DALL-E 3, GPT Image 1, Nano Banana / Pro, Flux 1.1 Pro, Grok Imagine / Pro, CogView-4) and 4 video models (Grok Imagine, Seedance 1.5 Pro / 2.0 Fast / 2.0) since v0.12.162, but the ClawRouter client exposed them inconsistently:
buildImageGenerationProviderinsrc/index.tsonly advertised 4 image models. OpenClaw's native image picker couldn't see Flux, Grok Imagine (×2), or CogView-4 — the only way to hit them was raw curl with an explicitmodelfield. Themodelsarray now lists all 8; defaultModel switched fromopenai/gpt-image-1togoogle/nano-banana(cheapest general-purpose default);capabilities.geometry.sizesadds CogView-4's 512x512, 768x768, 768x1344, 1344x768, 1440x1440 sizes;capabilities.edit.enabledflipped totrueso OpenClaw's edit UI surfaces gpt-image-1's/v1/images/image2imagepath.MODEL_ALIASESinsrc/models.tshad zero image/video shortcuts. All 140+ aliases were LLM chat models. Added 17 new aliases soresolveModelAlias("dalle")→openai/dall-e-3,"flux"→black-forest/flux-1.1-pro,"seedance"→bytedance/seedance-1.5-pro, plusbanana,banana-pro,nano-banana-pro,gpt-image,flux-pro,grok-imagine/-pro,grok-video,cogview,seedance-1.5,seedance-2,seedance-2-fast./imagegenand/videogenslash commands now actually exist. README documented/imagegen a dog dancing on the beachas if it worked, but no such command was ever registered — it was silent drift from the aspirational README. Both commands now register viaapi.registerCommand, accept--model=<alias>,--size=WxH,--n=<int>,--duration=<5|8|10>flags (parsed by a sharedparseGenArgshelper), resolve aliases throughresolveModelAlias, POST to the proxy's/v1/images/generationsand/v1/videos/generationsendpoints, and return inline markdown () or video URLs. 402 responses surface as "top up with/wallet" hints; video timeout is 200s to cover upstream polling./img2imgremains README-only for now — will land in a follow-up.- Partner framework now includes image/video as LLM-callable tools. Added three new
PartnerServiceDefinitionentries insrc/partners/registry.ts—image_generation,image_edit,video_generation— so the existingbuildPartnerTools→api.registerToolpipeline surfaces them asblockrun_image_generation,blockrun_image_edit,blockrun_video_generationtools. Agents can now tool-call image/video from chat without the skill layer guessing at raw HTTP shapes.
-
Dropped the Twitter/X user-lookup partner. We no longer run X data as a product surface. Removed
x_users_lookupfromPARTNER_SERVICES, deleted theskills/x-api/skill directory, and strippedx|from the/v1/(?:x|partner|pm|...)/paid-route regex insrc/proxy.ts(so/v1/x/*no longer short-circuits to the partner proxy — it now falls through to the usual chat-completion path or 404s cleanly). Server-side/v1/x/*endpoints are still live atblockrun.ai/apifor any existing integrations; only the client wiring is retired. -
/partners+clawrouter partnersCLI output compressed ~4×. Previously 6 lines per service (name, full agent-facing description, tool name, method, pricing block, blank) × 17 services ≈ 100 lines of wall-of-text, which is what @vicky was calling out as "读不了" (unreadable).PartnerServiceDefinitiongained two fields —category("Prediction markets" / "Market data" / "Image & Video") andshortDescription(≤ 40 chars) — driving a new grouped, column-aligned one-liner per tool. The longdescriptionfield stays intact for the LLM-facing JSON Schema (agents still see "Call this ONLY when..." guidance). Output is now ~25 lines, one screen.
- README leads with the free tier. Post-v0.12.160 the product story changed — 8 NVIDIA models free forever, no wallet required to start — but the README still opened "fund your wallet" as step 2 of Quick Start and buried the free tier in a single line at the bottom. Rewrites so the free tier is the hook, not a footnote: hero tagline adds "8 models free, no crypto required. No signup. No API key. No credit card." plus a 🆓 shields.io badge; the "Why ClawRouter exists" list opens with "Starts at $0"; the comparison-vs-others table adds a "Free tier" row showing ClawRouter's "8 models, no signup" against OpenRouter's rate limits and LiteLLM/Martian/Portkey's "no"; Quick Start gets a "No wallet? 8 models work free out of the box" callout and reframes step 2 as optional; routing-profiles table adds
/model freeat 100% savings; the Costs section lists the current 8 free model IDs by name (was a stale 11-model list referencing the retired Nemotron Ultra / Mistral Large / Devstral). This release is README-only — code is identical to v0.12.162 — version bump exists so the updated marketing reaches the npmjs.com package page and the clawhub marketplace listing.
-
ByteDance Seedance video models wired into the client. BlockRun server has exposed three Seedance models since late April —
bytedance/seedance-1.5-pro($0.03/sec),bytedance/seedance-2.0-fast($0.15/sec, ~60–80s gen time), andbytedance/seedance-2.0Pro ($0.30/sec) — all 720p, text-to-video + image-to-video, 5s default and up to 10s. The/v1/videos/generationsproxy passthrough insrc/proxy.tsalready forwarded anymodelvalue untouched, so actual USDC charges were always correct (server dictates the amount in its 402 response andpayment-preauth.tscaches the server-sentPaymentRequired, not a local estimate — charges never depended on ClawRouter's local pricing table). Three client-side gaps were fixed anyway:-
Usage telemetry was wrong for Seedance.
estimateVideoCostinsrc/proxy.tsonly knewxai/grok-imagine-video, so every Seedance request logged$0.42/cliptologUsageregardless of what the user was actually billed — skewing/usageoutput, savings %, and journal cost fields.VIDEO_PRICINGnow carries all four models at real server rates. -
OpenClaw's native video UI only saw one model.
buildVideoGenerationProviderinsrc/index.tsadvertisedmodels: ["xai/grok-imagine-video"], so users of the UI picker couldn't pick Seedance at all; the only path was raw curl with an explicitmodelfield. Themodelsarray now lists all four, and provider capabilities widen tomaxDurationSeconds: 10/supportedDurationSeconds: [5, 8, 10]to cover both vendors' ranges (server still validates per-modelmaxDurationSeconds, so invalid combos return a clean 400). -
README docs only mentioned Grok. Video-generation section now lists all four models in the table, swaps the curl example to
bytedance/seedance-2.0-fast(sweet-spot price/quality), and makes the upstream-polling note vendor-neutral instead of xAI-specific.
-
Usage telemetry was wrong for Seedance.
-
Docs: fixed proxy port in free-models guide. Thanks to @Bortlesboat (#160) for catching
4402→8402typos indocs/11-free-ai-models-zero-cost-blockrun.md. The rest of the repo,src/config.ts(DEFAULT_PORT = 8402), and all other docs have always said 8402; that one guide was sending new users at the wrong local port.
- De-Gemini the Anthropic-primary fallback chains. When Anthropic hiccups (503s, capacity), Gemini's own "high demand" 503s correlate with the same events — agents fall back from Claude to Gemini together, both overloaded. Reordered
src/router/config.tsfallback arrays in the two places Anthropic sits primary:premiumTiers.COMPLEX(claude-opus-4.7 primary) andagenticTiers.COMPLEX(claude-sonnet-4.6 primary). New order: in-family Anthropic hot swap (opus-4.6 / sonnet-4.6) → xAI Grok (independent infra, strong on complex + tool use) → Moonshot Kimi K2.6 / K2.5 (separate Moonshot infra) → OpenAI flagship (slow but reliable) → DeepSeek (cheap reliable) →free/qwen3-coder-480b(NVIDIA free ultimate backstop). Gemini removed entirely from both chains. Other Anthropic-primary tiers (premiumTiers.REASONING,agenticTiers.REASONING) already had no Gemini and were not touched.
- Free-tier catalog realigned with BlockRun server (13 → 8 NVIDIA free models). BlockRun retired five NVIDIA free models on 2026-04-21 (
nemotron-ultra-253b,nemotron-3-super-120b,nemotron-super-49b,mistral-large-3-675b,devstral-2-123b) and introduced two new ones benchmark-validated at 114–116 tok/s (qwen3-next-80b-a3b-thinking— fastest free reasoning;mistral-small-4-119b— fastest free chat). ClawRouter now exposes the same 8 visible free models:gpt-oss-120b,gpt-oss-20b,deepseek-v3.2,qwen3-coder-480b,glm-4.7,llama-4-maverick,qwen3-next-80b-a3b-thinking,mistral-small-4-119b. Retired IDs still resolve locally viaMODEL_ALIASESredirects to successors (free/nemotron-*→free/qwen3-next-80b-a3b-thinking,free/mistral-large-3-675b→free/mistral-small-4-119b,free/devstral-2-123b→free/qwen3-coder-480b), matching server-side behavior so stale user configs keep working. Touched:BLOCKRUN_MODELS+MODEL_ALIASESinsrc/models.ts,FREE_MODELSset insrc/proxy.ts, free-model list insrc/index.tspicker,MODEL_PRICINGfixture insrc/router/strategy.test.ts,scripts/update.sh+scripts/reinstall.shTOP_MODELS+ slash-command help, README Budget Models pricing table + Free tier note, skills/clawrouter/SKILL.md description + Available Models section. - Kimi K2.5 routing inverted: Moonshot direct is now primary. NVIDIA-hosted
nvidia/kimi-k2.5was retired 2026-04-21 (slow throughput) and redirects server-side tomoonshot/kimi-k2.5. ClawRouter mirrors this:moonshot/kimi-k2.5is the primary entry (no deprecation flag, full 16K output),nvidia/kimi-k2.5retained but markeddeprecated: truewithfallbackModel: "moonshot/kimi-k2.5". Aliaseskimi/moonshot/kimi-k2.5/nvidia/kimi-k2.5all resolve tomoonshot/kimi-k2.5. Router tier configs insrc/router/config.ts(auto + premium + agentic profiles, 7 occurrences) updated to point at the Moonshot variant.
- Market data tools — BlockRun gateway now exposes realtime and historical market data; ClawRouter wires them into OpenClaw as 6 first-class agent tools so the model stops scraping finance sites. Paid ($0.001 via x402, same wallet as LLM calls):
blockrun_stock_priceandblockrun_stock_historyacross 12 global equity markets (US, HK, JP, KR, UK, DE, FR, NL, IE, LU, CN, CA). Free (no x402 charge):blockrun_stock_list(ticker lookup / company-name search),blockrun_crypto_price(BTC-USD, ETH-USD, SOL-USD, …),blockrun_fx_price(EUR-USD, GBP-USD, JPY-USD, …),blockrun_commodity_price(XAU-USD gold, XAG-USD silver, XPT-USD platinum). Tool schemas advertise market codes, session hints (pre/post/on), and bar resolutions (1/5/15/60/240/D/W/M). Path routing extended: the partner-proxy whitelist insrc/proxy.tsnow matches/v1/(?:x|partner|pm|exa|modal|stocks|usstock|crypto|fx|commodity)/, routing all new paths throughproxyPaidApiRequest(payFetch handles 402 when present, passes through 200 for free categories). Tool definitions added insrc/partners/registry.ts;skills/clawrouter/SKILL.mdgains a "Built-in Agent Tools" section listing market data + X intelligence + Polymarket alongside the LLM router.
- SKILL.md data-flow + key-storage transparency — second-pass fix for the OpenClaw scanner on clawhub.ai. After v0.12.157 cleared the original scanner concerns (opaque credentials, implied multi-provider keys, no install artifact), a deeper rescan surfaced three new, more nuanced flags: (1) prompts go to blockrun.ai as a data-privacy risk not obvious from a "local router" framing, (2) wallet private-key storage location/encryption undocumented, (3) users may expect strictly-local routing. All three addressed: (a) description frontmatter and body lead reframed as "Hosted-gateway LLM router" + "This is not a local-inference tool" with explicit Ollama pointer for users who need local-only, (b) new Data Flow section with ASCII diagram + enumerated sent/not-sent lists + link to https://blockrun.ai/privacy, (c) new Credentials & Local Key Storage section documenting config file locations per OS (
~/.config/openclaw,~/Library/Application Support/openclaw,%APPDATA%\openclaw),0600POSIX permissions, plaintext storage parity with other OpenClaw provider keys, encryption guidance (FileVault/LUKS/BitLocker or burner wallet), and asrc/wallet.tssource pointer for key-derivation auditing, (d) new Supply-Chain Integrity section withnpm packverification instructions and tagged-release invariant from the release checklist.
- SKILL.md credential transparency — rewrote
skills/clawrouter/SKILL.mdto clear the OpenClaw scanner's medium-confidence suspicious verdict on clawhub.ai. Frontmatter now declaresrepository: https://github.com/BlockRunAI/ClawRouter,license: MIT, and a structuredmetadata.openclaw.installarray (kind: node,package: @blockrun/clawrouter,bins: [clawrouter]) so the registry entry has an auditable install artifact instead of a bare bash block. Body adds a Credentials & Data Handling section fully enumerating whatmodels.providers.blockrunstores (walletKey/solanaKey— auto-generated locally, never transmitted;gateway/routing— non-sensitive), and explicitly states the plugin does not collect or forward third-party provider API keys (OpenAI/Anthropic/Google/DeepSeek/xAI/NVIDIA) — the blockrun.ai gateway owns those relationships and routes on the server side. Addresses the three scanner flags (opaque credential declaration, implied multi-provider credential collection, no install artifact for review) raised against v0.12.156 on https://clawhub.ai/1bcmax/clawrouter.
-
Kimi K2.6 added — Moonshot's new flagship (
moonshot/kimi-k2.6, 256K context, vision + reasoning, $0.95 in / $4.00 out per 1M) registered inBLOCKRUN_MODELSwithkimi-k2.6alias. Added to the curated/modelpicker list (src/index.ts,scripts/update.sh,scripts/reinstall.sh), the README pricing table,docs/routing-profiles.md, and the AI-agent-facing model catalog inskills/clawrouter/SKILL.md. Premium routing tier (blockrun/premium) now uses K2.6 as the SIMPLE primary and as a fallback in MEDIUM/COMPLEX, withnvidia/kimi-k2.5retained as the first fallback for reliability. The generickimi/moonshotaliases still resolve tonvidia/kimi-k2.5(matches BlockRun server'sblockrun/kimistance); users opt in to K2.6 explicitly viakimi-k2.6orblockrun/premium. -
GitHub restored as canonical source — BlockRunAI GitHub org is back.
package.jsonrepository.url, README badges, CONTRIBUTING clone URL,openclaw.security.json, all docs (anthropic-*,clawrouter-cuts-*,clawrouter-vs-openrouter,11-free-ai-models,llm-router-benchmark-*,smart-llm-router-14-dimension-classifier,subscription-failover,troubleshooting),skills/release/SKILL.md, and thesse-error-formatregression-test comment now point atgithub.com/BlockRunAI/ClawRouter. GitLab mirror (gitlab.com/blockrunai/ClawRouter) is kept as a secondary remote for redundancy but is no longer advertised. Metadata + docs only; no runtime/code changes.
-
Docs: video generation endpoint — README now documents
POST /v1/videos/generationswithxai/grok-imagine-video($0.05/sec, 8s default). The proxy handler, cost estimator (estimateVideoCost), and local-file download path were already in place inproxy.ts; only the README was missing. -
Docs: Grok Imagine image models — README image table now includes
xai/grok-imagine-image($0.02) andxai/grok-imagine-image-pro($0.07), already wired into the image pricing map.
-
Claude Opus 4.7 flagship — BlockRun API has promoted
anthropic/claude-opus-4.7to flagship (1M context, 128K output, adaptive thinking; $5/$25 per 1M tokens). Added toBLOCKRUN_MODELS, now the primary for theCOMPLEXrouting tier across default/premium profiles and the new cost-savingsBASELINE_MODEL_ID. Aliases:opus,opus-4,anthropic/opus,anthropic/claude-opus-4, andanthropic/claude-opus-4.5now resolve to 4.7. Explicit 4.6 pins (opus-4.6,anthropic/claude-opus-4-6) still route to 4.6, which the server keeps available. Opus 4.7 is also added to the curatedTOP_MODELSpicker list anddoctorcommand. Opus 4.6 ClawRouter metadata updated to match server specs (1M/128K, was stale at 200K/32K).
- Repository URL fixed —
package.jsonrepository.urlnow points atgitlab.com/blockrunai/ClawRouter. The previous value (github.com/BlockRunAI/ClawRouter) has been dead since the GitHub org was banned 2026-04-15. Metadata-only bump; no code changes.
- Stop bundling blockrun-mcp — ClawRouter no longer auto-injects
mcp.servers.blockruninto~/.openclaw/openclaw.json. Thenpx -y @blockrun/mcp@latestspawns were leaking shell-wrapper + node grandchildren processes on the host (see reports of 70+ orphaned processes accumulating). Removal of the injection call is matched by a one-shot migration that strips any previously managedmcp.servers.blockrunentry the next time the gateway starts. User-definedblockrunMCP entries are preserved. Restart your gateway after upgrading to free any already-leaked processes. Users who still want the MCP bridge can opt in manually:openclaw mcp add blockrun npx -y @blockrun/mcp@latest.
- Predexon tools registered — 8 Predexon endpoints now registered as real OpenClaw tools (
blockrun_predexon_events,blockrun_predexon_leaderboard,blockrun_predexon_markets,blockrun_predexon_smart_money,blockrun_predexon_smart_activity,blockrun_predexon_wallet,blockrun_predexon_wallet_pnl,blockrun_predexon_matching_markets). Agent will now call these directly instead of falling back to browser scraping. - Partner tools GET support —
tools.tsexecute function now handles GET endpoints with query params and path param substitution (:wallet,:condition_id, etc.).
- Skill priority fix —
predexonandx-apiskills now explicitly instruct the agent not to use browser/web_fetch for these data sources, ensuring the structured API is always used over scraping.
- Predexon skill — New vendor skill ships with ClawRouter: 39 prediction market endpoints (Polymarket, Kalshi, dFlow, Binance, cross-market matching, wallet analytics, smart money). OpenClaw agents now auto-invoke this skill when users ask about prediction markets, market odds, or smart money positioning.
- Partner proxy extended —
/v1/pm/*paths now route through ClawRouter's partner proxy (same as/v1/x/*), enabling automatic x402 payment for all Predexon endpoints vialocalhost:8402.
-
Free model cost logging — Usage stats incorrectly showed non-zero cost for free models (e.g.
free/gpt-oss-120bshowed $0.001 per request due to theMIN_PAYMENT_USDfloor incalculateModelCost). Free models now logcost: $0.00andsavings: 100%, accurately reflecting that no payment is made.
/doctorchecks correct chain balance — Previously always checked Base (EVM), showing $0.00 for Solana-funded wallets. Now callsresolvePaymentChain()and usesSolanaBalanceMonitorwhen on Solana. Shows active chain label and hints to run/wallet solanaif balance is empty on Base.- Strip thinking tokens from non-streaming responses — Free models leaked
<think>...</think>blocks in non-streaming responses.stripThinkingTokens()was only applied in the streaming path — now also runs on non-streaming JSON responses. - Preserve OpenClaw channels on install/update —
reinstall.shandupdate.shnow backup~/.openclaw/credentials/beforeopenclaw plugins installand always restore after, preventing WhatsApp/Telegram channel disappearance.
- Blog section in README — 6 blog posts linked from the repo, including "11 Free AI Models, Zero Cost".
- BRCC ecosystem block — Replaced SocialClaw with BRCC (BlockRun for Claude Code) in the README ecosystem section.
blockrun.ai/brcc-installshort link — Redirect for BRCC install script.
- 11 free models — GPT-OSS 20B/120B, Nemotron Ultra 253B, Nemotron Super 49B/120B, DeepSeek V3.2, Mistral Large 3, Qwen3 Coder 480B, Devstral 2 123B, GLM 4.7, Llama 4 Maverick. All free, no wallet balance needed.
/model freealias — Points to nemotron-ultra-253b (strongest free model). All 11 free models individually selectable via/modelpicker.- New model aliases —
nemotron,devstral,qwen-coder,maverick,deepseek-free,mistral-free,glm-free,llama-free, and more (16 total).
- Skills not found by OpenClaw agents — Auto-copies bundled skills (imagegen, x-api, clawrouter) to
~/.openclaw/workspace/skills/on plugin registration. FixesENOENTerrors when agents invoke/imagegen. - Internal
releaseskill excluded — No longer installed to user workspaces. - Sync package-lock.json
- Skills not found by OpenClaw agents — Agents tried to read skill files (imagegen, x-api, etc.) from
~/.openclaw/workspace/skills/but ClawRouter only bundled them inside the npm package. Now auto-copies all user-facing bundled skills into the workspace directory on plugin registration. SupportsOPENCLAW_PROFILEfor multi-profile setups. Only updates when content changes. FixesENOENT: no such file or directoryerrors when agents invoke/imagegen. - Internal
releaseskill excluded — The release checklist skill is for ClawRouter maintainers only and is no longer installed to user workspaces. - Sync package-lock.json — Lock file was stuck at v0.12.69, now matches package.json.
- Plugin crash on string model config — ClawRouter crashed during OpenClaw plugin registration with
TypeError: Cannot create property 'primary' on string 'blockrun/auto'. This happened whenagents.defaults.modelin the OpenClaw config was a plain string (e.g."blockrun/auto") instead of the expected object{ primary: "blockrun/auto" }. Now auto-converts string/array/non-object model values to the correct object form.
- Config duplication on update —
update.shandreinstall.shaccumulated staleblockrun/*model entries inopenclaw.jsonon every update because only 2 hardcoded deprecated models were removed. Now performs a full reconciliation: removes anyblockrun/*entries not in the currentTOP_MODELSlist before adding new ones. Non-blockrun entries are untouched.
- OpenClaw skills registration — added
"skills": ["./skills"]toopenclaw.plugin.jsonso OpenClaw actually loads bundled skills (was missing, skills were never active) - imagegen skill — new
skills/imagegen/SKILL.md: teaches Claude to generate images viaPOST /v1/images/generations, model selection table (nano-banana, banana-pro, dall-e-3, flux), size options, example interactions - x-api skill — new
skills/x-api/SKILL.md: teaches Claude to look up X/Twitter user profiles viaPOST /v1/x/users/lookup, with pricing table, response schema, and example interactions
- Image generation docs — new
docs/image-generation.mdwith API reference, curl/TypeScript/Python/OpenAI SDK examples, model pricing table, and/imagegencommand reference - Comprehensive docs refresh — architecture updated for dual-chain (Base + Solana), configuration updated with all env vars (
CLAWROUTER_SOLANA_RPC_URL,CLAWROUTER_WORKER), troubleshooting updated for USDC-on-Solana funding, CHANGELOG backfilled for v0.11.14–v0.12.24
- Preserve user-defined blockrun/* allowlist entries —
injectModelsConfig()no longer removes user-addedblockrun/*allowlist entries on gateway restarts
/chaincommand — persist payment chain selection (Base or Solana) across restarts via/chain solanaor/chain base- Update nudge improved — now shows
npx @blockrun/clawrouter@latestinstead ofcurl | bash - Zero balance cache fix — funded wallets are detected immediately (zero balance never cached)
wallet recovercommand — restorewallet.keyfrom BIP-39 mnemonic on a new machine- Solana balance retry — retries once on empty to handle flaky public RPC endpoints
- Balance cache invalidated at startup — prevents false free-model fallback after fresh install
- openai/ prefix routing fix — virtual profiles (
blockrun/auto, etc.) now handleopenai/prefix injected by some clients - Body-read timeout increased — 5-minute timeout for slow reasoning models prevents proxy hangs
- Server-side update nudge — 429 responses from BlockRun now surface update hints when running an outdated ClawRouter version
- Body-read timeout — prevents proxy from hanging on stalled upstream streams
- @solana/kit version fix — pinned to
^5.0.0to resolve cross-version signing bug causingtransaction_simulation_failed(#74) /stats clearcommand — reset usage statistics- Gemini 3 models excluded from tool-heavy routing (#73)
- GPT-5.4 and GPT-5.4 Pro — added to model catalog
- Force agentic tiers on tool presence — requests with
toolsarray always route to agentic-capable models
- Solana sweep fix — correctly attaches signers to sweep transaction message (#70)
- Multi-account sweep — correctly handles partial reads and JSONL resilience in sweep migration
- SPL Token Program ID fix — corrected in Solana sweep transaction
Full Solana chain support. Pay with USDC on Solana (not SOL) alongside Base (EVM).
- SLIP-10 Ed25519 derivation — Solana wallet uses BIP-44 path
m/44'/501'/0'/0', compatible with Phantom and other wallets (#69) SolanaBalanceMonitor— reads SPL Token USDC balance;proxy.tsselects EVM or Solana monitor based on active chain- Solana address shown in
/wallet— displays both EVM (0x...) and Solana (base58) addresses - Health endpoint — returns Solana address alongside EVM address
- Pre-auth cache skipped for Solana — prevents double payment on Solana chain
- Startup balance uses chain-aware monitor — fixes EVM-only startup log when Solana is active
- Chain-aware proxy reuse — validates payment chain matches on EADDRINUSE path
etherspeer dep — added for@x402/evmvia SIWE compatibility
- Free model fallback notification — notifies user when routing to
gpt-oss-120bdue to insufficient USDC balance
- Input token logging — usage logs now include
inputTokensfrom provider responses
- Gemini 3.x in allowlist — replaced Gemini 2.5 with Gemini 3.1 Pro and Gemini 3 Flash Preview
- Top 16 model allowlist — trimmed from 88 to 16 curated models in
/modelpicker (4 routing profiles + 12 popular models)
- Populate model allowlist — populate
agents.defaults.modelswith BlockRun models so they appear in/modelpicker
- Auto-fix broken allowlist —
injectModelsConfig()detects and removes blockrun-only allowlist on every gateway start
- Allowlist cleanup in reinstall.sh — detect and remove blockrun-only allowlist that hid all other models
clawrouter reportcommand — daily/weekly/monthly usage reports vianpx @blockrun/clawrouter reportclawrouter doctorcommand — AI diagnostics for troubleshooting
- catbox.moe image hosting —
/imagegenuploads base64 data URIs to catbox.moe (replaces broken telegra.ph)
- Image upload for Telegram — base64 data URIs from Google image models converted to hosted URLs
- Output raw image URL —
/imagegenreturns plain URL instead of markdown syntax for Telegram compatibility
Session-level repetition detection: 3 consecutive identical request hashes auto-escalate to the next tier (SIMPLE → MEDIUM → COMPLEX → REASONING). Fixes Kimi K2.5 agentic loop problem without manual model switching.
Generate images from chat. Calls BlockRun's image generation API with x402 micropayments.
/imagegen a cat wearing sunglasses
/imagegen --model dall-e-3 a futuristic city
/imagegen --model banana-pro --size 2048x2048 landscape
| Model | Shorthand | Price |
|---|---|---|
| Google Nano Banana (default) | nano-banana |
$0.05/image |
| Google Nano Banana Pro | banana-pro |
$0.10/image (up to 4K) |
| OpenAI DALL-E 3 | dall-e-3 |
$0.04/image |
| OpenAI GPT Image 1 | gpt-image |
$0.02/image |
| Black Forest Flux 1.1 Pro | flux |
$0.04/image |
- Stop hijacking model picker — removed allowlist injection that hid non-BlockRun models from
/modelpicker - Silent fallback to free model — insufficient funds now skips remaining paid models and jumps to the free tier instead of showing payment errors
- Anthropic array content extraction — routing now handles
[{type:"text", text:"..."}]content format (was extracting empty string) - Session startup bias fix — never-downgrade logic: sessions can upgrade tiers but won't lock to the low-complexity startup message tier
- Session re-pins to fallback — after provider failure, session updates to the actual model that responded instead of retrying the failing primary every turn
/debugcommand — type/debug <prompt>to see routing diagnostics (tier, model, scores, session state) with zero API cost- Tool-calling model filter — requests with tool schemas skip incompatible models automatically
- Session persistence enabled by default —
deriveSessionId()hashes first user message; model stays pinned 30 min without client headers - baselineCost fix — hardcoded Opus 4.6 fallback pricing so savings metric always calculates correctly
- Tool call leaking fix — removed
grok-code-fast-1from all routing paths (was outputting tool invocations as plain text) - Systematic tool-calling guard —
toolCallingflag on models; incompatible models filtered from fallback chains - Async plugin fix —
register()made synchronous; OpenClaw was silently skipping initialization
- Agentic mode false trigger —
agenticScorenow scores user prompt only, not system prompt. Coding assistant system prompts no longer force all requests to Sonnet.
- OpenClaw tool API contract — fixed
inputSchema→parameters,execute(args)→execute(toolCallId, params), and return format
- Partner tool trigger reliability — directive tool description so AI calls the tool instead of answering from memory
- Baseline cost fix —
BASELINE_MODEL_IDcorrected fromclaude-opus-4-5toclaude-opus-4.6 - Wallet corruption safety — corrupted wallet files throw with recovery instructions instead of silently generating new wallet
- 9-language router — added ES, PT, KO, AR keywords across all 12 scoring dimensions (was 5 languages)
- Claude 4.6 — all Claude models updated to newest Sonnet 4.6 / Opus 4.6
- 7 new models — total 41 (Gemini 3.1 Pro Preview, Gemini 2.5 Flash Lite, o1, o1-mini, gpt-4.1-nano, grok-2-vision)
- 5 pricing fixes — 15-30% better routing from corrected model costs
- 67% cheaper ECO tier — Flash Lite for MEDIUM/COMPLEX