Files
Netcatty/components/settings
bincxz 64c6dd5b91 fix(ssh): per-host keepalive override + cloud-friendly defaults (#939, #581)
Issues #939 (cloud / Aliyun sessions silently freezing after 15-20 min idle
because no SSH keepalive packets are sent) and #581 (older routers like
NOKIA / ALCATEL being killed by ssh2 after a few unanswered keepalives) are
in direct tension at the global-setting level: cloud users want keepalive
ON, embedded-device users want it OFF, and any single global default hurts
the other group.

Resolves the conflict by moving keepalive to a per-host setting (mirroring
the existing `legacyAlgorithms` per-host pattern), with cloud-friendly
global defaults:

Domain:
  - Host gains `keepaliveOverride?: boolean` + `keepaliveInterval?: number`
    + `keepaliveCountMax?: number`. When override is true, the host's
    values are used; otherwise the global TerminalSettings values apply.
    Per-field fallback so a host can override interval only or countMax only.
  - TerminalSettings gains `keepaliveCountMax: number` so the second knob
    (number of unanswered keepalives before declaring dead) is no longer
    hardcoded at 3 in the bridge.
  - DEFAULT_TERMINAL_SETTINGS: keepaliveInterval bumped from 0 to 30, and
    keepaliveCountMax = 10. Cloud LBs / NAT tables stay populated; brief
    network glitches don't trip the dead-connection check; an actually
    dead session is detected within ~5 minutes. Existing users with 0
    saved keep their value (no migration) — they were the #581 router
    cohort and their setup still works untouched.

Plumbing:
  - domain/host.ts adds resolveHostKeepalive(host, globalSettings) with
    five unit tests covering both directions of the override flag and
    per-field fallback.
  - components/terminal/runtime/createTerminalSessionStarters.ts uses the
    resolver when building startSSHSession options.
  - electron/bridges/sshBridge.cjs reads keepaliveCountMax from options
    (defaulting to 10) at both connection sites (direct + jump host) and
    still routes interval=0 through to a fully disabled keepalive
    (preserving #581's escape hatch).

UI:
  - Settings → Terminal → Connection grows a second input next to the
    existing interval: "Max unanswered keepalives".
  - Host details panel gains a Keepalive section with a "Override global
    keepalive" toggle that, when on, exposes per-host interval +
    countMax inputs and an inline hint when interval = 0 (explaining
    the implications). Same visual pattern as the existing Legacy
    Algorithms section.

Sync:
  - keepaliveCountMax added to SYNCABLE_TERMINAL_KEYS so the new global
    field rides existing sync infrastructure. Per-host fields ride the
    hosts array passthrough automatically (older clients receiving them
    ignore unknown fields, per the existing lenient sync contract).

i18n: en + zh-CN strings for the new settings row, the host section
header, and the override toggle / inputs / disabled hint.

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
2026-05-11 15:25:29 +08:00
..