diff --git a/src/main/ssh/ssh-relay-cross-version-isolation.test.ts b/src/main/ssh/ssh-relay-cross-version-isolation.test.ts index c426e616f..a29801c36 100644 --- a/src/main/ssh/ssh-relay-cross-version-isolation.test.ts +++ b/src/main/ssh/ssh-relay-cross-version-isolation.test.ts @@ -98,7 +98,7 @@ describe('cross-version isolation', () => { // $HOME, isRelayAlreadyInstalled probe, lock acquire, upload (no exec), // npm install, finalize, socket probe, socket poll, then GC scan. const responses: string[] = [ - 'Linux x86_64', // uname -sm + '__ORCA_REMOTE_PLATFORM__ Linux x86_64', // tagged POSIX platform probe '/home/u', // echo $HOME 'MISSING', // isRelayAlreadyInstalled (v2 dir doesn't exist) '', // mkdir -p remoteRelayDir (v2) diff --git a/src/main/ssh/ssh-relay-deploy.test.ts b/src/main/ssh/ssh-relay-deploy.test.ts index ec825cdc4..334678190 100644 --- a/src/main/ssh/ssh-relay-deploy.test.ts +++ b/src/main/ssh/ssh-relay-deploy.test.ts @@ -42,7 +42,7 @@ vi.mock('./ssh-relay-deploy-helpers', () => ({ onData: vi.fn(), onClose: vi.fn() }), - execCommand: vi.fn().mockResolvedValue('Linux x86_64') + execCommand: vi.fn().mockResolvedValue('__ORCA_REMOTE_PLATFORM__ Linux x86_64') })) vi.mock('./ssh-remote-node-resolution', () => ({ @@ -123,7 +123,7 @@ describe('deployAndLaunchRelay', () => { it('calls exec to detect remote platform', async () => { const conn = makeMockConnection() const mockExecCommand = vi.mocked(execCommand) - mockExecCommand.mockResolvedValueOnce('Linux x86_64') // uname -sm + mockExecCommand.mockResolvedValueOnce('__ORCA_REMOTE_PLATFORM__ Linux x86_64') // tagged POSIX platform probe mockExecCommand.mockResolvedValueOnce('/home/user') // echo $HOME mockExecCommand.mockResolvedValueOnce('ORCA-NATIVE-DEPS-OK') // native deps probe mockExecCommand.mockResolvedValueOnce('DEAD') // socket probe @@ -131,13 +131,16 @@ describe('deployAndLaunchRelay', () => { await deployAndLaunchRelay(conn) - expect(mockExecCommand).toHaveBeenCalledWith(conn, 'uname -sm') + expect(mockExecCommand).toHaveBeenCalledWith( + conn, + "printf '\\n%s ' '__ORCA_REMOTE_PLATFORM__'; uname -sm" + ) }) it('reports progress via callback', async () => { const conn = makeMockConnection() const mockExecCommand = vi.mocked(execCommand) - mockExecCommand.mockResolvedValueOnce('Linux x86_64') + mockExecCommand.mockResolvedValueOnce('__ORCA_REMOTE_PLATFORM__ Linux x86_64') mockExecCommand.mockResolvedValueOnce('/home/user') mockExecCommand.mockResolvedValueOnce('ORCA-NATIVE-DEPS-OK') // native deps probe mockExecCommand.mockResolvedValueOnce('DEAD') // socket probe @@ -153,7 +156,7 @@ describe('deployAndLaunchRelay', () => { it('resolves the remote node path once per deploy', async () => { const conn = makeMockConnection() const mockExecCommand = vi.mocked(execCommand) - mockExecCommand.mockResolvedValueOnce('Linux x86_64') + mockExecCommand.mockResolvedValueOnce('__ORCA_REMOTE_PLATFORM__ Linux x86_64') mockExecCommand.mockResolvedValueOnce('/home/user') mockExecCommand.mockResolvedValueOnce('ORCA-NATIVE-DEPS-OK') mockExecCommand.mockResolvedValueOnce('DEAD') @@ -167,7 +170,7 @@ describe('deployAndLaunchRelay', () => { it('resolves node concurrently with remote home, not after the install-state chain', async () => { const conn = makeMockConnection() const mockExecCommand = vi.mocked(execCommand) - mockExecCommand.mockResolvedValueOnce('Linux x86_64') // uname -sm + mockExecCommand.mockResolvedValueOnce('__ORCA_REMOTE_PLATFORM__ Linux x86_64') // tagged POSIX platform probe let markNodeResolutionStarted: () => void = () => {} const nodeResolutionStarted = new Promise((resolve) => { @@ -221,7 +224,7 @@ describe('deployAndLaunchRelay', () => { const conn = makeMockConnection() vi.mocked(conn.canRunConcurrentExecCommands).mockReturnValue(false) const mockExecCommand = vi.mocked(execCommand) - mockExecCommand.mockResolvedValueOnce('Linux x86_64') // uname -sm + mockExecCommand.mockResolvedValueOnce('__ORCA_REMOTE_PLATFORM__ Linux x86_64') // tagged POSIX platform probe let releaseRemoteHome: (home: string) => void = () => {} let remoteHomeProbeStarted: () => void = () => {} const remoteHomeProbeStartedPromise = new Promise((resolve) => { @@ -274,7 +277,7 @@ describe('deployAndLaunchRelay', () => { fallbackInstallStateCompleted = true return true }) - mockExecCommand.mockResolvedValueOnce('Linux x86_64') // uname -sm + mockExecCommand.mockResolvedValueOnce('__ORCA_REMOTE_PLATFORM__ Linux x86_64') // tagged POSIX platform probe mockExecCommand.mockResolvedValueOnce('/home/user') // concurrent install-state $HOME mockExecCommand.mockRejectedValueOnce(sessionLimitError) // concurrent node path probe mockExecCommand.mockResolvedValueOnce('/home/user') // sequential fallback $HOME @@ -302,7 +305,7 @@ describe('deployAndLaunchRelay', () => { throw sessionLimitError }) .mockResolvedValueOnce(true) - mockExecCommand.mockResolvedValueOnce('Linux x86_64') // uname -sm + mockExecCommand.mockResolvedValueOnce('__ORCA_REMOTE_PLATFORM__ Linux x86_64') // tagged POSIX platform probe mockExecCommand.mockResolvedValueOnce('/home/user') // concurrent install-state $HOME mockExecCommand.mockResolvedValueOnce('/home/user') // sequential fallback $HOME mockExecCommand.mockResolvedValueOnce('ORCA-NATIVE-DEPS-OK') // native deps probe @@ -324,7 +327,7 @@ describe('deployAndLaunchRelay', () => { const mockExecCommand = vi.mocked(execCommand) const nodeError = new Error('Node.js not found on remote host') vi.mocked(resolveRemoteNodePath).mockRejectedValueOnce(nodeError) - mockExecCommand.mockResolvedValueOnce('Linux x86_64') // uname -sm + mockExecCommand.mockResolvedValueOnce('__ORCA_REMOTE_PLATFORM__ Linux x86_64') // tagged POSIX platform probe mockExecCommand.mockResolvedValueOnce('/home/user') // concurrent install-state $HOME await expect(deployAndLaunchRelay(conn)).rejects.toBe(nodeError) @@ -346,7 +349,7 @@ describe('deployAndLaunchRelay', () => { }) }) }) - mockExecCommand.mockResolvedValueOnce('Linux x86_64') // uname -sm + mockExecCommand.mockResolvedValueOnce('__ORCA_REMOTE_PLATFORM__ Linux x86_64') // tagged POSIX platform probe mockExecCommand.mockResolvedValueOnce('relative-home') // invalid install-state $HOME const timedDeploy = Promise.race([ @@ -370,7 +373,7 @@ describe('deployAndLaunchRelay', () => { const installError = new Error('permission denied while checking relay install') vi.mocked(resolveRemoteNodePath).mockRejectedValueOnce(sessionLimitError) vi.mocked(isRelayAlreadyInstalled).mockRejectedValueOnce(installError) - mockExecCommand.mockResolvedValueOnce('Linux x86_64') // uname -sm + mockExecCommand.mockResolvedValueOnce('__ORCA_REMOTE_PLATFORM__ Linux x86_64') // tagged POSIX platform probe mockExecCommand.mockResolvedValueOnce('/home/user') // concurrent install-state $HOME await expect(deployAndLaunchRelay(conn)).rejects.toBe(installError) @@ -384,7 +387,7 @@ describe('deployAndLaunchRelay', () => { const sessionLimitError = Object.assign(new Error('(SSH) Channel open failure: open failed'), { reason: 4 }) - mockExecCommand.mockResolvedValueOnce('Linux x86_64') // uname -sm + mockExecCommand.mockResolvedValueOnce('__ORCA_REMOTE_PLATFORM__ Linux x86_64') // tagged POSIX platform probe let releaseRemoteHome: (home: string) => void = () => {} let remoteHomeSettled = false mockExecCommand.mockReturnValueOnce( @@ -420,7 +423,7 @@ describe('deployAndLaunchRelay', () => { it('defaults fresh relays to keep-alive-until-reset', async () => { const conn = makeMockConnection() const mockExecCommand = vi.mocked(execCommand) - mockExecCommand.mockResolvedValueOnce('Linux x86_64') + mockExecCommand.mockResolvedValueOnce('__ORCA_REMOTE_PLATFORM__ Linux x86_64') mockExecCommand.mockResolvedValueOnce('/home/user') mockExecCommand.mockResolvedValueOnce('ORCA-NATIVE-DEPS-OK') mockExecCommand.mockResolvedValueOnce('DEAD') @@ -439,7 +442,7 @@ describe('deployAndLaunchRelay', () => { it('allows an unlimited SSH disconnect grace window', async () => { const conn = makeMockConnection() const mockExecCommand = vi.mocked(execCommand) - mockExecCommand.mockResolvedValueOnce('Linux x86_64') + mockExecCommand.mockResolvedValueOnce('__ORCA_REMOTE_PLATFORM__ Linux x86_64') mockExecCommand.mockResolvedValueOnce('/home/user') mockExecCommand.mockResolvedValueOnce('ORCA-NATIVE-DEPS-OK') mockExecCommand.mockResolvedValueOnce('DEAD') @@ -458,7 +461,7 @@ describe('deployAndLaunchRelay', () => { it('clamps configured SSH disconnect grace to the seven-day maximum', async () => { const conn = makeMockConnection() const mockExecCommand = vi.mocked(execCommand) - mockExecCommand.mockResolvedValueOnce('Linux x86_64') + mockExecCommand.mockResolvedValueOnce('__ORCA_REMOTE_PLATFORM__ Linux x86_64') mockExecCommand.mockResolvedValueOnce('/home/user') mockExecCommand.mockResolvedValueOnce('ORCA-NATIVE-DEPS-OK') mockExecCommand.mockResolvedValueOnce('DEAD') @@ -477,7 +480,7 @@ describe('deployAndLaunchRelay', () => { it('uses a content-hashed versioned remote install directory', async () => { const conn = makeMockConnection() const mockExecCommand = vi.mocked(execCommand) - mockExecCommand.mockResolvedValueOnce('Linux x86_64') + mockExecCommand.mockResolvedValueOnce('__ORCA_REMOTE_PLATFORM__ Linux x86_64') mockExecCommand.mockResolvedValueOnce('/home/user') mockExecCommand.mockResolvedValueOnce('ORCA-NATIVE-DEPS-OK') mockExecCommand.mockResolvedValueOnce('DEAD') @@ -522,12 +525,12 @@ describe('deployAndLaunchRelay', () => { const connB = makeMockConnection() const mockExecCommand = vi.mocked(execCommand) mockExecCommand - .mockResolvedValueOnce('Linux x86_64') // uname A + .mockResolvedValueOnce('__ORCA_REMOTE_PLATFORM__ Linux x86_64') // tagged POSIX platform probe A .mockResolvedValueOnce('/home/user') // $HOME A .mockResolvedValueOnce('ORCA-NATIVE-DEPS-OK') // native deps probe A .mockResolvedValueOnce('DEAD') // probe A .mockResolvedValueOnce('READY') // poll A - .mockResolvedValueOnce('Linux x86_64') // uname B + .mockResolvedValueOnce('__ORCA_REMOTE_PLATFORM__ Linux x86_64') // tagged POSIX platform probe B .mockResolvedValueOnce('/home/user') // $HOME B .mockResolvedValueOnce('ORCA-NATIVE-DEPS-OK') // native deps probe B .mockResolvedValueOnce('DEAD') // probe B @@ -561,8 +564,8 @@ describe('deployAndLaunchRelay', () => { const mockExecCommand = vi.mocked(execCommand) vi.mocked(resolveRemoteNodePath).mockResolvedValue('C:/Program Files/nodejs/node.exe') mockExecCommand - .mockRejectedValueOnce(new Error('uname not found')) // uname -sm - .mockResolvedValueOnce('Windows X64') // PowerShell platform probe + .mockRejectedValueOnce(new Error('uname not found')) // tagged POSIX platform probe + .mockResolvedValueOnce('__ORCA_REMOTE_PLATFORM__ Windows X64') // tagged PowerShell platform probe .mockResolvedValueOnce('C:\\Users\\me user') // remote home .mockResolvedValueOnce('ORCA-NATIVE-DEPS-OK') // native deps probe .mockResolvedValueOnce('') // no persisted active pipe @@ -607,8 +610,8 @@ describe('deployAndLaunchRelay', () => { onClose: vi.fn() }) mockExecCommand - .mockRejectedValueOnce(new Error('uname not found')) // uname -sm - .mockResolvedValueOnce('Windows X64') // PowerShell platform probe + .mockRejectedValueOnce(new Error('uname not found')) // tagged POSIX platform probe + .mockResolvedValueOnce('__ORCA_REMOTE_PLATFORM__ Windows X64') // tagged PowerShell platform probe .mockResolvedValueOnce('C:\\Users\\me user') // remote home .mockResolvedValueOnce('ORCA-NATIVE-DEPS-OK') // native deps probe .mockResolvedValueOnce('') // no persisted active pipe yet @@ -654,8 +657,8 @@ describe('deployAndLaunchRelay', () => { const persistedPipe = '\\\\.\\pipe\\orca-relay-1234567890abcdef1234' vi.mocked(resolveRemoteNodePath).mockResolvedValue('C:/Program Files/nodejs/node.exe') mockExecCommand - .mockRejectedValueOnce(new Error('uname not found')) // uname -sm - .mockResolvedValueOnce('Windows X64') // PowerShell platform probe + .mockRejectedValueOnce(new Error('uname not found')) // tagged POSIX platform probe + .mockResolvedValueOnce('__ORCA_REMOTE_PLATFORM__ Windows X64') // tagged PowerShell platform probe .mockResolvedValueOnce('C:\\Users\\me user') // remote home .mockResolvedValueOnce('ORCA-NATIVE-DEPS-OK') // native deps probe .mockResolvedValueOnce(`${persistedPipe}\n`) // persisted active pipe marker @@ -682,8 +685,8 @@ describe('deployAndLaunchRelay', () => { const mockExecCommand = vi.mocked(execCommand) vi.mocked(resolveRemoteNodePath).mockResolvedValue('C:/Program Files/nodejs/node.exe') mockExecCommand - .mockRejectedValueOnce(new Error('uname not found')) // uname A - .mockResolvedValueOnce('Windows X64') + .mockRejectedValueOnce(new Error('uname not found')) // tagged POSIX platform probe A + .mockResolvedValueOnce('__ORCA_REMOTE_PLATFORM__ Windows X64') .mockResolvedValueOnce('C:\\Users\\me user') .mockResolvedValueOnce('ORCA-NATIVE-DEPS-OK') .mockResolvedValueOnce('') // no persisted active pipe A @@ -691,8 +694,8 @@ describe('deployAndLaunchRelay', () => { .mockResolvedValueOnce('') .mockResolvedValueOnce('READY') .mockResolvedValueOnce('') // persist active pipe A - .mockRejectedValueOnce(new Error('uname not found')) // uname B - .mockResolvedValueOnce('Windows X64') + .mockRejectedValueOnce(new Error('uname not found')) // tagged POSIX platform probe B + .mockResolvedValueOnce('__ORCA_REMOTE_PLATFORM__ Windows X64') .mockResolvedValueOnce('C:\\Users\\me user') .mockResolvedValueOnce('ORCA-NATIVE-DEPS-OK') .mockResolvedValueOnce('') // no persisted active pipe B diff --git a/src/main/ssh/ssh-relay-native-deps-install.test.ts b/src/main/ssh/ssh-relay-native-deps-install.test.ts index 2b63b3a2d..4d2f92eb9 100644 --- a/src/main/ssh/ssh-relay-native-deps-install.test.ts +++ b/src/main/ssh/ssh-relay-native-deps-install.test.ts @@ -152,7 +152,7 @@ function makeExecResponses(opts: { // build toolchain — no chmod/probe/launch slots are reached. if (opts.npmInstall !== 'ok') { return [ - 'Linux x86_64', + '__ORCA_REMOTE_PLATFORM__ Linux x86_64', '/home/u', '', // mkdir remoteDir (uploadRelay) '', // chmod +x node @@ -171,7 +171,7 @@ function makeExecResponses(opts: { ? { reject: 'cd: no such file or directory' } : opts.probe const slots: ExecResponse[] = [ - 'Linux x86_64', + '__ORCA_REMOTE_PLATFORM__ Linux x86_64', '/home/u', '', // mkdir remoteDir (uploadRelay) '', // chmod +x node @@ -530,7 +530,7 @@ describe('installNativeDeps (via deployAndLaunchRelay)', () => { vi.mocked(resolveRemoteNodePath).mockResolvedValueOnce('C:/Program Files/nodejs/node.exe') const conn = makeMockConnection(sftpCapture) feed([ - 'Windows AMD64', + '__ORCA_REMOTE_PLATFORM__ Windows AMD64', 'C:\\Users\\u', '', // mkdir remoteDir '', // npm install native deps @@ -605,7 +605,7 @@ describe('installNativeDeps (via deployAndLaunchRelay)', () => { vi.mocked(isRelayAlreadyInstalled).mockResolvedValue(true) const conn = makeMockConnection(sftpCapture) feed([ - 'Linux x86_64', + '__ORCA_REMOTE_PLATFORM__ Linux x86_64', '/home/u', 'MISSING', // first native-deps probe before lock 'MISSING', // re-probe after lock @@ -632,7 +632,13 @@ describe('installNativeDeps (via deployAndLaunchRelay)', () => { it('does not mutate an existing relay dir when required native deps are present', async () => { vi.mocked(isRelayAlreadyInstalled).mockResolvedValue(true) const conn = makeMockConnection(sftpCapture) - feed(['Linux x86_64', '/home/u', 'ORCA-NATIVE-DEPS-OK', 'DEAD', 'READY']) + feed([ + '__ORCA_REMOTE_PLATFORM__ Linux x86_64', + '/home/u', + 'ORCA-NATIVE-DEPS-OK', + 'DEAD', + 'READY' + ]) await deployAndLaunchRelay(conn) diff --git a/src/main/ssh/ssh-remote-platform-detection.test.ts b/src/main/ssh/ssh-remote-platform-detection.test.ts index a8ffd4168..71fc4e7c0 100644 --- a/src/main/ssh/ssh-remote-platform-detection.test.ts +++ b/src/main/ssh/ssh-remote-platform-detection.test.ts @@ -11,13 +11,18 @@ const { detectRemoteHostPlatform } = await import('./ssh-remote-platform-detecti const conn = {} as SshConnection +function decodePowerShellCommand(command: string): string { + const match = command.match(/-EncodedCommand\s+([A-Za-z0-9+/=]+)/) + return match ? Buffer.from(match[1], 'base64').toString('utf16le') : '' +} + describe('detectRemoteHostPlatform', () => { beforeEach(() => { execCommandMock.mockReset() }) it('detects POSIX hosts from uname output', async () => { - execCommandMock.mockResolvedValueOnce('Linux x86_64\n') + execCommandMock.mockResolvedValueOnce('__ORCA_REMOTE_PLATFORM__ Linux x86_64\n') await expect(detectRemoteHostPlatform(conn)).resolves.toMatchObject({ relayPlatform: 'linux-x64', @@ -25,13 +30,16 @@ describe('detectRemoteHostPlatform', () => { arch: 'x64', pathFlavor: 'posix' }) - expect(execCommandMock).toHaveBeenCalledWith(conn, 'uname -sm') + expect(execCommandMock).toHaveBeenCalledWith( + conn, + "printf '\\n%s ' '__ORCA_REMOTE_PLATFORM__'; uname -sm" + ) }) it('falls back to PowerShell detection for Windows remotes', async () => { execCommandMock .mockRejectedValueOnce(new Error('uname unavailable')) - .mockResolvedValueOnce('Windows AMD64\r\n') + .mockResolvedValueOnce('__ORCA_REMOTE_PLATFORM__ Windows AMD64\r\n') await expect(detectRemoteHostPlatform(conn)).resolves.toMatchObject({ relayPlatform: 'win32-x64', @@ -45,17 +53,50 @@ describe('detectRemoteHostPlatform', () => { expect.stringContaining('powershell.exe'), { wrapCommand: false } ) + const command = execCommandMock.mock.calls[1]?.[1] ?? '' + expect(decodePowerShellCommand(command)).toContain( + 'Write-Output ("`n__ORCA_REMOTE_PLATFORM__ Windows " + $arch)' + ) + }) + + it('ignores untagged platforms before the tagged Windows ARM64 result', async () => { + execCommandMock + .mockRejectedValueOnce(new Error('uname unavailable')) + .mockResolvedValueOnce( + 'Linux x86_64\r\nWindows AMD64\r\n#< CLIXML\r\n' + + '__ORCA_REMOTE_PLATFORM__ Windows ARM64\r\n' + ) + + await expect(detectRemoteHostPlatform(conn)).resolves.toMatchObject({ + relayPlatform: 'win32-arm64', + os: 'win32', + arch: 'arm64', + pathFlavor: 'windows' + }) + }) + + it('ignores a marker concatenated to unterminated startup noise', async () => { + execCommandMock.mockResolvedValueOnce( + 'startup noise__ORCA_REMOTE_PLATFORM__ Linux x86_64\n' + + '__ORCA_REMOTE_PLATFORM__ Linux arm64\n' + ) + + await expect(detectRemoteHostPlatform(conn)).resolves.toMatchObject({ + relayPlatform: 'linux-arm64' + }) }) it('returns null when neither probe yields a supported platform', async () => { - execCommandMock.mockResolvedValueOnce('Linux').mockResolvedValueOnce('FreeBSD x86_64') + execCommandMock + .mockResolvedValueOnce('__ORCA_REMOTE_PLATFORM__ Linux') + .mockResolvedValueOnce('__ORCA_REMOTE_PLATFORM__ FreeBSD x86_64') await expect(detectRemoteHostPlatform(conn)).resolves.toBeNull() }) it('does not use whitespace regex splitting for remote platform output', async () => { const splitSpy = vi.spyOn(String.prototype, 'split') - execCommandMock.mockResolvedValueOnce('Darwin arm64 extra') + execCommandMock.mockResolvedValueOnce('__ORCA_REMOTE_PLATFORM__ Darwin arm64 extra') await expect(detectRemoteHostPlatform(conn)).resolves.toMatchObject({ relayPlatform: 'darwin-arm64' diff --git a/src/main/ssh/ssh-remote-platform-detection.ts b/src/main/ssh/ssh-remote-platform-detection.ts index f31f53f4e..f72b53843 100644 --- a/src/main/ssh/ssh-remote-platform-detection.ts +++ b/src/main/ssh/ssh-remote-platform-detection.ts @@ -1,10 +1,15 @@ import type { SshConnection } from './ssh-connection' -import { getProcessOutputFields } from '../../shared/process-output-field-scanner' +import { + getProcessOutputFields, + iterateProcessOutputLines +} from '../../shared/process-output-field-scanner' import { parseUnameToRelayPlatform, type RelayPlatform } from './relay-protocol' import { execCommand } from './ssh-relay-deploy-helpers' import { getRemoteHostPlatform, type RemoteHostPlatform } from './ssh-remote-platform' import { powerShellCommand } from './ssh-remote-powershell' +const PLATFORM_PROBE_MARKER = '__ORCA_REMOTE_PLATFORM__' + export async function detectRemoteHostPlatform( conn: SshConnection ): Promise { @@ -18,12 +23,12 @@ export async function detectRemoteHostPlatform( async function detectUnamePlatform(conn: SshConnection): Promise { try { - const output = await execCommand(conn, 'uname -sm') - const parts = getProcessOutputFields(output, 2) - if (parts.length < 2) { - return null - } - return parseUnameToRelayPlatform(parts[0], parts[1]) + const output = await execCommand( + conn, + // Why: Remote startup output may omit its trailing newline and must not absorb the marker. + `printf '\\n%s ' '${PLATFORM_PROBE_MARKER}'; uname -sm` + ) + return parseRemotePlatformOutput(output) } catch { return null } @@ -35,15 +40,27 @@ async function detectWindowsPlatform(conn: SshConnection): Promise { describe('detectRemoteHostPlatform', () => { it('uses uname when the remote is POSIX', async () => { - vi.mocked(execCommand).mockResolvedValueOnce('Darwin arm64') + vi.mocked(execCommand).mockResolvedValueOnce('__ORCA_REMOTE_PLATFORM__ Darwin arm64') await expect(detectRemoteHostPlatform(conn)).resolves.toMatchObject({ relayPlatform: 'darwin-arm64', @@ -46,7 +46,7 @@ describe('detectRemoteHostPlatform', () => { it('falls back to PowerShell when uname is unavailable on Windows', async () => { vi.mocked(execCommand) .mockRejectedValueOnce(new Error('uname not recognized')) - .mockResolvedValueOnce('Windows AMD64') + .mockResolvedValueOnce('__ORCA_REMOTE_PLATFORM__ Windows AMD64') await expect(detectRemoteHostPlatform(conn)).resolves.toMatchObject({ relayPlatform: 'win32-x64', @@ -59,5 +59,6 @@ describe('detectRemoteHostPlatform', () => { expect(script).toContain('$arch = $env:PROCESSOR_ARCHITECTURE') expect(script).toContain('try { $runtimeArch =') expect(script).toContain('catch {}') + expect(script).toContain('Write-Output ("`n__ORCA_REMOTE_PLATFORM__ Windows " + $arch)') }) })