mirror of
https://github.com/stablyai/orca.git
synced 2026-10-24 08:03:58 +00:00
A wedged Tailscale tunnel (known iOS failure mode) produces no AppState or network-type transition, so no revival nudge ever fires and the reconnect loop parked permanently at its give-up cap — users had to toggle Tailscale off/on just to force a transition (#7824). - rpc-client: past the give-up cap, drop to a 90s trickle dial instead of parking so the session self-heals once the tunnel recovers. - host screen: nudge the shared client on focus so opening the host retries immediately instead of waiting out a backoff/trickle timer. - connection-health: warning/unreachable verdicts on 100.64/10 or *.ts.net endpoints now carry a 'check Tailscale' hint, shown on the home host list and the in-session status line after ~3 failed attempts. - troubleshoot: 'Cannot reach <tailnet-ip>' now says to check Tailscale, adds a dedicated Tailscale section, and stops telling Tailscale users to disable their VPN (that advice killed their only route to the host); sections extracted to troubleshoot-common-issues.tsx to stay under the max-lines cap. Co-authored-by: Orca <help@stably.ai>
47 lines
1.4 KiB
TypeScript
47 lines
1.4 KiB
TypeScript
import { describe, expect, it, vi } from 'vitest'
|
|
import { testHostReachability, unreachableHostDetail } from './host-reachability'
|
|
|
|
describe('unreachableHostDetail', () => {
|
|
it('points at Tailscale for tailnet CGNAT endpoints', () => {
|
|
expect(unreachableHostDetail('ws://100.65.9.106:6768')).toBe(
|
|
'Cannot reach 100.65.9.106:6768 — check Tailscale'
|
|
)
|
|
})
|
|
|
|
it('points at Tailscale for MagicDNS endpoints', () => {
|
|
expect(unreachableHostDetail('ws://my-desktop.tailnet-1234.ts.net:6768')).toBe(
|
|
'Cannot reach my-desktop.tailnet-1234.ts.net:6768 — check Tailscale'
|
|
)
|
|
})
|
|
|
|
it('stays generic for LAN endpoints', () => {
|
|
expect(unreachableHostDetail('ws://192.168.1.50:6768')).toBe('Cannot reach 192.168.1.50:6768')
|
|
})
|
|
|
|
it('does not treat non-CGNAT 100.x addresses as Tailscale', () => {
|
|
expect(unreachableHostDetail('ws://100.20.1.5:6768')).toBe('Cannot reach 100.20.1.5:6768')
|
|
})
|
|
})
|
|
|
|
describe('testHostReachability', () => {
|
|
it('returns false without leaving timers when WebSocket rejects a malformed endpoint', async () => {
|
|
vi.useFakeTimers()
|
|
vi.stubGlobal(
|
|
'WebSocket',
|
|
class {
|
|
constructor() {
|
|
throw new TypeError('Invalid URL')
|
|
}
|
|
}
|
|
)
|
|
|
|
try {
|
|
await expect(testHostReachability('not-a-url')).resolves.toBe(false)
|
|
expect(vi.getTimerCount()).toBe(0)
|
|
} finally {
|
|
vi.unstubAllGlobals()
|
|
vi.useRealTimers()
|
|
}
|
|
})
|
|
})
|