({ nonInteractive }: UseMessageHandlersOptions)
| 29 | * Transforms ClineMessage format to TUIMessage format and updates the store. |
| 30 | */ |
| 31 | export function useMessageHandlers({ nonInteractive }: UseMessageHandlersOptions): UseMessageHandlersReturn { |
| 32 | const { |
| 33 | addMessage, |
| 34 | setPendingAsk, |
| 35 | setComplete, |
| 36 | setLoading, |
| 37 | setHasStartedTask, |
| 38 | setFileSearchResults, |
| 39 | setAllSlashCommands, |
| 40 | setAvailableModes, |
| 41 | setCurrentMode, |
| 42 | setTokenUsage, |
| 43 | setRouterModels, |
| 44 | setTaskHistory, |
| 45 | currentTodos, |
| 46 | setTodos, |
| 47 | } = useCLIStore() |
| 48 | |
| 49 | // Track seen message timestamps to filter duplicates and the prompt echo |
| 50 | const seenMessageIds = useRef<Set<string>>(new Set()) |
| 51 | const firstTextMessageSkipped = useRef(false) |
| 52 | |
| 53 | // Track pending command for injecting into command_output toolData |
| 54 | const pendingCommandRef = useRef<string | null>(null) |
| 55 | |
| 56 | /** |
| 57 | * Map extension "say" messages to TUI messages |
| 58 | */ |
| 59 | const handleSayMessage = useCallback( |
| 60 | (ts: number, say: ClineSay, text: string, partial: boolean) => { |
| 61 | const messageId = ts.toString() |
| 62 | const isResuming = useCLIStore.getState().isResumingTask |
| 63 | |
| 64 | if (say === "checkpoint_saved") { |
| 65 | return |
| 66 | } |
| 67 | |
| 68 | if (say === "api_req_started") { |
| 69 | return |
| 70 | } |
| 71 | |
| 72 | if (say === "user_feedback") { |
| 73 | seenMessageIds.current.add(messageId) |
| 74 | return |
| 75 | } |
| 76 | |
| 77 | // Skip first text message ONLY for new tasks, not resumed tasks |
| 78 | // When resuming, we want to show all historical messages including the first one |
| 79 | if (say === "text" && !firstTextMessageSkipped.current && !isResuming) { |
| 80 | firstTextMessageSkipped.current = true |
| 81 | seenMessageIds.current.add(messageId) |
| 82 | return |
| 83 | } |
| 84 | |
| 85 | if (seenMessageIds.current.has(messageId) && !partial) { |
| 86 | return |
| 87 | } |
| 88 |
no test coverage detected