diff --git a/electron-builder.yml b/electron-builder.yml index fe4c030..d5594c1 100644 --- a/electron-builder.yml +++ b/electron-builder.yml @@ -74,6 +74,13 @@ win: extraResources: - from: native/computer-use-helper/build/blitz-cu-helper.exe to: blitz-cu-helper.exe + # The supermux ConPTY session-host: the Windows terminal backend that conpty-host.mjs drives over + # host_rpc. resolveSessionHostBin looks for it at process.resourcesPath/bin/session-host.exe, so it + # maps to bin/session-host.exe here. Built by dist-win.ps1 (cargo --release, windows-gnu) into + # vendor/bin/session-host.exe. Self-contained: ldd shows only system DLLs (ucrtbase etc.), no MinGW + # runtime, so it runs on a clean Win10 1809+ box with no extra install. + - from: vendor/bin/session-host.exe + to: bin/session-host.exe # cross-platform analytics config; skipped when absent (local/fork builds) - from: build-config/activity-logging.json to: activity-logging.json diff --git a/scripts/dist-win.ps1 b/scripts/dist-win.ps1 index 501a345..526b107 100644 --- a/scripts/dist-win.ps1 +++ b/scripts/dist-win.ps1 @@ -22,6 +22,33 @@ Write-Host "[dist-win] building native CU helper" & (Join-Path $root 'native\computer-use-helper\build-win.ps1') if ($LASTEXITCODE -ne 0) { throw "[dist-win] helper build failed ($LASTEXITCODE)" } +# The Windows terminal backend: the supermux ConPTY session-host (conpty-host.mjs drives it over host_rpc). +# Bundled via win.extraResources at vendor/bin/session-host.exe (resolveSessionHostBin reads it at +# process.resourcesPath/bin/session-host.exe). It is a VENDORED binary (like vendor/bin/tmux on mac): a +# checkout already carries it, so a plain build just uses it. To REFRESH from source, set $env:SUPERMUX_REPO +# to the supermux repo root and re-run. Self-contained (ldd: only system DLLs, no MinGW runtime). +$sessionHost = Join-Path $root 'vendor\bin\session-host.exe' +if ($env:SUPERMUX_REPO) { + Write-Host "[dist-win] building supermux session-host from $env:SUPERMUX_REPO" + Push-Location (Join-Path $env:SUPERMUX_REPO 'server') + cargo build --release --bin session-host --target x86_64-pc-windows-gnu + $built = Join-Path (Get-Location).Path 'target\x86_64-pc-windows-gnu\release\session-host.exe' + Pop-Location + if (-not (Test-Path $built)) { throw "[dist-win] session-host build produced no exe at $built" } + New-Item -ItemType Directory -Force (Split-Path $sessionHost) | Out-Null + Copy-Item $built $sessionHost -Force + Write-Host "[dist-win] vendored session-host.exe ($([math]::Round((Get-Item $sessionHost).Length/1MB,1)) MB)" +} elseif (-not (Test-Path $sessionHost)) { + throw "[dist-win] vendor\bin\session-host.exe missing and SUPERMUX_REPO not set. Set `$env:SUPERMUX_REPO to the supermux repo root to build it." +} else { + Write-Host "[dist-win] using vendored vendor\bin\session-host.exe (set `$env:SUPERMUX_REPO to refresh from source)" +} + +# PREREQUISITE (Windows): Git for Windows must be installed on the END-USER machine. The agent runtime is +# POSIX (claude runs wait.sh / curl / tail / cat via its Bash tool), and Claude Code makes Git Bash optional +# (it falls back to the PowerShell tool, which cannot run that runtime). conpty-host pins the agent to Git +# Bash (CLAUDE_CODE_GIT_BASH_PATH); document Git for Windows in the install instructions. + Write-Host "[dist-win] electron-vite build" npm run build if ($LASTEXITCODE -ne 0) { throw "[dist-win] electron-vite build failed ($LASTEXITCODE)" } diff --git a/src/main/agent-runtime.mjs b/src/main/agent-runtime.mjs index cf41260..0e0fe35 100644 --- a/src/main/agent-runtime.mjs +++ b/src/main/agent-runtime.mjs @@ -206,6 +206,48 @@ export function buildAgentCommand({ runtime = AGENT_RUNTIME_CLAUDE, cmd, claudeS return buildClaudeCommand({ cmd: cmd || 'claude', claudeSid, mode, bootstrapFile, effort, hooks }) } +/** Resolve a POSIX shell (Git Bash) on Windows. The agent command + runtime are POSIX-shaped, so on win32 + * the ConPTY terminal host (which runs a program directly, no shell) must launch them under bash. Order: + * BLITZ_BASH_BIN, then the standard Git-for-Windows install paths. null = not found. Cached. */ +let resolvedBash +function resolveBashBin() { + if (resolvedBash !== undefined) return resolvedBash + const cands = [ + process.env.BLITZ_BASH_BIN, + 'C:\\Program Files\\Git\\bin\\bash.exe', + 'C:\\Program Files\\Git\\usr\\bin\\bash.exe', + 'C:\\Program Files (x86)\\Git\\bin\\bash.exe' + ].filter(Boolean) + resolvedBash = cands.find((p) => { try { return existsSync(p) } catch { return false } }) || null + return resolvedBash +} + +/** Windows: wrap a POSIX agent command so the ConPTY terminal host can run it. The command uses + * "$(cat bootstrap)" substitution and the agent then runs bash/curl/tail/wait.sh, none of which the bare + * CreateProcessW path provides. Write the command to a per-session launcher script and return a + * `bash