Skip to content

v2.2.0

Choose a tag to compare

@github-actions github-actions released this 10 May 03:43
· 100 commits to main since this release
d05fbdb

Highlights

Agent executor lands. The LLM → browser circuit now closes end-to-end. Before this release, RunAgent::execute had no browser dependency, StepRecord.results was hardcoded Vec::new(), and the system prompt didn't list any actions — the browser session opened and idled. As of v2.2.0, planned actions actually run.

What's new

ras-agent — wired to browser and tools

  • RunAgent and RunStep now own Arc<ActionRegistry> + Arc<dyn BrowserPort> + Arc<dyn EventBus>.
  • Each ActionInvocation from the LLM is dispatched via registry.get(&name) and handler.execute(params, ctx).await. Results land in StepRecord.results and feed into the next step's prompt.
  • Per-step page URL captured via BrowserPort::evaluate("location.href").
  • Loop detector hashes are recorded post-dispatch so failed actions still count.

Prompt — knows what the browser can do

  • System prompt enumerates every registered action: name, description, parameters_schema (JSON), and terminates_sequence flag.
  • Includes the exact AgentOutput JSON shape so models stop guessing the wire format.
  • Step results (truncated) are echoed back to the model on subsequent turns.

Termination — empty plans no longer count as success

  • done check honors results.is_done only.
  • Empty action lists trigger a stall counter; 2 consecutive empties abort the run with a tracing::error!. Previously this was the only way the loop terminated successfully — a bug masked by the missing executor.

Example — claude_code_oauth_cosmium now actually surfs

  • Builds ActionRegistry via register_default_actions (navigate, click_element, click_coordinate, type_text, scroll, screenshot, wait, done).
  • Threads ChromiumoxideAdapter as Arc<dyn BrowserPort> and BroadcastBus as Arc<dyn EventBus> into RunAgent::new.
  • max_steps raised from 2 to 10.

Tests

  • New ras-agent/tests/run_agent_executor_test.rs with mock BrowserPort + scripted LlmClient:
    • agent_navigates_then_completes — asserts NavigateAction reaches the browser and DoneAction terminates with the expected final_result.
    • agent_aborts_after_consecutive_empty_actions — verifies the 2-streak stall guard fires within budget.

Breaking changes

  • RunAgent::new(task, llm) → RunAgent::new(task, llm, registry, browser, events). Callers must build an ActionRegistry (typically via ras_tools::infrastructure::builtin::register::register_default_actions) and pass an Arc<dyn BrowserPort> + Arc<dyn EventBus>.
  • RunStep::new gains the same three trailing args.

No external consumers of these signatures existed prior to v2.2.0; the only in-tree caller (examples/claude_code_oauth_cosmium.rs) is updated in this release.

Reproduction

Before v2.2.0:

$ RAS_MODEL=anthropic/claude-haiku-4.5 cargo run --release
[done] (no final result returned)   # 1 LLM call, empty action[], exits at step 0

After v2.2.0: actions execute, browser navigates, done carries the final answer.

Verification

  • cargo test --workspace --no-fail-fast — 97 test groups pass
  • cargo clippy --workspace --all-targets -- -D clippy::unwrap_used -D clippy::dbg_macro — clean
  • cargo fmt --all -- --check — clean
  • cargo doc --workspace --no-deps — clean

Artifacts

  • Linux x86_64: ras-x86_64-unknown-linux-gnu, ras-daemon-x86_64-unknown-linux-gnu
  • macOS arm64: ras-aarch64-apple-darwin, ras-daemon-aarch64-apple-darwin
  • crates.io: all ras-* workspace crates published at 2.2.0

Pull requests

  • #20 — feat(agent): close LLM→browser circuit (v2.2.0)
  • #21 — release: v2.2.0 (agent executor)

Full changelog: v2.1.0...v2.2.0