mirror of
https://github.com/stablyai/orca.git
synced 2026-10-25 16:03:53 +00:00
fix(ssh): keep a reattached PTY live when its delivery cancellation is unproven
On the restoreRequired retry path the first attach already answered with an incarnation, so the remote PTY is proven alive and only its delivery record was retired. Filing that as ambiguous exit evidence recorded a live agent as possibly dead. Report it as restore-required and accept the PTY as live. Both errors already map to deliveryUnresumable in the renderer and to a 'detached' lease, so the pane behaves exactly as before.
This commit is contained in:
@@ -303,7 +303,7 @@ describe('SSH PTY reattach when the relay requires source restoration', () => {
|
||||
expect(mux.request.mock.calls.filter((call) => call[0] === 'pty.attach')).toHaveLength(2)
|
||||
})
|
||||
|
||||
it('does not install a second activation when the first cancellation is unverifiable', async () => {
|
||||
it('keeps the PTY live when the first activation cancellation is unproven', async () => {
|
||||
const mux = createMockMux()
|
||||
const activation = {
|
||||
status: 'pending',
|
||||
@@ -339,10 +339,12 @@ describe('SSH PTY reattach when the relay requires source restoration', () => {
|
||||
|
||||
const message = await spawnError(provider)
|
||||
|
||||
expect(message).toContain(SSH_PTY_LIVENESS_UNVERIFIABLE_ERROR)
|
||||
// The attach answered with an incarnation, so the PTY is proven live; only the retry is blocked.
|
||||
expect(message).toContain(SSH_PTY_RESTORE_REQUIRED_ERROR)
|
||||
expect(message).not.toContain(SSH_PTY_LIVENESS_UNVERIFIABLE_ERROR)
|
||||
expect(message).not.toContain(SSH_SESSION_EXPIRED_ERROR)
|
||||
expect(provider.hasPty('ssh:conn-1@@pty-old')).toBe(false)
|
||||
await expect(provider.probePtyLiveness('ssh:conn-1@@pty-old')).resolves.toBeNull()
|
||||
expect(provider.hasPty('ssh:conn-1@@pty-old')).toBe(true)
|
||||
await expect(provider.probePtyLiveness('ssh:conn-1@@pty-old')).resolves.toBe(true)
|
||||
expect(mux.request.mock.calls.filter((call) => call[0] === 'pty.attach')).toHaveLength(1)
|
||||
expect(mux.request.mock.calls.filter((call) => call[0] === 'pty.spawn')).toHaveLength(0)
|
||||
expect(mux.request).toHaveBeenCalledWith('pty.cancelDelivery', {
|
||||
|
||||
@@ -246,8 +246,11 @@ export async function reattachSshPtySessionForSpawn(
|
||||
if (unresumable.sourceActivationLease) {
|
||||
const canceled = await unresumable.sourceActivationLease.rollback()
|
||||
if (!canceled) {
|
||||
// Why: the attach answered with an incarnation, so the PTY is live; only its delivery
|
||||
// is stuck, and an unproven cancellation just blocks the second attach.
|
||||
args.acceptLivePty(unresumable.id)
|
||||
throw new Error(
|
||||
`${SSH_PTY_LIVENESS_UNVERIFIABLE_ERROR}: ${toRelaySshPtyId(args.connectionId, unresumable.id)}`
|
||||
`${SSH_PTY_RESTORE_REQUIRED_ERROR}: ${toRelaySshPtyId(args.connectionId, unresumable.id)}`
|
||||
)
|
||||
}
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user