@tanstack/cta-framework-react-cra 0.20.0 → 0.22.1
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.
- package/add-ons/db/assets/src/routes/demo.db-chat-api.ts +30 -26
- package/add-ons/mcp/assets/src/routes/api.mcp-todos.ts +29 -25
- package/add-ons/mcp/assets/src/routes/mcp.ts +22 -18
- package/add-ons/mcp/assets/src/utils/mcp-handler.ts +62 -60
- package/add-ons/neon/assets/src/routes/demo.neon.tsx +1 -1
- package/add-ons/oRPC/assets/src/routes/api.$.ts +12 -8
- package/add-ons/oRPC/assets/src/routes/api.rpc.$.ts +12 -8
- package/add-ons/start/assets/src/router.tsx.ejs +7 -14
- package/add-ons/start/assets/src/routes/api.demo-names.ts +11 -7
- package/add-ons/start/assets/src/routes/api.demo-tq-todos.ts.ejs +17 -13
- package/add-ons/start/assets/src/routes/demo.start.server-funcs.tsx +1 -1
- package/add-ons/start/assets/vite.config.ts.ejs +1 -3
- package/add-ons/start/package.json +1 -1
- package/add-ons/tRPC/assets/src/routes/api.trpc.$.tsx +8 -3
- package/examples/tanchat/assets/src/routes/api.demo-chat.ts +32 -28
- package/examples/tanchat/assets/src/routes/api.messages.ts +22 -17
- package/examples/tanchat/assets/src/routes/api.sse.ts +37 -33
- package/package.json +2 -2
- package/project/base/package.json +2 -2
- package/project/base/src/logo.svg +10 -42
- package/project/packages.json +2 -1
- package/tests/snapshots/react-cra/cr-js-form-npm.json +1 -1
- package/tests/snapshots/react-cra/cr-js-npm.json +1 -1
- package/tests/snapshots/react-cra/cr-ts-npm.json +1 -1
- package/tests/snapshots/react-cra/cr-ts-start-npm.json +5 -5
- package/tests/snapshots/react-cra/cr-ts-start-tanstack-query-npm.json +6 -6
- package/tests/snapshots/react-cra/fr-ts-biome-npm.json +1 -1
- package/tests/snapshots/react-cra/fr-ts-npm.json +1 -1
- package/tests/snapshots/react-cra/fr-ts-tw-npm.json +1 -1
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import {
|
|
1
|
+
import { createFileRoute } from '@tanstack/react-router'
|
|
2
2
|
|
|
3
3
|
import { createCollection, localOnlyCollectionOptions } from '@tanstack/db'
|
|
4
4
|
import { z } from 'zod'
|
|
@@ -41,34 +41,38 @@ const sendMessage = (message: { user: string; text: string }) => {
|
|
|
41
41
|
})
|
|
42
42
|
}
|
|
43
43
|
|
|
44
|
-
export const
|
|
45
|
-
|
|
46
|
-
|
|
47
|
-
|
|
48
|
-
|
|
49
|
-
controller
|
|
50
|
-
|
|
51
|
-
|
|
52
|
-
for (const change of changes) {
|
|
53
|
-
if (change.type === 'insert') {
|
|
54
|
-
controller.enqueue(JSON.stringify(change.value) + '\n')
|
|
44
|
+
export const Route = createFileRoute('/demo/db-chat-api')({
|
|
45
|
+
server: {
|
|
46
|
+
handlers: {
|
|
47
|
+
GET: () => {
|
|
48
|
+
const stream = new ReadableStream({
|
|
49
|
+
start(controller) {
|
|
50
|
+
for (const [_id, message] of serverMessagesCollection.state) {
|
|
51
|
+
controller.enqueue(JSON.stringify(message) + '\n')
|
|
55
52
|
}
|
|
56
|
-
|
|
53
|
+
serverMessagesCollection.subscribeChanges((changes) => {
|
|
54
|
+
for (const change of changes) {
|
|
55
|
+
if (change.type === 'insert') {
|
|
56
|
+
controller.enqueue(JSON.stringify(change.value) + '\n')
|
|
57
|
+
}
|
|
58
|
+
}
|
|
59
|
+
})
|
|
60
|
+
},
|
|
57
61
|
})
|
|
58
|
-
},
|
|
59
|
-
})
|
|
60
62
|
|
|
61
|
-
|
|
62
|
-
|
|
63
|
-
|
|
63
|
+
return new Response(stream, {
|
|
64
|
+
headers: {
|
|
65
|
+
'Content-Type': 'application/x-ndjson',
|
|
66
|
+
},
|
|
67
|
+
})
|
|
64
68
|
},
|
|
65
|
-
|
|
66
|
-
|
|
67
|
-
|
|
68
|
-
|
|
69
|
-
|
|
70
|
-
|
|
71
|
-
|
|
72
|
-
|
|
69
|
+
POST: async ({ request }) => {
|
|
70
|
+
const message = IncomingMessageSchema.safeParse(await request.json())
|
|
71
|
+
if (!message.success) {
|
|
72
|
+
return new Response(message.error.message, { status: 400 })
|
|
73
|
+
}
|
|
74
|
+
sendMessage(message.data)
|
|
75
|
+
},
|
|
76
|
+
},
|
|
73
77
|
},
|
|
74
78
|
})
|
|
@@ -1,29 +1,33 @@
|
|
|
1
|
-
import {
|
|
1
|
+
import { createFileRoute } from '@tanstack/react-router'
|
|
2
2
|
|
|
3
|
-
import { addTodo, getTodos, subscribeToTodos } from
|
|
3
|
+
import { addTodo, getTodos, subscribeToTodos } from '@/mcp-todos'
|
|
4
4
|
|
|
5
|
-
export const
|
|
6
|
-
|
|
7
|
-
|
|
8
|
-
|
|
9
|
-
|
|
10
|
-
controller
|
|
11
|
-
|
|
12
|
-
|
|
13
|
-
|
|
14
|
-
|
|
15
|
-
|
|
16
|
-
|
|
17
|
-
|
|
5
|
+
export const Route = createFileRoute('/api/mcp-todos')({
|
|
6
|
+
server: {
|
|
7
|
+
handlers: {
|
|
8
|
+
GET: () => {
|
|
9
|
+
const stream = new ReadableStream({
|
|
10
|
+
start(controller) {
|
|
11
|
+
setInterval(() => {
|
|
12
|
+
controller.enqueue(`event: ping\n\n`)
|
|
13
|
+
}, 1000)
|
|
14
|
+
const unsubscribe = subscribeToTodos((todos) => {
|
|
15
|
+
controller.enqueue(`data: ${JSON.stringify(todos)}\n\n`)
|
|
16
|
+
})
|
|
17
|
+
const todos = getTodos()
|
|
18
|
+
controller.enqueue(`data: ${JSON.stringify(todos)}\n\n`)
|
|
19
|
+
return () => unsubscribe()
|
|
20
|
+
},
|
|
21
|
+
})
|
|
22
|
+
return new Response(stream, {
|
|
23
|
+
headers: { 'Content-Type': 'text/event-stream' },
|
|
24
|
+
})
|
|
18
25
|
},
|
|
19
|
-
|
|
20
|
-
|
|
21
|
-
|
|
22
|
-
|
|
23
|
-
|
|
24
|
-
|
|
25
|
-
const { title } = await request.json();
|
|
26
|
-
addTodo(title);
|
|
27
|
-
return Response.json(getTodos());
|
|
26
|
+
POST: async ({ request }) => {
|
|
27
|
+
const { title } = await request.json()
|
|
28
|
+
addTodo(title)
|
|
29
|
+
return Response.json(getTodos())
|
|
30
|
+
},
|
|
31
|
+
},
|
|
28
32
|
},
|
|
29
|
-
})
|
|
33
|
+
})
|
|
@@ -1,29 +1,29 @@
|
|
|
1
|
-
import { McpServer } from
|
|
2
|
-
import {
|
|
3
|
-
import z from
|
|
1
|
+
import { McpServer } from '@modelcontextprotocol/sdk/server/mcp.js'
|
|
2
|
+
import { createFileRoute } from '@tanstack/react-router'
|
|
3
|
+
import z from 'zod'
|
|
4
4
|
|
|
5
|
-
import { handleMcpRequest } from
|
|
5
|
+
import { handleMcpRequest } from '@/utils/mcp-handler'
|
|
6
6
|
|
|
7
|
-
import { addTodo } from
|
|
7
|
+
import { addTodo } from '@/mcp-todos'
|
|
8
8
|
|
|
9
9
|
const server = new McpServer({
|
|
10
|
-
name:
|
|
11
|
-
version:
|
|
12
|
-
})
|
|
10
|
+
name: 'start-server',
|
|
11
|
+
version: '1.0.0',
|
|
12
|
+
})
|
|
13
13
|
|
|
14
14
|
server.registerTool(
|
|
15
|
-
|
|
15
|
+
'addTodo',
|
|
16
16
|
{
|
|
17
|
-
title:
|
|
18
|
-
description:
|
|
17
|
+
title: 'Tool to add a todo to a list of todos',
|
|
18
|
+
description: 'Add a todo to a list of todos',
|
|
19
19
|
inputSchema: {
|
|
20
|
-
title: z.string().describe(
|
|
20
|
+
title: z.string().describe('The title of the todo'),
|
|
21
21
|
},
|
|
22
22
|
},
|
|
23
23
|
({ title }) => ({
|
|
24
|
-
content: [{ type:
|
|
25
|
-
})
|
|
26
|
-
)
|
|
24
|
+
content: [{ type: 'text', text: String(addTodo(title)) }],
|
|
25
|
+
}),
|
|
26
|
+
)
|
|
27
27
|
|
|
28
28
|
// server.registerResource(
|
|
29
29
|
// "counter-value",
|
|
@@ -44,6 +44,10 @@ server.registerTool(
|
|
|
44
44
|
// }
|
|
45
45
|
// );
|
|
46
46
|
|
|
47
|
-
export const
|
|
48
|
-
|
|
49
|
-
|
|
47
|
+
export const Route = createFileRoute('/mcp')({
|
|
48
|
+
server: {
|
|
49
|
+
handlers: {
|
|
50
|
+
POST: async ({ request }) => handleMcpRequest(request, server),
|
|
51
|
+
},
|
|
52
|
+
},
|
|
53
|
+
})
|
|
@@ -1,61 +1,63 @@
|
|
|
1
|
-
import {
|
|
2
|
-
|
|
3
|
-
import type { McpServer } from
|
|
4
|
-
|
|
5
|
-
|
|
6
|
-
|
|
7
|
-
|
|
8
|
-
|
|
9
|
-
|
|
10
|
-
|
|
11
|
-
|
|
12
|
-
|
|
13
|
-
|
|
14
|
-
|
|
15
|
-
|
|
16
|
-
|
|
17
|
-
|
|
18
|
-
|
|
19
|
-
|
|
20
|
-
|
|
21
|
-
|
|
22
|
-
|
|
23
|
-
|
|
24
|
-
|
|
25
|
-
|
|
26
|
-
|
|
27
|
-
|
|
28
|
-
|
|
29
|
-
|
|
30
|
-
|
|
31
|
-
|
|
32
|
-
|
|
33
|
-
|
|
34
|
-
|
|
35
|
-
|
|
36
|
-
|
|
37
|
-
|
|
38
|
-
|
|
39
|
-
|
|
40
|
-
|
|
41
|
-
|
|
42
|
-
|
|
43
|
-
|
|
44
|
-
|
|
45
|
-
|
|
46
|
-
|
|
47
|
-
|
|
48
|
-
|
|
49
|
-
|
|
50
|
-
|
|
51
|
-
|
|
52
|
-
|
|
53
|
-
|
|
54
|
-
|
|
55
|
-
|
|
56
|
-
|
|
57
|
-
|
|
58
|
-
|
|
59
|
-
|
|
60
|
-
|
|
1
|
+
import { InMemoryTransport } from '@modelcontextprotocol/sdk/inMemory.js'
|
|
2
|
+
|
|
3
|
+
import type { McpServer } from '@modelcontextprotocol/sdk/server/mcp.js'
|
|
4
|
+
import type { JSONRPCMessage } from '@modelcontextprotocol/sdk/types.js'
|
|
5
|
+
|
|
6
|
+
export async function handleMcpRequest(
|
|
7
|
+
request: Request,
|
|
8
|
+
server: McpServer,
|
|
9
|
+
): Promise<Response> {
|
|
10
|
+
try {
|
|
11
|
+
const jsonRpcRequest = (await request.json()) as JSONRPCMessage
|
|
12
|
+
|
|
13
|
+
const [clientTransport, serverTransport] =
|
|
14
|
+
InMemoryTransport.createLinkedPair()
|
|
15
|
+
|
|
16
|
+
let responseData: JSONRPCMessage | null = null
|
|
17
|
+
|
|
18
|
+
clientTransport.onmessage = (message: JSONRPCMessage) => {
|
|
19
|
+
responseData = message
|
|
20
|
+
}
|
|
21
|
+
|
|
22
|
+
await server.connect(serverTransport)
|
|
23
|
+
|
|
24
|
+
await clientTransport.start()
|
|
25
|
+
await serverTransport.start()
|
|
26
|
+
|
|
27
|
+
await clientTransport.send(jsonRpcRequest)
|
|
28
|
+
|
|
29
|
+
await new Promise((resolve) => setTimeout(resolve, 10))
|
|
30
|
+
|
|
31
|
+
await clientTransport.close()
|
|
32
|
+
await serverTransport.close()
|
|
33
|
+
|
|
34
|
+
console.log('responseData', JSON.stringify(responseData, null, 2))
|
|
35
|
+
|
|
36
|
+
return Response.json(responseData, {
|
|
37
|
+
headers: {
|
|
38
|
+
'Content-Type': 'application/json',
|
|
39
|
+
},
|
|
40
|
+
})
|
|
41
|
+
} catch (error) {
|
|
42
|
+
console.error('MCP handler error:', error)
|
|
43
|
+
|
|
44
|
+
// Return a JSON-RPC error response
|
|
45
|
+
return Response.json(
|
|
46
|
+
{
|
|
47
|
+
jsonrpc: '2.0',
|
|
48
|
+
error: {
|
|
49
|
+
code: -32603,
|
|
50
|
+
message: 'Internal server error',
|
|
51
|
+
data: error instanceof Error ? error.message : String(error),
|
|
52
|
+
},
|
|
53
|
+
id: null,
|
|
54
|
+
},
|
|
55
|
+
{
|
|
56
|
+
status: 500,
|
|
57
|
+
headers: {
|
|
58
|
+
'Content-Type': 'application/json',
|
|
59
|
+
},
|
|
60
|
+
},
|
|
61
|
+
)
|
|
62
|
+
}
|
|
61
63
|
}
|
|
@@ -19,7 +19,7 @@ const getTodos = createServerFn({
|
|
|
19
19
|
const insertTodo = createServerFn({
|
|
20
20
|
method: 'POST',
|
|
21
21
|
})
|
|
22
|
-
.
|
|
22
|
+
.inputValidator((d: { title: string }) => d)
|
|
23
23
|
.handler(async ({ data }) => {
|
|
24
24
|
const client = await getClient()
|
|
25
25
|
if (!client) {
|
|
@@ -3,7 +3,7 @@ import '@/polyfill'
|
|
|
3
3
|
import { OpenAPIHandler } from '@orpc/openapi/fetch'
|
|
4
4
|
import { ZodToJsonSchemaConverter } from '@orpc/zod/zod4'
|
|
5
5
|
import { experimental_SmartCoercionPlugin as SmartCoercionPlugin } from '@orpc/json-schema'
|
|
6
|
-
import {
|
|
6
|
+
import { createFileRoute } from '@tanstack/react-router'
|
|
7
7
|
import { onError } from '@orpc/server'
|
|
8
8
|
import { OpenAPIReferencePlugin } from '@orpc/openapi/plugins'
|
|
9
9
|
|
|
@@ -63,11 +63,15 @@ async function handle({ request }: { request: Request }) {
|
|
|
63
63
|
return response ?? new Response('Not Found', { status: 404 })
|
|
64
64
|
}
|
|
65
65
|
|
|
66
|
-
export const
|
|
67
|
-
|
|
68
|
-
|
|
69
|
-
|
|
70
|
-
|
|
71
|
-
|
|
72
|
-
|
|
66
|
+
export const Route = createFileRoute('/api/$')({
|
|
67
|
+
server: {
|
|
68
|
+
handlers: {
|
|
69
|
+
HEAD: handle,
|
|
70
|
+
GET: handle,
|
|
71
|
+
POST: handle,
|
|
72
|
+
PUT: handle,
|
|
73
|
+
PATCH: handle,
|
|
74
|
+
DELETE: handle,
|
|
75
|
+
},
|
|
76
|
+
},
|
|
73
77
|
})
|
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
import '@/polyfill'
|
|
2
2
|
|
|
3
3
|
import { RPCHandler } from '@orpc/server/fetch'
|
|
4
|
-
import {
|
|
4
|
+
import { createFileRoute } from '@tanstack/react-router'
|
|
5
5
|
import router from '@/orpc/router'
|
|
6
6
|
|
|
7
7
|
const handler = new RPCHandler(router)
|
|
@@ -15,11 +15,15 @@ async function handle({ request }: { request: Request }) {
|
|
|
15
15
|
return response ?? new Response('Not Found', { status: 404 })
|
|
16
16
|
}
|
|
17
17
|
|
|
18
|
-
export const
|
|
19
|
-
|
|
20
|
-
|
|
21
|
-
|
|
22
|
-
|
|
23
|
-
|
|
24
|
-
|
|
18
|
+
export const Route = createFileRoute('/api/rpc/$')({
|
|
19
|
+
server: {
|
|
20
|
+
handlers: {
|
|
21
|
+
HEAD: handle,
|
|
22
|
+
GET: handle,
|
|
23
|
+
POST: handle,
|
|
24
|
+
PUT: handle,
|
|
25
|
+
PATCH: handle,
|
|
26
|
+
DELETE: handle,
|
|
27
|
+
},
|
|
28
|
+
},
|
|
25
29
|
})
|
|
@@ -1,17 +1,17 @@
|
|
|
1
|
-
import { createRouter
|
|
2
|
-
|
|
3
|
-
|
|
4
|
-
|
|
1
|
+
import { createRouter } from '@tanstack/react-router'<% if (addOnEnabled['tanstack-query']) { %>
|
|
2
|
+
import { setupRouterSsrQueryIntegration } from '@tanstack/react-router-ssr-query'
|
|
3
|
+
import * as TanstackQuery from "./integrations/tanstack-query/root-provider";
|
|
4
|
+
<% } %>
|
|
5
5
|
|
|
6
6
|
// Import the generated route tree
|
|
7
7
|
import { routeTree } from './routeTree.gen'
|
|
8
8
|
|
|
9
9
|
// Create a new router instance
|
|
10
|
-
export const
|
|
10
|
+
export const getRouter = () => {
|
|
11
11
|
<% if (addOnEnabled['tanstack-query']) { %>
|
|
12
12
|
const rqContext = TanstackQuery.getContext();
|
|
13
13
|
|
|
14
|
-
const router =
|
|
14
|
+
const router = createRouter({
|
|
15
15
|
routeTree,
|
|
16
16
|
context: { ...rqContext },
|
|
17
17
|
defaultPreload: "intent",
|
|
@@ -29,17 +29,10 @@ export const createRouter = () => {
|
|
|
29
29
|
return router;
|
|
30
30
|
|
|
31
31
|
<% } else { %>
|
|
32
|
-
return
|
|
32
|
+
return createRouter({
|
|
33
33
|
routeTree,
|
|
34
34
|
scrollRestoration: true,
|
|
35
35
|
defaultPreloadStaleTime: 0,
|
|
36
36
|
})
|
|
37
37
|
<% } %>
|
|
38
38
|
}
|
|
39
|
-
|
|
40
|
-
// Register the router instance for type safety
|
|
41
|
-
declare module '@tanstack/react-router' {
|
|
42
|
-
interface Register {
|
|
43
|
-
router: ReturnType<typeof createRouter>
|
|
44
|
-
}
|
|
45
|
-
}
|
|
@@ -1,11 +1,15 @@
|
|
|
1
|
-
import {
|
|
1
|
+
import { createFileRoute } from '@tanstack/react-router'
|
|
2
2
|
|
|
3
|
-
export const
|
|
4
|
-
|
|
5
|
-
|
|
6
|
-
|
|
7
|
-
'
|
|
3
|
+
export const Route = createFileRoute('/api/demo-names')({
|
|
4
|
+
server: {
|
|
5
|
+
handlers: {
|
|
6
|
+
GET: () => {
|
|
7
|
+
return new Response(JSON.stringify(['Alice', 'Bob', 'Charlie']), {
|
|
8
|
+
headers: {
|
|
9
|
+
'Content-Type': 'application/json',
|
|
10
|
+
},
|
|
11
|
+
})
|
|
8
12
|
},
|
|
9
|
-
}
|
|
13
|
+
},
|
|
10
14
|
},
|
|
11
15
|
})
|
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
<% if (!addOnEnabled['tanstack-query']) { ignoreFile() } %>import {
|
|
1
|
+
<% if (!addOnEnabled['tanstack-query']) { ignoreFile() } %>import { createFileRoute } from '@tanstack/react-router'
|
|
2
2
|
|
|
3
3
|
const todos = [
|
|
4
4
|
{
|
|
@@ -15,17 +15,21 @@ const todos = [
|
|
|
15
15
|
},
|
|
16
16
|
]
|
|
17
17
|
|
|
18
|
-
export const
|
|
19
|
-
|
|
20
|
-
|
|
21
|
-
|
|
22
|
-
|
|
23
|
-
|
|
24
|
-
|
|
25
|
-
|
|
26
|
-
|
|
27
|
-
|
|
28
|
-
|
|
29
|
-
|
|
18
|
+
export const Route = createFileRoute('/api/demo-tq-todos')({
|
|
19
|
+
server: {
|
|
20
|
+
handlers: {
|
|
21
|
+
GET: () => {
|
|
22
|
+
return Response.json(todos)
|
|
23
|
+
},
|
|
24
|
+
POST: async ({ request }) => {
|
|
25
|
+
const name = await request.json()
|
|
26
|
+
const todo = {
|
|
27
|
+
id: todos.length + 1,
|
|
28
|
+
name,
|
|
29
|
+
}
|
|
30
|
+
todos.push(todo)
|
|
31
|
+
return Response.json(todo)
|
|
32
|
+
},
|
|
33
|
+
},
|
|
30
34
|
},
|
|
31
35
|
})
|
|
@@ -25,7 +25,7 @@ const getTodos = createServerFn({
|
|
|
25
25
|
}).handler(async () => await readTodos())
|
|
26
26
|
|
|
27
27
|
const addTodo = createServerFn({ method: 'POST' })
|
|
28
|
-
.
|
|
28
|
+
.inputValidator((d: string) => d)
|
|
29
29
|
.handler(async ({ data }) => {
|
|
30
30
|
const todos = await readTodos()
|
|
31
31
|
todos.push({ id: todos.length + 1, name: data })
|
|
@@ -1,5 +1,6 @@
|
|
|
1
1
|
import { fetchRequestHandler } from '@trpc/server/adapters/fetch'
|
|
2
2
|
import { trpcRouter } from '@/integrations/trpc/router'
|
|
3
|
+
import { createFileRoute } from '@tanstack/react-router'
|
|
3
4
|
|
|
4
5
|
function handler({ request }: { request: Request }) {
|
|
5
6
|
return fetchRequestHandler({
|
|
@@ -9,7 +10,11 @@ function handler({ request }: { request: Request }) {
|
|
|
9
10
|
})
|
|
10
11
|
}
|
|
11
12
|
|
|
12
|
-
export const
|
|
13
|
-
|
|
14
|
-
|
|
13
|
+
export const Route = createFileRoute('/api/trpc/$')({
|
|
14
|
+
server: {
|
|
15
|
+
handlers: {
|
|
16
|
+
GET: handler,
|
|
17
|
+
POST: handler,
|
|
18
|
+
},
|
|
19
|
+
},
|
|
15
20
|
})
|
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import {
|
|
1
|
+
import { createFileRoute } from '@tanstack/react-router'
|
|
2
2
|
import { anthropic } from '@ai-sdk/anthropic'
|
|
3
3
|
import { convertToModelMessages, stepCountIs, streamText } from 'ai'
|
|
4
4
|
|
|
@@ -12,32 +12,36 @@ You can use the following tools to help the user:
|
|
|
12
12
|
- recommendGuitar: Recommend a guitar to the user
|
|
13
13
|
`
|
|
14
14
|
|
|
15
|
-
export const
|
|
16
|
-
|
|
17
|
-
|
|
18
|
-
|
|
19
|
-
|
|
20
|
-
|
|
21
|
-
|
|
22
|
-
|
|
23
|
-
|
|
24
|
-
|
|
25
|
-
|
|
26
|
-
|
|
27
|
-
|
|
28
|
-
|
|
29
|
-
|
|
30
|
-
|
|
31
|
-
|
|
32
|
-
|
|
33
|
-
|
|
34
|
-
|
|
35
|
-
|
|
36
|
-
|
|
37
|
-
|
|
38
|
-
|
|
39
|
-
|
|
40
|
-
|
|
41
|
-
|
|
15
|
+
export const Route = createFileRoute('/api/demo-chat')({
|
|
16
|
+
server: {
|
|
17
|
+
handlers: {
|
|
18
|
+
POST: async ({ request }) => {
|
|
19
|
+
try {
|
|
20
|
+
const { messages } = await request.json()
|
|
21
|
+
|
|
22
|
+
const tools = await getTools()
|
|
23
|
+
|
|
24
|
+
const result = await streamText({
|
|
25
|
+
model: anthropic('claude-3-5-sonnet-latest'),
|
|
26
|
+
messages: convertToModelMessages(messages),
|
|
27
|
+
temperature: 0.7,
|
|
28
|
+
stopWhen: stepCountIs(5),
|
|
29
|
+
system: SYSTEM_PROMPT,
|
|
30
|
+
tools,
|
|
31
|
+
})
|
|
32
|
+
|
|
33
|
+
return result.toUIMessageStreamResponse()
|
|
34
|
+
} catch (error) {
|
|
35
|
+
console.error('Chat API error:', error)
|
|
36
|
+
return new Response(
|
|
37
|
+
JSON.stringify({ error: 'Failed to process chat request' }),
|
|
38
|
+
{
|
|
39
|
+
status: 500,
|
|
40
|
+
headers: { 'Content-Type': 'application/json' },
|
|
41
|
+
},
|
|
42
|
+
)
|
|
43
|
+
}
|
|
44
|
+
},
|
|
45
|
+
},
|
|
42
46
|
},
|
|
43
47
|
})
|