Skip to content

fix: config duplication on update#112

Merged
1bcMax merged 1 commit intomainfrom
fix/config-duplication-on-update
Mar 22, 2026
Merged

fix: config duplication on update#112
1bcMax merged 1 commit intomainfrom
fix/config-duplication-on-update

Conversation

@1bcMax
Copy link
Copy Markdown
Member

@1bcMax 1bcMax commented Mar 22, 2026

Summary

  • Fix model allowlist accumulation in openclaw.jsonupdate.sh and reinstall.sh only removed 2 hardcoded deprecated models on each update, causing all other stale blockrun/* entries to accumulate indefinitely. Now performs full reconciliation: removes any blockrun/* entry not in the current TOP_MODELS set before adding new ones. Non-blockrun user entries are untouched.
  • Includes pre-existing improvements: atomicWrite for config file writes, glob pattern for models cache cleanup.

Test plan

  • Verified diff logic: currentKeys Set built from TOP_MODELS, then Object.keys(allowlist) filtered by blockrun/ prefix and Set membership
  • Non-blockrun entries (user's own models) are not affected by the startsWith('blockrun/') guard

🤖 Generated with Claude Code

Summary by CodeRabbit

  • Bug Fixes
    • Fixed duplicate stale model entries being added to the configuration file. The update process now performs a full reconciliation against the current model list, removing obsolete entries and ensuring clean configuration updates.

update.sh and reinstall.sh accumulated stale blockrun/* model entries
in openclaw.json because only 2 hardcoded deprecated models were removed.
Now removes any blockrun/* entries not in the current TOP_MODELS set
before adding new ones.
@coderabbitai
Copy link
Copy Markdown

coderabbitai bot commented Mar 22, 2026

Caution

Review failed

The pull request is closed.

ℹ️ Recent review info
⚙️ Run configuration

Configuration used: Path: .coderabbit.yaml

Review profile: CHILL

Plan: Pro

Run ID: 74c5ee14-91cb-4567-bb5b-7766dc8ef73f

📥 Commits

Reviewing files that changed from the base of the PR and between 8382b46 and 7dac1b6.

📒 Files selected for processing (5)
  • .gitignore
  • CHANGELOG.md
  • package.json
  • scripts/reinstall.sh
  • scripts/update.sh

📝 Walkthrough

Walkthrough

This release (v0.12.67) updates allowlist reconciliation logic in shell scripts to dynamically manage blockrun/* model entries against the current TOP_MODELS list instead of using hardcoded deprecation removals. Atomic file writes are introduced for safer JSON persistence, and .gstack/ is excluded from version control.

Changes

Cohort / File(s) Summary
Version & Configuration
.gitignore, CHANGELOG.md, package.json
Version bumped to 0.12.67; changelog documents blockrun/* duplication fix; .gstack/ excluded from version control.
Allowlist Reconciliation Logic
scripts/reinstall.sh, scripts/update.sh
Replaced hardcoded DEPRECATED_MODELS list with dynamic reconciliation: removes all existing blockrun/* allowlist entries not in current TOP_MODELS, then adds missing ones. Added atomic write helper in reinstall.sh for safer JSON updates and expanded cache cleanup to all agent subdirectories.

Estimated code review effort

🎯 3 (Moderate) | ⏱️ ~20 minutes

Possibly related issues

Possibly related PRs

✨ Finishing Touches
📝 Generate docstrings
  • Create stacked PR
  • Commit on current branch
🧪 Generate unit tests (beta)
  • Create PR with unit tests
  • Commit unit tests in branch fix/config-duplication-on-update

Thanks for using CodeRabbit! It's free for OSS, and your support helps us grow. If you like it, consider giving us a shout-out.

❤️ Share

Comment @coderabbitai help to get the list of available commands and usage tips.

Tip

CodeRabbit can use OpenGrep to find security vulnerabilities and bugs across 17+ programming languages.

OpenGrep is compatible with Semgrep configurations. Add an opengrep.yml or semgrep.yml configuration file to your project to enable OpenGrep analysis.

@1bcMax 1bcMax merged commit da3a1a1 into main Mar 22, 2026
2 of 4 checks passed
lionrooter added a commit to lionrooter/ClawRouter that referenced this pull request Mar 24, 2026
* refactor: extract routing into pluggable RouterStrategy system

- Add RouterStrategy interface and RouterOptions type to types.ts
- Add tierConfigs + profile fields to RoutingDecision (backward-compat)
- Create strategy.ts with RulesStrategy (extracted from index.ts) and registry
- Simplify index.ts to delegate to getStrategy("rules")
- Replace fragile reasoning-sniffing tier config re-derivation in proxy.ts
  with routingDecision.tierConfigs (two locations)
- Add 10 strategy tests (profiles, registry, backward compat)

* Fix free-profile and invalid-model fallback behavior

* fix: prettier formatting to pass CI

* fix: support /wallet solana as alias for chain selection (0.12.40)

Users running `npx @blockrun/clawrouter /wallet solana` got EVM balance
check ($0.00) and EVM address in "Fund wallet" despite having Solana USDC.
The CLI parser only recognized `chain solana` — now `/wallet` and `wallet`
are accepted aliases.

* fix: remove unused RoutingDecision import in strategy test

* feat: add GPT-5.3 and GPT-5.3 Codex, retire 5.2 Codex (0.12.41)

* fix: run npm install after openclaw plugin install to restore @solana/kit (0.12.42)

openclaw's plugin installer skips native deps like @solana/kit, breaking
Solana support on update. Both update.sh and reinstall.sh now run
npm install --omit=dev in the plugin directory after installation.

* fix: add gpt-5.3 models to update/reinstall allowlists (0.12.43)

* fix: sync TOP_MODELS, add deepseek-chat alias, fix codex docs (0.12.44)

- Add gpt-5.4 and gpt-5.3-codex to index.ts TOP_MODELS (was missing vs scripts)
- Add deepseek-chat → deepseek/deepseek-chat alias for bare model name
- Fix reinstall.sh showing retired gpt-5.2-codex instead of gpt-5.3-codex

* update X/Twitter account to @ClawRou after ban

* perf: benchmark-driven routing optimization (0.12.45)

Ran end-to-end latency benchmark across all 39 models via x402.
Retuned all 4 routing profiles based on measured latency:

- Auto SIMPLE: kimi-k2.5 (1646ms) → grok-4-fast-non-reasoning (1143ms, 30% faster)
- Auto MEDIUM: kimi-k2.5 → grok-4-1-fast-non-reasoning (1244ms)
- Agentic SIMPLE: gpt-4o-mini (2764ms) → grok-4-1-fast-non-reasoning (55% faster)
- Added grok-3-mini and grok-4-fast-reasoning to fallback chains
- Fixed duplicate claude-opus in premium REASONING fallback
- All latency annotations from benchmark-results.json

* chore: bump to 0.12.46 for npm publish

* fix: restore quality models as auto primary, keep fast models in fallback (0.12.47)

grok-4-fast models are fastest but refuse complex tasks ("I cannot access that").
Revert auto SIMPLE primary to gemini-2.5-flash (1238ms, 60% retention — fast AND quality).
Revert auto MEDIUM primary to kimi-k2.5 (strong tool use).
Revert agentic SIMPLE to gpt-4o-mini (best tool compliance).
Grok fast models stay in eco tier and fallback chains where speed matters most.

* fix: /wallet falls through to native handler on non-BlockRun LLMs, remove migrate-solana (0.12.48)

- Return null instead of {} so OpenClaw continues to native /wallet (e.g. Codex usage)
- Remove /wallet migrate-solana subcommand and solana-sweep.ts
- Remove deriveSolanaKeyBytesLegacy from wallet.ts
- Keep agentic routing for SIMPLE+tools queries (tool support needs reliable models)

* fix: rebuild dist with /wallet null-return fix (0.12.49)

* fix: strip blockrun branding from system prompts before upstream LLM calls

OpenClaw embeds model=blockrun/auto in the Runtime section of system prompts.
LLMs pick up "blockrun" and adopt it as their identity (e.g. "I'm Blockrun"),
overriding the user's SOUL.md persona settings.

New debrandSystemMessages() replaces blockrun/<profile> references with the
actual resolved model name and strips blockrun/ prefixes from explicit model
names in system messages before forwarding upstream.

Closes BlockRunAI#99

* fix: strip blockrun branding from system prompts before upstream LLM calls

OpenClaw embeds model=blockrun/auto in the Runtime section of system prompts.
LLMs pick up "blockrun" and adopt it as their identity (e.g. "I'm Blockrun"),
overriding the user's SOUL.md persona settings.

New debrandSystemMessages() replaces blockrun/<profile> references with the
actual resolved model name and strips blockrun/ prefixes from explicit model
names in system messages before forwarding upstream.

Closes BlockRunAI#99

* chore: bump to 0.12.50 for npm publish

* fix: reorder COMPLEX fallbacks quality-first, add gemini-3-flash-preview to SIMPLE/MEDIUM fallbacks (0.12.51)

* chore(deps): bump all x402 packages to 2.7.0

@x402/svm 2.5.0 → 2.7.0
@x402/evm 2.5.0 → 2.7.0
@x402/fetch 2.5.0 → 2.7.0
@x402/core 2.5.0 → 2.7.0 (transitive)

Bumped together to avoid @x402/core version split.

* chore: bump to 0.12.52 for npm publish

* fix: /wallet now shows per-model usage stats for all providers including openai/ (0.12.52)

* fix: /wallet shows per-model usage stats for all providers (0.12.53)

* fix: bundle all deps into dist to survive OpenClaw updates (0.12.54)

When OpenClaw auto-updates, it can wipe ClawRouter's node_modules causing
"Cannot find module" errors. Now all runtime deps are bundled into dist
via tsup noExternal, with createRequire banner for CJS compat (ws).
Also removed unused ethers dependency.

* chore(deps-dev): bump the dev-dependencies group with 4 updates (BlockRunAI#100)

* chore(deps-dev): bump the dev-dependencies group with 4 updates

Bumps the dev-dependencies group with 4 updates: [eslint](https://github.com/eslint/eslint), [openclaw](https://github.com/openclaw/openclaw), [typescript-eslint](https://github.com/typescript-eslint/typescript-eslint/tree/HEAD/packages/typescript-eslint) and [vitest](https://github.com/vitest-dev/vitest/tree/HEAD/packages/vitest).


Updates `eslint` from 10.0.2 to 10.0.3
- [Release notes](https://github.com/eslint/eslint/releases)
- [Commits](eslint/eslint@v10.0.2...v10.0.3)

Updates `openclaw` from 2026.3.2 to 2026.3.13
- [Release notes](https://github.com/openclaw/openclaw/releases)
- [Changelog](https://github.com/openclaw/openclaw/blob/main/CHANGELOG.md)
- [Commits](https://github.com/openclaw/openclaw/commits)

Updates `typescript-eslint` from 8.56.1 to 8.57.0
- [Release notes](https://github.com/typescript-eslint/typescript-eslint/releases)
- [Changelog](https://github.com/typescript-eslint/typescript-eslint/blob/main/packages/typescript-eslint/CHANGELOG.md)
- [Commits](https://github.com/typescript-eslint/typescript-eslint/commits/v8.57.0/packages/typescript-eslint)

Updates `vitest` from 4.0.18 to 4.1.0
- [Release notes](https://github.com/vitest-dev/vitest/releases)
- [Commits](https://github.com/vitest-dev/vitest/commits/v4.1.0/packages/vitest)

---
updated-dependencies:
- dependency-name: eslint
  dependency-version: 10.0.3
  dependency-type: direct:development
  update-type: version-update:semver-patch
  dependency-group: dev-dependencies
- dependency-name: openclaw
  dependency-version: 2026.3.13
  dependency-type: direct:development
  update-type: version-update:semver-patch
  dependency-group: dev-dependencies
- dependency-name: typescript-eslint
  dependency-version: 8.57.0
  dependency-type: direct:development
  update-type: version-update:semver-minor
  dependency-group: dev-dependencies
- dependency-name: vitest
  dependency-version: 4.1.0
  dependency-type: direct:development
  update-type: version-update:semver-minor
  dependency-group: dev-dependencies
...

Signed-off-by: dependabot[bot] <support@github.com>

* chore: regenerate lockfile after ethers removal and dep updates

* style: fix formatting for prettier 3.8

---------

Signed-off-by: dependabot[bot] <support@github.com>
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
Co-authored-by: 1bcMax <viewitter@gmail.com>

* chore(deps): bump @scure/bip32 from 1.7.0 to 2.0.1 (BlockRunAI#86)

* chore(deps): bump @scure/bip32 from 1.7.0 to 2.0.1

Bumps [@scure/bip32](https://github.com/paulmillr/scure-bip32) from 1.7.0 to 2.0.1.
- [Release notes](https://github.com/paulmillr/scure-bip32/releases)
- [Commits](paulmillr/scure-bip32@1.7.0...2.0.1)

---
updated-dependencies:
- dependency-name: "@scure/bip32"
  dependency-version: 2.0.1
  dependency-type: direct:production
  update-type: version-update:semver-major
...

Signed-off-by: dependabot[bot] <support@github.com>

* chore: regenerate lockfile after rebase

---------

Signed-off-by: dependabot[bot] <support@github.com>
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
Co-authored-by: 1bcMax <viewitter@gmail.com>

* chore: sync package-lock for 0.12.54

* feat: add zai/glm-5 and zai/glm-5-turbo models (0.12.55)

* feat: add zai/glm-5 and glm-5-turbo to model picker (0.12.56)

* chore: sync lockfile (opusscript from openclaw update)

* test: replace fixed wallets with ephemeral keys

* fix: redirect delisted models (grok-code-fast-1, grok-3-fast) instead of hard error (0.12.57)

* feat: add ErrorCategory type and categorizeError() function

* feat: add overload tracking and per-provider error counters

* feat: thread errorCategory through ModelRequestResult

* feat: category-based error handling in fallback loop

* feat: expose per-provider error stats in /stats endpoint

* test: add error classification unit tests

* chore: bump version to 0.12.58 (error classification)

* docs: add blog post — ClawRouter as agent-native router for OpenClaw

* fix: add bare grok-code-fast-1 alias for delisted model

* feat: add maxCostPerRun per-session budget cap (graceful + strict modes)

- graceful mode: when budget runs low, downgrade to cheaper models; routing
  profile requests continue on eco/free, explicit model requests are blocked
- strict mode: hard 429 once session projected spend exceeds cap
- session cost accumulation in SessionStore (addSessionCost / getSessionCost)
- effectiveSessionId fallback via deriveSessionId for explicit model requests
- pre-check Case B: block explicit model requests that can't be afforded
- second-pass block for explicit model requests after modelsToTry is built
- isFreeModel is now `let` so balance-fallback path stays in sync
- projected cost check in strict mode: (runCostUsd + thisReqEstUsd) > cap
- _balanceMonitorOverride hook for wallet-empty regression testing
- 74 tests passing (added 10b rewrite, 10c, 10d, 10e, updated 10, 11)

* chore: add atomic rollback to reinstall/update scripts

* docs: document maxCostPerRun config, update blog + X handle

* chore: bump version to 0.12.59 (maxCostPerRun budget cap)

* fix: use actual token counts for /stats cost calculation instead of estimates

Previously, /stats expense calculations used estimated input tokens
(body.length / 4) and max_tokens for output, then applied a 20% buffer.
This caused logged costs to significantly exceed actual costs.

Changes:
- Capture completion_tokens from API responses (streaming + non-streaming)
- Use actual input/output token counts when available, fall back to estimates
- Remove 20% buffer from logged cost (buffer remains in estimateAmount()
  for pre-payment, which is correct)
- Add outputTokens field to UsageEntry type and log entries

The pre-payment 20% buffer in estimateAmount() and the 1.5x
BALANCE_CHECK_BUFFER are intentionally unchanged — those are
conservative safeguards for payment, not for reporting.

Closes BlockRunAI#36

Co-authored-by: Kagura Chen <daniyuu19@sjtu.edu.cn>

* docs: add cost overrun infographic to blog post

* docs: add blockrun-prefixed images for SEO, add inference blind spots infographic

* docs: add ClawRouter proxy architecture diagram to blog post

* docs: add 7-layer token compression diagram to blog post

* docs: add observation compression diagram to blog post

* docs: add tier routing diagram to blog post

* docs: add error classification diagram to blog post

* docs: add session memory journaling diagram to blog post

* docs: add x402 wallet budget control diagram to blog post

* docs: fix Getting Started section — correct config path and auto-inject behavior

* docs: add OpenClaw vs ClawRouter comparison diagram to blog post

* docs: center images at 720px width, update Getting Started install command

* feat: add exclude-models persistence module

* feat: add filterByExcludeList to router selector

* feat: add /exclude command for model exclusion management

* feat: wire excludeModels filter into proxy fallback chain

* test: add exclude-models integration tests

* test: add exclude-models e2e integration test

* docs: complete pricing table with all 43 models and cost-per-request column

- Replace collapsed partial model list (20 models) with 3 clear sections:
  Budget (<$0.001), Mid-Range ($0.001-$0.01), Premium ($0.01+)
- Add ~$/request column so users can instantly compare real costs
- Add Features column (reasoning, vision, agentic, tools)
- Remove delisted grok-code-fast-1 from tier table
- Update model count 41+ → 43+

* feat: add MiniMax M2.7 model, update alias to default to M2.7

- Add minimax/minimax-m2.7 (same pricing as M2.5: $0.30/$1.20)
- Update `minimax` alias to point to M2.7 (self-evolving flagship)
- Add minimax-m2.7 and minimax-m2.5 explicit aliases
- Update README pricing table and model count (43 → 44)

* chore: bump version to 0.12.60

* docs: add /exclude command documentation to README

* chore: bump to 0.12.61 (rebuild dist with exclude-models)

* docs: add technical blog post — smart LLM routing with 14-dimension classifier

Covers benchmarking 46 models, efficiency frontier analysis, 14-dimension
scoring system with sigmoid confidence calibration, and tier-to-model mapping
across auto/eco/premium/agentic profiles.

* chore: bump to 0.12.64, expand model allowlist to 33 models

- Added gpt-5-nano, gpt-5-mini, gpt-4o-mini, gpt-5.4-pro, o4-mini,
  gemini-3-pro-preview, gemini-2.5-pro, gemini-2.5-flash, gemini-2.5-flash-lite,
  deepseek-reasoner, grok-4-0709, grok-4-1-fast-reasoning, minimax-m2.7,
  nvidia/gpt-oss-120b to TOP_MODELS allowlist
- Exclude docs/assets and docs/plans from npm package (30MB → 3.5MB)
- Update package description to 46+ models

* style: fix prettier formatting across 11 files

Fixes CI formatting check failure from actions/runs/23347953028.

* feat: add cost visibility headers, model field injection, and fallback error summary

- Add x-clawrouter-cost and x-clawrouter-savings response headers
- Add SSE cost comment before [DONE] terminator in streaming responses
- Inject actualModelUsed into SSE chunk model field and non-streaming response
- Track failed fallback attempts and log structured summary when all models fail

* docs: add ClawRouter vs OpenRouter comparison, rename blog files for SEO

- Add new article: clawrouter-vs-openrouter-llm-routing-comparison.md
  (100 OpenClaw issues analyzed, structured comparison across 8 categories)
- Remove outdated vs-openrouter.md (superseded by new article)
- Rename blog files to SEO-friendly slugs:
  blog-openclaw-cost-overruns → clawrouter-cuts-llm-api-costs-500x
  blog-benchmark-2026-03 → llm-router-benchmark-46-models-sub-1ms-routing
  technical-routing-2026-03 → smart-llm-router-14-dimension-classifier

* fix: remove unused isProviderError function to fix lint

The function was superseded by the isProviderError property on
tryModelRequest results but the dead function was never cleaned up.

* fix: remove unused FALLBACK_STATUS_CODES constant to fix lint

* fix: payment pre-auth cache key must include model ID

The pre-auth cache keyed on URL path alone (/api/v1/chat/completions),
so cached payment requirements from a paid model (e.g. sonnet) would be
incorrectly applied to a free model (nvidia/gpt-oss-120b). This caused
payment errors when users switched to free model with an empty wallet —
the pre-auth layer tried to sign a payment the server never requested.

Fix: cache key is now `${urlPath}:${model}` so each model gets its own
cached payment requirements.

* chore: bump to 0.12.65 (fix free model payment error)

* fix: payment settlement failure must fallback to free model

Payment settlement errors (e.g. insufficient funds on-chain) returned
non-standard HTTP codes that categorizeError() didn't recognize, so
isProviderError was false and the fallback loop broke immediately.

The user saw "Payment settlement failed" with no recovery, even though
nvidia/gpt-oss-120b (free) was available.

Fix: move payment error detection before the isProviderError gate.
When a payment error is detected on a paid model, skip directly to
the free model in the fallback chain (or append it if not present).

Reported by user Mark (chain-reaction) via logs.

* fix: save npm install error log to ~/clawrouter-npm-install.log

Previously the log file used a temp path that users couldn't find,
and the error output was easy to miss. Now saves to home directory
with clear messaging to send the log for debugging.

* docs: add illustrations to OpenRouter comparison article

12 diagrams from Engineering_the_Local_Router deck, placed in
docs/assets/ (excluded from npm package via files glob).

* feat: GEO optimize README with definition and FAQ section

- Add structured definition paragraph for AI discoverability
- Add 6 FAQ entries including competitor comparisons

* fix: /stats under-reporting costs — use actual x402 payment amounts

Fixes BlockRunAI#110. /stats was massively under-reporting expenses because:

1. grok-4-0709 pricing was 15x wrong ($0.2/$1.5 vs server's $3/$15)
2. nvidia/kimi-k2.5 pricing was off ($0.55/$2.5 vs server's $0.6/$3)
3. Cost logged from local estimate (actual output tokens, no margin)
   instead of actual x402 payment amount
4. Image generation endpoints (/v1/images/*) had zero cost logging
5. Partner API endpoints (/v1/x/*) logged cost: 0

Now uses AsyncLocalStorage to capture the real x402 payment amount
from onAfterPaymentCreation hook and logs that directly. No more
estimation — /stats reflects exactly what left the wallet.

* fix: config duplication on update — full model allowlist reconciliation (BlockRunAI#112)

update.sh and reinstall.sh accumulated stale blockrun/* model entries
in openclaw.json because only 2 hardcoded deprecated models were removed.
Now removes any blockrun/* entries not in the current TOP_MODELS set
before adding new ones.

* fix: remove redundant deprecated models list from reinstall step 2

The full reconciliation in step 6.2 already handles this — no need
for a hardcoded deprecated list in the earlier config cleaning step.

* chore(deps): bump viem from 2.46.3 to 2.47.6 (BlockRunAI#115)

Bumps [viem](https://github.com/wevm/viem) from 2.46.3 to 2.47.6.
- [Release notes](https://github.com/wevm/viem/releases)
- [Commits](https://github.com/wevm/viem/compare/viem@2.46.3...viem@2.47.6)

---
updated-dependencies:
- dependency-name: viem
  dependency-version: 2.47.6
  dependency-type: direct:production
  update-type: version-update:semver-minor
...

Signed-off-by: dependabot[bot] <support@github.com>
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>

* chore: sync lockfile after upstream merge

* fix: satisfy opusscript peer for npm ci

* style: format repo files and fix lint for CI

---------

Signed-off-by: dependabot[bot] <support@github.com>
Co-authored-by: 1bcMax <viewitter@gmail.com>
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
Co-authored-by: Bryan Fisher <bryan@lionroot.com>
Co-authored-by: Kagura <kagura.chen28@gmail.com>
Co-authored-by: Kagura Chen <daniyuu19@sjtu.edu.cn>
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant