(props: {
renderMessageOptions?: RenderAIMessageOptions;
children: React.ReactNode;
})
| 127 | * Provide the controller to interact with the AI chat. |
| 128 | */ |
| 129 | export function AIChatProvider(props: { |
| 130 | renderMessageOptions?: RenderAIMessageOptions; |
| 131 | children: React.ReactNode; |
| 132 | }) { |
| 133 | const { renderMessageOptions, children } = props; |
| 134 | |
| 135 | const messageContextRef = useAIMessageContextRef(); |
| 136 | const trackEvent = useTrackEvent(); |
| 137 | const [, setSearchState] = useSearch(); |
| 138 | const language = useLanguage(); |
| 139 | |
| 140 | // Open AI chat and sync with search state |
| 141 | const onOpen = React.useCallback(() => { |
| 142 | const { initialQuery } = globalState.getState(); |
| 143 | globalState.setState((state) => ({ ...state, opened: true })); |
| 144 | |
| 145 | // Update search state to show ask mode with first message or current ask value |
| 146 | setSearchState((prev) => ({ |
| 147 | ask: prev?.ask ?? initialQuery ?? '', |
| 148 | query: prev?.query ?? null, |
| 149 | scope: prev?.scope ?? 'default', |
| 150 | open: false, // Close search popover when opening chat |
| 151 | })); |
| 152 | }, [setSearchState]); |
| 153 | |
| 154 | // Close AI chat and clear ask parameter |
| 155 | const onClose = React.useCallback(() => { |
| 156 | globalState.setState((state) => ({ ...state, opened: false })); |
| 157 | |
| 158 | // Clear ask parameter but keep other search state |
| 159 | setSearchState((prev) => ({ |
| 160 | ask: null, |
| 161 | query: prev?.query ?? null, |
| 162 | scope: prev?.scope ?? 'default', |
| 163 | open: false, |
| 164 | })); |
| 165 | }, [setSearchState]); |
| 166 | |
| 167 | // Stream a message with the AI backend |
| 168 | const streamResponse = React.useCallback( |
| 169 | async (input: { |
| 170 | /** Text message to send to the AI backend */ |
| 171 | message?: string; |
| 172 | /** Tool call to send to the AI backend */ |
| 173 | toolCall?: AIToolCallResult; |
| 174 | }) => { |
| 175 | globalState.setState((state) => { |
| 176 | return { |
| 177 | ...state, |
| 178 | followUpSuggestions: [], |
| 179 | pendingTools: [], |
| 180 | loading: true, |
| 181 | error: false, |
| 182 | messages: [ |
| 183 | ...state.messages, |
| 184 | { |
| 185 | role: AIMessageRole.Assistant, |
| 186 | content: null, // Placeholder for streaming response |
nothing calls this directly
no test coverage detected