@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/lib/aui/README.md
DELETED
|
@@ -1,136 +0,0 @@
|
|
|
1
|
-
# AUI (Assistant-UI) System
|
|
2
|
-
|
|
3
|
-
A concise, type-safe tool system for AI assistants to control frontend and backend operations in Next.js/Vercel applications.
|
|
4
|
-
|
|
5
|
-
## Quick Start
|
|
6
|
-
|
|
7
|
-
```tsx
|
|
8
|
-
import aui from '@/lib/aui';
|
|
9
|
-
import { z } from 'zod';
|
|
10
|
-
|
|
11
|
-
// Simple tool - just 2 methods
|
|
12
|
-
const simpleTool = aui
|
|
13
|
-
.tool('weather')
|
|
14
|
-
.input(z.object({ city: z.string() }))
|
|
15
|
-
.execute(async ({ input }) => ({ temp: 72, city: input.city }))
|
|
16
|
-
.render(({ data }) => <div>{data.city}: {data.temp}°</div>);
|
|
17
|
-
|
|
18
|
-
// Complex tool - adds client optimization
|
|
19
|
-
const complexTool = aui
|
|
20
|
-
.tool('search')
|
|
21
|
-
.input(z.object({ query: z.string() }))
|
|
22
|
-
.execute(async ({ input }) => db.search(input.query))
|
|
23
|
-
.clientExecute(async ({ input, ctx }) => {
|
|
24
|
-
// Only when you need caching, offline, etc.
|
|
25
|
-
const cached = ctx.cache.get(input.query);
|
|
26
|
-
return cached || ctx.fetch('/api/tools/search', { body: input });
|
|
27
|
-
})
|
|
28
|
-
.render(({ data }) => <SearchResults results={data} />);
|
|
29
|
-
```
|
|
30
|
-
|
|
31
|
-
## Core Features
|
|
32
|
-
|
|
33
|
-
- **Concise API**: Define tools in 2-4 method calls
|
|
34
|
-
- **Type Safety**: Full TypeScript support with Zod validation
|
|
35
|
-
- **Dual Execution**: Run on server (default) or client (optimized)
|
|
36
|
-
- **React Integration**: Built-in rendering and hooks
|
|
37
|
-
- **Context Management**: Caching, sessions, and state
|
|
38
|
-
- **AI-Ready**: Designed for AI assistant control
|
|
39
|
-
|
|
40
|
-
## API Methods
|
|
41
|
-
|
|
42
|
-
### Core Methods
|
|
43
|
-
- `.tool(name)` - Create a new tool
|
|
44
|
-
- `.input(schema)` - Define input validation with Zod
|
|
45
|
-
- `.execute(handler)` - Server-side execution logic
|
|
46
|
-
- `.render(component)` - React component for rendering results
|
|
47
|
-
|
|
48
|
-
### Optional Methods
|
|
49
|
-
- `.clientExecute(handler)` - Client-side execution with caching
|
|
50
|
-
- `.middleware(fn)` - Add middleware for auth, logging, etc.
|
|
51
|
-
- `.describe(text)` - Add description for documentation
|
|
52
|
-
- `.tag(...tags)` - Add tags for organization
|
|
53
|
-
|
|
54
|
-
## Examples
|
|
55
|
-
|
|
56
|
-
See `/lib/aui/examples/` for complete examples including:
|
|
57
|
-
- Weather tool (simple)
|
|
58
|
-
- Search tool (with caching)
|
|
59
|
-
- Calculator tool (with validation)
|
|
60
|
-
- Form tool (with middleware)
|
|
61
|
-
- Analytics tool (complex visualization)
|
|
62
|
-
|
|
63
|
-
## Using Tools in React
|
|
64
|
-
|
|
65
|
-
```tsx
|
|
66
|
-
import { useAUITool, AUIProvider } from '@/lib/aui';
|
|
67
|
-
|
|
68
|
-
function MyComponent() {
|
|
69
|
-
const { execute, data, loading, error } = useAUITool(weatherTool);
|
|
70
|
-
|
|
71
|
-
return (
|
|
72
|
-
<div>
|
|
73
|
-
<button onClick={() => execute({ city: 'NYC' })}>
|
|
74
|
-
Get Weather
|
|
75
|
-
</button>
|
|
76
|
-
{loading && <div>Loading...</div>}
|
|
77
|
-
{data && weatherTool.renderer({ data })}
|
|
78
|
-
</div>
|
|
79
|
-
);
|
|
80
|
-
}
|
|
81
|
-
|
|
82
|
-
// Wrap your app with AUIProvider
|
|
83
|
-
export default function App() {
|
|
84
|
-
return (
|
|
85
|
-
<AUIProvider>
|
|
86
|
-
<MyComponent />
|
|
87
|
-
</AUIProvider>
|
|
88
|
-
);
|
|
89
|
-
}
|
|
90
|
-
```
|
|
91
|
-
|
|
92
|
-
## AI Control Example
|
|
93
|
-
|
|
94
|
-
Enable AI assistants to control both frontend and backend:
|
|
95
|
-
|
|
96
|
-
```tsx
|
|
97
|
-
const databaseTool = aui
|
|
98
|
-
.tool('database')
|
|
99
|
-
.input(z.object({
|
|
100
|
-
table: z.string(),
|
|
101
|
-
operation: z.enum(['select', 'insert', 'update', 'delete']),
|
|
102
|
-
conditions: z.record(z.any()).optional()
|
|
103
|
-
}))
|
|
104
|
-
.execute(async ({ input }) => {
|
|
105
|
-
// Server-side database operations
|
|
106
|
-
return await db[input.operation](input.table, input.conditions);
|
|
107
|
-
})
|
|
108
|
-
.clientExecute(async ({ input, ctx }) => {
|
|
109
|
-
// Client-side optimistic updates
|
|
110
|
-
if (input.operation === 'select') {
|
|
111
|
-
const cached = ctx.cache.get(`${input.table}:${input.operation}`);
|
|
112
|
-
if (cached) return cached;
|
|
113
|
-
}
|
|
114
|
-
return ctx.fetch('/api/database', { body: input });
|
|
115
|
-
});
|
|
116
|
-
```
|
|
117
|
-
|
|
118
|
-
## AI Control Examples
|
|
119
|
-
|
|
120
|
-
The system includes comprehensive examples for AI control in `/lib/aui/examples/ai-control-full.tsx`:
|
|
121
|
-
|
|
122
|
-
- **Database Operations**: Query and manipulate data
|
|
123
|
-
- **UI Control**: Manage modals, navigation, themes
|
|
124
|
-
- **File System**: Read/write files (server-side)
|
|
125
|
-
- **API Integration**: Call external APIs with CORS proxy
|
|
126
|
-
- **Real-time Streams**: WebSocket/SSE connections
|
|
127
|
-
- **Form Generation**: Dynamic form creation
|
|
128
|
-
- **Analytics**: Event tracking and analysis
|
|
129
|
-
|
|
130
|
-
## Testing
|
|
131
|
-
|
|
132
|
-
```bash
|
|
133
|
-
npm test -- --testPathPattern=aui
|
|
134
|
-
```
|
|
135
|
-
|
|
136
|
-
All 63 tests passing ✅
|
|
@@ -1,251 +0,0 @@
|
|
|
1
|
-
import { describe, it, expect, beforeEach } from '@jest/globals';
|
|
2
|
-
import aui, { z } from '../index';
|
|
3
|
-
import { AIControlledTool, createAITool, aiControlSystem } from '../ai-control';
|
|
4
|
-
import { clientControlSystem } from '../client-control';
|
|
5
|
-
|
|
6
|
-
describe('AUI Complete System Tests', () => {
|
|
7
|
-
beforeEach(() => {
|
|
8
|
-
aui.clear();
|
|
9
|
-
aiControlSystem.clear();
|
|
10
|
-
});
|
|
11
|
-
|
|
12
|
-
describe('Simple Tool Pattern', () => {
|
|
13
|
-
it('should create a simple tool with execute and render', async () => {
|
|
14
|
-
const simpleTool = aui
|
|
15
|
-
.tool('weather')
|
|
16
|
-
.input(z.object({ city: z.string() }))
|
|
17
|
-
.execute(async ({ input }) => ({ temp: 72, city: input.city }))
|
|
18
|
-
.render(({ data }) => `${data.city}: ${data.temp}°` as any);
|
|
19
|
-
|
|
20
|
-
expect(simpleTool.name).toBe('weather');
|
|
21
|
-
|
|
22
|
-
const result = await simpleTool.run({ city: 'New York' });
|
|
23
|
-
expect(result).toEqual({ temp: 72, city: 'New York' });
|
|
24
|
-
});
|
|
25
|
-
|
|
26
|
-
it('should validate input schema', async () => {
|
|
27
|
-
const tool = aui
|
|
28
|
-
.tool('validated')
|
|
29
|
-
.input(z.object({
|
|
30
|
-
required: z.string(),
|
|
31
|
-
optional: z.number().optional()
|
|
32
|
-
}))
|
|
33
|
-
.execute(async ({ input }) => input);
|
|
34
|
-
|
|
35
|
-
await expect(tool.run({ required: 'test' })).resolves.toEqual({ required: 'test' });
|
|
36
|
-
await expect(tool.run({ missing: 'field' } as any)).rejects.toThrow();
|
|
37
|
-
});
|
|
38
|
-
});
|
|
39
|
-
|
|
40
|
-
describe('Complex Tool Pattern', () => {
|
|
41
|
-
it('should support client and server execution', async () => {
|
|
42
|
-
const complexTool = aui
|
|
43
|
-
.tool('search')
|
|
44
|
-
.input(z.object({ query: z.string() }))
|
|
45
|
-
.execute(async ({ input }) => ({
|
|
46
|
-
results: [`server: ${input.query}`]
|
|
47
|
-
}))
|
|
48
|
-
.clientExecute(async ({ input, ctx }) => {
|
|
49
|
-
const cached = ctx.cache.get(input.query);
|
|
50
|
-
if (cached) return cached;
|
|
51
|
-
|
|
52
|
-
const result = { results: [`client: ${input.query}`] };
|
|
53
|
-
ctx.cache.set(input.query, result);
|
|
54
|
-
return result;
|
|
55
|
-
});
|
|
56
|
-
|
|
57
|
-
// Server execution
|
|
58
|
-
const serverResult = await complexTool.run(
|
|
59
|
-
{ query: 'test' },
|
|
60
|
-
{ isServer: true, cache: new Map(), fetch: fetch }
|
|
61
|
-
);
|
|
62
|
-
expect(serverResult.results[0]).toContain('server');
|
|
63
|
-
|
|
64
|
-
// Client execution
|
|
65
|
-
const clientResult = await complexTool.run(
|
|
66
|
-
{ query: 'test' },
|
|
67
|
-
{ isServer: false, cache: new Map(), fetch: fetch }
|
|
68
|
-
);
|
|
69
|
-
expect(clientResult.results[0]).toContain('client');
|
|
70
|
-
});
|
|
71
|
-
|
|
72
|
-
it('should support middleware', async () => {
|
|
73
|
-
const middlewareTool = aui
|
|
74
|
-
.tool('with-middleware')
|
|
75
|
-
.input(z.object({ value: z.number() }))
|
|
76
|
-
.execute(async ({ input }) => ({ result: input.value }))
|
|
77
|
-
.middleware(async ({ input, next }) => {
|
|
78
|
-
input.value = input.value * 2;
|
|
79
|
-
const result = await next();
|
|
80
|
-
result.result = result.result + 10;
|
|
81
|
-
return result;
|
|
82
|
-
});
|
|
83
|
-
|
|
84
|
-
const result = await middlewareTool.run({ value: 5 });
|
|
85
|
-
expect(result).toEqual({ result: 20 }); // (5 * 2) + 10
|
|
86
|
-
});
|
|
87
|
-
});
|
|
88
|
-
|
|
89
|
-
describe('AI Control System', () => {
|
|
90
|
-
it('should create AI-controlled tools with permissions', () => {
|
|
91
|
-
const aiTool = createAITool('ai-tool', {
|
|
92
|
-
permissions: {
|
|
93
|
-
allowClientExecution: true,
|
|
94
|
-
allowServerExecution: false
|
|
95
|
-
}
|
|
96
|
-
})
|
|
97
|
-
.input(z.object({ action: z.string() }))
|
|
98
|
-
.execute(async ({ input }) => ({ executed: input.action }));
|
|
99
|
-
|
|
100
|
-
expect(aiTool).toBeInstanceOf(AIControlledTool);
|
|
101
|
-
expect(aiTool.name).toBe('ai-tool');
|
|
102
|
-
});
|
|
103
|
-
|
|
104
|
-
it('should enforce rate limiting', async () => {
|
|
105
|
-
const rateLimitedTool = createAITool('rate-limited', {
|
|
106
|
-
rateLimit: {
|
|
107
|
-
requestsPerMinute: 2
|
|
108
|
-
},
|
|
109
|
-
audit: true // Enable audit to track execution for rate limiting
|
|
110
|
-
})
|
|
111
|
-
.input(z.object({ id: z.number() }))
|
|
112
|
-
.execute(async ({ input }) => ({ id: input.id }));
|
|
113
|
-
|
|
114
|
-
// First two requests should succeed
|
|
115
|
-
await expect(rateLimitedTool.run({ id: 1 })).resolves.toEqual({ id: 1 });
|
|
116
|
-
await expect(rateLimitedTool.run({ id: 2 })).resolves.toEqual({ id: 2 });
|
|
117
|
-
|
|
118
|
-
// Third request should fail
|
|
119
|
-
await expect(rateLimitedTool.run({ id: 3 })).rejects.toThrow('Rate limit exceeded');
|
|
120
|
-
});
|
|
121
|
-
|
|
122
|
-
it('should track execution with audit', async () => {
|
|
123
|
-
const auditedTool = createAITool('audited', { audit: true })
|
|
124
|
-
.input(z.object({ action: z.string() }))
|
|
125
|
-
.execute(async ({ input }) => ({ result: input.action }));
|
|
126
|
-
|
|
127
|
-
await auditedTool.run({ action: 'test1' });
|
|
128
|
-
await auditedTool.run({ action: 'test2' });
|
|
129
|
-
|
|
130
|
-
const log = auditedTool.getExecutionLog();
|
|
131
|
-
expect(log).toHaveLength(2);
|
|
132
|
-
expect(log[0].input).toEqual({ action: 'test1' });
|
|
133
|
-
expect(log[1].input).toEqual({ action: 'test2' });
|
|
134
|
-
});
|
|
135
|
-
});
|
|
136
|
-
|
|
137
|
-
describe('Tool Registry', () => {
|
|
138
|
-
it('should register and retrieve tools', () => {
|
|
139
|
-
const tool1 = aui.tool('tool1')
|
|
140
|
-
.input(z.object({ x: z.number() }))
|
|
141
|
-
.execute(async ({ input }) => input);
|
|
142
|
-
|
|
143
|
-
const tool2 = aui.tool('tool2')
|
|
144
|
-
.input(z.object({ y: z.string() }))
|
|
145
|
-
.execute(async ({ input }) => input);
|
|
146
|
-
|
|
147
|
-
expect(aui.has('tool1')).toBe(true);
|
|
148
|
-
expect(aui.has('tool2')).toBe(true);
|
|
149
|
-
expect(aui.getToolNames()).toEqual(['tool1', 'tool2']);
|
|
150
|
-
});
|
|
151
|
-
|
|
152
|
-
it('should support tool tags and discovery', () => {
|
|
153
|
-
const apiTool = aui.tool('api')
|
|
154
|
-
.tag('backend', 'api', 'rest')
|
|
155
|
-
.execute(async () => ({ success: true }));
|
|
156
|
-
|
|
157
|
-
const uiTool = aui.tool('ui')
|
|
158
|
-
.tag('frontend', 'ui', 'dom')
|
|
159
|
-
.execute(async () => ({ rendered: true }));
|
|
160
|
-
|
|
161
|
-
expect(aui.findByTag('backend')).toContain(apiTool);
|
|
162
|
-
expect(aui.findByTag('frontend')).toContain(uiTool);
|
|
163
|
-
expect(aui.findByTags('backend', 'api')).toContain(apiTool);
|
|
164
|
-
});
|
|
165
|
-
});
|
|
166
|
-
|
|
167
|
-
describe('Tool Execution', () => {
|
|
168
|
-
it('should execute tools through AUI instance', async () => {
|
|
169
|
-
aui.tool('executor')
|
|
170
|
-
.input(z.object({ value: z.number() }))
|
|
171
|
-
.execute(async ({ input }) => ({ doubled: input.value * 2 }));
|
|
172
|
-
|
|
173
|
-
const result = await aui.execute('executor', { value: 5 });
|
|
174
|
-
expect(result).toEqual({ doubled: 10 });
|
|
175
|
-
});
|
|
176
|
-
|
|
177
|
-
it('should handle execution errors', async () => {
|
|
178
|
-
aui.tool('error-tool')
|
|
179
|
-
.execute(async () => {
|
|
180
|
-
throw new Error('Execution failed');
|
|
181
|
-
});
|
|
182
|
-
|
|
183
|
-
await expect(aui.execute('error-tool', {})).rejects.toThrow('Execution failed');
|
|
184
|
-
});
|
|
185
|
-
});
|
|
186
|
-
|
|
187
|
-
describe('Client Control System', () => {
|
|
188
|
-
it('should list available client tools', () => {
|
|
189
|
-
const tools = clientControlSystem.listClientTools();
|
|
190
|
-
|
|
191
|
-
expect(tools).toContainEqual(
|
|
192
|
-
expect.objectContaining({
|
|
193
|
-
name: 'client-dom',
|
|
194
|
-
description: 'Manipulate DOM elements on the client'
|
|
195
|
-
})
|
|
196
|
-
);
|
|
197
|
-
|
|
198
|
-
expect(tools).toContainEqual(
|
|
199
|
-
expect.objectContaining({
|
|
200
|
-
name: 'client-forms',
|
|
201
|
-
description: 'Control and interact with forms'
|
|
202
|
-
})
|
|
203
|
-
);
|
|
204
|
-
});
|
|
205
|
-
});
|
|
206
|
-
|
|
207
|
-
describe('Tool Serialization', () => {
|
|
208
|
-
it('should serialize tool configuration', () => {
|
|
209
|
-
const tool = aui.tool('serializable')
|
|
210
|
-
.describe('A test tool')
|
|
211
|
-
.tag('test', 'demo')
|
|
212
|
-
.input(z.object({ x: z.number() }))
|
|
213
|
-
.execute(async ({ input }) => input)
|
|
214
|
-
.clientExecute(async ({ input }) => input)
|
|
215
|
-
.render(() => null as any);
|
|
216
|
-
|
|
217
|
-
const json = tool.toJSON();
|
|
218
|
-
|
|
219
|
-
expect(json).toEqual({
|
|
220
|
-
name: 'serializable',
|
|
221
|
-
description: 'A test tool',
|
|
222
|
-
tags: ['test', 'demo'],
|
|
223
|
-
hasInput: true,
|
|
224
|
-
hasExecute: true,
|
|
225
|
-
hasClientExecute: true,
|
|
226
|
-
hasRender: true,
|
|
227
|
-
hasMiddleware: false
|
|
228
|
-
});
|
|
229
|
-
});
|
|
230
|
-
});
|
|
231
|
-
|
|
232
|
-
describe('Context Management', () => {
|
|
233
|
-
it('should create and use context correctly', async () => {
|
|
234
|
-
const contextTool = aui.tool('context-test')
|
|
235
|
-
.execute(async ({ ctx }) => ({
|
|
236
|
-
isServer: ctx?.isServer,
|
|
237
|
-
hasCache: ctx?.cache instanceof Map,
|
|
238
|
-
hasFetch: typeof ctx?.fetch === 'function'
|
|
239
|
-
}));
|
|
240
|
-
|
|
241
|
-
const result = await contextTool.run({}, aui.createContext({
|
|
242
|
-
isServer: true,
|
|
243
|
-
user: { id: 1 }
|
|
244
|
-
}));
|
|
245
|
-
|
|
246
|
-
expect(result.isServer).toBe(true);
|
|
247
|
-
expect(result.hasCache).toBe(true);
|
|
248
|
-
expect(result.hasFetch).toBe(true);
|
|
249
|
-
});
|
|
250
|
-
});
|
|
251
|
-
});
|