diff --git a/aibridge/client.go b/aibridge/client.go index 836c09c4b0b..a88d03ac3be 100644 --- a/aibridge/client.go +++ b/aibridge/client.go @@ -18,7 +18,7 @@ const ( ClientKilo Client = "Kilo Code" ClientCoderAgents Client = "Coder Agents" ClientCrush Client = "Charm Crush" - ClientMux Client = "Mux" + ClientXum Client = "Xum" ClientRoo Client = "Roo Code" ClientCursor Client = "Cursor" ClientOpenCode Client = "OpenCode" @@ -35,8 +35,9 @@ func GuessClient(r *http.Request) Client { // Must be kept in sync with documentation: https://github.com/coder/coder/blob/3cf867f84aa32d2febf7a26dc7e52be6beb8a2ac/docs/ai-coder/ai-gateway/monitoring.md?plain=1#L47-L57 switch { - case strings.HasPrefix(userAgent, "mux/"): - return ClientMux + case strings.HasPrefix(userAgent, "xum/") || strings.HasPrefix(userAgent, "mux/"): + // Mux was renamed to Xum; "mux/" is kept for older, unupgraded clients. + return ClientXum case strings.HasPrefix(userAgent, "claude"): return ClientClaudeCode case strings.HasPrefix(userAgent, "codex"): diff --git a/aibridge/client_test.go b/aibridge/client_test.go index cde72029a16..edf64028b50 100644 --- a/aibridge/client_test.go +++ b/aibridge/client_test.go @@ -19,9 +19,14 @@ func TestGuessClient(t *testing.T) { wantClient aibridge.Client }{ { - name: "mux", + name: "xum", + userAgent: "xum/0.20.0 ai-sdk/openai/3.0.36 ai-sdk/provider-utils/4.0.15 runtime/node.js/22", + wantClient: aibridge.ClientXum, + }, + { + name: "xum_legacy_mux_user_agent", userAgent: "mux/0.19.0-next.2.gcceff159 ai-sdk/openai/3.0.36 ai-sdk/provider-utils/4.0.15 runtime/node.js/22", - wantClient: aibridge.ClientMux, + wantClient: aibridge.ClientXum, }, { name: "claude_code", diff --git a/aibridge/internal/integrationtest/bridge_internal_test.go b/aibridge/internal/integrationtest/bridge_internal_test.go index 877d68ac4ba..95f01f5c2c3 100644 --- a/aibridge/internal/integrationtest/bridge_internal_test.go +++ b/aibridge/internal/integrationtest/bridge_internal_test.go @@ -1172,13 +1172,13 @@ func TestSessionIDTracking(t *testing.T) { }{ // Session in header. { - name: "mux", + name: "xum", fixture: fixtures.AntSimple, - expectedClient: aibridge.ClientMux, - expectSessionID: "mux-workspace-321", + expectedClient: aibridge.ClientXum, + expectSessionID: "xum-workspace-321", header: http.Header{ - "User-Agent": []string{"mux/1.0.0"}, - "X-Mux-Workspace-Id": []string{"mux-workspace-321"}, + "User-Agent": []string{"xum/1.0.0"}, + "X-Mux-Workspace-Id": []string{"xum-workspace-321"}, }, }, // Session in body. diff --git a/aibridge/session.go b/aibridge/session.go index dcd60ed85af..5236821a885 100644 --- a/aibridge/session.go +++ b/aibridge/session.go @@ -62,7 +62,9 @@ func GuessSessionID(client Client, r *http.Request) *string { return sid } return cleanRef(r.Header.Get("session_id")) - case ClientMux: + case ClientXum: + // Header name is intentionally still "X-Mux-Workspace-Id"; Xum keeps the + // wire value from before the Mux rename. return cleanRef(r.Header.Get("X-Mux-Workspace-Id")) case ClientZed: return nil // Zed does not send a session ID from Zed Agent or Text Thread. diff --git a/aibridge/session_test.go b/aibridge/session_test.go index 222f00a0686..aaa5d618964 100644 --- a/aibridge/session_test.go +++ b/aibridge/session_test.go @@ -139,16 +139,16 @@ func TestGuessSessionID(t *testing.T) { headers: map[string]string{"session_id": "zed-session"}, body: `{"metadata":{"user_id":"user_abc_account_456_session_some-id"}}`, }, - // Mux. + // Xum. { - name: "mux_with_workspace_header", - client: aibridge.ClientMux, + name: "xum_with_workspace_header", + client: aibridge.ClientXum, headers: map[string]string{"X-Mux-Workspace-Id": "ws-abc-123"}, sessionID: utils.PtrTo("ws-abc-123"), }, { - name: "mux_without_workspace_header", - client: aibridge.ClientMux, + name: "xum_without_workspace_header", + client: aibridge.ClientXum, }, // Copilot VS Code. { diff --git a/docs/ai-coder/ai-gateway/clients/index.md b/docs/ai-coder/ai-gateway/clients/index.md index 769ad9d91f9..c596c585b34 100644 --- a/docs/ai-coder/ai-gateway/clients/index.md +++ b/docs/ai-coder/ai-gateway/clients/index.md @@ -38,7 +38,7 @@ The table below shows tested AI clients and their compatibility with AI Gateway. | Client | OpenAI | Anthropic | BYOK | Notes | |-----------------------------------|--------|-----------|------|--------------------------------------------------------------------------------------------------------------------------------------------------------| -| [Mux](./mux.md) | ✅ | ✅ | - | | +| [Xum](./xum.md) | ✅ | ✅ | - | | | [Claude Code](./claude-code.md) | - | ✅ | ✅ | | | [Codex CLI](./codex.md) | ✅ | - | ✅ | | | [OpenCode](./opencode.md) | ✅ | ✅ | ✅ | | diff --git a/docs/ai-coder/ai-gateway/clients/mux.md b/docs/ai-coder/ai-gateway/clients/xum.md similarity index 72% rename from docs/ai-coder/ai-gateway/clients/mux.md rename to docs/ai-coder/ai-gateway/clients/xum.md index 4756e4b5c4f..b7f6467f354 100644 --- a/docs/ai-coder/ai-gateway/clients/mux.md +++ b/docs/ai-coder/ai-gateway/clients/xum.md @@ -1,12 +1,12 @@ -# Mux +# Xum > [!NOTE] > AI Gateway is part of [AI Governance](../../ai-governance.md), which is > included with a Premium license. -Mux makes it easy to run parallel coding agents, each with its own isolated workspace, from your browser or desktop; it is open source and provider-agnostic. +Xum (formerly Mux) makes it easy to run parallel coding agents, each with its own isolated workspace, from your browser or desktop; it is open source and provider-agnostic. -Mux can be configured to route OpenAI- and Anthropic-compatible traffic through AI Gateway by setting a custom provider base URL and using a Coder-issued token for authentication. +Xum can be configured to route OpenAI- and Anthropic-compatible traffic through AI Gateway by setting a custom provider base URL and using a Coder-issued token for authentication. ## Prerequisites @@ -19,14 +19,14 @@ Mux can be configured to route OpenAI- and Anthropic-compatible traffic through ### OpenAI -1. Open Mux settings (`Cmd+,` / `Ctrl+,`). +1. Open Xum settings (`Cmd+,` / `Ctrl+,`). 2. Go to **Providers** → **OpenAI**. 3. Set **API Key** to your Coder API token. 4. Set **Base URL** to `https://coder.example.com/api/v2/ai-gateway/openai/v1`. ### Anthropic -1. Open Mux settings (`Cmd+,` / `Ctrl+,`). +1. Open Xum settings (`Cmd+,` / `Ctrl+,`). 2. Go to **Providers** → **Anthropic**. 3. Set **API Key** to your Coder API token. 4. Set **Base URL** to `https://coder.example.com/api/v2/ai-gateway/anthropic`. @@ -37,11 +37,11 @@ _Replace `coder.example.com` with your Coder deployment URL._ ## Environment variables -Mux reads provider configuration from its settings UI and also from environment variables. -Environment variables are useful in CI or when running Mux inside a Coder workspace. +Xum reads provider configuration from its settings UI and also from environment variables. +Environment variables are useful in CI or when running Xum inside a Coder workspace. > [!NOTE] -> Mux treats environment variables as a fallback when a provider is not configured in settings. +> Xum treats environment variables as a fallback when a provider is not configured in settings. > If you have already configured a provider in the UI, clear it (or update it) for env vars to take effect. ```sh @@ -54,9 +54,9 @@ export ANTHROPIC_API_KEY="" export ANTHROPIC_BASE_URL="https://coder.example.com/api/v2/ai-gateway/anthropic" ``` -## Run Mux in a Coder workspace +## Run Xum in a Coder workspace -To run Mux inside a Coder workspace (for example, as a Coder app), you can install it with the [Mux module](https://registry.coder.com/modules/coder/mux) and pre-configure AI Gateway via environment variables on the agent: +To run Xum inside a Coder workspace (for example, as a Coder app), you can install it with the [`mux` module](https://registry.coder.com/modules/coder/mux) (still published under its pre-rename name) and pre-configure AI Gateway via environment variables on the agent: ```tf data "coder_workspace" "me" {} @@ -82,7 +82,7 @@ module "mux" { ## Advanced: providers.jsonc -If you prefer a file-based config, edit `~/.mux/providers.jsonc`: +If you prefer a file-based config, edit `~/.xum/providers.jsonc`: ```json { @@ -97,4 +97,4 @@ If you prefer a file-based config, edit `~/.mux/providers.jsonc`: } ``` -**References:** [Mux provider environment variables](https://mux.coder.com/config/providers#environment-variables) +**References:** [Xum provider environment variables](https://xum.coder.com/config/providers#environment-variables) diff --git a/docs/ai-coder/ai-gateway/monitoring.md b/docs/ai-coder/ai-gateway/monitoring.md index 88ec03bc4e0..76998730deb 100644 --- a/docs/ai-coder/ai-gateway/monitoring.md +++ b/docs/ai-coder/ai-gateway/monitoring.md @@ -220,7 +220,7 @@ Available query filters: - `Kilo Code` - `Roo Code` - `Coder Agents` -- `Mux` +- `Xum` - `Cursor` - `OpenCode` - `Charm Crush` diff --git a/docs/manifest.json b/docs/manifest.json index 2330ab40aae..8f206c65dc9 100644 --- a/docs/manifest.json +++ b/docs/manifest.json @@ -1226,9 +1226,9 @@ "state": ["premium"] }, { - "title": "Mux", - "description": "Configure Mux, the parallel coding agent tool, to route requests through AI Gateway.", - "path": "./ai-coder/ai-gateway/clients/mux.md", + "title": "Xum", + "description": "Configure Xum, the parallel coding agent tool, to route requests through AI Gateway.", + "path": "./ai-coder/ai-gateway/clients/xum.md", "state": ["premium"] }, { diff --git a/site/src/pages/AIBridgePage/icons/AIBridgeClientIcon.tsx b/site/src/pages/AIBridgePage/icons/AIBridgeClientIcon.tsx index 575e586b812..092f90a1773 100644 --- a/site/src/pages/AIBridgePage/icons/AIBridgeClientIcon.tsx +++ b/site/src/pages/AIBridgePage/icons/AIBridgeClientIcon.tsx @@ -49,6 +49,14 @@ export const AIBridgeClientIcon = ({ className={cn(iconClassName, className)} /> ); + case "Xum": + return ( + + ); + // Legacy label for interceptions recorded before the Mux -> Xum rename. case "Mux": return ( ([ ["/icon/terminal.svg", "monochrome"], ["/icon/vercel.svg", "whiteWithColor"], ["/icon/widgets.svg", "monochrome"], + ["/icon/xum.svg", "monochrome"], ["/icon/windsurf.svg", "monochrome"], ["/icon/zed.svg", "monochrome"], ]); diff --git a/site/src/theme/icons.json b/site/src/theme/icons.json index 0bd3570d2ee..72152fc5055 100644 --- a/site/src/theme/icons.json +++ b/site/src/theme/icons.json @@ -151,5 +151,6 @@ "widgets.svg", "windows.svg", "windsurf.svg", + "xum.svg", "zed.svg" ] diff --git a/site/static/icon/xum.svg b/site/static/icon/xum.svg new file mode 100644 index 00000000000..9057e864425 --- /dev/null +++ b/site/static/icon/xum.svg @@ -0,0 +1,6 @@ + + + + + +