mirror of
https://github.com/stablyai/orca.git
synced 2026-10-28 08:02:54 +00:00
@@ -589,6 +589,31 @@ describe('preflight', () => {
|
||||
})
|
||||
})
|
||||
|
||||
it('returns no remote agents when the SSH connection is unavailable', async () => {
|
||||
getActiveMultiplexerMock.mockReturnValue(null)
|
||||
|
||||
registerPreflightHandlers()
|
||||
|
||||
await expect(
|
||||
handlers['preflight:detectRemoteAgents'](undefined, { connectionId: 'ssh-1' })
|
||||
).resolves.toEqual([])
|
||||
})
|
||||
|
||||
it('returns no remote agents when the SSH connection is disposed', async () => {
|
||||
const request = vi.fn()
|
||||
getActiveMultiplexerMock.mockReturnValue({
|
||||
isDisposed: () => true,
|
||||
request
|
||||
})
|
||||
|
||||
registerPreflightHandlers()
|
||||
|
||||
await expect(
|
||||
handlers['preflight:detectRemoteAgents'](undefined, { connectionId: 'ssh-1' })
|
||||
).resolves.toEqual([])
|
||||
expect(request).not.toHaveBeenCalled()
|
||||
})
|
||||
|
||||
it('detects agents from the selected WSL distro for a WSL workspace', async () => {
|
||||
Object.defineProperty(process, 'platform', {
|
||||
configurable: true,
|
||||
|
||||
@@ -248,7 +248,9 @@ export async function refreshShellPathAndDetectAgents(
|
||||
export async function detectRemoteAgents(args: { connectionId: string }): Promise<string[]> {
|
||||
const mux = getActiveMultiplexer(args.connectionId)
|
||||
if (!mux || mux.isDisposed()) {
|
||||
throw new Error(`No active SSH connection for "${args.connectionId}"`)
|
||||
// Why: remote agent detection is passive UI polling. A disconnected host has
|
||||
// no detectable agents until reconnect, but should not spam IPC errors.
|
||||
return []
|
||||
}
|
||||
const result = (await mux.request('preflight.detectAgents', {
|
||||
commands: KNOWN_AGENT_COMMANDS
|
||||
|
||||
@@ -2831,6 +2831,43 @@ describe('registerPtyHandlers', () => {
|
||||
expect(store.markSshRemotePtyLease).toHaveBeenCalledWith('ssh-1', 'remote-pty', 'terminated')
|
||||
})
|
||||
|
||||
it('returns idle process inspection results for detached SSH PTYs without a provider', async () => {
|
||||
const provider = {
|
||||
spawn: vi.fn(),
|
||||
write: vi.fn(),
|
||||
resize: vi.fn(),
|
||||
shutdown: vi.fn(),
|
||||
sendSignal: vi.fn(),
|
||||
getCwd: vi.fn(),
|
||||
getInitialCwd: vi.fn(),
|
||||
clearBuffer: vi.fn(),
|
||||
acknowledgeDataEvent: vi.fn(),
|
||||
onData: vi.fn(() => () => {}),
|
||||
onReplay: vi.fn(() => () => {}),
|
||||
onExit: vi.fn(() => () => {}),
|
||||
listProcesses: vi.fn(),
|
||||
hasChildProcesses: vi.fn(),
|
||||
getForegroundProcess: vi.fn(),
|
||||
serialize: vi.fn(),
|
||||
revive: vi.fn(),
|
||||
getDefaultShell: vi.fn(),
|
||||
getProfiles: vi.fn()
|
||||
}
|
||||
registerSshPtyProvider('ssh-1', provider as never)
|
||||
registerPtyHandlers(mainWindow as never)
|
||||
setPtyOwnership('remote-pty', 'ssh-1')
|
||||
unregisterSshPtyProvider('ssh-1')
|
||||
|
||||
await expect(handlers.get('pty:hasChildProcesses')!(null, { id: 'remote-pty' })).resolves.toBe(
|
||||
false
|
||||
)
|
||||
await expect(
|
||||
handlers.get('pty:getForegroundProcess')!(null, { id: 'remote-pty' })
|
||||
).resolves.toBeNull()
|
||||
expect(provider.hasChildProcesses).not.toHaveBeenCalled()
|
||||
expect(provider.getForegroundProcess).not.toHaveBeenCalled()
|
||||
})
|
||||
|
||||
it('injects ORCA_TERMINAL_HANDLE for non-local PTY providers', async () => {
|
||||
const spawn = vi.fn(async () => ({ id: 'remote-pty' }))
|
||||
registerSshPtyProvider('ssh-1', {
|
||||
|
||||
@@ -226,6 +226,13 @@ function getProviderForPty(ptyId: string): IPtyProvider {
|
||||
return getProvider(connectionId)
|
||||
}
|
||||
|
||||
function hasPtyProviderForInspection(ptyId: string): boolean {
|
||||
// Why: process inspection is background polling; disconnected SSH hosts should
|
||||
// read as idle instead of surfacing repeated IPC errors.
|
||||
const connectionId = ptyOwnership.get(ptyId)
|
||||
return connectionId == null || sshProviders.has(connectionId)
|
||||
}
|
||||
|
||||
function getAppPtyId(connectionId: string | null | undefined, ptyId: string): string {
|
||||
return connectionId ? toAppSshPtyId(connectionId, ptyId) : ptyId
|
||||
}
|
||||
@@ -2801,6 +2808,9 @@ export function registerPtyHandlers(
|
||||
ipcMain.handle(
|
||||
'pty:hasChildProcesses',
|
||||
async (_event, args: { id: string }): Promise<boolean> => {
|
||||
if (!hasPtyProviderForInspection(args.id)) {
|
||||
return false
|
||||
}
|
||||
return getProviderForPty(args.id).hasChildProcesses(args.id)
|
||||
}
|
||||
)
|
||||
@@ -2808,6 +2818,9 @@ export function registerPtyHandlers(
|
||||
ipcMain.handle(
|
||||
'pty:getForegroundProcess',
|
||||
async (_event, args: { id: string }): Promise<string | null> => {
|
||||
if (!hasPtyProviderForInspection(args.id)) {
|
||||
return null
|
||||
}
|
||||
return getProviderForPty(args.id).getForegroundProcess(args.id)
|
||||
}
|
||||
)
|
||||
|
||||
Reference in New Issue
Block a user