Files
orca/src/shared/agent-completion-time.ts
T
JinjingandOrca 4c2a10d157 Fix smart sort ranking of done agents by completion time (#13899)
* Fix smart sort ranking of done agents by completion time

Completed entries stayed in the Done sort class indefinitely when
same-state writes refreshed updatedAt without moving stateStartedAt.
Introduce agentEntryCompletionAt() to use actual completion time for
both age display and sort eligibility, ensuring consistent aging
regardless of hook updates.

* Fix smart sort ranking of done agents by completion time

Co-authored-by: Orca <help@stably.ai>

---------

Co-authored-by: Orca <help@stably.ai>
2026-08-11 18:11:34 -07:00

44 lines
1.5 KiB
TypeScript

import type { AgentStateHistoryEntry, AgentStatusEntry } from './agent-status-types'
/** The subset of a hook entry a completion time is derived from. */
export type AgentCompletionSource = Pick<
AgentStatusEntry,
'state' | 'stateStartedAt' | 'stateHistory' | 'interrupted' | 'sessionBoundary'
>
function mostRecentCompletedTurnInHistory(
history: readonly AgentStateHistoryEntry[] | undefined
): number | null {
let max = 0
for (const row of history ?? []) {
if (
row.state === 'done' &&
row.interrupted !== true &&
Number.isFinite(row.startedAt) &&
row.startedAt > max
) {
max = row.startedAt
}
}
return max > 0 ? max : null
}
/**
* When the entry's agent last actually COMPLETED a turn, or null when nothing qualifies.
* One clock for both the displayed completion age and Smart Sort's Done eligibility, so a row
* can't rank as freshly done while showing an age past the staleness threshold.
*
* A completion is only:
* - a non-interrupted `done` (its `stateStartedAt` — unmoved by same-state tool/prompt pings); or
* - for a session-boundary `done` (connected idle, not a turn), the real completion it displaced.
*/
export function agentEntryCompletionAt(entry: AgentCompletionSource): number | null {
if (entry.state !== 'done' || entry.interrupted === true) {
return null
}
if (entry.sessionBoundary === true) {
return mostRecentCompletedTurnInHistory(entry.stateHistory)
}
return Number.isFinite(entry.stateStartedAt) ? entry.stateStartedAt : null
}