(msg: NavigableMessage)
| 16 | |
| 17 | // Tier-2 blocklist (tier-1 is height > 0) — things that render but aren't actionable. |
| 18 | export function isNavigableMessage(msg: NavigableMessage): boolean { |
| 19 | switch (msg.type) { |
| 20 | case 'assistant': |
| 21 | { |
| 22 | const b = msg.message.content[0]; |
| 23 | // Text responses (minus AssistantTextMessage's return-null cases — tier-1 |
| 24 | // misses unmeasured virtual items), or tool calls with extractable input. |
| 25 | return b?.type === 'text' && !isEmptyMessageText(b.text) && !SYNTHETIC_MESSAGES.has(b.text) || b?.type === 'tool_use' && b.name in PRIMARY_INPUT; |
| 26 | } |
| 27 | case 'user': |
| 28 | { |
| 29 | if (msg.isMeta || msg.isCompactSummary) return false; |
| 30 | const b = msg.message.content[0]; |
| 31 | if (b?.type !== 'text') return false; |
| 32 | // Interrupt etc. — synthetic, not user-authored. |
| 33 | if (SYNTHETIC_MESSAGES.has(b.text)) return false; |
| 34 | // Same filter as VirtualMessageList sticky-prompt: XML-wrapped (command |
| 35 | // expansions, bash-stdout, etc.) aren't real prompts. |
| 36 | return !stripSystemReminders(b.text).startsWith('<'); |
| 37 | } |
| 38 | case 'system': |
| 39 | // biome-ignore lint/nursery/useExhaustiveSwitchCases: blocklist — fallthrough return-true is the design |
| 40 | switch (msg.subtype) { |
| 41 | case 'api_metrics': |
| 42 | case 'stop_hook_summary': |
| 43 | case 'turn_duration': |
| 44 | case 'memory_saved': |
| 45 | case 'agents_killed': |
| 46 | case 'away_summary': |
| 47 | case 'thinking': |
| 48 | return false; |
| 49 | } |
| 50 | return true; |
| 51 | case 'grouped_tool_use': |
| 52 | case 'collapsed_read_search': |
| 53 | return true; |
| 54 | case 'attachment': |
| 55 | switch (msg.attachment.type) { |
| 56 | case 'queued_command': |
| 57 | case 'diagnostics': |
| 58 | case 'hook_blocking_error': |
| 59 | case 'hook_error_during_execution': |
| 60 | return true; |
| 61 | } |
| 62 | return false; |
| 63 | } |
| 64 | } |
| 65 | type PrimaryInput = { |
| 66 | label: string; |
| 67 | extract: (input: Record<string, unknown>) => string | undefined; |
no test coverage detected