@lantos1618/better-ui 0.2.3 β 0.3.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/README.md +183 -367
- package/dist/index.d.mts +314 -0
- package/dist/index.d.ts +314 -0
- package/dist/index.js +522 -0
- package/dist/index.mjs +491 -0
- package/package.json +59 -26
- package/lib/aui/README.md +0 -136
- package/lib/aui/__tests__/aui-complete.test.ts +0 -251
- package/lib/aui/__tests__/aui-comprehensive.test.ts +0 -376
- package/lib/aui/__tests__/aui-concise.test.ts +0 -278
- package/lib/aui/__tests__/aui-integration.test.ts +0 -309
- package/lib/aui/__tests__/aui-simple.test.ts +0 -116
- package/lib/aui/__tests__/aui.test.ts +0 -269
- package/lib/aui/__tests__/concise-api.test.ts +0 -165
- package/lib/aui/__tests__/core.test.ts +0 -265
- package/lib/aui/__tests__/simple-api.test.ts +0 -200
- package/lib/aui/ai-assistant.ts +0 -408
- package/lib/aui/ai-control.ts +0 -353
- package/lib/aui/client/use-aui.ts +0 -55
- package/lib/aui/client-control.ts +0 -551
- package/lib/aui/client-executor.ts +0 -417
- package/lib/aui/components/ToolRenderer.tsx +0 -22
- package/lib/aui/core.ts +0 -137
- package/lib/aui/demo.tsx +0 -89
- package/lib/aui/examples/ai-complete-demo.tsx +0 -359
- package/lib/aui/examples/ai-control-demo.tsx +0 -356
- package/lib/aui/examples/ai-control-tools.ts +0 -308
- package/lib/aui/examples/concise-api.tsx +0 -153
- package/lib/aui/examples/index.tsx +0 -163
- package/lib/aui/examples/quick-demo.tsx +0 -91
- package/lib/aui/examples/simple-demo.tsx +0 -71
- package/lib/aui/examples/simple-tools.tsx +0 -160
- package/lib/aui/examples/user-api.tsx +0 -208
- package/lib/aui/examples/user-requested.tsx +0 -174
- package/lib/aui/examples/weather-search-tools.tsx +0 -119
- package/lib/aui/examples.tsx +0 -367
- package/lib/aui/hooks/useAUITool.ts +0 -142
- package/lib/aui/hooks/useAUIToolEnhanced.ts +0 -343
- package/lib/aui/hooks/useAUITools.ts +0 -195
- package/lib/aui/index.ts +0 -156
- package/lib/aui/provider.tsx +0 -45
- package/lib/aui/server-control.ts +0 -386
- package/lib/aui/server-executor.ts +0 -165
- package/lib/aui/server.ts +0 -167
- package/lib/aui/tool-registry.ts +0 -380
- package/lib/aui/tools/advanced-examples.tsx +0 -86
- package/lib/aui/tools/ai-complete.ts +0 -375
- package/lib/aui/tools/api-tools.tsx +0 -230
- package/lib/aui/tools/data-tools.tsx +0 -232
- package/lib/aui/tools/dom-tools.tsx +0 -202
- package/lib/aui/tools/examples.ts +0 -43
- package/lib/aui/tools/file-tools.tsx +0 -202
- package/lib/aui/tools/form-tools.tsx +0 -233
- package/lib/aui/tools/index.ts +0 -8
- package/lib/aui/tools/navigation-tools.tsx +0 -172
- package/lib/aui/tools/notification-tools.ts +0 -213
- package/lib/aui/tools/state-tools.tsx +0 -209
- package/lib/aui/types.ts +0 -47
- package/lib/aui/vercel-ai.ts +0 -100
package/README.md
CHANGED
|
@@ -1,262 +1,148 @@
|
|
|
1
|
-
# Better UI
|
|
1
|
+
# Better UI
|
|
2
2
|
|
|
3
|
-
> A
|
|
3
|
+
> A minimal, type-safe AI-first UI framework for building tools
|
|
4
4
|
|
|
5
5
|
[](https://www.npmjs.com/package/@lantos1618/better-ui)
|
|
6
6
|
[](LICENSE)
|
|
7
7
|
[](https://www.typescriptlang.org/)
|
|
8
|
-
[](https://nextjs.org/)
|
|
9
8
|
|
|
10
|
-
##
|
|
9
|
+
## What is Better UI?
|
|
11
10
|
|
|
12
|
-
Better UI
|
|
11
|
+
Better UI provides a clean, fluent API for creating tools that AI assistants can execute. Define input/output schemas with Zod, implement server and client logic separately, and render results with React components.
|
|
13
12
|
|
|
14
|
-
|
|
13
|
+
**Key differentiator**: Unlike other AI tool libraries, Better UI includes **view integration** - tools can render their own results in UI.
|
|
15
14
|
|
|
16
|
-
|
|
17
|
-
- **π Type Safety**: Full TypeScript + Zod schema validation
|
|
18
|
-
- **π¨ AI-Native**: Built specifically for AI assistants to control applications
|
|
19
|
-
- **β‘ Performance**: Smart client-side caching and optimization
|
|
20
|
-
- **π§ Extensible**: Easy to create custom tools for any use case
|
|
21
|
-
|
|
22
|
-
## π¦ Installation
|
|
15
|
+
## Installation
|
|
23
16
|
|
|
24
17
|
```bash
|
|
25
|
-
npm install @lantos1618/better-ui
|
|
26
|
-
# or
|
|
27
|
-
yarn add @lantos1618/better-ui
|
|
28
|
-
# or
|
|
29
|
-
bun add @lantos1618/better-ui
|
|
18
|
+
npm install @lantos1618/better-ui zod
|
|
30
19
|
```
|
|
31
20
|
|
|
32
|
-
##
|
|
33
|
-
|
|
34
|
-
### 1. Simple Tool (2 methods only!)
|
|
21
|
+
## Quick Start
|
|
35
22
|
|
|
36
|
-
```
|
|
37
|
-
import {
|
|
23
|
+
```typescript
|
|
24
|
+
import { tool } from '@lantos1618/better-ui';
|
|
38
25
|
import { z } from 'zod';
|
|
39
26
|
|
|
40
|
-
const
|
|
41
|
-
|
|
42
|
-
|
|
43
|
-
|
|
44
|
-
.
|
|
45
|
-
|
|
27
|
+
const weather = tool({
|
|
28
|
+
name: 'weather',
|
|
29
|
+
description: 'Get weather for a city',
|
|
30
|
+
input: z.object({ city: z.string() }),
|
|
31
|
+
output: z.object({ temp: z.number(), condition: z.string() }),
|
|
32
|
+
});
|
|
46
33
|
|
|
47
|
-
|
|
34
|
+
// Server implementation (runs on server)
|
|
35
|
+
weather.server(async ({ city }) => {
|
|
36
|
+
const data = await weatherAPI.get(city);
|
|
37
|
+
return { temp: data.temp, condition: data.condition };
|
|
38
|
+
});
|
|
48
39
|
|
|
49
|
-
|
|
50
|
-
|
|
51
|
-
|
|
52
|
-
|
|
53
|
-
|
|
54
|
-
|
|
55
|
-
|
|
56
|
-
const cached = ctx.cache.get(input.query);
|
|
57
|
-
return cached || ctx.fetch('/api/tools/search', { body: input });
|
|
58
|
-
})
|
|
59
|
-
.render(({ data }) => <SearchResults results={data} />);
|
|
40
|
+
// View for rendering results (our differentiator!)
|
|
41
|
+
weather.view((data) => (
|
|
42
|
+
<div className="weather-card">
|
|
43
|
+
<span>{data.temp}Β°</span>
|
|
44
|
+
<span>{data.condition}</span>
|
|
45
|
+
</div>
|
|
46
|
+
));
|
|
60
47
|
```
|
|
61
48
|
|
|
62
|
-
##
|
|
49
|
+
## Core Concepts
|
|
63
50
|
|
|
64
|
-
|
|
51
|
+
### 1. Tool Definition
|
|
65
52
|
|
|
66
|
-
|
|
53
|
+
```typescript
|
|
54
|
+
const myTool = tool({
|
|
55
|
+
name: 'myTool',
|
|
56
|
+
description: 'What this tool does',
|
|
57
|
+
input: z.object({ /* input schema */ }),
|
|
58
|
+
output: z.object({ /* output schema */ }),
|
|
59
|
+
tags: ['category', 'type'],
|
|
60
|
+
cache: { ttl: 60000 }, // optional caching
|
|
61
|
+
});
|
|
62
|
+
```
|
|
67
63
|
|
|
68
|
-
|
|
69
|
-
// app/api/chat/route.ts
|
|
70
|
-
import { openai } from '@ai-sdk/openai';
|
|
71
|
-
import { streamText, convertToCoreMessages } from 'ai';
|
|
72
|
-
import { aui } from '@lantos1618/better-ui';
|
|
73
|
-
import { z } from 'zod';
|
|
64
|
+
### 2. Server Implementation
|
|
74
65
|
|
|
75
|
-
|
|
76
|
-
const weatherTool = aui
|
|
77
|
-
.tool('getWeather')
|
|
78
|
-
.description('Get current weather for a city')
|
|
79
|
-
.input(z.object({
|
|
80
|
-
city: z.string().describe('City name'),
|
|
81
|
-
unit: z.enum(['celsius', 'fahrenheit']).optional()
|
|
82
|
-
}))
|
|
83
|
-
.execute(async ({ input }) => {
|
|
84
|
-
// Fetch real weather data
|
|
85
|
-
const response = await fetch(`https://api.weather.com/v1/weather?city=${input.city}`);
|
|
86
|
-
return response.json();
|
|
87
|
-
});
|
|
66
|
+
The `.server()` method defines logic that runs on the server (API routes, server components):
|
|
88
67
|
|
|
89
|
-
|
|
90
|
-
|
|
91
|
-
|
|
92
|
-
.
|
|
93
|
-
|
|
94
|
-
|
|
95
|
-
|
|
96
|
-
const response = await fetch(`https://api.stocks.com/v1/quote/${input.symbol}`);
|
|
97
|
-
return response.json();
|
|
98
|
-
});
|
|
68
|
+
```typescript
|
|
69
|
+
myTool.server(async ({ query }, ctx) => {
|
|
70
|
+
// Direct access to databases, secrets, file system
|
|
71
|
+
const results = await db.search(query);
|
|
72
|
+
return { results };
|
|
73
|
+
});
|
|
74
|
+
```
|
|
99
75
|
|
|
100
|
-
|
|
101
|
-
const tools = {
|
|
102
|
-
getWeather: weatherTool.toAISDKTool(),
|
|
103
|
-
getStockPrice: stockTool.toAISDKTool(),
|
|
104
|
-
};
|
|
76
|
+
### 3. Client Implementation (Optional)
|
|
105
77
|
|
|
106
|
-
|
|
107
|
-
const { messages } = await req.json();
|
|
78
|
+
The `.client()` method defines what happens when called from the browser. If not specified, auto-fetches to `/api/tools/execute`.
|
|
108
79
|
|
|
109
|
-
|
|
110
|
-
|
|
111
|
-
|
|
112
|
-
|
|
113
|
-
|
|
80
|
+
```typescript
|
|
81
|
+
myTool.client(async ({ query }, ctx) => {
|
|
82
|
+
// Custom client logic: caching, optimistic updates, etc.
|
|
83
|
+
const cached = ctx.cache.get(query);
|
|
84
|
+
if (cached) return cached;
|
|
85
|
+
|
|
86
|
+
return ctx.fetch('/api/search', {
|
|
87
|
+
method: 'POST',
|
|
88
|
+
body: JSON.stringify({ query })
|
|
114
89
|
});
|
|
115
|
-
|
|
116
|
-
return result.toDataStreamResponse();
|
|
117
|
-
}
|
|
90
|
+
});
|
|
118
91
|
```
|
|
119
92
|
|
|
120
|
-
###
|
|
93
|
+
### 4. View (Our Differentiator)
|
|
121
94
|
|
|
122
|
-
|
|
123
|
-
// app/chat/page.tsx
|
|
124
|
-
'use client';
|
|
95
|
+
The `.view()` method defines how to render the tool's results:
|
|
125
96
|
|
|
126
|
-
|
|
127
|
-
|
|
97
|
+
```typescript
|
|
98
|
+
myTool.view((data, { loading, error }) => {
|
|
99
|
+
if (loading) return <Spinner />;
|
|
100
|
+
if (error) return <Error message={error.message} />;
|
|
101
|
+
return <Results items={data.results} />;
|
|
102
|
+
});
|
|
103
|
+
```
|
|
128
104
|
|
|
129
|
-
|
|
130
|
-
const { messages, input, handleInputChange, handleSubmit } = useChat();
|
|
105
|
+
## Fluent Builder Alternative
|
|
131
106
|
|
|
132
|
-
|
|
133
|
-
|
|
134
|
-
|
|
135
|
-
|
|
136
|
-
|
|
137
|
-
|
|
138
|
-
|
|
139
|
-
<div>{message.content}</div>
|
|
140
|
-
|
|
141
|
-
{/* Render tool calls with Better UI */}
|
|
142
|
-
{message.toolInvocations?.map((toolCall) => (
|
|
143
|
-
<ToolRenderer
|
|
144
|
-
key={toolCall.toolCallId}
|
|
145
|
-
toolCall={toolCall}
|
|
146
|
-
tool={tools[toolCall.toolName]}
|
|
147
|
-
/>
|
|
148
|
-
))}
|
|
149
|
-
</div>
|
|
150
|
-
))}
|
|
151
|
-
</div>
|
|
152
|
-
|
|
153
|
-
<form onSubmit={handleSubmit} className="p-4 border-t">
|
|
154
|
-
<input
|
|
155
|
-
value={input}
|
|
156
|
-
onChange={handleInputChange}
|
|
157
|
-
placeholder="Ask about weather or stocks..."
|
|
158
|
-
className="w-full p-2 border rounded"
|
|
159
|
-
/>
|
|
160
|
-
</form>
|
|
161
|
-
</div>
|
|
162
|
-
</ToolExecutorProvider>
|
|
163
|
-
);
|
|
164
|
-
}
|
|
107
|
+
```typescript
|
|
108
|
+
const search = tool('search')
|
|
109
|
+
.description('Search the database')
|
|
110
|
+
.input(z.object({ query: z.string() }))
|
|
111
|
+
.output(z.object({ results: z.array(z.string()) }))
|
|
112
|
+
.server(async ({ query }) => ({ results: await db.search(query) }))
|
|
113
|
+
.view((data) => <ResultsList items={data.results} />);
|
|
165
114
|
```
|
|
166
115
|
|
|
167
|
-
|
|
116
|
+
## React Usage
|
|
168
117
|
|
|
169
|
-
```
|
|
170
|
-
|
|
171
|
-
import { aui } from '@lantos1618/better-ui';
|
|
172
|
-
import { z } from 'zod';
|
|
118
|
+
```typescript
|
|
119
|
+
import { useTool } from '@lantos1618/better-ui';
|
|
173
120
|
|
|
174
|
-
|
|
175
|
-
|
|
176
|
-
|
|
177
|
-
|
|
178
|
-
|
|
179
|
-
|
|
180
|
-
|
|
181
|
-
|
|
182
|
-
|
|
183
|
-
start: z.string().optional(),
|
|
184
|
-
end: z.string().optional(),
|
|
185
|
-
}).optional(),
|
|
186
|
-
}).optional(),
|
|
187
|
-
}))
|
|
188
|
-
.execute(async ({ input }) => {
|
|
189
|
-
// Your database logic
|
|
190
|
-
return await db.search(input.query, input.filters);
|
|
191
|
-
})
|
|
192
|
-
.clientExecute(async ({ input, ctx }) => {
|
|
193
|
-
// Client-side caching
|
|
194
|
-
const cacheKey = JSON.stringify(input);
|
|
195
|
-
const cached = ctx.cache.get(cacheKey);
|
|
196
|
-
if (cached && Date.now() - cached.timestamp < 60000) {
|
|
197
|
-
return cached.data;
|
|
198
|
-
}
|
|
199
|
-
|
|
200
|
-
const result = await ctx.fetch('/api/search', {
|
|
201
|
-
method: 'POST',
|
|
202
|
-
body: JSON.stringify(input)
|
|
203
|
-
});
|
|
204
|
-
|
|
205
|
-
ctx.cache.set(cacheKey, { data: result, timestamp: Date.now() });
|
|
206
|
-
return result;
|
|
207
|
-
})
|
|
208
|
-
.render(({ data }) => (
|
|
209
|
-
<div className="grid gap-2">
|
|
210
|
-
{data.results.map((item) => (
|
|
211
|
-
<div key={item.id} className="p-2 border rounded">
|
|
212
|
-
<h3>{item.title}</h3>
|
|
213
|
-
<p>{item.description}</p>
|
|
214
|
-
</div>
|
|
215
|
-
))}
|
|
121
|
+
function WeatherWidget({ city }) {
|
|
122
|
+
const { data, loading, error, execute } = useTool(weather);
|
|
123
|
+
|
|
124
|
+
return (
|
|
125
|
+
<div>
|
|
126
|
+
<button onClick={() => execute({ city })}>Get Weather</button>
|
|
127
|
+
{loading && <Spinner />}
|
|
128
|
+
{error && <div>Error: {error.message}</div>}
|
|
129
|
+
{data && <weather.View data={data} />}
|
|
216
130
|
</div>
|
|
217
|
-
)
|
|
218
|
-
|
|
219
|
-
|
|
220
|
-
|
|
221
|
-
|
|
222
|
-
|
|
223
|
-
.
|
|
224
|
-
|
|
225
|
-
data: z.array(z.object({
|
|
226
|
-
label: z.string(),
|
|
227
|
-
value: z.number(),
|
|
228
|
-
})),
|
|
229
|
-
title: z.string().optional(),
|
|
230
|
-
}))
|
|
231
|
-
.execute(async ({ input }) => input)
|
|
232
|
-
.render(({ data }) => (
|
|
233
|
-
<ChartComponent type={data.type} data={data.data} title={data.title} />
|
|
234
|
-
));
|
|
235
|
-
|
|
236
|
-
// Form generation tool
|
|
237
|
-
export const generateFormTool = aui
|
|
238
|
-
.tool('generateForm')
|
|
239
|
-
.description('Create dynamic forms')
|
|
240
|
-
.input(z.object({
|
|
241
|
-
fields: z.array(z.object({
|
|
242
|
-
name: z.string(),
|
|
243
|
-
type: z.enum(['text', 'number', 'email', 'select', 'checkbox']),
|
|
244
|
-
label: z.string(),
|
|
245
|
-
required: z.boolean().optional(),
|
|
246
|
-
options: z.array(z.string()).optional(),
|
|
247
|
-
})),
|
|
248
|
-
submitUrl: z.string(),
|
|
249
|
-
}))
|
|
250
|
-
.execute(async ({ input }) => input)
|
|
251
|
-
.render(({ data }) => (
|
|
252
|
-
<DynamicForm fields={data.fields} submitUrl={data.submitUrl} />
|
|
253
|
-
));
|
|
131
|
+
);
|
|
132
|
+
}
|
|
133
|
+
|
|
134
|
+
// Or with auto-execution
|
|
135
|
+
function WeatherWidget({ city }) {
|
|
136
|
+
const { data, loading } = useTool(weather, { city }, { auto: true });
|
|
137
|
+
return <weather.View data={data} loading={loading} />;
|
|
138
|
+
}
|
|
254
139
|
```
|
|
255
140
|
|
|
256
|
-
|
|
141
|
+
## AI Integration
|
|
142
|
+
|
|
143
|
+
### With Vercel AI SDK
|
|
257
144
|
|
|
258
|
-
```
|
|
259
|
-
// app/api/chat/route.ts
|
|
145
|
+
```typescript
|
|
260
146
|
import { streamText } from 'ai';
|
|
261
147
|
import { openai } from '@ai-sdk/openai';
|
|
262
148
|
|
|
@@ -267,15 +153,8 @@ export async function POST(req: Request) {
|
|
|
267
153
|
model: openai('gpt-4'),
|
|
268
154
|
messages,
|
|
269
155
|
tools: {
|
|
270
|
-
|
|
271
|
-
|
|
272
|
-
generateForm: generateFormTool.toAISDKTool(),
|
|
273
|
-
},
|
|
274
|
-
toolChoice: 'auto', // Let AI decide when to use tools
|
|
275
|
-
async onToolCall({ toolCall, toolResult }) {
|
|
276
|
-
// Log tool usage for analytics
|
|
277
|
-
console.log(`Tool ${toolCall.toolName} called with:`, toolCall.args);
|
|
278
|
-
console.log(`Result:`, toolResult);
|
|
156
|
+
weather: weather.toAITool(),
|
|
157
|
+
search: search.toAITool(),
|
|
279
158
|
},
|
|
280
159
|
});
|
|
281
160
|
|
|
@@ -283,175 +162,112 @@ export async function POST(req: Request) {
|
|
|
283
162
|
}
|
|
284
163
|
```
|
|
285
164
|
|
|
286
|
-
##
|
|
287
|
-
|
|
288
|
-
Better UI comes with a comprehensive set of pre-built tools:
|
|
165
|
+
## API Reference
|
|
289
166
|
|
|
290
|
-
###
|
|
291
|
-
- `clickTool` - Click elements on the page
|
|
292
|
-
- `typeTool` - Type text into inputs
|
|
293
|
-
- `scrollTool` - Scroll to elements
|
|
294
|
-
- `selectTool` - Select dropdown options
|
|
167
|
+
### `tool(config)` or `tool(name)`
|
|
295
168
|
|
|
296
|
-
|
|
297
|
-
- `fetchTool` - Make HTTP requests
|
|
298
|
-
- `graphqlTool` - Execute GraphQL queries
|
|
169
|
+
Create a new tool with object config or fluent builder.
|
|
299
170
|
|
|
300
|
-
|
|
301
|
-
|
|
302
|
-
|
|
303
|
-
|
|
304
|
-
|
|
305
|
-
|
|
306
|
-
|
|
171
|
+
```typescript
|
|
172
|
+
// Object config
|
|
173
|
+
const t = tool({
|
|
174
|
+
name: string,
|
|
175
|
+
description?: string,
|
|
176
|
+
input: ZodSchema,
|
|
177
|
+
output?: ZodSchema,
|
|
178
|
+
tags?: string[],
|
|
179
|
+
cache?: { ttl: number, key?: (input) => string },
|
|
180
|
+
});
|
|
307
181
|
|
|
308
|
-
|
|
309
|
-
|
|
310
|
-
|
|
182
|
+
// Fluent builder
|
|
183
|
+
const t = tool('name')
|
|
184
|
+
.description(string)
|
|
185
|
+
.input(ZodSchema)
|
|
186
|
+
.output(ZodSchema)
|
|
187
|
+
.tags(...string[])
|
|
188
|
+
.cache({ ttl, key? });
|
|
189
|
+
```
|
|
311
190
|
|
|
312
|
-
|
|
191
|
+
### `.server(handler)`
|
|
313
192
|
|
|
314
|
-
|
|
193
|
+
Define server-side implementation.
|
|
315
194
|
|
|
316
195
|
```typescript
|
|
317
|
-
|
|
318
|
-
.
|
|
319
|
-
|
|
320
|
-
|
|
321
|
-
.input(schema: ZodSchema) // Input validation schema
|
|
322
|
-
.execute(handler: ExecuteHandler) // Server-side logic (required)
|
|
323
|
-
.clientExecute(handler: ClientHandler) // Client-side logic (optional)
|
|
324
|
-
.render(component: RenderFunction) // React component (optional)
|
|
325
|
-
.stream(handler: StreamHandler) // Streaming support (optional)
|
|
196
|
+
t.server(async (input, ctx) => {
|
|
197
|
+
// ctx.env, ctx.headers, ctx.user, ctx.session available
|
|
198
|
+
return result;
|
|
199
|
+
});
|
|
326
200
|
```
|
|
327
201
|
|
|
328
|
-
###
|
|
329
|
-
|
|
330
|
-
```tsx
|
|
331
|
-
// Provider for tool execution
|
|
332
|
-
<ToolExecutorProvider tools={tools}>
|
|
333
|
-
<App />
|
|
334
|
-
</ToolExecutorProvider>
|
|
202
|
+
### `.client(handler)`
|
|
335
203
|
|
|
336
|
-
|
|
337
|
-
<ToolRenderer toolCall={toolCall} tool={tool} />
|
|
338
|
-
|
|
339
|
-
// Hook for manual execution
|
|
340
|
-
const executor = useToolExecutor();
|
|
341
|
-
const result = await executor.execute(toolCall);
|
|
342
|
-
|
|
343
|
-
// Hook for tool discovery
|
|
344
|
-
const tools = useToolRegistry();
|
|
345
|
-
const weatherTools = tools.getByTag('weather');
|
|
346
|
-
```
|
|
347
|
-
|
|
348
|
-
### AI Assistant Integration
|
|
204
|
+
Define client-side implementation (optional).
|
|
349
205
|
|
|
350
206
|
```typescript
|
|
351
|
-
|
|
352
|
-
|
|
353
|
-
|
|
354
|
-
model: 'gpt-4',
|
|
355
|
-
tools: [weatherTool, searchTool],
|
|
356
|
-
systemPrompt: 'You are a helpful assistant.',
|
|
207
|
+
t.client(async (input, ctx) => {
|
|
208
|
+
// ctx.cache, ctx.fetch, ctx.optimistic available
|
|
209
|
+
return result;
|
|
357
210
|
});
|
|
358
|
-
|
|
359
|
-
const response = await assistant.chat('What\'s the weather in NYC?');
|
|
360
|
-
```
|
|
361
|
-
|
|
362
|
-
## ποΈ Architecture
|
|
363
|
-
|
|
364
|
-
```
|
|
365
|
-
ββββββββββββββββ ββββββββββββββββ ββββββββββββββββ
|
|
366
|
-
β AI Model ββββββΆβ AUI System ββββββΆβ Your App β
|
|
367
|
-
β (GPT, etc) β β β β β
|
|
368
|
-
ββββββββββββββββ ββββββββββββββββ ββββββββββββββββ
|
|
369
|
-
β β β
|
|
370
|
-
βΌ βΌ βΌ
|
|
371
|
-
Tool Calls Tool Registry Tool Execution
|
|
372
|
-
Type Validation React Rendering
|
|
373
|
-
Client/Server Split State Management
|
|
374
211
|
```
|
|
375
212
|
|
|
376
|
-
|
|
377
|
-
|
|
378
|
-
```bash
|
|
379
|
-
# Run all tests
|
|
380
|
-
npm test
|
|
381
|
-
|
|
382
|
-
# Run with coverage
|
|
383
|
-
npm run test:coverage
|
|
213
|
+
### `.view(component)`
|
|
384
214
|
|
|
385
|
-
|
|
386
|
-
npm run type-check
|
|
215
|
+
Define React component for rendering results.
|
|
387
216
|
|
|
388
|
-
|
|
389
|
-
|
|
217
|
+
```typescript
|
|
218
|
+
t.view((data, { loading, error }) => <Component data={data} />);
|
|
390
219
|
```
|
|
391
220
|
|
|
392
|
-
|
|
393
|
-
|
|
394
|
-
### Vercel Deployment
|
|
221
|
+
### `useTool(tool, input?, options?)`
|
|
395
222
|
|
|
396
|
-
|
|
397
|
-
# Install Vercel CLI
|
|
398
|
-
npm i -g vercel
|
|
399
|
-
|
|
400
|
-
# Deploy
|
|
401
|
-
vercel
|
|
223
|
+
React hook for executing tools.
|
|
402
224
|
|
|
403
|
-
|
|
404
|
-
|
|
225
|
+
```typescript
|
|
226
|
+
const {
|
|
227
|
+
data, // Result data
|
|
228
|
+
loading, // Loading state
|
|
229
|
+
error, // Error if any
|
|
230
|
+
execute, // Execute function
|
|
231
|
+
reset, // Reset state
|
|
232
|
+
executed, // Has been executed
|
|
233
|
+
} = useTool(myTool, initialInput, {
|
|
234
|
+
auto: false, // Auto-execute on mount
|
|
235
|
+
onSuccess: (data) => {},
|
|
236
|
+
onError: (error) => {},
|
|
237
|
+
});
|
|
405
238
|
```
|
|
406
239
|
|
|
407
|
-
|
|
408
|
-
|
|
409
|
-
```env
|
|
410
|
-
# Required for AI features
|
|
411
|
-
OPENAI_API_KEY=your_api_key
|
|
240
|
+
## Project Structure
|
|
412
241
|
|
|
413
|
-
|
|
414
|
-
|
|
415
|
-
|
|
242
|
+
```
|
|
243
|
+
src/
|
|
244
|
+
tool.tsx # Core tool() API
|
|
245
|
+
react/
|
|
246
|
+
useTool.ts # React hook
|
|
247
|
+
index.ts # Main exports
|
|
248
|
+
|
|
249
|
+
app/
|
|
250
|
+
demo/ # Demo page
|
|
251
|
+
api/chat/ # Chat API route
|
|
252
|
+
api/tools/ # Tool execution API
|
|
253
|
+
|
|
254
|
+
lib/
|
|
255
|
+
tools.tsx # Example tool definitions
|
|
256
|
+
|
|
257
|
+
docs/
|
|
258
|
+
API_V2.md # Full API documentation
|
|
416
259
|
```
|
|
417
260
|
|
|
418
|
-
##
|
|
419
|
-
|
|
420
|
-
Check out our example applications:
|
|
421
|
-
|
|
422
|
-
- [Chat Application](./examples/chat-app) - Full chat UI with tool execution
|
|
423
|
-
- [Dashboard](./examples/dashboard) - Analytics dashboard with AI controls
|
|
424
|
-
- [Form Builder](./examples/form-builder) - Dynamic form generation
|
|
425
|
-
- [Data Explorer](./examples/data-explorer) - Database exploration tool
|
|
426
|
-
|
|
427
|
-
## π€ Contributing
|
|
428
|
-
|
|
429
|
-
We welcome contributions! Please see our [Contributing Guide](CONTRIBUTING.md) for details.
|
|
430
|
-
|
|
431
|
-
1. Fork the repository
|
|
432
|
-
2. Create your feature branch (`git checkout -b feature/amazing-feature`)
|
|
433
|
-
3. Commit your changes (`git commit -m 'Add amazing feature'`)
|
|
434
|
-
4. Push to the branch (`git push origin feature/amazing-feature`)
|
|
435
|
-
5. Open a Pull Request
|
|
436
|
-
|
|
437
|
-
## π License
|
|
438
|
-
|
|
439
|
-
MIT License - see [LICENSE](LICENSE) for details.
|
|
440
|
-
|
|
441
|
-
## π Acknowledgments
|
|
442
|
-
|
|
443
|
-
Built with:
|
|
444
|
-
- [Next.js](https://nextjs.org/) - The React framework
|
|
445
|
-
- [TypeScript](https://www.typescriptlang.org/) - Type safety
|
|
446
|
-
- [Zod](https://zod.dev/) - Schema validation
|
|
447
|
-
- [Vercel AI SDK](https://sdk.vercel.ai/) - AI integration
|
|
448
|
-
|
|
449
|
-
## π Support
|
|
261
|
+
## Development
|
|
450
262
|
|
|
451
|
-
|
|
452
|
-
|
|
453
|
-
|
|
263
|
+
```bash
|
|
264
|
+
npm install
|
|
265
|
+
npm run dev # Run dev server
|
|
266
|
+
npm run build:lib # Build library
|
|
267
|
+
npm run build # Build everything
|
|
268
|
+
npm run type-check # TypeScript check
|
|
269
|
+
```
|
|
454
270
|
|
|
455
|
-
|
|
271
|
+
## License
|
|
456
272
|
|
|
457
|
-
|
|
273
|
+
MIT
|