Files
orca/src/shared/agent-session-command-menu-query.ts
T
Brennan Benson e08cb10cc6 Prevent resting chats from delaying native command menus (#35069)
* Scope native chat command discovery to menu demand

* Fix command discovery CI imports and test timing

* fix: recover demanded command menus after context retirement

* test: load command host fixture before mocked consumers

* test: retain eager cache reads across command expiry

* test: cover command recovery after pending deadline

* test: count demanded command renders and query isolation

* test: load mobile command host fixture during collection

* test: type command batch fields from subscribe events

* test: check command event arrays without assertion

* Fix command discovery fixture project boundaries

* Name command fixture mocks with public Vitest types

* Assert opening metadata on resumed session snapshots

* test: assert passive command population boundaries

* test: cover mobile command capability handoff

* test: correct capability proof scope adapters
2026-10-29 13:16:35 -07:00

70 lines
1.6 KiB
TypeScript

import type { AgentSessionCommandsResult } from './agent-session-wire'
/** Own recovery only while this target's menu is demanded. */
export function startAgentSessionCommandMenuQuery(
read: () => Promise<AgentSessionCommandsResult>,
accept: (result: AgentSessionCommandsResult) => void
): { invalidate(): void; dispose(): void } {
let stopped = false
let running = false
let dirty = false
let failures = 0
let deadline = Date.now() + 330_000
let timer: ReturnType<typeof setTimeout> | undefined
const schedule = (delay: number): void => {
clearTimeout(timer)
if (!stopped && Date.now() + delay < deadline) {
timer = setTimeout(() => void run(), delay)
}
}
const run = async (): Promise<void> => {
if (stopped || Date.now() >= deadline) {
return
}
running = true
dirty = false
let delay: number | undefined
try {
const result = await read()
if (stopped || Date.now() >= deadline) {
return
}
accept(result)
failures = 0
if (result.commandsPending) {
delay = 10_000
}
} catch {
if (++failures < 3) {
delay = 10_000
}
} finally {
running = false
if (dirty) {
schedule(0)
} else if (delay !== undefined) {
schedule(delay)
}
}
}
void run()
return {
invalidate() {
if (stopped) {
return
}
failures = 0
deadline = Date.now() + 330_000
dirty = true
if (!running) {
schedule(0)
}
},
dispose() {
stopped = true
dirty = false
clearTimeout(timer)
}
}
}