Repository navigation
Releases: usehivy/bridge
Release list
v1.0.1
Fixes
fix(harness/opencode): Default to fully autonomous permissions when bridge spawns opencode. The previous permission block only coverededit/bash/webfetchand only whenpermission_modewas set, leaving opencode'saskdefaults forexternal_directory/doom_loopand the hardcoded.envread carve-out in place — any of which would block a headless run. The new block emits an explicit granular allow-everything permission map, including overrides for**/.envand**/.env.*on both read and edit.
Full Changelog: v1.0.0...v1.0.1
v1.0.0
Bridge 1.0.0 — first major release. Bridge is now a thin translation shell between its HTTP/SSE/webhook API and an external coding-agent CLI subprocess (Claude Code or OpenCode) over the Agent Client Protocol (ACP). The in-house LLM harness has been removed.
Removed (breaking)
- In-house harness.
rig-coreprovider stack, conversation loop, verifier agent, immortal handoff, custom tools (Read,Edit,Bash, etc.), and LSP integration are gone. Bridge no longer ships a model client. POST /push/agents/{id}/conversations. SQLite + boot-timerestore_conversation(ACPsession/load) covers it.AgentDefinitionv2. Requiredharness: "claude" | "open_code"discriminator. Slimmedprovider(model, api_key, base_url, type) andconfig(permission_mode, disabled_tools, small_fast_model). Legacy v1 agents will not deserialize.
Added
- Per-harness adapters.
crates/harnesswithHarnessAdaptertrait.claude(wraps@agentclientprotocol/claude-agent-acp) andopen_code(wrapsopencode-ai). - One agent per bridge instance.
- Conversation persistence + restore across
docker stop/docker start. ACPsession/loadrebuilds model context from the harness's on-disk transcript. - SSE multi-attach +
Last-Event-IDresume. - Skill bundles with subdirectories, with
../absolute path rejection. DefaultBodyLimit::max(25 MiB)(overridable viaBRIDGE_MAX_BODY_BYTES).- Sentry error reporting. Set
SENTRY_DSNto capture errors + panics. Captures wired at: harness child subprocess exit, ACP driver exit, prompt failures, skill traversal/write failures, SSE broadcast lag, boot restore failures.
Verified
- 9-phase E2E suite green on both harnesses (
make test-e2e,make test-e2e-opencode).
See CHANGELOG for the full entry.
v0.22.3
Added
full_reasoningonresponse_completedevents. Mirrorsfull_response: reasoning_delta chunks are accumulated throughStreamAttempt.accumulated_reasoning, threaded throughPromptResponse → classify_turn_result → emit_turn_complete_events, and emitted alongsidefull_responseon theResponseCompletedSSE event. Lets downstream consumers dropreasoning_deltaevents from persistent storage without losing reasoning content — same pattern already used forresponse_chunk → message_end.full_response.
v0.22.2
Changed
DEV_BOX_TOOLSreminder text (crates/runtime/src/environment.rs) updated to match the tools actually shipped in the hiveloop dev-box sandbox image. Replacedchrome-devtools-axi 0.1.15 (port 9224),gh-axi, andchrome-headless-shellwithagent-browserand plaingh(auto-authenticated via the hiveloop git-credentials wrapper). Addedrtk,ripgrep(rg),ast-grep(sg),npm/npx, anduv/uvxto the list. Only fires whenBRIDGE_STANDALONE_AGENT=true.
v0.22.1 — verifier agent
Highlights
Verifier agent (config.verifier). Optional second LLM that judges, after every terminal-text turn, whether the main agent really finished or stopped prematurely. On needs_work + high (within max_reprompts_per_turn cap), bridge synthesizes a user-message re-prompt and resumes the same turn — the agent sees what looks like a normal user follow-up.
The verifier sees the agent's system prompt, full conversation text, and full tool I/O (head/tail-elided at 1000 chars/side). Frozen JSON-schema verdict shape (verdict, confidence, instruction) plus stable system-prompt bytes mean the verifier hits the upstream's prefix cache from call two onward. Failures (build errors, timeouts, parse failures) emit verifier_error and proceed — the verifier never blocks the agent.
Three new SSE events: verifier_started, verifier_verdict, verifier_error. Force-disable via BRIDGE_VERIFIER_DISABLED=1.
See: Verifier Agent, SSE → Verifier Events.
Changes
Added
- Verifier agent (
config.verifier) — see above.
Changed
VerifierProvider::OpenAIwire format normalized to"open_ai"(matchingcore::ProviderType::OpenAI). The serde-default"open_a_i"is rejected. Inline tests guard the rename. No impact on existing callers — the verifier is brand new in this release.
Fixed
artisan-testrtk filter now passes through unchanged. Laravel 13 shipslaravel/paowhich makesphp artisan testemit single-line JSON instead of the human-readable PHPUnit summary. The previous filter stripped every line that didn't match its hardcodedTests:/OK (...)patterns and left the agent with no test signal. The replacement filter wins precedence overartisan-zz-generic(which would otherwise truncate at 240 chars/line and mangle pao's JSON) but does no rewriting.- Tool-description tests (
*_description_is_rich). Restored phrases that the earlier tool-description trim removed butglobandreaddescription tests still asserted on.test-unithad been failing on every CI run since the trim landed.
Full changelog
https://github.com/usehiveloop/bridge/blob/v0.22.1/CHANGELOG.md
v0.22.0
Added
- Workspace artifacts (
AgentDefinition.artifacts). New optional config block (upload_url,download_url,max_size_bytes,accepted_file_types,max_concurrent_uploads,chunk_size_bytes,headers) that auto-registers anupload_to_workspacetool on the agent. The tool streams files from the agent's sandbox to the control plane via a tus.io v1.0.0 resumable upload protocol. Bridge handles per-chunk SHA-256 integrity checks, jittered exponential retry on 5xx/network errors (6 retries / 7 attempts),409 Conflictserver-offset realignment, and crash-resume from a newartifact_uploadssqlite table whenBRIDGE_STORAGE_PATHis set. Idempotency key issha256(agent_id || abs_path || file_sha256)— re-calling the tool with the same file returns the cached control-plane response. The tool result is a JSON object (artifact_id,upload_url,download_url,size,content_type,sha256). Agent push-time validation (AgentDefinition::validate()) rejects emptyaccepted_file_types, zeromax_size_bytes, malformed URLs, and zeromax_concurrent_uploads/chunk_size_bytes. Theartifactsfield is also exposed on theGET /agents/{id}response. ArtifactsConfigcore type andArtifactUploadRowstorage row. New modulebridge_core::artifacts; new sqlite tableartifact_uploadswith(idempotency_key, agent_id, conversation_id, location, total_size, file_sha256, bytes_sent, status, response_json, last_error, created_at, updated_at).config.system_reminder_refresh_turns— controls how often the stable system reminder (skills, subagents, todos) is re-emitted at the head of the user message. Default10; values<1clamp to1; always emitted on turn 0 and on turns whereturn_count % N == 0.- Sandbox environment system reminder. When
BRIDGE_STANDALONE_AGENT=true, bridge injects a system reminder describing the sandbox's resource limits and installed tools (crates/runtime/src/environment.rs). - Stall timeout + repeat-call guard. Resilience pass on the runtime: a per-turn stall timeout aborts hung LLM calls, and a repeat-call guard suppresses agents that re-fire the same tool with the same arguments back-to-back. (
feat(runtime): resilience pass — stall timeout, repeat-call guard, env reminder, strip fixes) cache_control+tool_choicemiddleware for the LLM provider stack, with head-merge behavior to avoid history loss between provider invocations. Addscrates/llm/src/providers/cache_control_middleware.rsandcrates/llm/src/providers/tool_choice_middleware.rs.
Changed
- Immortal mode rewritten as in-place forgecode-style compaction. The previous LLM-driven checkpoint extractor has been removed. Compaction now replaces the eligible head of the conversation in place with one user message containing a structured summary derived from the messages it replaced — pure code, deterministic, no LLM call.
ImmortalConfigis now{ token_budget, retention_window, eviction_window, expose_journal_tools }; the previous LLM-checkpoint fields (checkpoint_prompt,verify_checkpoint,checkpoint_max_tokens,checkpoint_timeout_secs,max_previous_checkpoints,carry_forward_budget_fraction) are gone. (feat(immortal): replace LLM checkpoint with forgecode-style in-place compaction) - Optional journal tools.
journal_read/journal_writeare now registered only whenconfig.immortalis set ANDimmortal.expose_journal_toolsis true (default). Agents without immortal mode no longer see journal tools. (feat(runtime): optional journal tools + todos-snapshot carry-forward) - Bash routed through rtk.
bashtool invocations are routed through the rtk filter pipeline for token-efficient output. An in-process allowlist router (replacing the earlierrtk-rewritedispatch) decides which commands get routed. Test-runner output (PHPUnit / Pest summary lines) is preserved verbatim — no syntheticartisan test: okcollapse. (feat(bash): route tool invocations through rtk for token-efficient output,fix(bash): replace rtk-rewrite dispatch with in-process allowlist router) - Trimmed verbose tool descriptions.
lsp(2862 → 1129 bytes),todowrite(2685 → 578),multiedit(2179 → 650),journal_write(2528 → 976). Removed tutorial-style "when to use / when not to use" sections, duplicated language lists, redundant "CRITICAL REQUIREMENTS" / "WARNING" blocks. (fix(immortal,prompt): plug strip leak; trim system-reminder + tool descriptions)
Fixed
history_stripleak inside rig's loop. Strip previously fired only at the top of each bridge turn, so single-bridge-turn agents (where everything happens inside rig's loop) saw oldReadresults, PHPUnit dumps, etc. accumulate unchecked. Strip now fires insideconversation/run.rs's resume loop too, after the immortal hook's cancellation history is promoted. (fix(immortal,prompt): plug strip leak; …)- Refactor: split
supervisor,conversation,agent_runnerinto sub-modules.crates/runtime/src/supervisor.rs,conversation.rs, andagent_runner.rsare now directories with focused submodules (each file under ~300 lines). Public API is unchanged; references to the old single-file paths in docs have been updated. (refactor(runtime): split supervisor/conversation/agent_runner below 300 lines)
Infrastructure
- New sqlite migration adds the
artifact_uploadstable with indexes onstatusandagent_id. Migrations remain idempotent (IF NOT EXISTS). - Workspace deps:
tokio-utilfeatures extended to["rt", "io"]; new entrieshex,mime_guess,bytes(intoolscrate).toolsdev-deps addaxumfor the in-process TUS test server.
v0.21.1
Changed
- Subagent execution timeout is now per-agent configurable via
AgentConfig.subagent_timeout_foreground_secsandAgentConfig.subagent_timeout_background_secs(seconds, bothOption<u64>). Each subagent's own config supplies its timeout;__self__self-delegation reads from the parent agent's config. Default raised to 300s (5 min) for both foreground and background (previously hardcoded 120s foreground / 300s background).
Infrastructure
- `openapi.json` regenerated — publishes the two new `AgentConfig` fields.
v0.21.0
Added
- Declarative tool-call requirements (
config.tool_requirements). Declare tools the agent MUST call per turn with cadence (every_turn,first_turn_only,every_n_turns {n}— "reset on call"), position (anywhere,turn_start,turn_end— lenient about read-only tools liketodoread/journal_read), minimum call count, and enforcement variant (next_turn_reminderdefault,warn,reprompt). Tool-name matching is flexible: patterns without__also match MCP tools registered as{server}__{name}, so"post_message"matchesslack__post_message. Bridge rejects pushes where a required tool also appears indisabled_tools(400 InvalidRequest). Violations fire atool_requirement_violatedevent and — for non-warnenforcement — attach a<system-reminder>block to the next user message naming the missing tool(s). full_messagefield onPOST /conversations/{id}/messages. Offload large payloads (stack traces, log dumps, file contents) to disk instead of inflating context on every turn. Bridge writesfull_messageto{BRIDGE_ATTACHMENTS_DIR | ./.bridge-attachments}/{conversation_id}/{uuid}.txt, appends a<system-reminder>tocontentpointing the agent at the absolute path, and tailors the tool hint to the agent's registered tools (RipGrep+Read, just one of them,AstGrep, orbashwith a "don'tcat" warning, or an explicit "no search tool registered" note). Missingcontentis auto-summarized from the first ~500 bytes offull_messagerather than rejected. Attachments are cleaned up when the conversation ends. Disk failures are logged and the message is delivered without the attachment —full_messagecan never cause a send-message rejection. Themessage_receivedevent now carries anattachment_pathfield (null when no attachment).BRIDGE_ATTACHMENTS_DIRenv var — overrides the attachments root directory (default./.bridge-attachments).ChainFailedandContextPressureWarningSSE/webhook events.ChainFailedfires when a chain handoff attempt errors out (the conversation continues with oversized history).ContextPressureWarningfires once per turn when cumulative tool-output bytes exceed ~1.5× the immortal token budget.- Provider-aware checkpoint prompt. The default checkpoint extraction prompt is now provider-aware. Gemini models (detected by
ProviderType::Googleor model-name substring) automatically receive a stricter XML-delimited template with explicit per-section length caps and active-verb pruning directives. In testing this arrested Gemini 2.5 Flash's monotonic checkpoint-size growth (4k → 7k → 15k bytes over 3 chains with the old prompt) to a flat ~9k across 4 chains. Other providers fall through to the existing default. Override per-agent viaconfig.immortal.checkpoint_prompt. - Rich
turn_completedevent payload. Now includesturn_latency_ms,cumulative_tool_calls,history_tokens_estimate(tiktoken count of current history — the same signal chain checks use),history_message_count, andjournal_entries_committed. ImmortalConfignew fields.carry_forward_budget_fraction(default0.3) caps the carry-forward tail at a fraction oftoken_budget.verify_checkpoint(defaultfalse) controls the optional phase-2 verification pass.checkpoint_max_tokens(default1500) caps checkpoint LLM output.checkpoint_timeout_secs(default45) bounds the extraction call.max_previous_checkpoints(default2) limits how many prior chain checkpoints feed the next extraction — prevents unbounded chain-over-chain growth.
Changed
- Immortal chain-event ordering.
ChainStartednow fires BEFORE the checkpoint extraction LLM call (previously fired after). SSE consumers can now render progress UI during the 7-75s extraction window.ChainCompletedpayload addsduration_ms,carry_forward_tokens,checkpoint_bytes,verified. - Token-bounded carry-forward. Replaces turn-count-only.
carry_forward_budget_fraction(default 30% of budget) caps the tail, preventing a single tool-heavy turn from stuffing the new chain's context. - Single-phase checkpoint by default.
verify_checkpointnow defaults tofalse— the phase-2 verification pass rarely improves output for strong summarizer models and ~doubles cost. - Journal writes stage per turn.
journal_writetool calls now stage in-memory and commit only on turn success (or discard on failure). Prevents duplicate/orphan entries from rolled-back turns. Chain-checkpoint entries (system-generated) still persist immediately.
Fixed
- History restoration on mid-turn LLM errors. When the agent's LLM call errored mid-turn (429, provider error), bridge truncated the persisted-messages side but left the in-memory rig history as the
mem::take'd emptyVec. Subsequent turns silently started from empty history, defeating chain-token checks. Now restored from the pre-turn backup on the same error path the timeout/cancel paths already used. - Pre-stream LLM retry. Retryable upstream errors (429/5xx/timeouts) that occur BEFORE any delta is emitted are now retried with exponential backoff (up to 3 attempts). Safe because we bail on any streaming progress.
send_message4xx on empty body restored.contentis now#[serde(default)]so callers can supply onlyfull_message, but an empty request with neither field still returns 400 InvalidRequest — preserving the pre-attachments behavior that malformed bodies like{"invalid": true}return 4xx.
Infrastructure
openapi.jsonregenerated — publishes the newToolRequirement,RequirementCadence,RequirementPosition,RequirementEnforcementschemas and thefull_messagefield onSendMessageRequest.- New
scripts/immortal-real-test.mjsstandalone driver — exercises the full immortal flow with a real LLM against a live bridge, streams SSE events, and prints a deep post-run report.
v0.20.1 — LSP installer cleanup + tolerant failures
Changed
- `bridge install-lsp` catalog trimmed. Servers whose only distribution is via niche toolchains (opam, gem, dart pub, dotnet tool, cs/Coursier) were dropped — each was reliably failing with `No such file or directory` on stock dev boxes. Placeholder entries that only `echo`'d setup instructions (haskell, nixd, julials, sourcekit-lsp, old deno) were also dropped. Removed ids: `ocaml-lsp`, `ruby-lsp`, `ruby-lsp-official`, `dart`, `metals`, `csharp`, `haskell`, `nixd`, `julials`, `sourcekit-lsp`. The `InstallMethod::{Gem, LuaRocks, Opam, Stack}` enum variants and their install paths are deleted as dead code.
- `deno` re-added as a real install via the official `install.sh` with `DENO_INSTALL=$HOME/.local`, so the binary lands in `~/.local/bin/deno` alongside the other self-contained downloads.
- Per-server install failures are non-fatal. `bridge install-lsp ` downgrades individual failures from error to warning and always exits 0. The final log summarises which ids were skipped so the operator can install the missing toolchain and re-run that specific id. Previously one missing `opam` would make the whole command exit 1.
Bundled servers (30 total)
- JavaScript/TypeScript: typescript, eslint, biome, deno, vue, svelte, astro, tailwindcss
- Systems: rust, go, zig, clangd
- Python: python (pyright), ruff, pylsp
- Config / infra: yaml-ls, dockerfile, terraform, graphql, cmake, ansible
- JVM / BEAM: jdtls (Java), elixir-ls, clojure-lsp
- Misc: php, bash, prisma, elm, tinymist (Typst), vimls
If a server you want isn't bundled, install its binary yourself (homebrew, nix, ghcup, opam, gem, ...) and put it on `PATH` — bridge's runtime still recognizes the server id and will launch it.
v0.20.0 — subagent orchestration unified; ast_grep + rip_grep
Breaking changes
Subagent orchestration simplified to match Claude Code's model.
- Removed
parallel_agentandjointools. Fan-out is now achieved by emitting multiplesub_agenttool_use blocks in a single assistant turn — the runtime already dispatches tool calls concurrently. No tasks-array wrapper needed. - Renamed
background→runInBackgroundon thesub_agentandagenttools, matching Claude Code'srun_in_background. - Background subagent outputs are auto-injected into the parent's next user turn as
[Background Agent Task Completed]messages; no explicit wait/join call is needed. TaskRegistryremoved.AgentContext.task_registrygone;AgentState::newno longer takes atask_registryargument.- Net: ~1,100 lines deleted, zero behavioural regressions across the 640+ workspace tests.
Migration
- Rename `"background": true` → `"runInBackground": true` in system prompts, agent definitions, and any code constructing tool calls.
- Replace `parallel_agent` call sites with multiple `sub_agent` tool_use blocks in the same turn.
- Remove any use of `join` — background results arrive automatically.
- Drop `parallel_agent` and `join` from any `tools` allowlist or `disabled_tools` list.
New
Search tools
- Replaced the generic `grep` tool with two focused tools:
- `RipGrep` — regex/text search over file contents (ripgrep-powered).
- `AstGrep` — structural code search using ast-grep patterns.
LSP
- `e2e/lsp-smoke` — dockerized LSP integration harness.
- Hardening across `crates/lsp` (error, installer, manager, server, integration tests).
CI
- `cargo fmt`, clippy 1.95 compatibility, and e2e-harness timeout bumps.
Docs
- Full rewrite of `docs/tools-reference/agent-tools.md` for the single-tool model.
- Updated tool indexes, core concepts, architecture deep-dive, and the multi-agent tutorial.
- Migration guide in `docs/reference/changelog.md`.