@agent-native/dispatch 0.24.2 → 0.24.3
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.
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"agents-panel.d.ts","sourceRoot":"","sources":["../../src/components/agents-panel.tsx"],"names":[],"mappings":"
|
|
1
|
+
{"version":3,"file":"agents-panel.d.ts","sourceRoot":"","sources":["../../src/components/agents-panel.tsx"],"names":[],"mappings":"AAmBA,MAAM,WAAW,cAAc;IAC7B,EAAE,EAAE,MAAM,CAAC;IACX,IAAI,EAAE,MAAM,CAAC;IACb,WAAW,EAAE,MAAM,CAAC;IACpB,GAAG,EAAE,MAAM,CAAC;IACZ,KAAK,EAAE,MAAM,CAAC;IACd,MAAM,EAAE,SAAS,GAAG,QAAQ,GAAG,WAAW,CAAC;IAC3C,UAAU,CAAC,EAAE,MAAM,CAAC;IACpB,IAAI,CAAC,EAAE,MAAM,CAAC;IACd,KAAK,CAAC,EAAE,QAAQ,GAAG,UAAU,CAAC;CAC/B;AA4CD,wBAAgB,WAAW,CAAC,EAC1B,MAAM,EACN,SAAS,GACV,EAAE;IACD,MAAM,EAAE,cAAc,EAAE,CAAC;IACzB,SAAS,EAAE,MAAM,IAAI,CAAC;CACvB,mDA+SA"}
|
|
@@ -1,5 +1,6 @@
|
|
|
1
1
|
import { jsx as _jsx, jsxs as _jsxs } from "react/jsx-runtime";
|
|
2
2
|
import { agentNativePath } from "@agent-native/core/client/api-path";
|
|
3
|
+
import { useOrgRole } from "@agent-native/core/client/org";
|
|
3
4
|
import { IconExternalLink, IconTrash } from "@tabler/icons-react";
|
|
4
5
|
import { useRef, useState } from "react";
|
|
5
6
|
import { AlertDialog, AlertDialogAction, AlertDialogCancel, AlertDialogContent, AlertDialogDescription, AlertDialogFooter, AlertDialogHeader, AlertDialogTitle, AlertDialogTrigger, } from "./ui/alert-dialog.js";
|
|
@@ -46,6 +47,10 @@ function validateAgentForm(name, url) {
|
|
|
46
47
|
return errors;
|
|
47
48
|
}
|
|
48
49
|
export function AgentsPanel({ agents, onRefresh, }) {
|
|
50
|
+
const { org, isLoading: orgLoading, error: orgError } = useOrgRole();
|
|
51
|
+
const canManageSharedAgents = !orgLoading &&
|
|
52
|
+
!orgError &&
|
|
53
|
+
(!org?.orgId || org.role === "owner" || org.role === "admin");
|
|
49
54
|
const [name, setName] = useState("");
|
|
50
55
|
const [url, setUrl] = useState("");
|
|
51
56
|
const [description, setDescription] = useState("");
|
|
@@ -117,12 +122,12 @@ export function AgentsPanel({ agents, onRefresh, }) {
|
|
|
117
122
|
if (res.ok)
|
|
118
123
|
onRefresh();
|
|
119
124
|
};
|
|
120
|
-
return (_jsx("section", { className: "rounded-2xl bg-card p-5", children: _jsxs("div", { className: "grid gap-4 xl:grid-cols-[minmax(0,1fr)_320px]", children: [_jsxs("div", { className: "space-y-4", children: [_jsxs("div", { children: [_jsx("div", { className: "text-sm font-medium text-foreground", children: "Available by default" }), _jsxs("div", { className: "mt-2 flex flex-wrap gap-2", children: [builtinAgents.map((agent) => (_jsxs("div", { className: "inline-flex items-center gap-2 rounded-full border px-3 py-1.5 text-xs text-muted-foreground", children: [_jsx("span", { className: "h-2 w-2 rounded-full", style: { backgroundColor: agent.color } }), _jsx("span", { children: agent.name })] }, agent.id))), builtinAgents.length === 0 && (_jsx("div", { className: "rounded-xl border border-dashed px-4 py-6 text-sm text-muted-foreground", children: "No default agents detected." }))] })] }), _jsxs("div", { children: [_jsx("div", { className: "text-sm font-medium text-foreground", children: "Added in this workspace" }), _jsxs("div", { className: "mt-2 space-y-2", children: [workspaceAgents.map((agent) => (_jsx("div", { className: "flex items-start justify-between gap-3 rounded-xl border bg-muted/30 px-4 py-3", children: _jsxs("div", { className: "min-w-0", children: [_jsx("div", { className: "text-sm font-medium text-foreground", children: agent.name }), agent.description ? (_jsx("div", { className: "mt-1 text-xs text-muted-foreground", children: agent.description })) : null, _jsx("div", { className: "mt-1 text-xs text-muted-foreground", children: _jsxs("a", { href: agent.url, target: "_blank", rel: "noreferrer", className: "inline-flex items-center gap-1 hover:text-foreground", children: [agent.url, _jsx(IconExternalLink, { className: "h-3 w-3" })] }) })] }) }, agent.id))), customAgents.map((agent) => (_jsxs("div", { className: "flex items-start justify-between gap-3 rounded-xl border bg-muted/30 px-4 py-3", children: [_jsxs("div", { className: "min-w-0", children: [_jsx("div", { className: "text-sm font-medium text-foreground", children: agent.name }), agent.description ? (_jsx("div", { className: "mt-1 text-xs text-muted-foreground", children: agent.description })) : null, _jsxs("div", { className: "mt-1 flex items-center gap-2 text-xs text-muted-foreground", children: [_jsxs("a", { href: agent.url, target: "_blank", rel: "noreferrer", className: "inline-flex items-center gap-1 hover:text-foreground", children: [agent.url, _jsx(IconExternalLink, { className: "h-3 w-3" })] }), _jsx("span", { children: "\u00B7" }), _jsx("span", { children: agent.scope || "shared" })] })] }), _jsxs(AlertDialog, { children: [_jsx(AlertDialogTrigger, { asChild: true, children: _jsx(Button, { variant: "ghost", size: "icon", children: _jsx(IconTrash, { className: "h-4 w-4" }) }) }), _jsxs(AlertDialogContent, { children: [_jsxs(AlertDialogHeader, { children: [_jsx(AlertDialogTitle, { children: "Remove this agent?" }), _jsxs(AlertDialogDescription, { children: ["\u201C", agent.name, "\u201D will be removed from the workspace. Any jobs or chats that delegate to it will stop working."] })] }), _jsxs(AlertDialogFooter, { children: [_jsx(AlertDialogCancel, { children: "Cancel" }), _jsx(AlertDialogAction, { onClick: () => handleDelete(agent.resourceId), children: "Remove" })] })] })] })] }, agent.id))), workspaceAgents.length === 0 && customAgents.length === 0 && (_jsx("div", { className: "rounded-xl border border-dashed px-4 py-6 text-sm text-muted-foreground", children: "No extra agents added yet." }))] })] })] }), _jsxs("div", { className: "rounded-xl border bg-muted/20 p-4", children: [_jsx("div", { className: "text-sm font-medium text-foreground", children: "Add external agent" }), _jsx("p", { className: "mt-1 text-xs leading-relaxed text-muted-foreground", children: "Add another A2A-compatible app by saving its agent endpoint here." }), _jsxs("form", { className:
|
|
125
|
+
return (_jsx("section", { className: "rounded-2xl bg-card p-5", children: _jsxs("div", { className: "grid gap-4 xl:grid-cols-[minmax(0,1fr)_320px]", children: [_jsxs("div", { className: "space-y-4", children: [_jsxs("div", { children: [_jsx("div", { className: "text-sm font-medium text-foreground", children: "Available by default" }), _jsxs("div", { className: "mt-2 flex flex-wrap gap-2", children: [builtinAgents.map((agent) => (_jsxs("div", { className: "inline-flex items-center gap-2 rounded-full border px-3 py-1.5 text-xs text-muted-foreground", children: [_jsx("span", { className: "h-2 w-2 rounded-full", style: { backgroundColor: agent.color } }), _jsx("span", { children: agent.name })] }, agent.id))), builtinAgents.length === 0 && (_jsx("div", { className: "rounded-xl border border-dashed px-4 py-6 text-sm text-muted-foreground", children: "No default agents detected." }))] })] }), _jsxs("div", { children: [_jsx("div", { className: "text-sm font-medium text-foreground", children: "Added in this workspace" }), _jsxs("div", { className: "mt-2 space-y-2", children: [workspaceAgents.map((agent) => (_jsx("div", { className: "flex items-start justify-between gap-3 rounded-xl border bg-muted/30 px-4 py-3", children: _jsxs("div", { className: "min-w-0", children: [_jsx("div", { className: "text-sm font-medium text-foreground", children: agent.name }), agent.description ? (_jsx("div", { className: "mt-1 text-xs text-muted-foreground", children: agent.description })) : null, _jsx("div", { className: "mt-1 text-xs text-muted-foreground", children: _jsxs("a", { href: agent.url, target: "_blank", rel: "noreferrer", className: "inline-flex items-center gap-1 hover:text-foreground", children: [agent.url, _jsx(IconExternalLink, { className: "h-3 w-3" })] }) })] }) }, agent.id))), customAgents.map((agent) => (_jsxs("div", { className: "flex items-start justify-between gap-3 rounded-xl border bg-muted/30 px-4 py-3", children: [_jsxs("div", { className: "min-w-0", children: [_jsx("div", { className: "text-sm font-medium text-foreground", children: agent.name }), agent.description ? (_jsx("div", { className: "mt-1 text-xs text-muted-foreground", children: agent.description })) : null, _jsxs("div", { className: "mt-1 flex items-center gap-2 text-xs text-muted-foreground", children: [_jsxs("a", { href: agent.url, target: "_blank", rel: "noreferrer", className: "inline-flex items-center gap-1 hover:text-foreground", children: [agent.url, _jsx(IconExternalLink, { className: "h-3 w-3" })] }), _jsx("span", { children: "\u00B7" }), _jsx("span", { children: agent.scope || "shared" })] })] }), canManageSharedAgents && (_jsxs(AlertDialog, { children: [_jsx(AlertDialogTrigger, { asChild: true, children: _jsx(Button, { variant: "ghost", size: "icon", children: _jsx(IconTrash, { className: "h-4 w-4" }) }) }), _jsxs(AlertDialogContent, { children: [_jsxs(AlertDialogHeader, { children: [_jsx(AlertDialogTitle, { children: "Remove this agent?" }), _jsxs(AlertDialogDescription, { children: ["\u201C", agent.name, "\u201D will be removed from the workspace. Any jobs or chats that delegate to it will stop working."] })] }), _jsxs(AlertDialogFooter, { children: [_jsx(AlertDialogCancel, { children: "Cancel" }), _jsx(AlertDialogAction, { onClick: () => handleDelete(agent.resourceId), children: "Remove" })] })] })] }))] }, agent.id))), workspaceAgents.length === 0 && customAgents.length === 0 && (_jsx("div", { className: "rounded-xl border border-dashed px-4 py-6 text-sm text-muted-foreground", children: "No extra agents added yet." }))] })] })] }), _jsxs("div", { className: "rounded-xl border bg-muted/20 p-4", children: [_jsx("div", { className: "text-sm font-medium text-foreground", children: "Add external agent" }), canManageSharedAgents ? (_jsx("p", { className: "mt-1 text-xs leading-relaxed text-muted-foreground", children: "Add another A2A-compatible app by saving its agent endpoint here." })) : !orgLoading ? (_jsx("p", { className: "mt-1 text-xs leading-relaxed text-muted-foreground", children: "Only workspace owners and admins can add shared agents." })) : null, _jsxs("form", { className: `mt-4 space-y-3 ${canManageSharedAgents ? "" : "hidden"}`, onSubmit: handleAdd, noValidate: true, children: [_jsxs("div", { className: "space-y-1.5", children: [_jsx(Input, { ref: nameRef, value: name, onChange: (event) => {
|
|
121
126
|
setName(event.target.value);
|
|
122
127
|
setErrors((current) => ({ ...current, name: undefined }));
|
|
123
128
|
}, placeholder: "Name", "aria-invalid": Boolean(errors.name), "aria-describedby": errors.name ? "external-agent-name-error" : undefined }), errors.name ? (_jsx("p", { id: "external-agent-name-error", className: "text-xs font-medium text-destructive", children: errors.name })) : null] }), _jsxs("div", { className: "space-y-1.5", children: [_jsx(Input, { value: url, onChange: (event) => {
|
|
124
129
|
setUrl(event.target.value);
|
|
125
130
|
setErrors((current) => ({ ...current, url: undefined }));
|
|
126
|
-
}, placeholder: "https://app.example.com", "aria-invalid": Boolean(errors.url), "aria-describedby": errors.url ? "external-agent-url-error" : undefined }), errors.url ? (_jsx("p", { id: "external-agent-url-error", className: "text-xs font-medium text-destructive", children: errors.url })) : null] }), _jsx(Input, { value: description, onChange: (event) => setDescription(event.target.value), placeholder: "Description (optional)" }), errors.form ? (_jsx("p", { className: "text-xs font-medium text-destructive", children: errors.form })) : null, _jsx(Button, { type: "submit", className: "w-full", disabled: saving, children: saving ? "Saving..." : "Add agent" })] })] })] }) }));
|
|
131
|
+
}, placeholder: "https://app.example.com", "aria-invalid": Boolean(errors.url), "aria-describedby": errors.url ? "external-agent-url-error" : undefined }), errors.url ? (_jsx("p", { id: "external-agent-url-error", className: "text-xs font-medium text-destructive", children: errors.url })) : null] }), _jsx(Input, { value: description, onChange: (event) => setDescription(event.target.value), placeholder: "Description (optional)" }), errors.form ? (_jsx("p", { className: "text-xs font-medium text-destructive", children: errors.form })) : null, _jsx(Button, { type: "submit", className: "w-full", disabled: saving || !canManageSharedAgents, children: saving ? "Saving..." : "Add agent" })] })] })] }) }));
|
|
127
132
|
}
|
|
128
133
|
//# sourceMappingURL=agents-panel.js.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"agents-panel.js","sourceRoot":"","sources":["../../src/components/agents-panel.tsx"],"names":[],"mappings":"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","sourcesContent":["import { agentNativePath } from \"@agent-native/core/client/api-path\";\nimport { IconExternalLink, IconTrash } from \"@tabler/icons-react\";\nimport { useRef, useState, type FormEvent } from \"react\";\n\nimport {\n AlertDialog,\n AlertDialogAction,\n AlertDialogCancel,\n AlertDialogContent,\n AlertDialogDescription,\n AlertDialogFooter,\n AlertDialogHeader,\n AlertDialogTitle,\n AlertDialogTrigger,\n} from \"./ui/alert-dialog\";\nimport { Button } from \"./ui/button\";\nimport { Input } from \"./ui/input\";\n\nexport interface ConnectedAgent {\n id: string;\n name: string;\n description: string;\n url: string;\n color: string;\n source: \"builtin\" | \"custom\" | \"workspace\";\n resourceId?: string;\n path?: string;\n scope?: \"shared\" | \"personal\";\n}\n\ntype AgentFormErrors = Partial<Record<\"name\" | \"url\" | \"form\", string>>;\n\nfunction slugifyAgentName(value: string): string {\n return value\n .trim()\n .toLowerCase()\n .replace(/[^a-z0-9]+/g, \"-\")\n .replace(/^-+|-+$/g, \"\");\n}\n\nfunction validateAgentForm(name: string, url: string): AgentFormErrors {\n const errors: AgentFormErrors = {};\n const trimmedName = name.trim();\n const trimmedUrl = url.trim();\n\n if (!trimmedName) {\n errors.name = \"Agent name is required.\";\n } else if (!slugifyAgentName(trimmedName)) {\n errors.name = \"Agent name must include at least one letter or number.\";\n }\n\n if (!trimmedUrl) {\n errors.url = \"Agent endpoint URL is required.\";\n } else {\n try {\n const parsed = new URL(trimmedUrl);\n if (parsed.protocol !== \"https:\" && parsed.protocol !== \"http:\") {\n errors.url = \"Use an http:// or https:// endpoint URL.\";\n } else if (!parsed.hostname) {\n errors.url = \"Enter a complete endpoint URL with a host.\";\n } else if (parsed.username || parsed.password) {\n errors.url = \"Do not include credentials in the endpoint URL.\";\n }\n } catch {\n errors.url =\n \"Enter a valid endpoint URL, such as https://app.example.com.\";\n }\n }\n\n return errors;\n}\n\nexport function AgentsPanel({\n agents,\n onRefresh,\n}: {\n agents: ConnectedAgent[];\n onRefresh: () => void;\n}) {\n const [name, setName] = useState(\"\");\n const [url, setUrl] = useState(\"\");\n const [description, setDescription] = useState(\"\");\n const [saving, setSaving] = useState(false);\n const [errors, setErrors] = useState<AgentFormErrors>({});\n const nameRef = useRef<HTMLInputElement>(null);\n\n const customAgents = agents.filter((agent) => agent.source === \"custom\");\n const workspaceAgents = agents.filter(\n (agent) => agent.source === \"workspace\",\n );\n const builtinAgents = agents.filter((agent) => agent.source === \"builtin\");\n\n const handleAdd = async (event?: FormEvent<HTMLFormElement>) => {\n event?.preventDefault();\n const trimmedName = name.trim();\n const trimmedUrl = url.trim();\n const nextErrors = validateAgentForm(trimmedName, trimmedUrl);\n if (Object.keys(nextErrors).length > 0) {\n setErrors(nextErrors);\n return;\n }\n\n const id = slugifyAgentName(trimmedName);\n const agentJson = JSON.stringify(\n {\n id,\n name: trimmedName,\n description: description.trim() || undefined,\n url: trimmedUrl,\n color: \"#6B7280\",\n },\n null,\n 2,\n );\n\n setSaving(true);\n try {\n const res = await fetch(agentNativePath(\"/_agent-native/resources\"), {\n method: \"POST\",\n headers: { \"Content-Type\": \"application/json\" },\n body: JSON.stringify({\n path: `remote-agents/${id}.json`,\n content: agentJson,\n shared: true,\n }),\n });\n if (res.ok) {\n setName(\"\");\n setUrl(\"\");\n setDescription(\"\");\n setErrors({});\n onRefresh();\n nameRef.current?.focus();\n } else {\n setErrors({\n form: `Could not add agent. Request failed with ${res.status}.`,\n });\n }\n } catch (error) {\n setErrors({\n form:\n error instanceof Error\n ? error.message\n : \"Could not add agent. Please try again.\",\n });\n } finally {\n setSaving(false);\n }\n };\n\n const handleDelete = async (resourceId?: string) => {\n if (!resourceId) return;\n const res = await fetch(\n agentNativePath(`/_agent-native/resources/${resourceId}`),\n {\n method: \"DELETE\",\n },\n );\n if (res.ok) onRefresh();\n };\n\n return (\n <section className=\"rounded-2xl bg-card p-5\">\n <div className=\"grid gap-4 xl:grid-cols-[minmax(0,1fr)_320px]\">\n <div className=\"space-y-4\">\n <div>\n <div className=\"text-sm font-medium text-foreground\">\n Available by default\n </div>\n <div className=\"mt-2 flex flex-wrap gap-2\">\n {builtinAgents.map((agent) => (\n <div\n key={agent.id}\n className=\"inline-flex items-center gap-2 rounded-full border px-3 py-1.5 text-xs text-muted-foreground\"\n >\n <span\n className=\"h-2 w-2 rounded-full\"\n style={{ backgroundColor: agent.color }}\n />\n <span>{agent.name}</span>\n </div>\n ))}\n {builtinAgents.length === 0 && (\n <div className=\"rounded-xl border border-dashed px-4 py-6 text-sm text-muted-foreground\">\n No default agents detected.\n </div>\n )}\n </div>\n </div>\n\n <div>\n <div className=\"text-sm font-medium text-foreground\">\n Added in this workspace\n </div>\n <div className=\"mt-2 space-y-2\">\n {workspaceAgents.map((agent) => (\n <div\n key={agent.id}\n className=\"flex items-start justify-between gap-3 rounded-xl border bg-muted/30 px-4 py-3\"\n >\n <div className=\"min-w-0\">\n <div className=\"text-sm font-medium text-foreground\">\n {agent.name}\n </div>\n {agent.description ? (\n <div className=\"mt-1 text-xs text-muted-foreground\">\n {agent.description}\n </div>\n ) : null}\n <div className=\"mt-1 text-xs text-muted-foreground\">\n <a\n href={agent.url}\n target=\"_blank\"\n rel=\"noreferrer\"\n className=\"inline-flex items-center gap-1 hover:text-foreground\"\n >\n {agent.url}\n <IconExternalLink className=\"h-3 w-3\" />\n </a>\n </div>\n </div>\n </div>\n ))}\n {customAgents.map((agent) => (\n <div\n key={agent.id}\n className=\"flex items-start justify-between gap-3 rounded-xl border bg-muted/30 px-4 py-3\"\n >\n <div className=\"min-w-0\">\n <div className=\"text-sm font-medium text-foreground\">\n {agent.name}\n </div>\n {agent.description ? (\n <div className=\"mt-1 text-xs text-muted-foreground\">\n {agent.description}\n </div>\n ) : null}\n <div className=\"mt-1 flex items-center gap-2 text-xs text-muted-foreground\">\n <a\n href={agent.url}\n target=\"_blank\"\n rel=\"noreferrer\"\n className=\"inline-flex items-center gap-1 hover:text-foreground\"\n >\n {agent.url}\n <IconExternalLink className=\"h-3 w-3\" />\n </a>\n <span>·</span>\n <span>{agent.scope || \"shared\"}</span>\n </div>\n </div>\n <AlertDialog>\n <AlertDialogTrigger asChild>\n <Button variant=\"ghost\" size=\"icon\">\n <IconTrash className=\"h-4 w-4\" />\n </Button>\n </AlertDialogTrigger>\n <AlertDialogContent>\n <AlertDialogHeader>\n <AlertDialogTitle>Remove this agent?</AlertDialogTitle>\n <AlertDialogDescription>\n “{agent.name}” will be removed from the workspace. Any\n jobs or chats that delegate to it will stop working.\n </AlertDialogDescription>\n </AlertDialogHeader>\n <AlertDialogFooter>\n <AlertDialogCancel>Cancel</AlertDialogCancel>\n <AlertDialogAction\n onClick={() => handleDelete(agent.resourceId)}\n >\n Remove\n </AlertDialogAction>\n </AlertDialogFooter>\n </AlertDialogContent>\n </AlertDialog>\n </div>\n ))}\n {workspaceAgents.length === 0 && customAgents.length === 0 && (\n <div className=\"rounded-xl border border-dashed px-4 py-6 text-sm text-muted-foreground\">\n No extra agents added yet.\n </div>\n )}\n </div>\n </div>\n </div>\n\n <div className=\"rounded-xl border bg-muted/20 p-4\">\n <div className=\"text-sm font-medium text-foreground\">\n Add external agent\n </div>\n <p className=\"mt-1 text-xs leading-relaxed text-muted-foreground\">\n Add another A2A-compatible app by saving its agent endpoint here.\n </p>\n <form className=\"mt-4 space-y-3\" onSubmit={handleAdd} noValidate>\n <div className=\"space-y-1.5\">\n <Input\n ref={nameRef}\n value={name}\n onChange={(event) => {\n setName(event.target.value);\n setErrors((current) => ({ ...current, name: undefined }));\n }}\n placeholder=\"Name\"\n aria-invalid={Boolean(errors.name)}\n aria-describedby={\n errors.name ? \"external-agent-name-error\" : undefined\n }\n />\n {errors.name ? (\n <p\n id=\"external-agent-name-error\"\n className=\"text-xs font-medium text-destructive\"\n >\n {errors.name}\n </p>\n ) : null}\n </div>\n <div className=\"space-y-1.5\">\n <Input\n value={url}\n onChange={(event) => {\n setUrl(event.target.value);\n setErrors((current) => ({ ...current, url: undefined }));\n }}\n placeholder=\"https://app.example.com\"\n aria-invalid={Boolean(errors.url)}\n aria-describedby={\n errors.url ? \"external-agent-url-error\" : undefined\n }\n />\n {errors.url ? (\n <p\n id=\"external-agent-url-error\"\n className=\"text-xs font-medium text-destructive\"\n >\n {errors.url}\n </p>\n ) : null}\n </div>\n <Input\n value={description}\n onChange={(event) => setDescription(event.target.value)}\n placeholder=\"Description (optional)\"\n />\n {errors.form ? (\n <p className=\"text-xs font-medium text-destructive\">\n {errors.form}\n </p>\n ) : null}\n <Button type=\"submit\" className=\"w-full\" disabled={saving}>\n {saving ? \"Saving...\" : \"Add agent\"}\n </Button>\n </form>\n </div>\n </div>\n </section>\n );\n}\n"]}
|
|
1
|
+
{"version":3,"file":"agents-panel.js","sourceRoot":"","sources":["../../src/components/agents-panel.tsx"],"names":[],"mappings":"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","sourcesContent":["import { agentNativePath } from \"@agent-native/core/client/api-path\";\nimport { useOrgRole } from \"@agent-native/core/client/org\";\nimport { IconExternalLink, IconTrash } from \"@tabler/icons-react\";\nimport { useRef, useState, type FormEvent } from \"react\";\n\nimport {\n AlertDialog,\n AlertDialogAction,\n AlertDialogCancel,\n AlertDialogContent,\n AlertDialogDescription,\n AlertDialogFooter,\n AlertDialogHeader,\n AlertDialogTitle,\n AlertDialogTrigger,\n} from \"./ui/alert-dialog\";\nimport { Button } from \"./ui/button\";\nimport { Input } from \"./ui/input\";\n\nexport interface ConnectedAgent {\n id: string;\n name: string;\n description: string;\n url: string;\n color: string;\n source: \"builtin\" | \"custom\" | \"workspace\";\n resourceId?: string;\n path?: string;\n scope?: \"shared\" | \"personal\";\n}\n\ntype AgentFormErrors = Partial<Record<\"name\" | \"url\" | \"form\", string>>;\n\nfunction slugifyAgentName(value: string): string {\n return value\n .trim()\n .toLowerCase()\n .replace(/[^a-z0-9]+/g, \"-\")\n .replace(/^-+|-+$/g, \"\");\n}\n\nfunction validateAgentForm(name: string, url: string): AgentFormErrors {\n const errors: AgentFormErrors = {};\n const trimmedName = name.trim();\n const trimmedUrl = url.trim();\n\n if (!trimmedName) {\n errors.name = \"Agent name is required.\";\n } else if (!slugifyAgentName(trimmedName)) {\n errors.name = \"Agent name must include at least one letter or number.\";\n }\n\n if (!trimmedUrl) {\n errors.url = \"Agent endpoint URL is required.\";\n } else {\n try {\n const parsed = new URL(trimmedUrl);\n if (parsed.protocol !== \"https:\" && parsed.protocol !== \"http:\") {\n errors.url = \"Use an http:// or https:// endpoint URL.\";\n } else if (!parsed.hostname) {\n errors.url = \"Enter a complete endpoint URL with a host.\";\n } else if (parsed.username || parsed.password) {\n errors.url = \"Do not include credentials in the endpoint URL.\";\n }\n } catch {\n errors.url =\n \"Enter a valid endpoint URL, such as https://app.example.com.\";\n }\n }\n\n return errors;\n}\n\nexport function AgentsPanel({\n agents,\n onRefresh,\n}: {\n agents: ConnectedAgent[];\n onRefresh: () => void;\n}) {\n const { org, isLoading: orgLoading, error: orgError } = useOrgRole();\n const canManageSharedAgents =\n !orgLoading &&\n !orgError &&\n (!org?.orgId || org.role === \"owner\" || org.role === \"admin\");\n const [name, setName] = useState(\"\");\n const [url, setUrl] = useState(\"\");\n const [description, setDescription] = useState(\"\");\n const [saving, setSaving] = useState(false);\n const [errors, setErrors] = useState<AgentFormErrors>({});\n const nameRef = useRef<HTMLInputElement>(null);\n\n const customAgents = agents.filter((agent) => agent.source === \"custom\");\n const workspaceAgents = agents.filter(\n (agent) => agent.source === \"workspace\",\n );\n const builtinAgents = agents.filter((agent) => agent.source === \"builtin\");\n\n const handleAdd = async (event?: FormEvent<HTMLFormElement>) => {\n event?.preventDefault();\n const trimmedName = name.trim();\n const trimmedUrl = url.trim();\n const nextErrors = validateAgentForm(trimmedName, trimmedUrl);\n if (Object.keys(nextErrors).length > 0) {\n setErrors(nextErrors);\n return;\n }\n\n const id = slugifyAgentName(trimmedName);\n const agentJson = JSON.stringify(\n {\n id,\n name: trimmedName,\n description: description.trim() || undefined,\n url: trimmedUrl,\n color: \"#6B7280\",\n },\n null,\n 2,\n );\n\n setSaving(true);\n try {\n const res = await fetch(agentNativePath(\"/_agent-native/resources\"), {\n method: \"POST\",\n headers: { \"Content-Type\": \"application/json\" },\n body: JSON.stringify({\n path: `remote-agents/${id}.json`,\n content: agentJson,\n shared: true,\n }),\n });\n if (res.ok) {\n setName(\"\");\n setUrl(\"\");\n setDescription(\"\");\n setErrors({});\n onRefresh();\n nameRef.current?.focus();\n } else {\n setErrors({\n form: `Could not add agent. Request failed with ${res.status}.`,\n });\n }\n } catch (error) {\n setErrors({\n form:\n error instanceof Error\n ? error.message\n : \"Could not add agent. Please try again.\",\n });\n } finally {\n setSaving(false);\n }\n };\n\n const handleDelete = async (resourceId?: string) => {\n if (!resourceId) return;\n const res = await fetch(\n agentNativePath(`/_agent-native/resources/${resourceId}`),\n {\n method: \"DELETE\",\n },\n );\n if (res.ok) onRefresh();\n };\n\n return (\n <section className=\"rounded-2xl bg-card p-5\">\n <div className=\"grid gap-4 xl:grid-cols-[minmax(0,1fr)_320px]\">\n <div className=\"space-y-4\">\n <div>\n <div className=\"text-sm font-medium text-foreground\">\n Available by default\n </div>\n <div className=\"mt-2 flex flex-wrap gap-2\">\n {builtinAgents.map((agent) => (\n <div\n key={agent.id}\n className=\"inline-flex items-center gap-2 rounded-full border px-3 py-1.5 text-xs text-muted-foreground\"\n >\n <span\n className=\"h-2 w-2 rounded-full\"\n style={{ backgroundColor: agent.color }}\n />\n <span>{agent.name}</span>\n </div>\n ))}\n {builtinAgents.length === 0 && (\n <div className=\"rounded-xl border border-dashed px-4 py-6 text-sm text-muted-foreground\">\n No default agents detected.\n </div>\n )}\n </div>\n </div>\n\n <div>\n <div className=\"text-sm font-medium text-foreground\">\n Added in this workspace\n </div>\n <div className=\"mt-2 space-y-2\">\n {workspaceAgents.map((agent) => (\n <div\n key={agent.id}\n className=\"flex items-start justify-between gap-3 rounded-xl border bg-muted/30 px-4 py-3\"\n >\n <div className=\"min-w-0\">\n <div className=\"text-sm font-medium text-foreground\">\n {agent.name}\n </div>\n {agent.description ? (\n <div className=\"mt-1 text-xs text-muted-foreground\">\n {agent.description}\n </div>\n ) : null}\n <div className=\"mt-1 text-xs text-muted-foreground\">\n <a\n href={agent.url}\n target=\"_blank\"\n rel=\"noreferrer\"\n className=\"inline-flex items-center gap-1 hover:text-foreground\"\n >\n {agent.url}\n <IconExternalLink className=\"h-3 w-3\" />\n </a>\n </div>\n </div>\n </div>\n ))}\n {customAgents.map((agent) => (\n <div\n key={agent.id}\n className=\"flex items-start justify-between gap-3 rounded-xl border bg-muted/30 px-4 py-3\"\n >\n <div className=\"min-w-0\">\n <div className=\"text-sm font-medium text-foreground\">\n {agent.name}\n </div>\n {agent.description ? (\n <div className=\"mt-1 text-xs text-muted-foreground\">\n {agent.description}\n </div>\n ) : null}\n <div className=\"mt-1 flex items-center gap-2 text-xs text-muted-foreground\">\n <a\n href={agent.url}\n target=\"_blank\"\n rel=\"noreferrer\"\n className=\"inline-flex items-center gap-1 hover:text-foreground\"\n >\n {agent.url}\n <IconExternalLink className=\"h-3 w-3\" />\n </a>\n <span>·</span>\n <span>{agent.scope || \"shared\"}</span>\n </div>\n </div>\n {canManageSharedAgents && (\n <AlertDialog>\n <AlertDialogTrigger asChild>\n <Button variant=\"ghost\" size=\"icon\">\n <IconTrash className=\"h-4 w-4\" />\n </Button>\n </AlertDialogTrigger>\n <AlertDialogContent>\n <AlertDialogHeader>\n <AlertDialogTitle>\n Remove this agent?\n </AlertDialogTitle>\n <AlertDialogDescription>\n “{agent.name}” will be removed from the workspace.\n Any jobs or chats that delegate to it will stop\n working.\n </AlertDialogDescription>\n </AlertDialogHeader>\n <AlertDialogFooter>\n <AlertDialogCancel>Cancel</AlertDialogCancel>\n <AlertDialogAction\n onClick={() => handleDelete(agent.resourceId)}\n >\n Remove\n </AlertDialogAction>\n </AlertDialogFooter>\n </AlertDialogContent>\n </AlertDialog>\n )}\n </div>\n ))}\n {workspaceAgents.length === 0 && customAgents.length === 0 && (\n <div className=\"rounded-xl border border-dashed px-4 py-6 text-sm text-muted-foreground\">\n No extra agents added yet.\n </div>\n )}\n </div>\n </div>\n </div>\n\n <div className=\"rounded-xl border bg-muted/20 p-4\">\n <div className=\"text-sm font-medium text-foreground\">\n Add external agent\n </div>\n {canManageSharedAgents ? (\n <p className=\"mt-1 text-xs leading-relaxed text-muted-foreground\">\n Add another A2A-compatible app by saving its agent endpoint here.\n </p>\n ) : !orgLoading ? (\n <p className=\"mt-1 text-xs leading-relaxed text-muted-foreground\">\n Only workspace owners and admins can add shared agents.\n </p>\n ) : null}\n <form\n className={`mt-4 space-y-3 ${canManageSharedAgents ? \"\" : \"hidden\"}`}\n onSubmit={handleAdd}\n noValidate\n >\n <div className=\"space-y-1.5\">\n <Input\n ref={nameRef}\n value={name}\n onChange={(event) => {\n setName(event.target.value);\n setErrors((current) => ({ ...current, name: undefined }));\n }}\n placeholder=\"Name\"\n aria-invalid={Boolean(errors.name)}\n aria-describedby={\n errors.name ? \"external-agent-name-error\" : undefined\n }\n />\n {errors.name ? (\n <p\n id=\"external-agent-name-error\"\n className=\"text-xs font-medium text-destructive\"\n >\n {errors.name}\n </p>\n ) : null}\n </div>\n <div className=\"space-y-1.5\">\n <Input\n value={url}\n onChange={(event) => {\n setUrl(event.target.value);\n setErrors((current) => ({ ...current, url: undefined }));\n }}\n placeholder=\"https://app.example.com\"\n aria-invalid={Boolean(errors.url)}\n aria-describedby={\n errors.url ? \"external-agent-url-error\" : undefined\n }\n />\n {errors.url ? (\n <p\n id=\"external-agent-url-error\"\n className=\"text-xs font-medium text-destructive\"\n >\n {errors.url}\n </p>\n ) : null}\n </div>\n <Input\n value={description}\n onChange={(event) => setDescription(event.target.value)}\n placeholder=\"Description (optional)\"\n />\n {errors.form ? (\n <p className=\"text-xs font-medium text-destructive\">\n {errors.form}\n </p>\n ) : null}\n <Button\n type=\"submit\"\n className=\"w-full\"\n disabled={saving || !canManageSharedAgents}\n >\n {saving ? \"Saving...\" : \"Add agent\"}\n </Button>\n </form>\n </div>\n </div>\n </section>\n );\n}\n"]}
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@agent-native/dispatch",
|
|
3
|
-
"version": "0.24.
|
|
3
|
+
"version": "0.24.3",
|
|
4
4
|
"description": "Dispatch — workspace control plane for agent-native apps. Vault, integrations, destinations, scheduled jobs, and cross-app delegation, shipped as a single drop-in package.",
|
|
5
5
|
"homepage": "https://github.com/BuilderIO/agent-native#readme",
|
|
6
6
|
"bugs": {
|
|
@@ -99,7 +99,7 @@
|
|
|
99
99
|
"typescript-7": "npm:typescript@^7.0.2",
|
|
100
100
|
"vite": "8.1.0",
|
|
101
101
|
"vitest": "^4.1.5",
|
|
102
|
-
"@agent-native/core": "0.153.
|
|
102
|
+
"@agent-native/core": "0.153.4"
|
|
103
103
|
},
|
|
104
104
|
"peerDependencies": {
|
|
105
105
|
"@agent-native/core": ">=0.8.0",
|
|
@@ -1,4 +1,5 @@
|
|
|
1
1
|
import { agentNativePath } from "@agent-native/core/client/api-path";
|
|
2
|
+
import { useOrgRole } from "@agent-native/core/client/org";
|
|
2
3
|
import { IconExternalLink, IconTrash } from "@tabler/icons-react";
|
|
3
4
|
import { useRef, useState, type FormEvent } from "react";
|
|
4
5
|
|
|
@@ -77,6 +78,11 @@ export function AgentsPanel({
|
|
|
77
78
|
agents: ConnectedAgent[];
|
|
78
79
|
onRefresh: () => void;
|
|
79
80
|
}) {
|
|
81
|
+
const { org, isLoading: orgLoading, error: orgError } = useOrgRole();
|
|
82
|
+
const canManageSharedAgents =
|
|
83
|
+
!orgLoading &&
|
|
84
|
+
!orgError &&
|
|
85
|
+
(!org?.orgId || org.role === "owner" || org.role === "admin");
|
|
80
86
|
const [name, setName] = useState("");
|
|
81
87
|
const [url, setUrl] = useState("");
|
|
82
88
|
const [description, setDescription] = useState("");
|
|
@@ -249,30 +255,35 @@ export function AgentsPanel({
|
|
|
249
255
|
<span>{agent.scope || "shared"}</span>
|
|
250
256
|
</div>
|
|
251
257
|
</div>
|
|
252
|
-
|
|
253
|
-
<
|
|
254
|
-
<
|
|
255
|
-
<
|
|
256
|
-
|
|
257
|
-
|
|
258
|
-
|
|
259
|
-
<
|
|
260
|
-
<
|
|
261
|
-
|
|
262
|
-
|
|
263
|
-
|
|
264
|
-
|
|
265
|
-
|
|
266
|
-
|
|
267
|
-
|
|
268
|
-
|
|
269
|
-
|
|
270
|
-
>
|
|
271
|
-
|
|
272
|
-
|
|
273
|
-
|
|
274
|
-
|
|
275
|
-
|
|
258
|
+
{canManageSharedAgents && (
|
|
259
|
+
<AlertDialog>
|
|
260
|
+
<AlertDialogTrigger asChild>
|
|
261
|
+
<Button variant="ghost" size="icon">
|
|
262
|
+
<IconTrash className="h-4 w-4" />
|
|
263
|
+
</Button>
|
|
264
|
+
</AlertDialogTrigger>
|
|
265
|
+
<AlertDialogContent>
|
|
266
|
+
<AlertDialogHeader>
|
|
267
|
+
<AlertDialogTitle>
|
|
268
|
+
Remove this agent?
|
|
269
|
+
</AlertDialogTitle>
|
|
270
|
+
<AlertDialogDescription>
|
|
271
|
+
“{agent.name}” will be removed from the workspace.
|
|
272
|
+
Any jobs or chats that delegate to it will stop
|
|
273
|
+
working.
|
|
274
|
+
</AlertDialogDescription>
|
|
275
|
+
</AlertDialogHeader>
|
|
276
|
+
<AlertDialogFooter>
|
|
277
|
+
<AlertDialogCancel>Cancel</AlertDialogCancel>
|
|
278
|
+
<AlertDialogAction
|
|
279
|
+
onClick={() => handleDelete(agent.resourceId)}
|
|
280
|
+
>
|
|
281
|
+
Remove
|
|
282
|
+
</AlertDialogAction>
|
|
283
|
+
</AlertDialogFooter>
|
|
284
|
+
</AlertDialogContent>
|
|
285
|
+
</AlertDialog>
|
|
286
|
+
)}
|
|
276
287
|
</div>
|
|
277
288
|
))}
|
|
278
289
|
{workspaceAgents.length === 0 && customAgents.length === 0 && (
|
|
@@ -288,10 +299,20 @@ export function AgentsPanel({
|
|
|
288
299
|
<div className="text-sm font-medium text-foreground">
|
|
289
300
|
Add external agent
|
|
290
301
|
</div>
|
|
291
|
-
|
|
292
|
-
|
|
293
|
-
|
|
294
|
-
|
|
302
|
+
{canManageSharedAgents ? (
|
|
303
|
+
<p className="mt-1 text-xs leading-relaxed text-muted-foreground">
|
|
304
|
+
Add another A2A-compatible app by saving its agent endpoint here.
|
|
305
|
+
</p>
|
|
306
|
+
) : !orgLoading ? (
|
|
307
|
+
<p className="mt-1 text-xs leading-relaxed text-muted-foreground">
|
|
308
|
+
Only workspace owners and admins can add shared agents.
|
|
309
|
+
</p>
|
|
310
|
+
) : null}
|
|
311
|
+
<form
|
|
312
|
+
className={`mt-4 space-y-3 ${canManageSharedAgents ? "" : "hidden"}`}
|
|
313
|
+
onSubmit={handleAdd}
|
|
314
|
+
noValidate
|
|
315
|
+
>
|
|
295
316
|
<div className="space-y-1.5">
|
|
296
317
|
<Input
|
|
297
318
|
ref={nameRef}
|
|
@@ -347,7 +368,11 @@ export function AgentsPanel({
|
|
|
347
368
|
{errors.form}
|
|
348
369
|
</p>
|
|
349
370
|
) : null}
|
|
350
|
-
<Button
|
|
371
|
+
<Button
|
|
372
|
+
type="submit"
|
|
373
|
+
className="w-full"
|
|
374
|
+
disabled={saving || !canManageSharedAgents}
|
|
375
|
+
>
|
|
351
376
|
{saving ? "Saving..." : "Add agent"}
|
|
352
377
|
</Button>
|
|
353
378
|
</form>
|