import { AGY_AGENT_NAME_RE, DROID_AGENT_NAME_RE, HERMES_AGENT_NAME_RE, titleHasAgentName, titleHasAnyLegacyAgentName } from './agent-name-token-match' export { AGY_AGENT_NAME_RE, DROID_AGENT_NAME_RE, HERMES_AGENT_NAME_RE, titleHasAgentName } export type AgentStatus = 'working' | 'permission' | 'idle' export const CLAUDE_IDLE = '\u2733' // ✳ const CLAUDE_COMMAND_RE = String.raw`(?:.*[\\/])?claude(?:\.(?:exe|cmd|bat|ps1))?` export const CLAUDE_MANAGEMENT_TITLE_RE = new RegExp( String.raw`^\s*(?:"${CLAUDE_COMMAND_RE}"|'${CLAUDE_COMMAND_RE}'|${CLAUDE_COMMAND_RE})\s+agents\s*$`, 'i' ) export const GEMINI_WORKING = '\u2726' // ✦ export const GEMINI_SILENT_WORKING = '\u23f2' // ⏲ export const GEMINI_IDLE = '\u25c7' // ◇ export const GEMINI_PERMISSION = '\u270b' // ✋ const STRONG_IDLE_KEYWORDS = ['ready', 'idle', 'done'] as const const STRONG_WORKING_KEYWORDS = ['working', 'thinking', 'running'] as const // Why: plain `\b` matches inside hyphenated tokens and cwd paths such as // "~/codex/ready"; the left side also blocks path separators for Windows/Unix. export const STRONG_IDLE_KEYWORDS_RE = new RegExp( `(?= 0x2800 && codePoint <= 0x28ff) { return true } } return false } export function containsLegacyAgentName(title: string): boolean { return titleHasAnyLegacyAgentName(title) } export function containsAgentName(title: string): boolean { return ( containsLegacyAgentName(title) || AGY_AGENT_NAME_RE.test(title) || DROID_AGENT_NAME_RE.test(title) || HERMES_AGENT_NAME_RE.test(title) ) } export function containsAny(title: string, words: readonly string[]): boolean { const lower = title.toLowerCase() return words.some((word) => lower.includes(word)) } export function isClaudeManagementTitle(title: string): boolean { return CLAUDE_MANAGEMENT_TITLE_RE.test(title) } export function isCursorNativeAgentTitle(title: string): boolean { return title.trim().toLowerCase() === CURSOR_NATIVE_TITLE_LOWER }