private/Invoke-WtwWmuxProject.ps1
|
function Get-WtwWmuxBin { [CmdletBinding()] param() if ($env:WMUX_CLI -and (Test-Path $env:WMUX_CLI)) { return $env:WMUX_CLI } $cmd = Get-Command wmux -ErrorAction SilentlyContinue if ($cmd) { return $cmd.Source } if (-not $IsWindows) { return $null } $candidates = @( (Join-Path $env:LOCALAPPDATA 'Programs/wmux/wmux.exe'), (Join-Path $env:LOCALAPPDATA 'wmux/wmux.exe'), (Join-Path $env:ProgramFiles 'wmux/wmux.exe'), (Join-Path ${env:ProgramFiles(x86)} 'wmux/wmux.exe') ) | Where-Object { $_ } return $candidates | Where-Object { Test-Path $_ } | Select-Object -First 1 } function Test-WtwWmuxPresent { [CmdletBinding()] param() return [bool](Get-WtwWmuxBin) } function Invoke-WtwWmuxCommand { [CmdletBinding()] param( [Parameter(Mandatory)] [string[]] $ArgumentList ) $wmux = Get-WtwWmuxBin if (-not $wmux) { return [PSCustomObject]@{ ExitCode = 127; Output = 'wmux CLI not found' } } Write-Verbose "wmux command: $wmux $($ArgumentList -join ' ')" $output = & $wmux @ArgumentList 2>&1 $outputText = $output -join [Environment]::NewLine $exitCode = $LASTEXITCODE if ($null -eq $exitCode) { $exitCode = 1 if ([string]::IsNullOrWhiteSpace($outputText)) { $outputText = 'wmux CLI command did not report an exit code.' } } if ($outputText -match 'failed to get single instance lock|gotLock\s*=\s*false') { $exitCode = 1 if (-not ($outputText -match 'wmux CLI command was not accepted')) { $outputText = "wmux CLI command was not accepted by the running app. $outputText" } } return [PSCustomObject]@{ ExitCode = $exitCode; Output = $outputText } } function ConvertFrom-WtwWmuxJsonOutput { [CmdletBinding()] param([string] $Output) if ([string]::IsNullOrWhiteSpace($Output)) { return $null } try { return $Output | ConvertFrom-Json -Depth 100 -ErrorAction Stop } catch { return $null } } function Get-WtwWmuxObjectValue { [CmdletBinding()] param( [Parameter(Mandatory)] $Object, [Parameter(Mandatory)][string[]] $Names ) foreach ($name in $Names) { $prop = $Object.PSObject.Properties[$name] if ($prop -and $null -ne $prop.Value -and "$($prop.Value)" -ne '') { return $prop.Value } } return $null } function Get-WtwWmuxLiveWorkspaces { [CmdletBinding()] param() $result = Invoke-WtwWmuxCommand -ArgumentList @('list-workspaces', '--json') if ($result.ExitCode -ne 0) { return @() } $parsed = ConvertFrom-WtwWmuxJsonOutput -Output $result.Output if (-not $parsed) { return @() } if ($parsed -is [array]) { return @($parsed) } if ($parsed.PSObject.Properties.Name -contains 'workspaces') { return @($parsed.workspaces) } return @($parsed) } function Get-WtwWmuxLiveSurfaces { [CmdletBinding()] param() $result = Invoke-WtwWmuxCommand -ArgumentList @('list-surfaces', '--json') if ($result.ExitCode -ne 0) { return @() } $parsed = ConvertFrom-WtwWmuxJsonOutput -Output $result.Output if (-not $parsed) { return @() } if ($parsed -is [array]) { return @($parsed) } if ($parsed.PSObject.Properties.Name -contains 'surfaces') { return @($parsed.surfaces) } return @($parsed) } function Find-WtwWmuxWorkspace { [CmdletBinding()] param([Parameter(Mandatory)][string] $PrettyName) $workspaces = Get-WtwWmuxLiveWorkspaces if ($workspaces.Count -eq 0) { return $null } return $workspaces | Where-Object { $name = Get-WtwWmuxObjectValue -Object $_ -Names @('name', 'title', 'displayName') [string]::Equals($name, $PrettyName, [System.StringComparison]::OrdinalIgnoreCase) } | Select-Object -First 1 } function ConvertTo-WtwWmuxPowerShellSingleQuotedLiteral { [CmdletBinding()] param([AllowNull()][string] $Value) return "'$($Value.Replace("'", "''"))'" } function Initialize-WtwWmuxWorkspaceShell { [CmdletBinding()] param( [Parameter(Mandatory)][string] $ProjectPath, [Parameter(Mandatory)][string] $PrettyName ) # Current wmux releases ignore cwd on new-workspace; newer builds may honor # --cwd on new-surface. Keep both paths useful by also sending Set-Location. $surfaceResult = Invoke-WtwWmuxCommand -ArgumentList @('new-surface', '--cwd', $ProjectPath) if ($surfaceResult.ExitCode -ne 0) { return [PSCustomObject]@{ Success = $false; Reason = "new-surface failed: $($surfaceResult.Output)" } } Start-Sleep -Milliseconds 250 $initCommand = "Set-Location -LiteralPath $(ConvertTo-WtwWmuxPowerShellSingleQuotedLiteral -Value $ProjectPath); Clear-Host" $sendResult = Invoke-WtwWmuxCommand -ArgumentList @('send', $initCommand) if ($sendResult.ExitCode -ne 0) { return [PSCustomObject]@{ Success = $false; Reason = "send failed: $($sendResult.Output)" } } $enterResult = Invoke-WtwWmuxCommand -ArgumentList @('send-key', 'Enter') if ($enterResult.ExitCode -ne 0) { return [PSCustomObject]@{ Success = $false; Reason = "send-key failed: $($enterResult.Output)" } } return [PSCustomObject]@{ Success = $true; Reason = $null } } function Open-WtwWmuxProject { [CmdletBinding()] param( [Parameter(Mandatory)][string] $ProjectPath, [Parameter(Mandatory)][string] $PrettyName, [string] $StatusValue ) if (-not $IsWindows) { return [PSCustomObject]@{ Success = $false; Reason = 'wmux is Windows-only' } } if (-not (Test-WtwWmuxPresent)) { return [PSCustomObject]@{ Success = $false; Reason = 'wmux CLI not found' } } return [PSCustomObject]@{ Success = $false Created = $false WorkspaceName = $PrettyName Path = [System.IO.Path]::GetFullPath($ProjectPath) Reason = 'wmux CLI workspace/surface commands are no-op in the current installed wmux build; WTW integration is disabled until wmux exposes the substrate/API tracked in openwong2kim/wmux#15.' } } function Register-WtwWmuxProject { <# .SYNOPSIS Best-effort live wmux workspace registration for a worktree. .DESCRIPTION wmux currently exposes live workspace commands rather than a stable SourceGit-style on-disk repository registry. This therefore registers a worktree only when the wmux CLI is installed and reachable. #> [CmdletBinding()] param( [Parameter(Mandatory)][string] $ProjectPath, [Parameter(Mandatory)][string] $PrettyName, [string] $RepoName, [string] $TaskName ) if (-not $IsWindows) { return $null } if (-not (Test-WtwWmuxPresent)) { return $null } $statusValue = if ($RepoName -and $TaskName) { "$RepoName/$TaskName" } elseif ($RepoName) { $RepoName } else { $null } Write-Host ' wmux: integration pending upstream workspace/surface API - skipping project registration.' -ForegroundColor DarkGray return $null } function Unregister-WtwWmuxProject { [CmdletBinding()] param([string] $PrettyName) if (-not $IsWindows) { return } if (-not $PrettyName) { return } if (-not (Test-WtwWmuxPresent)) { return } $workspace = Find-WtwWmuxWorkspace -PrettyName $PrettyName if (-not $workspace) { return } $workspaceId = Get-WtwWmuxObjectValue -Object $workspace -Names @('id', 'ref', 'workspaceId') if (-not $workspaceId) { return } $result = Invoke-WtwWmuxCommand -ArgumentList @('close-workspace', "$workspaceId") if ($result.ExitCode -eq 0) { Write-Host " wmux: removed live workspace '$PrettyName'." -ForegroundColor Green } } |