@meshagent/meshagent-tailwind 0.5.6 → 0.5.8
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/CHANGELOG.md +6 -0
- package/dist/cjs/Chat.js +28 -5
- package/dist/cjs/ChatInput.d.ts +4 -1
- package/dist/cjs/ChatInput.js +15 -3
- package/dist/cjs/ChatThread.js +1 -0
- package/dist/cjs/ChatTypingIndicator.js +2 -2
- package/dist/cjs/components/pane-example.d.ts +1 -0
- package/dist/cjs/components/pane-example.js +43 -0
- package/dist/cjs/components/ui/dialog.d.ts +15 -0
- package/dist/cjs/components/ui/dialog.js +166 -0
- package/dist/cjs/components/ui/form.d.ts +24 -0
- package/dist/cjs/components/ui/form.js +146 -0
- package/dist/cjs/components/ui/input.d.ts +3 -0
- package/dist/cjs/components/ui/input.js +41 -0
- package/dist/cjs/components/ui/label.d.ts +4 -0
- package/dist/cjs/components/ui/label.js +53 -0
- package/dist/cjs/components/ui/radio-group.d.ts +5 -0
- package/dist/cjs/components/ui/radio-group.js +76 -0
- package/dist/cjs/components/ui/select.d.ts +15 -0
- package/dist/cjs/components/ui/select.js +199 -0
- package/dist/cjs/components/ui/sheet.d.ts +13 -0
- package/dist/cjs/components/ui/sheet.js +110 -0
- package/dist/cjs/components/ui/sonner.d.ts +3 -0
- package/dist/cjs/components/ui/sonner.js +42 -0
- package/dist/cjs/lib/pane-service.d.ts +16 -0
- package/dist/cjs/lib/pane-service.js +35 -0
- package/dist/cjs/lib/utils.d.ts +4 -0
- package/dist/cjs/tools/ask-user-for-file.d.ts +10 -0
- package/dist/cjs/tools/ask-user-for-file.js +68 -0
- package/dist/cjs/tools/ask-user.d.ts +10 -0
- package/dist/cjs/tools/ask-user.js +161 -0
- package/dist/cjs/tools/build-schema.d.ts +3 -0
- package/dist/cjs/tools/build-schema.js +55 -0
- package/dist/cjs/tools/display-document.d.ts +10 -0
- package/dist/cjs/tools/display-document.js +49 -0
- package/dist/cjs/tools/file-dialog.d.ts +11 -0
- package/dist/cjs/tools/file-dialog.js +113 -0
- package/dist/cjs/tools/form-dialog.d.ts +12 -0
- package/dist/cjs/tools/form-dialog.js +92 -0
- package/dist/cjs/tools/form-schema.d.ts +41 -0
- package/dist/cjs/tools/form-schema.js +51 -0
- package/dist/cjs/tools/form.d.ts +16 -0
- package/dist/cjs/tools/form.js +81 -0
- package/dist/cjs/tools/toast.d.ts +10 -0
- package/dist/cjs/tools/toast.js +52 -0
- package/dist/cjs/tools/ui-toolkit.d.ts +6 -0
- package/dist/cjs/tools/ui-toolkit.js +44 -0
- package/dist/esm/Chat.js +29 -6
- package/dist/esm/ChatInput.d.ts +4 -1
- package/dist/esm/ChatInput.js +15 -3
- package/dist/esm/ChatThread.js +1 -0
- package/dist/esm/ChatTypingIndicator.js +2 -2
- package/dist/esm/components/pane-example.d.ts +1 -0
- package/dist/esm/components/pane-example.js +30 -0
- package/dist/esm/components/ui/dialog.d.ts +15 -0
- package/dist/esm/components/ui/dialog.js +136 -0
- package/dist/esm/components/ui/form.d.ts +24 -0
- package/dist/esm/components/ui/form.js +121 -0
- package/dist/esm/components/ui/input.d.ts +3 -0
- package/dist/esm/components/ui/input.js +21 -0
- package/dist/esm/components/ui/label.d.ts +4 -0
- package/dist/esm/components/ui/label.js +23 -0
- package/dist/esm/components/ui/radio-group.d.ts +5 -0
- package/dist/esm/components/ui/radio-group.js +46 -0
- package/dist/esm/components/ui/select.d.ts +15 -0
- package/dist/esm/components/ui/select.js +169 -0
- package/dist/esm/components/ui/sheet.d.ts +13 -0
- package/dist/esm/components/ui/sheet.js +80 -0
- package/dist/esm/components/ui/sonner.d.ts +3 -0
- package/dist/esm/components/ui/sonner.js +22 -0
- package/dist/esm/lib/pane-service.d.ts +16 -0
- package/dist/esm/lib/pane-service.js +15 -0
- package/dist/esm/lib/utils.d.ts +4 -0
- package/dist/esm/tools/ask-user-for-file.d.ts +10 -0
- package/dist/esm/tools/ask-user-for-file.js +48 -0
- package/dist/esm/tools/ask-user.d.ts +10 -0
- package/dist/esm/tools/ask-user.js +141 -0
- package/dist/esm/tools/build-schema.d.ts +3 -0
- package/dist/esm/tools/build-schema.js +25 -0
- package/dist/esm/tools/display-document.d.ts +10 -0
- package/dist/esm/tools/display-document.js +29 -0
- package/dist/esm/tools/file-dialog.d.ts +11 -0
- package/dist/esm/tools/file-dialog.js +101 -0
- package/dist/esm/tools/form-dialog.d.ts +12 -0
- package/dist/esm/tools/form-dialog.js +79 -0
- package/dist/esm/tools/form-schema.d.ts +41 -0
- package/dist/esm/tools/form-schema.js +31 -0
- package/dist/esm/tools/form.d.ts +16 -0
- package/dist/esm/tools/form.js +64 -0
- package/dist/esm/tools/toast.d.ts +10 -0
- package/dist/esm/tools/toast.js +32 -0
- package/dist/esm/tools/ui-toolkit.d.ts +6 -0
- package/dist/esm/tools/ui-toolkit.js +24 -0
- package/dist/index.css +1 -1
- package/package.json +7 -4
|
@@ -0,0 +1,25 @@
|
|
|
1
|
+
import * as z from "zod";
|
|
2
|
+
function buildZodSchemaFromAskUser(formSchema) {
|
|
3
|
+
const shape = {};
|
|
4
|
+
for (const item of formSchema) {
|
|
5
|
+
if (item.hasOwnProperty("input")) {
|
|
6
|
+
const f = item.input;
|
|
7
|
+
shape[f.name] = z.string().min(1, `${f.description} is required`);
|
|
8
|
+
} else if (item.hasOwnProperty("checkbox")) {
|
|
9
|
+
const f = item.checkbox;
|
|
10
|
+
shape[f.name] = z.boolean();
|
|
11
|
+
} else if (item.hasOwnProperty("radio_group")) {
|
|
12
|
+
const f = item.radio_group;
|
|
13
|
+
const options = f.options.map((opt) => opt.value);
|
|
14
|
+
shape[f.name] = z.enum(options, "Select an option").default(f.default_value || options[0]);
|
|
15
|
+
} else if (item.hasOwnProperty("select")) {
|
|
16
|
+
const f = item.select;
|
|
17
|
+
const options = f.options.map((opt) => opt.value);
|
|
18
|
+
shape[f.name] = z.enum(options, "Select an option").default(f.default_value || options[0]);
|
|
19
|
+
}
|
|
20
|
+
}
|
|
21
|
+
return z.object(shape);
|
|
22
|
+
}
|
|
23
|
+
export {
|
|
24
|
+
buildZodSchemaFromAskUser
|
|
25
|
+
};
|
|
@@ -0,0 +1,10 @@
|
|
|
1
|
+
import { Tool } from '@meshagent/meshagent';
|
|
2
|
+
import type { Response } from '@meshagent/meshagent';
|
|
3
|
+
export declare class DisplayDocument extends Tool {
|
|
4
|
+
constructor({ name, description, title }?: {
|
|
5
|
+
name?: string;
|
|
6
|
+
description?: string;
|
|
7
|
+
title?: string;
|
|
8
|
+
});
|
|
9
|
+
execute(arguments_: Record<string, any>): Promise<Response>;
|
|
10
|
+
}
|
|
@@ -0,0 +1,29 @@
|
|
|
1
|
+
import { Tool, EmptyResponse } from "@meshagent/meshagent";
|
|
2
|
+
const displayDocumentSchema = {
|
|
3
|
+
type: "object",
|
|
4
|
+
additionalProperties: false,
|
|
5
|
+
required: ["path"],
|
|
6
|
+
properties: {
|
|
7
|
+
path: {
|
|
8
|
+
type: "string"
|
|
9
|
+
}
|
|
10
|
+
}
|
|
11
|
+
};
|
|
12
|
+
class DisplayDocument extends Tool {
|
|
13
|
+
constructor({ name, description, title } = {}) {
|
|
14
|
+
super({
|
|
15
|
+
name: name ?? "display_document",
|
|
16
|
+
description: description ?? "display document to the user",
|
|
17
|
+
title: title ?? "display document",
|
|
18
|
+
inputSchema: displayDocumentSchema
|
|
19
|
+
});
|
|
20
|
+
}
|
|
21
|
+
async execute(arguments_) {
|
|
22
|
+
const { path } = arguments_;
|
|
23
|
+
console.log("Navigate to document:", path);
|
|
24
|
+
return new EmptyResponse();
|
|
25
|
+
}
|
|
26
|
+
}
|
|
27
|
+
export {
|
|
28
|
+
DisplayDocument
|
|
29
|
+
};
|
|
@@ -0,0 +1,11 @@
|
|
|
1
|
+
export declare function showFileDialog({ title, description }: {
|
|
2
|
+
title?: string;
|
|
3
|
+
description?: string;
|
|
4
|
+
}): Promise<Record<string, any> | null>;
|
|
5
|
+
export declare function FileDialog({ title, description, onSubmit, onDismiss, onCleanup }: {
|
|
6
|
+
title?: string;
|
|
7
|
+
description?: string;
|
|
8
|
+
onSubmit: (file: File | null) => void;
|
|
9
|
+
onDismiss: () => void;
|
|
10
|
+
onCleanup: () => void;
|
|
11
|
+
}): import("react/jsx-runtime").JSX.Element;
|
|
@@ -0,0 +1,101 @@
|
|
|
1
|
+
import { jsx, jsxs } from "react/jsx-runtime";
|
|
2
|
+
import { useState, useCallback, useRef } from "react";
|
|
3
|
+
import { createRoot } from "react-dom/client";
|
|
4
|
+
import {
|
|
5
|
+
Dialog,
|
|
6
|
+
DialogContent,
|
|
7
|
+
DialogHeader,
|
|
8
|
+
DialogTitle,
|
|
9
|
+
DialogDescription,
|
|
10
|
+
DialogFooter,
|
|
11
|
+
DialogClose
|
|
12
|
+
} from "../components/ui/dialog";
|
|
13
|
+
import { Button } from "../components/ui/button";
|
|
14
|
+
function showFileDialog({ title, description }) {
|
|
15
|
+
return new Promise((resolve) => {
|
|
16
|
+
const container = document.createElement("div");
|
|
17
|
+
document.body.appendChild(container);
|
|
18
|
+
const root = createRoot(container);
|
|
19
|
+
const onCleanup = () => {
|
|
20
|
+
root.unmount();
|
|
21
|
+
container.remove();
|
|
22
|
+
};
|
|
23
|
+
const onDismiss = () => resolve(null);
|
|
24
|
+
root.render(/* @__PURE__ */ jsx(
|
|
25
|
+
FileDialog,
|
|
26
|
+
{
|
|
27
|
+
title,
|
|
28
|
+
description,
|
|
29
|
+
onSubmit: resolve,
|
|
30
|
+
onDismiss,
|
|
31
|
+
onCleanup
|
|
32
|
+
}
|
|
33
|
+
));
|
|
34
|
+
});
|
|
35
|
+
}
|
|
36
|
+
function FileDialog({ title, description, onSubmit, onDismiss, onCleanup }) {
|
|
37
|
+
const inputRef = useRef(null);
|
|
38
|
+
const [open, setOpen] = useState(true);
|
|
39
|
+
const [selectedFile, setSelectedFile] = useState(null);
|
|
40
|
+
const handleSubmit = useCallback((e) => {
|
|
41
|
+
e.preventDefault();
|
|
42
|
+
onSubmit(selectedFile);
|
|
43
|
+
setOpen(false);
|
|
44
|
+
}, [selectedFile, onSubmit]);
|
|
45
|
+
const handleFileChange = (e) => {
|
|
46
|
+
if (e.target.files && e.target.files[0]) {
|
|
47
|
+
setSelectedFile(e.target.files[0]);
|
|
48
|
+
}
|
|
49
|
+
};
|
|
50
|
+
const onOpenChange = useCallback((isOpen) => {
|
|
51
|
+
onDismiss();
|
|
52
|
+
setOpen(isOpen);
|
|
53
|
+
}, [onDismiss]);
|
|
54
|
+
const onAnimationEnd = useCallback(() => {
|
|
55
|
+
if (!open) {
|
|
56
|
+
onCleanup();
|
|
57
|
+
}
|
|
58
|
+
}, [open, onCleanup]);
|
|
59
|
+
return /* @__PURE__ */ jsx(Dialog, { open, onOpenChange, modal: true, children: /* @__PURE__ */ jsxs(
|
|
60
|
+
DialogContent,
|
|
61
|
+
{
|
|
62
|
+
showCloseButton: true,
|
|
63
|
+
onAnimationEnd,
|
|
64
|
+
className: "\n sm:max-w-[425px]\n fixed top-1/2 left-1/2 w-[90vw] max-w-md max-h-[90vh]\n transform -translate-x-1/2 -translate-y-1/2\n bg-white rounded shadow-lg p-6 overflow-y-auto",
|
|
65
|
+
children: [
|
|
66
|
+
/* @__PURE__ */ jsxs(DialogHeader, { children: [
|
|
67
|
+
/* @__PURE__ */ jsx(DialogTitle, { children: title }),
|
|
68
|
+
/* @__PURE__ */ jsx(DialogDescription, { children: description })
|
|
69
|
+
] }),
|
|
70
|
+
/* @__PURE__ */ jsx(
|
|
71
|
+
"input",
|
|
72
|
+
{
|
|
73
|
+
id: "file-input",
|
|
74
|
+
type: "file",
|
|
75
|
+
onChange: handleFileChange,
|
|
76
|
+
className: "\n block w-full text-sm text-gray-500 file:mr-4 file:py-2\n file:px-4 file:rounded-full file:border-0 file:text-sm \n file:font-semibold file:bg-gray-100 hover:file:bg-gray-200"
|
|
77
|
+
}
|
|
78
|
+
),
|
|
79
|
+
/* @__PURE__ */ jsx(
|
|
80
|
+
"input",
|
|
81
|
+
{
|
|
82
|
+
ref: inputRef,
|
|
83
|
+
type: "file",
|
|
84
|
+
multiple: true,
|
|
85
|
+
accept: "",
|
|
86
|
+
className: "hidden",
|
|
87
|
+
onChange: handleFileChange
|
|
88
|
+
}
|
|
89
|
+
),
|
|
90
|
+
/* @__PURE__ */ jsxs(DialogFooter, { className: "pt-4", children: [
|
|
91
|
+
/* @__PURE__ */ jsx(DialogClose, { asChild: true, children: /* @__PURE__ */ jsx(Button, { variant: "outline", children: "Cancel" }) }),
|
|
92
|
+
/* @__PURE__ */ jsx(Button, { onClick: handleSubmit, children: "Submit" })
|
|
93
|
+
] })
|
|
94
|
+
]
|
|
95
|
+
}
|
|
96
|
+
) });
|
|
97
|
+
}
|
|
98
|
+
export {
|
|
99
|
+
FileDialog,
|
|
100
|
+
showFileDialog
|
|
101
|
+
};
|
|
@@ -0,0 +1,12 @@
|
|
|
1
|
+
import type { FormSchema } from "./form-schema";
|
|
2
|
+
export declare function showUserFormDialog({ formSchema, title }: {
|
|
3
|
+
formSchema: FormSchema;
|
|
4
|
+
title?: string;
|
|
5
|
+
}): Promise<Record<string, any> | null>;
|
|
6
|
+
export declare function FormDialog({ title, formSchema, onSubmit, onDismiss, onCleanup }: {
|
|
7
|
+
title?: string;
|
|
8
|
+
formSchema: FormSchema;
|
|
9
|
+
onSubmit: (data: Record<string, any>) => void;
|
|
10
|
+
onDismiss: () => void;
|
|
11
|
+
onCleanup: () => void;
|
|
12
|
+
}): import("react/jsx-runtime").JSX.Element;
|
|
@@ -0,0 +1,79 @@
|
|
|
1
|
+
import { jsx, jsxs } from "react/jsx-runtime";
|
|
2
|
+
import { useState, useCallback } from "react";
|
|
3
|
+
import { createRoot } from "react-dom/client";
|
|
4
|
+
import { useForm } from "react-hook-form";
|
|
5
|
+
import {
|
|
6
|
+
Dialog,
|
|
7
|
+
DialogContent,
|
|
8
|
+
DialogHeader,
|
|
9
|
+
DialogTitle,
|
|
10
|
+
DialogFooter,
|
|
11
|
+
DialogClose
|
|
12
|
+
} from "@/components/ui/dialog";
|
|
13
|
+
import { Button } from "@/components/ui/button";
|
|
14
|
+
import { FormField } from "./form";
|
|
15
|
+
function showUserFormDialog({ formSchema, title }) {
|
|
16
|
+
return new Promise((resolve) => {
|
|
17
|
+
const container = document.createElement("div");
|
|
18
|
+
document.body.appendChild(container);
|
|
19
|
+
const root = createRoot(container);
|
|
20
|
+
const onCleanup = () => {
|
|
21
|
+
root.unmount();
|
|
22
|
+
container.remove();
|
|
23
|
+
};
|
|
24
|
+
const onDismiss = () => resolve(null);
|
|
25
|
+
root.render(/* @__PURE__ */ jsx(
|
|
26
|
+
FormDialog,
|
|
27
|
+
{
|
|
28
|
+
title,
|
|
29
|
+
formSchema,
|
|
30
|
+
onSubmit: resolve,
|
|
31
|
+
onDismiss,
|
|
32
|
+
onCleanup
|
|
33
|
+
}
|
|
34
|
+
));
|
|
35
|
+
});
|
|
36
|
+
}
|
|
37
|
+
function FormDialog({ title, formSchema, onSubmit, onDismiss, onCleanup }) {
|
|
38
|
+
const [open, setOpen] = useState(true);
|
|
39
|
+
const form = useForm({
|
|
40
|
+
resolver: async (values) => ({ values, errors: {} }),
|
|
41
|
+
mode: "onChange",
|
|
42
|
+
defaultValues: {}
|
|
43
|
+
});
|
|
44
|
+
const handleSubmit = useCallback((e) => {
|
|
45
|
+
e.preventDefault();
|
|
46
|
+
onSubmit(form.getValues());
|
|
47
|
+
}, [onSubmit]);
|
|
48
|
+
const onOpenChange = useCallback((isOpen) => {
|
|
49
|
+
onDismiss();
|
|
50
|
+
setOpen(isOpen);
|
|
51
|
+
}, [onDismiss]);
|
|
52
|
+
const onAnimationEnd = useCallback(() => {
|
|
53
|
+
if (!open) {
|
|
54
|
+
onCleanup();
|
|
55
|
+
}
|
|
56
|
+
}, [open, onCleanup]);
|
|
57
|
+
return /* @__PURE__ */ jsx(Dialog, { open, onOpenChange, modal: true, children: /* @__PURE__ */ jsxs(
|
|
58
|
+
DialogContent,
|
|
59
|
+
{
|
|
60
|
+
className: "sm:max-w-[425px]\n fixed top-1/2 left-1/2 w-[90vw] max-w-md max-h-[90vh]\n transform -translate-x-1/2 -translate-y-1/2\n bg-white rounded shadow-lg p-6 overflow-y-auto",
|
|
61
|
+
showCloseButton: true,
|
|
62
|
+
onAnimationEnd,
|
|
63
|
+
children: [
|
|
64
|
+
/* @__PURE__ */ jsx(DialogHeader, { children: /* @__PURE__ */ jsx(DialogTitle, { children: title }) }),
|
|
65
|
+
/* @__PURE__ */ jsxs("form", { onSubmit: handleSubmit, className: "grid gap-4 py-4", children: [
|
|
66
|
+
formSchema.map((fieldItem, index) => /* @__PURE__ */ jsx(FormField, { fieldItem, control: form.control }, index)),
|
|
67
|
+
/* @__PURE__ */ jsxs(DialogFooter, { className: "pt-4", children: [
|
|
68
|
+
/* @__PURE__ */ jsx(DialogClose, { asChild: true, children: /* @__PURE__ */ jsx(Button, { variant: "outline", children: "Cancel" }) }),
|
|
69
|
+
/* @__PURE__ */ jsx(Button, { type: "submit", children: "Submit" })
|
|
70
|
+
] })
|
|
71
|
+
] })
|
|
72
|
+
]
|
|
73
|
+
}
|
|
74
|
+
) });
|
|
75
|
+
}
|
|
76
|
+
export {
|
|
77
|
+
FormDialog,
|
|
78
|
+
showUserFormDialog
|
|
79
|
+
};
|
|
@@ -0,0 +1,41 @@
|
|
|
1
|
+
export interface BaseField<T> {
|
|
2
|
+
name: string;
|
|
3
|
+
description: string;
|
|
4
|
+
default_value: T;
|
|
5
|
+
}
|
|
6
|
+
export interface InputField extends BaseField<string> {
|
|
7
|
+
multiline: boolean;
|
|
8
|
+
}
|
|
9
|
+
export interface SelectOption {
|
|
10
|
+
name: string;
|
|
11
|
+
value: string;
|
|
12
|
+
}
|
|
13
|
+
export interface SelectField extends BaseField<string> {
|
|
14
|
+
options: SelectOption[];
|
|
15
|
+
}
|
|
16
|
+
export interface RadioOption {
|
|
17
|
+
name: string;
|
|
18
|
+
value: string;
|
|
19
|
+
}
|
|
20
|
+
export interface RadioGroupField extends BaseField<string> {
|
|
21
|
+
options: RadioOption[];
|
|
22
|
+
}
|
|
23
|
+
export interface CheckboxField extends BaseField<boolean> {
|
|
24
|
+
}
|
|
25
|
+
export type FormField = InputField | SelectField | RadioGroupField | CheckboxField;
|
|
26
|
+
export interface InputFieldItem {
|
|
27
|
+
input: InputField;
|
|
28
|
+
}
|
|
29
|
+
export interface SelectFieldItem {
|
|
30
|
+
select: SelectField;
|
|
31
|
+
}
|
|
32
|
+
export interface RadioGroupFieldItem {
|
|
33
|
+
radio_group: RadioGroupField;
|
|
34
|
+
}
|
|
35
|
+
export interface CheckboxFieldItem {
|
|
36
|
+
checkbox: CheckboxField;
|
|
37
|
+
}
|
|
38
|
+
export type FormFieldItem = InputFieldItem | SelectFieldItem | RadioGroupFieldItem | CheckboxFieldItem;
|
|
39
|
+
export type FormSchema = FormFieldItem[];
|
|
40
|
+
export declare function getFormFieldType(fieldItem: FormFieldItem): String;
|
|
41
|
+
export declare function getFormField(fieldItem: FormFieldItem): FormField;
|
|
@@ -0,0 +1,31 @@
|
|
|
1
|
+
function getFormFieldType(fieldItem) {
|
|
2
|
+
if ("input" in fieldItem) {
|
|
3
|
+
return "input";
|
|
4
|
+
} else if ("select" in fieldItem) {
|
|
5
|
+
return "select";
|
|
6
|
+
} else if ("radio_group" in fieldItem) {
|
|
7
|
+
return "radio_group";
|
|
8
|
+
} else if ("checkbox" in fieldItem) {
|
|
9
|
+
return "checkbox";
|
|
10
|
+
}
|
|
11
|
+
throw new Error("Unknown form field type");
|
|
12
|
+
}
|
|
13
|
+
function getFormField(fieldItem) {
|
|
14
|
+
if ("input" in fieldItem) {
|
|
15
|
+
return fieldItem.input;
|
|
16
|
+
}
|
|
17
|
+
if ("select" in fieldItem) {
|
|
18
|
+
return fieldItem.select;
|
|
19
|
+
}
|
|
20
|
+
if ("radio_group" in fieldItem) {
|
|
21
|
+
return fieldItem.radio_group;
|
|
22
|
+
}
|
|
23
|
+
if ("checkbox" in fieldItem) {
|
|
24
|
+
return fieldItem.checkbox;
|
|
25
|
+
}
|
|
26
|
+
throw new Error("Unknown form field type");
|
|
27
|
+
}
|
|
28
|
+
export {
|
|
29
|
+
getFormField,
|
|
30
|
+
getFormFieldType
|
|
31
|
+
};
|
|
@@ -0,0 +1,16 @@
|
|
|
1
|
+
import React from "react";
|
|
2
|
+
import type { Control } from "react-hook-form";
|
|
3
|
+
import type { FormFieldItem } from "./form-schema";
|
|
4
|
+
export type FieldErrorProperty = {
|
|
5
|
+
errors: string[];
|
|
6
|
+
} | undefined;
|
|
7
|
+
export type FieldErrors = {
|
|
8
|
+
errors: string[];
|
|
9
|
+
properties?: {
|
|
10
|
+
[x: string]: FieldErrorProperty;
|
|
11
|
+
} | undefined;
|
|
12
|
+
};
|
|
13
|
+
export declare function FormField({ fieldItem, control }: {
|
|
14
|
+
fieldItem: FormFieldItem;
|
|
15
|
+
control: Control<any>;
|
|
16
|
+
}): React.ReactElement;
|
|
@@ -0,0 +1,64 @@
|
|
|
1
|
+
import { jsx, jsxs } from "react/jsx-runtime";
|
|
2
|
+
import { useMemo } from "react";
|
|
3
|
+
import { useController } from "react-hook-form";
|
|
4
|
+
import {
|
|
5
|
+
getFormField,
|
|
6
|
+
getFormFieldType
|
|
7
|
+
} from "./form-schema";
|
|
8
|
+
function FormField({ fieldItem, control }) {
|
|
9
|
+
const field = useMemo(() => getFormField(fieldItem), [fieldItem]);
|
|
10
|
+
const fieldKey = useMemo(() => getFormFieldType(fieldItem), [fieldItem]);
|
|
11
|
+
const { field: controllerField } = useController({
|
|
12
|
+
name: field.name,
|
|
13
|
+
control,
|
|
14
|
+
defaultValue: field.default_value
|
|
15
|
+
});
|
|
16
|
+
switch (fieldKey) {
|
|
17
|
+
case "checkbox": {
|
|
18
|
+
return /* @__PURE__ */ jsxs("label", { className: "flex items-center space-x-2", children: [
|
|
19
|
+
/* @__PURE__ */ jsx(
|
|
20
|
+
"input",
|
|
21
|
+
{
|
|
22
|
+
type: "checkbox",
|
|
23
|
+
checked: controllerField.value,
|
|
24
|
+
onChange: (e) => controllerField.onChange(e.target.checked)
|
|
25
|
+
}
|
|
26
|
+
),
|
|
27
|
+
/* @__PURE__ */ jsx("span", { children: field.description })
|
|
28
|
+
] });
|
|
29
|
+
}
|
|
30
|
+
case "radio_group": {
|
|
31
|
+
const f2 = field;
|
|
32
|
+
return /* @__PURE__ */ jsxs("div", { children: [
|
|
33
|
+
/* @__PURE__ */ jsx("label", { className: "block font-medium mb-1", children: field.description }),
|
|
34
|
+
(f2.options ?? []).map((opt) => /* @__PURE__ */ jsxs("label", { className: "flex items-center space-x-2", children: [
|
|
35
|
+
/* @__PURE__ */ jsx(
|
|
36
|
+
"input",
|
|
37
|
+
{
|
|
38
|
+
type: "radio",
|
|
39
|
+
value: opt.value,
|
|
40
|
+
checked: controllerField.value === opt.value,
|
|
41
|
+
onChange: () => controllerField.onChange(opt.value)
|
|
42
|
+
}
|
|
43
|
+
),
|
|
44
|
+
/* @__PURE__ */ jsx("span", { children: opt.name })
|
|
45
|
+
] }, opt.value))
|
|
46
|
+
] });
|
|
47
|
+
}
|
|
48
|
+
case "select": {
|
|
49
|
+
const f2 = field;
|
|
50
|
+
return /* @__PURE__ */ jsxs("div", { children: [
|
|
51
|
+
/* @__PURE__ */ jsx("label", { className: "block font-medium mb-1", children: field.description }),
|
|
52
|
+
/* @__PURE__ */ jsx("select", { ...controllerField, className: "border p-2 w-full rounded", children: (f2.options ?? []).map((opt) => /* @__PURE__ */ jsx("option", { value: opt.value, children: opt.name }, opt.value)) })
|
|
53
|
+
] });
|
|
54
|
+
}
|
|
55
|
+
}
|
|
56
|
+
const f = field;
|
|
57
|
+
return /* @__PURE__ */ jsxs("div", { className: "space-y-1", children: [
|
|
58
|
+
/* @__PURE__ */ jsx("label", { className: "block font-medium", children: f.description }),
|
|
59
|
+
f.multiline ? /* @__PURE__ */ jsx("textarea", { ...controllerField, className: "border p-2 w-full rounded" }) : /* @__PURE__ */ jsx("input", { type: "text", ...controllerField, className: "border p-2 w-full rounded" })
|
|
60
|
+
] });
|
|
61
|
+
}
|
|
62
|
+
export {
|
|
63
|
+
FormField
|
|
64
|
+
};
|
|
@@ -0,0 +1,10 @@
|
|
|
1
|
+
import { Tool } from '@meshagent/meshagent';
|
|
2
|
+
import type { Response } from '@meshagent/meshagent';
|
|
3
|
+
export declare class Toast extends Tool {
|
|
4
|
+
constructor({ name, description, title }?: {
|
|
5
|
+
name?: string;
|
|
6
|
+
description?: string;
|
|
7
|
+
title?: string;
|
|
8
|
+
});
|
|
9
|
+
execute(arguments_: Record<string, any>): Promise<Response>;
|
|
10
|
+
}
|
|
@@ -0,0 +1,32 @@
|
|
|
1
|
+
import { Tool, EmptyResponse } from "@meshagent/meshagent";
|
|
2
|
+
import { toast } from "sonner";
|
|
3
|
+
const toastSchema = {
|
|
4
|
+
type: "object",
|
|
5
|
+
additionalProperties: false,
|
|
6
|
+
required: ["title", "description"],
|
|
7
|
+
properties: {
|
|
8
|
+
title: {
|
|
9
|
+
type: "string",
|
|
10
|
+
description: "a very short summary suitable for a toast title"
|
|
11
|
+
}
|
|
12
|
+
}
|
|
13
|
+
};
|
|
14
|
+
class Toast extends Tool {
|
|
15
|
+
constructor({ name, description, title } = {}) {
|
|
16
|
+
super({
|
|
17
|
+
name: name ?? "show_toast",
|
|
18
|
+
description: description ?? "let the user know something important (will be shown as a toast)",
|
|
19
|
+
title: title ?? "show user a toast",
|
|
20
|
+
inputSchema: toastSchema
|
|
21
|
+
});
|
|
22
|
+
}
|
|
23
|
+
async execute(arguments_) {
|
|
24
|
+
toast(arguments_.title, {
|
|
25
|
+
description: arguments_.description ?? ""
|
|
26
|
+
});
|
|
27
|
+
return new EmptyResponse();
|
|
28
|
+
}
|
|
29
|
+
}
|
|
30
|
+
export {
|
|
31
|
+
Toast
|
|
32
|
+
};
|
|
@@ -0,0 +1,24 @@
|
|
|
1
|
+
import { RemoteToolkit } from "@meshagent/meshagent";
|
|
2
|
+
import { AskUser } from "./ask-user";
|
|
3
|
+
import { AskUserForFile } from "./ask-user-for-file";
|
|
4
|
+
import { DisplayDocument } from "./display-document";
|
|
5
|
+
import { Toast } from "./toast";
|
|
6
|
+
class UIToolkit extends RemoteToolkit {
|
|
7
|
+
constructor({ room }) {
|
|
8
|
+
super({
|
|
9
|
+
name: "ui",
|
|
10
|
+
title: "UI Tools",
|
|
11
|
+
description: "User interface tools",
|
|
12
|
+
room,
|
|
13
|
+
tools: [
|
|
14
|
+
new AskUser(),
|
|
15
|
+
new AskUserForFile(),
|
|
16
|
+
new Toast(),
|
|
17
|
+
new DisplayDocument()
|
|
18
|
+
]
|
|
19
|
+
});
|
|
20
|
+
}
|
|
21
|
+
}
|
|
22
|
+
export {
|
|
23
|
+
UIToolkit
|
|
24
|
+
};
|