Tags: wjw0315/mux
Tags
🤖 refactor: auto-cleanup (coder#2942) ## Summary Periodic auto-cleanup: removes the dead `setPRStatusStoreInstance` export from `PRStatusStore.ts`. ## Background The function was exported but never imported or called anywhere in the codebase. The getter (`getPRStatusStoreInstance`) creates the singleton on demand; no test or production code ever needed to inject a custom instance via the setter. It is the only `set*StoreInstance` pattern across all stores, so there is no convention to maintain. ## Validation - `make typecheck` — passes - `make lint` — passes - `make fmt-check` — passes - `bun test src/browser/stores/PRStatusStore` — 12/12 pass - Grep confirms zero references outside the definition site Auto-cleanup checkpoint: ff743d1 --- _Generated with `mux` • Model: `anthropic:claude-opus-4-6` • Thinking: `xhigh` • Cost: `$0.00`_ <!-- mux-attribution: model=anthropic:claude-opus-4-6 thinking=xhigh costs=0.00 --> Co-authored-by: mux-bot[bot] <264182336+mux-bot[bot]@users.noreply.github.com>
🤖 feat: add per-model provider modelParameters overrides (coder#2743) ## Summary Add config-driven per-model parameter overrides from `~/.mux/providers.jsonc` and thread them through the chat streaming path so standard call settings (for example `max_output_tokens`, `temperature`, and `top_p`) are applied at request time, while provider-specific extra keys are safely merged into provider options. Closes coder#2574 ## Background Users need a way to tune model request parameters without code changes or UI additions. This adds a providers-config surface that supports exact model entries plus wildcard fallbacks and keeps runtime behavior defensive for hand-edited config. ## Implementation - Added shared schemas and types for `modelParameters` in provider config, including a single snake_case→AI SDK call-settings mapping source of truth. - Added `resolveModelParameterOverrides(...)` with precedence: 1. effective model id 2. canonical model id 3. `"*"` wildcard - Split resolved values into: - `standard` call settings (mapped to SDK keys) - `providerExtras` (unknown keys) - Integrated override resolution in `AIService.streamMessage()` and: - deep-merged `providerExtras` under the provider namespace - preserved Mux-built provider options as conflict winners - passed resolved standard settings through `startStream(..., callSettingsOverrides)` - Threaded call settings through StreamManager request construction and into `streamText(...)`, with explicit precedence for `maxOutputTokens`: 1. explicit per-request value 2. config override 3. model stats fallback - Added debug logs for resolved overrides under `MUX_DEBUG_LLM_REQUEST=1`. ## Validation - `make static-check` - `bun test src/common/config/schemas/providersConfig.test.ts src/common/utils/ai/modelParameterOverrides.test.ts src/node/services/streamManager.test.ts src/node/services/aiService.test.ts` ## Risks - Medium/contained: the change touches the main chat stream assembly path and provider option composition. - Mitigations: - provider extras are namespace-scoped and merged under existing Mux options - standard keys are type-constrained and defensively validated at resolution time - precedence behavior is covered by focused unit tests --- _Generated with `mux` • Model: `openai:gpt-5.3-codex` • Thinking: `xhigh` • Cost: `$13.96`_ <!-- mux-attribution: model=openai:gpt-5.3-codex thinking=xhigh costs=13.96 -->
🤖 feat: merge Costs + Stats into unified Stats tab with sub-tabs (cod… …er#2729) ## Summary Merge the standalone "Costs" and "Stats" top-level tabs into a single unified "Stats" tab with sub-tabs (Cost, Timing, Models). ## Background Previously the right sidebar had separate "Costs" and "Stats" tabs. The Stats tab was feature-flagged and duplicated some navigation patterns. This consolidates them into a single top-level "Stats" tab with a ToggleGroup for switching between sub-views. ## Implementation - **Internal key preserved**: The stored tab key remains `"costs"` to avoid persisted layout migrations. Only the display name changes to "Stats". - **Sub-tab container** (`StatsContainer.tsx`): Uses `ToggleGroup` with "Cost", "Timing", and "Models" options. Timing/Models only appear when the `statsTab` feature flag is enabled. - **Extracted panels**: `TimingPanel` and `ModelBreakdownPanel` extracted from `StatsTab.tsx` via shared `useStatsData` hook. - **Unified tab label**: Merged `CostsTabLabel` + `StatsTabLabel` into one component showing both cost and duration badges. - **Layout migration**: `stripLegacyStatsTab` runs as a pre-parse step in `parseRightSidebarLayoutState`, stripping `"stats"` from persisted layouts before `isTabType` validation. This preserves user layout configuration during upgrade. --- _Generated with `mux` • Model: `anthropic:claude-opus-4-6` • Thinking: `xhigh` • Cost: `$6.61`_ <!-- mux-attribution: model=anthropic:claude-opus-4-6 thinking=xhigh costs=6.61 -->
🤖 feat: add Debugging docs for Output tab (coder#2645) ## Summary Add documentation for Mux's Output-tab debugging workflow. - Added a new Reference page: `docs/reference/debugging.mdx` - Documented command-palette command mode (`>`) before running **Show Output**/**Hide Output** - Documented log-level filtering, clearing logs, and opening the raw log file - Added navigation entry in `docs/docs.json` under **Reference** - Added redirect: `/debugging` → `/reference/debugging` - Regenerated `src/node/builtinSkills/mux-docs.md` via `make fmt` ## Validation - `make fmt` - `make static-check` ## Risks Low risk. Changes are documentation-only plus the expected generated mux-docs index sync. --- _Generated with `mux` • Model: `openai:gpt-5.3-codex` • Thinking: `xhigh` • Cost: `$1.41`_ <!-- mux-attribution: model=openai:gpt-5.3-codex thinking=xhigh costs=1.41 -->
🤖 fix: eliminate dev-server startup crash from tsgo/tsc-alias race (c… …oder#2612) ## Summary Fix the `make dev-server` startup crash (`Cannot find module '@/node/config'`) that occurs on every cold start on non-Windows platforms. ## Background The non-Windows `dev-server` target launches `tsgo -w` and `tsc-alias -w` as **independent parallel watchers**. On startup, tsgo immediately rebuilds `dist/` with unresolved `@/` path aliases, and nodemon restarts the server after its 500ms delay — before tsc-alias finishes rewriting all ~415 files. This produces a transient `MODULE_NOT_FOUND` crash every time. The Windows `dev-server` target already avoids this by using `scripts/build-main-watch.js`, which runs tsgo → tsc-alias **sequentially**. ## Implementation Replace the parallel watcher pair with a source-watching nodemon that executes the existing sequential `build-main-watch.js` script on each change — the same approach Windows already uses. This is a one-line Makefile change (plus a comment). ## Validation - `make build-main` passes - `make dev-server` starts without the `Cannot find module '@/node/config'` crash - Source file changes trigger sequential rebuild → clean server restart --- _Generated with `mux` • Model: `anthropic:claude-opus-4-6` • Thinking: `xhigh` • Cost: `$2.23`_ <!-- mux-attribution: model=anthropic:claude-opus-4-6 thinking=xhigh costs=2.23 -->
🤖 refactor: apply react-effects guidance to runtime settings (coder#2570 ) ## Summary Apply `react-effects` skill guidance to eliminate 4 anti-pattern useEffects and tighten 1 more in the runtime settings UI code. Net removal of ~90 lines of effect/ref machinery, replaced by render-time derivation and event-handler colocation. ## Background An audit of the runtime settings code (`useDraftWorkspaceSettings.ts`, `RuntimesSection.tsx`) flagged several effects that violate the project's `react-effects` skill guidelines: 1. **Mode-switch restoration** lived in a `useEffect` watching `selectedRuntime.mode` via a prev-ref, but mode switches are always user-initiated events 2. **Project override sync** stored 3 derived values in state and synced them via a large effect, when they're deterministic functions of existing data 3. **Scope validity guard** used an effect to reset scope when a project disappears, when the valid scope can be derived during render 4. **Project/default reset** used two prev-refs to detect project or default-mode changes and imperatively reset state, solvable with React's `key` pattern 5. **Default seeding** re-ran on every dep change instead of once per project mount ## Implementation ### `RuntimesSection.tsx` - **Scope validity:** Removed the effect. Added `effectiveScope` computed during render that falls back to `ALL_SCOPE_VALUE` when the selected project isn't in the projects map. UI binds to `effectiveScope`. - **Project override sync:** Removed 3 `useState` + the sync effect. Added `deriveProjectOverrideState()` pure function called during render. Handlers (`handleOverrideToggle`, `handleRuntimeToggle`) now rely solely on the existing cache + version-bump mechanism for optimistic updates. ### `useDraftWorkspaceSettings.ts` - **Mode-switch restore:** Extracted `mergeRememberedRuntimeConfig()` pure helper. `setSelectedRuntime` merges remembered fields synchronously before committing state. Deleted the 50-line effect + `prevSelectedRuntimeModeRef`. - **Project reset:** Updated `ChatInput` key in `ProjectPage.tsx` to include `projectPath`, so project switches trigger natural React remount. Removed `prevProjectPathRef`. Simplified default-mode tracking to `appliedDefaultRuntimeChoiceRef`. - **Default seeding:** Added `seededProjectPathRef` so seeding runs once per project mount. ## Validation - `make static-check` passes - 16/16 focused tests pass (`useDraftWorkspaceSettings` + `useCreationWorkspace`) ## Risks - **Key-based remount** (`ProjectPage.tsx`): Adding `projectPath` to the `ChatInput` key means project switches fully remount the input. This is the intended behavior (reset draft state), but worth verifying that no expensive initialization (branch fetching, etc.) causes a visible delay during project navigation. - **Optimistic override UI**: Handlers now rely entirely on cache writes + version bumps for re-derivation. Verified that both `handleOverrideToggle` and `handleRuntimeToggle` already write to `overrideCacheRef` and bump the version counter. --- _Generated with `mux` • Model: `anthropic:claude-opus-4-6` • Thinking: `xhigh` • Cost: `$3.22`_ <!-- mux-attribution: model=anthropic:claude-opus-4-6 thinking=xhigh costs=3.22 -->
🤖 fix: unify SSH clone prompt mediation for clone flows (coder#2544) ## Summary Adds a unified SSH prompt mediation pipeline for the git clone flow so that OpenSSH prompts (host-key verification, credential/passphrase) are surfaced in-app instead of causing cryptic clone failures. Most of the diff is tests. ## Background When cloning via SSH (especially with GitHub shorthand like `owner/repo`), OpenSSH prompts were not visible in the Electron app. This caused silent hangs and opaque error messages. The fix introduces a mediated askpass architecture that intercepts SSH prompts, routes them through `SshPromptService` to the frontend via oRPC subscriptions, and classifies errors deterministically from structured prompt outcomes. ## Implementation **Prompt mediation pipeline:** - `SshPromptService` — manages pending prompt lifecycle, deduplication by SSH endpoint, timeout, and responder gating - `openSshPromptMediation.ts` — `createMediatedAskpassSession()` bridges askpass ↔ `SshPromptService`, classifies prompts (host-key vs credential), records `MediatedPromptOutcome` for downstream error classification - `sshAskpass.ts` — spawns a local HTTP server as `SSH_ASKPASS` target so OpenSSH can route prompts back to the app - `SshPromptDialog.tsx` — generic in-app dialog for both host-key and credential SSH prompts **Error classification (outcome-first architecture):** - `sshCloneFailure.ts` — dedicated module with `classifySshCloneFailure()` that derives error codes from structured prompt outcomes (timeout, rejection, cancellation) rather than fragile stderr regex matching; stderr heuristics remain as fallback only - `summarizeCloneStderr()` — returns last 3 meaningful stderr lines instead of just the final line, preventing truncated diagnostic messages like "and the repository exists." **Canonical SSH transport detection:** - Introduced `parseCloneTransport()` — a single parser/classifier for clone URL transport semantics that all SSH-related decisions consume (askpass enablement + prompt deduplication) - Recognizes SCP-style (`[user@]host:path`), `ssh://`, `git+ssh://`, and `ssh+git://` as SSH transports - `isSshCloneUrl()` and `deriveSshClonePromptDedupeKey()` both delegate to `parseCloneTransport()` — no duplicated protocol logic - Previously, `git+ssh://` and `ssh+git://` URLs bypassed askpass setup, causing opaque clone failures **Schema/contract tightening:** - Clone error `code` is now required (not optional) in the oRPC schema, matching the backend behavior that always emits a code - Frontend `formatCloneError` accepts required `code`, providing deterministic error-to-message mapping **Clone URL handling:** - `parseScpStyleSshUrl()` handles `[user@]host:path` SCP-style URLs without requiring a username, with a protocol-URL exclusion guard to prevent matching `https://...` ## Validation - 36 projectService tests pass including: host-key accept/reject, endpoint dedupe for concurrent clones, timeout classification (50ms), ambiguous transport → `clone_failed`, credential success, credential cancel → `ssh_credential_cancelled`, multi-line stderr summary, HTTPS/git:// no-askpass, ssh://+git+ssh://+ssh+git:// askpass injection - 21 sshPromptService tests pass - 8 SshPromptDialog tests pass - `make static-check` passes (typecheck, lint, format, docs link check) ## Risks - **Low:** SSH askpass HTTP server binds to localhost on a random port per clone; if the clone process outlives cleanup, the port is leaked until process exit (mitigated by `using` disposable pattern) - **Low:** Stderr regex fallbacks could mis-classify novel SSH error formats; mitigated by preferring structured prompt outcomes when available --- _Generated with `mux` • Model: `anthropic:claude-opus-4-6` • Thinking: `xhigh`_ <!-- mux-attribution: model=anthropic:claude-opus-4-6 thinking=xhigh -->
PreviousNext