autoui-react 0.0.4-alpha → 0.1.0

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/dist/index.mjs CHANGED
@@ -1,105 +1,24 @@
1
- import { clsx } from 'clsx';
2
- import { twMerge } from 'tailwind-merge';
3
- import { Slot } from '@radix-ui/react-slot';
4
- import { cva } from 'class-variance-authority';
5
- import { jsx, jsxs } from 'react/jsx-runtime';
6
- import React, { useState, useEffect, useRef, useCallback, useReducer } from 'react';
7
- import { createOpenAI } from '@ai-sdk/openai';
8
- import { generateObject } from 'ai';
1
+ import { useState, useEffect, useRef, useCallback, useReducer } from 'react';
9
2
  import { z } from 'zod';
10
-
11
- var __defProp = Object.defineProperty;
12
- var __getOwnPropNames = Object.getOwnPropertyNames;
13
- var __esm = (fn, res) => function __init() {
14
- return fn && (res = (0, fn[__getOwnPropNames(fn)[0]])(fn = 0)), res;
15
- };
16
- var __export = (target, all) => {
17
- for (var name in all)
18
- __defProp(target, name, { get: all[name], enumerable: true });
19
- };
20
- function cn(...inputs) {
21
- return twMerge(clsx(inputs));
22
- }
23
- var init_utils = __esm({
24
- "src/lib/utils.ts"() {
25
- }
26
- });
27
-
28
- // components/ui/button.tsx
29
- var button_exports = {};
30
- __export(button_exports, {
31
- Button: () => Button2,
32
- buttonVariants: () => buttonVariants
33
- });
34
- function Button2({
35
- className,
36
- variant,
37
- size,
38
- asChild = false,
39
- ...props
40
- }) {
41
- const Comp = asChild ? Slot : "button";
42
- return /* @__PURE__ */ jsx(
43
- Comp,
44
- {
45
- "data-slot": "button",
46
- className: cn(buttonVariants({ variant, size, className })),
47
- ...props
48
- }
49
- );
50
- }
51
- var buttonVariants;
52
- var init_button = __esm({
53
- "components/ui/button.tsx"() {
54
- init_utils();
55
- buttonVariants = cva(
56
- "inline-flex items-center justify-center gap-2 whitespace-nowrap rounded-md text-sm font-medium transition-all disabled:pointer-events-none disabled:opacity-50 [&_svg]:pointer-events-none [&_svg:not([class*='size-'])]:size-4 shrink-0 [&_svg]:shrink-0 outline-none focus-visible:border-ring focus-visible:ring-ring/50 focus-visible:ring-[3px] aria-invalid:ring-destructive/20 dark:aria-invalid:ring-destructive/40 aria-invalid:border-destructive",
57
- {
58
- variants: {
59
- variant: {
60
- default: "bg-primary text-primary-foreground shadow-xs hover:bg-primary/90",
61
- destructive: "bg-destructive text-white shadow-xs hover:bg-destructive/90 focus-visible:ring-destructive/20 dark:focus-visible:ring-destructive/40 dark:bg-destructive/60",
62
- outline: "border bg-background shadow-xs hover:bg-accent hover:text-accent-foreground dark:bg-input/30 dark:border-input dark:hover:bg-input/50",
63
- secondary: "bg-secondary text-secondary-foreground shadow-xs hover:bg-secondary/80",
64
- ghost: "hover:bg-accent hover:text-accent-foreground dark:hover:bg-accent/50",
65
- link: "text-primary underline-offset-4 hover:underline"
66
- },
67
- size: {
68
- default: "h-9 px-4 py-2 has-[>svg]:px-3",
69
- sm: "h-8 rounded-md gap-1.5 px-3 has-[>svg]:px-2.5",
70
- lg: "h-10 rounded-md px-6 has-[>svg]:px-4",
71
- icon: "size-9"
72
- }
73
- },
74
- defaultVariants: {
75
- variant: "default",
76
- size: "default"
77
- }
78
- }
79
- );
80
- }
81
- });
3
+ import { jsxs, jsx } from 'react/jsx-runtime';
82
4
 
83
5
  // src/core/reducer.ts
84
6
  function cloneNode(node) {
85
7
  return {
86
8
  ...node,
87
- props: node.props ? { ...node.props } : null,
88
- bindings: node.bindings ? { ...node.bindings } : null,
89
- events: node.events ? { ...node.events } : null,
90
- children: node.children ? node.children.map((child) => cloneNode(child)) : null
9
+ props: node.props ? { ...node.props } : void 0,
10
+ bindings: node.bindings ? { ...node.bindings } : void 0,
11
+ events: node.events ? { ...node.events } : void 0,
12
+ children: node.children?.map((child) => cloneNode(child))
91
13
  };
92
14
  }
93
15
  function findNodeById(tree, nodeId) {
94
- if (!tree)
95
- return void 0;
96
- if (tree.id === nodeId)
97
- return tree;
16
+ if (!tree) return void 0;
17
+ if (tree.id === nodeId) return tree;
98
18
  if (tree.children) {
99
19
  for (const child of tree.children) {
100
20
  const found = findNodeById(child, nodeId);
101
- if (found)
102
- return found;
21
+ if (found) return found;
103
22
  }
104
23
  }
105
24
  return void 0;
@@ -114,15 +33,13 @@ function updateNodeById(tree, nodeId, updater) {
114
33
  if (node.children) {
115
34
  for (const child of node.children) {
116
35
  const path2 = findPath(child, id, newPath);
117
- if (path2)
118
- return path2;
36
+ if (path2) return path2;
119
37
  }
120
38
  }
121
39
  return null;
122
40
  }
123
41
  const path = findPath(result, nodeId);
124
- if (!path)
125
- return result;
42
+ if (!path) return result;
126
43
  const nodeToUpdate = path[path.length - 1];
127
44
  const updatedNode = updater(nodeToUpdate);
128
45
  if (path.length === 1) {
@@ -131,14 +48,18 @@ function updateNodeById(tree, nodeId, updater) {
131
48
  const parent = path[path.length - 2];
132
49
  const updatedParent = {
133
50
  ...parent,
134
- children: parent.children ? parent.children.map(
51
+ children: parent.children?.map(
135
52
  (child) => child.id === nodeId ? updatedNode : child
136
- ) : null
53
+ )
137
54
  };
138
55
  if (path.length === 2) {
139
56
  return updatedParent;
140
57
  }
141
- return updateNodeById(result, parent.id, () => updatedParent);
58
+ return updateNodeById(
59
+ result,
60
+ parent.id,
61
+ () => updatedParent
62
+ );
142
63
  }
143
64
  function replaceNodeById(tree, nodeId, newNode) {
144
65
  return updateNodeById(tree, nodeId, () => newNode);
@@ -165,8 +86,7 @@ function removeNodeById(tree, nodeId) {
165
86
  }
166
87
  for (const child of node.children) {
167
88
  const parent2 = findParent(child, id);
168
- if (parent2)
169
- return parent2;
89
+ if (parent2) return parent2;
170
90
  }
171
91
  }
172
92
  return null;
@@ -176,11 +96,10 @@ function removeNodeById(tree, nodeId) {
176
96
  throw new Error("Cannot remove root node");
177
97
  }
178
98
  const parent = findParent(result, nodeId);
179
- if (!parent)
180
- return result;
99
+ if (!parent) return result;
181
100
  return updateNodeById(result, parent.id, (node) => ({
182
101
  ...node,
183
- children: node.children ? node.children.filter((child) => child.id !== nodeId) : null
102
+ children: node.children?.filter((child) => child.id !== nodeId)
184
103
  }));
185
104
  }
186
105
  function uiReducer(state, action) {
@@ -197,7 +116,7 @@ function uiReducer(state, action) {
197
116
  ...state,
198
117
  layout: action.node,
199
118
  loading: false,
200
- error: null
119
+ error: void 0
201
120
  };
202
121
  }
203
122
  case "PARTIAL_UPDATE": {
@@ -206,7 +125,7 @@ function uiReducer(state, action) {
206
125
  ...state,
207
126
  layout: action.node,
208
127
  loading: false,
209
- error: null
128
+ error: void 0
210
129
  };
211
130
  }
212
131
  if (action.nodeId === "root" || action.nodeId === state.layout.id) {
@@ -214,23 +133,19 @@ function uiReducer(state, action) {
214
133
  ...state,
215
134
  layout: action.node,
216
135
  loading: false,
217
- error: null
136
+ error: void 0
218
137
  };
219
138
  }
220
139
  return {
221
140
  ...state,
222
141
  layout: replaceNodeById(state.layout, action.nodeId, action.node),
223
142
  loading: false,
224
- error: null
143
+ error: void 0
225
144
  };
226
145
  }
227
146
  case "ADD_NODE": {
228
147
  if (!state.layout) {
229
- return {
230
- ...state,
231
- error: "Cannot add node: Layout is empty.",
232
- loading: false
233
- };
148
+ return state;
234
149
  }
235
150
  return {
236
151
  ...state,
@@ -238,41 +153,21 @@ function uiReducer(state, action) {
238
153
  state.layout,
239
154
  action.parentId,
240
155
  action.node,
241
- action.index === null ? void 0 : action.index
156
+ action.index
242
157
  ),
243
158
  loading: false,
244
- error: null
159
+ error: void 0
245
160
  };
246
161
  }
247
162
  case "REMOVE_NODE": {
248
163
  if (!state.layout) {
249
- return {
250
- ...state,
251
- error: "Cannot remove node: Layout is empty.",
252
- loading: false
253
- };
254
- }
255
- try {
256
- return {
257
- ...state,
258
- layout: removeNodeById(state.layout, action.nodeId),
259
- loading: false,
260
- error: null
261
- };
262
- } catch (e) {
263
- const errorMessage = e instanceof Error ? e.message : "Failed to remove node.";
264
- return {
265
- ...state,
266
- error: errorMessage,
267
- loading: false
268
- };
164
+ return state;
269
165
  }
270
- }
271
- case "ERROR": {
272
166
  return {
273
167
  ...state,
274
- error: action.message,
275
- loading: false
168
+ layout: removeNodeById(state.layout, action.nodeId),
169
+ loading: false,
170
+ error: void 0
276
171
  };
277
172
  }
278
173
  case "LOADING": {
@@ -281,15 +176,20 @@ function uiReducer(state, action) {
281
176
  loading: action.isLoading
282
177
  };
283
178
  }
179
+ case "ERROR": {
180
+ return {
181
+ ...state,
182
+ error: action.message,
183
+ loading: false
184
+ };
185
+ }
284
186
  default:
285
187
  return state;
286
188
  }
287
189
  }
288
190
  var initialState = {
289
- layout: null,
290
- loading: false,
291
- history: [],
292
- error: null
191
+ loading: true,
192
+ history: []
293
193
  };
294
194
 
295
195
  // src/core/action-router.ts
@@ -336,7 +236,7 @@ var ActionRouter = class {
336
236
  schema,
337
237
  goal,
338
238
  history: [event],
339
- userContext: userContext || null
239
+ userContext
340
240
  },
341
241
  prompt: `Generate a new UI for the goal: "${goal}". The user just triggered: ${event.type} on node ${event.nodeId}`
342
242
  };
@@ -385,20 +285,16 @@ var ActionRouter = class {
385
285
  ...additionalContext
386
286
  }
387
287
  };
388
- const templateValues = {
389
- goal,
390
- eventType: event.type,
391
- nodeId: event.nodeId,
392
- targetNodeId,
393
- actionType: matchingRoute.actionType,
394
- ...userContext || {},
395
- // Spread the original userContext (passed to resolveRoute)
396
- ...additionalContext
397
- // Spread additionalContext afterwards (can override userContext keys)
398
- };
399
288
  const prompt = this.processTemplate(
400
289
  matchingRoute.promptTemplate,
401
- templateValues
290
+ {
291
+ goal,
292
+ eventType: event.type,
293
+ nodeId: event.nodeId,
294
+ targetNodeId,
295
+ actionType: matchingRoute.actionType,
296
+ ...additionalContext
297
+ }
402
298
  );
403
299
  return {
404
300
  actionType: matchingRoute.actionType,
@@ -466,58 +362,27 @@ var uiEventType = z.enum([
466
362
  var uiEvent = z.object({
467
363
  type: uiEventType,
468
364
  nodeId: z.string(),
469
- timestamp: z.number().nullable(),
470
- payload: z.record(z.unknown()).nullable()
471
- });
472
- z.enum(["AI_RESPONSE", "ERROR"]);
473
- var runtimeRecord = z.record(z.any()).nullable();
474
- var openAISimplifiedValue = z.string().nullable();
475
- var openAIRecordSimplifiedNullable = z.record(openAISimplifiedValue).nullable();
476
- var openAIEventPayloadSimplifiedNullable = z.record(openAISimplifiedValue).nullable();
477
- var openAIBaseNode = z.object({
478
- id: z.string(),
479
- node_type: z.string(),
480
- props: openAIRecordSimplifiedNullable,
481
- // Nullable record
482
- bindings: openAIRecordSimplifiedNullable,
483
- // Nullable record
484
- events: z.record(
485
- z.string(),
486
- z.object({
487
- action: z.string(),
488
- target: z.string(),
489
- payload: openAIEventPayloadSimplifiedNullable
490
- })
491
- ).nullable(),
492
- // Entire events object is nullable
493
- children: z.null()
494
- // Base children are null. When extended, it will be an array or null.
365
+ timestamp: z.number().optional(),
366
+ payload: z.record(z.any()).optional()
495
367
  });
496
- var openAINodeL4 = openAIBaseNode;
497
- var openAINodeL3 = openAIBaseNode.extend({
498
- children: z.array(openAINodeL4).nullable()
499
- });
500
- var openAINodeL2 = openAIBaseNode.extend({
501
- children: z.array(openAINodeL3).nullable()
502
- });
503
- var openAIUISpec = openAIBaseNode.extend({
504
- children: z.array(openAINodeL2).nullable()
505
- });
506
- var uiSpecNode = z.object({
368
+ z.enum([
369
+ "AI_RESPONSE",
370
+ "ERROR"
371
+ ]);
372
+ var uiSpecNode = z.lazy(() => z.object({
507
373
  id: z.string(),
508
- node_type: z.string(),
509
- props: runtimeRecord,
510
- bindings: runtimeRecord,
511
- events: z.record(
512
- z.string(),
513
- z.object({
514
- action: z.string(),
515
- target: z.string(),
516
- payload: runtimeRecord
517
- })
518
- ).nullable(),
519
- children: z.lazy(() => z.array(uiSpecNode)).nullable()
520
- });
374
+ type: z.string(),
375
+ // e.g., "ListView", "Button", "TextField"
376
+ props: z.record(z.any()).optional(),
377
+ bindings: z.record(z.any()).optional(),
378
+ // Data bindings
379
+ events: z.record(z.string(), z.object({
380
+ action: z.string(),
381
+ target: z.string().optional(),
382
+ payload: z.record(z.any()).optional()
383
+ })).optional(),
384
+ children: z.array(uiSpecNode).optional()
385
+ }));
521
386
  z.discriminatedUnion("type", [
522
387
  z.object({
523
388
  type: z.literal("UI_EVENT"),
@@ -536,7 +401,7 @@ z.discriminatedUnion("type", [
536
401
  type: z.literal("ADD_NODE"),
537
402
  parentId: z.string(),
538
403
  node: uiSpecNode,
539
- index: z.number().nullable()
404
+ index: z.number().optional()
540
405
  }),
541
406
  z.object({
542
407
  type: z.literal("REMOVE_NODE"),
@@ -552,16 +417,16 @@ z.discriminatedUnion("type", [
552
417
  })
553
418
  ]);
554
419
  z.object({
555
- layout: uiSpecNode.nullable(),
420
+ layout: uiSpecNode.optional(),
556
421
  loading: z.boolean(),
557
422
  history: z.array(uiEvent),
558
- error: z.string().nullable()
423
+ error: z.string().optional()
559
424
  });
560
425
  z.object({
561
426
  schema: z.record(z.unknown()),
562
427
  goal: z.string(),
563
- history: z.array(uiEvent).nullable(),
564
- userContext: z.record(z.unknown()).nullable().optional()
428
+ history: z.array(uiEvent).optional(),
429
+ userContext: z.record(z.unknown()).optional()
565
430
  });
566
431
 
567
432
  // src/core/system-events.ts
@@ -587,7 +452,7 @@ var SystemEventManager = class {
587
452
  }
588
453
  /**
589
454
  * Register a listener for a specific system event type
590
- *
455
+ *
591
456
  * @param eventType - The system event type to listen for
592
457
  * @param listener - The listener function
593
458
  * @returns Function to unregister the listener
@@ -607,7 +472,7 @@ var SystemEventManager = class {
607
472
  }
608
473
  /**
609
474
  * Emit a system event to all registered listeners
610
- *
475
+ *
611
476
  * @param event - The system event to emit
612
477
  */
613
478
  async emit(event) {
@@ -627,22 +492,14 @@ function createSystemEvent(type, data) {
627
492
  }
628
493
 
629
494
  // src/env.ts
630
- var rawApiKeyFromEnv = process.env.VITE_OPENAI_API_KEY;
631
- var defaultApiKeyLiteral = "sk-proj-literal-default-for-debug-in-env-ts";
632
- var env = {
633
- MOCK_PLANNER: process.env.VITE_MOCK_PLANNER || "1",
634
- // Simplified MOCK_PLANNER assignment
635
- NODE_ENV: process.env.VITE_NODE_ENV || "development",
636
- // Simplified NODE_ENV assignment
637
- OPENAI_API_KEY: rawApiKeyFromEnv === void 0 ? defaultApiKeyLiteral : rawApiKeyFromEnv
638
- };
495
+ ({
496
+ MOCK_PLANNER: import.meta.env?.VITE_MOCK_PLANNER || "1",
497
+ NODE_ENV: import.meta.env?.MODE || "development"
498
+ // Add other environment variables as needed
499
+ });
639
500
 
640
501
  // src/core/planner.ts
641
- var strictOpenAI = createOpenAI({
642
- compatibility: "strict"
643
- // Required for structured outputs with OpenAI API
644
- });
645
- function buildPrompt(input, customPrompt) {
502
+ function buildPrompt(input, targetNodeId, customPrompt) {
646
503
  const { schema, goal, history, userContext } = input;
647
504
  const schemaInfo = Object.entries(schema).map(([tableName, tableSchema]) => {
648
505
  return `Table: ${tableName}
@@ -655,9 +512,6 @@ Schema: ${JSON.stringify(tableSchema)}`;
655
512
 
656
513
  User Context:
657
514
  ${JSON.stringify(userContext)}` : "";
658
- if (customPrompt) {
659
- return customPrompt;
660
- }
661
515
  return `
662
516
  You are an expert UI generator.
663
517
  Create a user interface that achieves the following goal: "${goal}"
@@ -671,10 +525,10 @@ ${recentEvents}${userContextSection}
671
525
  Generate a complete UI specification in JSON format that matches the following TypeScript type:
672
526
  type UISpecNode = {
673
527
  id: string;
674
- node_type: string;
675
- props?: Record<string, unknown>;
676
- bindings?: Record<string, unknown>;
677
- events?: Record<string, { action: string; target: string; payload?: Record<string, unknown>; }>;
528
+ type: string;
529
+ props?: Record<string, any>;
530
+ bindings?: Record<string, any>;
531
+ events?: Record<string, { action: string; target?: string; payload?: Record<string, any>; }>;
678
532
  children?: UISpecNode[];
679
533
  };
680
534
 
@@ -684,419 +538,211 @@ UI Guidance:
684
538
  3. Include navigation between related views when needed
685
539
  4. Keep the interface simple and intuitive
686
540
  5. Bind to schema data where appropriate
687
- 6. Provide event handlers for user interactions - make sure to always include both action and target properties
541
+ 6. Provide event handlers for user interactions
688
542
 
689
543
  Respond ONLY with the JSON UI specification and no other text.
690
544
  `;
691
545
  }
692
546
  function mockPlanner(input, targetNodeId, customPrompt) {
693
- if (customPrompt) {
694
- console.log("mockPlanner received customPrompt:", customPrompt);
695
- }
696
- const taskSchema = input.schema.tasks;
697
- const taskData = taskSchema?.sampleData || [
698
- {
699
- id: "1",
700
- title: "Example Task 1",
701
- description: "This is a sample task",
702
- status: "pending",
703
- priority: "medium"
704
- },
705
- {
706
- id: "2",
707
- title: "Example Task 2",
708
- description: "Another sample task",
709
- status: "completed",
710
- priority: "high"
711
- }
712
- ];
713
547
  const mockNode = {
714
548
  id: targetNodeId || "root",
715
- node_type: "Container",
716
- props: {
717
- className: "p-4 space-y-6"
718
- },
719
- bindings: null,
720
- events: null,
549
+ type: "Container",
550
+ props: { title: "Mock UI" },
721
551
  children: [
722
552
  {
723
- id: "header-1",
724
- node_type: "Header",
725
- props: {
726
- title: "Task Management Dashboard",
727
- className: "mb-4"
728
- },
729
- bindings: null,
730
- events: null,
731
- children: null
732
- },
733
- {
734
- id: "main-content",
735
- node_type: "Container",
736
- props: {
737
- className: "grid grid-cols-1 gap-6 md:grid-cols-3"
738
- },
739
- bindings: null,
740
- events: null,
741
- children: [
742
- {
743
- id: "tasks-container",
744
- node_type: "Container",
745
- props: {
746
- className: "md:col-span-2"
747
- },
748
- bindings: null,
749
- events: null,
750
- children: [
751
- {
752
- id: "list-heading",
753
- node_type: "Container",
754
- props: {
755
- className: "flex justify-between items-center mb-4"
756
- },
757
- bindings: null,
758
- events: null,
759
- children: [
760
- {
761
- id: "list-title",
762
- node_type: "Header",
763
- props: {
764
- title: "Tasks",
765
- className: "border-none p-0 m-0"
766
- },
767
- bindings: null,
768
- events: null,
769
- children: null
770
- },
771
- {
772
- id: "add-task-button",
773
- node_type: "Button",
774
- props: {
775
- label: "Add Task",
776
- variant: "default"
777
- },
778
- bindings: null,
779
- events: {
780
- onClick: {
781
- action: "ADD_TASK",
782
- target: "tasks-container",
783
- payload: {}
784
- }
785
- },
786
- children: null
787
- }
788
- ]
789
- },
790
- {
791
- id: "task-list",
792
- node_type: "ListView",
793
- props: {
794
- selectable: "true"
795
- },
796
- bindings: {
797
- items: JSON.stringify(taskData),
798
- fields: JSON.stringify([
799
- { key: "id", label: "ID" },
800
- { key: "title", label: "Title" },
801
- { key: "status", label: "Status" },
802
- { key: "priority", label: "Priority" }
803
- ])
804
- },
805
- events: {
806
- onSelect: {
807
- action: "SELECT_TASK",
808
- target: "task-detail",
809
- payload: {
810
- source: "task-list"
811
- }
812
- }
813
- },
814
- children: null
815
- }
816
- ]
817
- },
818
- {
819
- id: "task-detail",
820
- node_type: "Detail",
821
- props: {
822
- title: "Task Details",
823
- visible: "true"
824
- },
825
- bindings: {
826
- data: JSON.stringify(taskData[0]),
827
- fields: JSON.stringify([
828
- { key: "title", label: "Title", type: "heading" },
829
- { key: "description", label: "Description", type: "content" },
830
- { key: "status", label: "Status" },
831
- { key: "priority", label: "Priority" },
832
- { key: "dueDate", label: "Due Date" }
833
- ])
834
- },
835
- events: {
836
- onBack: {
837
- action: "CLOSE_DETAIL",
838
- target: "task-detail",
839
- payload: {}
840
- }
841
- },
842
- children: null
843
- }
844
- ]
553
+ id: "text-1",
554
+ type: "Text",
555
+ props: { text: "This is a mock UI for testing" }
845
556
  }
846
557
  ]
847
558
  };
848
559
  return mockNode;
849
560
  }
850
- async function callPlannerLLM(input, routeResolution) {
851
- await systemEvents.emit(
852
- createSystemEvent("PLAN_START" /* PLAN_START */, { plannerInput: input })
853
- );
854
- if (env.MOCK_PLANNER === "1" || !env.OPENAI_API_KEY) {
855
- console.warn(
856
- "Using mock planner because MOCK_PLANNER is enabled or OPENAI_API_KEY is not available"
857
- );
858
- return mockPlanner(input);
859
- }
860
- const startTime = Date.now();
861
- const prompt = routeResolution?.prompt || buildPrompt(input);
862
- await systemEvents.emit(
863
- createSystemEvent("PLAN_PROMPT_CREATED" /* PLAN_PROMPT_CREATED */, { prompt })
864
- );
865
- try {
866
- const { object: uiSpec } = await generateObject({
867
- model: strictOpenAI("gpt-4o", { structuredOutputs: true }),
868
- schema: openAIUISpec,
869
- messages: [{ role: "user", content: prompt }],
870
- temperature: 0.2,
871
- maxTokens: 4e3
872
- });
873
- await systemEvents.emit(
874
- createSystemEvent("PLAN_COMPLETE" /* PLAN_COMPLETE */, {
875
- layout: uiSpec,
876
- executionTimeMs: Date.now() - startTime
877
- })
878
- );
879
- return uiSpec;
880
- } catch (error) {
881
- console.error("Error calling LLM planner:", error);
882
- await systemEvents.emit(
883
- createSystemEvent("PLAN_ERROR" /* PLAN_ERROR */, {
884
- error: error instanceof Error ? error : new Error(String(error))
885
- })
886
- );
887
- throw error;
888
- }
889
- }
890
- async function processEvent(event, router, schema, layout, dataContext, goal, userContext) {
891
- const routeResolution = await router.resolveRoute(
892
- event,
893
- schema,
894
- layout || null,
895
- dataContext,
896
- goal,
897
- userContext
898
- );
899
- if (!routeResolution) {
900
- throw new Error(
901
- `No route found for event type: ${event.type}, node: ${event.nodeId}`
902
- );
903
- }
904
- if (routeResolution.actionType.toString() === "NoOp") {
905
- if (!layout)
906
- throw new Error("Layout is undefined and action is NoOp");
907
- return layout;
908
- }
909
- const plannerInputForLLM = routeResolution.plannerInput;
910
- const newLayout = await callPlannerLLM(plannerInputForLLM, routeResolution);
911
- return newLayout;
912
- }
913
561
 
914
562
  // src/core/state.ts
563
+ var useChat = (config) => ({
564
+ append: async (message) => {
565
+ },
566
+ data: { content: "{}" },
567
+ isLoading: false,
568
+ error: null,
569
+ stop: () => {
570
+ }
571
+ });
915
572
  function useUIStateEngine({
916
573
  schema,
917
574
  goal,
918
575
  userContext,
919
576
  mockMode = false,
920
- planningConfig,
577
+ planningConfig = {},
921
578
  router = createDefaultRouter(),
922
579
  dataContext = {},
923
580
  enablePartialUpdates = false
924
581
  }) {
925
- if (userContext === null) {
926
- console.warn(
927
- "useUIStateEngine: userContext was explicitly set to null. This is an allowed but discouraged value. Consider using undefined if you intend to omit the user context."
928
- );
929
- }
930
582
  const [state, dispatch] = useReducer(uiReducer, initialState);
931
- const handleEvent = useCallback(
932
- async (event) => {
933
- dispatch({ type: "UI_EVENT", event });
934
- dispatch({ type: "LOADING", isLoading: true });
935
- try {
936
- let resolvedNode;
937
- let actionTypeForDispatch = "FULL_REFRESH" /* FULL_REFRESH */;
938
- let targetNodeIdForDispatch = "root";
939
- if (enablePartialUpdates) {
940
- const route = router.resolveRoute(
941
- event,
942
- schema,
943
- state.layout,
944
- dataContext,
945
- goal,
946
- userContext
947
- );
948
- if (route) {
949
- console.log("Resolved route:", route);
950
- actionTypeForDispatch = route.actionType;
951
- targetNodeIdForDispatch = route.targetNodeId;
952
- systemEvents.emit(
953
- createSystemEvent("PLAN_START" /* PLAN_START */, {
954
- plannerInput: route.plannerInput
955
- })
956
- );
957
- if (mockMode) {
958
- resolvedNode = mockPlanner(
959
- route.plannerInput,
960
- route.targetNodeId,
961
- route.prompt
962
- );
963
- } else {
964
- resolvedNode = await callPlannerLLM(route.plannerInput, route);
965
- }
966
- } else {
967
- const input = {
968
- schema,
969
- goal,
970
- history: [...state.history, event],
971
- userContext
972
- };
973
- if (mockMode) {
974
- resolvedNode = mockPlanner(input);
975
- } else {
976
- resolvedNode = await callPlannerLLM(input);
977
- }
978
- }
979
- } else {
980
- const input = {
981
- schema,
982
- goal,
983
- history: [...state.history, event],
984
- // event is already in history from UI_EVENT dispatch
985
- userContext
986
- };
987
- if (mockMode) {
988
- resolvedNode = mockPlanner(input);
989
- } else {
990
- resolvedNode = await callPlannerLLM(input);
991
- }
992
- }
993
- switch (actionTypeForDispatch) {
994
- case "UPDATE_NODE" /* UPDATE_NODE */:
995
- case "SHOW_DETAIL" /* SHOW_DETAIL */:
996
- case "HIDE_DETAIL" /* HIDE_DETAIL */:
997
- case "TOGGLE_STATE" /* TOGGLE_STATE */:
998
- case "ADD_DROPDOWN" /* ADD_DROPDOWN */:
999
- case "UPDATE_FORM" /* UPDATE_FORM */:
1000
- case "NAVIGATE" /* NAVIGATE */:
1001
- dispatch({
1002
- type: "PARTIAL_UPDATE",
1003
- nodeId: targetNodeIdForDispatch,
1004
- node: resolvedNode
1005
- });
1006
- break;
1007
- case "FULL_REFRESH" /* FULL_REFRESH */:
1008
- default:
1009
- dispatch({ type: "AI_RESPONSE", node: resolvedNode });
1010
- break;
1011
- }
1012
- } catch (e) {
1013
- const errorMessage = e instanceof Error ? e.message : String(e);
1014
- dispatch({ type: "ERROR", message: errorMessage });
583
+ const { append, data, isLoading, error, stop } = useChat();
584
+ const handleEvent = useCallback((event) => {
585
+ dispatch({ type: "UI_EVENT", event });
586
+ if (enablePartialUpdates) {
587
+ const route = router.resolveRoute(
588
+ event,
589
+ schema,
590
+ state.layout,
591
+ dataContext,
592
+ goal,
593
+ userContext
594
+ );
595
+ if (route) {
596
+ console.log("Resolved route:", route);
1015
597
  systemEvents.emit(
1016
- createSystemEvent("PLAN_ERROR" /* PLAN_ERROR */, {
1017
- error: e instanceof Error ? e : new Error(String(e))
598
+ createSystemEvent("PLAN_START" /* PLAN_START */, {
599
+ plannerInput: route.plannerInput
1018
600
  })
1019
601
  );
1020
- } finally {
1021
- dispatch({ type: "LOADING", isLoading: false });
602
+ if (mockMode) {
603
+ const node = mockPlanner(route.plannerInput, route.targetNodeId, route.prompt);
604
+ switch (route.actionType) {
605
+ case "FULL_REFRESH" /* FULL_REFRESH */:
606
+ dispatch({ type: "AI_RESPONSE", node });
607
+ break;
608
+ case "UPDATE_NODE" /* UPDATE_NODE */:
609
+ case "SHOW_DETAIL" /* SHOW_DETAIL */:
610
+ case "HIDE_DETAIL" /* HIDE_DETAIL */:
611
+ case "TOGGLE_STATE" /* TOGGLE_STATE */:
612
+ case "ADD_DROPDOWN" /* ADD_DROPDOWN */:
613
+ case "UPDATE_FORM" /* UPDATE_FORM */:
614
+ case "NAVIGATE" /* NAVIGATE */:
615
+ dispatch({
616
+ type: "PARTIAL_UPDATE",
617
+ nodeId: route.targetNodeId,
618
+ node
619
+ });
620
+ break;
621
+ }
622
+ } else {
623
+ const prompt = route.prompt;
624
+ systemEvents.emit(
625
+ createSystemEvent("PLAN_PROMPT_CREATED" /* PLAN_PROMPT_CREATED */, { prompt })
626
+ );
627
+ append({
628
+ content: prompt,
629
+ role: "user"
630
+ });
631
+ sessionStorage.setItem("currentRoute", JSON.stringify({
632
+ actionType: route.actionType,
633
+ targetNodeId: route.targetNodeId
634
+ }));
635
+ }
636
+ return;
1022
637
  }
1023
- },
1024
- [
1025
- // append, // REMOVE
1026
- goal,
638
+ }
639
+ const input = {
1027
640
  schema,
1028
- state.history,
1029
- // Keep state.history if input preparation needs it
1030
- state.layout,
1031
- // stop, // REMOVE
1032
- userContext,
1033
- router,
1034
- mockMode,
1035
- dataContext,
1036
- enablePartialUpdates,
1037
- dispatch
1038
- // Add dispatch
1039
- ]
1040
- );
641
+ goal,
642
+ history: [...state.history, event],
643
+ userContext
644
+ };
645
+ if (mockMode) {
646
+ const node = mockPlanner();
647
+ dispatch({ type: "AI_RESPONSE", node });
648
+ } else {
649
+ const prompt = buildPrompt(input);
650
+ append({
651
+ content: prompt,
652
+ role: "user"
653
+ });
654
+ }
655
+ }, [append, goal, schema, state.history, state.layout, stop, userContext, router, mockMode, dataContext, enablePartialUpdates]);
1041
656
  useEffect(() => {
1042
- const initialFetch = async () => {
1043
- dispatch({ type: "LOADING", isLoading: true });
657
+ {
1044
658
  try {
1045
- const input = {
1046
- schema,
1047
- goal,
1048
- history: [],
1049
- userContext
1050
- };
1051
- let node;
1052
- if (mockMode) {
1053
- node = mockPlanner(input);
659
+ systemEvents.emit(
660
+ createSystemEvent("PLAN_RESPONSE_CHUNK" /* PLAN_RESPONSE_CHUNK */, {
661
+ chunk: data.content,
662
+ isComplete: true
663
+ })
664
+ );
665
+ const jsonMatch = data.content.match(/```(?:json)?\s*([\s\S]*?)\s*```/) || [null, data.content];
666
+ const jsonStr = jsonMatch[1].trim();
667
+ const parsedJson = JSON.parse(jsonStr);
668
+ const validatedNode = uiSpecNode.parse(parsedJson);
669
+ const routeInfoStr = sessionStorage.getItem("currentRoute");
670
+ if (routeInfoStr && enablePartialUpdates) {
671
+ try {
672
+ const routeInfo = JSON.parse(routeInfoStr);
673
+ switch (routeInfo.actionType) {
674
+ case "FULL_REFRESH" /* FULL_REFRESH */:
675
+ dispatch({ type: "AI_RESPONSE", node: validatedNode });
676
+ break;
677
+ case "UPDATE_NODE" /* UPDATE_NODE */:
678
+ case "SHOW_DETAIL" /* SHOW_DETAIL */:
679
+ case "HIDE_DETAIL" /* HIDE_DETAIL */:
680
+ case "TOGGLE_STATE" /* TOGGLE_STATE */:
681
+ case "ADD_DROPDOWN" /* ADD_DROPDOWN */:
682
+ case "UPDATE_FORM" /* UPDATE_FORM */:
683
+ case "NAVIGATE" /* NAVIGATE */:
684
+ dispatch({
685
+ type: "PARTIAL_UPDATE",
686
+ nodeId: routeInfo.targetNodeId,
687
+ node: validatedNode
688
+ });
689
+ break;
690
+ default:
691
+ dispatch({ type: "AI_RESPONSE", node: validatedNode });
692
+ }
693
+ sessionStorage.removeItem("currentRoute");
694
+ } catch (e) {
695
+ console.error("Error parsing route info:", e);
696
+ dispatch({ type: "AI_RESPONSE", node: validatedNode });
697
+ }
1054
698
  } else {
1055
- node = await callPlannerLLM(input);
699
+ dispatch({ type: "AI_RESPONSE", node: validatedNode });
1056
700
  }
1057
- dispatch({ type: "AI_RESPONSE", node });
1058
- } catch (e) {
1059
- const errorMessage = e instanceof Error ? e.message : String(e);
1060
- dispatch({ type: "ERROR", message: errorMessage });
1061
701
  systemEvents.emit(
1062
- // Also emit system event for initial load error
702
+ createSystemEvent("PLAN_COMPLETE" /* PLAN_COMPLETE */, {
703
+ layout: validatedNode,
704
+ executionTimeMs: 0
705
+ // Not available here
706
+ })
707
+ );
708
+ } catch (parseError) {
709
+ console.error("Failed to parse LLM response:", parseError);
710
+ dispatch({
711
+ type: "ERROR",
712
+ message: "Failed to parse LLM response"
713
+ });
714
+ systemEvents.emit(
1063
715
  createSystemEvent("PLAN_ERROR" /* PLAN_ERROR */, {
1064
- error: e instanceof Error ? e : new Error(String(e))
716
+ error: parseError instanceof Error ? parseError : new Error("Parse error")
1065
717
  })
1066
718
  );
1067
- } finally {
1068
- dispatch({ type: "LOADING", isLoading: false });
1069
719
  }
720
+ }
721
+ }, [data.content, error, isLoading, enablePartialUpdates]);
722
+ useEffect(() => {
723
+ const input = {
724
+ schema,
725
+ goal,
726
+ history: [],
727
+ userContext
1070
728
  };
1071
- initialFetch();
1072
- }, [goal, schema, userContext, mockMode, dispatch]);
729
+ if (mockMode) {
730
+ const node = mockPlanner();
731
+ dispatch({ type: "AI_RESPONSE", node });
732
+ } else {
733
+ const prompt = buildPrompt(input);
734
+ append({
735
+ content: prompt,
736
+ role: "user"
737
+ });
738
+ }
739
+ }, [append, goal, schema, userContext, mockMode]);
1073
740
  return {
1074
741
  state,
1075
742
  dispatch,
1076
743
  handleEvent
1077
744
  };
1078
745
  }
1079
- z.enum([
1080
- // Layout components
1081
- "Container",
1082
- "Card",
1083
- "Header",
1084
- // Input components
1085
- "Button",
1086
- "Input",
1087
- "Select",
1088
- "Textarea",
1089
- "Checkbox",
1090
- "RadioGroup",
1091
- // Data display components
1092
- "ListView",
1093
- "Detail",
1094
- "Tabs",
1095
- "Dialog",
1096
- // Typography
1097
- "Heading",
1098
- "Text"
1099
- ]);
1100
746
  var ShimmerBlock = () => /* @__PURE__ */ jsx("div", { className: "w-full h-8 bg-gray-200 animate-pulse rounded" });
1101
747
  var ShimmerTable = ({ rows = 3 }) => /* @__PURE__ */ jsxs("div", { className: "w-full space-y-2", children: [
1102
748
  /* @__PURE__ */ jsx("div", { className: "w-full h-10 bg-gray-200 animate-pulse rounded" }),
@@ -1110,259 +756,117 @@ var ShimmerCard = () => /* @__PURE__ */ jsxs("div", { className: "w-full p-4 spa
1110
756
  /* @__PURE__ */ jsx("div", { className: "w-5/6 h-4 bg-gray-200 animate-pulse rounded" })
1111
757
  ] })
1112
758
  ] });
1113
- var Container = (props) => /* @__PURE__ */ jsx("div", { className: `autoui-mock-container ${props.className || ""}`, children: props.children });
1114
- var Header = ({
1115
- title,
1116
- className
1117
- }) => /* @__PURE__ */ jsx(
1118
- "header",
1119
- {
1120
- className: `py-4 px-6 border-b border-gray-300 mb-4 bg-gray-50 dark:bg-gray-800 ${className || ""}`,
1121
- children: /* @__PURE__ */ jsx("h1", { className: "text-xl font-semibold text-gray-800 dark:text-white", children: title })
1122
- }
1123
- );
759
+ var Container = (props) => /* @__PURE__ */ jsx("div", { className: `w-full ${props.className || ""}`, style: props.style, children: props.children });
760
+ var Header = ({ title }) => /* @__PURE__ */ jsx("header", { className: "py-4 px-6 border-b mb-4", children: /* @__PURE__ */ jsx("h1", { className: "text-xl font-semibold", children: title }) });
1124
761
  var Button = ({ onClick, children, variant = "default" }) => /* @__PURE__ */ jsx(
1125
762
  "button",
1126
763
  {
1127
- className: `px-4 py-2 rounded-md font-medium transition-colors ${variant === "default" ? "bg-blue-600 text-white hover:bg-blue-700" : variant === "outline" ? "border border-gray-300 dark:border-gray-600 text-gray-700 dark:text-gray-300 hover:bg-gray-50 dark:hover:bg-gray-800" : "bg-red-600 text-white hover:bg-red-700"}`,
764
+ className: `px-4 py-2 rounded font-medium ${variant === "default" ? "bg-blue-600 text-white" : variant === "outline" ? "border border-gray-300 text-gray-700" : "bg-red-600 text-white"}`,
1128
765
  onClick,
1129
766
  children
1130
767
  }
1131
768
  );
1132
- var Table = ({ items = [], fields = [], onSelect, selectable }) => /* @__PURE__ */ jsx("div", { className: "w-full border border-gray-300 dark:border-gray-700 rounded-lg overflow-hidden shadow-sm", children: /* @__PURE__ */ jsxs("table", { className: "w-full", children: [
1133
- /* @__PURE__ */ jsx("thead", { className: "bg-gray-100 dark:bg-gray-800 border-b border-gray-300 dark:border-gray-700", children: /* @__PURE__ */ jsx("tr", { children: fields.map((field) => /* @__PURE__ */ jsx(
1134
- "th",
1135
- {
1136
- className: "px-6 py-3 text-left text-xs font-medium text-gray-700 dark:text-gray-300 uppercase tracking-wider",
1137
- children: field.label
1138
- },
1139
- field.key
1140
- )) }) }),
1141
- /* @__PURE__ */ jsx("tbody", { className: "bg-white dark:bg-gray-900 divide-y divide-gray-200 dark:divide-gray-700", children: items.map((item, index) => /* @__PURE__ */ jsx(
769
+ var Table = ({ items = [], fields = [], onSelect, selectable }) => /* @__PURE__ */ jsx("div", { className: "w-full border rounded-lg overflow-hidden", children: /* @__PURE__ */ jsxs("table", { className: "w-full", children: [
770
+ /* @__PURE__ */ jsx("thead", { className: "bg-gray-50", children: /* @__PURE__ */ jsx("tr", { children: fields.map((field) => /* @__PURE__ */ jsx("th", { className: "px-6 py-3 text-left text-xs font-medium text-gray-500 uppercase tracking-wider", children: field.label }, field.key)) }) }),
771
+ /* @__PURE__ */ jsx("tbody", { className: "bg-white divide-y divide-gray-200", children: items.map((item, index) => /* @__PURE__ */ jsx(
1142
772
  "tr",
1143
773
  {
1144
774
  onClick: () => selectable && onSelect && onSelect(item),
1145
- className: selectable ? "cursor-pointer hover:bg-gray-100 dark:hover:bg-gray-800" : "",
1146
- children: fields.map((field) => /* @__PURE__ */ jsx(
1147
- "td",
1148
- {
1149
- className: "px-6 py-4 whitespace-nowrap text-sm text-gray-800 dark:text-gray-300",
1150
- children: item[field.key] ?? ""
1151
- },
1152
- field.key
1153
- ))
775
+ className: selectable ? "cursor-pointer hover:bg-gray-50" : "",
776
+ children: fields.map((field) => /* @__PURE__ */ jsx("td", { className: "px-6 py-4 whitespace-nowrap text-sm text-gray-500", children: item[field.key] }, field.key))
1154
777
  },
1155
778
  index
1156
779
  )) })
1157
780
  ] }) });
1158
781
  var Detail = ({ data, fields = [], title, visible = true, onBack }) => {
1159
- if (!visible)
1160
- return null;
1161
- return /* @__PURE__ */ jsxs("div", { className: "w-full border border-gray-300 dark:border-gray-700 rounded-lg p-6 space-y-4 bg-white dark:bg-gray-900 shadow-sm", children: [
1162
- /* @__PURE__ */ jsxs("div", { className: "flex justify-between items-center border-b border-gray-200 dark:border-gray-700 pb-3", children: [
1163
- title && /* @__PURE__ */ jsx("h2", { className: "text-lg font-medium text-gray-800 dark:text-white", children: title }),
782
+ if (!visible) return null;
783
+ return /* @__PURE__ */ jsxs("div", { className: "w-full border rounded-lg p-6 space-y-4", children: [
784
+ /* @__PURE__ */ jsxs("div", { className: "flex justify-between items-center", children: [
785
+ title && /* @__PURE__ */ jsx("h2", { className: "text-lg font-medium", children: title }),
1164
786
  onBack && /* @__PURE__ */ jsx(Button, { variant: "outline", onClick: onBack, children: "Back" })
1165
787
  ] }),
1166
788
  /* @__PURE__ */ jsx("div", { className: "space-y-4", children: fields.map((field) => {
1167
789
  if (field.type === "heading") {
1168
- return /* @__PURE__ */ jsx(
1169
- "h3",
1170
- {
1171
- className: "text-xl font-semibold text-gray-800 dark:text-white",
1172
- children: data?.[field.key] ?? ""
1173
- },
1174
- field.key
1175
- );
790
+ return /* @__PURE__ */ jsx("h3", { className: "text-xl font-semibold", children: data?.[field.key] }, field.key);
1176
791
  }
1177
792
  if (field.type === "content") {
1178
- return /* @__PURE__ */ jsx(
1179
- "div",
1180
- {
1181
- className: "text-sm text-gray-700 dark:text-gray-300",
1182
- children: data?.[field.key] ?? ""
1183
- },
1184
- field.key
1185
- );
793
+ return /* @__PURE__ */ jsx("div", { className: "text-sm text-gray-700", children: data?.[field.key] }, field.key);
1186
794
  }
1187
- return /* @__PURE__ */ jsxs(
1188
- "div",
1189
- {
1190
- className: "flex flex-col border-b border-gray-100 dark:border-gray-800 py-2",
1191
- children: [
1192
- field.label && /* @__PURE__ */ jsx("span", { className: "text-xs text-gray-600 dark:text-gray-400 font-medium", children: field.label }),
1193
- /* @__PURE__ */ jsx("span", { className: "text-sm text-gray-800 dark:text-gray-200", children: data?.[field.key] ?? "" })
1194
- ]
1195
- },
1196
- field.key
1197
- );
795
+ return /* @__PURE__ */ jsxs("div", { className: "flex flex-col", children: [
796
+ field.label && /* @__PURE__ */ jsx("span", { className: "text-xs text-gray-500", children: field.label }),
797
+ /* @__PURE__ */ jsx("span", { className: "text-sm", children: data?.[field.key] })
798
+ ] }, field.key);
1198
799
  }) })
1199
800
  ] });
1200
801
  };
1201
- var getSafeProp = (props, key, validator, defaultValue) => {
1202
- if (props && typeof props === "object" && key in props) {
1203
- const value = props[key];
1204
- if (validator(value)) {
1205
- return value;
1206
- }
1207
- }
1208
- return defaultValue;
1209
- };
1210
- var isObject = (value) => typeof value === "object" && value !== null;
1211
- var isString = (value) => typeof value === "string";
1212
- var isBoolean = (value) => typeof value === "boolean";
1213
- var isCSSProperties = (value) => isObject(value);
1214
- var isButtonVariant = (value) => isString(value) && ["default", "outline", "destructive"].includes(value);
1215
- var getSafeBinding = (bindings, key, validator, defaultValue) => {
1216
- if (bindings && typeof bindings === "object" && key in bindings) {
1217
- const value = bindings[key];
1218
- if (validator(value)) {
1219
- return value;
1220
- }
1221
- }
1222
- return defaultValue;
1223
- };
1224
- var isArrayOf = (itemValidator) => (arr) => Array.isArray(arr) && arr.every(itemValidator);
1225
- var isReactNode = (value) => {
1226
- return typeof value === "string" || typeof value === "number" || typeof value === "boolean" || value === null || typeof value === "undefined" || typeof value === "object" && value !== null && "$$typeof" in value;
1227
- };
1228
- var isRecordWithReactNodeValues = (value) => isObject(value) && Object.values(value).every(isReactNode);
1229
- var isFieldObject = (item) => isObject(item) && isString(item.key) && isString(item.label);
1230
- var isDetailFieldObject = (item) => isObject(item) && isString(item.key) && isString(item.label) && (item.type === void 0 || isString(item.type));
1231
- var createEventHandler = (node, eventName, uiEventType2, processEvent2) => {
1232
- const eventConfig = node.events?.[uiEventType2];
1233
- if (!processEvent2 || !eventConfig)
1234
- return void 0;
1235
- return (eventPayload) => {
1236
- const fullEvent = {
1237
- type: uiEventType2,
1238
- nodeId: node.id,
1239
- timestamp: Date.now(),
1240
- payload: {
1241
- ...eventConfig.payload || {},
1242
- ...eventPayload || {}
1243
- }
1244
- };
1245
- processEvent2(fullEvent);
802
+ var createEventHandler = (node, eventName) => {
803
+ const eventConfig = node.events?.[eventName];
804
+ if (!eventConfig) return void 0;
805
+ return () => {
806
+ console.log(`Event triggered: ${eventName} on node ${node.id}`, {
807
+ action: eventConfig.action,
808
+ target: eventConfig.target,
809
+ payload: eventConfig.payload
810
+ });
1246
811
  };
1247
812
  };
1248
813
  var adapterMap = {
1249
- Container: (node, processEvent2) => /* @__PURE__ */ jsx(
1250
- Container,
814
+ Container: (node) => /* @__PURE__ */ jsx(Container, { style: node.props?.style, className: node.props?.className, children: node.children?.map((child) => renderNode(child)) }),
815
+ Header: (node) => /* @__PURE__ */ jsx(Header, { title: node.props?.title || "Untitled" }),
816
+ Button: (node) => /* @__PURE__ */ jsx(
817
+ Button,
1251
818
  {
1252
- style: getSafeProp(node.props, "style", isCSSProperties, {}),
1253
- className: getSafeProp(node.props, "className", isString, ""),
1254
- children: node.children?.map((child) => renderNode(child, processEvent2))
819
+ variant: node.props?.variant,
820
+ onClick: createEventHandler(node, "onClick"),
821
+ children: node.props?.label || "Button"
1255
822
  }
1256
823
  ),
1257
- Header: (node) => /* @__PURE__ */ jsx(
1258
- Header,
824
+ ListView: (node) => /* @__PURE__ */ jsx(
825
+ Table,
1259
826
  {
1260
- title: getSafeProp(node.props, "title", isString, "Untitled"),
1261
- className: getSafeProp(node.props, "className", isString, "")
827
+ items: node.bindings?.items || [],
828
+ fields: node.bindings?.fields || [],
829
+ selectable: node.props?.selectable,
830
+ onSelect: createEventHandler(node, "onSelect")
1262
831
  }
1263
832
  ),
1264
- Button: (node, processEvent2) => /* @__PURE__ */ jsx(
1265
- Button,
833
+ Detail: (node) => /* @__PURE__ */ jsx(
834
+ Detail,
1266
835
  {
1267
- variant: getSafeProp(node.props, "variant", isButtonVariant, "default"),
1268
- onClick: createEventHandler(node, "onClick", "CLICK", processEvent2),
1269
- children: getSafeProp(node.props, "label", isString, "Button")
836
+ data: node.bindings?.data,
837
+ fields: node.bindings?.fields || [],
838
+ title: node.props?.title,
839
+ visible: node.props?.visible !== false,
840
+ onBack: createEventHandler(node, "onBack")
1270
841
  }
1271
- ),
1272
- ListView: (node, processEvent2) => {
1273
- const items = getSafeBinding(
1274
- node.bindings,
1275
- "items",
1276
- isArrayOf(isRecordWithReactNodeValues),
1277
- []
1278
- );
1279
- const fields = getSafeBinding(
1280
- node.bindings,
1281
- "fields",
1282
- isArrayOf(isFieldObject),
1283
- []
1284
- );
1285
- const selectable = getSafeProp(node.props, "selectable", isBoolean, false);
1286
- return /* @__PURE__ */ jsx(
1287
- Table,
1288
- {
1289
- items,
1290
- fields,
1291
- selectable,
1292
- onSelect: (item) => {
1293
- const handler = createEventHandler(
1294
- node,
1295
- "onSelect",
1296
- "CLICK",
1297
- processEvent2
1298
- );
1299
- if (handler) {
1300
- handler({ selectedItem: item });
1301
- }
1302
- }
1303
- }
1304
- );
1305
- },
1306
- Detail: (node, processEvent2) => {
1307
- const data = getSafeBinding(
1308
- node.bindings,
1309
- "data",
1310
- isRecordWithReactNodeValues,
1311
- {}
1312
- );
1313
- const fields = getSafeBinding(
1314
- node.bindings,
1315
- "fields",
1316
- isArrayOf(isDetailFieldObject),
1317
- []
1318
- );
1319
- const title = getSafeProp(node.props, "title", isString, "");
1320
- const visible = getSafeProp(node.props, "visible", isBoolean, true);
1321
- return /* @__PURE__ */ jsx(
1322
- Detail,
1323
- {
1324
- data,
1325
- fields,
1326
- title,
1327
- visible,
1328
- onBack: createEventHandler(node, "onBack", "CLICK", processEvent2)
1329
- }
1330
- );
1331
- }
842
+ )
1332
843
  };
1333
- function renderNode(node, processEvent2) {
1334
- const mappedComponent = adapterMap[node.node_type];
1335
- if (mappedComponent) {
1336
- return mappedComponent(node, processEvent2);
844
+ function renderNode(node) {
845
+ const Component = adapterMap[node.type];
846
+ if (Component) {
847
+ return Component(node);
1337
848
  }
1338
- console.warn(`Unknown node type: ${node.node_type}`);
1339
- return React.createElement(
1340
- Container,
1341
- {},
1342
- `Unknown node type: ${node.node_type}`
1343
- );
849
+ return /* @__PURE__ */ jsxs("div", { className: "p-2 border border-red-300 rounded", children: [
850
+ /* @__PURE__ */ jsxs("p", { className: "text-sm text-red-500", children: [
851
+ "Unsupported component: ",
852
+ node.type
853
+ ] }),
854
+ node.children?.map((child) => renderNode(child))
855
+ ] });
1344
856
  }
1345
- var renderedNodesCache = /* @__PURE__ */ new Map();
1346
- var MAX_CACHE_SIZE = 10;
1347
- var CACHE_TTL = 5e3;
1348
- async function renderNode2(node, adapter = "shadcn", processEvent2) {
857
+ async function renderNode2(node, adapter = "shadcn") {
1349
858
  const startTime = Date.now();
1350
- const nodeId = node.id;
1351
- const cachedItem = renderedNodesCache.get(nodeId);
1352
- if (cachedItem && startTime - cachedItem.timestamp < CACHE_TTL) {
1353
- return cachedItem.element;
1354
- }
1355
859
  await systemEvents.emit(
1356
860
  createSystemEvent("RENDER_START" /* RENDER_START */, { layout: node })
1357
861
  );
1358
862
  let result;
1359
863
  switch (adapter) {
1360
864
  case "shadcn":
1361
- result = renderNode(node, processEvent2);
865
+ result = renderNode(node);
1362
866
  break;
1363
867
  default:
1364
868
  console.warn(`Unsupported adapter: ${adapter}, falling back to shadcn`);
1365
- result = renderNode(node, processEvent2);
869
+ result = renderNode(node);
1366
870
  }
1367
871
  await systemEvents.emit(
1368
872
  createSystemEvent("RENDER_COMPLETE" /* RENDER_COMPLETE */, {
@@ -1370,23 +874,13 @@ async function renderNode2(node, adapter = "shadcn", processEvent2) {
1370
874
  renderTimeMs: Date.now() - startTime
1371
875
  })
1372
876
  );
1373
- renderedNodesCache.set(nodeId, {
1374
- element: result,
1375
- timestamp: startTime
1376
- });
1377
- if (renderedNodesCache.size > MAX_CACHE_SIZE) {
1378
- const oldestKey = [...renderedNodesCache.entries()].sort(
1379
- ([, a], [, b]) => a.timestamp - b.timestamp
1380
- )[0][0];
1381
- renderedNodesCache.delete(oldestKey);
1382
- }
1383
877
  return result;
1384
878
  }
1385
879
  function renderShimmer(node, adapter = "shadcn") {
1386
880
  if (!node) {
1387
881
  return /* @__PURE__ */ jsx(ShimmerBlock, {});
1388
882
  }
1389
- switch (node.node_type) {
883
+ switch (node.type) {
1390
884
  case "ListView":
1391
885
  return /* @__PURE__ */ jsx(ShimmerTable, { rows: 3 });
1392
886
  case "Detail":
@@ -1399,16 +893,6 @@ function renderShimmer(node, adapter = "shadcn") {
1399
893
  }
1400
894
 
1401
895
  // src/core/bindings.ts
1402
- var bindingsCache = /* @__PURE__ */ new Map();
1403
- var MAX_CACHE_SIZE2 = 50;
1404
- var CACHE_TTL2 = 2e3;
1405
- var nodeCacheTimestamps = /* @__PURE__ */ new Map();
1406
- function hashDataContext(context) {
1407
- return JSON.stringify(context);
1408
- }
1409
- function createCacheKey(nodeId, context) {
1410
- return `${nodeId}:${hashDataContext(context)}`;
1411
- }
1412
896
  function getValueByPath(context, path) {
1413
897
  const parts = path.split(".");
1414
898
  let current = context;
@@ -1426,32 +910,19 @@ function getValueByPath(context, path) {
1426
910
  function setValueByPath(context, path, value) {
1427
911
  const result = { ...context };
1428
912
  const parts = path.split(".");
1429
- if (parts.length === 0)
1430
- return result;
1431
913
  let current = result;
1432
914
  for (let i = 0; i < parts.length - 1; i++) {
1433
915
  const part = parts[i];
1434
- if (typeof current !== "object" || current === null) {
1435
- console.error("setValueByPath: Cannot create path in a non-object.");
1436
- return context;
916
+ if (!(part in current) || current[part] === null || current[part] === void 0) {
917
+ current[part] = {};
1437
918
  }
1438
- const currentAsObject = current;
1439
- if (!(part in currentAsObject) || typeof currentAsObject[part] !== "object" || currentAsObject[part] === null) {
1440
- currentAsObject[part] = {};
919
+ current = current[part];
920
+ if (typeof current !== "object") {
921
+ current = {};
1441
922
  }
1442
- current = currentAsObject[part];
1443
923
  }
1444
924
  const lastPart = parts[parts.length - 1];
1445
- if (typeof current === "object" && current !== null) {
1446
- current[lastPart] = value;
1447
- } else if (parts.length === 1 && typeof result === "object" && result !== null) {
1448
- result[lastPart] = value;
1449
- } else {
1450
- console.warn(
1451
- `setValueByPath: Could not set value for path "${path}". Final segment location is not an object.`
1452
- );
1453
- return context;
1454
- }
925
+ current[lastPart] = value;
1455
926
  return result;
1456
927
  }
1457
928
  function processBinding(binding, context) {
@@ -1471,27 +942,18 @@ function processBinding(binding, context) {
1471
942
  return binding;
1472
943
  }
1473
944
  async function resolveBindings(node, context) {
1474
- const currentTime = Date.now();
1475
- const cacheKey = createCacheKey(node.id, context);
1476
- const cachedNode = bindingsCache.get(cacheKey);
1477
- const cachedTimestamp = nodeCacheTimestamps.get(cacheKey);
1478
- if (cachedNode && cachedTimestamp && currentTime - cachedTimestamp < CACHE_TTL2) {
1479
- return cachedNode;
1480
- }
1481
945
  await systemEvents.emit(
1482
- createSystemEvent("BINDING_RESOLUTION_START" /* BINDING_RESOLUTION_START */, {
1483
- layout: node
1484
- })
946
+ createSystemEvent("BINDING_RESOLUTION_START" /* BINDING_RESOLUTION_START */, { layout: node })
1485
947
  );
1486
948
  const result = {
1487
949
  ...node,
1488
- props: node.props ? { ...node.props } : null,
1489
- events: node.events ? { ...node.events } : null
950
+ props: node.props ? { ...node.props } : void 0,
951
+ events: node.events ? { ...node.events } : void 0
1490
952
  };
1491
953
  if (node.bindings) {
1492
954
  for (const [key, binding] of Object.entries(node.bindings)) {
1493
955
  const value = processBinding(binding, context);
1494
- if (value !== void 0 && typeof value === "string") {
956
+ if (value !== void 0) {
1495
957
  if (!result.props) {
1496
958
  result.props = {};
1497
959
  }
@@ -1500,9 +962,7 @@ async function resolveBindings(node, context) {
1500
962
  }
1501
963
  }
1502
964
  if (node.children) {
1503
- result.children = await Promise.all(
1504
- node.children.map((child) => resolveBindings(child, context))
1505
- );
965
+ result.children = await Promise.all(node.children.map((child) => resolveBindings(child, context)));
1506
966
  }
1507
967
  await systemEvents.emit(
1508
968
  createSystemEvent("BINDING_RESOLUTION_COMPLETE" /* BINDING_RESOLUTION_COMPLETE */, {
@@ -1510,17 +970,6 @@ async function resolveBindings(node, context) {
1510
970
  resolvedLayout: result
1511
971
  })
1512
972
  );
1513
- bindingsCache.set(cacheKey, result);
1514
- nodeCacheTimestamps.set(cacheKey, currentTime);
1515
- if (bindingsCache.size > MAX_CACHE_SIZE2) {
1516
- const entries = [...nodeCacheTimestamps.entries()];
1517
- if (entries.length > 0) {
1518
- entries.sort((a, b) => a[1] - b[1]);
1519
- const oldestKey = entries[0][0];
1520
- bindingsCache.delete(oldestKey);
1521
- nodeCacheTimestamps.delete(oldestKey);
1522
- }
1523
- }
1524
973
  return result;
1525
974
  }
1526
975
  function executeAction(action, targetId, payload, context = {}, layoutTree) {
@@ -1543,6 +992,7 @@ function executeAction(action, targetId, payload, context = {}, layoutTree) {
1543
992
  }
1544
993
  break;
1545
994
  }
995
+ // Add more actions as needed
1546
996
  default:
1547
997
  console.warn(`Unknown action: ${action}`);
1548
998
  }
@@ -1556,7 +1006,7 @@ var EventManager = class {
1556
1006
  }
1557
1007
  /**
1558
1008
  * Register a hook for specific event types
1559
- *
1009
+ *
1560
1010
  * @param eventTypes - Event types to register for, or 'all' for all events
1561
1011
  * @param hook - Hook function to execute
1562
1012
  * @returns Unregister function
@@ -1589,7 +1039,7 @@ var EventManager = class {
1589
1039
  }
1590
1040
  /**
1591
1041
  * Process an event through all registered hooks
1592
- *
1042
+ *
1593
1043
  * @param event - The UI event to process
1594
1044
  * @returns Whether the default action should proceed
1595
1045
  */
@@ -1610,15 +1060,13 @@ var EventManager = class {
1610
1060
  if (this.hooks.all) {
1611
1061
  for (const hook of this.hooks.all) {
1612
1062
  await hook(context);
1613
- if (propagationStopped)
1614
- break;
1063
+ if (propagationStopped) break;
1615
1064
  }
1616
1065
  }
1617
1066
  if (!propagationStopped && this.hooks[event.type]) {
1618
1067
  for (const hook of this.hooks[event.type] || []) {
1619
1068
  await hook(context);
1620
- if (propagationStopped)
1621
- break;
1069
+ if (propagationStopped) break;
1622
1070
  }
1623
1071
  }
1624
1072
  return !defaultPrevented;
@@ -1635,20 +1083,6 @@ function createEventHook(eventTypes, hook, options) {
1635
1083
  }
1636
1084
  };
1637
1085
  }
1638
-
1639
- // src/core/component-detection.ts
1640
- function areShadcnComponentsAvailable() {
1641
- try {
1642
- init_button();
1643
- return true;
1644
- } catch (error) {
1645
- return false;
1646
- }
1647
- }
1648
- function getMissingComponentsMessage() {
1649
- return `Missing required shadcn components. Please run:
1650
- > npm run setup-shadcn`;
1651
- }
1652
1086
  var AutoUI = ({
1653
1087
  schema,
1654
1088
  goal,
@@ -1659,32 +1093,23 @@ var AutoUI = ({
1659
1093
  systemEventHooks,
1660
1094
  debugMode = false,
1661
1095
  mockMode = true,
1096
+ databaseConfig,
1662
1097
  planningConfig,
1663
1098
  integration = {},
1664
1099
  scope = {},
1665
1100
  enablePartialUpdates = false
1666
1101
  }) => {
1667
- const [schemaAdapterInstance] = useState(null);
1102
+ const [schemaAdapterInstance, setSchemaAdapterInstance] = useState(null);
1668
1103
  const [dataContext, setDataContext] = useState({});
1669
- const [componentsAvailable, setComponentsAvailable] = useState(true);
1670
1104
  const effectiveSchema = schema;
1671
1105
  const scopedGoal = goal;
1672
- useEffect(() => {
1673
- if (componentAdapter === "shadcn") {
1674
- setComponentsAvailable(areShadcnComponentsAvailable());
1675
- }
1676
- }, [componentAdapter]);
1677
1106
  useEffect(() => {
1678
1107
  const unregisters = [];
1679
1108
  if (systemEventHooks) {
1680
1109
  Object.entries(systemEventHooks).forEach(([eventType, hooks]) => {
1681
- if (!hooks)
1682
- return;
1110
+ if (!hooks) return;
1683
1111
  hooks.forEach((hook) => {
1684
- const unregister = systemEvents.on(
1685
- eventType,
1686
- hook
1687
- );
1112
+ const unregister = systemEvents.on(eventType, hook);
1688
1113
  unregisters.push(unregister);
1689
1114
  });
1690
1115
  });
@@ -1693,9 +1118,7 @@ var AutoUI = ({
1693
1118
  const debugHook = (event) => {
1694
1119
  console.debug(`[AutoUI Debug] System Event:`, event);
1695
1120
  };
1696
- Object.values(SystemEventType).filter(
1697
- (eventType) => eventType !== "RENDER_START" /* RENDER_START */ && eventType !== "BINDING_RESOLUTION_START" /* BINDING_RESOLUTION_START */
1698
- ).forEach((eventType) => {
1121
+ Object.values(SystemEventType).forEach((eventType) => {
1699
1122
  const unregister = systemEvents.on(eventType, debugHook);
1700
1123
  unregisters.push(unregister);
1701
1124
  });
@@ -1738,141 +1161,84 @@ var AutoUI = ({
1738
1161
  });
1739
1162
  const eventManagerRef = useRef(new EventManager());
1740
1163
  useEffect(() => {
1741
- if (!eventHooks)
1742
- return;
1164
+ if (!eventHooks) return;
1743
1165
  const unregisters = [];
1744
1166
  if (eventHooks.all) {
1745
- const unregister = eventManagerRef.current.register(
1746
- "all",
1747
- async (ctx) => {
1748
- for (const hook of eventHooks.all || []) {
1749
- await hook(ctx);
1750
- if (ctx.isPropagationStopped())
1751
- break;
1752
- }
1167
+ const unregister = eventManagerRef.current.register("all", async (ctx) => {
1168
+ for (const hook of eventHooks.all || []) {
1169
+ await hook(ctx);
1170
+ if (ctx.isPropagationStopped()) break;
1753
1171
  }
1754
- );
1172
+ });
1755
1173
  unregisters.push(unregister);
1756
1174
  }
1757
1175
  Object.entries(eventHooks).forEach(([type, hooks]) => {
1758
- if (type === "all" || !hooks)
1759
- return;
1760
- const unregister = eventManagerRef.current.register(
1761
- [type],
1762
- async (ctx) => {
1763
- for (const hook of hooks) {
1764
- await hook(ctx);
1765
- if (ctx.isPropagationStopped())
1766
- break;
1767
- }
1176
+ if (type === "all" || !hooks) return;
1177
+ const unregister = eventManagerRef.current.register([type], async (ctx) => {
1178
+ for (const hook of hooks) {
1179
+ await hook(ctx);
1180
+ if (ctx.isPropagationStopped()) break;
1768
1181
  }
1769
- );
1182
+ });
1770
1183
  unregisters.push(unregister);
1771
1184
  });
1772
1185
  return () => {
1773
1186
  unregisters.forEach((unregister) => unregister());
1774
1187
  };
1775
1188
  }, [eventHooks]);
1776
- const processEvent2 = useCallback(
1777
- async (event) => {
1778
- const shouldProceed = await eventManagerRef.current.processEvent(event);
1779
- if (onEvent) {
1780
- onEvent(event);
1781
- }
1782
- if (!shouldProceed) {
1783
- console.info("Event processing was prevented by hooks", event);
1784
- return;
1785
- }
1786
- const findNodeById2 = (node, id) => {
1787
- if (!node)
1788
- return void 0;
1789
- if (node.id === id)
1790
- return node;
1791
- if (node.children) {
1792
- for (const child of node.children) {
1793
- const found = findNodeById2(child, id);
1794
- if (found)
1795
- return found;
1796
- }
1189
+ useCallback(async (event) => {
1190
+ const shouldProceed = await eventManagerRef.current.processEvent(event);
1191
+ if (onEvent) {
1192
+ onEvent(event);
1193
+ }
1194
+ if (!shouldProceed) {
1195
+ console.info("Event processing was prevented by hooks", event);
1196
+ return;
1197
+ }
1198
+ const findNodeById2 = (node, id) => {
1199
+ if (!node) return void 0;
1200
+ if (node.id === id) return node;
1201
+ if (node.children) {
1202
+ for (const child of node.children) {
1203
+ const found = findNodeById2(child, id);
1204
+ if (found) return found;
1797
1205
  }
1798
- return void 0;
1799
- };
1800
- const sourceNode = findNodeById2(state.layout, event.nodeId);
1801
- if (!sourceNode) {
1802
- console.warn(`Node not found for event: ${event.nodeId}`);
1803
- handleEvent(event);
1804
- return;
1805
1206
  }
1806
- const eventConfig = sourceNode.events?.[event.type];
1807
- if (!eventConfig) {
1808
- console.warn(
1809
- `No event config found for ${event.type} on node ${event.nodeId}`
1810
- );
1811
- handleEvent(event);
1812
- return;
1813
- }
1814
- const newContext = executeAction(
1815
- eventConfig.action,
1816
- eventConfig.target || "",
1817
- // Provide empty string as fallback if target is null
1818
- {
1819
- ...eventConfig.payload,
1820
- ...event.payload
1821
- },
1822
- dataContext,
1823
- state.layout || void 0
1824
- );
1825
- setDataContext(newContext);
1207
+ return void 0;
1208
+ };
1209
+ const sourceNode = findNodeById2(state.layout, event.nodeId);
1210
+ if (!sourceNode) {
1211
+ console.warn(`Node not found for event: ${event.nodeId}`);
1826
1212
  handleEvent(event);
1827
- },
1828
- [dataContext, handleEvent, onEvent, state.layout]
1829
- );
1830
- const [resolvedLayout, setResolvedLayout] = useState(
1831
- void 0
1832
- );
1833
- const [renderedNode, setRenderedNode] = useState(
1834
- null
1835
- );
1836
- const resolveLayoutBindings = useCallback(async () => {
1213
+ return;
1214
+ }
1215
+ const eventConfig = sourceNode.events?.[event.type];
1216
+ if (!eventConfig) {
1217
+ console.warn(`No event config found for ${event.type} on node ${event.nodeId}`);
1218
+ handleEvent(event);
1219
+ return;
1220
+ }
1221
+ const newContext = executeAction(
1222
+ eventConfig.action,
1223
+ eventConfig.target,
1224
+ {
1225
+ ...eventConfig.payload,
1226
+ ...event.payload
1227
+ },
1228
+ dataContext,
1229
+ state.layout
1230
+ );
1231
+ setDataContext(newContext);
1232
+ handleEvent(event);
1233
+ }, [dataContext, handleEvent, onEvent, state.layout]);
1234
+ const [resolvedLayout, setResolvedLayout] = useState(void 0);
1235
+ useEffect(() => {
1837
1236
  if (state.layout) {
1838
- try {
1839
- const resolved = await resolveBindings(state.layout, dataContext);
1840
- setResolvedLayout(resolved);
1841
- } catch (err) {
1842
- console.error("Error resolving bindings:", err);
1843
- }
1237
+ resolveBindings(state.layout, dataContext).then((resolved) => setResolvedLayout(resolved)).catch((err) => console.error("Error resolving bindings:", err));
1844
1238
  } else {
1845
1239
  setResolvedLayout(void 0);
1846
1240
  }
1847
1241
  }, [state.layout, dataContext]);
1848
- useEffect(() => {
1849
- resolveLayoutBindings();
1850
- }, [resolveLayoutBindings]);
1851
- const renderResolvedLayout = useCallback(async () => {
1852
- if (resolvedLayout) {
1853
- try {
1854
- const rendered = await renderNode2(
1855
- resolvedLayout,
1856
- componentAdapter,
1857
- processEvent2
1858
- );
1859
- setRenderedNode(rendered);
1860
- } catch (err) {
1861
- console.error("Error rendering node:", err);
1862
- }
1863
- } else {
1864
- setRenderedNode(null);
1865
- }
1866
- }, [resolvedLayout, componentAdapter, processEvent2]);
1867
- useEffect(() => {
1868
- renderResolvedLayout();
1869
- }, [renderResolvedLayout]);
1870
- if (!componentsAvailable) {
1871
- return /* @__PURE__ */ jsxs("div", { className: "autoui-error p-4 border border-red-300 bg-red-50 text-red-700 rounded", children: [
1872
- /* @__PURE__ */ jsx("p", { className: "font-medium", children: "Component Library Not Found" }),
1873
- /* @__PURE__ */ jsx("p", { className: "text-sm whitespace-pre-line", children: getMissingComponentsMessage() })
1874
- ] });
1875
- }
1876
1242
  return /* @__PURE__ */ jsxs(
1877
1243
  "div",
1878
1244
  {
@@ -1889,24 +1255,11 @@ var AutoUI = ({
1889
1255
  ] }) })
1890
1256
  ) : (
1891
1257
  // Render the resolved layout
1892
- /* @__PURE__ */ jsx("div", { className: "autoui-content", children: renderedNode })
1258
+ /* @__PURE__ */ jsx("div", { className: "autoui-content", children: renderNode2(resolvedLayout, componentAdapter) })
1893
1259
  ),
1894
- state.error && /* @__PURE__ */ jsxs("div", { className: "autoui-error p-4 border border-red-300 bg-red-50 dark:bg-red-900 dark:border-red-700 rounded-md", children: [
1895
- /* @__PURE__ */ jsx("p", { className: "autoui-error-title text-lg font-semibold text-red-700 dark:text-red-300 mb-2", children: "Error generating UI" }),
1896
- /* @__PURE__ */ jsx("p", { className: "autoui-error-message text-sm text-red-600 dark:text-red-300", children: state.error }),
1897
- !mockMode && /* @__PURE__ */ jsxs("div", { className: "mt-4 text-sm text-red-600 dark:text-red-300", children: [
1898
- /* @__PURE__ */ jsx("p", { children: "This could be because:" }),
1899
- /* @__PURE__ */ jsxs("ul", { className: "list-disc pl-5 mt-2", children: [
1900
- /* @__PURE__ */ jsx("li", { children: "Your OpenAI API key is missing or invalid" }),
1901
- /* @__PURE__ */ jsx("li", { children: "The OpenAI service is experiencing issues" }),
1902
- /* @__PURE__ */ jsx("li", { children: "Your API rate limit has been exceeded" })
1903
- ] }),
1904
- /* @__PURE__ */ jsxs("p", { className: "mt-2", children: [
1905
- "Try setting ",
1906
- /* @__PURE__ */ jsx("code", { children: "mockMode=true" }),
1907
- " to use sample data instead."
1908
- ] })
1909
- ] })
1260
+ state.error && /* @__PURE__ */ jsxs("div", { className: "autoui-error", children: [
1261
+ /* @__PURE__ */ jsx("p", { className: "autoui-error-title", children: "Error generating UI" }),
1262
+ /* @__PURE__ */ jsx("p", { className: "autoui-error-message", children: state.error })
1910
1263
  ] })
1911
1264
  ]
1912
1265
  }
@@ -1959,26 +1312,26 @@ var DrizzleAdapter = class {
1959
1312
  */
1960
1313
  mapDataType(drizzleType) {
1961
1314
  const typeMap = {
1962
- serial: "integer",
1963
- integer: "integer",
1964
- int: "integer",
1965
- bigint: "integer",
1966
- text: "string",
1967
- varchar: "string",
1968
- char: "string",
1969
- boolean: "boolean",
1970
- bool: "boolean",
1971
- timestamp: "datetime",
1972
- timestamptz: "datetime",
1973
- date: "date",
1974
- time: "time",
1975
- json: "object",
1976
- jsonb: "object",
1977
- real: "number",
1978
- float: "number",
1979
- double: "number",
1980
- numeric: "number",
1981
- decimal: "number"
1315
+ "serial": "integer",
1316
+ "integer": "integer",
1317
+ "int": "integer",
1318
+ "bigint": "integer",
1319
+ "text": "string",
1320
+ "varchar": "string",
1321
+ "char": "string",
1322
+ "boolean": "boolean",
1323
+ "bool": "boolean",
1324
+ "timestamp": "datetime",
1325
+ "timestamptz": "datetime",
1326
+ "date": "date",
1327
+ "time": "time",
1328
+ "json": "object",
1329
+ "jsonb": "object",
1330
+ "real": "number",
1331
+ "float": "number",
1332
+ "double": "number",
1333
+ "numeric": "number",
1334
+ "decimal": "number"
1982
1335
  };
1983
1336
  return typeMap[drizzleType.toLowerCase()] || "string";
1984
1337
  }
@@ -2021,92 +1374,10 @@ function createSchemaAdapter(options) {
2021
1374
  case "custom":
2022
1375
  return options.adapter;
2023
1376
  default:
2024
- throw new Error(
2025
- `Unsupported schema adapter type: ${options.type}`
2026
- );
1377
+ throw new Error(`Unsupported schema adapter type: ${options.type}`);
2027
1378
  }
2028
1379
  }
2029
1380
 
2030
- // src/ai-utils.ts
2031
- var generateComponent = async (prompt) => {
2032
- console.warn(
2033
- "generateComponent is a placeholder and will be implemented in a future version"
2034
- );
2035
- return `<div>Generated Component for: ${prompt}</div>`;
2036
- };
2037
- var generateUIDescription = async (prompt) => {
2038
- console.warn(
2039
- "generateUIDescription is a placeholder and will be implemented in a future version"
2040
- );
2041
- return `Description for ${prompt}`;
2042
- };
2043
- var generateUIComponent = async (prompt) => {
2044
- console.warn(
2045
- "generateUIComponent is a placeholder and will be implemented in a future version"
2046
- );
2047
- return `<div>Generated UI Component for: ${prompt}</div>`;
2048
- };
2049
- function usePlanner(options) {
2050
- const { goal, schema, userContext, router: customRouter } = options;
2051
- const [layout, setLayout] = useState(void 0);
2052
- const [loading, setLoading] = useState(false);
2053
- const [error, setError] = useState(null);
2054
- const router = customRouter || createDefaultRouter();
2055
- const dataContext = {};
2056
- const generateInitialLayout = useCallback(async () => {
2057
- setLoading(true);
2058
- setError(null);
2059
- try {
2060
- const plannerInput2 = {
2061
- schema,
2062
- goal,
2063
- userContext: userContext || null,
2064
- history: null
2065
- };
2066
- const generatedLayout = await callPlannerLLM(plannerInput2);
2067
- setLayout(generatedLayout);
2068
- } catch (err) {
2069
- setError(err instanceof Error ? err : new Error(String(err)));
2070
- } finally {
2071
- setLoading(false);
2072
- }
2073
- }, [schema, goal, userContext]);
2074
- const handleEvent = useCallback(
2075
- async (event) => {
2076
- if (!layout) {
2077
- setError(new Error("Cannot handle event - no layout exists"));
2078
- return;
2079
- }
2080
- setLoading(true);
2081
- setError(null);
2082
- try {
2083
- const updatedLayout = await processEvent(
2084
- event,
2085
- router,
2086
- schema,
2087
- layout,
2088
- dataContext,
2089
- goal,
2090
- userContext
2091
- );
2092
- setLayout(updatedLayout);
2093
- } catch (err) {
2094
- setError(err instanceof Error ? err : new Error(String(err)));
2095
- } finally {
2096
- setLoading(false);
2097
- }
2098
- },
2099
- [layout, router, schema, dataContext, goal, userContext]
2100
- );
2101
- return {
2102
- layout,
2103
- loading,
2104
- error,
2105
- handleEvent,
2106
- generateInitialLayout
2107
- };
2108
- }
2109
-
2110
- export { ActionRouter, ActionType, AutoUI, DrizzleAdapter, SystemEventType, createDefaultRouter, createEventHook, createSchemaAdapter, createSystemEvent, generateComponent, generateUIComponent, generateUIDescription, systemEvents, uiEvent, uiEventType, uiSpecNode, usePlanner };
2111
- //# sourceMappingURL=out.js.map
1381
+ export { ActionRouter, ActionType, AutoUI, DrizzleAdapter, SystemEventType, createDefaultRouter, createEventHook, createSchemaAdapter, createSystemEvent, systemEvents, uiEvent, uiEventType, uiSpecNode };
1382
+ //# sourceMappingURL=index.mjs.map
2112
1383
  //# sourceMappingURL=index.mjs.map