mirror of
https://github.com/wu736139669/hapi.git
synced 2026-10-29 23:11:42 +00:00
* fix(hub): govern runner capabilities so Cursor reopen soft-fails on skew Hub↔runner protocol drift was reported as missing Cursor chat data when cursor-chat-store-status was unregistered. Soft-fail reopen on probe errors, advertise required machine capabilities, surface an unmissable upgrade banner, and stop-runner when a newer CLI binary is already on disk. Fixes #1084 Co-authored-by: Cursor <cursoragent@cursor.com> * fix(web,hub): make runner skew banner dismissible; gate auto-upgrade Compact the out-of-date banner (minimize + 1h snooze + per-host Restart) so it no longer blocks the session list. Auto stop-runner on skew stays opt-in via HAPI_AUTO_UPGRADE_RUNNERS / autoUpgradeRunners (default off). Co-authored-by: Cursor <cursoragent@cursor.com> * fix(web): tolerate full sessionStorage on skew banner minimize QuotaExceededError from setItem aborted minimize before React state updated, leaving the banner stuck over the session list. Persist to memory when storage fails; only enable Restart when a newer CLI is already on disk; clarify opt-in is stop-runner only, not package push. Co-authored-by: Cursor <cursoragent@cursor.com> * fix(hub): drop redundant autoUpgradeRunners; runners already self-restart CLI version handoff already reloads the runner when the on-disk binary mtime changes. Hub-driven stop-runner on skew duplicated that. Keep the skew banner and manual Restart only as a stuck/disabled-handoff escape. Co-authored-by: Cursor <cursoragent@cursor.com> * fix(cli,hub,web): runner-only caps ads; gate Restart on supervisor Address #1108 bot Majors on the thin tip: terminal/lazy bootstraps no longer merge CURRENT_MACHINE_CAPABILITIES into the machine row (only asRunner registration does). Banner Restart refuses unsupervised hosts so stop-runner cannot leave a detached laptop offline; supervised runners advertise supervisedRestart via HAPI_RUNNER_SUPERVISED=1. Co-authored-by: Cursor <cursoragent@cursor.com> * fix(hub,cli,web): clear sticky runner ads; docs SUPERVISED; i18n skew label Omit-means-clear on runner registration so rollback cannot leave supervisedRestart/capabilities sticky; always advertise boolean supervisedRestart from asRunner. Document HAPI_RUNNER_SUPERVISED=1 and localize MachineSelector UPDATE REQUIRED. Co-authored-by: Cursor <cursoragent@cursor.com> --------- Co-authored-by: Debian <heavygee@oos-linux.in.lockhouse> Co-authored-by: Cursor <cursoragent@cursor.com>
49 lines
1.8 KiB
TypeScript
49 lines
1.8 KiB
TypeScript
import { describe, expect, it } from 'vitest'
|
|
import {
|
|
CURRENT_MACHINE_CAPABILITIES,
|
|
MACHINE_CAPABILITIES,
|
|
REQUIRED_MACHINE_CAPABILITIES,
|
|
cliBinaryUpdatedOnDisk,
|
|
isMachineCapabilitySkewed,
|
|
missingRequiredCapabilities,
|
|
} from './runnerCapabilities'
|
|
|
|
describe('runnerCapabilities', () => {
|
|
it('requires cursor-chat-store-status so hub features cannot fail-closed without a registry entry', () => {
|
|
expect(REQUIRED_MACHINE_CAPABILITIES).toContain(MACHINE_CAPABILITIES.CursorChatStoreStatus)
|
|
expect(CURRENT_MACHINE_CAPABILITIES).toEqual(expect.arrayContaining([
|
|
...REQUIRED_MACHINE_CAPABILITIES,
|
|
]))
|
|
})
|
|
|
|
it('treats missing/empty advertised capabilities as skewed', () => {
|
|
expect(isMachineCapabilitySkewed(undefined)).toBe(true)
|
|
expect(isMachineCapabilitySkewed(null)).toBe(true)
|
|
expect(isMachineCapabilitySkewed([])).toBe(true)
|
|
expect(missingRequiredCapabilities([])).toEqual([
|
|
MACHINE_CAPABILITIES.CursorChatStoreStatus,
|
|
])
|
|
})
|
|
|
|
it('is not skewed when required capabilities are advertised', () => {
|
|
expect(isMachineCapabilitySkewed([...CURRENT_MACHINE_CAPABILITIES])).toBe(false)
|
|
expect(missingRequiredCapabilities([
|
|
MACHINE_CAPABILITIES.CursorChatStoreStatus,
|
|
'other-cap',
|
|
])).toEqual([])
|
|
})
|
|
|
|
it('detects on-disk CLI binary updates via mtime drift', () => {
|
|
expect(cliBinaryUpdatedOnDisk({
|
|
startedCliMtimeMs: 100,
|
|
installedCliMtimeMs: 200,
|
|
})).toBe(true)
|
|
expect(cliBinaryUpdatedOnDisk({
|
|
startedCliMtimeMs: 100,
|
|
installedCliMtimeMs: 100,
|
|
})).toBe(false)
|
|
expect(cliBinaryUpdatedOnDisk({})).toBe(false)
|
|
expect(cliBinaryUpdatedOnDisk(null)).toBe(false)
|
|
})
|
|
})
|