Skip to content

Releases: usehivy/bridge

v1.0.1

Choose a tag to compare

@bahdcoder bahdcoder released this 03 May 05:25

Fixes

  • fix(harness/opencode): Default to fully autonomous permissions when bridge spawns opencode. The previous permission block only covered edit/bash/webfetch and only when permission_mode was set, leaving opencode's ask defaults for external_directory / doom_loop and the hardcoded .env read 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 **/.env and **/.env.* on both read and edit.

Full Changelog: v1.0.0...v1.0.1

v1.0.0

Choose a tag to compare

@bahdcoder bahdcoder released this 02 May 20:58

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-core provider 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-time restore_conversation (ACP session/load) covers it.
  • AgentDefinition v2. Required harness: "claude" | "open_code" discriminator. Slimmed provider (model, api_key, base_url, type) and config (permission_mode, disabled_tools, small_fast_model). Legacy v1 agents will not deserialize.

Added

  • Per-harness adapters. crates/harness with HarnessAdapter trait. claude (wraps @agentclientprotocol/claude-agent-acp) and open_code (wraps opencode-ai).
  • One agent per bridge instance.
  • Conversation persistence + restore across docker stop / docker start. ACP session/load rebuilds model context from the harness's on-disk transcript.
  • SSE multi-attach + Last-Event-ID resume.
  • Skill bundles with subdirectories, with ../absolute path rejection.
  • DefaultBodyLimit::max(25 MiB) (overridable via BRIDGE_MAX_BODY_BYTES).
  • Sentry error reporting. Set SENTRY_DSN to 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

Choose a tag to compare

@bahdcoder bahdcoder released this 01 May 17:38

Added

  • full_reasoning on response_completed events. Mirrors full_response: reasoning_delta chunks are accumulated through StreamAttempt.accumulated_reasoning, threaded through PromptResponse → classify_turn_result → emit_turn_complete_events, and emitted alongside full_response on the ResponseCompleted SSE event. Lets downstream consumers drop reasoning_delta events from persistent storage without losing reasoning content — same pattern already used for response_chunk → message_end.full_response.

v0.22.2

Choose a tag to compare

@bahdcoder bahdcoder released this 30 Apr 04:07

Changed

  • DEV_BOX_TOOLS reminder text (crates/runtime/src/environment.rs) updated to match the tools actually shipped in the hiveloop dev-box sandbox image. Replaced chrome-devtools-axi 0.1.15 (port 9224), gh-axi, and chrome-headless-shell with agent-browser and plain gh (auto-authenticated via the hiveloop git-credentials wrapper). Added rtk, ripgrep (rg), ast-grep (sg), npm/npx, and uv/uvx to the list. Only fires when BRIDGE_STANDALONE_AGENT=true.

v0.22.1 — verifier agent

Choose a tag to compare

@bahdcoder bahdcoder released this 30 Apr 03:38

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::OpenAI wire format normalized to "open_ai" (matching core::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-test rtk filter now passes through unchanged. Laravel 13 ships laravel/pao which makes php artisan test emit single-line JSON instead of the human-readable PHPUnit summary. The previous filter stripped every line that didn't match its hardcoded Tests: / OK (...) patterns and left the agent with no test signal. The replacement filter wins precedence over artisan-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 but glob and read description tests still asserted on. test-unit had 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

Choose a tag to compare

@bahdcoder bahdcoder released this 26 Apr 13:22

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 an upload_to_workspace tool 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 Conflict server-offset realignment, and crash-resume from a new artifact_uploads sqlite table when BRIDGE_STORAGE_PATH is set. Idempotency key is sha256(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 empty accepted_file_types, zero max_size_bytes, malformed URLs, and zero max_concurrent_uploads / chunk_size_bytes. The artifacts field is also exposed on the GET /agents/{id} response.
  • ArtifactsConfig core type and ArtifactUploadRow storage row. New module bridge_core::artifacts; new sqlite table artifact_uploads with (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. Default 10; values <1 clamp to 1; always emitted on turn 0 and on turns where turn_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_choice middleware for the LLM provider stack, with head-merge behavior to avoid history loss between provider invocations. Adds crates/llm/src/providers/cache_control_middleware.rs and crates/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. ImmortalConfig is 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_write are now registered only when config.immortal is set AND immortal.expose_journal_tools is true (default). Agents without immortal mode no longer see journal tools. (feat(runtime): optional journal tools + todos-snapshot carry-forward)
  • Bash routed through rtk. bash tool invocations are routed through the rtk filter pipeline for token-efficient output. An in-process allowlist router (replacing the earlier rtk-rewrite dispatch) decides which commands get routed. Test-runner output (PHPUnit / Pest summary lines) is preserved verbatim — no synthetic artisan test: ok collapse. (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_strip leak 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 old Read results, PHPUnit dumps, etc. accumulate unchecked. Strip now fires inside conversation/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_runner into sub-modules. crates/runtime/src/supervisor.rs, conversation.rs, and agent_runner.rs are 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_uploads table with indexes on status and agent_id. Migrations remain idempotent (IF NOT EXISTS).
  • Workspace deps: tokio-util features extended to ["rt", "io"]; new entries hex, mime_guess, bytes (in tools crate). tools dev-deps add axum for the in-process TUS test server.

v0.21.1

Choose a tag to compare

@bahdcoder bahdcoder released this 19 Apr 16:44

Changed

  • Subagent execution timeout is now per-agent configurable via AgentConfig.subagent_timeout_foreground_secs and AgentConfig.subagent_timeout_background_secs (seconds, both Option<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

Choose a tag to compare

@bahdcoder bahdcoder released this 19 Apr 05:43

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 like todoread / journal_read), minimum call count, and enforcement variant (next_turn_reminder default, warn, reprompt). Tool-name matching is flexible: patterns without __ also match MCP tools registered as {server}__{name}, so "post_message" matches slack__post_message. Bridge rejects pushes where a required tool also appears in disabled_tools (400 InvalidRequest). Violations fire a tool_requirement_violated event and — for non-warn enforcement — attach a <system-reminder> block to the next user message naming the missing tool(s).
  • full_message field on POST /conversations/{id}/messages. Offload large payloads (stack traces, log dumps, file contents) to disk instead of inflating context on every turn. Bridge writes full_message to {BRIDGE_ATTACHMENTS_DIR | ./.bridge-attachments}/{conversation_id}/{uuid}.txt, appends a <system-reminder> to content pointing the agent at the absolute path, and tailors the tool hint to the agent's registered tools (RipGrep + Read, just one of them, AstGrep, or bash with a "don't cat" warning, or an explicit "no search tool registered" note). Missing content is auto-summarized from the first ~500 bytes of full_message rather than rejected. Attachments are cleaned up when the conversation ends. Disk failures are logged and the message is delivered without the attachment — full_message can never cause a send-message rejection. The message_received event now carries an attachment_path field (null when no attachment).
  • BRIDGE_ATTACHMENTS_DIR env var — overrides the attachments root directory (default ./.bridge-attachments).
  • ChainFailed and ContextPressureWarning SSE/webhook events. ChainFailed fires when a chain handoff attempt errors out (the conversation continues with oversized history). ContextPressureWarning fires 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::Google or 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 via config.immortal.checkpoint_prompt.
  • Rich turn_completed event payload. Now includes turn_latency_ms, cumulative_tool_calls, history_tokens_estimate (tiktoken count of current history — the same signal chain checks use), history_message_count, and journal_entries_committed.
  • ImmortalConfig new fields. carry_forward_budget_fraction (default 0.3) caps the carry-forward tail at a fraction of token_budget. verify_checkpoint (default false) controls the optional phase-2 verification pass. checkpoint_max_tokens (default 1500) caps checkpoint LLM output. checkpoint_timeout_secs (default 45) bounds the extraction call. max_previous_checkpoints (default 2) limits how many prior chain checkpoints feed the next extraction — prevents unbounded chain-over-chain growth.

Changed

  • Immortal chain-event ordering. ChainStarted now fires BEFORE the checkpoint extraction LLM call (previously fired after). SSE consumers can now render progress UI during the 7-75s extraction window. ChainCompleted payload adds duration_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_checkpoint now defaults to false — the phase-2 verification pass rarely improves output for strong summarizer models and ~doubles cost.
  • Journal writes stage per turn. journal_write tool 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 empty Vec. 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_message 4xx on empty body restored. content is now #[serde(default)] so callers can supply only full_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.json regenerated — publishes the new ToolRequirement, RequirementCadence, RequirementPosition, RequirementEnforcement schemas and the full_message field on SendMessageRequest.
  • New scripts/immortal-real-test.mjs standalone 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

Choose a tag to compare

@bahdcoder bahdcoder released this 17 Apr 18:32

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

Choose a tag to compare

@bahdcoder bahdcoder released this 17 Apr 17:06

Breaking changes

Subagent orchestration simplified to match Claude Code's model.

  • Removed parallel_agent and join tools. Fan-out is now achieved by emitting multiple sub_agent tool_use blocks in a single assistant turn — the runtime already dispatches tool calls concurrently. No tasks-array wrapper needed.
  • Renamed background → runInBackground on the sub_agent and agent tools, matching Claude Code's run_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.
  • TaskRegistry removed. AgentContext.task_registry gone; AgentState::new no longer takes a task_registry argument.
  • 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`.