Skip to content

fix(preflight): do not pin empty WSL/local agent detection (#8366)#8391

Open
bbingz wants to merge 2 commits into
stablyai:mainfrom
bbingz:fix/wsl-agent-detect-nonsticky-empty
Open

fix(preflight): do not pin empty WSL/local agent detection (#8366)#8391
bbingz wants to merge 2 commits into
stablyai:mainfrom
bbingz:fix/wsl-agent-detect-nonsticky-empty

Conversation

@bbingz

@bbingz bbingz commented Jul 12, 2026

Copy link
Copy Markdown
Contributor

Summary

WSL cold-start / probe failures return an empty agent list, and the renderer treated that empty [] as a successful cache hit (if (existing) is true for arrays). The launcher then permanently hid installed agents (including Grok) until a context switch. This also adds one cold-start retry for WSL ETIMEDOUT / killed probes, and wires the local launch surfaces to re-probe once on remount after an empty result (same contract as SSH/runtime).

Closes #8366

Root cause

  1. Renderer pin: ensureDetectedAgents short-circuited on any non-null detectedAgentIds, including []. Remote/runtime already used existing?.length (Detect agents in the serve user's package-manager bins; don't pin empty remote-detect results #6029); local did not.
  2. Resolved empty promise: even after a re-entry, a resolved detectPromise for the same context key could still short-circuit.
  3. WSL soft-fail: detectWslCommandsOnPath swallowed timeouts into new Set() with no retry, feeding the sticky empty cache.
  4. Hook gap (follow-up in this PR): store non-sticky empty alone was not enough — useDetectedAgents only called ensureLocal when detectedIds === null, so TabBar/QuickLaunch never re-entered after []. SSH/runtime already had one empty remount retry; local did not.

Fix

  • Local cache short-circuit: existing?.length && detectedContextKey === contextKey (mirror remote/runtime).
  • Clear detectPromise when the detection/refresh result is empty so the next ensure re-probes.
  • Retry WSL agent detection once on ETIMEDOUT / killed only; hard shell failures still fail immediately to empty.
  • useDetectedAgents local path: one empty remount retry per mounted surface (emptyRetryKey = 'local'), same shape as SSH/runtime.

Merge order

Land Grok-compat fixes in this order (independent of this PR's file set unless noted):

  1. fix(terminal): stop leaking Shift+Enter CSI-u without Kitty handshake #8386 — Shift/Ctrl+Enter CSI-u encoding (input correctness; land first if still open)
  2. Fix zero-percent Grok usage visibility #8336 — SuperGrok weekly zero usage (minimal; close fix(grok): tolerate missing creditUsagePercent in billing API #8298 as overreach)
  3. fix(codex): use argv-safe POSIX hook commands #8390 — Codex argv-safe POSIX hooks (/bin/sh '<path>', closes [Bug] Codex hooks failing when launched via Orca (from Grok) #8110)
  4. This PR — non-sticky empty WSL/local agent detection + local launcher remount retry ([windows] Sometimes Grok CLI is not detected in Orca but works in system terminal #8366)
  5. Follow-up auth residual PR (fix(grok): prefer auth.x.ai session + mention Grok in OSC52 toast #8392 prefer auth.x.ai entry) — can land in any order relative to this PR

This PR does not depend on #8386 / #8336 / #8390 and may land as soon as it is green. Prefer landing after #8390 only for review sequencing of the Grok-compat batch, not for correctness.

Test plan

  • pnpm exec vitest run --config config/vitest.config.ts src/renderer/src/store/slices/detected-agents.test.ts src/main/ipc/preflight-wsl-agent-detection.test.ts src/renderer/src/hooks/useDetectedAgents.test.tsx
  • Unit: empty local detection re-probes on next ensure (store)
  • Unit: local launch surface remount retries empty once and does not thrash on same mount
  • Unit: WSL ETIMEDOUT / killed retries once and returns second result
  • Unit: non-timeout probe failures do not retry
  • Manual (Windows+WSL): cold-start Orca with Grok on PATH in WSL; open launcher twice without switching projects — Grok should appear after a warm probe

…8366)

Empty [] is truthy, so a cold-start soft-fail permanently hid agents from
the launcher until a context switch. Match remote/runtime non-sticky empty
caching, clear empty detectPromise snapshots, and retry one WSL ETIMEDOUT.
@coderabbitai

coderabbitai Bot commented Jul 12, 2026

Copy link
Copy Markdown
Contributor

Review Change Stack

📝 Walkthrough

Walkthrough

Adds one retry for WSL detection command failures caused by timeouts or killed child processes, while leaving other failures non-retriable. Expands tests for retry counts and returned results. Updates detected-agent state handling so empty detection or refresh results do not remain cached, allowing subsequent detection calls to run again. Adds local hook retry behavior and coverage for empty results, remounts, and later detected agents.

🚥 Pre-merge checks | ✅ 4 | ❌ 1

❌ Failed checks (1 warning)

Check name Status Explanation Resolution
Description check ⚠️ Warning The description covers the change and testing, but it omits required template sections for screenshots, AI review report, security audit, and notes. Add the missing sections, including screenshots/no visual change, a cross-platform AI review summary, a security audit, and platform-specific notes.
✅ Passed checks (4 passed)
Check name Status Explanation
Linked Issues check ✅ Passed The changes satisfy #8366 by making empty local/WSL detection non-sticky and adding one retry for timeout/killed probes.
Out of Scope Changes check ✅ Passed No unrelated billing or Codex-hook changes were introduced; the diff stays focused on WSL/local agent detection and retry behavior.
Docstring Coverage ✅ Passed No functions found in the changed files to evaluate docstring coverage. Skipping docstring coverage check.
Title check ✅ Passed The title is concise and accurately summarizes the main change: preventing empty WSL/local agent detection from being pinned.

Thanks for using CodeRabbit! It's free for OSS, and your support helps us grow. If you like it, consider giving us a shout-out.

❤️ Share

Comment @coderabbitai help to get the list of available commands.

@coderabbitai coderabbitai Bot left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

🧹 Nitpick comments (1)
src/main/ipc/preflight-wsl-agent-detection.test.ts (1)

99-135: 📐 Maintainability & Code Quality | 🔵 Trivial | ⚡ Quick win

Consider adding a retry exhaustion test.

The three new tests cover single-retry success and non-retriable failure, but don't verify behavior when both attempts timeout (retry exhaustion). A test confirming detectWslCommandsOnPath returns an empty Set and execFileAsyncMock is called exactly twice after two consecutive ETIMEDOUT rejections would close the gap.

🧪 Suggested test for retry exhaustion
  it('returns an empty set when both attempts timeout', async () => {
    const timeoutError = Object.assign(new Error('Timed out running wsl.exe'), {
      code: 'ETIMEDOUT'
    })
    execFileAsyncMock.mockRejectedValue(timeoutError)

    const found = await detectWslCommandsOnPath({ distro: 'Ubuntu' }, ['grok'])

    expect(found).toEqual(new Set())
    expect(execFileAsyncMock).toHaveBeenCalledTimes(2)
  })

ℹ️ Review info
⚙️ Run configuration

Configuration used: Repository UI

Review profile: CHILL

Plan: Pro

Run ID: d1b358ea-54b0-4880-a68a-aef5c16402c7

📥 Commits

Reviewing files that changed from the base of the PR and between 26934b1 and 8663d45.

📒 Files selected for processing (4)
  • src/main/ipc/preflight-wsl-agent-detection.test.ts
  • src/main/ipc/preflight-wsl-agent-detection.ts
  • src/renderer/src/store/slices/detected-agents.test.ts
  • src/renderer/src/store/slices/detected-agents.ts

Store non-sticky empty was not enough: useDetectedAgents only called
ensureLocal when detectedIds was null, so TabBar/QuickLaunch never
re-probed after a WSL cold-start []. Mirror SSH/runtime one-shot empty
remount retry for local surfaces (stablyai#8366 / stablyai#8391).
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

[windows] Sometimes Grok CLI is not detected in Orca but works in system terminal [Bug] Codex hooks failing when launched via Orca (from Grok)

2 participants