Skip to content

feat(cast-agent): boot runtime + gateway status pill#26

Merged
BunsDev merged 3 commits into
mainfrom
feat/cast-agent-integration
May 16, 2026
Merged

feat(cast-agent): boot runtime + gateway status pill#26
BunsDev merged 3 commits into
mainfrom
feat/cast-agent-integration

Conversation

@BunsDev

@BunsDev BunsDev commented May 16, 2026

Copy link
Copy Markdown
Member

Summary

First integration slice for the Cast Agent backend that landed in #25 as a skeleton. Picks the smallest end-to-end consumer — a gateway status pill in the agent panel header — to validate the runtime and global-handle plumbing without taking on message-flow, session, or streaming work yet.

  • Dedicated tokio runtime on a background OS thread (crates/cast_agent/src/runtime.rs). CastAgentRuntime::boot() builds a 2-worker multi-thread runtime, blocks-on CastAgent::new(), then spawns a 30s recurring GET /health probe so is_available() reflects current state.
  • Global handle via OnceLock<CastAgentRuntime> so callers share one instance; runtime::is_available() is a sync atomic read safe to call on every render frame.
  • crates/ai facade — new ai::cast_agent::* module gated by the existing cast-agent feature, re-exporting the runtime entry points so app/src depends on ai, not directly on cast_agent.
  • Eager boot at app startuprun() in app/src/lib.rs initializes the runtime right after init_feature_flags() so the first render doesn't pay the OnceLock boot cost.
  • Status pillrender_gateway_status_pill() in app/src/ai_assistant/panel.rs draws an 8px brand-colored dot in the agent panel header. Green (#22C55E) when the gateway responds to GET /health, amber (#F59E0B) when it doesn't.

Feature wiring

  • New cast-agent = ["ai/cast-agent"] feature on warp-app so app/src can use #[cfg(feature = "cast-agent")] directly. Bundled into gui (gui = ["voice_input", "cast-agent"]) so the OSS graphical build ships with the pill enabled — headless builds skip the tokio runtime + reqwest cost.
  • crates/cast_agent now pulls in the workspace async-trait dep because AgentBackend was promoted to a #[async_trait] trait in a follow-up commit to PR feat: apply OpenCoven brand + scaffold Cast Agent crate #25.

Verification

Command Result
cargo check -p cast_agent
cargo check -p ai
cargo check -p ai --features cast-agent ✅ (cached)
cargo check -p warp-app --bin cast-codes --features gui ✅ 1m 33s
cargo check -p warp-app --bin cast-codes --features gui,cast-agent
./script/check_rebrand

Design choices

  • Dedicated thread, not block_on: avoids blocking the UI thread on every async call; future session/streaming work can handle.spawn(...) on the same runtime.
  • Cached atomic, not request-per-render: is_available() reads an AtomicBool::Acquire; the background probe writes it. Render-loop friendly.
  • Lazy OnceLock + eager startup hint: the runtime initializes on first access regardless, but run() warms it eagerly so the cost lands at boot, not in a render frame.
  • Feature mirror, not direct dep: app depends on ai::cast_agent rather than the cast_agent crate so the feature gate remains a single source of truth and future facade work (telemetry wrappers, etc.) has a place to live.

Out of scope (next follow-ups)

Documented in CAST-AGENT.md:

  • Session list + click-through (clicking a Coven session opens a terminal pane at the session CWD).
  • Streaming responses via tokio-tungstenite.
  • Per-call #[cfg(feature = "warp-agent")] gating of warp_* deps inside crates/ai.

Test plan

  • Launch CastCodes; open the agent panel. With no gateway running, the status pill should show amber within a second.
  • Run a local Coven Gateway on http://localhost:3000 answering 200 OK on GET /health; within 30 seconds, the pill should flip to green.
  • Stop the gateway; within ~30s the pill should return to amber.
  • Confirm no UI-thread stalls when opening the panel (eager boot should make startup smooth).
  • Build with --no-default-features --features minimal and confirm the cast_agent runtime is not pulled in.

BunsDev and others added 3 commits May 16, 2026 03:59
PRODUCT + TECH specs for upgrading the existing browser pane
(app/src/browser/) into a secure, agent-driven design/UX layer:

- Toolbar + tab strip restyle matching the comux reference.
- Titlebar toggle button, View menu mirror, command palette, ⌘⌥B keymap.
- Global persistence of pane open/closed state and tab list.
- Per-app private WebKit data dir, popup interception, gated DevTools,
  bundled tracker/ad blocklist.
- Agent surface (screenshot, evaluate, element picker, console/network
  capture, navigation API) exposed via warpui actions and an in-process
  MCP server discoverable through ~/.cast-codes/mcp.json.

Builds on prior pane work (390efd4, multi-tab support) without
migrating away from the existing wry-direct architecture.

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
Implementation plan for the first of four sequential subprojects:
toolbar/tab-strip restyle, ToggleBrowserPane action with ⌘⌥B keymap +
titlebar toggle button, persistence of pane state + tabs across
restarts. Security hardening, agent surface, and MCP server are
deferred to PLAN-02 / PLAN-03 / PLAN-04.

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
Wires the Cast Agent backend end-to-end as the agent panel's first live
consumer — small enough to validate the runtime + global handle plumbing,
intentionally narrow so message-flow and session integration land in
later PRs.

What's new:
- `crates/cast_agent/src/runtime.rs` — owns a dedicated multi-threaded
  tokio runtime on a background OS thread. `CastAgentRuntime::boot()`
  builds the runtime, blocks-on `CastAgent::new()`, and spawns a 30s
  recurring health probe so `is_available()` reflects current state.
- `runtime::global()` exposes a `OnceLock<CastAgentRuntime>` so callers
  get a single shared instance; `runtime::is_available()` is a sync
  atomic read safe to call on every render frame.
- `crates/ai/src/lib.rs` — adds a `cast_agent` module facade (gated by
  the existing `cast-agent` feature) re-exporting the runtime entry
  points so `app/src` depends on `ai::cast_agent::*` rather than the
  cast_agent crate directly.
- `app/src/lib.rs` — `run()` eagerly initializes the runtime right
  after `init_feature_flags()` so the first UI render doesn't pay the
  `OnceLock` boot cost. Gated by `cfg(feature = "cast-agent")`.
- `app/src/ai_assistant/panel.rs` — `render_gateway_status_pill()`
  draws an 8px brand-colored dot in the agent panel header. Green
  when the gateway responds to `GET /health`, amber when it doesn't.
- `app/src/ai/coven_brand.rs` — `OPENCOVEN_SUCCESS` (#22C55E) and
  `OPENCOVEN_WARNING` (#F59E0B), matching the brand palette already
  applied in `castcodes_dark`.

Feature wiring:
- `app/Cargo.toml` — new `cast-agent = ["ai/cast-agent"]` feature so
  `app/src` can use `#[cfg(feature = "cast-agent")]` directly. Bundled
  into `gui` so the OSS graphical build ships with the pill enabled;
  headless builds skip the tokio runtime + reqwest cost.
- `crates/cast_agent/Cargo.toml` — adds `async-trait` workspace dep
  (the `AgentBackend` trait now uses `#[async_trait]` for object
  safety, mirroring the rest of the workspace).

Verified:
- `cargo check -p cast_agent` ✅
- `cargo check -p ai` ✅
- `cargo check -p ai --features cast-agent` ✅
- `cargo check -p warp-app --bin cast-codes --features gui` ✅ (1m 33s)
- `cargo check -p warp-app --bin cast-codes --features gui,cast-agent` ✅
- `./script/check_rebrand` ✅

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
@BunsDev BunsDev self-assigned this May 16, 2026
@BunsDev
BunsDev requested a review from Copilot May 16, 2026 10:03

Copilot AI left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Pull request overview

Introduces the first end-to-end integration slice of the Cast Agent backend into the GUI by booting a dedicated Tokio runtime with a process-wide handle and surfacing gateway reachability via a small status pill in the agent panel header. The PR also adds a set of Browser Panel spec/plan documents under specs/.

Changes:

  • Add cast_agent::runtime (singleton runtime + periodic /health probe) and re-export it via an ai::cast_agent facade.
  • Eagerly boot the runtime at app startup and render a gateway status pill (green/amber) in the AI assistant panel header.
  • Add new Browser Panel product/tech specs and an implementation plan under specs/CASTCODES-BROWSER-PANEL/.

Reviewed changes

Copilot reviewed 13 out of 14 changed files in this pull request and generated 5 comments.

Show a summary per file
File Description
specs/CASTCODES-BROWSER-PANEL/TECH.md Adds a technical spec for a future Browser Panel implementation.
specs/CASTCODES-BROWSER-PANEL/PRODUCT.md Adds a product spec defining Browser Panel UX/security/agent goals.
specs/CASTCODES-BROWSER-PANEL/PLAN-01-ui-toggle-persistence.md Adds a detailed step-by-step implementation plan for Browser Panel UI/toggle/persistence.
crates/cast_agent/src/runtime.rs Implements a singleton Tokio runtime + recurring health probe and sync is_available().
crates/cast_agent/src/lib.rs Exposes the new runtime module and re-exports runtime entry points.
crates/cast_agent/src/agent.rs Adds health_probe() and applies async_trait to the backend impl.
crates/cast_agent/Cargo.toml Adds async-trait dependency to support #[async_trait] usage.
crates/ai/src/lib.rs Adds ai::cast_agent facade gated by the cast-agent feature.
CAST-AGENT.md Updates documentation to reflect runtime boot + status pill wiring.
Cargo.lock Records the new async-trait dependency for cast_agent.
app/src/lib.rs Eagerly boots the Cast Agent runtime during application startup.
app/src/ai/coven_brand.rs Adds brand colors for success/warning used by the status pill.
app/src/ai_assistant/panel.rs Renders a gateway status pill that reads ai::cast_agent::is_available().
app/Cargo.toml Adds cast-agent feature wiring and bundles it into gui.
Comments suppressed due to low confidence (1)

crates/cast_agent/src/runtime.rs:39

  • CastAgentRuntime::boot()’s doc comment says it “spawns a background thread”, but this function currently just builds a multi-thread runtime and continues on the caller thread. If the intent is to offload initialization work from the UI thread, the implementation needs an actual OS thread handoff; otherwise, update the comment to avoid incorrect guarantees.
impl CastAgentRuntime {
    /// Build a runtime + agent. Spawns a background thread so the runtime
    /// is multi-threaded without taking over the UI thread.
    fn boot(config: Option<CastAgentConfig>) -> std::io::Result<Self> {

💡 Add Copilot custom instructions for smarter, more guided reviews. Learn how to get started.

Comment thread crates/cast_agent/src/runtime.rs
Comment thread crates/cast_agent/src/runtime.rs
Comment thread app/Cargo.toml
Comment thread specs/CASTCODES-BROWSER-PANEL/TECH.md
Comment thread specs/CASTCODES-BROWSER-PANEL/PLAN-01-ui-toggle-persistence.md
@BunsDev

BunsDev commented May 16, 2026

Copy link
Copy Markdown
Member Author

@copilot apply changes based on the comments in this thread

@BunsDev
BunsDev merged commit 5d5c54d into main May 16, 2026
16 of 17 checks passed
@BunsDev
BunsDev deleted the feat/cast-agent-integration branch May 16, 2026 10:11
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants