mirror of
https://github.com/wu736139669/hapi.git
synced 2026-11-08 01:43:07 +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>
52 lines
1.8 KiB
TypeScript
52 lines
1.8 KiB
TypeScript
import { afterEach, beforeEach, describe, expect, it, vi } from 'vitest'
|
|
import {
|
|
clearRunnerSkewTempDismiss,
|
|
isRunnerSkewMinimized,
|
|
isRunnerSkewTempDismissed,
|
|
resetRunnerSkewBannerMemoryForTests,
|
|
setRunnerSkewMinimized,
|
|
tempDismissRunnerSkew,
|
|
} from './runnerSkewBannerState'
|
|
|
|
describe('runnerSkewBannerState', () => {
|
|
beforeEach(() => {
|
|
window.sessionStorage.clear()
|
|
resetRunnerSkewBannerMemoryForTests()
|
|
})
|
|
|
|
afterEach(() => {
|
|
vi.restoreAllMocks()
|
|
window.sessionStorage.clear()
|
|
resetRunnerSkewBannerMemoryForTests()
|
|
})
|
|
|
|
it('persists minimize to sessionStorage', () => {
|
|
setRunnerSkewMinimized(true)
|
|
expect(isRunnerSkewMinimized()).toBe(true)
|
|
expect(window.sessionStorage.getItem('hapi.runnerSkew.minimized.v1')).toBe('1')
|
|
})
|
|
|
|
it('still minimizes when sessionStorage setItem throws QuotaExceededError', () => {
|
|
const proto = Object.getPrototypeOf(window.sessionStorage) as Storage
|
|
vi.spyOn(proto, 'setItem').mockImplementation(() => {
|
|
throw new DOMException('quota', 'QuotaExceededError')
|
|
})
|
|
|
|
expect(() => setRunnerSkewMinimized(true)).not.toThrow()
|
|
expect(isRunnerSkewMinimized()).toBe(true)
|
|
})
|
|
|
|
it('still temp-dismisses when sessionStorage is full', () => {
|
|
const proto = Object.getPrototypeOf(window.sessionStorage) as Storage
|
|
vi.spyOn(proto, 'setItem').mockImplementation(() => {
|
|
throw new DOMException('quota', 'QuotaExceededError')
|
|
})
|
|
|
|
const now = 1_700_000_000_000
|
|
expect(() => tempDismissRunnerSkew(now)).not.toThrow()
|
|
expect(isRunnerSkewTempDismissed(now + 1)).toBe(true)
|
|
clearRunnerSkewTempDismiss()
|
|
expect(isRunnerSkewTempDismissed(now + 1)).toBe(false)
|
|
})
|
|
})
|