mirror of
https://github.com/stablyai/orca.git
synced 2026-11-06 03:57:35 +00:00
* fix(agent-status): stop a stale self-authored agent title from faking a pending question A workspace card could show the amber "agent is asking you something" icon while every pane sat idle and its only agent row read `done`. Orca injects its own `<Agent> - action required` OSC title when a hook reports blocked/waiting, then classifies that same title back as evidence. Two gaps let that one-shot string outlive the state it described: - The pane-id sets that suppress the title heuristic were built only from FRESH rows, so once a row aged past AGENT_STATUS_STALE_AFTER_MS the pane stopped suppressing its own title and `permission` — which outranks `done` — decided the indicator. Pane identity is not a liveness fact, so it is now tracked separately and never expires. Stale rows suppress `permission` only; a working spinner re-renders, so its stale-row fallback is preserved. - The hook-driven tab-title write compared the resolved title against the pane's layout slot (`titlesByLeafId`, which only a mounted pane updates) while writing `tab.title`. Once those slots diverged, `done` resolved to a title equal to the pane slot, the no-op guard skipped the write, and the tab kept the stale label. The guard now compares against the slot it actually overwrites. All three status surfaces read the same suppression inputs, so all three showed it: the workspace card, the terminal tab glyph, and the cmd-J palette dot. Tests: each fix has a regression test that fails without it (the sidebar, tab-bar and palette tests all go red from a single ablation of the stale-set lookup). * fix(agent-status): preserve native permissions and cover palette fallbacks --------- Co-authored-by: Merge Sim <sim@local>
63 lines
2.8 KiB
TypeScript
63 lines
2.8 KiB
TypeScript
import { describe, expect, it } from 'vitest'
|
|
import {
|
|
getSyntheticAgentTerminalTitle,
|
|
isSyntheticAgentPermissionTitle,
|
|
shouldDriveSyntheticAgentTitleFromHook
|
|
} from './synthetic-agent-title'
|
|
|
|
describe('synthetic agent titles', () => {
|
|
it.each(['Codex - action required', ' Pi - action required ', 'OMP - action required'])(
|
|
'recognizes the generated permission label %s',
|
|
(title) => {
|
|
expect(isSyntheticAgentPermissionTitle(title)).toBe(true)
|
|
}
|
|
)
|
|
|
|
it.each([
|
|
'✋ Gemini CLI',
|
|
'π ! approve command',
|
|
'OpenCode - action required',
|
|
'Codex ready',
|
|
'Codex - action required for deployment'
|
|
])('keeps native and contextual titles outside generated permission suppression: %s', (title) => {
|
|
expect(isSyntheticAgentPermissionTitle(title)).toBe(false)
|
|
})
|
|
|
|
it('provides terminal-state titles for Codex hook completion', () => {
|
|
expect(getSyntheticAgentTerminalTitle('codex', 'done')).toBe('Codex ready')
|
|
expect(getSyntheticAgentTerminalTitle('codex', 'waiting')).toBe('Codex - action required')
|
|
})
|
|
|
|
it('does not synthesize Codex working titles over Codex native spinner titles', () => {
|
|
expect(shouldDriveSyntheticAgentTitleFromHook('codex', 'working')).toBe(false)
|
|
expect(shouldDriveSyntheticAgentTitleFromHook('codex', 'done')).toBe(true)
|
|
})
|
|
|
|
it('does not synthesize OpenCode titles over native session titles', () => {
|
|
expect(getSyntheticAgentTerminalTitle('opencode', 'done')).toBeNull()
|
|
expect(getSyntheticAgentTerminalTitle('opencode', 'waiting')).toBeNull()
|
|
expect(shouldDriveSyntheticAgentTitleFromHook('opencode', 'working')).toBe(false)
|
|
expect(shouldDriveSyntheticAgentTitleFromHook('opencode', 'done')).toBe(false)
|
|
expect(shouldDriveSyntheticAgentTitleFromHook('opencode', 'waiting')).toBe(false)
|
|
})
|
|
|
|
it('provides Devin titles for hook-driven status updates', () => {
|
|
expect(getSyntheticAgentTerminalTitle('devin', 'done')).toBe('Devin ready')
|
|
expect(getSyntheticAgentTerminalTitle('devin', 'waiting')).toBe('Devin - action required')
|
|
expect(shouldDriveSyntheticAgentTitleFromHook('devin', 'working')).toBe(true)
|
|
})
|
|
|
|
it('provides Pi-compatible OMP titles for hook-driven status updates', () => {
|
|
expect(getSyntheticAgentTerminalTitle('omp', 'done')).toBe('OMP ready')
|
|
expect(getSyntheticAgentTerminalTitle('omp', 'waiting')).toBe('OMP - action required')
|
|
// Why: the native π working title carries session name/cwd; synthesizing would clobber it.
|
|
expect(shouldDriveSyntheticAgentTitleFromHook('omp', 'working')).toBe(false)
|
|
})
|
|
|
|
it('provides Pi titles for hook-driven status updates', () => {
|
|
expect(getSyntheticAgentTerminalTitle('pi', 'done')).toBe('Pi ready')
|
|
expect(getSyntheticAgentTerminalTitle('pi', 'waiting')).toBe('Pi - action required')
|
|
expect(shouldDriveSyntheticAgentTitleFromHook('pi', 'working')).toBe(false)
|
|
})
|
|
})
|