From 6078b54b0a3aab716002246d862dc82a3885ab5b Mon Sep 17 00:00:00 2001 From: Daniel Farina Date: Wed, 22 Jul 2026 03:28:45 -0400 Subject: [PATCH] feat(agents): add Grok Build as a native ACP runtime Register Grok Build in the managed ACP catalog so Buzz can discover and spawn `grok agent --always-approve stdio` without a separate adapter package. Wire default args, ~/.grok/bin discovery, onboarding visibility, process sweep, docs, and unit coverage. Verified live with `buzz-acp models` against the installed Grok CLI. --- README.md | 6 +-- TESTING.md | 4 +- crates/buzz-acp/README.md | 19 ++++++- crates/buzz-acp/src/config.rs | 31 +++++++++-- .../src-tauri/src/managed_agents/discovery.rs | 53 ++++++++++++++++++- .../src/managed_agents/discovery/tests.rs | 26 +++++++++ .../src-tauri/src/managed_agents/runtime.rs | 1 + .../features/onboarding/ui/agentReadiness.ts | 4 +- .../ui/onboardingRuntimeSelection.ts | 2 +- 9 files changed, 132 insertions(+), 14 deletions(-) diff --git a/README.md b/README.md index 6aa3eeff0b..814015e03d 100644 --- a/README.md +++ b/README.md @@ -100,7 +100,7 @@ Agents are part of the room, not haunted cron jobs. |---|---|---| | Relay, channels, threads, DMs, canvases, media, search, audit log | Mobile clients (iOS + Android, Flutter) | Web-of-trust reputation across relays | | Desktop app (Tauri + React) | Workflow approval gates (infra exists, glue still drying) | Push notifications | -| `buzz-cli` (agent-first, JSON in / JSON out) + ACP harness (Goose, Codex, Claude Code) | Huddle lifecycle events | Culture features | +| `buzz-cli` (agent-first, JSON in / JSON out) + ACP harness (Goose, Codex, Claude Code, Grok Build) | Huddle lifecycle events | Culture features | | YAML workflows: message / reaction / schedule / webhook triggers | | | | Git events (NIP-34: patches, repo announcements, status) | | | | Git hosting backend | | | @@ -174,7 +174,7 @@ If you'd rather point buzz at a different bash-compatible shell, set `BUZZ_SHELL ┌─────────────────────────────────────────────────────────────────────────┐ │ Clients │ │ Human client AI agent CLI / scripts │ -│ (Buzz desktop) (Goose, Codex, ...) (buzz-cli, agents) │ +│ (Buzz desktop) (Goose, Codex, Grok, ...) (buzz-cli, agents) │ │ │ ┌──────────────┐ │ │ │ │ │ buzz-acp │ │ │ │ │ │ (ACP ↔ MCP) │ │ │ @@ -204,7 +204,7 @@ A Rust workspace of focused crates. Single source of truth: the relay. See [ARCH **Services** — `buzz-db` (Postgres) · `buzz-auth` (NIP-42/98 Schnorr auth, rate limiting) · `buzz-pubsub` (Redis, presence, typing) · `buzz-search` (Postgres FTS) · `buzz-audit` (hash-chain log). Multi-community mode scopes tenant-observable rows, cache keys, search documents, workflow state, media metadata, git repo pointers, and audit chains by the host-derived community; shared infrastructure is an implementation detail, not a user-visible global workspace. -**Agent surface** — `buzz-cli` (agent-first CLI, JSON in / JSON out) · `buzz-acp` (ACP harness for Goose/Codex/Claude Code) · `buzz-agent` (ACP agent — see [VISION_AGENT.md](VISION_AGENT.md)) · `buzz-dev-mcp` (shell + file-edit tools) · `buzz-workflow` (YAML automation) · `buzz-persona` (agent persona packs) +**Agent surface** — `buzz-cli` (agent-first CLI, JSON in / JSON out) · `buzz-acp` (ACP harness for Goose/Codex/Claude Code/Grok Build) · `buzz-agent` (ACP agent — see [VISION_AGENT.md](VISION_AGENT.md)) · `buzz-dev-mcp` (shell + file-edit tools) · `buzz-workflow` (YAML automation) · `buzz-persona` (agent persona packs) **Git & pairing** — `git-sign-nostr` / `git-credential-nostr` (nostr-signed git) · `buzz-pair-relay` / `buzz-pairing-cli` (relay pairing) diff --git a/TESTING.md b/TESTING.md index 242dd44f25..93e8c1c7f2 100644 --- a/TESTING.md +++ b/TESTING.md @@ -179,7 +179,7 @@ header fallback. There is no REST API for fetching message threads — use ## ACP Harness (optional, end-to-end with a real agent) -`buzz-acp` connects an ACP-speaking agent (goose, codex, claude code, +`buzz-acp` connects an ACP-speaking agent (goose, codex, claude code, Grok Build, Grok Build, buzz-agent) to the relay. The harness listens for events, drives the agent over stdio, and the agent replies through MCP tools. @@ -222,7 +222,7 @@ buzz-acp # foreground; logs to stdout (run in > **Using a different ACP agent?** The default recipe assumes `goose` is on > `$PATH` and configured (`goose --version` should print). For codex / claude -> code / buzz-agent, set `BUZZ_ACP_AGENT_COMMAND` and `BUZZ_ACP_AGENT_ARGS` +> code / Grok Build / buzz-agent, set `BUZZ_ACP_AGENT_COMMAND` and `BUZZ_ACP_AGENT_ARGS` > accordingly — see `crates/buzz-acp/README.md`. Without these, buzz-acp > will fail to spawn the agent subprocess on startup. diff --git a/crates/buzz-acp/README.md b/crates/buzz-acp/README.md index b9c8406242..01bed7385f 100644 --- a/crates/buzz-acp/README.md +++ b/crates/buzz-acp/README.md @@ -9,7 +9,7 @@ Buzz Relay ──WS──→ buzz-acp ──stdio──→ Your Agent (send_message, etc.) ``` -Supports any agent that speaks [ACP](https://agentclientprotocol.com/) over stdio: **goose**, **codex** (via [codex-acp](https://github.com/agentclientprotocol/codex-acp)), and **claude code** (via [claude-agent-acp](https://github.com/agentclientprotocol/claude-agent-acp)). +Supports any agent that speaks [ACP](https://agentclientprotocol.com/) over stdio: **goose**, **codex** (via [codex-acp](https://github.com/agentclientprotocol/codex-acp)), **claude code** (via [claude-agent-acp](https://github.com/agentclientprotocol/claude-agent-acp)), and **Grok Build** (native `grok agent stdio`). ## Prerequisites @@ -71,6 +71,23 @@ buzz-acp > **API key note:** `codex-acp` always attempts a ChatGPT WebSocket login first, which logs a `426 Upgrade Required` error. This is expected and non-fatal — it falls back to `OPENAI_API_KEY` automatically. Set `OPENAI_API_KEY` to ensure it has a working fallback. +## Running with Grok Build + +[Grok Build](https://x.ai/) speaks ACP natively — no separate adapter package. + +```bash +# Install: curl -fsSL https://x.ai/cli/install.sh | bash +# Auth: grok login OR export XAI_API_KEY=... + +export BUZZ_ACP_AGENT_COMMAND="grok" +# Default args are: agent,--always-approve,stdio +export BUZZ_ACP_AGENT_ARGS="agent,--always-approve,stdio" + +buzz-acp +``` + +Grok discovers skills under `~/.grok/skills` and project `.agents/skills` (including Buzz's generated `buzz-cli` skill). + ## Running with Claude Code [claude-agent-acp](https://github.com/agentclientprotocol/claude-agent-acp) wraps the Claude Agent SDK in an ACP interface. diff --git a/crates/buzz-acp/src/config.rs b/crates/buzz-acp/src/config.rs index d78c4fa319..052a891a41 100644 --- a/crates/buzz-acp/src/config.rs +++ b/crates/buzz-acp/src/config.rs @@ -611,6 +611,14 @@ pub(crate) fn normalize_agent_command_identity(command: &str) -> String { fn default_agent_args(command: &str) -> Option> { match normalize_agent_command_identity(command).as_str() { "goose" => Some(vec!["acp".to_string()]), + // Grok Build speaks ACP natively over stdio. + // `grok agent --always-approve stdio` keeps managed turns unattended. + "grok" | "grok-build" | "grok-acp" => Some(vec![ + "agent".to_string(), + "--always-approve".to_string(), + "stdio".to_string(), + ]), + "codex" | "codex-acp" | "claude-agent-acp" | "claude-code-acp" | "claude-code" | "claudecode" | "buzz-agent" => Some(Vec::new()), _ => None, @@ -686,10 +694,10 @@ pub fn normalize_agent_args(command: &str, agent_args: Vec) -> Vec &'static [PathBuf] { paths.extend([ home.join(".local/share/mise/shims"), home.join(".local/bin"), + // Grok Build installer places the CLI at ~/.grok/bin/grok. + home.join(".grok/bin"), home.join(".volta/bin"), home.join(".asdf/shims"), ]); @@ -157,6 +160,42 @@ const KNOWN_ACP_RUNTIMES: &[KnownAcpRuntime] = &[ // Verified: `codex login status` exits 0 when logged in, non-zero otherwise. auth_probe_args: Some(&["codex", "login", "status"]), }, + KnownAcpRuntime { + id: "grok", + label: "Grok Build", + // Native ACP via `grok agent stdio` (no separate *-acp adapter package). + commands: &["grok"], + aliases: &["grok-build", "grok-acp"], + avatar_url: GROK_AVATAR_URL, + mcp_command: Some("buzz-dev-mcp"), + mcp_hooks: false, + underlying_cli: Some("grok"), + cli_install_commands: &["curl -fsSL https://x.ai/cli/install.sh | bash"], + cli_install_commands_windows: &[ + "powershell.exe -NoProfile -ExecutionPolicy Bypass -Command \"irm https://x.ai/cli/install.ps1 | iex\"", + ], + adapter_install_commands: &[], + install_instructions_url: "https://docs.x.ai/", + cli_install_hint: "Install Grok Build via the official xAI install script.", + adapter_install_hint: "", + skill_dir: Some(".grok/skills"), + supports_acp_model_switching: true, + model_env_var: None, + provider_env_var: None, + provider_locked: true, + default_env: &[], + config_file_path: Some("~/.grok/config.toml"), + config_file_format: Some("toml"), + supports_acp_native_config: false, + thinking_env_var: None, + max_tokens_env_var: None, + context_limit_env_var: None, + required_normalized_fields: &[], + login_hint: Some("Run `grok login` or set XAI_API_KEY."), + // No stable non-interactive auth-status subcommand yet; availability is + // based on finding the binary. Auth failures surface when a turn starts. + auth_probe_args: None, + }, KnownAcpRuntime { id: "buzz-agent", label: "Buzz Agent", @@ -343,6 +382,14 @@ pub use overrides::{apply_agent_command_update, create_time_agent_command_overri fn default_agent_args(command: &str) -> Option> { match normalize_command_identity(command).as_str() { "goose" => Some(vec!["acp".to_string()]), + // Grok Build speaks ACP natively over stdio. + // `grok agent --always-approve stdio` keeps managed turns unattended. + "grok" | "grok-build" | "grok-acp" => Some(vec![ + "agent".to_string(), + "--always-approve".to_string(), + "stdio".to_string(), + ]), + "codex" | "codex-acp" | "claude-agent-acp" | "claude-code-acp" | "claude-code" | "claudecode" | "buzz-agent" => Some(Vec::new()), _ => None, @@ -364,8 +411,10 @@ pub fn normalize_agent_args(command: &str, agent_args: Vec) -> Vec( ONBOARDING_RUNTIME_ORDER,