( params: RouterParams, )
| 246 | } |
| 247 | |
| 248 | export async function routeUserPrompt( |
| 249 | params: RouterParams, |
| 250 | ): Promise<CommandResult> { |
| 251 | const { |
| 252 | agentMode, |
| 253 | inputRef, |
| 254 | inputValue, |
| 255 | isChainInProgressRef, |
| 256 | isStreaming, |
| 257 | streamMessageIdRef, |
| 258 | addToQueue, |
| 259 | saveToHistory, |
| 260 | scrollToLatest, |
| 261 | sendMessage, |
| 262 | setInputFocused, |
| 263 | setInputValue, |
| 264 | setMessages, |
| 265 | } = params |
| 266 | |
| 267 | const inputMode = useChatStore.getState().inputMode |
| 268 | const setInputMode = useChatStore.getState().setInputMode |
| 269 | const pendingAttachments = useChatStore.getState().pendingAttachments |
| 270 | const pendingImages = pendingAttachments.filter((a) => a.kind === 'image') |
| 271 | const pendingTextAttachments = pendingAttachments.filter( |
| 272 | (a) => a.kind === 'text', |
| 273 | ) |
| 274 | |
| 275 | const trimmed = inputValue.trim() |
| 276 | // Allow empty messages if there are pending attachments (images or text) |
| 277 | const hasAttachments = pendingAttachments.length > 0 |
| 278 | if (!trimmed && !hasAttachments) return |
| 279 | |
| 280 | // Track user input complete |
| 281 | // Count @ mentions (simple pattern match - more accurate than nothing) |
| 282 | const mentionMatches = trimmed.match(/@\S+/g) || [] |
| 283 | trackEvent(AnalyticsEvent.USER_INPUT_COMPLETE, { |
| 284 | inputLength: trimmed.length, |
| 285 | mode: agentMode, |
| 286 | inputMode, |
| 287 | hasImages: pendingImages.length > 0, |
| 288 | imageCount: pendingImages.length, |
| 289 | hasTextAttachments: pendingTextAttachments.length > 0, |
| 290 | textAttachmentCount: pendingTextAttachments.length, |
| 291 | isSlashCommand: isSlashCommand(trimmed), |
| 292 | isBashCommand: trimmed.startsWith('!'), |
| 293 | hasMentions: mentionMatches.length > 0, |
| 294 | mentionCount: mentionMatches.length, |
| 295 | }) |
| 296 | |
| 297 | // Handle bash mode commands |
| 298 | if (inputMode === 'bash') { |
| 299 | const commandWithBang = '!' + trimmed |
| 300 | saveToHistory(commandWithBang) |
| 301 | setInputValue({ text: '', cursorPosition: 0, lastEditDueToNav: false }) |
| 302 | setInputMode('default') |
| 303 | setInputFocused(true) |
| 304 | inputRef.current?.focus() |
| 305 |
no test coverage detected