Files
orca/src/shared/agent-interrupt-intent.ts
T
Kelvin Amoaba cc3b3fb9a5 fix(agent-status): leave Grok cancels to Grok's own StopCancelled hook (#35417)
Esc never cancels a Grok turn and Ctrl+C can open a stop dialog the user
can decline, so keypress inference marked live Grok turns finished.
2026-10-28 23:22:23 +00:00

71 lines
2.1 KiB
TypeScript

import type { AgentType } from './agent-status-types'
export type AgentInterruptInputIntent = 'plain-escape' | 'ctrl-c'
export const AGENT_INTERRUPT_SETTLE_MS = 500
export type AgentInterruptInferenceRequest = {
paneKey: string
baselineUpdatedAt: number
baselineStateStartedAt: number
baselinePrompt: string
baselineAgentType: AgentType | undefined
intent: AgentInterruptInputIntent
inputCount?: number
}
export function isAgentInterruptInputIntent(intent: unknown): intent is AgentInterruptInputIntent {
return intent === 'plain-escape' || intent === 'ctrl-c'
}
// Ctrl+C can copy text or leave a Codex side chat without cancelling the main turn.
// Grok's Escape only hints and its Ctrl+C can open a stop dialog; its StopCancelled hook is the verdict.
export function shouldIgnoreInterruptIntent(
agentType: AgentType | undefined,
intent: AgentInterruptInputIntent
): boolean {
return (
agentType === 'grok' ||
(intent === 'ctrl-c' && (agentType === 'codex' || agentType === 'droid'))
)
}
// Escape also closes views (including Codex search and /permissions); only provider evidence ends the turn.
const ESCAPE_ALSO_NAVIGATES_AGENT_TYPES: ReadonlySet<AgentType> = new Set([
'claude',
'codex',
'omp',
'pi',
'prime-agent'
])
export function isNavigationEscapeIntent(
agentType: AgentType | undefined,
intent: AgentInterruptInputIntent
): boolean {
return (
intent === 'plain-escape' &&
agentType !== undefined &&
ESCAPE_ALSO_NAVIGATES_AGENT_TYPES.has(agentType)
)
}
// First Escape may leave work running or close OpenCode2's dock; require a second same-turn Escape on both renderer and server.
const DOUBLE_ESCAPE_INTERRUPT_AGENT_TYPES: ReadonlySet<AgentType> = new Set([
'opencode',
'opencode2',
'copilot'
])
/** True when this agent only yields an interrupt on a second same-turn Escape. */
export function requiresDoubleEscapeInterrupt(
agentType: AgentType | undefined,
intent: AgentInterruptInputIntent
): boolean {
return (
intent === 'plain-escape' &&
agentType !== undefined &&
DOUBLE_ESCAPE_INTERRUPT_AGENT_TYPES.has(agentType)
)
}