@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.
Files changed (59) hide show
  1. package/README.md +231 -148
  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 -20
  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,408 +0,0 @@
1
- import { z } from 'zod';
2
- import { AUITool, AUIContext } from './core';
3
- import { AIControlledTool, aiControlSystem } from './ai-control';
4
- import { clientControlSystem } from './client-control';
5
- import { globalToolRegistry, ToolMetadata } from './tool-registry';
6
- import { ClientExecutor } from './client-executor';
7
-
8
- export interface AIAssistantConfig {
9
- name: string;
10
- description?: string;
11
- systemPrompt?: string;
12
- tools?: string[]; // Tool names this assistant can use
13
- capabilities?: {
14
- canExecuteServerTools?: boolean;
15
- canExecuteClientTools?: boolean;
16
- canAccessDatabase?: boolean;
17
- canAccessFileSystem?: boolean;
18
- canMakeNetworkRequests?: boolean;
19
- };
20
- maxTokens?: number;
21
- temperature?: number;
22
- model?: string;
23
- }
24
-
25
- export interface AIToolCall {
26
- id: string;
27
- tool: string;
28
- input: any;
29
- status: 'pending' | 'executing' | 'completed' | 'failed';
30
- result?: any;
31
- error?: Error;
32
- startTime?: Date;
33
- endTime?: Date;
34
- }
35
-
36
- export interface AIConversationMessage {
37
- role: 'user' | 'assistant' | 'system' | 'tool';
38
- content: string;
39
- toolCalls?: AIToolCall[];
40
- timestamp: Date;
41
- }
42
-
43
- export class AIAssistant {
44
- private config: AIAssistantConfig;
45
- private conversation: AIConversationMessage[] = [];
46
- private availableTools: Map<string, AUITool | AIControlledTool> = new Map();
47
- private executor: ClientExecutor;
48
- private pendingToolCalls: Map<string, AIToolCall> = new Map();
49
-
50
- constructor(config: AIAssistantConfig) {
51
- this.config = config;
52
- this.executor = new ClientExecutor();
53
- this.initializeTools();
54
- }
55
-
56
- private initializeTools(): void {
57
- if (this.config.tools) {
58
- this.config.tools.forEach(toolName => {
59
- const tool = globalToolRegistry.get(toolName) ||
60
- aiControlSystem.get(toolName) ||
61
- clientControlSystem.tools.get(toolName);
62
-
63
- if (tool) {
64
- this.availableTools.set(toolName, tool);
65
- }
66
- });
67
- }
68
- }
69
-
70
- async processMessage(message: string, context?: Partial<AUIContext>): Promise<{
71
- response: string;
72
- toolCalls?: AIToolCall[];
73
- }> {
74
- // Add user message to conversation
75
- this.conversation.push({
76
- role: 'user',
77
- content: message,
78
- timestamp: new Date(),
79
- });
80
-
81
- // Parse message for tool calls
82
- const toolCalls = await this.extractToolCalls(message);
83
-
84
- if (toolCalls.length > 0) {
85
- // Execute tool calls
86
- const results = await this.executeToolCalls(toolCalls, context);
87
-
88
- // Generate response based on tool results
89
- const response = this.generateToolResponse(results);
90
-
91
- // Add assistant response to conversation
92
- this.conversation.push({
93
- role: 'assistant',
94
- content: response,
95
- toolCalls: results,
96
- timestamp: new Date(),
97
- });
98
-
99
- return { response, toolCalls: results };
100
- }
101
-
102
- // Generate regular response
103
- const response = await this.generateResponse(message);
104
-
105
- this.conversation.push({
106
- role: 'assistant',
107
- content: response,
108
- timestamp: new Date(),
109
- });
110
-
111
- return { response };
112
- }
113
-
114
- private async extractToolCalls(message: string): Promise<AIToolCall[]> {
115
- const toolCalls: AIToolCall[] = [];
116
-
117
- // Simple pattern matching for tool calls
118
- // Format: @toolname{input}
119
- const pattern = /@(\w+)\{([^}]+)\}/g;
120
- let match;
121
-
122
- while ((match = pattern.exec(message)) !== null) {
123
- const [, toolName, inputStr] = match;
124
-
125
- if (this.availableTools.has(toolName)) {
126
- try {
127
- const input = JSON.parse(inputStr);
128
- toolCalls.push({
129
- id: `tc_${Date.now()}_${Math.random().toString(36).substr(2, 9)}`,
130
- tool: toolName,
131
- input,
132
- status: 'pending',
133
- });
134
- } catch {
135
- // Invalid JSON, skip
136
- }
137
- }
138
- }
139
-
140
- return toolCalls;
141
- }
142
-
143
- private async executeToolCalls(
144
- toolCalls: AIToolCall[],
145
- context?: Partial<AUIContext>
146
- ): Promise<AIToolCall[]> {
147
- const results = await Promise.all(
148
- toolCalls.map(async (call) => {
149
- const tool = this.availableTools.get(call.tool);
150
- if (!tool) {
151
- return {
152
- ...call,
153
- status: 'failed' as const,
154
- error: new Error(`Tool ${call.tool} not available`),
155
- };
156
- }
157
-
158
- call.status = 'executing';
159
- call.startTime = new Date();
160
- this.pendingToolCalls.set(call.id, call);
161
-
162
- try {
163
- const result = await tool.run(call.input, {
164
- ...context,
165
- cache: context?.cache || new Map(),
166
- fetch: context?.fetch || fetch,
167
- isServer: context?.isServer ?? (typeof window === 'undefined'),
168
- } as AUIContext);
169
-
170
- call.status = 'completed';
171
- call.result = result;
172
- call.endTime = new Date();
173
- } catch (error) {
174
- call.status = 'failed';
175
- call.error = error as Error;
176
- call.endTime = new Date();
177
- }
178
-
179
- this.pendingToolCalls.delete(call.id);
180
- return call;
181
- })
182
- );
183
-
184
- return results;
185
- }
186
-
187
- private generateToolResponse(toolCalls: AIToolCall[]): string {
188
- const successful = toolCalls.filter(tc => tc.status === 'completed');
189
- const failed = toolCalls.filter(tc => tc.status === 'failed');
190
-
191
- let response = '';
192
-
193
- if (successful.length > 0) {
194
- response += `Successfully executed ${successful.length} tool(s):\n`;
195
- successful.forEach(tc => {
196
- response += `- ${tc.tool}: ${JSON.stringify(tc.result)}\n`;
197
- });
198
- }
199
-
200
- if (failed.length > 0) {
201
- response += `\nFailed to execute ${failed.length} tool(s):\n`;
202
- failed.forEach(tc => {
203
- response += `- ${tc.tool}: ${tc.error?.message}\n`;
204
- });
205
- }
206
-
207
- return response || 'No tools were executed.';
208
- }
209
-
210
- private async generateResponse(message: string): Promise<string> {
211
- // Simple response generation
212
- // In a real implementation, this would call an LLM API
213
- return `I understand you said: "${message}". How can I help you with that?`;
214
- }
215
-
216
- getAvailableTools(): ToolMetadata[] {
217
- return Array.from(this.availableTools.keys()).map(name => {
218
- const tool = this.availableTools.get(name)!;
219
- return globalToolRegistry.getMetadata(name) || {
220
- name: tool.name,
221
- description: tool.description,
222
- tags: tool.tags,
223
- category: 'custom',
224
- };
225
- });
226
- }
227
-
228
- getConversation(): AIConversationMessage[] {
229
- return [...this.conversation];
230
- }
231
-
232
- clearConversation(): void {
233
- this.conversation = [];
234
- if (this.config.systemPrompt) {
235
- this.conversation.push({
236
- role: 'system',
237
- content: this.config.systemPrompt,
238
- timestamp: new Date(),
239
- });
240
- }
241
- }
242
-
243
- addTool(toolName: string): boolean {
244
- const tool = globalToolRegistry.get(toolName) ||
245
- aiControlSystem.get(toolName) ||
246
- clientControlSystem.tools.get(toolName);
247
-
248
- if (tool) {
249
- this.availableTools.set(toolName, tool);
250
- if (!this.config.tools) {
251
- this.config.tools = [];
252
- }
253
- this.config.tools.push(toolName);
254
- return true;
255
- }
256
-
257
- return false;
258
- }
259
-
260
- removeTool(toolName: string): boolean {
261
- if (this.availableTools.has(toolName)) {
262
- this.availableTools.delete(toolName);
263
- if (this.config.tools) {
264
- this.config.tools = this.config.tools.filter(t => t !== toolName);
265
- }
266
- return true;
267
- }
268
- return false;
269
- }
270
-
271
- getPendingToolCalls(): AIToolCall[] {
272
- return Array.from(this.pendingToolCalls.values());
273
- }
274
-
275
- cancelToolCall(id: string): boolean {
276
- if (this.pendingToolCalls.has(id)) {
277
- const call = this.pendingToolCalls.get(id)!;
278
- call.status = 'failed';
279
- call.error = new Error('Cancelled by user');
280
- call.endTime = new Date();
281
- this.pendingToolCalls.delete(id);
282
- return true;
283
- }
284
- return false;
285
- }
286
- }
287
-
288
- // Helper function to create a tool-calling format for LLMs
289
- export function formatToolForLLM(tool: AUITool | AIControlledTool): {
290
- name: string;
291
- description: string;
292
- parameters: any;
293
- } {
294
- const metadata = globalToolRegistry.getMetadata(tool.name);
295
-
296
- return {
297
- name: tool.name,
298
- description: tool.description || metadata?.description || '',
299
- parameters: tool.schema ? schemaToOpenAIFormat(tool.schema) : {
300
- type: 'object',
301
- properties: {},
302
- },
303
- };
304
- }
305
-
306
- function schemaToOpenAIFormat(schema: z.ZodType<any>): any {
307
- if (schema instanceof z.ZodObject) {
308
- const shape = schema.shape;
309
- const properties: Record<string, any> = {};
310
- const required: string[] = [];
311
-
312
- Object.entries(shape).forEach(([key, value]: [string, any]) => {
313
- properties[key] = schemaToOpenAIFormat(value);
314
- if (!value.isOptional()) {
315
- required.push(key);
316
- }
317
- });
318
-
319
- return {
320
- type: 'object',
321
- properties,
322
- required: required.length > 0 ? required : undefined,
323
- };
324
- }
325
-
326
- if (schema instanceof z.ZodString) {
327
- return { type: 'string' };
328
- }
329
-
330
- if (schema instanceof z.ZodNumber) {
331
- return { type: 'number' };
332
- }
333
-
334
- if (schema instanceof z.ZodBoolean) {
335
- return { type: 'boolean' };
336
- }
337
-
338
- if (schema instanceof z.ZodArray) {
339
- return {
340
- type: 'array',
341
- items: schemaToOpenAIFormat(schema.element),
342
- };
343
- }
344
-
345
- if (schema instanceof z.ZodEnum) {
346
- return {
347
- type: 'string',
348
- enum: schema.options,
349
- };
350
- }
351
-
352
- return { type: 'string' };
353
- }
354
-
355
- // Pre-configured assistants
356
- export const assistants = {
357
- webDeveloper: new AIAssistant({
358
- name: 'Web Developer Assistant',
359
- description: 'Helps with web development tasks',
360
- systemPrompt: 'You are a helpful web development assistant. You can manipulate the DOM, handle forms, manage storage, and control navigation.',
361
- tools: [
362
- 'client-dom',
363
- 'client-events',
364
- 'client-forms',
365
- 'client-storage',
366
- 'client-navigation',
367
- ],
368
- capabilities: {
369
- canExecuteClientTools: true,
370
- canMakeNetworkRequests: true,
371
- },
372
- }),
373
-
374
- dataAnalyst: new AIAssistant({
375
- name: 'Data Analyst Assistant',
376
- description: 'Helps with data analysis and database operations',
377
- systemPrompt: 'You are a data analysis assistant. You can query databases, process data, and generate insights.',
378
- tools: [
379
- 'db-control',
380
- 'api-control',
381
- ],
382
- capabilities: {
383
- canExecuteServerTools: true,
384
- canAccessDatabase: true,
385
- canMakeNetworkRequests: true,
386
- },
387
- }),
388
-
389
- uiDesigner: new AIAssistant({
390
- name: 'UI Designer Assistant',
391
- description: 'Helps with UI design and animations',
392
- systemPrompt: 'You are a UI design assistant. You can create animations, control media, and manipulate visual elements.',
393
- tools: [
394
- 'client-dom',
395
- 'client-animation',
396
- 'client-media',
397
- 'ui-control',
398
- ],
399
- capabilities: {
400
- canExecuteClientTools: true,
401
- },
402
- }),
403
- };
404
-
405
- // Export a function to create custom assistants
406
- export function createAIAssistant(config: AIAssistantConfig): AIAssistant {
407
- return new AIAssistant(config);
408
- }