11"use client" ;
22
33import { useChat } from "@ai-sdk/react" ;
4- import { lastAssistantMessageIsCompleteWithApprovalResponses } from "ai" ;
4+ import {
5+ lastAssistantMessageIsCompleteWithApprovalResponses ,
6+ lastAssistantMessageIsCompleteWithToolCalls ,
7+ } from "ai" ;
58import type { ChatUiMessage } from "@/lib/chat-tools" ;
69import type { TriggerChatTransport } from "@trigger.dev/sdk/chat" ;
710import type { CompactionChunkData } from "@trigger.dev/sdk/ai" ;
@@ -14,10 +17,12 @@ function ToolInvocation({
1417 part,
1518 onApprove,
1619 onDeny,
20+ onToolOutput,
1721} : {
1822 part : any ;
1923 onApprove ?: ( approvalId : string ) => void ;
2024 onDeny ?: ( approvalId : string ) => void ;
25+ onToolOutput ?: ( toolCallId : string , output : unknown ) => void ;
2126} ) {
2227 const [ expanded , setExpanded ] = useState ( false ) ;
2328 const toolName = part . type . startsWith ( "tool-" ) ? part . type . slice ( 5 ) : "tool" ;
@@ -72,6 +77,31 @@ function ToolInvocation({
7277 </ div >
7378 ) }
7479
80+ { /* askUser tool: show question + option buttons when input-available */ }
81+ { toolName === "askUser" && state === "input-available" && args ?. question && (
82+ < div className = "border-t border-gray-200 px-3 py-2 space-y-2" >
83+ < div className = "font-medium text-gray-700" > { args . question } </ div >
84+ < div className = "flex flex-wrap gap-2" >
85+ { ( args . options ?? [ ] ) . map ( ( opt : any ) => (
86+ < button
87+ key = { opt . id }
88+ type = "button"
89+ onClick = { ( ) =>
90+ onToolOutput ?.( part . toolCallId , {
91+ skipped : false ,
92+ answers : [ { questionId : args . question , optionId : opt . id , text : opt . label } ] ,
93+ } )
94+ }
95+ className = "rounded border border-blue-300 bg-blue-50 px-3 py-1.5 text-xs text-blue-700 hover:bg-blue-100"
96+ title = { opt . description }
97+ >
98+ { opt . label }
99+ </ button >
100+ ) ) }
101+ </ div >
102+ </ div >
103+ ) }
104+
75105 { expanded && (
76106 < div className = "border-t border-gray-200 px-3 py-2 space-y-2" >
77107 { args && Object . keys ( args ) . length > 0 && (
@@ -310,14 +340,17 @@ export function Chat({
310340 sendMessage,
311341 stop : aiStop ,
312342 addToolApprovalResponse,
343+ addToolOutput,
313344 status,
314345 error,
315346 } = useChat ( {
316347 id : chatId ,
317348 messages : initialMessages ,
318349 transport,
319350 resume : resumeProp ,
320- sendAutomaticallyWhen : lastAssistantMessageIsCompleteWithApprovalResponses ,
351+ sendAutomaticallyWhen : ( opts ) =>
352+ lastAssistantMessageIsCompleteWithApprovalResponses ( opts ) ||
353+ lastAssistantMessageIsCompleteWithToolCalls ( opts ) ,
321354 } ) ;
322355
323356 // Use transport.stopGeneration for reliable stop after reconnect.
@@ -616,6 +649,9 @@ export function Chat({
616649 part = { part }
617650 onApprove = { handleApprove }
618651 onDeny = { handleDeny }
652+ onToolOutput = { ( toolCallId , output ) =>
653+ addToolOutput ( { toolCallId, output } )
654+ }
619655 />
620656 ) ;
621657 }
0 commit comments