Skip to content

Release 3.1.4: OpenClaw 2026.6.8 + provider compatibility + Telegram pairing#217

Merged
KrasimirKralev merged 18 commits into
mainfrom
beta
Jun 19, 2026
Merged

Release 3.1.4: OpenClaw 2026.6.8 + provider compatibility + Telegram pairing#217
KrasimirKralev merged 18 commits into
mainfrom
beta

Conversation

@KrasimirKralev

@KrasimirKralev KrasimirKralev commented Jun 19, 2026

Copy link
Copy Markdown
Contributor

Release 3.1.4 β€” OpenClaw 2026.6.8 + provider compatibility + Telegram pairing

Promotes the staged beta line to main. Version 3.1.3 β†’ 3.1.4, OpenClaw pin 2026.6.1 β†’ 2026.6.8.

Headline: OpenClaw 2026.6.8 provider compatibility

2026.6.8 reworked provider auth; without these fixes OpenRouter 401s and Gemini/Anthropic silently fall back to the fallback model.

Telegram pairing

Installer / updater

Local AI

Docs

Validation

All provider paths (ClawBox AI, OpenRouter, OpenAI/Codex, Gemini, Anthropic) verified end-to-end on a Jetson running 2026.6.8; unit tests green on-device. Final sign-off on a fresh beta flash.

Summary by CodeRabbit

  • Documentation
    • Expanded README β€œQuick Start” with clear requirements, JetPack 6.2-only guidance, and a more detailed installation flow plus connection instructions.
  • New Features
    • Added Telegram pairing approval UX (desktop popups with approve/dismiss/open, and Settings-side approved user management).
    • Introduced clawbox update for streamlined updates.
    • Added Gemma as the fully-local AI option.
  • Bug Fixes
    • Updated local AI options (Ollama removed).
    • Improved installation/update behavior and Telegram token-change reset handling.
  • Chores
    • Bumped version to 3.1.4.

KrasimirKralev and others added 16 commits June 12, 2026 13:04
…yout (#199)

* docs: pin supported platform to JetPack 6.2 and document the install layout

Field report (from-scratch install on a fresh NVIDIA image): NVIDIA now
steers downloads to JetPack 7 / Ubuntu 24.04, where the installer fails on
PEP 668 (externally-managed pip) -- and the bare `sudo bash install.sh`
quickstart says nothing about the expected clone location, so running from
a personal user's checkout crashes on the hardcoded /home/clawbox/clawbox
paths. Pin JetPack 6.2 explicitly (with download link and a 24.04 warning)
and document the supported clone-as-clawbox recipe.

* docs: fail fast on real useradd errors in the quickstart recipe

CodeRabbit finding: '|| true' swallowed genuine useradd failures, letting
the later clone/install steps fail somewhere less obvious. Only skip
creation when the user already exists.
Move the fleet from 2026.6.1 to 2026.6.6. Validated on a Jetson device:
core + both auth-bypass patches + ClawBox AI and Codex (ARM @openclaw/codex
2026.6.6) chat all work; the codex plugin realigns to the bumped pin on the
next gateway start. Fresh installs and the updater both read this pin.
)

* fix(openai): stop Codex subscription OAuth corrupting the id token

The OpenAI subscription OAuth flows ran an id_token -> openai-api-key token
exchange and stored the resulting sk- key as the codex profile's `access`.
gateway-pre-start then synthesized ~/.codex/auth.json with
`id_token: p.id || p.access` -> the API key string, which the Codex app-server
rejects with 'failed to set external auth: invalid ID token format'. Because
~/.codex/auth.json is shared and rebuilt every gateway start, the bad
credential also poisoned the API-key OpenAI provider and survived re-auth.

- device-poll (device-code flow): drop the api-key exchange; return the raw
  OAuth JWTs (access_token + id_token + refresh_token).
- oauth/exchange (redirect flow): same change, so both completion paths are
  consistent and the bug isn't left latent on the redirect path.
- configure: persist the id_token as the profile's `id` so the synthesis
  writes a valid JWT id_token (and a JWT access_token, fixing account_id
  resolution that split `access` on '.').
- AIModelsStep: forward id_token from the OAuth result to configure.

Validated on a device: a fresh Codex device-code login now stores a JWT access
+ id, synthesizes a valid ~/.codex/auth.json, and OpenAI accepts the credential
(invalid-ID-token replaced by the account's normal rate-limit).

* test(openai): update OAuth tests to the no-api-key-exchange behavior

The Codex OAuth fix removed the id_token->api-key exchange, so the tests that
asserted that (now-removed) behavior were failing. Replace them with tests that
assert the new contract: the OpenAI exchange/device-poll routes return the raw
OAuth JWTs incl. id_token and make no second (api-key) request.

* fix(openai): reject non-JWT Codex subscription credentials at configure time

Addresses CodeRabbit review on #201: the configure route accepted a
client-supplied idToken but still wrote the codex oauth profile when neither
idToken nor access was JWT-shaped β€” which the gateway's id->access synthesis
fallback could turn back into an invalid id_token. Reject codex subscription
saves with a 502 unless the id_token (or access, trimmed) is JWT-like, and
store the trimmed id_token. Updates the subscription configure test to use
JWT-shaped credentials.
…ns detect CI (#207)

The e2e-install harness entrypoint seeds /etc/clawbox/test-mode.env
(CLAWBOX_TEST_MODE=1 + NETWORK_INTERFACE=eth0) before any install.sh runs,
expecting install.sh to read it ("so install.sh knows it's in test mode even
before it writes its own .env"). But install.sh only read CLAWBOX_TEST_MODE
from its process env, so updater-triggered `install.sh --step` runs via
clawbox-root-update@.service β€” which inherit only /etc/clawbox/network.env,
populated late during step_network_setup β€” ran with CLAWBOX_TEST_MODE=0. They
then executed the real Jetson/WiFi steps (iw dev eth0, nvpmodel, jetson_clocks)
and failed on the non-Tegra CI host, intermittently breaking e2e-install.

Source the seeded marker at startup so every invocation (bootstrap and
updater-triggered) detects test mode up front. The file exists only in the CI
container, so this is a no-op on real devices.
…rminal (#208)

ClawBox had no CLI updater (only OpenClaw does), so the only way to update was
the Settings UI β€” which gives no visibility when a step fails (issue #202).

`clawbox update` re-runs install.sh in place: the same complete path the Update
button drives (git-sync to the pinned code, system packages, OpenClaw at the
pinned version, gateway config, rebuild), but straight in the terminal with
live output so owners can watch each step and see exactly where it fails. It
shells out via sudo; CLAWBOX_ROOT overrides the install location.
A Telegram bot set up on an older OpenClaw can carry a
channels.telegram.groupPolicy value the current schema rejects (allowed:
open, disabled, allowlist). A single invalid value invalidates the entire
openclaw.json, so the gateway loads nothing and the bot stays connected but
never replies β€” surfaced as 'OpenClaw config is invalid … groupPolicy: must
be equal to one of the allowed values'.

gateway-pre-start.sh already strips the legacy dmPolicy/allowFrom keys from
channels.telegram on every start; extend that same block to reset an unknown
groupPolicy to the secure default ('disabled' β€” ClawBox has no group-chat
UI; owner DMs are unaffected) so affected devices self-heal on restart.
#205)

A flat agents.defaults.compaction.reserveTokensFloor of 24000 suits
large-context cloud models but swallows most of Ollama's 32K window,
leaving ~8.7K of usable input β€” less than the agent's ~20K-token system
prompt + tool schemas. Every local-model turn then fails before the model
runs ("context overflow" / unrecoverable auto-compaction).

Size the reserve to the active model's context window β€” a quarter, clamped
to [4096, 24000]: Ollama 32768 -> 8192, llama.cpp/cloud keep 24000.
Validated on a 2026.6.6 device (reserve 8000 -> the Ollama model responds);
85/85 affected tests green on-device.
On Jetson, Gemma 4 (llama.cpp) runs at its full 131K context while the 3B
Ollama models are RAM-capped at 32K β€” too tight for the agent's heavy system
prompt β€” so Gemma is the only local engine that performs well. Make it the
sole local option, folded into the existing AI Provider step (cloud-first,
"go local from here") rather than a separate wizard step.

- AI Provider step + Settings -> Local AI: Gemma is offered alongside the
  cloud providers; Ollama is hidden (its provider def, panel, hooks and routes
  are left intact, so re-enabling is a one-line revert).
- Gemma is promoted up-front (PRIMARY_PROVIDER_IDS) and carries a "Fully
  local" badge instead of "Recommended" (which stays on ClawBox AI).
- i18n: ai.fullyLocal across all 10 locales.

Validated on a 2026.6.6 device: 55/55 affected tests green.
…209)

* feat: approve Telegram pairing codes from Settings

Add a "User access" section to Settings -> Telegram so the owner can approve who may chat with the bot without a terminal:

- paste an 8-char pairing code, or load pending requests and approve with one click (openclaw pairing list/approve telegram --json/--notify)
- --notify makes OpenClaw confirm to the user automatically
- show currently approved senders, read from the credentials allowFrom store

New /setup-api/telegram/pairing route + helpers in openclaw-config.ts; i18n for all 10 locales; unit + route tests.

* refactor: share one spawnOpenclaw helper for the openclaw CLI

Extract the spawn/timeout/error machinery duplicated between config-set and the new pairing CLI calls into a single spawnOpenclaw(args, {captureStdout}); export the shared PAIRING_CODE_RE so the route stops re-declaring it.

* feat: desktop popup for new Telegram access requests with inline approve

When a new person DMs the bot, a corner popup now appears on the desktop (even with Settings closed) showing the requester with Approve / Open / Dismiss. A fast file-read endpoint (?poll=1) backs a 20s poller; de-dup via localStorage. Also corrects the pending-request shape to OpenClaw's real {code,id,meta} (was guessed userId/username).
…-only merge (#211)

step_git_pull used `git merge --ff-only || echo continuing with current code`, which silently kept stale code whenever the box had any local divergence β€” so config/openclaw-target.txt, OpenClaw, and the gateway stayed pinned to the old version (#202). The bootstrap + step also defaulted the branch to main, force-pulling a beta box toward main.

Route both through the robust helpers the in-app updater already uses:
- resolve_update_branch honors an explicit CLAWBOX_BRANCH first, then .update-branch, then the current branch, then main.
- The bootstrap resolves the branch the same way (inline, validated) instead of defaulting to main.
- step_git_pull hard-syncs via resolve_update_branch + sync_repo_to_update_target (fetch + reset --hard) instead of the ff-only merge.

Refs #202.
* feat(telegram): show the requester's name in pairing UI

Pending popup + Settings pending list now show the sender's Telegram display name (meta.name) instead of just the numeric id (the field was mis-guessed as meta.username before). For the Approved users list, capture meta.name at approval time and remember it in an id->name map in config-store (OpenClaw's allowlist stores ids only); GET now returns approved as {id, name?}. Already-approved ids stay as ids until re-approved.

* feat(telegram): reset allowlist on new bot token + live-refresh approved list

- configure: when the bot token actually changes, wipe OpenClaw's allowlist/pending stores (new clearTelegramPairingState) + the ClawBox name map, so a new bot starts fresh. Re-saving the same token keeps approvals.
- popup/Settings: dispatch a clawbox:telegram-approved event on approve; both the desktop popup and the Settings list listen and update live, so an approval reflects immediately without a manual refresh.

* fix(telegram): refresh approved/pending lists after a reconfigure resets the allowlist

* fix(telegram): read the sender name from meta.firstName/lastName

The real pending-request meta on the device is { firstName, accountId } β€” not { name } (that was from a different channel's source). Capture + display now use firstName (+ lastName), so the approver's name actually shows.

* refactor(telegram): derive the sender name once at the read boundary

Per /simplify: the firstName/lastName -> name join was duplicated in the route + both UIs. listTelegramPairingRequests/readTelegramPairingRequests now attach a derived name; the route and components just read req.name.
… compat) (#214)

OpenRouter/anthropic/openai/google chats failed with '401 Missing
Authentication header' on OpenClaw 2026.6.8. ClawBox wrote their auth as
type:"token" profiles (and OpenRouter's provider apiKey as the placeholder
"openrouter-ref"); 2026.6.6 resolved those, but 2026.6.8 reworked auth
resolution and no longer turns a token-mode profile into an Authorization
header, nor resolves the placeholder β€” it sends models.providers.*.apiKey
verbatim. Write the same type:"api_key" shape the working providers
(clawai/ollama/llamacpp) use, and inline OpenRouter's real key. Verified
end-to-end on device against 2026.6.8.
…26.6.8 (#215)

* fix: route google through OpenAI-compat endpoint so Gemini runs on 2026.6.8

OpenClaw's native google plugin registers Gemini models but fails auth at
call time on 2026.6.8 β€” chats silently fall back to the fallback model with
reason=auth. Configure google the same way ClawBox already handles OpenRouter:
an openai-completions provider pointed at Google's /v1beta/openai endpoint with
the key inline, so the gateway actually authenticates the call.

- configure: add isGoogle branch writing models.providers.google (openai-compat,
  inline key, seeded from GOOGLE_MODELS).
- chat/model: generalize the models.providers auto-extend from openrouter-only
  to openrouter+google (google is now an openai-completions provider too, so a
  picked model not in the seed needs registering β€” same quirk as openrouter).
- provider-models: add gemini-3.5-flash + gemini-3.1-flash-lite to GOOGLE_MODELS.

Verified end-to-end on device (OpenClaw 2026.6.8): native generateContent and
/v1beta/openai both return 200; the openai-compat provider resolves and runs
every Gemini model with no auth fallback.

* fix(chat/model): fail loud on readConfig error instead of clobbering the model list

Address CodeRabbit review on #215:
- chat/model auto-extend: readConfig().catch(()=>({})) meant a config-read
  failure produced existingModels=[] and overwrote models.providers.<p>.models
  with ONLY the picked id, dropping every other configured model. Return 500
  instead of silently clobbering.
- configure test: assert gemini-3.1-flash-lite is in the seeded google models
  (was only checking 2.5-flash + 3.5-flash).
… helper) (#216)

* fix: route anthropic through OpenAI-compat endpoint (+ extract shared helper)

Anthropic's native plugin reads a per-agent sqlite auth store that ClawBox's
file auth profile doesn't populate, so chats fail with ProviderAuthError 'No API
key found' at call time (missing-provider-auth) on 2026.6.8 β€” the same class as
google. Route anthropic through Anthropic's OpenAI-compatible endpoint
(api.anthropic.com/v1) with the key inline, like google/openrouter.

Now that there are three openai-compat providers, extract the shared
writeOpenAICompatProvider() helper (CodeRabbit/simplify flagged the duplication
on #215) and refactor openrouter + google to use it. chat/model auto-extend
gates on a shared OPENAI_COMPAT_PROVIDERS set (openrouter, google, anthropic).

openai-direct (API-key) has the same root cause but is intentionally NOT
rerouted here: it's untested (Codex/oauth is the common path) and its native
responses/reasoning behavior could degrade under a plain openai-completions
shim β€” a separate follow-up if anyone hits it.

Verified on device: api.anthropic.com/v1/chat/completions returns 200 for
claude-opus-4-8 with the key; the rerouted provider resolves + runs.

* fix(chat/model): reject auto-extend onto a half-written provider

Address CodeRabbit review on #216:
- chat/model auto-extend: if models.providers.<p> exists without an inline
  apiKey (legacy/partial state), appending only .models leaves an openai-compat
  provider that can't authenticate. Return 409 'Re-save in Settings' instead of
  switching the primary onto a broken provider.
- configure test: cover a user-picked non-curated model (claude-opus-4-8) β€” the
  helper must still seed the pick via defaultModel so the gateway resolves it.

* test(chat/model): give the openrouter auto-extend mock an inline apiKey

The new 409 guard for half-written providers needs models.providers.<p>.apiKey;
the existing 'accepts an arbitrary openrouter slug' mock only had the auth
profile (no provider entry), so it 409'd. Add the realistic provider entry
(baseUrl/api/apiKey/models) a configured openrouter provider actually has.

* fix(chat/model): require baseUrl + api + apiKey before auto-extend

CodeRabbit: a complete openai-compat provider entry has baseUrl + api + apiKey
(written atomically by ai-models/configure). Check all three before appending a
model, so a partially-written entry triggers the 409 re-save instead of leaving
the primary on an unusable provider.
Reverts the TEMP skip from #128 (8bdb5ac). With the AP/install-bootstrap
regressions resolved on main, we want the at-flash install to land a
working llama-server + Gemma 4 GGUF on the device so first boot has
local inference available without an extra Settings UI round-trip.

The step still does the right thing on re-runs (idempotent: the
needs_rebuild gate at step_llamacpp_install:1245 checks for an
existing CUDA-linked llama-server, and ensure_llamacpp_model_cached
short-circuits when the GGUF is already cached). Cold flash adds
roughly 5–10 min per device on the Jetson Orin Nano β€” paid in
parallel across both devices in Phase 3.

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
@KrasimirKralev
KrasimirKralev requested a review from a team as a code owner June 19, 2026 12:55
@coderabbitai

coderabbitai Bot commented Jun 19, 2026

Copy link
Copy Markdown

Review Change Stack

πŸ“ Walkthrough

Walkthrough

Adds Telegram pairing approval flow (lib helpers, new API route, Settings UI card, desktop popup, and translations), simplifies OpenAI OAuth to return raw id_token tokens, unifies Google/Anthropic/OpenRouter under a shared writeOpenAICompatProvider helper, removes Ollama as a local AI option (llamacpp/Gemma only), hardens install.sh branch resolution and git sync, and adds a clawbox update CLI command.

Changes

Telegram Pairing Approval Feature

Layer / File(s) Summary
Telegram pairing lib helpers and types
src/lib/openclaw-config.ts
Adds PAIRING_CODE_RE, TelegramPairingRequest, and exported functions to list, read, approve, read allowlists, and clear Telegram pairing state.
Telegram configure route: token-change pairing reset
src/app/setup-api/telegram/configure/route.ts
Detects bot token changes, clears pairing state and approved names via clearTelegramPairingState, returns reset: true/false in the success response.
New /setup-api/telegram/pairing route (GET + POST)
src/app/setup-api/telegram/pairing/route.ts
GET returns {configured, approved, pending} with optional pending via poll=1 (pairing store) or pending=1 (CLI list); POST validates, approves, and persists display names for pairing codes.
Settings app pairing card and state
src/components/SettingsApp.tsx
Adds pairing state (approved users, pending requests, code input, approval status), refreshPairing effect, loadPending action, approvePairingCode approval handler, token-reset handling, and a "User access" card with code input, pending-request buttons, and approved-users list.
Desktop page.tsx pairing popup
src/app/page.tsx
Adds 20s polling to fetch pending requests, approve/dismiss/open callbacks, notification container render condition, and per-request popup cards with spinner/disabled states.
Telegram groupPolicy config migration
scripts/gateway-pre-start.sh
Resets channels.telegram.groupPolicy to "disabled" when the stored value is not a recognized enum.
Telegram pairing and fullyLocal translations
src/lib/translations.ts
Adds ai.fullyLocal and all per-locale "User access" pairing-flow translation keys across all supported locales.
Telegram pairing tests
src/tests/unit/telegram-pairing.test.ts, src/tests/routes/telegram/pairing.test.ts, src/tests/routes/telegram/configure.test.ts
Unit tests for all lib helpers; route tests for GET/POST pairing endpoint and configure token-change reset.
Telegram pairing design spec
docs/superpowers/specs/2026-06-16-telegram-pairing-design.md
New design document covering problem, goals, verified facts, proposed architecture, security constraints, test expectations, and out-of-scope items.

AI Provider Unification and OAuth Simplification

Layer / File(s) Summary
Shared helpers and model catalogs
src/lib/openclaw-config.ts, src/lib/provider-models.ts
Introduces spawnOpenclaw generic helper for standardized CLI spawning; adds compactionReserveFloorForContext for dynamic reserve sizing; expands GOOGLE_MODELS with gemini-3.5-flash and gemini-3.1-flash-lite.
OpenAI OAuth simplification: return raw tokens
src/app/setup-api/ai-models/oauth/device-poll/route.ts, src/app/setup-api/ai-models/oauth/exchange/route.ts
Removes the second id_token→openai-api-key exchange; returns raw id_token alongside access_token directly from OAuth response.
AI models configure route: OpenAI-compat unification
src/app/setup-api/ai-models/configure/route.ts
Introduces writeOpenAICompatProvider helper; adds idToken/isGoogle/isAnthropic request handling; adds Codex JWT validation; migrates auth profiles from token mode to type: "api_key"; replaces fixed compaction reserve with dynamic floor; rewires OpenRouter/Google/Anthropic to use the helper.
Chat model route: generalized compat auto-extension
src/app/setup-api/chat/model/route.ts
Replaces OpenRouter-only model auto-extension with OPENAI_COMPAT_PROVIDERS allowlist (google, anthropic, openrouter); adds provider config validation for required fields.
Remove Ollama: llamacpp-only local AI
src/components/AIModelsStep.tsx, src/components/SettingsApp.tsx, src/components/SetupWizard.tsx, e2e/settings-workflow.spec.ts, e2e/setup-local-ai-order.spec.ts
Adds llamacpp to primary provider IDs; splits badge logic (clawai: "recommended", llamacpp: "fully local"); restricts Settings local AI selection to llamacpp; updates e2e assertions for Ollama removal and Gemma 4 presence.
AI provider and OAuth tests
src/tests/routes/ai-models/configure.test.ts, src/tests/routes/ai-models/device-poll.test.ts, src/tests/oauth-routes.test.ts, src/tests/routes/chat-model.test.ts, src/tests/components/ai-models-step.test.tsx, src/tests/unit/openclaw-config.test.ts
Updates configure tests for api_key profile assertions and new Google/Anthropic compat tests; updates OAuth tests to expect raw token responses; adds compaction reserve floor unit test coverage.

Installer and Updater Hardening

Layer / File(s) Summary
install.sh branch resolution, git hard-sync, and test-mode
install.sh
Bootstrap derives _br safely from CLAWBOX_BRANCH/.update-branch/git branch with main fallback; sources test-mode.env early; resolve_update_branch prefers validated CLAWBOX_BRANCH; step_git_pull uses hard-sync via sync_repo_to_update_target; enables step_llamacpp_install.
clawbox update CLI command
mcp/clawbox-cli.ts
Adds cmd === "update" branch that locates and sudo-runs install.sh with path validation and exit code propagation; updates help text.

Documentation, Config, and Version Bump

Layer / File(s) Summary
README, version, and target updates
README.md, config/openclaw-target.txt, package.json
README adds requirements table (device, JetPack 6.2, Ubuntu 22.04, link) and JetPack 7 not-supported warning; expands install steps (user creation, clone, chown, run script); target version bumped to 2026.6.8; package version bumped to 3.1.4.

Sequence Diagram(s)

sequenceDiagram
  participant DesktopPage as page.tsx (desktop)
  participant PairingAPI as /setup-api/telegram/pairing
  participant openclawConfig as openclaw-config.ts
  participant SettingsApp as SettingsApp.tsx

  rect rgba(30, 100, 200, 0.5)
    note over DesktopPage: Poll every 20s
    DesktopPage->>PairingAPI: GET ?poll=1
    PairingAPI->>openclawConfig: readTelegramPairingRequests()
    PairingAPI->>openclawConfig: readTelegramAllowFrom()
    PairingAPI-->>DesktopPage: {pending[], approved[]}
    DesktopPage->>DesktopPage: filter dismissed codes, show popups
  end

  rect rgba(200, 80, 30, 0.5)
    note over DesktopPage: User approves from popup
    DesktopPage->>PairingAPI: POST {code}
    PairingAPI->>openclawConfig: approveTelegramPairing(code)
    PairingAPI->>openclawConfig: persist display name
    PairingAPI-->>DesktopPage: {approved[]}
    DesktopPage->>DesktopPage: dispatch clawbox:telegram-approved
  end

  rect rgba(30, 160, 80, 0.5)
    note over SettingsApp: Listens for approval event
    SettingsApp->>PairingAPI: GET (refreshPairing)
    PairingAPI-->>SettingsApp: updated approved list
  end
Loading

Estimated code review effort

🎯 5 (Critical) | ⏱️ ~120 minutes

Possibly related PRs

  • ID-Robots/clawbox#212: Directly overlaps the Telegram pairing approval/reset/live-refresh work across page.tsx, configure/route.ts, pairing/route.ts, SettingsApp.tsx, and clearTelegramPairingState storage.
  • ID-Robots/clawbox#216: Shares the writeOpenAICompatProvider extraction and Anthropic OpenAI-compat routing changes in configure/route.ts and chat/model/route.ts.
  • ID-Robots/clawbox#211: Shares the same install.sh updater branch resolution and sync_repo_to_update_target hard-sync changes.

Suggested labels

bug, documentation, enhancement

Suggested reviewers

  • yalexx
  • GeorgiK77

πŸ‡ A rabbit hopped through settings one day,
Found Telegram codes waiting in the queue!
With Gemma alone to light the local way,
The install now hard-syncsβ€”no merge askew.
clawbox update runs with a sudo cheer,
OAuth raw tokens, the key path is clear! ✨

πŸš₯ Pre-merge checks | βœ… 4 | ❌ 1

❌ Failed checks (1 warning)

Check name Status Explanation Resolution
Docstring Coverage ⚠️ Warning Docstring coverage is 35.14% which is insufficient. The required threshold is 80.00%. Write docstrings for the functions missing them to satisfy the coverage threshold.
βœ… Passed checks (4 passed)
Check name Status Explanation
Title check βœ… Passed The title clearly summarizes the main release: version bump to 3.1.4, OpenClaw pin update to 2026.6.8, and the three major feature areas (provider compatibility, Telegram pairing). It is concise, specific, and directly matches the changeset content.
Description check βœ… Passed The description is comprehensive and well-structured. It includes a clear summary of changes, links to related issues/PRs, outlines how testing was performed (end-to-end on Jetson + unit tests), and addresses each required section from the template including type of change, testing approach, and validation steps.
Linked Issues check βœ… Passed Check skipped because no linked issues were found for this pull request.
Out of Scope Changes check βœ… Passed Check skipped because no linked issues were found for this pull request.

✏️ Tip: You can configure your own custom pre-merge checks in the settings.

✨ 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 beta

Warning

There were issues while running some tools. Please review the errors and either fix the tool's configuration or disable the tool if it's a critical failure.

πŸ”§ ESLint

If the error stems from missing dependencies, add them to the package.json file. For unrecoverable errors (e.g., due to private dependencies), disable the tool in the CodeRabbit configuration.

ESLint install failed: dependency version conflict. Check your lock file or package.json.


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.

@github-actions

github-actions Bot commented Jun 19, 2026

Copy link
Copy Markdown

CI Summary

βœ… Tests

  • Result: passed
  • View run
  • Coverage: statements 69.62%, branches 59.5%, functions 64.85%, lines 71.61%

βœ… E2E

βœ… E2E Install

@coderabbitai coderabbitai Bot left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Actionable comments posted: 5

Caution

Some comments are outside the diff and can’t be posted inline due to platform limitations.

⚠️ Outside diff range comments (1)
src/components/SettingsApp.tsx (1)

2330-2337: ⚠️ Potential issue | 🟑 Minor | ⚑ Quick win

Finish the Ollama removal in the Settings copy.

Line 2330 exposes only llamacpp, but the adjacent description still says users can β€œchoose a different local engine,” and this section still has visible Ollama wording in the same render path. Update the copy/legacy labels so Settings consistently presents Gemma 4 as the only local engine.

Suggested copy adjustment
               title="Set Up Local AI"
               description={localAiStatus?.configured
-                ? "Choose a different local engine if you want to switch your on-device fallback."
+                ? "Gemma 4 is configured as your private on-device fallback."
                 : "Turn on a local model so ClawBox always has a private on-device backup."}
πŸ€– Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

In `@src/components/SettingsApp.tsx` around lines 2330 - 2337, The SettingsApp
component at the Local AI configuration section is exposing only llamacpp as a
provider in the providerIds array, but the description text still mentions
"choose a different local engine" which incorrectly implies multiple options are
available. Update the description text in the section where title is "Set Up
Local AI" to remove references to switching or choosing different local engines,
and instead clearly state that Gemma 4 (via llamacpp) is the only available
local engine option. Ensure all copy reflects that there is a single local
engine choice rather than multiple options, maintaining consistency with the
provider configuration.
πŸ€– Prompt for all review comments with AI agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

Inline comments:
In `@docs/superpowers/specs/2026-06-16-telegram-pairing-design.md`:
- Around line 47-56: Update the Architecture section of the design spec to
include a new subsection documenting the desktop notification popup in
`src/app/page.tsx` with its 20-second polling loop and `?poll=1` query parameter
usage. Revise the GET endpoint description (lines 47-48) to clearly distinguish
between `?poll=1` for fast cached store reads used by the desktop notification
layer and `?pending=1` for the slow authoritative CLI used by the Settings UI.
Clarify the "No auto-poll" statement on line 55 to specify that auto-polling is
avoided in the SettingsApp component but the desktop notification component
performs 20-second interval polling for new pairing requests.

In `@mcp/clawbox-cli.ts`:
- Around line 326-341: The `projectRoot` variable assignment that reads from the
`CLAWBOX_ROOT` environment variable lacks input validation, which poses a
security risk if the environment variable is compromised. Add validation to
check that `CLAWBOX_ROOT` matches a safe-character pattern (following the same
approach as in `force-update.sh` lines 32-35) before using it to construct the
`installScript` path. If validation fails, log an appropriate error message and
exit with status 1, ensuring the script path cannot be manipulated through
environment variable injection.

In `@src/app/page.tsx`:
- Around line 1786-1808: The buttons in this component (the dismiss button with
dismissPairingRequest, the approve button with approvePairingRequest, and the
"Open" button with openTelegramPairingSettings) lack an explicit type attribute.
Add type="button" to each of these button elements to prevent accidental form
submission behavior if the component structure changes in the future to include
a form wrapper.

In `@src/components/SettingsApp.tsx`:
- Around line 2450-2462: The pairing code input field lacks an accessible name
for screen readers since placeholders are not reliable for accessibility. Add an
aria-label attribute to the input element that clearly describes its purpose
(such as "Telegram pairing code"), or alternatively add an id attribute to the
input and associate it with a label element. This will ensure screen readers
properly announce the input purpose to users.

In `@src/tests/routes/chat-model.test.ts`:
- Around line 334-335: The test fixtures in the openrouter profile objects
(appearing at lines 334-335, 358-359, and 382-383) are using the legacy schema
with mode: "token", but the actual provider setup now persists profiles using
type: "api_key" with a key property. Update each of these fixture definitions to
use the current auth profile schema by replacing the mode: "token" structure
with type: "api_key" and including the appropriate key property to match the
real provider contract and prevent hidden regressions.

---

Outside diff comments:
In `@src/components/SettingsApp.tsx`:
- Around line 2330-2337: The SettingsApp component at the Local AI configuration
section is exposing only llamacpp as a provider in the providerIds array, but
the description text still mentions "choose a different local engine" which
incorrectly implies multiple options are available. Update the description text
in the section where title is "Set Up Local AI" to remove references to
switching or choosing different local engines, and instead clearly state that
Gemma 4 (via llamacpp) is the only available local engine option. Ensure all
copy reflects that there is a single local engine choice rather than multiple
options, maintaining consistency with the provider configuration.
πŸͺ„ Autofix (Beta)

Fix all unresolved CodeRabbit comments on this PR:

  • Push a commit to this branch (recommended)
  • Create a new PR with the fixes

ℹ️ Review info
βš™οΈ Run configuration

Configuration used: Path: .coderabbit.yaml

Review profile: ASSERTIVE

Plan: Pro

Run ID: ee8163f5-452a-4e15-b4f8-ec0f6e3f17d7

πŸ“₯ Commits

Reviewing files that changed from the base of the PR and between 40f23e6 and a691fc3.

πŸ“’ Files selected for processing (31)
  • README.md
  • config/openclaw-target.txt
  • docs/superpowers/specs/2026-06-16-telegram-pairing-design.md
  • e2e/settings-workflow.spec.ts
  • e2e/setup-local-ai-order.spec.ts
  • install.sh
  • mcp/clawbox-cli.ts
  • package.json
  • scripts/gateway-pre-start.sh
  • src/app/page.tsx
  • src/app/setup-api/ai-models/configure/route.ts
  • src/app/setup-api/ai-models/oauth/device-poll/route.ts
  • src/app/setup-api/ai-models/oauth/exchange/route.ts
  • src/app/setup-api/chat/model/route.ts
  • src/app/setup-api/telegram/configure/route.ts
  • src/app/setup-api/telegram/pairing/route.ts
  • src/components/AIModelsStep.tsx
  • src/components/SettingsApp.tsx
  • src/components/SetupWizard.tsx
  • src/lib/openclaw-config.ts
  • src/lib/provider-models.ts
  • src/lib/translations.ts
  • src/tests/components/ai-models-step.test.tsx
  • src/tests/oauth-routes.test.ts
  • src/tests/routes/ai-models/configure.test.ts
  • src/tests/routes/ai-models/device-poll.test.ts
  • src/tests/routes/chat-model.test.ts
  • src/tests/routes/telegram/configure.test.ts
  • src/tests/routes/telegram/pairing.test.ts
  • src/tests/unit/openclaw-config.test.ts
  • src/tests/unit/telegram-pairing.test.ts

Comment thread docs/superpowers/specs/2026-06-16-telegram-pairing-design.md
Comment thread mcp/clawbox-cli.ts
Comment thread src/app/page.tsx
Comment thread src/components/SettingsApp.tsx
Comment thread src/tests/routes/chat-model.test.ts
- cli: validate CLAWBOX_ROOT against the SAFE_PATH guard (force-update.sh /
  updater.ts) before `sudo bash install.sh` β€” blocks a compromised env from
  running an attacker-controlled script.
- a11y: aria-label on the pairing-code input; type="button" on the desktop
  pairing-popup buttons.
- copy: Local AI Settings no longer says 'choose a different local engine'
  (Gemma 4 is the only engine since #206).
- docs: telegram-pairing spec now documents the desktop popup + its 20s
  ?poll=1 polling (the spec said 'no auto-poll').

Skipped: the chat-model.test fixture mode:"token" note β€” the route gates on
models.providers.*.apiKey, not the profile mode, so the fixture shape is inert.

@coderabbitai coderabbitai Bot left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Caution

Some comments are outside the diff and can’t be posted inline due to platform limitations.

⚠️ Outside diff range comments (1)
docs/superpowers/specs/2026-06-16-telegram-pairing-design.md (1)

47-48: ⚠️ Potential issue | 🟑 Minor | ⚑ Quick win

GET endpoint description is incomplete β€” missing ?poll=1 query parameter.

The GET endpoint description states pending is only populated with ?pending=1, but the actual implementation supports two modes:

  • ?poll=1 (fast file readβ€”for the desktop 20s poller)
  • ?pending=1 (slow CLIβ€”for manual Settings "Check" button)

Update lines 47–48 to document both pathways:

-  `pending` is only populated when `?pending=1` (opt-in to the slow CLI).
+  `pending` is only populated when `?poll=1` (fast, safe for polling) or `?pending=1` (slow CLI, authoritative for manual checks).

This aligns with the desktop popup behavior documented on lines 59–60 and the actual route implementation.

πŸ€– Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

In `@docs/superpowers/specs/2026-06-16-telegram-pairing-design.md` around lines 47
- 48, The GET endpoint description on lines 47-48 is incomplete and only
documents the `?pending=1` query parameter. Update the description to document
both supported query parameters: add `?poll=1` (fast file read used by the
desktop 20s poller) and `?pending=1` (slow CLI used for manual Settings "Check"
button). This will align the documentation with the actual implementation and
match the behavior documented on lines 59-60 regarding the desktop popup
behavior.
πŸ€– Prompt for all review comments with AI agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

Outside diff comments:
In `@docs/superpowers/specs/2026-06-16-telegram-pairing-design.md`:
- Around line 47-48: The GET endpoint description on lines 47-48 is incomplete
and only documents the `?pending=1` query parameter. Update the description to
document both supported query parameters: add `?poll=1` (fast file read used by
the desktop 20s poller) and `?pending=1` (slow CLI used for manual Settings
"Check" button). This will align the documentation with the actual
implementation and match the behavior documented on lines 59-60 regarding the
desktop popup behavior.

ℹ️ Review info
βš™οΈ Run configuration

Configuration used: Path: .coderabbit.yaml

Review profile: ASSERTIVE

Plan: Pro

Run ID: 4ced9fcb-8c56-448d-b725-3c6916665bcb

πŸ“₯ Commits

Reviewing files that changed from the base of the PR and between a691fc3 and bef8930.

πŸ“’ Files selected for processing (4)
  • docs/superpowers/specs/2026-06-16-telegram-pairing-design.md
  • mcp/clawbox-cli.ts
  • src/app/page.tsx
  • src/components/SettingsApp.tsx

@KrasimirKralev
KrasimirKralev merged commit 0e7f25c into main Jun 19, 2026
7 checks passed
KrasimirKralev added a commit that referenced this pull request Jul 5, 2026
… + review) (#248)

* feat(ci): ClawReview β€” our own advisory PR bot (policy + duplicates + review)

Clawsweeper-inspired PR bot, owned by us, complementing CodeRabbit:

- Structured advisory review on every PR (opened/reopened/synchronize):
  summary, source/test surface split, severity-ranked findings (P1-P3),
  duplicate detection vs open PRs + linked-issue validation, and a hidden
  <!-- clawreview-verdict:... --> marker for tooling
- Deterministic repo-policy checks (no AI needed): beta-first base-branch
  rule (docs/meta paths may target main), package.json<->bun.lock
  consistency, conventional title, tests-expected heuristic,
  security-sensitive-path flagging, size warning
- Auto area-labels from touched paths (same taxonomy as the issue-triage bot)
- Advisory by design: posts + updates ONE comment (upsert by marker, no spam
  on every push); never closes PRs; never fails the pipeline (exit 0 on any
  error); skips bot-authored PRs
- Security: pull_request_target with the base-repo checkout ONLY β€” PR code
  is never checked out or executed; the diff is reviewed as data via the API
  (capped at 80k chars); PR title/body/diff are declared untrusted in the
  system prompt
- Same hardening as the triage bot: SHA-pinned actions, job-scoped
  permissions, --prefix scripts SDK install, graceful no-op without
  ANTHROPIC_API_KEY (same pending secret)

Dry-run validated against real PRs: #243 (bot-skip fires), #238 (meta->main
passes base policy), #227 (device->beta passes; sensitive-path + tests
checks fire).

* feat(ci): ClawReview review fixes β€” empirically tuned policy, hardened plumbing

Four-angle /simplify review applied. The big one: replaying the policy
checks against the 40 most recently merged PRs showed 55% would have warned
(the routine release PR collected 5 warnings at once) β€” warnings tuned to
be rare enough to mean something:

- Release promotions (head beta -> base main) are the sanctioned path to
  main: exempted from feature-PR conventions (was 3/4 of base-check warns)
- Lockfile check is diff-aware: only warns when package.json DEPENDENCY
  sections change β€” version-only bumps never break --frozen-lockfile
  (6/6 historical warns on the naive check were false)
- 'release' added to the conventional-title types (the repo's own release
  convention was failing its own check)
- Tests-expected check gated to >=10 changed src lines (string-swap PRs
  were the main noise)
- SENSITIVE_RE: config/ narrowed to root-privilege files (was flagging
  every openclaw-target.txt version bump); added real misses (login-api
  route, rate limiters, oauth utils, credentials route, root-update-step.sh,
  launch-browser.sh, recover.sh); rendered as an ℹ️ note, not ⚠️, so
  warnings keep meaning

Plumbing (config + simplification reviews):
- upsertComment author-checked (a user comment starting with our marker
  can't be PATCH-overwritten) and single-page (bot comments early)
- --paginate + per-page '-q [...]' arrays would crash JSON.parse on
  >100-item PRs (we've had a 1,028-file PR) β€” files now fetched as JSONL
- drafts skipped (reviewed at ready_for_review; type added)
- bot-skip moved before the expensive gathering; dead 'dependabot' arm
  dropped; dead fetched fields trimmed; labels applied in one batched
  pr edit; duplicate render gated on likely && of
- reciprocal keep-in-sync comments at the two cross-bot drift points
  (area taxonomy, SDK version pin)

Re-validated by dry-run: #217 release promotion 5 warns -> 0 (1 pass +
1 info), #238 meta->main all-pass, #227 device->beta all-pass.

* feat(ci): give ClawReview its crab voice πŸ¦€

Playful frame, rigorous content: greeting, verdict badge, clean-bill line,
and sign-off carry the persona (Shipshape β€” claws up / Needs a molt /
Walking sideways / This shell looks occupied); policy checks and findings
stay strictly factual so a P1 never drowns in puns. Lines are picked
deterministically by PR number, keeping the upserted comment's voice stable
across pushes. The model's summary gets at most one marine flourish by
prompt; finding titles/details are instructed pun-free.

* feat(ci): optional ClawReview GitHub App identity (clawreview[bot] + crab avatar)

Both bots (pr-review + issue-triage) mint an installation token via
actions/create-github-app-token when the CLAWREVIEW_APP_ID +
CLAWREVIEW_APP_PRIVATE_KEY secrets exist β€” comments and labels then post as
clawreview[bot] with the App's avatar (and get the App's own rate limits).
Without the secrets the step skips and everything falls back to
github-actions[bot]; the bots work either way. Comment-upsert author check
accepts both identities so the switch-over edits the same comment.

* feat(ci): OAuth subscription transport + CodeRabbit fixes

Both bots now prefer the Claude Code CLI (claude -p, authed by
CLAUDE_CODE_OAUTH_TOKEN) β€” the official Pro/Max subscription path, same
runtime as claude-code-action and the team's crons β€” falling back to the
Anthropic SDK when only ANTHROPIC_API_KEY is set, and no-op without either.

- review()/main() split into reviewViaClaudeCli + reviewViaSdk (pr-review)
  and classifyViaClaudeCli + classifyViaSdk (issue-triage); selected by
  CLAUDE_CODE_OAUTH_TOKEN presence at runtime
- parseModelJson tolerates fenced/wrapped CLI output (json wrapper ->
  .result -> object); the SDK path keeps schema-enforced output
- workflows install the backend the available secret needs (CLI when OAuth,
  SDK otherwise), both pinned; token passed to the run step
- REVIEW_ONLY env prints the composed comment without posting, for local
  end-to-end testing of either transport

CodeRabbit (#248):
- top-level permissions: {} so the default token grant is empty (only the
  job's explicit scopes apply)
- bun.lock check: dependency-entry match now requires a version-spec-shaped
  value (^/~/digit/npm:/workspace:/git/url), so edits to scripts/name/etc.
  no longer misfire the 'dependencies changed' warning

Validated end-to-end via the OAuth CLI transport against PR #227: correct
verdict, crab voice, and a genuine P3 finding in gateway-pre-start.sh.
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.

2 participants