@tanstack/cta-framework-react-cra 0.40.0 → 0.41.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
@@ -3,5 +3,5 @@
3
3
  Add components using the latest version of [Shadcn](https://ui.shadcn.com/).
4
4
 
5
5
  ```bash
6
- pnpx shadcn@latest add button
6
+ pnpm dlx shadcn@latest add button
7
7
  ```
@@ -3,5 +3,5 @@
3
3
  Use the latest version of Shadcn to install new components, like this command to add a button component:
4
4
 
5
5
  ```bash
6
- pnpx shadcn@latest add button
6
+ pnpm dlx shadcn@latest add button
7
7
  ```
@@ -5,7 +5,7 @@ The current setup shows an example of how to use Strapi with an articles collect
5
5
  - Create a local running copy of the strapi admin
6
6
 
7
7
  ```bash
8
- pnpx create-strapi@latest my-strapi-project
8
+ pnpm dlx create-strapi@latest my-strapi-project
9
9
  cd my-strapi-project
10
10
  pnpm dev
11
11
  ```
package/dist/checksum.js CHANGED
@@ -1,3 +1,3 @@
1
1
  // This file is auto-generated. Do not edit manually.
2
2
  // Generated from add-ons, examples, hosts, project, and toolchains directories
3
- export const contentChecksum = 'feb5810163b26e8f14f145eedea21242641ec1d266639a75873acc3eb7b04faa';
3
+ export const contentChecksum = 'd7d41081b1bcca2817f39f2d535d21ebd80c3dd2ec04560d0cd3a0663eb04058';
@@ -1 +1 @@
1
- export declare const contentChecksum = "feb5810163b26e8f14f145eedea21242641ec1d266639a75873acc3eb7b04faa";
1
+ export declare const contentChecksum = "d7d41081b1bcca2817f39f2d535d21ebd80c3dd2ec04560d0cd3a0663eb04058";
@@ -5,12 +5,18 @@ import { Store } from '@tanstack/store'
5
5
  import { Send, X, ChevronRight } from 'lucide-react'
6
6
  import { Streamdown } from 'streamdown'
7
7
 
8
- import { useChat } from '@ai-sdk/react'
9
- import { DefaultChatTransport } from 'ai'
8
+ import { fetchServerSentEvents, useChat } from '@tanstack/ai-react'
9
+ import { clientTools } from '@tanstack/ai-client'
10
+ import type { UIMessage } from '@tanstack/ai-react'
10
11
 
11
12
  import GuitarRecommendation from './example-GuitarRecommendation'
13
+ import { recommendGuitarToolDef } from '@/lib/example.guitar-tools'
12
14
 
13
- import type { UIMessage } from 'ai'
15
+ const recommendGuitarToolClient = recommendGuitarToolDef.client(({ id }) => ({
16
+ id: +id,
17
+ }))
18
+
19
+ const tools = clientTools(recommendGuitarToolClient)
14
20
 
15
21
  export const showAIAssistant = new Store(false)
16
22
 
@@ -43,10 +49,10 @@ function Messages({ messages }: { messages: Array<UIMessage> }) {
43
49
  : 'bg-transparent'
44
50
  }`}
45
51
  >
46
- {parts.map((part) => {
47
- if (part.type === 'text') {
52
+ {parts.map((part, index) => {
53
+ if (part.type === 'text' && part.content) {
48
54
  return (
49
- <div className="flex items-start gap-2 px-4">
55
+ <div key={index} className="flex items-start gap-2 px-4">
50
56
  {role === 'assistant' ? (
51
57
  <div className="w-6 h-6 rounded-lg bg-gradient-to-r from-orange-500 to-red-600 flex items-center justify-center text-xs font-medium text-white flex-shrink-0">
52
58
  AI
@@ -57,21 +63,19 @@ function Messages({ messages }: { messages: Array<UIMessage> }) {
57
63
  </div>
58
64
  )}
59
65
  <div className="flex-1 min-w-0 text-white prose dark:prose-invert max-w-none prose-sm">
60
- <Streamdown>{part.text}</Streamdown>
66
+ <Streamdown>{part.content}</Streamdown>
61
67
  </div>
62
68
  </div>
63
69
  )
64
70
  }
65
71
  if (
66
- part.type === 'tool-recommendGuitar' &&
67
- part.state === 'output-available' &&
68
- (part.output as { id: string })?.id
72
+ part.type === 'tool-call' &&
73
+ part.name === 'recommendGuitar' &&
74
+ part.output
69
75
  ) {
70
76
  return (
71
- <div key={id} className="max-w-[80%] mx-auto">
72
- <GuitarRecommendation
73
- id={(part.output as { id: string })?.id}
74
- />
77
+ <div key={part.id} className="max-w-[80%] mx-auto">
78
+ <GuitarRecommendation id={String(part.output?.id)} />
75
79
  </div>
76
80
  )
77
81
  }
@@ -85,9 +89,8 @@ function Messages({ messages }: { messages: Array<UIMessage> }) {
85
89
  export default function AIAssistant() {
86
90
  const isOpen = useStore(showAIAssistant)
87
91
  const { messages, sendMessage } = useChat({
88
- transport: new DefaultChatTransport({
89
- api: '/demo/api/tanchat',
90
- }),
92
+ connection: fetchServerSentEvents('/demo/api/tanchat'),
93
+ tools,
91
94
  })
92
95
  const [input, setInput] = useState('')
93
96
 
@@ -124,8 +127,10 @@ export default function AIAssistant() {
124
127
  <form
125
128
  onSubmit={(e) => {
126
129
  e.preventDefault()
127
- sendMessage({ text: input })
128
- setInput('')
130
+ if (input.trim()) {
131
+ sendMessage(input)
132
+ setInput('')
133
+ }
129
134
  }}
130
135
  >
131
136
  <div className="relative">
@@ -143,9 +148,9 @@ export default function AIAssistant() {
143
148
  Math.min(target.scrollHeight, 120) + 'px'
144
149
  }}
145
150
  onKeyDown={(e) => {
146
- if (e.key === 'Enter' && !e.shiftKey) {
151
+ if (e.key === 'Enter' && !e.shiftKey && input.trim()) {
147
152
  e.preventDefault()
148
- sendMessage({ text: input })
153
+ sendMessage(input)
149
154
  setInput('')
150
155
  }
151
156
  }}
@@ -10,6 +10,16 @@ export interface Guitar {
10
10
  const guitars: Array<Guitar> = [
11
11
  {
12
12
  id: 1,
13
+ name: 'TanStack Ukelele',
14
+ image: '/example-ukelele-tanstack.jpg',
15
+ description:
16
+ "Introducing the TanStack Signature Ukulele—a beautifully handcrafted concert ukulele that combines exceptional sound quality with distinctive style. Featuring a warm, resonant koa-wood body with natural grain patterns, this instrument delivers the rich, mellow tones Hawaii is famous for. The exclusive TanStack palm tree inlay on the soundhole adds a unique touch of island flair, while the matching branded headstock makes this a true collector's piece for developers and musicians alike. Whether you're a beginner looking for a quality starter instrument or an experienced player wanting something special, the TanStack Ukulele brings together craftsmanship, character, and that unmistakable tropical spirit.",
17
+ shortDescription:
18
+ 'Premium koa-wood ukulele featuring exclusive TanStack branding, perfect for beach vibes and island-inspired melodies.',
19
+ price: 299,
20
+ },
21
+ {
22
+ id: 2,
13
23
  name: 'Video Game Guitar',
14
24
  image: '/example-guitar-video-games.jpg',
15
25
  description:
@@ -19,7 +29,7 @@ const guitars: Array<Guitar> = [
19
29
  price: 699,
20
30
  },
21
31
  {
22
- id: 2,
32
+ id: 3,
23
33
  name: 'Superhero Guitar',
24
34
  image: '/example-guitar-superhero.jpg',
25
35
  description:
@@ -29,7 +39,7 @@ const guitars: Array<Guitar> = [
29
39
  price: 699,
30
40
  },
31
41
  {
32
- id: 3,
42
+ id: 4,
33
43
  name: 'Motherboard Guitar',
34
44
  image: '/example-guitar-motherboard.jpg',
35
45
  description:
@@ -39,7 +49,7 @@ const guitars: Array<Guitar> = [
39
49
  price: 649,
40
50
  },
41
51
  {
42
- id: 4,
52
+ id: 5,
43
53
  name: 'Racing Guitar',
44
54
  image: '/example-guitar-racing.jpg',
45
55
  description:
@@ -49,7 +59,7 @@ const guitars: Array<Guitar> = [
49
59
  price: 679,
50
60
  },
51
61
  {
52
- id: 5,
62
+ id: 6,
53
63
  name: 'Steamer Trunk Guitar',
54
64
  image: '/example-guitar-steamer-trunk.jpg',
55
65
  description:
@@ -59,7 +69,7 @@ const guitars: Array<Guitar> = [
59
69
  price: 629,
60
70
  },
61
71
  {
62
- id: 6,
72
+ id: 7,
63
73
  name: "Travelin' Man Guitar",
64
74
  image: '/example-guitar-traveling.jpg',
65
75
  description:
@@ -69,7 +79,7 @@ const guitars: Array<Guitar> = [
69
79
  price: 499,
70
80
  },
71
81
  {
72
- id: 7,
82
+ id: 8,
73
83
  name: 'Flowerly Love Guitar',
74
84
  image: '/example-guitar-flowers.jpg',
75
85
  description:
@@ -0,0 +1,40 @@
1
+ import { toolDefinition } from '@tanstack/ai'
2
+ import { z } from 'zod'
3
+ import guitars from '@/data/example-guitars'
4
+
5
+ // Tool definition for getting guitars
6
+ export const getGuitarsToolDef = toolDefinition({
7
+ name: 'getGuitars',
8
+ description: 'Get all products from the database',
9
+ inputSchema: z.object({}),
10
+ outputSchema: z.array(
11
+ z.object({
12
+ id: z.number(),
13
+ name: z.string(),
14
+ image: z.string(),
15
+ description: z.string(),
16
+ shortDescription: z.string(),
17
+ price: z.number(),
18
+ }),
19
+ ),
20
+ })
21
+
22
+ // Server implementation
23
+ export const getGuitars = getGuitarsToolDef.server(() => guitars)
24
+
25
+ // Tool definition for guitar recommendation
26
+ export const recommendGuitarToolDef = toolDefinition({
27
+ name: 'recommendGuitar',
28
+ description:
29
+ 'REQUIRED tool to display a guitar recommendation to the user. This tool MUST be used whenever recommending a guitar - do NOT write recommendations yourself. This displays the guitar in a special appealing format with a buy button.',
30
+ inputSchema: z.object({
31
+ id: z
32
+ .union([z.string(), z.number()])
33
+ .describe(
34
+ 'The ID of the guitar to recommend (from the getGuitars results)',
35
+ ),
36
+ }),
37
+ outputSchema: z.object({
38
+ id: z.number(),
39
+ }),
40
+ })
@@ -1,48 +1,63 @@
1
1
  import { createFileRoute } from '@tanstack/react-router'
2
- <% if (addOnEnabled['netlify']) { %>import { createAnthropic } from '@ai-sdk/anthropic'
3
- <% } else { %>import { anthropic } from '@ai-sdk/anthropic'
4
- <% } %>import { convertToModelMessages, stepCountIs, streamText } from 'ai'
2
+ import { chat, maxIterations, toStreamResponse } from '@tanstack/ai'
3
+ import { anthropic } from '@tanstack/ai-anthropic'
5
4
 
6
- import getTools from '@/utils/demo.tools'
5
+ import { getGuitars, recommendGuitarToolDef } from '@/lib/example.guitar-tools'
7
6
 
8
7
  const SYSTEM_PROMPT = `You are a helpful assistant for a store that sells guitars.
9
8
 
10
- You can use the following tools to help the user:
9
+ CRITICAL INSTRUCTIONS - YOU MUST FOLLOW THIS EXACT WORKFLOW:
11
10
 
12
- - getGuitars: Get all guitars from the database
13
- - recommendGuitar: Recommend a guitar to the user
11
+ When a user asks for a guitar recommendation:
12
+ 1. FIRST: Use the getGuitars tool (no parameters needed)
13
+ 2. SECOND: Use the recommendGuitar tool with the ID of the guitar you want to recommend
14
+ 3. NEVER write a recommendation directly - ALWAYS use the recommendGuitar tool
15
+
16
+ IMPORTANT:
17
+ - The recommendGuitar tool will display the guitar in a special, appealing format
18
+ - You MUST use recommendGuitar for ANY guitar recommendation
19
+ - ONLY recommend guitars from our inventory (use getGuitars first)
20
+ - The recommendGuitar tool has a buy button - this is how customers purchase
21
+ - Do NOT describe the guitar yourself - let the recommendGuitar tool do it
14
22
  `
15
- <% if (addOnEnabled['netlify']) { %>const anthropic = createAnthropic({
16
- baseURL: process.env.ANTHROPIC_BASE_URL
17
- ? `${process.env.ANTHROPIC_BASE_URL}/v1`
18
- : undefined,
19
- apiKey: process.env.ANTHROPIC_API_KEY,
20
- headers: {
21
- 'user-agent': 'anthropic/',
22
- },
23
- })
24
- <% } %>
25
- export const Route = createFileRoute('/api/demo-chat')({
23
+
24
+ export const Route = createFileRoute('/demo/api/tanchat')({
26
25
  server: {
27
26
  handlers: {
28
27
  POST: async ({ request }) => {
28
+ // Capture request signal before reading body (it may be aborted after body is consumed)
29
+ const requestSignal = request.signal
30
+
31
+ // If request is already aborted, return early
32
+ if (requestSignal.aborted) {
33
+ return new Response(null, { status: 499 }) // 499 = Client Closed Request
34
+ }
35
+
36
+ const abortController = new AbortController()
37
+
29
38
  try {
30
39
  const { messages } = await request.json()
31
40
 
32
- const tools = await getTools()
33
-
34
- const result = await streamText({
35
- model: anthropic('<% if (addOnEnabled['netlify']) { %>claude-sonnet-4-5-20250929<% } else { %>claude-haiku-4-5<% } %>'),
36
- messages: convertToModelMessages(messages),
37
- temperature: 0.7,
38
- stopWhen: stepCountIs(5),
39
- system: SYSTEM_PROMPT,
40
- tools,
41
+ const stream = chat({
42
+ adapter: anthropic(),
43
+ model: 'claude-haiku-4-5',
44
+ tools: [
45
+ getGuitars, // Server tool
46
+ recommendGuitarToolDef, // No server execute - client will handle
47
+ ],
48
+ systemPrompts: [SYSTEM_PROMPT],
49
+ agentLoopStrategy: maxIterations(5),
50
+ messages,
51
+ abortController,
41
52
  })
42
53
 
43
- return result.toUIMessageStreamResponse()
44
- } catch (error) {
54
+ return toStreamResponse(stream, { abortController })
55
+ } catch (error: any) {
45
56
  console.error('Chat API error:', error)
57
+ // If request was aborted, return early (don't send error response)
58
+ if (error.name === 'AbortError' || abortController.signal.aborted) {
59
+ return new Response(null, { status: 499 }) // 499 = Client Closed Request
60
+ }
46
61
  return new Response(
47
62
  JSON.stringify({ error: 'Failed to process chat request' }),
48
63
  {
@@ -1,16 +1,22 @@
1
1
  import { useEffect, useRef, useState } from 'react'
2
2
  import { createFileRoute } from '@tanstack/react-router'
3
- import { Send } from 'lucide-react'
3
+ import { Send, Square } from 'lucide-react'
4
4
  import { Streamdown } from 'streamdown'
5
- import { useChat } from '@ai-sdk/react'
6
- import { DefaultChatTransport } from 'ai'
7
-
8
- import type { UIMessage } from 'ai'
5
+ import { fetchServerSentEvents, useChat } from '@tanstack/ai-react'
6
+ import { clientTools } from '@tanstack/ai-client'
7
+ import type { UIMessage } from '@tanstack/ai-react'
9
8
 
10
9
  import GuitarRecommendation from '@/components/example-GuitarRecommendation'
10
+ import { recommendGuitarToolDef } from '@/lib/example.guitar-tools'
11
11
 
12
12
  import './tanchat.css'
13
13
 
14
+ const recommendGuitarToolClient = recommendGuitarToolDef.client(({ id }) => ({
15
+ id: +id,
16
+ }))
17
+
18
+ const tools = clientTools(recommendGuitarToolClient)
19
+
14
20
  function InitalLayout({ children }: { children: React.ReactNode }) {
15
21
  return (
16
22
  <div className="flex-1 flex items-center justify-center px-4">
@@ -56,17 +62,17 @@ function Messages({ messages }: { messages: Array<UIMessage> }) {
56
62
  className="flex-1 overflow-y-auto pb-4 min-h-0"
57
63
  >
58
64
  <div className="max-w-3xl mx-auto w-full px-4">
59
- {messages.map(({ id, role, parts }) => (
65
+ {messages.map((message) => (
60
66
  <div
61
- key={id}
67
+ key={message.id}
62
68
  className={`p-4 ${
63
- role === 'assistant'
69
+ message.role === 'assistant'
64
70
  ? 'bg-gradient-to-r from-orange-500/5 to-red-600/5'
65
71
  : 'bg-transparent'
66
72
  }`}
67
73
  >
68
74
  <div className="flex items-start gap-4 max-w-3xl mx-auto w-full">
69
- {role === 'assistant' ? (
75
+ {message.role === 'assistant' ? (
70
76
  <div className="w-8 h-8 rounded-lg bg-gradient-to-r from-orange-500 to-red-600 mt-2 flex items-center justify-center text-sm font-medium text-white flex-shrink-0">
71
77
  AI
72
78
  </div>
@@ -75,31 +81,31 @@ function Messages({ messages }: { messages: Array<UIMessage> }) {
75
81
  Y
76
82
  </div>
77
83
  )}
78
- <div className="flex-1">
79
- {parts.map((part, index) => {
80
- if (part.type === 'text') {
84
+ <div className="flex-1 min-w-0">
85
+ {message.parts.map((part, index) => {
86
+ if (part.type === 'text' && part.content) {
81
87
  return (
82
88
  <div
83
89
  className="flex-1 min-w-0 prose dark:prose-invert max-w-none prose-sm"
84
90
  key={index}
85
91
  >
86
- <Streamdown>{part.text}</Streamdown>
92
+ <Streamdown>{part.content}</Streamdown>
87
93
  </div>
88
94
  )
89
95
  }
96
+ // Guitar recommendation card
90
97
  if (
91
- part.type === 'tool-recommendGuitar' &&
92
- part.state === 'output-available' &&
93
- (part.output as { id: string })?.id
98
+ part.type === 'tool-call' &&
99
+ part.name === 'recommendGuitar' &&
100
+ part.output
94
101
  ) {
95
102
  return (
96
- <div key={index} className="max-w-[80%] mx-auto">
97
- <GuitarRecommendation
98
- id={(part.output as { id: string })?.id}
99
- />
103
+ <div key={part.id} className="max-w-[80%] mx-auto">
104
+ <GuitarRecommendation id={String(part.output?.id)} />
100
105
  </div>
101
106
  )
102
107
  }
108
+ return null
103
109
  })}
104
110
  </div>
105
111
  </div>
@@ -111,10 +117,9 @@ function Messages({ messages }: { messages: Array<UIMessage> }) {
111
117
  }
112
118
 
113
119
  function ChatPage() {
114
- const { messages, sendMessage } = useChat({
115
- transport: new DefaultChatTransport({
116
- api: '/demo/api/tanchat',
117
- }),
120
+ const { messages, sendMessage, isLoading, stop } = useChat({
121
+ connection: fetchServerSentEvents('/demo/api/tanchat'),
122
+ tools,
118
123
  })
119
124
  const [input, setInput] = useState('')
120
125
 
@@ -126,44 +131,60 @@ function ChatPage() {
126
131
  <Messages messages={messages} />
127
132
 
128
133
  <Layout>
129
- <form
130
- onSubmit={(e) => {
131
- e.preventDefault()
132
- sendMessage({ text: input })
133
- setInput('')
134
- }}
135
- >
136
- <div className="relative max-w-xl mx-auto">
137
- <textarea
138
- value={input}
139
- onChange={(e) => setInput(e.target.value)}
140
- placeholder="Type something clever..."
141
- className="w-full rounded-lg border border-orange-500/20 bg-gray-800/50 pl-4 pr-12 py-3 text-sm text-white placeholder-gray-400 focus:outline-none focus:ring-2 focus:ring-orange-500/50 focus:border-transparent resize-none overflow-hidden shadow-lg"
142
- rows={1}
143
- style={{ minHeight: '44px', maxHeight: '200px' }}
144
- onInput={(e) => {
145
- const target = e.target as HTMLTextAreaElement
146
- target.style.height = 'auto'
147
- target.style.height =
148
- Math.min(target.scrollHeight, 200) + 'px'
149
- }}
150
- onKeyDown={(e) => {
151
- if (e.key === 'Enter' && !e.shiftKey) {
152
- e.preventDefault()
153
- sendMessage({ text: input })
154
- setInput('')
155
- }
156
- }}
157
- />
158
- <button
159
- type="submit"
160
- disabled={!input.trim()}
161
- className="absolute right-2 top-1/2 -translate-y-1/2 p-2 text-orange-500 hover:text-orange-400 disabled:text-gray-500 transition-colors focus:outline-none"
162
- >
163
- <Send className="w-4 h-4" />
164
- </button>
165
- </div>
166
- </form>
134
+ <div className="space-y-3">
135
+ {isLoading && (
136
+ <div className="flex items-center justify-center">
137
+ <button
138
+ onClick={stop}
139
+ className="px-4 py-2 bg-red-600 hover:bg-red-700 text-white rounded-lg text-sm font-medium transition-colors flex items-center gap-2"
140
+ >
141
+ <Square className="w-4 h-4 fill-current" />
142
+ Stop
143
+ </button>
144
+ </div>
145
+ )}
146
+ <form
147
+ onSubmit={(e) => {
148
+ e.preventDefault()
149
+ if (input.trim()) {
150
+ sendMessage(input)
151
+ setInput('')
152
+ }
153
+ }}
154
+ >
155
+ <div className="relative max-w-xl mx-auto">
156
+ <textarea
157
+ value={input}
158
+ onChange={(e) => setInput(e.target.value)}
159
+ placeholder="Type something clever..."
160
+ className="w-full rounded-lg border border-orange-500/20 bg-gray-800/50 pl-4 pr-12 py-3 text-sm text-white placeholder-gray-400 focus:outline-none focus:ring-2 focus:ring-orange-500/50 focus:border-transparent resize-none overflow-hidden shadow-lg"
161
+ rows={1}
162
+ style={{ minHeight: '44px', maxHeight: '200px' }}
163
+ disabled={isLoading}
164
+ onInput={(e) => {
165
+ const target = e.target as HTMLTextAreaElement
166
+ target.style.height = 'auto'
167
+ target.style.height =
168
+ Math.min(target.scrollHeight, 200) + 'px'
169
+ }}
170
+ onKeyDown={(e) => {
171
+ if (e.key === 'Enter' && !e.shiftKey && input.trim()) {
172
+ e.preventDefault()
173
+ sendMessage(input)
174
+ setInput('')
175
+ }
176
+ }}
177
+ />
178
+ <button
179
+ type="submit"
180
+ disabled={!input.trim() || isLoading}
181
+ className="absolute right-2 top-1/2 -translate-y-1/2 p-2 text-orange-500 hover:text-orange-400 disabled:text-gray-500 transition-colors focus:outline-none"
182
+ >
183
+ <Send className="w-4 h-4" />
184
+ </button>
185
+ </div>
186
+ </form>
187
+ </div>
167
188
  </Layout>
168
189
  </div>
169
190
  </div>
@@ -1,10 +1,9 @@
1
1
  {
2
2
  "dependencies": {
3
- "@ai-sdk/anthropic": "^2.0.1",
4
- "@ai-sdk/mcp": "^0.0.5",
5
- "@ai-sdk/react": "^2.0.8",
6
- "@modelcontextprotocol/sdk": "^1.8.0",
7
- "ai": "^5.0.8",
3
+ "@tanstack/ai": "^0.0.1",
4
+ "@tanstack/ai-anthropic": "^0.0.1",
5
+ "@tanstack/ai-client": "^0.0.1",
6
+ "@tanstack/ai-react": "^0.0.1",
8
7
  "highlight.js": "^11.11.1",
9
8
  "streamdown": "^1.6.5",
10
9
  "lucide-react": "^0.544.0",
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@tanstack/cta-framework-react-cra",
3
- "version": "0.40.0",
3
+ "version": "0.41.0",
4
4
  "description": "CTA Framework for React (Create React App)",
5
5
  "type": "module",
6
6
  "main": "./dist/index.js",
package/src/checksum.ts CHANGED
@@ -1,3 +1,3 @@
1
1
  // This file is auto-generated. Do not edit manually.
2
2
  // Generated from add-ons, examples, hosts, project, and toolchains directories
3
- export const contentChecksum = 'feb5810163b26e8f14f145eedea21242641ec1d266639a75873acc3eb7b04faa'
3
+ export const contentChecksum = 'd7d41081b1bcca2817f39f2d535d21ebd80c3dd2ec04560d0cd3a0663eb04058'
@@ -1,54 +0,0 @@
1
- import { tool } from 'ai'
2
- // import { experimental_createMCPClient } from '@ai-sdk/mcp'
3
- // import { StdioClientTransport } from "@modelcontextprotocol/sdk/client/stdio.js";
4
- import { z } from 'zod'
5
-
6
- import guitars from '../data/example-guitars'
7
-
8
- // Example of using an SSE MCP server
9
- // const mcpClient = await experimental_createMCPClient({
10
- // transport: {
11
- // type: "sse",
12
- // url: "http://localhost:8081/sse",
13
- // },
14
- // name: "Demo Service",
15
- // });
16
-
17
- // Example of using an STDIO MCP server
18
- // const mcpClient = await experimental_createMCPClient({
19
- // transport: new StdioClientTransport({
20
- // command: "node",
21
- // args: [
22
- // "stdio-server.js",
23
- // ],
24
- // }),
25
- // });
26
-
27
- const getGuitars = tool({
28
- description: 'Get all products from the database',
29
- inputSchema: z.object({}),
30
- execute: async () => {
31
- return Promise.resolve(guitars)
32
- },
33
- })
34
-
35
- const recommendGuitar = tool({
36
- description: 'Use this tool to recommend a guitar to the user',
37
- inputSchema: z.object({
38
- id: z.string().describe('The id of the guitar to recommend'),
39
- }),
40
- execute: async ({ id }) => {
41
- return {
42
- id,
43
- }
44
- },
45
- })
46
-
47
- export default async function getTools() {
48
- // const mcpTools = await mcpClient.tools()
49
- return {
50
- // ...mcpTools,
51
- getGuitars,
52
- recommendGuitar,
53
- }
54
- }