@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.
Files changed (59) hide show
  1. package/README.md +183 -367
  2. package/dist/index.d.mts +314 -0
  3. package/dist/index.d.ts +314 -0
  4. package/dist/index.js +522 -0
  5. package/dist/index.mjs +491 -0
  6. package/package.json +59 -26
  7. package/lib/aui/README.md +0 -136
  8. package/lib/aui/__tests__/aui-complete.test.ts +0 -251
  9. package/lib/aui/__tests__/aui-comprehensive.test.ts +0 -376
  10. package/lib/aui/__tests__/aui-concise.test.ts +0 -278
  11. package/lib/aui/__tests__/aui-integration.test.ts +0 -309
  12. package/lib/aui/__tests__/aui-simple.test.ts +0 -116
  13. package/lib/aui/__tests__/aui.test.ts +0 -269
  14. package/lib/aui/__tests__/concise-api.test.ts +0 -165
  15. package/lib/aui/__tests__/core.test.ts +0 -265
  16. package/lib/aui/__tests__/simple-api.test.ts +0 -200
  17. package/lib/aui/ai-assistant.ts +0 -408
  18. package/lib/aui/ai-control.ts +0 -353
  19. package/lib/aui/client/use-aui.ts +0 -55
  20. package/lib/aui/client-control.ts +0 -551
  21. package/lib/aui/client-executor.ts +0 -417
  22. package/lib/aui/components/ToolRenderer.tsx +0 -22
  23. package/lib/aui/core.ts +0 -137
  24. package/lib/aui/demo.tsx +0 -89
  25. package/lib/aui/examples/ai-complete-demo.tsx +0 -359
  26. package/lib/aui/examples/ai-control-demo.tsx +0 -356
  27. package/lib/aui/examples/ai-control-tools.ts +0 -308
  28. package/lib/aui/examples/concise-api.tsx +0 -153
  29. package/lib/aui/examples/index.tsx +0 -163
  30. package/lib/aui/examples/quick-demo.tsx +0 -91
  31. package/lib/aui/examples/simple-demo.tsx +0 -71
  32. package/lib/aui/examples/simple-tools.tsx +0 -160
  33. package/lib/aui/examples/user-api.tsx +0 -208
  34. package/lib/aui/examples/user-requested.tsx +0 -174
  35. package/lib/aui/examples/weather-search-tools.tsx +0 -119
  36. package/lib/aui/examples.tsx +0 -367
  37. package/lib/aui/hooks/useAUITool.ts +0 -142
  38. package/lib/aui/hooks/useAUIToolEnhanced.ts +0 -343
  39. package/lib/aui/hooks/useAUITools.ts +0 -195
  40. package/lib/aui/index.ts +0 -156
  41. package/lib/aui/provider.tsx +0 -45
  42. package/lib/aui/server-control.ts +0 -386
  43. package/lib/aui/server-executor.ts +0 -165
  44. package/lib/aui/server.ts +0 -167
  45. package/lib/aui/tool-registry.ts +0 -380
  46. package/lib/aui/tools/advanced-examples.tsx +0 -86
  47. package/lib/aui/tools/ai-complete.ts +0 -375
  48. package/lib/aui/tools/api-tools.tsx +0 -230
  49. package/lib/aui/tools/data-tools.tsx +0 -232
  50. package/lib/aui/tools/dom-tools.tsx +0 -202
  51. package/lib/aui/tools/examples.ts +0 -43
  52. package/lib/aui/tools/file-tools.tsx +0 -202
  53. package/lib/aui/tools/form-tools.tsx +0 -233
  54. package/lib/aui/tools/index.ts +0 -8
  55. package/lib/aui/tools/navigation-tools.tsx +0 -172
  56. package/lib/aui/tools/notification-tools.ts +0 -213
  57. package/lib/aui/tools/state-tools.tsx +0 -209
  58. package/lib/aui/types.ts +0 -47
  59. package/lib/aui/vercel-ai.ts +0 -100
@@ -1,353 +0,0 @@
1
- import { ReactElement } from 'react';
2
- import { z } from 'zod';
3
- import { AUITool, AUIContext } from './core';
4
-
5
- export interface AIControlOptions {
6
- permissions?: {
7
- allowClientExecution?: boolean;
8
- allowServerExecution?: boolean;
9
- allowDatabaseAccess?: boolean;
10
- allowFileSystemAccess?: boolean;
11
- allowNetworkRequests?: boolean;
12
- };
13
- rateLimit?: {
14
- requestsPerMinute?: number;
15
- requestsPerHour?: number;
16
- };
17
- audit?: boolean;
18
- sandbox?: boolean;
19
- }
20
-
21
- export class AIControlledTool<TInput = any, TOutput = any> extends AUITool<TInput, TOutput> {
22
- private controlOptions: AIControlOptions = {};
23
- private executionLog: Array<{
24
- timestamp: Date;
25
- input: TInput;
26
- output?: TOutput;
27
- error?: Error;
28
- context?: Partial<AUIContext>;
29
- }> = [];
30
-
31
- constructor(name: string, options?: AIControlOptions) {
32
- super(name);
33
- this.controlOptions = options || {};
34
- }
35
-
36
- // Override methods to maintain correct type
37
- input<T>(schema: z.ZodType<T>): AIControlledTool<T, TOutput> {
38
- super.input(schema);
39
- return this as any;
40
- }
41
-
42
- execute<O>(handler: (params: { input: TInput; ctx?: AUIContext }) => O | Promise<O>): AIControlledTool<TInput, O> {
43
- super.execute(handler);
44
- return this as any;
45
- }
46
-
47
- clientExecute(handler: (params: { input: TInput; ctx: AUIContext }) => TOutput | Promise<TOutput>): this {
48
- super.clientExecute(handler);
49
- return this;
50
- }
51
-
52
- render(component: (props: { data: TOutput; input?: TInput; loading?: boolean; error?: Error }) => ReactElement): this {
53
- super.render(component);
54
- return this;
55
- }
56
-
57
- middleware(fn: (params: { input: TInput; ctx: AUIContext; next: () => Promise<TOutput> }) => Promise<TOutput>): this {
58
- super.middleware(fn);
59
- return this;
60
- }
61
-
62
- describe(description: string): this {
63
- super.describe(description);
64
- return this;
65
- }
66
-
67
- tag(...tags: string[]): this {
68
- super.tag(...tags);
69
- return this;
70
- }
71
-
72
- withPermissions(permissions: AIControlOptions['permissions']): this {
73
- this.controlOptions.permissions = {
74
- ...this.controlOptions.permissions,
75
- ...permissions
76
- };
77
- return this;
78
- }
79
-
80
- withRateLimit(limit: AIControlOptions['rateLimit']): this {
81
- this.controlOptions.rateLimit = limit;
82
- return this;
83
- }
84
-
85
- enableAudit(): this {
86
- this.controlOptions.audit = true;
87
- return this;
88
- }
89
-
90
- enableSandbox(): this {
91
- this.controlOptions.sandbox = true;
92
- return this;
93
- }
94
-
95
- async run(input: TInput, ctx?: AUIContext): Promise<TOutput> {
96
- const startTime = Date.now();
97
-
98
- try {
99
- this.validatePermissions(ctx);
100
- await this.checkRateLimit();
101
-
102
- const result = await super.run(input, ctx);
103
-
104
- if (this.controlOptions.audit) {
105
- this.executionLog.push({
106
- timestamp: new Date(),
107
- input,
108
- output: result,
109
- context: ctx ? { user: ctx.user, session: ctx.session } : undefined
110
- });
111
- }
112
-
113
- return result;
114
- } catch (error) {
115
- if (this.controlOptions.audit) {
116
- this.executionLog.push({
117
- timestamp: new Date(),
118
- input,
119
- error: error as Error,
120
- context: ctx ? { user: ctx.user, session: ctx.session } : undefined
121
- });
122
- }
123
- throw error;
124
- }
125
- }
126
-
127
- private validatePermissions(ctx?: AUIContext): void {
128
- if (!this.controlOptions.permissions) return;
129
-
130
- const isClient = !ctx?.isServer;
131
- const perms = this.controlOptions.permissions;
132
-
133
- if (isClient && !perms.allowClientExecution) {
134
- throw new Error('Client execution not allowed for this tool');
135
- }
136
-
137
- if (ctx?.isServer && !perms.allowServerExecution) {
138
- throw new Error('Server execution not allowed for this tool');
139
- }
140
- }
141
-
142
- private async checkRateLimit(): Promise<void> {
143
- if (!this.controlOptions.rateLimit) return;
144
-
145
- const now = Date.now();
146
- const { requestsPerMinute, requestsPerHour } = this.controlOptions.rateLimit;
147
-
148
- if (requestsPerMinute) {
149
- const recentMinute = this.executionLog.filter(
150
- log => now - log.timestamp.getTime() < 60000
151
- );
152
- if (recentMinute.length >= requestsPerMinute) {
153
- throw new Error('Rate limit exceeded (per minute)');
154
- }
155
- }
156
-
157
- if (requestsPerHour) {
158
- const recentHour = this.executionLog.filter(
159
- log => now - log.timestamp.getTime() < 3600000
160
- );
161
- if (recentHour.length >= requestsPerHour) {
162
- throw new Error('Rate limit exceeded (per hour)');
163
- }
164
- }
165
- }
166
-
167
- getExecutionLog() {
168
- return [...this.executionLog];
169
- }
170
-
171
- clearExecutionLog() {
172
- this.executionLog = [];
173
- }
174
- }
175
-
176
- export function createAITool(name: string, options?: AIControlOptions): AIControlledTool {
177
- return new AIControlledTool(name, options);
178
- }
179
-
180
- export const aiTools = {
181
- fileSystem: createAITool('fs-control', {
182
- permissions: {
183
- allowServerExecution: true,
184
- allowFileSystemAccess: true
185
- },
186
- audit: true
187
- })
188
- .input(z.object({
189
- action: z.enum(['read', 'write', 'delete', 'list']),
190
- path: z.string(),
191
- content: z.string().optional()
192
- }))
193
- .execute(async ({ input }) => {
194
- switch (input.action) {
195
- case 'read':
196
- return { content: 'File content here' };
197
- case 'write':
198
- return { success: true, path: input.path };
199
- case 'delete':
200
- return { success: true, deleted: input.path };
201
- case 'list':
202
- return { files: ['file1.txt', 'file2.txt'] };
203
- default:
204
- throw new Error('Unknown action');
205
- }
206
- }),
207
-
208
- database: createAITool('db-control', {
209
- permissions: {
210
- allowServerExecution: true,
211
- allowDatabaseAccess: true
212
- },
213
- rateLimit: {
214
- requestsPerMinute: 30,
215
- requestsPerHour: 500
216
- },
217
- audit: true
218
- })
219
- .input(z.object({
220
- query: z.string(),
221
- params: z.array(z.any()).optional()
222
- }))
223
- .execute(async ({ input }) => {
224
- return {
225
- rows: [],
226
- query: input.query,
227
- executed: new Date().toISOString()
228
- };
229
- }),
230
-
231
- uiManipulation: createAITool('ui-control', {
232
- permissions: {
233
- allowClientExecution: true
234
- },
235
- audit: true
236
- })
237
- .input(z.object({
238
- selector: z.string(),
239
- action: z.enum(['click', 'type', 'focus', 'scroll']),
240
- value: z.string().optional()
241
- }))
242
- .clientExecute(async ({ input }) => {
243
- const element = document.querySelector(input.selector);
244
- if (!element) throw new Error(`Element not found: ${input.selector}`);
245
-
246
- switch (input.action) {
247
- case 'click':
248
- (element as HTMLElement).click();
249
- break;
250
- case 'type':
251
- if (element instanceof HTMLInputElement && input.value) {
252
- element.value = input.value;
253
- element.dispatchEvent(new Event('input', { bubbles: true }));
254
- }
255
- break;
256
- case 'focus':
257
- (element as HTMLElement).focus();
258
- break;
259
- case 'scroll':
260
- element.scrollIntoView({ behavior: 'smooth' });
261
- break;
262
- }
263
-
264
- return { success: true, action: input.action, selector: input.selector };
265
- }),
266
-
267
- apiCall: createAITool('api-control', {
268
- permissions: {
269
- allowNetworkRequests: true
270
- },
271
- rateLimit: {
272
- requestsPerMinute: 20
273
- },
274
- audit: true
275
- })
276
- .input(z.object({
277
- url: z.string().url(),
278
- method: z.enum(['GET', 'POST', 'PUT', 'DELETE']),
279
- headers: z.record(z.string()).optional(),
280
- body: z.any().optional()
281
- }))
282
- .execute(async ({ input, ctx }) => {
283
- const response = await ctx!.fetch(input.url, {
284
- method: input.method,
285
- headers: input.headers,
286
- body: input.body ? JSON.stringify(input.body) : undefined
287
- });
288
-
289
- return {
290
- status: response.status,
291
- data: await response.json().catch(() => null),
292
- headers: Object.fromEntries(response.headers.entries())
293
- };
294
- })
295
- };
296
-
297
- export function createAIControlSystem() {
298
- const tools = new Map<string, AIControlledTool>();
299
-
300
- return {
301
- register(tool: AIControlledTool) {
302
- tools.set(tool.name, tool);
303
- return this;
304
- },
305
-
306
- get(name: string) {
307
- return tools.get(name);
308
- },
309
-
310
- clear() {
311
- tools.clear();
312
- },
313
-
314
- async execute(name: string, input: any, ctx?: AUIContext) {
315
- const tool = tools.get(name);
316
- if (!tool) throw new Error(`Tool ${name} not found`);
317
- return await tool.run(input, ctx);
318
- },
319
-
320
- getAuditLog(toolName?: string) {
321
- if (toolName) {
322
- const tool = tools.get(toolName);
323
- return tool ? tool.getExecutionLog() : [];
324
- }
325
-
326
- const allLogs: any[] = [];
327
- tools.forEach((tool, name) => {
328
- const logs = tool.getExecutionLog();
329
- logs.forEach(log => allLogs.push({ tool: name, ...log }));
330
- });
331
- return allLogs.sort((a, b) =>
332
- b.timestamp.getTime() - a.timestamp.getTime()
333
- );
334
- },
335
-
336
- listTools() {
337
- return Array.from(tools.values()).map(tool => ({
338
- name: tool.name,
339
- description: tool.description,
340
- tags: tool.tags,
341
- config: tool.toJSON()
342
- }));
343
- }
344
- };
345
- }
346
-
347
- export const aiControlSystem = createAIControlSystem();
348
-
349
- Object.values(aiTools).forEach(tool => {
350
- aiControlSystem.register(tool);
351
- });
352
-
353
- export default aiControlSystem;
@@ -1,55 +0,0 @@
1
- 'use client';
2
-
3
- import { useState, useCallback } from 'react';
4
- import { AUITool, AUIContext } from '../index';
5
-
6
- interface UseAUIOptions {
7
- cache?: boolean;
8
- context?: Partial<AUIContext>;
9
- }
10
-
11
- interface UseAUIResult<TInput, TOutput> {
12
- execute: (input: TInput) => Promise<void>;
13
- data: TOutput | null;
14
- loading: boolean;
15
- error: Error | null;
16
- reset: () => void;
17
- }
18
-
19
- export function useAUI<TInput = any, TOutput = any>(
20
- tool: AUITool<TInput, TOutput>,
21
- options: UseAUIOptions = {}
22
- ): UseAUIResult<TInput, TOutput> {
23
- const [data, setData] = useState<TOutput | null>(null);
24
- const [loading, setLoading] = useState(false);
25
- const [error, setError] = useState<Error | null>(null);
26
-
27
- const execute = useCallback(async (input: TInput) => {
28
- setLoading(true);
29
- setError(null);
30
-
31
- try {
32
- const context: AUIContext = {
33
- cache: options.cache ? new Map() : new Map(),
34
- fetch: globalThis.fetch,
35
- isServer: false,
36
- ...options.context
37
- };
38
-
39
- const result = await tool.run(input, context);
40
- setData(result);
41
- } catch (err) {
42
- setError(err instanceof Error ? err : new Error('Unknown error'));
43
- } finally {
44
- setLoading(false);
45
- }
46
- }, [tool, options.cache, options.context]);
47
-
48
- const reset = useCallback(() => {
49
- setData(null);
50
- setError(null);
51
- setLoading(false);
52
- }, []);
53
-
54
- return { execute, data, loading, error, reset };
55
- }