-
Notifications
You must be signed in to change notification settings - Fork 42
🤖 feat: Coder workspace integration for SSH runtime #1617
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
base: main
Are you sure you want to change the base?
Conversation
Add support for Coder workspaces as a sub-option of SSH runtime: Backend: - Add CoderService for CLI interactions (version check, templates, presets, workspaces) - Add CoderSSHRuntime extending SSHRuntime with Coder-specific provisioning - Workspace creation derives Coder name from mux branch, transforms to valid format - Handle collision detection, parent dir creation, abort with SIGKILL escalation Frontend: - Add CoderControls component with New/Existing mode toggle - Template and preset dropdowns (presets shown only when 2+) - useCoderWorkspace hook manages async data fetching - Allow disabling Coder when CLI becomes unavailable Schema: - CoderWorkspaceConfigSchema with optional workspaceName (backend derives for new) - ORPC endpoints: coder.getInfo, listTemplates, listPresets, listWorkspaces - Filter unknown statuses to prevent validation errors Fixes applied: - Bounded collision retry loop - Derive KNOWN_STATUSES from schema - Clear SIGKILL timeout on normal exit - Pass coderProps when enabled OR available
Introduce runtime hooks to customize workspace creation flow: - createFlags.deferredHost: skip srcBaseDir resolution for runtimes where the host does not exist yet (e.g., Coder) - createFlags.configLevelCollisionDetection: use config-based collision check when runtime cannot reach host - finalizeConfig(): derive names and compute host after collision handling - validateBeforePersist(): external validation before persisting metadata CoderSSHRuntime now owns the full name derivation and collision preflight logic, keeping policy local to the runtime. UI improvements: - Tri-state Coder CLI detection: loading (spinner), unavailable, available - Extract CoderCheckbox helper to reduce duplication Add unit tests for CoderSSHRuntime: - finalizeConfig: name derivation, normalization, validation, pass-through - deleteWorkspace: existingWorkspace handling, force flag, error combining --- _Generated with `mux` • Model: `anthropic:claude-opus-4-5` • Thinking: `high` • Cost: `$92.78`_
- Add fixed h-7 height to template/preset rows so spinner does not cause vertical shift when dropdown appears - Always show preset dropdown (disabled with "No presets" when empty) instead of hiding it, preventing layout jump
CLI returns [{Template: {...}}, ...] but we were expecting flat [{...}, ...].
Unwrap the Template field when parsing.
CLI returns [{TemplatePreset: {ID, Name, ...}}, ...] with PascalCase fields.
Unwrap and map to expected schema.
Add runtime-status events for ensureReady() progress:
- New stream event type for runtime startup progress (checking/starting/waiting/ready/error)
- CoderSSHRuntime emits status events during workspace start/wait
- DockerRuntime returns typed error results (runtime_not_ready vs runtime_start_failed)
- Frontend StreamingBarrier shows runtime-specific status text
- New runtime_start_failed error type for transient failures (retryable)
Add Coder sidebar icon:
- CoderIcon placeholder SVG in RuntimeIcons.tsx
- RuntimeBadge detects Coder workspaces (SSH + coder config) and shows CoderIcon
- Uses existing SSH blue styling, tooltip shows "Coder: {workspaceName}"
Other improvements:
- workspaceExists() search-based collision check (avoids listing all workspaces)
- Refactored coderService process management (graceful termination, runCoderCommand helper)
- Updated test fixtures for Coder CLI JSON wrapper structures
---
_Generated with `mux` • Model: `anthropic:claude-opus-4-5` • Thinking: `high` • Cost: `$152.30`_
Add coverage for Coder-backed SSH runtime readiness and runtime-status event plumbing. - CoderSSHRuntime: validateBeforePersist / postCreateSetup / ensureReady - CoderService: getWorkspaceStatus / startWorkspaceAndWait - Frontend: runtime-status routing + StreamingMessageAggregator lifecycle - Retry policy: runtime_not_ready (non-retryable) vs runtime_start_failed (retryable) Also drops brittle execAsync string snapshot tests for deleteWorkspace/ensureSSHConfig. --- _Generated with • Model: openai:gpt-5.2 • Thinking: high • Cost: 65.97_
…start The in-memory flag was set during postCreateSetup() but never persisted. After app restart, workspaces created in 'New' mode would fail ensureReady() without ever checking the Coder server. The flag was redundant - getWorkspaceStatus() already returns 'workspace not found' for missing workspaces, which triggers the same runtime_not_ready error. Existing throttling (lastActivityAtMs with 5-minute threshold) prevents constant network calls - only one status check per session or after inactivity.
mock.module affects all tests globally in Bun's test runner, causing failures in BackgroundProcessManager, hooks, and other tests that depend on the real execBuffered function. Using spyOn with mock.restore() in afterEach provides proper per-test isolation without affecting other test files.
Prevents race condition where changing templates quickly could apply presets from the previous template to the newly selected one.
Backend CoderService.listWorkspaces() already defaults to filterRunning=true.
Workspace creation: - Pre-fetch template rich parameters via API before spawning coder create - Pass defaults via --parameter flags to avoid interactive prompts - CSV-encode parameter values containing quotes/commas for CLI parsing - Validate required params have values (from preset or defaults) - Stream build logs in real-time via async queue Workspace status: - Change getWorkspaceStatus() return to discriminated union (ok/not_found/error) - Prevents treating transient errors as "workspace gone" Workspace deletion: - Check Coder workspace status before SSH cleanup - Skip SSH when workspace is not_found/deleted/deleting (avoids hang) - Proceed with SSH on API errors (let it fail naturally) Other: - Prefix new Coder workspace names with mux- - Replace placeholder Coder icon with official shorthand logo --- _Generated with `mux` • Model: `anthropic:claude-opus-4-5` • Thinking: `high` • Cost: `$205.71`_
ecc7975 to
0370ec2
Compare
When getWorkspaceStatus returns an error due to abort, properly return a failed EnsureReadyResult instead of optimistically proceeding.
0370ec2 to
40b0be4
Compare
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
💡 Codex Review
Here are some automated review suggestions for this pull request.
Reviewed commit: ecc7975e30
ℹ️ About Codex in GitHub
Your team has set up Codex to review pull requests in this repo. Reviews are triggered when you
- Open a pull request for review
- Mark a draft as ready
- Comment "@codex review".
If Codex has suggestions, it will comment; otherwise it will react with 👍.
Codex can also answer questions or update the PR. Try commenting "@codex address that feedback".
- Remove filterRunning parameter from listWorkspaces() - return all statuses - Show status in dropdown options (e.g., 'my-workspace (template) • stopped') - Change empty state text from 'No running workspaces' to 'No workspaces found' - Make coder controls container w-fit instead of full width ensureReady() already handles starting stopped workspaces, so users should be able to see and select them in the existing workspace picker. Addresses Codex review comment on PR #1617.
|
@codex review |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
💡 Codex Review
Here are some automated review suggestions for this pull request.
Reviewed commit: 06a3653ba6
ℹ️ About Codex in GitHub
Your team has set up Codex to review pull requests in this repo. Reviews are triggered when you
- Open a pull request for review
- Mark a draft as ready
- Comment "@codex review".
If Codex has suggestions, it will comment; otherwise it will react with 👍.
Codex can also answer questions or update the PR. Try commenting "@codex address that feedback".
- Add runtime-status handler to bufferedEventHandlers in WorkspaceStore so Coder startup progress is displayed in StreamingBarrier - Add safety check in coderService.deleteWorkspace() to refuse deleting workspaces without 'mux-' prefix (defense in depth) - Add tests for delete safeguard Addresses Codex review comment on PR #1617.
Summary
Adds support for Coder workspaces as a first-class runtime option within mux. Users can create new Coder workspaces or connect to existing ones directly from the workspace creation UI.
Features
Backend: CoderService + CoderSSHRuntime
CoderService (
src/node/services/coderService.ts)codercommands (version check, templates, presets, workspaces)getWorkspaceStatus()(ok/not_found/error)CoderSSHRuntime (
src/node/runtime/CoderSSHRuntime.ts)ensureReady()handles workspace startup with status polling and retry logicruntime-statusevents for UI progress feedback (checking → starting → ready)mux-{branch-name}with Coder-compatible normalizationFrontend: Coder Controls UI
CoderControls (
src/browser/components/ChatInput/CoderControls.tsx)useCoderWorkspace (
src/browser/hooks/useCoderWorkspace.ts)RuntimeBadge - Shows Coder icon for Coder-backed workspaces with tooltip
Schemas & API
CoderWorkspaceConfigSchemawith optional workspaceName (backend derives for new)coder.getInfo,listTemplates,listPresets,listWorkspacesRuntimeStatusEventSchemafor streaming runtime startup progressRuntime Readiness Events
New
runtime-statusstream event type shows progress during workspace startup:checking- Querying Coder workspace statusstarting- Starting stopped workspacewaiting- Waiting for workspace to be readyready- Workspace is runningerror- Startup failedStreamingBarrier displays status text to users during startup.
Key Implementation Details
Non-interactive
coder createThe original approach tried to detect interactive prompts and retry with defaults, but this failed because prompt display names don't match CLI parameter keys. The solution:
coder whoami --output jsoncoder templates list/api/v2/templateversions/{id}/rich-parameters)--parameter name=valueflagsDeletion Robustness
Deleting a mux workspace could hang if the Coder workspace was already deleted (SSH would try to connect to non-existent host). Now:
not_found,deleted, ordeletingAbort Signal Handling
All async operations respect abort signals, including the status check in
ensureReady()which now properly returns failure on abort rather than optimistically proceeding.Testing
App.coder.stories.tsx)tests/runtime/runtime.test.tsCommits
Generated with
mux• Model:anthropic:claude-opus-4-5• Thinking:high• Cost:$207.48