@@ -7,11 +7,18 @@ import rehypeSanitize from 'rehype-sanitize'
77import rehypeHighlight from 'rehype-highlight'
88import remarkGfm from 'remark-gfm'
99import { fetchServerSentEvents , useChat } from '@tanstack/ai-react'
10+ import { clientTools } from '@tanstack/ai-client'
1011import { ThinkingPart } from '@tanstack/ai-react-ui'
1112
1213import type { UIMessage } from '@tanstack/ai-react'
1314
1415import GuitarRecommendation from '@/components/example-GuitarRecommendation'
16+ import {
17+ addToCartToolDef ,
18+ addToWishListToolDef ,
19+ getPersonalGuitarPreferenceToolDef ,
20+ recommendGuitarToolDef ,
21+ } from '@/lib/guitar-tools'
1522import {
1623 MODEL_OPTIONS ,
1724 getDefaultModelOption ,
@@ -20,6 +27,39 @@ import {
2027} from '@/lib/model-selection'
2128import './tanchat.css'
2229
30+ const getPersonalGuitarPreferenceToolClient =
31+ getPersonalGuitarPreferenceToolDef . client ( ( ) => ( { preference : 'acoustic' } ) )
32+
33+ const addToWishListToolClient = addToWishListToolDef . client ( ( args ) => {
34+ const wishList = JSON . parse ( localStorage . getItem ( 'wishList' ) || '[]' )
35+ wishList . push ( args . guitarId )
36+ localStorage . setItem ( 'wishList' , JSON . stringify ( wishList ) )
37+ return {
38+ success : true ,
39+ guitarId : args . guitarId ,
40+ totalItems : wishList . length ,
41+ }
42+ } )
43+
44+ const addToCartToolClient = addToCartToolDef . client ( ( args ) => ( {
45+ success : true ,
46+ cartId : 'CART_CLIENT_' + Date . now ( ) ,
47+ guitarId : args . guitarId ,
48+ quantity : args . quantity ,
49+ totalItems : args . quantity ,
50+ } ) )
51+
52+ const recommendGuitarToolClient = recommendGuitarToolDef . client ( ( { id } ) => ( {
53+ id,
54+ } ) )
55+
56+ const tools = clientTools (
57+ getPersonalGuitarPreferenceToolClient ,
58+ addToWishListToolClient ,
59+ addToCartToolClient ,
60+ recommendGuitarToolClient ,
61+ )
62+
2363function ChatInputArea ( { children } : { children : React . ReactNode } ) {
2464 return (
2565 < div className = "border-t border-orange-500/10 bg-gray-900/80 backdrop-blur-sm" >
@@ -365,37 +405,11 @@ function ChatPage() {
365405 const { messages, sendMessage, isLoading, addToolApprovalResponse, stop } =
366406 useChat ( {
367407 connection : fetchServerSentEvents ( '/api/chat' ) ,
408+ tools,
368409 onChunk : ( chunk : any ) => {
369410 setChunks ( ( prev ) => [ ...prev , chunk ] )
370411 } ,
371412 body,
372- onToolCall : async ( { toolName, input } ) => {
373- // Handle client-side tool execution
374- switch ( toolName ) {
375- case 'getPersonalGuitarPreference' :
376- // Pure client tool - executes immediately
377- return { preference : 'acoustic' }
378-
379- case 'recommendGuitar' :
380- // Client tool for UI display
381- return { id : input . id }
382-
383- case 'addToWishList' :
384- // Hybrid: client execution AFTER approval
385- // Only runs after user approves
386- const wishList = JSON . parse (
387- localStorage . getItem ( 'wishList' ) || '[]' ,
388- )
389- wishList . push ( input . guitarId )
390- localStorage . setItem ( 'wishList' , JSON . stringify ( wishList ) )
391- return {
392- success : true ,
393- guitarId : input . guitarId ,
394- totalItems : wishList . length ,
395- }
396- }
397- return Promise . resolve ( { result : 'Unknown client tool' } )
398- } ,
399413 } )
400414 const [ input , setInput ] = useState ( '' )
401415
0 commit comments