Repository navigation
v2.2.0
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
RunAgentandRunStepnow ownArc<ActionRegistry>+Arc<dyn BrowserPort>+Arc<dyn EventBus>.- Each
ActionInvocationfrom the LLM is dispatched viaregistry.get(&name)andhandler.execute(params, ctx).await. Results land inStepRecord.resultsand 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), andterminates_sequenceflag. - Includes the exact
AgentOutputJSON 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
donecheck honorsresults.is_doneonly.- 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
ActionRegistryviaregister_default_actions(navigate, click_element, click_coordinate, type_text, scroll, screenshot, wait, done). - Threads
ChromiumoxideAdapterasArc<dyn BrowserPort>andBroadcastBusasArc<dyn EventBus>intoRunAgent::new. max_stepsraised from 2 to 10.
Tests
- New
ras-agent/tests/run_agent_executor_test.rswith mockBrowserPort+ scriptedLlmClient:agent_navigates_then_completes— assertsNavigateActionreaches the browser andDoneActionterminates with the expectedfinal_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 anActionRegistry(typically viaras_tools::infrastructure::builtin::register::register_default_actions) and pass anArc<dyn BrowserPort>+Arc<dyn EventBus>.RunStep::newgains 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 passcargo clippy --workspace --all-targets -- -D clippy::unwrap_used -D clippy::dbg_macro— cleancargo fmt --all -- --check— cleancargo 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 at2.2.0
Pull requests
Full changelog: v2.1.0...v2.2.0