@mcp-b/char 0.0.0-beta-20260124143827

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.
@@ -0,0 +1,619 @@
1
+ import { c } from "react-compiler-runtime";
2
+ import { createContext, useContext, useEffect, useRef, useState } from "react";
3
+ import { AlertCircle, Check, ChevronDownIcon, ChevronUpIcon, FileText } from "lucide-react";
4
+ import { makeAssistantToolUI } from "@assistant-ui/react";
5
+ import { clsx } from "clsx";
6
+ import { twMerge } from "tailwind-merge";
7
+ import { jsx, jsxs } from "react/jsx-runtime";
8
+ import { Slot } from "@radix-ui/react-slot";
9
+ import { cva } from "class-variance-authority";
10
+ import * as CollapsiblePrimitive from "@radix-ui/react-collapsible";
11
+ import Ajv from "ajv";
12
+ import { withTheme } from "@rjsf/core";
13
+ import { Theme } from "@rjsf/shadcn";
14
+ import validator from "@rjsf/validator-ajv8";
15
+
16
+ //#region src/utils/cn.ts
17
+ /**
18
+ * Merges Tailwind CSS classes with proper precedence handling.
19
+ * Combines clsx for conditional classes and tailwind-merge for deduplication.
20
+ */
21
+ function cn(...inputs) {
22
+ return twMerge(clsx(inputs));
23
+ }
24
+
25
+ //#endregion
26
+ //#region src/components/ui/button.tsx
27
+ const buttonVariants = cva("inline-flex shrink-0 items-center justify-center gap-2 whitespace-nowrap rounded-md font-medium text-sm outline-none transition-all focus-visible:border-ring focus-visible:ring-[3px] focus-visible:ring-ring/50 disabled:pointer-events-none disabled:opacity-50 aria-invalid:border-destructive aria-invalid:ring-destructive/20 dark:aria-invalid:ring-destructive/40 [&_svg:not([class*='size-'])]:size-4 [&_svg]:pointer-events-none [&_svg]:shrink-0", {
28
+ variants: {
29
+ variant: {
30
+ default: "bg-primary text-primary-foreground hover:bg-primary/90",
31
+ destructive: "bg-destructive text-white hover:bg-destructive/90 focus-visible:ring-destructive/20 dark:bg-destructive/60 dark:focus-visible:ring-destructive/40",
32
+ outline: "border bg-background shadow-xs hover:bg-accent hover:text-accent-foreground dark:border-input dark:bg-input/30 dark:hover:bg-input/50",
33
+ secondary: "bg-secondary text-secondary-foreground hover:bg-secondary/80",
34
+ ghost: "hover:bg-accent hover:text-accent-foreground dark:hover:bg-accent/50",
35
+ link: "text-primary underline-offset-4 hover:underline"
36
+ },
37
+ size: {
38
+ default: "h-9 px-4 py-2 has-[>svg]:px-3",
39
+ sm: "h-8 gap-1.5 rounded-md px-3 has-[>svg]:px-2.5",
40
+ lg: "h-10 rounded-md px-6 has-[>svg]:px-4",
41
+ icon: "size-9",
42
+ "icon-sm": "size-8",
43
+ "icon-lg": "size-10"
44
+ }
45
+ },
46
+ defaultVariants: {
47
+ variant: "default",
48
+ size: "default"
49
+ }
50
+ });
51
+ function Button(t0) {
52
+ const $ = c(16);
53
+ let className;
54
+ let props;
55
+ let t1;
56
+ let t2;
57
+ let t3;
58
+ if ($[0] !== t0) {
59
+ ({className, variant: t1, size: t2, asChild: t3, ...props} = t0);
60
+ $[0] = t0;
61
+ $[1] = className;
62
+ $[2] = props;
63
+ $[3] = t1;
64
+ $[4] = t2;
65
+ $[5] = t3;
66
+ } else {
67
+ className = $[1];
68
+ props = $[2];
69
+ t1 = $[3];
70
+ t2 = $[4];
71
+ t3 = $[5];
72
+ }
73
+ const variant = t1 === void 0 ? "default" : t1;
74
+ const size = t2 === void 0 ? "default" : t2;
75
+ const Comp = (t3 === void 0 ? false : t3) ? Slot : "button";
76
+ let t4;
77
+ if ($[6] !== className || $[7] !== size || $[8] !== variant) {
78
+ t4 = cn(buttonVariants({
79
+ variant,
80
+ size,
81
+ className
82
+ }));
83
+ $[6] = className;
84
+ $[7] = size;
85
+ $[8] = variant;
86
+ $[9] = t4;
87
+ } else t4 = $[9];
88
+ let t5;
89
+ if ($[10] !== Comp || $[11] !== props || $[12] !== size || $[13] !== t4 || $[14] !== variant) {
90
+ t5 = /* @__PURE__ */ jsx(Comp, {
91
+ "data-slot": "button",
92
+ "data-variant": variant,
93
+ "data-size": size,
94
+ className: t4,
95
+ ...props
96
+ });
97
+ $[10] = Comp;
98
+ $[11] = props;
99
+ $[12] = size;
100
+ $[13] = t4;
101
+ $[14] = variant;
102
+ $[15] = t5;
103
+ } else t5 = $[15];
104
+ return t5;
105
+ }
106
+
107
+ //#endregion
108
+ //#region src/components/ui/collapsible.tsx
109
+ function Collapsible(t0) {
110
+ const $ = c(4);
111
+ let props;
112
+ if ($[0] !== t0) {
113
+ ({...props} = t0);
114
+ $[0] = t0;
115
+ $[1] = props;
116
+ } else props = $[1];
117
+ let t1;
118
+ if ($[2] !== props) {
119
+ t1 = /* @__PURE__ */ jsx(CollapsiblePrimitive.Root, {
120
+ "data-slot": "collapsible",
121
+ ...props
122
+ });
123
+ $[2] = props;
124
+ $[3] = t1;
125
+ } else t1 = $[3];
126
+ return t1;
127
+ }
128
+ function CollapsibleTrigger(t0) {
129
+ const $ = c(4);
130
+ let props;
131
+ if ($[0] !== t0) {
132
+ ({...props} = t0);
133
+ $[0] = t0;
134
+ $[1] = props;
135
+ } else props = $[1];
136
+ let t1;
137
+ if ($[2] !== props) {
138
+ t1 = /* @__PURE__ */ jsx(CollapsiblePrimitive.CollapsibleTrigger, {
139
+ "data-slot": "collapsible-trigger",
140
+ ...props
141
+ });
142
+ $[2] = props;
143
+ $[3] = t1;
144
+ } else t1 = $[3];
145
+ return t1;
146
+ }
147
+ function CollapsibleContent(t0) {
148
+ const $ = c(4);
149
+ let props;
150
+ if ($[0] !== t0) {
151
+ ({...props} = t0);
152
+ $[0] = t0;
153
+ $[1] = props;
154
+ } else props = $[1];
155
+ let t1;
156
+ if ($[2] !== props) {
157
+ t1 = /* @__PURE__ */ jsx(CollapsiblePrimitive.CollapsibleContent, {
158
+ "data-slot": "collapsible-content",
159
+ ...props
160
+ });
161
+ $[2] = props;
162
+ $[3] = t1;
163
+ } else t1 = $[3];
164
+ return t1;
165
+ }
166
+
167
+ //#endregion
168
+ //#region src/providers/ToolExecutionProvider.tsx
169
+ const ToolExecutionContext = createContext(null);
170
+ const ToolExecutionProvider = (t0) => {
171
+ const $ = c(3);
172
+ const { value, children } = t0;
173
+ let t1;
174
+ if ($[0] !== children || $[1] !== value) {
175
+ t1 = /* @__PURE__ */ jsx(ToolExecutionContext.Provider, {
176
+ value,
177
+ children
178
+ });
179
+ $[0] = children;
180
+ $[1] = value;
181
+ $[2] = t1;
182
+ } else t1 = $[2];
183
+ return t1;
184
+ };
185
+ function useOptionalToolExecution() {
186
+ return useContext(ToolExecutionContext);
187
+ }
188
+
189
+ //#endregion
190
+ //#region src/tools/FormToolUI.tsx
191
+ const Form = withTheme(Theme);
192
+ const ajv = new Ajv();
193
+ /**
194
+ * Normalize a JSON Schema to handle common model mistakes.
195
+ * - Converts uppercase types (Gemini format) to lowercase (JSON Schema format)
196
+ * - Recursively processes nested schemas
197
+ */
198
+ function normalizeSchema(schema) {
199
+ if (!schema || typeof schema !== "object") return schema;
200
+ const obj = { ...schema };
201
+ if (typeof obj.type === "string") obj.type = obj.type.toLowerCase();
202
+ if (obj.properties && typeof obj.properties === "object") obj.properties = Object.fromEntries(Object.entries(obj.properties).map(([key, value]) => [key, normalizeSchema(value)]));
203
+ if (obj.items) if (Array.isArray(obj.items)) obj.items = obj.items.map(normalizeSchema);
204
+ else obj.items = normalizeSchema(obj.items);
205
+ if (obj.additionalProperties && typeof obj.additionalProperties === "object") obj.additionalProperties = normalizeSchema(obj.additionalProperties);
206
+ for (const keyword of [
207
+ "allOf",
208
+ "anyOf",
209
+ "oneOf"
210
+ ]) if (Array.isArray(obj[keyword])) obj[keyword] = obj[keyword].map(normalizeSchema);
211
+ if (obj.not && typeof obj.not === "object") obj.not = normalizeSchema(obj.not);
212
+ return obj;
213
+ }
214
+ /**
215
+ * Validate a JSON Schema using AJV's meta-schema validation.
216
+ * Returns null if valid, or an error message string if invalid.
217
+ */
218
+ function validateSchema(schema) {
219
+ if (ajv.validateSchema(schema)) return null;
220
+ return [
221
+ "Invalid JSON Schema:",
222
+ ...(ajv.errors ?? []).map((err) => {
223
+ return `- ${err.instancePath || "root"}: ${err.message}`;
224
+ }),
225
+ "",
226
+ "Please fix the schema and try again."
227
+ ].join("\n");
228
+ }
229
+ /**
230
+ * Display component for schema validation errors
231
+ */
232
+ function SchemaErrorDisplay(t0) {
233
+ const $ = c(16);
234
+ const { title, error } = t0;
235
+ const [isOpen, setIsOpen] = useState(true);
236
+ let t1;
237
+ if ($[0] === Symbol.for("react.memo_cache_sentinel")) {
238
+ t1 = /* @__PURE__ */ jsxs("div", {
239
+ className: "relative",
240
+ children: [/* @__PURE__ */ jsx(FileText, { className: "h-3.5 w-3.5 text-destructive" }), /* @__PURE__ */ jsx(AlertCircle, { className: "absolute -bottom-0.5 -right-0.5 h-2 w-2 text-destructive" })]
241
+ });
242
+ $[0] = t1;
243
+ } else t1 = $[0];
244
+ let t2;
245
+ if ($[1] !== title) {
246
+ t2 = /* @__PURE__ */ jsxs("span", {
247
+ className: "flex-grow text-xs font-medium text-destructive",
248
+ children: [title, " - Invalid Schema"]
249
+ });
250
+ $[1] = title;
251
+ $[2] = t2;
252
+ } else t2 = $[2];
253
+ let t3;
254
+ if ($[3] !== isOpen) {
255
+ t3 = /* @__PURE__ */ jsx("span", {
256
+ className: "inline-flex h-5 w-5 items-center justify-center p-0",
257
+ children: isOpen ? /* @__PURE__ */ jsx(ChevronUpIcon, { className: "h-3 w-3 text-destructive/70" }) : /* @__PURE__ */ jsx(ChevronDownIcon, { className: "h-3 w-3 text-destructive/70" })
258
+ });
259
+ $[3] = isOpen;
260
+ $[4] = t3;
261
+ } else t3 = $[4];
262
+ let t4;
263
+ if ($[5] !== t2 || $[6] !== t3) {
264
+ t4 = /* @__PURE__ */ jsx(CollapsibleTrigger, {
265
+ asChild: true,
266
+ children: /* @__PURE__ */ jsxs("button", {
267
+ type: "button",
268
+ className: "flex w-full items-center gap-1.5 px-2 py-1.5 text-left transition-colors hover:bg-destructive/15",
269
+ children: [
270
+ t1,
271
+ t2,
272
+ t3
273
+ ]
274
+ })
275
+ });
276
+ $[5] = t2;
277
+ $[6] = t3;
278
+ $[7] = t4;
279
+ } else t4 = $[7];
280
+ let t5;
281
+ if ($[8] !== error) {
282
+ t5 = /* @__PURE__ */ jsx(CollapsibleContent, { children: /* @__PURE__ */ jsx("div", {
283
+ className: "border-t border-destructive/20 px-2 py-1.5",
284
+ children: /* @__PURE__ */ jsx("pre", {
285
+ className: "whitespace-pre-wrap text-[11px] text-foreground/70",
286
+ children: error
287
+ })
288
+ }) });
289
+ $[8] = error;
290
+ $[9] = t5;
291
+ } else t5 = $[9];
292
+ let t6;
293
+ if ($[10] !== t4 || $[11] !== t5) {
294
+ t6 = /* @__PURE__ */ jsxs("div", {
295
+ className: "my-1 overflow-hidden rounded-lg bg-destructive/10 border border-destructive/20",
296
+ children: [t4, t5]
297
+ });
298
+ $[10] = t4;
299
+ $[11] = t5;
300
+ $[12] = t6;
301
+ } else t6 = $[12];
302
+ let t7;
303
+ if ($[13] !== isOpen || $[14] !== t6) {
304
+ t7 = /* @__PURE__ */ jsx(Collapsible, {
305
+ open: isOpen,
306
+ onOpenChange: setIsOpen,
307
+ children: t6
308
+ });
309
+ $[13] = isOpen;
310
+ $[14] = t6;
311
+ $[15] = t7;
312
+ } else t7 = $[15];
313
+ return t7;
314
+ }
315
+ /**
316
+ * Parse form result data, handling cases where it may be stringified
317
+ */
318
+ function parseFormData(data) {
319
+ if (typeof data === "object" && data !== null) {
320
+ if (Object.keys(data).some((key) => isNaN(Number(key)))) return data;
321
+ }
322
+ if (typeof data === "string") try {
323
+ const parsed = JSON.parse(data);
324
+ if (typeof parsed === "object" && parsed !== null) return parsed;
325
+ } catch (error) {
326
+ console.warn("[FormToolUI] Failed to parse form data as JSON:", {
327
+ data: data.substring(0, 100),
328
+ error: error instanceof Error ? error.message : "Unknown parse error"
329
+ });
330
+ return { value: data };
331
+ }
332
+ return typeof data === "object" && data !== null ? data : { value: String(data) };
333
+ }
334
+ /**
335
+ * Format a value for display
336
+ */
337
+ function formatValue(value) {
338
+ if (value === null || value === void 0) return "—";
339
+ if (typeof value === "boolean") return value ? "Yes" : "No";
340
+ if (typeof value === "object") return JSON.stringify(value);
341
+ return String(value);
342
+ }
343
+ /**
344
+ * Display component for submitted form data - matches UnifiedToolFallback pattern
345
+ */
346
+ function FormResultDisplay(t0) {
347
+ const $ = c(41);
348
+ const { title, data } = t0;
349
+ const [isOpen, setIsOpen] = useState(false);
350
+ let T0;
351
+ let T1;
352
+ let t1;
353
+ let t2;
354
+ let t3;
355
+ let t4;
356
+ let t5;
357
+ let t6;
358
+ let t7;
359
+ let t8;
360
+ if ($[0] !== data || $[1] !== isOpen || $[2] !== title) {
361
+ const parsedData = parseFormData(data);
362
+ const entries = Object.entries(parsedData);
363
+ T1 = Collapsible;
364
+ t7 = isOpen;
365
+ t8 = setIsOpen;
366
+ t5 = "my-1 overflow-hidden rounded-lg bg-muted/50";
367
+ let t9$1;
368
+ if ($[13] === Symbol.for("react.memo_cache_sentinel")) {
369
+ t9$1 = /* @__PURE__ */ jsxs("div", {
370
+ className: "relative",
371
+ children: [/* @__PURE__ */ jsx(FileText, { className: "h-3.5 w-3.5 text-muted-foreground" }), /* @__PURE__ */ jsx(Check, { className: "absolute -bottom-0.5 -right-0.5 h-2 w-2 text-muted-foreground" })]
372
+ });
373
+ $[13] = t9$1;
374
+ } else t9$1 = $[13];
375
+ let t10$1;
376
+ if ($[14] !== title) {
377
+ t10$1 = /* @__PURE__ */ jsx("span", {
378
+ className: "flex-grow text-xs font-medium text-foreground/80",
379
+ children: title
380
+ });
381
+ $[14] = title;
382
+ $[15] = t10$1;
383
+ } else t10$1 = $[15];
384
+ let t11$1;
385
+ if ($[16] !== isOpen) {
386
+ t11$1 = /* @__PURE__ */ jsx("span", {
387
+ className: "inline-flex h-5 w-5 items-center justify-center p-0",
388
+ children: isOpen ? /* @__PURE__ */ jsx(ChevronUpIcon, { className: "h-3 w-3 text-muted-foreground/70" }) : /* @__PURE__ */ jsx(ChevronDownIcon, { className: "h-3 w-3 text-muted-foreground/70" })
389
+ });
390
+ $[16] = isOpen;
391
+ $[17] = t11$1;
392
+ } else t11$1 = $[17];
393
+ if ($[18] !== t10$1 || $[19] !== t11$1) {
394
+ t6 = /* @__PURE__ */ jsx(CollapsibleTrigger, {
395
+ asChild: true,
396
+ children: /* @__PURE__ */ jsxs("button", {
397
+ type: "button",
398
+ className: "flex w-full items-center gap-1.5 px-2 py-1.5 text-left transition-colors hover:bg-muted/70",
399
+ children: [
400
+ t9$1,
401
+ t10$1,
402
+ t11$1
403
+ ]
404
+ })
405
+ });
406
+ $[18] = t10$1;
407
+ $[19] = t11$1;
408
+ $[20] = t6;
409
+ } else t6 = $[20];
410
+ T0 = CollapsibleContent;
411
+ t3 = "border-t border-border px-2 py-1.5";
412
+ if ($[21] === Symbol.for("react.memo_cache_sentinel")) {
413
+ t4 = /* @__PURE__ */ jsx("div", {
414
+ className: "mb-0.5 text-[10px] font-medium uppercase tracking-wide text-muted-foreground/70",
415
+ children: "Submitted data"
416
+ });
417
+ $[21] = t4;
418
+ } else t4 = $[21];
419
+ t1 = "rounded bg-muted/50 p-1.5 space-y-0.5";
420
+ t2 = entries.map(_temp);
421
+ $[0] = data;
422
+ $[1] = isOpen;
423
+ $[2] = title;
424
+ $[3] = T0;
425
+ $[4] = T1;
426
+ $[5] = t1;
427
+ $[6] = t2;
428
+ $[7] = t3;
429
+ $[8] = t4;
430
+ $[9] = t5;
431
+ $[10] = t6;
432
+ $[11] = t7;
433
+ $[12] = t8;
434
+ } else {
435
+ T0 = $[3];
436
+ T1 = $[4];
437
+ t1 = $[5];
438
+ t2 = $[6];
439
+ t3 = $[7];
440
+ t4 = $[8];
441
+ t5 = $[9];
442
+ t6 = $[10];
443
+ t7 = $[11];
444
+ t8 = $[12];
445
+ }
446
+ let t9;
447
+ if ($[22] !== t1 || $[23] !== t2) {
448
+ t9 = /* @__PURE__ */ jsx("div", {
449
+ className: t1,
450
+ children: t2
451
+ });
452
+ $[22] = t1;
453
+ $[23] = t2;
454
+ $[24] = t9;
455
+ } else t9 = $[24];
456
+ let t10;
457
+ if ($[25] !== t3 || $[26] !== t4 || $[27] !== t9) {
458
+ t10 = /* @__PURE__ */ jsxs("div", {
459
+ className: t3,
460
+ children: [t4, t9]
461
+ });
462
+ $[25] = t3;
463
+ $[26] = t4;
464
+ $[27] = t9;
465
+ $[28] = t10;
466
+ } else t10 = $[28];
467
+ let t11;
468
+ if ($[29] !== T0 || $[30] !== t10) {
469
+ t11 = /* @__PURE__ */ jsx(T0, { children: t10 });
470
+ $[29] = T0;
471
+ $[30] = t10;
472
+ $[31] = t11;
473
+ } else t11 = $[31];
474
+ let t12;
475
+ if ($[32] !== t11 || $[33] !== t5 || $[34] !== t6) {
476
+ t12 = /* @__PURE__ */ jsxs("div", {
477
+ className: t5,
478
+ children: [t6, t11]
479
+ });
480
+ $[32] = t11;
481
+ $[33] = t5;
482
+ $[34] = t6;
483
+ $[35] = t12;
484
+ } else t12 = $[35];
485
+ let t13;
486
+ if ($[36] !== T1 || $[37] !== t12 || $[38] !== t7 || $[39] !== t8) {
487
+ t13 = /* @__PURE__ */ jsx(T1, {
488
+ open: t7,
489
+ onOpenChange: t8,
490
+ children: t12
491
+ });
492
+ $[36] = T1;
493
+ $[37] = t12;
494
+ $[38] = t7;
495
+ $[39] = t8;
496
+ $[40] = t13;
497
+ } else t13 = $[40];
498
+ return t13;
499
+ }
500
+ /**
501
+ * FormToolUI - Renders a dynamic form from JSON Schema
502
+ *
503
+ * HITL Pattern (AI SDK v6):
504
+ * - Model calls `form` tool with JSON Schema
505
+ * - This UI renders the form using @rjsf/shadcn
506
+ * - User fills out and submits form
507
+ * - addToolOutput() sends data to backend via WebSocket + updates local UI state
508
+ *
509
+ * Schema Handling:
510
+ * - Normalizes uppercase types (Gemini format) to lowercase (JSON Schema)
511
+ * - Validates schema with AJV and sends errors back to model if invalid
512
+ */
513
+ function _temp(t0) {
514
+ const [key, value] = t0;
515
+ return /* @__PURE__ */ jsxs("div", {
516
+ className: "flex gap-2 text-[11px]",
517
+ children: [/* @__PURE__ */ jsxs("span", {
518
+ className: "font-medium text-muted-foreground",
519
+ children: [key, ":"]
520
+ }), /* @__PURE__ */ jsx("span", {
521
+ className: "text-foreground/70",
522
+ children: formatValue(value)
523
+ })]
524
+ }, key);
525
+ }
526
+ const FormToolUI = makeAssistantToolUI({
527
+ toolName: "form",
528
+ render: ({ args, result, status, addResult, toolCallId }) => {
529
+ const toolExecution = useOptionalToolExecution();
530
+ const errorSentRef = useRef(false);
531
+ const [schemaError, setSchemaError] = useState(null);
532
+ const isWaiting = status.type === "requires-action";
533
+ const normalizedSchema = args.schema && typeof args.schema === "object" ? normalizeSchema(args.schema) : null;
534
+ useEffect(() => {
535
+ if (!normalizedSchema || !isWaiting || errorSentRef.current || result) return;
536
+ const validationError = validateSchema(normalizedSchema);
537
+ if (validationError) {
538
+ errorSentRef.current = true;
539
+ setSchemaError(validationError);
540
+ if (toolExecution) toolExecution.addToolOutput({
541
+ toolCallId,
542
+ output: `Error: ${validationError}`
543
+ });
544
+ else console.error("[FormToolUI] Cannot send schema error: ToolExecution context not available");
545
+ }
546
+ }, [
547
+ normalizedSchema,
548
+ isWaiting,
549
+ result,
550
+ toolExecution,
551
+ toolCallId
552
+ ]);
553
+ if (schemaError) return /* @__PURE__ */ jsx(SchemaErrorDisplay, {
554
+ title: args.title ?? "Form",
555
+ error: schemaError
556
+ });
557
+ if (result) return /* @__PURE__ */ jsx(FormResultDisplay, {
558
+ title: args.title ?? "Form",
559
+ data: result
560
+ });
561
+ const handleSubmit = ({ formData }) => {
562
+ if (!formData) return;
563
+ if (!toolExecution) {
564
+ console.error("[FormToolUI] Cannot submit form: ToolExecution context not available", { toolCallId });
565
+ return;
566
+ }
567
+ const outputValue = typeof formData === "object" ? JSON.stringify(formData) : String(formData);
568
+ toolExecution.addToolOutput({
569
+ toolCallId,
570
+ output: outputValue
571
+ });
572
+ };
573
+ if (!normalizedSchema) return /* @__PURE__ */ jsxs("div", {
574
+ className: "my-1 flex items-center gap-1.5 rounded-lg bg-muted/50 px-2 py-1.5 text-sm text-foreground/70",
575
+ children: [/* @__PURE__ */ jsx(FileText, { className: "h-3.5 w-3.5 animate-pulse text-muted-foreground" }), /* @__PURE__ */ jsx("span", {
576
+ className: "text-xs",
577
+ children: "Loading form..."
578
+ })]
579
+ });
580
+ return /* @__PURE__ */ jsxs("div", {
581
+ className: "my-1 overflow-hidden rounded-lg bg-muted/50",
582
+ children: [/* @__PURE__ */ jsxs("div", {
583
+ className: "flex items-center gap-1.5 px-2 py-1.5 border-b border-border",
584
+ children: [/* @__PURE__ */ jsx(FileText, { className: "h-3.5 w-3.5 text-foreground/70" }), /* @__PURE__ */ jsx("span", {
585
+ className: "text-xs font-medium text-foreground",
586
+ children: args.title ?? "Form"
587
+ })]
588
+ }), /* @__PURE__ */ jsxs("div", {
589
+ className: "px-2 py-2",
590
+ children: [args.description && /* @__PURE__ */ jsx("p", {
591
+ className: "text-xs text-muted-foreground mb-3",
592
+ children: args.description
593
+ }), /* @__PURE__ */ jsx(Form, {
594
+ schema: normalizedSchema,
595
+ validator,
596
+ onSubmit: handleSubmit,
597
+ disabled: !isWaiting,
598
+ className: "space-y-3",
599
+ uiSchema: { "ui:submitButtonOptions": { norender: true } },
600
+ children: /* @__PURE__ */ jsx("div", {
601
+ className: "flex justify-end pt-1",
602
+ children: /* @__PURE__ */ jsxs(Button, {
603
+ type: "submit",
604
+ disabled: !isWaiting,
605
+ size: "sm",
606
+ className: "h-7 px-3 text-xs",
607
+ children: [/* @__PURE__ */ jsx(Check, { className: "h-3 w-3 mr-1" }), args.submitLabel || "Submit"]
608
+ })
609
+ })
610
+ })]
611
+ })]
612
+ });
613
+ }
614
+ });
615
+ var FormToolUI_default = FormToolUI;
616
+
617
+ //#endregion
618
+ export { Collapsible as a, Button as c, useOptionalToolExecution as i, cn as l, FormToolUI_default as n, CollapsibleContent as o, ToolExecutionProvider as r, CollapsibleTrigger as s, FormToolUI as t };
619
+ //# sourceMappingURL=FormToolUI-04m9zI5r.js.map