Skip to content

2026.08.05-rc

Pre-release
Pre-release

Choose a tag to compare

@MatthewSuttles MatthewSuttles released this 08 Aug 20:13
· 6 commits to main since this release
f46efea

This release turns a self-hosted hivemind into a server for the upcoming desktop companion app — device pairing, a full chat API with token-authenticated streaming, per-user notifications, and a guided Remote Access wizard for getting a public tunnel URL — alongside major delegation guardrails, LLM failover chains, and an in-app skill marketplace.

Features

Desktop companion support

  • Desktop pairing: authorize page, code exchange, revoke-self (#427) — Browser-approval pairing for desktop clients: the app opens a Devise-protected authorize page showing an editable device name, approval mints a one-time five-minute exchange code (never the raw token) delivered to a 127.0.0.1 loopback callback, and a PKCE-style code exchange redeems it for a device-named ApiToken. Codes are single-use with an atomic replay guard, paired devices appear on the existing API tokens page, and a bearer-authenticated revoke-self endpoint backs the app's sign-out.
  • Desktop chat API: session endpoints + bearer cable auth (#428) — api/v1/sessions gains create, full-transcript show with a processing flag (the client's single hydration call), multipart messages (routed through Sessions::ResolvePendingQuestion so ask_user replies work unchanged), interrupt (cancel/redirect/inject with sub-agent propagation), and rename with title_update broadcast. ActionCable now accepts Authorization: Bearer on the WebSocket handshake alongside the existing cookie auth. Shared session logic was extracted into a SessionChatActions concern used by the web, mobile, and API controllers — and this fixes a pre-existing bug where bearer-only api/v1 requests without a session cookie were rejected by Devise before token auth ran.
  • Per-user NotificationChannel + needs_input/errors categories (#426) — A new NotificationChannel streams notifications_user_#{id}; every WebPush::NotificationTriggers notification now broadcasts there alongside web push with a {category, title, body, session_id, agent_id, tag, timestamp} payload. Two new categories with settings toggles: needs_input (agent asked a question) and errors (session failed).
  • Remote Access: tunnel wizard, Cloudflare provisioning, cloudflared sidecar (#429) — An admin/owner-only Remote Access settings page for getting a public URL: bring-your-own-tunnel verification (HTTP health check plus a real /cable WebSocket handshake before setting the canonical host), or fully guided Cloudflare setup that creates the tunnel, ingress, and DNS CNAME via the API and runs cloudflared as a compose sidecar behind a tunnel profile controlled through docker-proxy. A recurring health check feeds an always-on status card with re-verify/restart/reconfigure/disconnect, secrets live in the encrypted vault store, and install.sh now asks about remote access and prints the wizard URL.

Delegation and orchestration

  • Spawn-time delegation guardrails behind Delegations::Request (#433) — All delegation guardrails consolidated into one service enforced before any LLM spend: a real depth limit (the delegate tool is stripped from a child's schema at max depth, replacing the old post-hoc callback suppression), a fan-out cap per parent session, duplicate-pending rejection, and team scoping. Limits configured via the delegation Setting key and clamped to hard ceilings so a bad setting can never disable runaway protection.
  • Shared orchestration budget across delegation trees (#434) — Per-agent budgets couldn't bound a fan-out's total cost. Each delegation tree now carries an orchestration_id, Delegations::OrchestrationBudget sums usage across the whole tree, and both choke points enforce it: over-budget trees can't spawn new delegations and their sessions are blocked from further LLM calls. Default $5 per tree, configurable and clamped to $100.
  • Remove dead TeamMessage delegation path (#430) — Deletes Agents::Orchestrate/Delegate/Communicate/Handoff and AgentTaskJob, none of which had live callers — AgentTaskJob was a stub that marked delegated tasks completed without executing anything. Real delegation via SubAgentTask/SubAgentJob is untouched; the orphaned team_messages table is dropped reversibly.

LLM reliability

  • Model/provider failover chains for LLM calls (#423) — When an LLM call fails with an unavailability-class error (auth, 429, 5xx, timeout, connection), it falls back through an ordered chain configured in agent.model_config["fallback_models"] — same-provider model strings or explicit {provider, model} entries. Implemented as a Providers::FailoverAdapter at the single resolver choke point, so chat, ToolLoop, and background jobs all get failover with no call-site changes. Content/validation errors and prompt-too-long still propagate untouched; every failover is logged, audit-logged, and tagged in usage.

Skills

  • In-app skill marketplace (browse & install from ClawHub) (#424) — Browse and search ClawHub's ~13k public skills from the Skills page and install with one click. Every install runs through the same SkillSecurityScanner pipeline as manual file import — flagged skills park in the existing review flow. Registry outages degrade to a friendly alert.

Integrations

  • Remove Nango and Composio integrations (#425) — Pipedream now covers third-party app integrations, making both aggregators redundant. Removes their executors, routes, and UI sections, with a data migration cleaning up seeded tool rows and vault credentials.

Fixes

  • Production boot crash from redundant authenticate_user! skip (#436) — A cross-PR interaction between the pairing and chat-API changes left Api::V1::DesktopPairingController skipping a Devise callback its parent had already removed, which raised at eager load and crashed the server at boot in production. Fixed, with a new eager-load spec so this class of error fails CI instead of taking down a deploy.

  • Desktop pairing approve never reached the loopback callback (#437) — form_with defaults to Turbo, which followed the 302 to the app's http://127.0.0.1 callback with fetch — blocked by the browser, so the exchange code never arrived. Both pairing forms now opt out of Turbo so the redirect is a plain top-level navigation.

  • Stale version string in the sidebar (#439) — The image bakes its version as an env var at build time, but the compose deploy passes the operator's .env into containers via env_file, so a stale HIVEMIND_VERSION pin there overrode it and the sidebar misreported what was running. The version is now baked into a file inside the image, which always wins; env var and git-describe remain as dev fallbacks.

  • Removed the Beta pill from the Team Chat nav item (#435)

  • Memory extraction stored the agent's name as the user's (#438) — Greeting an agent by name ("hey marty") was extracted as "the user's name is Marty": the extraction prompts never told the model who the agent was, so vocatives aimed at the agent accumulated as high-importance facts about the user's identity — until agents started greeting the user by their own name. Both extraction prompts now name the agent, treat vocatives as addressing the agent, and only record the user's name when stated about themselves. Verified against the live LLM in both directions.

Full Changelog: 2026.07.01...2026.08.05-rc