@lantos1618/better-ui 0.2.2 → 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 +231 -148
- 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 -20
- 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,190 +1,273 @@
|
|
|
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
|
+
[](LICENSE)
|
|
7
|
+
[](https://www.typescriptlang.org/)
|
|
6
8
|
|
|
7
|
-
|
|
8
|
-
// Simple tool - just 2 methods
|
|
9
|
-
const simpleTool = aui
|
|
10
|
-
.tool('weather')
|
|
11
|
-
.input(z.object({ city: z.string() }))
|
|
12
|
-
.execute(async ({ input }) => ({ temp: 72, city: input.city }))
|
|
13
|
-
.render(({ data }) => <div>{data.city}: {data.temp}°</div>);
|
|
9
|
+
## What is Better UI?
|
|
14
10
|
|
|
15
|
-
|
|
16
|
-
const complexTool = aui
|
|
17
|
-
.tool('search')
|
|
18
|
-
.input(z.object({ query: z.string() }))
|
|
19
|
-
.execute(async ({ input }) => db.search(input.query))
|
|
20
|
-
.clientExecute(async ({ input, ctx }) => {
|
|
21
|
-
// Only when you need caching, offline, etc.
|
|
22
|
-
const cached = ctx.cache.get(input.query);
|
|
23
|
-
return cached || ctx.fetch('/api/tools/search', { body: input });
|
|
24
|
-
})
|
|
25
|
-
.render(({ data }) => <SearchResults results={data} />);
|
|
26
|
-
```
|
|
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.
|
|
27
12
|
|
|
28
|
-
|
|
13
|
+
**Key differentiator**: Unlike other AI tool libraries, Better UI includes **view integration** - tools can render their own results in UI.
|
|
29
14
|
|
|
30
|
-
|
|
31
|
-
- **Type Safety**: Full TypeScript support with Zod schemas
|
|
32
|
-
- **Minimal Boilerplate**: Only `input()` and `execute()` are required
|
|
33
|
-
- **Dual Execution**: Server-side execution with optional client-side optimization
|
|
34
|
-
- **React Integration**: Seamless rendering of tool results
|
|
35
|
-
- **AI-Ready**: Designed for AI assistants to control UI/backend
|
|
15
|
+
## Installation
|
|
36
16
|
|
|
37
|
-
|
|
17
|
+
```bash
|
|
18
|
+
npm install @lantos1618/better-ui zod
|
|
19
|
+
```
|
|
38
20
|
|
|
21
|
+
## Quick Start
|
|
22
|
+
|
|
23
|
+
```typescript
|
|
24
|
+
import { tool } from '@lantos1618/better-ui';
|
|
25
|
+
import { z } from 'zod';
|
|
26
|
+
|
|
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
|
+
});
|
|
33
|
+
|
|
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
|
+
});
|
|
39
|
+
|
|
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
|
+
));
|
|
39
47
|
```
|
|
40
|
-
|
|
41
|
-
|
|
42
|
-
|
|
43
|
-
|
|
44
|
-
|
|
45
|
-
|
|
46
|
-
|
|
47
|
-
|
|
48
|
+
|
|
49
|
+
## Core Concepts
|
|
50
|
+
|
|
51
|
+
### 1. Tool Definition
|
|
52
|
+
|
|
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
|
+
});
|
|
48
62
|
```
|
|
49
63
|
|
|
50
|
-
|
|
64
|
+
### 2. Server Implementation
|
|
51
65
|
|
|
52
|
-
|
|
53
|
-
|
|
54
|
-
|
|
66
|
+
The `.server()` method defines logic that runs on the server (API routes, server components):
|
|
67
|
+
|
|
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
|
+
});
|
|
55
74
|
```
|
|
56
75
|
|
|
57
|
-
|
|
76
|
+
### 3. Client Implementation (Optional)
|
|
58
77
|
|
|
59
|
-
|
|
78
|
+
The `.client()` method defines what happens when called from the browser. If not specified, auto-fetches to `/api/tools/execute`.
|
|
60
79
|
|
|
61
|
-
|
|
62
|
-
|
|
63
|
-
|
|
64
|
-
|
|
65
|
-
|
|
66
|
-
- `.description(text)` - Optional tool description
|
|
67
|
-
- Returns a built tool object ready to use (no build step needed)
|
|
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;
|
|
68
85
|
|
|
69
|
-
|
|
86
|
+
return ctx.fetch('/api/search', {
|
|
87
|
+
method: 'POST',
|
|
88
|
+
body: JSON.stringify({ query })
|
|
89
|
+
});
|
|
90
|
+
});
|
|
91
|
+
```
|
|
92
|
+
|
|
93
|
+
### 4. View (Our Differentiator)
|
|
70
94
|
|
|
71
|
-
|
|
72
|
-
import { ToolExecutorProvider, ToolRenderer, useToolExecutor } from '@/lib/aui/client';
|
|
95
|
+
The `.view()` method defines how to render the tool's results:
|
|
73
96
|
|
|
74
|
-
|
|
75
|
-
|
|
76
|
-
<
|
|
77
|
-
|
|
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
|
+
```
|
|
78
104
|
|
|
79
|
-
|
|
80
|
-
<ToolRenderer toolCall={toolCall} tool={weatherTool} />
|
|
105
|
+
## Fluent Builder Alternative
|
|
81
106
|
|
|
82
|
-
|
|
83
|
-
const
|
|
84
|
-
|
|
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} />);
|
|
85
114
|
```
|
|
86
115
|
|
|
87
|
-
##
|
|
116
|
+
## React Usage
|
|
117
|
+
|
|
118
|
+
```typescript
|
|
119
|
+
import { useTool } from '@lantos1618/better-ui';
|
|
88
120
|
|
|
89
|
-
|
|
90
|
-
|
|
91
|
-
|
|
92
|
-
|
|
93
|
-
|
|
94
|
-
|
|
95
|
-
|
|
96
|
-
|
|
97
|
-
|
|
98
|
-
.render(({ data }) => (
|
|
99
|
-
<div className="weather-card">
|
|
100
|
-
<h3>{data.city}</h3>
|
|
101
|
-
<p>{data.temp}°F</p>
|
|
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} />}
|
|
102
130
|
</div>
|
|
103
|
-
)
|
|
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
|
+
}
|
|
104
139
|
```
|
|
105
140
|
|
|
106
|
-
|
|
107
|
-
```tsx
|
|
108
|
-
const searchTool = aui
|
|
109
|
-
.tool('search')
|
|
110
|
-
.input(z.object({ query: z.string() }))
|
|
111
|
-
.execute(async ({ input }) => {
|
|
112
|
-
return await database.search(input.query);
|
|
113
|
-
})
|
|
114
|
-
.clientExecute(async ({ input, ctx }) => {
|
|
115
|
-
// Client-side caching and offline support
|
|
116
|
-
const cached = ctx.cache.get(input.query);
|
|
117
|
-
if (cached) return cached;
|
|
118
|
-
|
|
119
|
-
const result = await ctx.fetch('/api/aui', {
|
|
120
|
-
method: 'POST',
|
|
121
|
-
body: JSON.stringify({
|
|
122
|
-
toolCall: { toolName: 'search', input }
|
|
123
|
-
})
|
|
124
|
-
});
|
|
125
|
-
|
|
126
|
-
ctx.cache.set(input.query, result);
|
|
127
|
-
return result;
|
|
128
|
-
})
|
|
129
|
-
.render(({ data }) => <SearchResults results={data} />);
|
|
130
|
-
```
|
|
131
|
-
|
|
132
|
-
## 🗂️ Project Structure
|
|
133
|
-
|
|
134
|
-
```
|
|
135
|
-
better-ui/
|
|
136
|
-
├── app/ # Next.js app directory
|
|
137
|
-
│ ├── api/ # API routes
|
|
138
|
-
│ └── aui-demo/ # Demo pages
|
|
139
|
-
├── lib/aui/ # AUI system core
|
|
140
|
-
│ ├── core/ # Core builder and registry
|
|
141
|
-
│ ├── client/ # Client-side execution
|
|
142
|
-
│ ├── server/ # Server-side execution
|
|
143
|
-
│ ├── tools/ # Example tools
|
|
144
|
-
│ └── types/ # TypeScript definitions
|
|
145
|
-
├── examples/ # Usage examples
|
|
146
|
-
└── agent/ # Development metadata
|
|
147
|
-
```
|
|
148
|
-
|
|
149
|
-
## 🧪 Testing
|
|
141
|
+
## AI Integration
|
|
150
142
|
|
|
151
|
-
|
|
152
|
-
|
|
153
|
-
|
|
154
|
-
|
|
143
|
+
### With Vercel AI SDK
|
|
144
|
+
|
|
145
|
+
```typescript
|
|
146
|
+
import { streamText } from 'ai';
|
|
147
|
+
import { openai } from '@ai-sdk/openai';
|
|
148
|
+
|
|
149
|
+
export async function POST(req: Request) {
|
|
150
|
+
const { messages } = await req.json();
|
|
151
|
+
|
|
152
|
+
const result = await streamText({
|
|
153
|
+
model: openai('gpt-4'),
|
|
154
|
+
messages,
|
|
155
|
+
tools: {
|
|
156
|
+
weather: weather.toAITool(),
|
|
157
|
+
search: search.toAITool(),
|
|
158
|
+
},
|
|
159
|
+
});
|
|
160
|
+
|
|
161
|
+
return result.toDataStreamResponse();
|
|
162
|
+
}
|
|
155
163
|
```
|
|
156
164
|
|
|
157
|
-
##
|
|
165
|
+
## API Reference
|
|
166
|
+
|
|
167
|
+
### `tool(config)` or `tool(name)`
|
|
168
|
+
|
|
169
|
+
Create a new tool with object config or fluent builder.
|
|
170
|
+
|
|
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
|
+
});
|
|
181
|
+
|
|
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
|
+
```
|
|
158
190
|
|
|
159
|
-
|
|
160
|
-
|
|
161
|
-
|
|
191
|
+
### `.server(handler)`
|
|
192
|
+
|
|
193
|
+
Define server-side implementation.
|
|
194
|
+
|
|
195
|
+
```typescript
|
|
196
|
+
t.server(async (input, ctx) => {
|
|
197
|
+
// ctx.env, ctx.headers, ctx.user, ctx.session available
|
|
198
|
+
return result;
|
|
199
|
+
});
|
|
200
|
+
```
|
|
201
|
+
|
|
202
|
+
### `.client(handler)`
|
|
162
203
|
|
|
163
|
-
|
|
164
|
-
npm run build
|
|
204
|
+
Define client-side implementation (optional).
|
|
165
205
|
|
|
166
|
-
|
|
167
|
-
|
|
206
|
+
```typescript
|
|
207
|
+
t.client(async (input, ctx) => {
|
|
208
|
+
// ctx.cache, ctx.fetch, ctx.optimistic available
|
|
209
|
+
return result;
|
|
210
|
+
});
|
|
168
211
|
```
|
|
169
212
|
|
|
170
|
-
|
|
213
|
+
### `.view(component)`
|
|
171
214
|
|
|
172
|
-
|
|
173
|
-
- [Examples](./examples/) - Complete usage examples
|
|
174
|
-
- [API Reference](./lib/aui/README.md) - Core API documentation
|
|
215
|
+
Define React component for rendering results.
|
|
175
216
|
|
|
176
|
-
|
|
217
|
+
```typescript
|
|
218
|
+
t.view((data, { loading, error }) => <Component data={data} />);
|
|
219
|
+
```
|
|
220
|
+
|
|
221
|
+
### `useTool(tool, input?, options?)`
|
|
222
|
+
|
|
223
|
+
React hook for executing tools.
|
|
224
|
+
|
|
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
|
+
});
|
|
238
|
+
```
|
|
177
239
|
|
|
178
|
-
|
|
179
|
-
2. Create a feature branch
|
|
180
|
-
3. Make your changes
|
|
181
|
-
4. Add tests
|
|
182
|
-
5. Submit a pull request
|
|
240
|
+
## Project Structure
|
|
183
241
|
|
|
184
|
-
|
|
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
|
|
259
|
+
```
|
|
185
260
|
|
|
186
|
-
|
|
261
|
+
## Development
|
|
262
|
+
|
|
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
|
+
```
|
|
187
270
|
|
|
188
|
-
|
|
271
|
+
## License
|
|
189
272
|
|
|
190
|
-
|
|
273
|
+
MIT
|