mirror of
https://github.com/stablyai/orca.git
synced 2026-10-22 00:03:47 +00:00
98 lines
3.5 KiB
TypeScript
98 lines
3.5 KiB
TypeScript
import { describe, expect, it } from 'vitest'
|
|
import type { RuntimeWorktreeAgentRow } from '../../../src/shared/runtime-types'
|
|
import {
|
|
AGENT_STATUS_STALE_AFTER_MS,
|
|
agentDisplayLabel,
|
|
agentDotState,
|
|
agentIdentityLabel,
|
|
formatTimeAgo
|
|
} from './agent-row-display'
|
|
|
|
function row(overrides: Partial<RuntimeWorktreeAgentRow> = {}): RuntimeWorktreeAgentRow {
|
|
return {
|
|
paneKey: 'p',
|
|
parentPaneKey: null,
|
|
state: 'working',
|
|
agentType: 'claude',
|
|
prompt: '',
|
|
lastAssistantMessage: null,
|
|
toolName: null,
|
|
toolInput: null,
|
|
interrupted: false,
|
|
stateStartedAt: 0,
|
|
updatedAt: 0,
|
|
...overrides
|
|
}
|
|
}
|
|
|
|
describe('agentDotState', () => {
|
|
it('maps known states through and unknown to idle', () => {
|
|
expect(agentDotState(row({ state: 'working', updatedAt: 0 }), 0)).toBe('working')
|
|
expect(agentDotState(row({ state: 'blocked', updatedAt: 0 }), 0)).toBe('blocked')
|
|
expect(agentDotState(row({ state: 'waiting', updatedAt: 0 }), 0)).toBe('waiting')
|
|
expect(agentDotState(row({ state: 'done', updatedAt: 0 }), 0)).toBe('done')
|
|
expect(agentDotState(row({ state: 'unknown-state' as never }), 0)).toBe('idle')
|
|
})
|
|
|
|
it('reports interrupted regardless of state', () => {
|
|
expect(agentDotState(row({ state: 'done', interrupted: true }), 0)).toBe('interrupted')
|
|
})
|
|
|
|
it('decays a stale active state to idle, matching desktop', () => {
|
|
const stale = AGENT_STATUS_STALE_AFTER_MS + 1
|
|
// Active states past the staleness window read as idle…
|
|
expect(agentDotState(row({ state: 'working', updatedAt: 0 }), stale)).toBe('idle')
|
|
expect(agentDotState(row({ state: 'blocked', updatedAt: 0 }), stale)).toBe('idle')
|
|
expect(agentDotState(row({ state: 'waiting', updatedAt: 0 }), stale)).toBe('idle')
|
|
// …exactly at the threshold it is still fresh (decay is strictly past it).
|
|
expect(
|
|
agentDotState(row({ state: 'working', updatedAt: 0 }), AGENT_STATUS_STALE_AFTER_MS)
|
|
).toBe('working')
|
|
// 'done' never decays; interrupted still wins.
|
|
expect(agentDotState(row({ state: 'done', updatedAt: 0 }), stale)).toBe('done')
|
|
expect(agentDotState(row({ state: 'working', updatedAt: 0, interrupted: true }), stale)).toBe(
|
|
'interrupted'
|
|
)
|
|
})
|
|
})
|
|
|
|
describe('agentDisplayLabel', () => {
|
|
it('prefers last message, then prompt, then state label', () => {
|
|
expect(agentDisplayLabel(row({ lastAssistantMessage: 'hello there' }), 0)).toBe('hello there')
|
|
expect(agentDisplayLabel(row({ lastAssistantMessage: ' ', prompt: 'do the thing' }), 0)).toBe(
|
|
'do the thing'
|
|
)
|
|
expect(agentDisplayLabel(row({ state: 'working', prompt: '', updatedAt: 0 }), 0)).toBe(
|
|
'Working'
|
|
)
|
|
})
|
|
|
|
it('falls back to the decayed state label when stale', () => {
|
|
expect(
|
|
agentDisplayLabel(
|
|
row({ state: 'working', prompt: '', updatedAt: 0 }),
|
|
AGENT_STATUS_STALE_AFTER_MS + 1
|
|
)
|
|
).toBe('Idle')
|
|
})
|
|
})
|
|
|
|
describe('agentIdentityLabel', () => {
|
|
it('maps known agent types and falls back to initials', () => {
|
|
expect(agentIdentityLabel('claude')).toBe('CL')
|
|
expect(agentIdentityLabel('codex')).toBe('CX')
|
|
expect(agentIdentityLabel('mystery')).toBe('MY')
|
|
expect(agentIdentityLabel(null)).toBe('')
|
|
})
|
|
})
|
|
|
|
describe('formatTimeAgo', () => {
|
|
const now = 10_000_000
|
|
it('formats across thresholds', () => {
|
|
expect(formatTimeAgo(now - 30_000, now)).toBe('just now')
|
|
expect(formatTimeAgo(now - 5 * 60_000, now)).toBe('5m')
|
|
expect(formatTimeAgo(now - 3 * 3_600_000, now)).toBe('3h')
|
|
expect(formatTimeAgo(now - 2 * 86_400_000, now)).toBe('2d')
|
|
})
|
|
})
|