Add XAI Grok to the AI panel (#1558)
Grok Build is added as one more entry in the agent discovery list, over ACP, like the others. Thanks @cfaulkingham. Co-Authored-By: Claude Sonnet 5.5 <noreply@anthropic.com>
This commit is contained in:
1 parent
a6742180a9
commit
342305705d
4 files changed
+41
-6
No files matched your search
+3
-2
@@ -228,12 +228,13 @@ annotations and exact projected curves remain deferred. See [view DXF](docs/view
|
|||||||
`diagnostics.crash_reports`, the MCP `crash_reports` tool or the CLI. Nothing is sent
|
`diagnostics.crash_reports`, the MCP `crash_reports` tool or the CLI. Nothing is sent
|
||||||
anywhere. See [crash reports](docs/crash-reports.md).
|
anywhere. See [crash reports](docs/crash-reports.md).
|
||||||
- Agent chat (off by default, desktop): a side panel that drives a coding agent the user
|
- Agent chat (off by default, desktop): a side panel that drives a coding agent the user
|
||||||
already has (Claude Code through its ACP adapter, Codex, Gemini CLI, OpenCode, …) over the
|
already has (Claude Code through its ACP adapter, Codex, Gemini CLI, OpenCode, Grok Build, …) over the
|
||||||
Agent Client Protocol, under the user's own login; SolidCraft stores no keys. The agent works
|
Agent Client Protocol, under the user's own login; SolidCraft stores no keys. The agent works
|
||||||
through SolidCraft's MCP tools on a gated endpoint of its own: file actions wait for Allow or
|
through SolidCraft's MCP tools on a gated endpoint of its own: file actions wait for Allow or
|
||||||
Deny, crash reports are off limits, 24 changes per message, one undo step per message, and
|
Deny, crash reports are off limits, 24 changes per message, one undo step per message, and
|
||||||
the agent's whole process group ends with the panel or the app. Docks left or right,
|
the agent's whole process group ends with the panel or the app. Docks left or right,
|
||||||
minimises to a strip. See [agent chat](docs/agent-chat.md).
|
minimises to a strip. Grok Build discovery includes `~/.grok/bin` and reuses the user's
|
||||||
|
Grok login. See [agent chat](docs/agent-chat.md).
|
||||||
- Command scripts from designs (#886): `timeline.export_script` (CLI `solidcraft-cli script`)
|
- Command scripts from designs (#886): `timeline.export_script` (CLI `solidcraft-cli script`)
|
||||||
writes a design's history as a script that `eval` and `run` replay into the same design —
|
writes a design's history as a script that `eval` and `run` replay into the same design —
|
||||||
user parameters, units, sheet metal and plastic rules and materials as their own commands,
|
user parameters, units, sheet metal and plastic rules and materials as their own commands,
|
||||||
|
|||||||
@@ -68,6 +68,16 @@ pub const KNOWN: &[Known] = &[
|
|||||||
config_dir_var: None,
|
config_dir_var: None,
|
||||||
key_vars: &[],
|
key_vars: &[],
|
||||||
},
|
},
|
||||||
|
Known {
|
||||||
|
id: "grok",
|
||||||
|
name: "XAI Grok",
|
||||||
|
programs: &["grok"],
|
||||||
|
args: &["agent", "stdio"],
|
||||||
|
install: "see https://docs.x.ai/build/overview (Grok Build installer); then run grok login",
|
||||||
|
credentials: Some(".grok/auth.json"),
|
||||||
|
config_dir_var: None,
|
||||||
|
key_vars: &["XAI_API_KEY"],
|
||||||
|
},
|
||||||
Known {
|
Known {
|
||||||
id: "copilot",
|
id: "copilot",
|
||||||
name: "GitHub Copilot CLI",
|
name: "GitHub Copilot CLI",
|
||||||
@@ -153,14 +163,14 @@ fn home() -> Option<PathBuf> {
|
|||||||
std::env::var_os(if cfg!(windows) { "USERPROFILE" } else { "HOME" }).map(PathBuf::from).filter(|p| p.is_absolute())
|
std::env::var_os(if cfg!(windows) { "USERPROFILE" } else { "HOME" }).map(PathBuf::from).filter(|p| p.is_absolute())
|
||||||
}
|
}
|
||||||
|
|
||||||
/// PATH, then the usual places npm, Homebrew, nvm, Volta, bun and pipx put commands.
|
/// PATH, then the usual places npm, Homebrew, nvm, Volta, bun, pipx and Grok put commands.
|
||||||
pub fn search_dirs() -> Vec<PathBuf> {
|
pub fn search_dirs() -> Vec<PathBuf> {
|
||||||
let mut dirs: Vec<PathBuf> = std::env::var_os("PATH").map(|p| std::env::split_paths(&p).collect()).unwrap_or_default();
|
let mut dirs: Vec<PathBuf> = std::env::var_os("PATH").map(|p| std::env::split_paths(&p).collect()).unwrap_or_default();
|
||||||
if let Some(prefix) = std::env::var_os("NPM_CONFIG_PREFIX").map(PathBuf::from) {
|
if let Some(prefix) = std::env::var_os("NPM_CONFIG_PREFIX").map(PathBuf::from) {
|
||||||
dirs.push(if cfg!(windows) { prefix.clone() } else { prefix.join("bin") });
|
dirs.push(if cfg!(windows) { prefix.clone() } else { prefix.join("bin") });
|
||||||
}
|
}
|
||||||
if let Some(h) = home() {
|
if let Some(h) = home() {
|
||||||
for d in [".local/bin", ".npm-global/bin", ".npm-packages/bin", ".volta/bin", ".bun/bin", ".cargo/bin", "bin"] {
|
for d in [".local/bin", ".npm-global/bin", ".npm-packages/bin", ".volta/bin", ".bun/bin", ".cargo/bin", ".grok/bin", "bin"] {
|
||||||
dirs.push(h.join(d));
|
dirs.push(h.join(d));
|
||||||
}
|
}
|
||||||
// nvm: every installed Node version's bin.
|
// nvm: every installed Node version's bin.
|
||||||
@@ -326,6 +336,7 @@ mod tests {
|
|||||||
assert_eq!(version_of("@agentclientprotocol/codex-acp 2.2.2"), "2.2.2");
|
assert_eq!(version_of("@agentclientprotocol/codex-acp 2.2.2"), "2.2.2");
|
||||||
assert_eq!(version_of("2.1.295 (Claude Code)"), "2.1.295");
|
assert_eq!(version_of("2.1.295 (Claude Code)"), "2.1.295");
|
||||||
assert_eq!(version_of("goose v1.9.0"), "v1.9.0");
|
assert_eq!(version_of("goose v1.9.0"), "v1.9.0");
|
||||||
|
assert_eq!(version_of("grok 1.0.58 (26283d10dd58) [alpha]"), "1.0.58");
|
||||||
assert_eq!(version_of("dev build"), "dev build");
|
assert_eq!(version_of("dev build"), "dev build");
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -336,6 +347,7 @@ mod tests {
|
|||||||
let gemini = KNOWN.iter().find(|k| k.id == "gemini").unwrap();
|
let gemini = KNOWN.iter().find(|k| k.id == "gemini").unwrap();
|
||||||
let qwen = KNOWN.iter().find(|k| k.id == "qwen").unwrap();
|
let qwen = KNOWN.iter().find(|k| k.id == "qwen").unwrap();
|
||||||
let goose = KNOWN.iter().find(|k| k.id == "goose").unwrap();
|
let goose = KNOWN.iter().find(|k| k.id == "goose").unwrap();
|
||||||
|
let grok = KNOWN.iter().find(|k| k.id == "grok").unwrap();
|
||||||
if std::env::var_os("GEMINI_API_KEY").is_none() && std::env::var_os("GOOGLE_API_KEY").is_none() {
|
if std::env::var_os("GEMINI_API_KEY").is_none() && std::env::var_os("GOOGLE_API_KEY").is_none() {
|
||||||
assert_eq!(login_of(gemini, Some(&home)), Login::NotLoggedIn);
|
assert_eq!(login_of(gemini, Some(&home)), Login::NotLoggedIn);
|
||||||
}
|
}
|
||||||
@@ -345,6 +357,13 @@ mod tests {
|
|||||||
assert_eq!(login_of(qwen, Some(&home)), Login::NotLoggedIn);
|
assert_eq!(login_of(qwen, Some(&home)), Login::NotLoggedIn);
|
||||||
}
|
}
|
||||||
assert_eq!(login_of(goose, Some(&home)), Login::Unknown, "keeps no file we know");
|
assert_eq!(login_of(goose, Some(&home)), Login::Unknown, "keeps no file we know");
|
||||||
|
if std::env::var_os("XAI_API_KEY").is_none() {
|
||||||
|
assert_eq!(login_of(grok, Some(&home)), Login::NotLoggedIn);
|
||||||
|
}
|
||||||
|
std::fs::create_dir_all(home.join(".grok")).unwrap();
|
||||||
|
// Discovery checks only for the file; it never needs to parse the user's tokens.
|
||||||
|
std::fs::write(home.join(".grok/auth.json"), "not credential data").unwrap();
|
||||||
|
assert_eq!(login_of(grok, Some(&home)), Login::LooksLoggedIn);
|
||||||
let _ = std::fs::remove_dir_all(home);
|
let _ = std::fs::remove_dir_all(home);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
+16
-2
@@ -1,7 +1,7 @@
|
|||||||
# Agent chat
|
# Agent chat
|
||||||
|
|
||||||
Agent chat is a side panel where you talk to a coding agent you already use (Claude Code,
|
Agent chat is a side panel where you talk to a coding agent you already use (Claude Code,
|
||||||
Codex, Gemini CLI, OpenCode and others), or to a model behind an OpenAI-compatible endpoint you
|
Codex, Gemini CLI, OpenCode, Grok Build and others), or to a model behind an OpenAI-compatible endpoint you
|
||||||
choose (Ollama or LM Studio on your computer, OpenAI, any other URL), and have it work on the
|
choose (Ollama or LM Studio on your computer, OpenAI, any other URL), and have it work on the
|
||||||
design that's open. A coding agent runs on your computer under **your own account** with that
|
design that's open. A coding agent runs on your computer under **your own account** with that
|
||||||
agent: SolidCraft doesn't sell or proxy a model and needs no key for it. An endpoint's key, if
|
agent: SolidCraft doesn't sell or proxy a model and needs no key for it. An endpoint's key, if
|
||||||
@@ -53,7 +53,7 @@ conversation starts with), its own permission setting, and **Remove** for the on
|
|||||||
|
|
||||||
SolidCraft looks for agents that speak the [Agent Client Protocol](https://agentclientprotocol.com)
|
SolidCraft looks for agents that speak the [Agent Client Protocol](https://agentclientprotocol.com)
|
||||||
on your `PATH` and in the usual install folders a desktop app's `PATH` often misses (npm's
|
on your `PATH` and in the usual install folders a desktop app's `PATH` often misses (npm's
|
||||||
global folder, nvm, Volta, bun, `~/.local/bin`, Homebrew, `%APPDATA%\npm`). For each one it
|
global folder, nvm, Volta, bun, `~/.local/bin`, `~/.grok/bin`, Homebrew, `%APPDATA%\npm`). For each one it
|
||||||
shows its **version** (from `--version`, given three seconds) and whether it looks **signed in**.
|
shows its **version** (from `--version`, given three seconds) and whether it looks **signed in**.
|
||||||
SolidCraft only checks whether the agent's own login file (`~/.claude/.credentials.json`,
|
SolidCraft only checks whether the agent's own login file (`~/.claude/.credentials.json`,
|
||||||
`~/.codex/auth.json`, `~/.gemini/oauth_creds.json`, …) or one of its key variables exists. It never
|
`~/.codex/auth.json`, `~/.gemini/oauth_creds.json`, …) or one of its key variables exists. It never
|
||||||
@@ -66,12 +66,26 @@ the keychain, so SolidCraft doesn't guess there.
|
|||||||
| Codex | `npm install -g @agentclientprotocol/codex-acp` |
|
| Codex | `npm install -g @agentclientprotocol/codex-acp` |
|
||||||
| Gemini CLI | `npm install -g @google/gemini-cli` (it speaks ACP itself: `gemini --acp`) |
|
| Gemini CLI | `npm install -g @google/gemini-cli` (it speaks ACP itself: `gemini --acp`) |
|
||||||
| OpenCode | `npm install -g opencode-ai` (`opencode acp`) |
|
| OpenCode | `npm install -g opencode-ai` (`opencode acp`) |
|
||||||
|
| XAI Grok | [Grok Build installer](https://docs.x.ai/build/overview), then `grok login` (`grok agent stdio` speaks ACP) |
|
||||||
| GitHub Copilot CLI, Qwen Code, goose | listed with their install command when missing |
|
| GitHub Copilot CLI, Qwen Code, goose | listed with their install command when missing |
|
||||||
|
|
||||||
The panel lists agents that aren't installed with their install command and a **Copy** button.
|
The panel lists agents that aren't installed with their install command and a **Copy** button.
|
||||||
**Refresh** looks again after you install one. **Test** starts an agent briefly, asks it for a
|
**Refresh** looks again after you install one. **Test** starts an agent briefly, asks it for a
|
||||||
session and ends it again.
|
session and ends it again.
|
||||||
|
|
||||||
|
### XAI Grok
|
||||||
|
|
||||||
|
Install **Grok Build** and run `grok login` in a terminal to sign in with your Grok account.
|
||||||
|
In SolidCraft, open **AI → Refresh**, select
|
||||||
|
**XAI Grok**, then **Connect**. You can make it the default under
|
||||||
|
**Preferences → AI → Agents**.
|
||||||
|
|
||||||
|
SolidCraft reuses Grok Build's sign-in in `~/.grok/auth.json`; it checks only whether that file
|
||||||
|
exists and does not read or copy its tokens. If sign-in is needed, the panel offers Grok's own
|
||||||
|
sign-in methods. You can also run `grok login` again and reconnect. Grok controls model access
|
||||||
|
and usage limits for your account. This connection does not require an API key in SolidCraft.
|
||||||
|
Grok Build also supports `XAI_API_KEY` for users who choose API authentication.
|
||||||
|
|
||||||
### Add agent…
|
### Add agent…
|
||||||
|
|
||||||
- **Installed agent:** your own entry for an installed agent, for example with other arguments.
|
- **Installed agent:** your own entry for an installed agent, for example with other arguments.
|
||||||
|
|||||||
@@ -50,6 +50,7 @@ with SolidCraft, the user installs the agent.
|
|||||||
| Codex | `codex-acp` adapter (`@zed-industries/codex-acp` 0.16 moved to `@agentclientprotocol/codex-acp`) | `@agentclientprotocol/codex-acp` 2.2.2, Apache-2.0 | `--version` (0.16 rejected the flag; 2.x prints it) | Agent method `chat-gpt` (the adapter opens the browser for the ChatGPT login when the client calls `authenticate`), and `api-key` for a key the user configures in Codex. 0.16 also listed `env_var` methods for `CODEX_API_KEY` / `OPENAI_API_KEY`. The login is Codex's own: `~/.codex/auth.json`. |
|
| Codex | `codex-acp` adapter (`@zed-industries/codex-acp` 0.16 moved to `@agentclientprotocol/codex-acp`) | `@agentclientprotocol/codex-acp` 2.2.2, Apache-2.0 | `--version` (0.16 rejected the flag; 2.x prints it) | Agent method `chat-gpt` (the adapter opens the browser for the ChatGPT login when the client calls `authenticate`), and `api-key` for a key the user configures in Codex. 0.16 also listed `env_var` methods for `CODEX_API_KEY` / `OPENAI_API_KEY`. The login is Codex's own: `~/.codex/auth.json`. |
|
||||||
| Gemini CLI | built in: `gemini --acp` (the ACP registry's current flag; older releases used `--experimental-acp`) | `@google/gemini-cli` 0.64, Apache-2.0 | `--version` | Its own Google login (`~/.gemini/oauth_creds.json`) or a key in the environment. |
|
| Gemini CLI | built in: `gemini --acp` (the ACP registry's current flag; older releases used `--experimental-acp`) | `@google/gemini-cli` 0.64, Apache-2.0 | `--version` | Its own Google login (`~/.gemini/oauth_creds.json`) or a key in the environment. |
|
||||||
| OpenCode | built in: `opencode acp` | `opencode-ai` 1.19, MIT | `--version` | Its own providers' logins (`~/.local/share/opencode/auth.json`) or keys in the environment. |
|
| OpenCode | built in: `opencode acp` | `opencode-ai` 1.19, MIT | `--version` | Its own providers' logins (`~/.local/share/opencode/auth.json`) or keys in the environment. |
|
||||||
|
| XAI Grok | built in: `grok agent stdio` | [Grok Build](https://github.com/xai-org/grok-build), Apache-2.0; installed separately | `grok --version` prints `grok 1.0.58 (…) [alpha]` (checked 2026-10-15; in-app connection also checked with 1.0.60) | Its own `~/.grok/auth.json` or `XAI_API_KEY`. `grok login` signs in in the browser; ACP advertises `cached_token` and `grok.com` authentication methods. |
|
||||||
| Others in the ACP registry | `copilot --acp`, `qwen --acp`, `opencode acp`, `goose acp`, `cline --acp`, `kimi acp`, … | mixed; several are proprietary, one is GPL and one AGPL (we only start them as programs, never link them) | `--version` | each its own |
|
| Others in the ACP registry | `copilot --acp`, `qwen --acp`, `opencode acp`, `goose acp`, `cline --acp`, `kimi acp`, … | mixed; several are proprietary, one is GPL and one AGPL (we only start them as programs, never link them) | `--version` | each its own |
|
||||||
|
|
||||||
The registry (`https://cdn.agentclientprotocol.com/registry/v1/latest/registry.json`) lists
|
The registry (`https://cdn.agentclientprotocol.com/registry/v1/latest/registry.json`) lists
|
||||||
|
|||||||
Reference in new issue
Block a user