@agent-native/dispatch 0.2.2 → 0.2.4

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/README.md CHANGED
@@ -18,9 +18,9 @@ The agent and the UI are equal citizens of the same system. Every action works b
18
18
  - **Any database, any host** — Any SQL database Drizzle supports. Any hosting target Nitro supports. No lock-in.
19
19
  - **Any AI agent** — Claude Code, Codex, Gemini CLI, OpenCode, or Builder.io. Use whichever agent you prefer.
20
20
 
21
- ## Cloneable SaaS Templates
21
+ ## Templates
22
22
 
23
- Start from a complete, production-grade SaaS app. Each one replaces tools you're paying for except you own everything and can customize it however you want. Not demos; products.
23
+ Start from a complete, production-grade SaaS app — cloneable, not scaffolded. Each one replaces tools you're paying for, except you own everything and can customize it however you want. Not demos; products.
24
24
 
25
25
  <table>
26
26
  <tr>
@@ -145,7 +145,7 @@ Generate forms from a prompt, branch logic with the agent, and own every respons
145
145
  </tr>
146
146
  </table>
147
147
 
148
- Every template is cloneable SaaS — fork it, customize it with the agent, own it. Try them with example data before connecting your own sources.
148
+ Every template is a complete cloneable SaaS — fork it, customize it with the agent, own it. Try them with example data before connecting your own sources.
149
149
 
150
150
  ## Quick Start
151
151
 
@@ -184,7 +184,7 @@ my-platform/
184
184
  Add another app later:
185
185
 
186
186
  ```bash
187
- agent-native add-app notes --template content
187
+ npx @agent-native/core add-app notes --template content
188
188
  ```
189
189
 
190
190
  Deploy every app behind one origin:
@@ -1 +1 @@
1
- {"version":3,"file":"agents-panel.d.ts","sourceRoot":"","sources":["../../src/components/agents-panel.tsx"],"names":[],"mappings":"AAiBA,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;AAED,wBAAgB,WAAW,CAAC,EAC1B,MAAM,EACN,SAAS,GACV,EAAE;IACD,MAAM,EAAE,cAAc,EAAE,CAAC;IACzB,SAAS,EAAE,MAAM,IAAI,CAAC;CACvB,2CAkOA"}
1
+ {"version":3,"file":"agents-panel.d.ts","sourceRoot":"","sources":["../../src/components/agents-panel.tsx"],"names":[],"mappings":"AAiBA,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,2CAuRA"}
@@ -5,21 +5,66 @@ import { Input } from "../components/ui/input.js";
5
5
  import { AlertDialog, AlertDialogAction, AlertDialogCancel, AlertDialogContent, AlertDialogDescription, AlertDialogFooter, AlertDialogHeader, AlertDialogTitle, AlertDialogTrigger, } from "../components/ui/alert-dialog.js";
6
6
  import { IconExternalLink, IconTrash } from "@tabler/icons-react";
7
7
  import { agentNativePath } from "@agent-native/core/client";
8
+ function slugifyAgentName(value) {
9
+ return value
10
+ .trim()
11
+ .toLowerCase()
12
+ .replace(/[^a-z0-9]+/g, "-")
13
+ .replace(/^-+|-+$/g, "");
14
+ }
15
+ function validateAgentForm(name, url) {
16
+ const errors = {};
17
+ const trimmedName = name.trim();
18
+ const trimmedUrl = url.trim();
19
+ if (!trimmedName) {
20
+ errors.name = "Agent name is required.";
21
+ }
22
+ else if (!slugifyAgentName(trimmedName)) {
23
+ errors.name = "Agent name must include at least one letter or number.";
24
+ }
25
+ if (!trimmedUrl) {
26
+ errors.url = "Agent endpoint URL is required.";
27
+ }
28
+ else {
29
+ try {
30
+ const parsed = new URL(trimmedUrl);
31
+ if (parsed.protocol !== "https:" && parsed.protocol !== "http:") {
32
+ errors.url = "Use an http:// or https:// endpoint URL.";
33
+ }
34
+ else if (!parsed.hostname) {
35
+ errors.url = "Enter a complete endpoint URL with a host.";
36
+ }
37
+ else if (parsed.username || parsed.password) {
38
+ errors.url = "Do not include credentials in the endpoint URL.";
39
+ }
40
+ }
41
+ catch {
42
+ errors.url =
43
+ "Enter a valid endpoint URL, such as https://app.example.com.";
44
+ }
45
+ }
46
+ return errors;
47
+ }
8
48
  export function AgentsPanel({ agents, onRefresh, }) {
9
49
  const [name, setName] = useState("");
10
50
  const [url, setUrl] = useState("");
11
51
  const [description, setDescription] = useState("");
12
52
  const [saving, setSaving] = useState(false);
53
+ const [errors, setErrors] = useState({});
13
54
  const nameRef = useRef(null);
14
55
  const customAgents = agents.filter((agent) => agent.source === "custom");
15
56
  const workspaceAgents = agents.filter((agent) => agent.source === "workspace");
16
57
  const builtinAgents = agents.filter((agent) => agent.source === "builtin");
17
- const handleAdd = async () => {
58
+ const handleAdd = async (event) => {
59
+ event?.preventDefault();
18
60
  const trimmedName = name.trim();
19
61
  const trimmedUrl = url.trim();
20
- if (!trimmedName || !trimmedUrl)
62
+ const nextErrors = validateAgentForm(trimmedName, trimmedUrl);
63
+ if (Object.keys(nextErrors).length > 0) {
64
+ setErrors(nextErrors);
21
65
  return;
22
- const id = trimmedName.toLowerCase().replace(/[^a-z0-9-]/g, "-");
66
+ }
67
+ const id = slugifyAgentName(trimmedName);
23
68
  const agentJson = JSON.stringify({
24
69
  id,
25
70
  name: trimmedName,
@@ -42,9 +87,22 @@ export function AgentsPanel({ agents, onRefresh, }) {
42
87
  setName("");
43
88
  setUrl("");
44
89
  setDescription("");
90
+ setErrors({});
45
91
  onRefresh();
46
92
  nameRef.current?.focus();
47
93
  }
94
+ else {
95
+ setErrors({
96
+ form: `Could not add agent. Request failed with ${res.status}.`,
97
+ });
98
+ }
99
+ }
100
+ catch (error) {
101
+ setErrors({
102
+ form: error instanceof Error
103
+ ? error.message
104
+ : "Could not add agent. Please try again.",
105
+ });
48
106
  }
49
107
  finally {
50
108
  setSaving(false);
@@ -59,6 +117,12 @@ export function AgentsPanel({ agents, onRefresh, }) {
59
117
  if (res.ok)
60
118
  onRefresh();
61
119
  };
62
- return (_jsx("section", { className: "rounded-2xl border 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("div", { className: "mt-4 space-y-3", children: [_jsx(Input, { ref: nameRef, value: name, onChange: (event) => setName(event.target.value), placeholder: "Name" }), _jsx(Input, { value: url, onChange: (event) => setUrl(event.target.value), placeholder: "https://app.example.com" }), _jsx(Input, { value: description, onChange: (event) => setDescription(event.target.value), placeholder: "Description (optional)" }), _jsx(Button, { className: "w-full", onClick: handleAdd, disabled: !name.trim() || !url.trim() || saving, children: saving ? "Saving..." : "Add agent" })] })] })] }) }));
120
+ return (_jsx("section", { className: "rounded-2xl border 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: "mt-4 space-y-3", onSubmit: handleAdd, noValidate: true, children: [_jsxs("div", { className: "space-y-1.5", children: [_jsx(Input, { ref: nameRef, value: name, onChange: (event) => {
121
+ setName(event.target.value);
122
+ setErrors((current) => ({ ...current, name: undefined }));
123
+ }, 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
+ setUrl(event.target.value);
125
+ 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" })] })] })] }) }));
63
127
  }
64
128
  //# sourceMappingURL=agents-panel.js.map
@@ -1 +1 @@
1
- {"version":3,"file":"agents-panel.js","sourceRoot":"","sources":["../../src/components/agents-panel.tsx"],"names":[],"mappings":";AAAA,OAAO,EAAE,MAAM,EAAE,QAAQ,EAAE,MAAM,OAAO,CAAC;AACzC,OAAO,EAAE,MAAM,EAAE,MAAM,wBAAwB,CAAC;AAChD,OAAO,EAAE,KAAK,EAAE,MAAM,uBAAuB,CAAC;AAC9C,OAAO,EACL,WAAW,EACX,iBAAiB,EACjB,iBAAiB,EACjB,kBAAkB,EAClB,sBAAsB,EACtB,iBAAiB,EACjB,iBAAiB,EACjB,gBAAgB,EAChB,kBAAkB,GACnB,MAAM,8BAA8B,CAAC;AACtC,OAAO,EAAE,gBAAgB,EAAE,SAAS,EAAE,MAAM,qBAAqB,CAAC;AAClE,OAAO,EAAE,eAAe,EAAE,MAAM,2BAA2B,CAAC;AAc5D,MAAM,UAAU,WAAW,CAAC,EAC1B,MAAM,EACN,SAAS,GAIV;IACC,MAAM,CAAC,IAAI,EAAE,OAAO,CAAC,GAAG,QAAQ,CAAC,EAAE,CAAC,CAAC;IACrC,MAAM,CAAC,GAAG,EAAE,MAAM,CAAC,GAAG,QAAQ,CAAC,EAAE,CAAC,CAAC;IACnC,MAAM,CAAC,WAAW,EAAE,cAAc,CAAC,GAAG,QAAQ,CAAC,EAAE,CAAC,CAAC;IACnD,MAAM,CAAC,MAAM,EAAE,SAAS,CAAC,GAAG,QAAQ,CAAC,KAAK,CAAC,CAAC;IAC5C,MAAM,OAAO,GAAG,MAAM,CAAmB,IAAI,CAAC,CAAC;IAE/C,MAAM,YAAY,GAAG,MAAM,CAAC,MAAM,CAAC,CAAC,KAAK,EAAE,EAAE,CAAC,KAAK,CAAC,MAAM,KAAK,QAAQ,CAAC,CAAC;IACzE,MAAM,eAAe,GAAG,MAAM,CAAC,MAAM,CACnC,CAAC,KAAK,EAAE,EAAE,CAAC,KAAK,CAAC,MAAM,KAAK,WAAW,CACxC,CAAC;IACF,MAAM,aAAa,GAAG,MAAM,CAAC,MAAM,CAAC,CAAC,KAAK,EAAE,EAAE,CAAC,KAAK,CAAC,MAAM,KAAK,SAAS,CAAC,CAAC;IAE3E,MAAM,SAAS,GAAG,KAAK,IAAI,EAAE;QAC3B,MAAM,WAAW,GAAG,IAAI,CAAC,IAAI,EAAE,CAAC;QAChC,MAAM,UAAU,GAAG,GAAG,CAAC,IAAI,EAAE,CAAC;QAC9B,IAAI,CAAC,WAAW,IAAI,CAAC,UAAU;YAAE,OAAO;QAExC,MAAM,EAAE,GAAG,WAAW,CAAC,WAAW,EAAE,CAAC,OAAO,CAAC,aAAa,EAAE,GAAG,CAAC,CAAC;QACjE,MAAM,SAAS,GAAG,IAAI,CAAC,SAAS,CAC9B;YACE,EAAE;YACF,IAAI,EAAE,WAAW;YACjB,WAAW,EAAE,WAAW,CAAC,IAAI,EAAE,IAAI,SAAS;YAC5C,GAAG,EAAE,UAAU;YACf,KAAK,EAAE,SAAS;SACjB,EACD,IAAI,EACJ,CAAC,CACF,CAAC;QAEF,SAAS,CAAC,IAAI,CAAC,CAAC;QAChB,IAAI,CAAC;YACH,MAAM,GAAG,GAAG,MAAM,KAAK,CAAC,eAAe,CAAC,0BAA0B,CAAC,EAAE;gBACnE,MAAM,EAAE,MAAM;gBACd,OAAO,EAAE,EAAE,cAAc,EAAE,kBAAkB,EAAE;gBAC/C,IAAI,EAAE,IAAI,CAAC,SAAS,CAAC;oBACnB,IAAI,EAAE,iBAAiB,EAAE,OAAO;oBAChC,OAAO,EAAE,SAAS;oBAClB,MAAM,EAAE,IAAI;iBACb,CAAC;aACH,CAAC,CAAC;YACH,IAAI,GAAG,CAAC,EAAE,EAAE,CAAC;gBACX,OAAO,CAAC,EAAE,CAAC,CAAC;gBACZ,MAAM,CAAC,EAAE,CAAC,CAAC;gBACX,cAAc,CAAC,EAAE,CAAC,CAAC;gBACnB,SAAS,EAAE,CAAC;gBACZ,OAAO,CAAC,OAAO,EAAE,KAAK,EAAE,CAAC;YAC3B,CAAC;QACH,CAAC;gBAAS,CAAC;YACT,SAAS,CAAC,KAAK,CAAC,CAAC;QACnB,CAAC;IACH,CAAC,CAAC;IAEF,MAAM,YAAY,GAAG,KAAK,EAAE,UAAmB,EAAE,EAAE;QACjD,IAAI,CAAC,UAAU;YAAE,OAAO;QACxB,MAAM,GAAG,GAAG,MAAM,KAAK,CACrB,eAAe,CAAC,4BAA4B,UAAU,EAAE,CAAC,EACzD;YACE,MAAM,EAAE,QAAQ;SACjB,CACF,CAAC;QACF,IAAI,GAAG,CAAC,EAAE;YAAE,SAAS,EAAE,CAAC;IAC1B,CAAC,CAAC;IAEF,OAAO,CACL,kBAAS,SAAS,EAAC,gCAAgC,YACjD,eAAK,SAAS,EAAC,+CAA+C,aAC5D,eAAK,SAAS,EAAC,WAAW,aACxB,0BACE,cAAK,SAAS,EAAC,qCAAqC,qCAE9C,EACN,eAAK,SAAS,EAAC,2BAA2B,aACvC,aAAa,CAAC,GAAG,CAAC,CAAC,KAAK,EAAE,EAAE,CAAC,CAC5B,eAEE,SAAS,EAAC,8FAA8F,aAExG,eACE,SAAS,EAAC,sBAAsB,EAChC,KAAK,EAAE,EAAE,eAAe,EAAE,KAAK,CAAC,KAAK,EAAE,GACvC,EACF,yBAAO,KAAK,CAAC,IAAI,GAAQ,KAPpB,KAAK,CAAC,EAAE,CAQT,CACP,CAAC,EACD,aAAa,CAAC,MAAM,KAAK,CAAC,IAAI,CAC7B,cAAK,SAAS,EAAC,yEAAyE,4CAElF,CACP,IACG,IACF,EAEN,0BACE,cAAK,SAAS,EAAC,qCAAqC,wCAE9C,EACN,eAAK,SAAS,EAAC,gBAAgB,aAC5B,eAAe,CAAC,GAAG,CAAC,CAAC,KAAK,EAAE,EAAE,CAAC,CAC9B,cAEE,SAAS,EAAC,gFAAgF,YAE1F,eAAK,SAAS,EAAC,SAAS,aACtB,cAAK,SAAS,EAAC,qCAAqC,YACjD,KAAK,CAAC,IAAI,GACP,EACL,KAAK,CAAC,WAAW,CAAC,CAAC,CAAC,CACnB,cAAK,SAAS,EAAC,oCAAoC,YAChD,KAAK,CAAC,WAAW,GACd,CACP,CAAC,CAAC,CAAC,IAAI,EACR,cAAK,SAAS,EAAC,oCAAoC,YACjD,aACE,IAAI,EAAE,KAAK,CAAC,GAAG,EACf,MAAM,EAAC,QAAQ,EACf,GAAG,EAAC,YAAY,EAChB,SAAS,EAAC,sDAAsD,aAE/D,KAAK,CAAC,GAAG,EACV,KAAC,gBAAgB,IAAC,SAAS,EAAC,SAAS,GAAG,IACtC,GACA,IACF,IAvBD,KAAK,CAAC,EAAE,CAwBT,CACP,CAAC,EACD,YAAY,CAAC,GAAG,CAAC,CAAC,KAAK,EAAE,EAAE,CAAC,CAC3B,eAEE,SAAS,EAAC,gFAAgF,aAE1F,eAAK,SAAS,EAAC,SAAS,aACtB,cAAK,SAAS,EAAC,qCAAqC,YACjD,KAAK,CAAC,IAAI,GACP,EACL,KAAK,CAAC,WAAW,CAAC,CAAC,CAAC,CACnB,cAAK,SAAS,EAAC,oCAAoC,YAChD,KAAK,CAAC,WAAW,GACd,CACP,CAAC,CAAC,CAAC,IAAI,EACR,eAAK,SAAS,EAAC,4DAA4D,aACzE,aACE,IAAI,EAAE,KAAK,CAAC,GAAG,EACf,MAAM,EAAC,QAAQ,EACf,GAAG,EAAC,YAAY,EAChB,SAAS,EAAC,sDAAsD,aAE/D,KAAK,CAAC,GAAG,EACV,KAAC,gBAAgB,IAAC,SAAS,EAAC,SAAS,GAAG,IACtC,EACJ,oCAAc,EACd,yBAAO,KAAK,CAAC,KAAK,IAAI,QAAQ,GAAQ,IAClC,IACF,EACN,MAAC,WAAW,eACV,KAAC,kBAAkB,IAAC,OAAO,kBACzB,KAAC,MAAM,IAAC,OAAO,EAAC,OAAO,EAAC,IAAI,EAAC,MAAM,YACjC,KAAC,SAAS,IAAC,SAAS,EAAC,SAAS,GAAG,GAC1B,GACU,EACrB,MAAC,kBAAkB,eACjB,MAAC,iBAAiB,eAChB,KAAC,gBAAgB,qCAAsC,EACvD,MAAC,sBAAsB,yBACnB,KAAK,CAAC,IAAI,2GAEW,IACP,EACpB,MAAC,iBAAiB,eAChB,KAAC,iBAAiB,yBAA2B,EAC7C,KAAC,iBAAiB,IAChB,OAAO,EAAE,GAAG,EAAE,CAAC,YAAY,CAAC,KAAK,CAAC,UAAU,CAAC,uBAG3B,IACF,IACD,IACT,KAjDT,KAAK,CAAC,EAAE,CAkDT,CACP,CAAC,EACD,eAAe,CAAC,MAAM,KAAK,CAAC,IAAI,YAAY,CAAC,MAAM,KAAK,CAAC,IAAI,CAC5D,cAAK,SAAS,EAAC,yEAAyE,2CAElF,CACP,IACG,IACF,IACF,EAEN,eAAK,SAAS,EAAC,mCAAmC,aAChD,cAAK,SAAS,EAAC,qCAAqC,mCAE9C,EACN,YAAG,SAAS,EAAC,oDAAoD,kFAE7D,EACJ,eAAK,SAAS,EAAC,gBAAgB,aAC7B,KAAC,KAAK,IACJ,GAAG,EAAE,OAAO,EACZ,KAAK,EAAE,IAAI,EACX,QAAQ,EAAE,CAAC,KAAK,EAAE,EAAE,CAAC,OAAO,CAAC,KAAK,CAAC,MAAM,CAAC,KAAK,CAAC,EAChD,WAAW,EAAC,MAAM,GAClB,EACF,KAAC,KAAK,IACJ,KAAK,EAAE,GAAG,EACV,QAAQ,EAAE,CAAC,KAAK,EAAE,EAAE,CAAC,MAAM,CAAC,KAAK,CAAC,MAAM,CAAC,KAAK,CAAC,EAC/C,WAAW,EAAC,yBAAyB,GACrC,EACF,KAAC,KAAK,IACJ,KAAK,EAAE,WAAW,EAClB,QAAQ,EAAE,CAAC,KAAK,EAAE,EAAE,CAAC,cAAc,CAAC,KAAK,CAAC,MAAM,CAAC,KAAK,CAAC,EACvD,WAAW,EAAC,wBAAwB,GACpC,EACF,KAAC,MAAM,IACL,SAAS,EAAC,QAAQ,EAClB,OAAO,EAAE,SAAS,EAClB,QAAQ,EAAE,CAAC,IAAI,CAAC,IAAI,EAAE,IAAI,CAAC,GAAG,CAAC,IAAI,EAAE,IAAI,MAAM,YAE9C,MAAM,CAAC,CAAC,CAAC,WAAW,CAAC,CAAC,CAAC,WAAW,GAC5B,IACL,IACF,IACF,GACE,CACX,CAAC;AACJ,CAAC","sourcesContent":["import { useRef, useState } from \"react\";\nimport { Button } from \"@/components/ui/button\";\nimport { Input } from \"@/components/ui/input\";\nimport {\n AlertDialog,\n AlertDialogAction,\n AlertDialogCancel,\n AlertDialogContent,\n AlertDialogDescription,\n AlertDialogFooter,\n AlertDialogHeader,\n AlertDialogTitle,\n AlertDialogTrigger,\n} from \"@/components/ui/alert-dialog\";\nimport { IconExternalLink, IconTrash } from \"@tabler/icons-react\";\nimport { agentNativePath } from \"@agent-native/core/client\";\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\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 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 () => {\n const trimmedName = name.trim();\n const trimmedUrl = url.trim();\n if (!trimmedName || !trimmedUrl) return;\n\n const id = trimmedName.toLowerCase().replace(/[^a-z0-9-]/g, \"-\");\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 onRefresh();\n nameRef.current?.focus();\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 border 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 <div className=\"mt-4 space-y-3\">\n <Input\n ref={nameRef}\n value={name}\n onChange={(event) => setName(event.target.value)}\n placeholder=\"Name\"\n />\n <Input\n value={url}\n onChange={(event) => setUrl(event.target.value)}\n placeholder=\"https://app.example.com\"\n />\n <Input\n value={description}\n onChange={(event) => setDescription(event.target.value)}\n placeholder=\"Description (optional)\"\n />\n <Button\n className=\"w-full\"\n onClick={handleAdd}\n disabled={!name.trim() || !url.trim() || saving}\n >\n {saving ? \"Saving...\" : \"Add agent\"}\n </Button>\n </div>\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 { useRef, useState, type FormEvent } from \"react\";\nimport { Button } from \"@/components/ui/button\";\nimport { Input } from \"@/components/ui/input\";\nimport {\n AlertDialog,\n AlertDialogAction,\n AlertDialogCancel,\n AlertDialogContent,\n AlertDialogDescription,\n AlertDialogFooter,\n AlertDialogHeader,\n AlertDialogTitle,\n AlertDialogTrigger,\n} from \"@/components/ui/alert-dialog\";\nimport { IconExternalLink, IconTrash } from \"@tabler/icons-react\";\nimport { agentNativePath } from \"@agent-native/core/client\";\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 border 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"]}
@@ -29,6 +29,6 @@ export function Header({ onOpenMobile, showAgentToggle = true, }) {
29
29
  const location = useLocation();
30
30
  const title = useHeaderTitle();
31
31
  const actions = useHeaderActions();
32
- return (_jsxs("header", { className: "flex h-12 shrink-0 items-center gap-3 border-b border-border bg-background px-4 lg:px-6", children: [onOpenMobile ? (_jsx(Button, { variant: "ghost", size: "icon", className: "h-8 w-8 2xl:hidden cursor-pointer", onClick: onOpenMobile, "aria-label": "Open navigation", children: _jsx(IconLayoutSidebar, {}) })) : null, _jsx("div", { className: "flex items-center gap-3 flex-1 min-w-0", children: title ?? (_jsx("h1", { className: "text-lg font-semibold tracking-tight truncate", children: resolveTitle(location.pathname) })) }), _jsxs("div", { className: "flex items-center gap-2 shrink-0", children: [actions, showAgentToggle ? (_jsx(AgentToggleButton, { className: "h-8 w-8 rounded-md hover:bg-accent" })) : null] })] }));
32
+ return (_jsxs("header", { className: "flex h-12 shrink-0 items-center gap-3 border-b border-border bg-background px-4 lg:px-6", children: [onOpenMobile ? (_jsx(Button, { variant: "ghost", size: "icon", className: "h-8 w-8 lg:hidden cursor-pointer", onClick: onOpenMobile, "aria-label": "Open navigation", children: _jsx(IconLayoutSidebar, {}) })) : null, _jsx("div", { className: "flex items-center gap-3 flex-1 min-w-0", children: title ?? (_jsx("h1", { className: "text-lg font-semibold tracking-tight truncate", children: resolveTitle(location.pathname) })) }), _jsxs("div", { className: "flex items-center gap-2 shrink-0", children: [actions, showAgentToggle ? (_jsx(AgentToggleButton, { className: "h-8 w-8 rounded-md hover:bg-accent" })) : null] })] }));
33
33
  }
34
34
  //# sourceMappingURL=Header.js.map
@@ -1 +1 @@
1
- {"version":3,"file":"Header.js","sourceRoot":"","sources":["../../../src/components/layout/Header.tsx"],"names":[],"mappings":";AAAA,OAAO,EAAE,WAAW,EAAE,MAAM,cAAc,CAAC;AAC3C,OAAO,EAAE,cAAc,EAAE,gBAAgB,EAAE,MAAM,iBAAiB,CAAC;AACnE,OAAO,EAAE,iBAAiB,EAAE,MAAM,2BAA2B,CAAC;AAC9D,OAAO,EAAE,MAAM,EAAE,MAAM,wBAAwB,CAAC;AAChD,OAAO,EAAE,iBAAiB,EAAE,MAAM,qBAAqB,CAAC;AAExD,MAAM,UAAU,GAA2B;IACzC,GAAG,EAAE,UAAU;IACf,WAAW,EAAE,UAAU;IACvB,QAAQ,EAAE,OAAO;IACjB,eAAe,EAAE,cAAc;IAC/B,YAAY,EAAE,WAAW;IACzB,YAAY,EAAE,WAAW;IACzB,SAAS,EAAE,QAAQ;IACnB,eAAe,EAAE,cAAc;IAC/B,aAAa,EAAE,YAAY;IAC3B,YAAY,EAAE,WAAW;IACzB,QAAQ,EAAE,OAAO;IACjB,OAAO,EAAE,MAAM;CAChB,CAAC;AAEF,SAAS,YAAY,CAAC,QAAgB;IACpC,IAAI,UAAU,CAAC,QAAQ,CAAC;QAAE,OAAO,UAAU,CAAC,QAAQ,CAAC,CAAC;IAEtD,IAAI,QAAQ,CAAC,UAAU,CAAC,aAAa,CAAC;QAAE,OAAO,YAAY,CAAC;IAE5D,OAAO,UAAU,CAAC;AACpB,CAAC;AAED,MAAM,UAAU,MAAM,CAAC,EACrB,YAAY,EACZ,eAAe,GAAG,IAAI,GAIvB;IACC,MAAM,QAAQ,GAAG,WAAW,EAAE,CAAC;IAC/B,MAAM,KAAK,GAAG,cAAc,EAAE,CAAC;IAC/B,MAAM,OAAO,GAAG,gBAAgB,EAAE,CAAC;IAEnC,OAAO,CACL,kBAAQ,SAAS,EAAC,yFAAyF,aACxG,YAAY,CAAC,CAAC,CAAC,CACd,KAAC,MAAM,IACL,OAAO,EAAC,OAAO,EACf,IAAI,EAAC,MAAM,EACX,SAAS,EAAC,mCAAmC,EAC7C,OAAO,EAAE,YAAY,gBACV,iBAAiB,YAE5B,KAAC,iBAAiB,KAAG,GACd,CACV,CAAC,CAAC,CAAC,IAAI,EACR,cAAK,SAAS,EAAC,wCAAwC,YACpD,KAAK,IAAI,CACR,aAAI,SAAS,EAAC,+CAA+C,YAC1D,YAAY,CAAC,QAAQ,CAAC,QAAQ,CAAC,GAC7B,CACN,GACG,EACN,eAAK,SAAS,EAAC,kCAAkC,aAC9C,OAAO,EACP,eAAe,CAAC,CAAC,CAAC,CACjB,KAAC,iBAAiB,IAAC,SAAS,EAAC,oCAAoC,GAAG,CACrE,CAAC,CAAC,CAAC,IAAI,IACJ,IACC,CACV,CAAC;AACJ,CAAC","sourcesContent":["import { useLocation } from \"react-router\";\nimport { useHeaderTitle, useHeaderActions } from \"./HeaderActions\";\nimport { AgentToggleButton } from \"@agent-native/core/client\";\nimport { Button } from \"@/components/ui/button\";\nimport { IconLayoutSidebar } from \"@tabler/icons-react\";\n\nconst pageTitles: Record<string, string> = {\n \"/\": \"Overview\",\n \"/overview\": \"Overview\",\n \"/vault\": \"Vault\",\n \"/integrations\": \"Integrations\",\n \"/workspace\": \"Resources\",\n \"/messaging\": \"Messaging\",\n \"/agents\": \"Agents\",\n \"/destinations\": \"Destinations\",\n \"/identities\": \"Identities\",\n \"/approvals\": \"Approvals\",\n \"/audit\": \"Audit\",\n \"/team\": \"Team\",\n};\n\nfunction resolveTitle(pathname: string): string {\n if (pageTitles[pathname]) return pageTitles[pathname];\n\n if (pathname.startsWith(\"/extensions\")) return \"Extensions\";\n\n return \"Dispatch\";\n}\n\nexport function Header({\n onOpenMobile,\n showAgentToggle = true,\n}: {\n onOpenMobile?: () => void;\n showAgentToggle?: boolean;\n}) {\n const location = useLocation();\n const title = useHeaderTitle();\n const actions = useHeaderActions();\n\n return (\n <header className=\"flex h-12 shrink-0 items-center gap-3 border-b border-border bg-background px-4 lg:px-6\">\n {onOpenMobile ? (\n <Button\n variant=\"ghost\"\n size=\"icon\"\n className=\"h-8 w-8 2xl:hidden cursor-pointer\"\n onClick={onOpenMobile}\n aria-label=\"Open navigation\"\n >\n <IconLayoutSidebar />\n </Button>\n ) : null}\n <div className=\"flex items-center gap-3 flex-1 min-w-0\">\n {title ?? (\n <h1 className=\"text-lg font-semibold tracking-tight truncate\">\n {resolveTitle(location.pathname)}\n </h1>\n )}\n </div>\n <div className=\"flex items-center gap-2 shrink-0\">\n {actions}\n {showAgentToggle ? (\n <AgentToggleButton className=\"h-8 w-8 rounded-md hover:bg-accent\" />\n ) : null}\n </div>\n </header>\n );\n}\n"]}
1
+ {"version":3,"file":"Header.js","sourceRoot":"","sources":["../../../src/components/layout/Header.tsx"],"names":[],"mappings":";AAAA,OAAO,EAAE,WAAW,EAAE,MAAM,cAAc,CAAC;AAC3C,OAAO,EAAE,cAAc,EAAE,gBAAgB,EAAE,MAAM,iBAAiB,CAAC;AACnE,OAAO,EAAE,iBAAiB,EAAE,MAAM,2BAA2B,CAAC;AAC9D,OAAO,EAAE,MAAM,EAAE,MAAM,wBAAwB,CAAC;AAChD,OAAO,EAAE,iBAAiB,EAAE,MAAM,qBAAqB,CAAC;AAExD,MAAM,UAAU,GAA2B;IACzC,GAAG,EAAE,UAAU;IACf,WAAW,EAAE,UAAU;IACvB,QAAQ,EAAE,OAAO;IACjB,eAAe,EAAE,cAAc;IAC/B,YAAY,EAAE,WAAW;IACzB,YAAY,EAAE,WAAW;IACzB,SAAS,EAAE,QAAQ;IACnB,eAAe,EAAE,cAAc;IAC/B,aAAa,EAAE,YAAY;IAC3B,YAAY,EAAE,WAAW;IACzB,QAAQ,EAAE,OAAO;IACjB,OAAO,EAAE,MAAM;CAChB,CAAC;AAEF,SAAS,YAAY,CAAC,QAAgB;IACpC,IAAI,UAAU,CAAC,QAAQ,CAAC;QAAE,OAAO,UAAU,CAAC,QAAQ,CAAC,CAAC;IAEtD,IAAI,QAAQ,CAAC,UAAU,CAAC,aAAa,CAAC;QAAE,OAAO,YAAY,CAAC;IAE5D,OAAO,UAAU,CAAC;AACpB,CAAC;AAED,MAAM,UAAU,MAAM,CAAC,EACrB,YAAY,EACZ,eAAe,GAAG,IAAI,GAIvB;IACC,MAAM,QAAQ,GAAG,WAAW,EAAE,CAAC;IAC/B,MAAM,KAAK,GAAG,cAAc,EAAE,CAAC;IAC/B,MAAM,OAAO,GAAG,gBAAgB,EAAE,CAAC;IAEnC,OAAO,CACL,kBAAQ,SAAS,EAAC,yFAAyF,aACxG,YAAY,CAAC,CAAC,CAAC,CACd,KAAC,MAAM,IACL,OAAO,EAAC,OAAO,EACf,IAAI,EAAC,MAAM,EACX,SAAS,EAAC,kCAAkC,EAC5C,OAAO,EAAE,YAAY,gBACV,iBAAiB,YAE5B,KAAC,iBAAiB,KAAG,GACd,CACV,CAAC,CAAC,CAAC,IAAI,EACR,cAAK,SAAS,EAAC,wCAAwC,YACpD,KAAK,IAAI,CACR,aAAI,SAAS,EAAC,+CAA+C,YAC1D,YAAY,CAAC,QAAQ,CAAC,QAAQ,CAAC,GAC7B,CACN,GACG,EACN,eAAK,SAAS,EAAC,kCAAkC,aAC9C,OAAO,EACP,eAAe,CAAC,CAAC,CAAC,CACjB,KAAC,iBAAiB,IAAC,SAAS,EAAC,oCAAoC,GAAG,CACrE,CAAC,CAAC,CAAC,IAAI,IACJ,IACC,CACV,CAAC;AACJ,CAAC","sourcesContent":["import { useLocation } from \"react-router\";\nimport { useHeaderTitle, useHeaderActions } from \"./HeaderActions\";\nimport { AgentToggleButton } from \"@agent-native/core/client\";\nimport { Button } from \"@/components/ui/button\";\nimport { IconLayoutSidebar } from \"@tabler/icons-react\";\n\nconst pageTitles: Record<string, string> = {\n \"/\": \"Overview\",\n \"/overview\": \"Overview\",\n \"/vault\": \"Vault\",\n \"/integrations\": \"Integrations\",\n \"/workspace\": \"Resources\",\n \"/messaging\": \"Messaging\",\n \"/agents\": \"Agents\",\n \"/destinations\": \"Destinations\",\n \"/identities\": \"Identities\",\n \"/approvals\": \"Approvals\",\n \"/audit\": \"Audit\",\n \"/team\": \"Team\",\n};\n\nfunction resolveTitle(pathname: string): string {\n if (pageTitles[pathname]) return pageTitles[pathname];\n\n if (pathname.startsWith(\"/extensions\")) return \"Extensions\";\n\n return \"Dispatch\";\n}\n\nexport function Header({\n onOpenMobile,\n showAgentToggle = true,\n}: {\n onOpenMobile?: () => void;\n showAgentToggle?: boolean;\n}) {\n const location = useLocation();\n const title = useHeaderTitle();\n const actions = useHeaderActions();\n\n return (\n <header className=\"flex h-12 shrink-0 items-center gap-3 border-b border-border bg-background px-4 lg:px-6\">\n {onOpenMobile ? (\n <Button\n variant=\"ghost\"\n size=\"icon\"\n className=\"h-8 w-8 lg:hidden cursor-pointer\"\n onClick={onOpenMobile}\n aria-label=\"Open navigation\"\n >\n <IconLayoutSidebar />\n </Button>\n ) : null}\n <div className=\"flex items-center gap-3 flex-1 min-w-0\">\n {title ?? (\n <h1 className=\"text-lg font-semibold tracking-tight truncate\">\n {resolveTitle(location.pathname)}\n </h1>\n )}\n </div>\n <div className=\"flex items-center gap-2 shrink-0\">\n {actions}\n {showAgentToggle ? (\n <AgentToggleButton className=\"h-8 w-8 rounded-md hover:bg-accent\" />\n ) : null}\n </div>\n </header>\n );\n}\n"]}
@@ -1 +1 @@
1
- {"version":3,"file":"Layout.d.ts","sourceRoot":"","sources":["../../../src/components/layout/Layout.tsx"],"names":[],"mappings":"AAAA,OAAO,EAAY,KAAK,aAAa,EAAE,KAAK,SAAS,EAAE,MAAM,OAAO,CAAC;AAoCrE,MAAM,MAAM,kBAAkB,GAAG,SAAS,GAAG,YAAY,CAAC;AAE1D,MAAM,MAAM,eAAe,GAAG,aAAa,CAAC;IAC1C,IAAI,CAAC,EAAE,MAAM,GAAG,MAAM,CAAC;IACvB,SAAS,CAAC,EAAE,MAAM,CAAC;CACpB,CAAC,CAAC;AAEH,MAAM,WAAW,eAAe;IAC9B,uEAAuE;IACvE,EAAE,EAAE,MAAM,CAAC;IACX,iFAAiF;IACjF,EAAE,EAAE,MAAM,CAAC;IACX,KAAK,EAAE,MAAM,CAAC;IACd,IAAI,CAAC,EAAE,eAAe,CAAC;IACvB,mFAAmF;IACnF,OAAO,CAAC,EAAE,kBAAkB,CAAC;IAC7B,gEAAgE;IAChE,KAAK,CAAC,EAAE,CAAC,QAAQ,EAAE,MAAM,KAAK,OAAO,CAAC;CACvC;AAED,MAAM,WAAW,uBAAuB;IACtC,8DAA8D;IAC9D,QAAQ,CAAC,EAAE,SAAS,eAAe,EAAE,CAAC;IACtC,kFAAkF;IAClF,SAAS,CAAC,EAAE,SAAS,MAAM,EAAE,CAAC;CAC/B;AAmJD,wBAAgB,UAAU,CAAC,EACzB,UAAU,EACV,UAAU,GACX,EAAE;IACD,UAAU,CAAC,EAAE,MAAM,IAAI,CAAC;IACxB,UAAU,CAAC,EAAE,uBAAuB,CAAC;CACtC,2CAwGA;AAED,wBAAgB,MAAM,CAAC,EACrB,QAAQ,EACR,UAAU,GACX,EAAE;IACD,QAAQ,EAAE,SAAS,CAAC;IACpB,UAAU,CAAC,EAAE,uBAAuB,CAAC;CACtC,2CAyEA"}
1
+ {"version":3,"file":"Layout.d.ts","sourceRoot":"","sources":["../../../src/components/layout/Layout.tsx"],"names":[],"mappings":"AAAA,OAAO,EAAY,KAAK,aAAa,EAAE,KAAK,SAAS,EAAE,MAAM,OAAO,CAAC;AAoCrE,MAAM,MAAM,kBAAkB,GAAG,SAAS,GAAG,YAAY,CAAC;AAE1D,MAAM,MAAM,eAAe,GAAG,aAAa,CAAC;IAC1C,IAAI,CAAC,EAAE,MAAM,GAAG,MAAM,CAAC;IACvB,SAAS,CAAC,EAAE,MAAM,CAAC;CACpB,CAAC,CAAC;AAEH,MAAM,WAAW,eAAe;IAC9B,uEAAuE;IACvE,EAAE,EAAE,MAAM,CAAC;IACX,iFAAiF;IACjF,EAAE,EAAE,MAAM,CAAC;IACX,KAAK,EAAE,MAAM,CAAC;IACd,IAAI,CAAC,EAAE,eAAe,CAAC;IACvB,mFAAmF;IACnF,OAAO,CAAC,EAAE,kBAAkB,CAAC;IAC7B,gEAAgE;IAChE,KAAK,CAAC,EAAE,CAAC,QAAQ,EAAE,MAAM,KAAK,OAAO,CAAC;CACvC;AAED,MAAM,WAAW,uBAAuB;IACtC,8DAA8D;IAC9D,QAAQ,CAAC,EAAE,SAAS,eAAe,EAAE,CAAC;IACtC,kFAAkF;IAClF,SAAS,CAAC,EAAE,SAAS,MAAM,EAAE,CAAC;CAC/B;AAmJD,wBAAgB,UAAU,CAAC,EACzB,UAAU,EACV,UAAU,GACX,EAAE;IACD,UAAU,CAAC,EAAE,MAAM,IAAI,CAAC;IACxB,UAAU,CAAC,EAAE,uBAAuB,CAAC;CACtC,2CAwGA;AAED,wBAAgB,MAAM,CAAC,EACrB,QAAQ,EACR,UAAU,GACX,EAAE;IACD,QAAQ,EAAE,SAAS,CAAC;IACpB,UAAU,CAAC,EAAE,uBAAuB,CAAC;CACtC,2CAiEA"}
@@ -170,12 +170,11 @@ export function NavContent({ onNavigate, extensions, }) {
170
170
  export function Layout({ children, extensions, }) {
171
171
  const location = useLocation();
172
172
  const [mobileOpen, setMobileOpen] = useState(false);
173
- const hasEmbeddedAgentChat = location.pathname === "/" || location.pathname === "/overview";
174
173
  if (CHROMELESS_PATHS.some((path) => location.pathname === path)) {
175
174
  return _jsx(_Fragment, { children: children });
176
175
  }
177
176
  const showHeader = !pageOwnsToolbar(location.pathname);
178
- const appContent = (_jsxs("div", { className: "flex h-full flex-1 flex-col overflow-hidden", children: [showHeader ? (_jsx(Header, { onOpenMobile: () => setMobileOpen(true), showAgentToggle: !hasEmbeddedAgentChat })) : null, _jsx(InvitationBanner, {}), _jsx("main", { className: "flex-1 overflow-y-auto", children: showHeader ? (_jsx("div", { className: "mx-auto max-w-7xl space-y-5 px-4 py-6 sm:px-6", children: children })) : (children) })] }));
179
- return (_jsx(HeaderActionsProvider, { children: _jsxs("div", { className: "flex h-screen w-full overflow-hidden bg-background", children: [_jsx("aside", { className: "hidden 2xl:flex w-64 shrink-0 flex-col border-r bg-sidebar text-sidebar-foreground", children: _jsx(NavContent, { extensions: extensions }) }), _jsx(Sheet, { open: mobileOpen, onOpenChange: setMobileOpen, children: _jsxs(SheetContent, { side: "left", className: "w-72 p-0 bg-sidebar text-sidebar-foreground [&>button]:hidden", children: [_jsx(SheetTitle, { className: "sr-only", children: "Navigation" }), _jsx(SheetDescription, { className: "sr-only", children: "Workspace navigation links" }), _jsx("div", { className: "flex h-full w-full flex-col", children: _jsx(NavContent, { extensions: extensions, onNavigate: () => setMobileOpen(false) }) })] }) }), _jsx(AgentSidebar, { position: "right", defaultOpen: false, emptyStateText: "Create apps, grant keys, and route work across the workspace.", suggestions: SIDEBAR_SUGGESTIONS, children: appContent })] }) }));
177
+ const appContent = (_jsxs("div", { className: "flex h-full flex-1 flex-col overflow-hidden", children: [showHeader ? _jsx(Header, { onOpenMobile: () => setMobileOpen(true) }) : null, _jsx(InvitationBanner, {}), _jsx("main", { className: "flex-1 overflow-y-auto", children: showHeader ? (_jsx("div", { className: "mx-auto max-w-7xl space-y-5 px-4 py-6 sm:px-6", children: children })) : (children) })] }));
178
+ return (_jsx(HeaderActionsProvider, { children: _jsxs("div", { className: "flex h-screen w-full overflow-hidden bg-background", children: [_jsx("aside", { className: "hidden lg:flex w-64 shrink-0 flex-col border-r bg-sidebar text-sidebar-foreground", children: _jsx(NavContent, { extensions: extensions }) }), _jsx(Sheet, { open: mobileOpen, onOpenChange: setMobileOpen, children: _jsxs(SheetContent, { side: "left", className: "w-72 p-0 bg-sidebar text-sidebar-foreground [&>button]:hidden", children: [_jsx(SheetTitle, { className: "sr-only", children: "Navigation" }), _jsx(SheetDescription, { className: "sr-only", children: "Workspace navigation links" }), _jsx("div", { className: "flex h-full w-full flex-col", children: _jsx(NavContent, { extensions: extensions, onNavigate: () => setMobileOpen(false) }) })] }) }), _jsx(AgentSidebar, { position: "right", defaultOpen: false, emptyStateText: "Create apps, grant keys, and route work across the workspace.", suggestions: SIDEBAR_SUGGESTIONS, children: appContent })] }) }));
180
179
  }
181
180
  //# sourceMappingURL=Layout.js.map
@@ -1 +1 @@
1
- {"version":3,"file":"Layout.js","sourceRoot":"","sources":["../../../src/components/layout/Layout.tsx"],"names":[],"mappings":";AAAA,OAAO,EAAE,QAAQ,EAAsC,MAAM,OAAO,CAAC;AACrE,OAAO,EAAE,OAAO,EAAE,WAAW,EAAE,MAAM,cAAc,CAAC;AACpD,OAAO,EACL,YAAY,EACZ,cAAc,EACd,OAAO,EACP,cAAc,GACf,MAAM,2BAA2B,CAAC;AACnC,OAAO,EAAE,gBAAgB,EAAE,MAAM,+BAA+B,CAAC;AACjE,OAAO,EAAE,mBAAmB,EAAE,MAAM,iCAAiC,CAAC;AACtE,OAAO,EACL,gBAAgB,EAChB,QAAQ,EACR,YAAY,EACZ,iBAAiB,EACjB,OAAO,EACP,eAAe,EACf,kBAAkB,EAClB,iBAAiB,EACjB,aAAa,EACb,eAAe,EACf,WAAW,EACX,UAAU,EACV,eAAe,EACf,cAAc,GACf,MAAM,qBAAqB,CAAC;AAC7B,OAAO,EAAE,EAAE,EAAE,MAAM,aAAa,CAAC;AACjC,OAAO,EACL,KAAK,EACL,YAAY,EACZ,gBAAgB,EAChB,UAAU,GACX,MAAM,uBAAuB,CAAC;AAC/B,OAAO,EAAE,MAAM,EAAE,MAAM,UAAU,CAAC;AAClC,OAAO,EAAE,qBAAqB,EAAE,MAAM,iBAAiB,CAAC;AA6BxD,MAAM,iBAAiB,GAAG;IACxB;QACE,EAAE,EAAE,UAAU;QACd,EAAE,EAAE,WAAW;QACf,KAAK,EAAE,UAAU;QACjB,IAAI,EAAE,aAAa;QACnB,OAAO,EAAE,SAAS;KACnB;IACD;QACE,EAAE,EAAE,MAAM;QACV,EAAE,EAAE,OAAO;QACX,KAAK,EAAE,MAAM;QACb,IAAI,EAAE,QAAQ;QACd,OAAO,EAAE,SAAS;KACnB;IACD;QACE,EAAE,EAAE,SAAS;QACb,EAAE,EAAE,UAAU;QACd,KAAK,EAAE,SAAS;QAChB,IAAI,EAAE,YAAY;QAClB,OAAO,EAAE,SAAS;KACnB;IACD;QACE,EAAE,EAAE,OAAO;QACX,EAAE,EAAE,QAAQ;QACZ,KAAK,EAAE,OAAO;QACd,IAAI,EAAE,OAAO;QACb,OAAO,EAAE,SAAS;KACnB;IACD;QACE,EAAE,EAAE,cAAc;QAClB,EAAE,EAAE,eAAe;QACnB,KAAK,EAAE,cAAc;QACrB,IAAI,EAAE,UAAU;QAChB,OAAO,EAAE,SAAS;KACnB;IACD;QACE,EAAE,EAAE,QAAQ;QACZ,EAAE,EAAE,SAAS;QACb,KAAK,EAAE,QAAQ;QACf,IAAI,EAAE,iBAAiB;QACvB,OAAO,EAAE,SAAS;KACnB;CAC4C,CAAC;AAEhD,MAAM,oBAAoB,GAAG;IAC3B;QACE,EAAE,EAAE,WAAW;QACf,EAAE,EAAE,YAAY;QAChB,KAAK,EAAE,WAAW;QAClB,IAAI,EAAE,kBAAkB;QACxB,OAAO,EAAE,YAAY;KACtB;IACD;QACE,EAAE,EAAE,WAAW;QACf,EAAE,EAAE,YAAY;QAChB,KAAK,EAAE,WAAW;QAClB,IAAI,EAAE,iBAAiB;QACvB,OAAO,EAAE,YAAY;KACtB;IACD;QACE,EAAE,EAAE,cAAc;QAClB,EAAE,EAAE,eAAe;QACnB,KAAK,EAAE,cAAc;QACrB,IAAI,EAAE,gBAAgB;QACtB,OAAO,EAAE,YAAY;KACtB;IACD;QACE,EAAE,EAAE,YAAY;QAChB,EAAE,EAAE,aAAa;QACjB,KAAK,EAAE,YAAY;QACnB,IAAI,EAAE,eAAe;QACrB,OAAO,EAAE,YAAY;KACtB;IACD;QACE,EAAE,EAAE,WAAW;QACf,EAAE,EAAE,YAAY;QAChB,KAAK,EAAE,WAAW;QAClB,IAAI,EAAE,eAAe;QACrB,OAAO,EAAE,YAAY;KACtB;IACD;QACE,EAAE,EAAE,OAAO;QACX,EAAE,EAAE,QAAQ;QACZ,KAAK,EAAE,OAAO;QACd,IAAI,EAAE,WAAW;QACjB,OAAO,EAAE,YAAY;KACtB;IACD;QACE,EAAE,EAAE,MAAM;QACV,EAAE,EAAE,OAAO;QACX,KAAK,EAAE,MAAM;QACb,IAAI,EAAE,cAAc;QACpB,OAAO,EAAE,YAAY;KACtB;CAC4C,CAAC;AAEhD,MAAM,eAAe,GAA+B,EAAE,CAAC;AAEvD,MAAM,mBAAmB,GAAG;IAC1B,kBAAkB;IAClB,uBAAuB;IACvB,0BAA0B;CAC3B,CAAC;AAEF,MAAM,gBAAgB,GAAG,CAAC,WAAW,CAAC,CAAC;AAEvC,0FAA0F;AAC1F,8EAA8E;AAC9E,4BAA4B;AAC5B,SAAS,eAAe,CAAC,QAAgB;IACvC,IAAI,QAAQ,KAAK,QAAQ,IAAI,QAAQ,CAAC,UAAU,CAAC,SAAS,CAAC;QAAE,OAAO,IAAI,CAAC;IACzE,IAAI,QAAQ,KAAK,aAAa,IAAI,QAAQ,CAAC,UAAU,CAAC,cAAc,CAAC;QACnE,OAAO,IAAI,CAAC;IACd,OAAO,KAAK,CAAC;AACf,CAAC;AAQD,SAAS,UAAU,CAAC,IAAqB;IACvC,OAAO,IAAI,CAAC,OAAO,IAAI,YAAY,CAAC;AACtC,CAAC;AAED,SAAS,kBAAkB,CAAC,IAAqB,EAAE,QAAgB;IACjE,IAAI,IAAI,CAAC,KAAK,EAAE,CAAC;QACf,IAAI,CAAC;YACH,IAAI,IAAI,CAAC,KAAK,CAAC,QAAQ,CAAC;gBAAE,OAAO,IAAI,CAAC;QACxC,CAAC;QAAC,MAAM,CAAC;YACP,OAAO,KAAK,CAAC;QACf,CAAC;IACH,CAAC;IACD,OAAO,QAAQ,KAAK,IAAI,CAAC,EAAE,IAAI,QAAQ,CAAC,UAAU,CAAC,GAAG,IAAI,CAAC,EAAE,GAAG,CAAC,CAAC;AACpE,CAAC;AAED,SAAS,kBAAkB,CACzB,KAAiC,EACjC,OAA2B;IAE3B,OAAO,KAAK,CAAC,MAAM,CAAC,CAAC,IAAI,EAAE,EAAE,CAAC,UAAU,CAAC,IAAI,CAAC,KAAK,OAAO,CAAC,CAAC;AAC9D,CAAC;AAED,MAAM,UAAU,UAAU,CAAC,EACzB,UAAU,EACV,UAAU,GAIX;IACC,MAAM,QAAQ,GAAG,WAAW,EAAE,CAAC;IAC/B,MAAM,EAAE,IAAI,EAAE,SAAS,EAAE,GAAG,cAAc,CACxC,oBAAoB,EACpB,EAAE,EACF,EAAE,SAAS,EAAE,MAAM,EAAE,CACtB,CAAC;IACF,MAAM,EAAE,GAAG,SAAsC,CAAC;IAClD,MAAM,cAAc,GAAG,EAAE,EAAE,WAAW,IAAI,EAAE,EAAE,IAAI,IAAI,IAAI,CAAC;IAC3D,MAAM,iBAAiB,GAAG,UAAU,EAAE,QAAQ,IAAI,eAAe,CAAC;IAClE,MAAM,eAAe,GAAG;QACtB,GAAG,iBAAiB;QACpB,GAAG,kBAAkB,CAAC,iBAAiB,EAAE,SAAS,CAAC;KACpD,CAAC;IACF,MAAM,kBAAkB,GAAG;QACzB,GAAG,oBAAoB;QACvB,GAAG,kBAAkB,CAAC,iBAAiB,EAAE,YAAY,CAAC;KACvD,CAAC;IACF,MAAM,cAAc,GAAG,kBAAkB,CAAC,IAAI,CAAC,CAAC,IAAI,EAAE,EAAE,CACtD,kBAAkB,CAAC,IAAI,EAAE,QAAQ,CAAC,QAAQ,CAAC,CAC5C,CAAC;IAEF,MAAM,aAAa,GAAG,CAAC,IAAqB,EAAE,EAAE;QAC9C,MAAM,IAAI,GAAG,IAAI,CAAC,IAAI,CAAC;QACvB,OAAO,CACL,uBACE,MAAC,OAAO,IACN,EAAE,EAAE,IAAI,CAAC,EAAE,EACX,OAAO,EAAE,UAAU,EACnB,SAAS,EAAE,CAAC,EAAE,QAAQ,EAAE,EAAE,EAAE;oBAC1B,MAAM,MAAM,GACV,QAAQ,IAAI,kBAAkB,CAAC,IAAI,EAAE,QAAQ,CAAC,QAAQ,CAAC,CAAC;oBAC1D,OAAO,EAAE,CACP,4DAA4D,EAC5D,MAAM;wBACJ,CAAC,CAAC,8DAA8D;wBAChE,CAAC,CAAC,yFAAyF,CAC9F,CAAC;gBACJ,CAAC,aAEA,IAAI,CAAC,CAAC,CAAC,CACN,KAAC,IAAI,IAAC,IAAI,EAAE,EAAE,EAAE,SAAS,EAAC,UAAU,GAAG,CACxC,CAAC,CAAC,CAAC,CACF,eAAM,SAAS,EAAC,kBAAkB,iBAAa,MAAM,GAAG,CACzD,EACD,eAAM,SAAS,EAAC,UAAU,YAAE,IAAI,CAAC,KAAK,GAAQ,IACtC,IArBH,IAAI,CAAC,EAAE,CAsBX,CACN,CAAC;IACJ,CAAC,CAAC;IAEF,OAAO,CACL,8BACE,cAAK,SAAS,EAAC,oBAAoB,YACjC,eAAK,SAAS,EAAC,yBAAyB,aACtC,eAAK,SAAS,EAAC,oFAAoF,aACjG,cACE,GAAG,EAAE,OAAO,CAAC,8BAA8B,CAAC,EAC5C,GAAG,EAAC,EAAE,iBACM,MAAM,EAClB,SAAS,EAAC,uCAAuC,GACjD,EACF,cACE,GAAG,EAAE,OAAO,CAAC,6BAA6B,CAAC,EAC3C,GAAG,EAAC,EAAE,iBACM,MAAM,EAClB,SAAS,EAAC,uCAAuC,GACjD,IACE,EACN,eAAK,SAAS,EAAC,SAAS,aACtB,cAAK,SAAS,EAAC,gDAAgD,YAC5D,cAAc,IAAI,UAAU,GACzB,EACN,cAAK,SAAS,EAAC,wCAAwC,YACpD,cAAc;wCACb,CAAC,CAAC,eAAe,EAAE,EAAE,QAAQ,IAAI,CAAC,OAAO,EAAE,EAAE,QAAQ,KAAK,CAAC,CAAC,CAAC,CAAC,EAAE,CAAC,CAAC,CAAC,GAAG,EAAE;wCACxE,CAAC,CAAC,yBAAyB,GACzB,IACF,IACF,GACF,EAEN,eAAK,SAAS,EAAC,kCAAkC,aAC/C,aAAI,SAAS,EAAC,aAAa,YAAE,eAAe,CAAC,GAAG,CAAC,aAAa,CAAC,GAAM,EACrE,mBAAS,SAAS,EAAC,YAAY,EAAC,IAAI,EAAE,cAAc,aAClD,mBAAS,SAAS,EAAC,yOAAyO,aAC1P,wCAAuB,EACvB,KAAC,eAAe,IACd,IAAI,EAAE,EAAE,EACR,SAAS,EAAC,4CAA4C,GACtD,IACM,EACV,aAAI,SAAS,EAAC,kBAAkB,YAC7B,kBAAkB,CAAC,GAAG,CAAC,aAAa,CAAC,GACnC,IACG,IACN,EAEN,eAAK,SAAS,EAAC,oBAAoB,aACjC,KAAC,mBAAmB,KAAG,EACvB,KAAC,cAAc,KAAG,IACd,IACL,CACJ,CAAC;AACJ,CAAC;AAED,MAAM,UAAU,MAAM,CAAC,EACrB,QAAQ,EACR,UAAU,GAIX;IACC,MAAM,QAAQ,GAAG,WAAW,EAAE,CAAC;IAC/B,MAAM,CAAC,UAAU,EAAE,aAAa,CAAC,GAAG,QAAQ,CAAC,KAAK,CAAC,CAAC;IACpD,MAAM,oBAAoB,GACxB,QAAQ,CAAC,QAAQ,KAAK,GAAG,IAAI,QAAQ,CAAC,QAAQ,KAAK,WAAW,CAAC;IAEjE,IAAI,gBAAgB,CAAC,IAAI,CAAC,CAAC,IAAI,EAAE,EAAE,CAAC,QAAQ,CAAC,QAAQ,KAAK,IAAI,CAAC,EAAE,CAAC;QAChE,OAAO,4BAAG,QAAQ,GAAI,CAAC;IACzB,CAAC;IAED,MAAM,UAAU,GAAG,CAAC,eAAe,CAAC,QAAQ,CAAC,QAAQ,CAAC,CAAC;IACvD,MAAM,UAAU,GAAG,CACjB,eAAK,SAAS,EAAC,6CAA6C,aACzD,UAAU,CAAC,CAAC,CAAC,CACZ,KAAC,MAAM,IACL,YAAY,EAAE,GAAG,EAAE,CAAC,aAAa,CAAC,IAAI,CAAC,EACvC,eAAe,EAAE,CAAC,oBAAoB,GACtC,CACH,CAAC,CAAC,CAAC,IAAI,EACR,KAAC,gBAAgB,KAAG,EACpB,eAAM,SAAS,EAAC,wBAAwB,YACrC,UAAU,CAAC,CAAC,CAAC,CACZ,cAAK,SAAS,EAAC,+CAA+C,YAC3D,QAAQ,GACL,CACP,CAAC,CAAC,CAAC,CACF,QAAQ,CACT,GACI,IACH,CACP,CAAC;IAEF,OAAO,CACL,KAAC,qBAAqB,cACpB,eAAK,SAAS,EAAC,oDAAoD,aACjE,gBAAO,SAAS,EAAC,oFAAoF,YACnG,KAAC,UAAU,IAAC,UAAU,EAAE,UAAU,GAAI,GAChC,EAER,KAAC,KAAK,IAAC,IAAI,EAAE,UAAU,EAAE,YAAY,EAAE,aAAa,YAClD,MAAC,YAAY,IACX,IAAI,EAAC,MAAM,EACX,SAAS,EAAC,+DAA+D,aAEzE,KAAC,UAAU,IAAC,SAAS,EAAC,SAAS,2BAAwB,EACvD,KAAC,gBAAgB,IAAC,SAAS,EAAC,SAAS,2CAElB,EACnB,cAAK,SAAS,EAAC,6BAA6B,YAC1C,KAAC,UAAU,IACT,UAAU,EAAE,UAAU,EACtB,UAAU,EAAE,GAAG,EAAE,CAAC,aAAa,CAAC,KAAK,CAAC,GACtC,GACE,IACO,GACT,EAOR,KAAC,YAAY,IACX,QAAQ,EAAC,OAAO,EAChB,WAAW,EAAE,KAAK,EAClB,cAAc,EAAC,+DAA+D,EAC9E,WAAW,EAAE,mBAAmB,YAE/B,UAAU,GACE,IACX,GACgB,CACzB,CAAC;AACJ,CAAC","sourcesContent":["import { useState, type ComponentType, type ReactNode } from \"react\";\nimport { NavLink, useLocation } from \"react-router\";\nimport {\n AgentSidebar,\n FeedbackButton,\n appPath,\n useActionQuery,\n} from \"@agent-native/core/client\";\nimport { InvitationBanner } from \"@agent-native/core/client/org\";\nimport { ToolsSidebarSection } from \"@agent-native/core/client/tools\";\nimport {\n IconArrowUpRight,\n IconApps,\n IconChartBar,\n IconBrandTelegram,\n IconKey,\n IconChevronDown,\n IconLayersSubtract,\n IconPlugConnected,\n IconBroadcast,\n IconFingerprint,\n IconHistory,\n IconPuzzle,\n IconShieldCheck,\n IconUsersGroup,\n} from \"@tabler/icons-react\";\nimport { cn } from \"@/lib/utils\";\nimport {\n Sheet,\n SheetContent,\n SheetDescription,\n SheetTitle,\n} from \"@/components/ui/sheet\";\nimport { Header } from \"./Header\";\nimport { HeaderActionsProvider } from \"./HeaderActions\";\n\nexport type DispatchNavSection = \"primary\" | \"operations\";\n\nexport type DispatchNavIcon = ComponentType<{\n size?: number | string;\n className?: string;\n}>;\n\nexport interface DispatchNavItem {\n /** Stable id used for keys and navigation.view. Avoid built-in ids. */\n id: string;\n /** React Router path for the tab, usually backed by an app/routes/*.tsx file. */\n to: string;\n label: string;\n icon?: DispatchNavIcon;\n /** Defaults to \"operations\", which is where local management tools usually fit. */\n section?: DispatchNavSection;\n /** Override active matching for nested or multi-route tools. */\n match?: (pathname: string) => boolean;\n}\n\nexport interface DispatchExtensionConfig {\n /** Extra sidebar tabs supplied by the generated workspace. */\n navItems?: readonly DispatchNavItem[];\n /** Extra React Query keys to invalidate when Dispatch receives DB sync events. */\n queryKeys?: readonly string[];\n}\n\nconst PRIMARY_NAV_ITEMS = [\n {\n id: \"overview\",\n to: \"/overview\",\n label: \"Overview\",\n icon: IconBroadcast,\n section: \"primary\",\n },\n {\n id: \"apps\",\n to: \"/apps\",\n label: \"Apps\",\n icon: IconApps,\n section: \"primary\",\n },\n {\n id: \"metrics\",\n to: \"/metrics\",\n label: \"Metrics\",\n icon: IconChartBar,\n section: \"primary\",\n },\n {\n id: \"vault\",\n to: \"/vault\",\n label: \"Vault\",\n icon: IconKey,\n section: \"primary\",\n },\n {\n id: \"integrations\",\n to: \"/integrations\",\n label: \"Integrations\",\n icon: IconPuzzle,\n section: \"primary\",\n },\n {\n id: \"agents\",\n to: \"/agents\",\n label: \"Agents\",\n icon: IconPlugConnected,\n section: \"primary\",\n },\n] as const satisfies readonly DispatchNavItem[];\n\nconst OPERATIONS_NAV_ITEMS = [\n {\n id: \"workspace\",\n to: \"/workspace\",\n label: \"Resources\",\n icon: IconLayersSubtract,\n section: \"operations\",\n },\n {\n id: \"messaging\",\n to: \"/messaging\",\n label: \"Messaging\",\n icon: IconBrandTelegram,\n section: \"operations\",\n },\n {\n id: \"destinations\",\n to: \"/destinations\",\n label: \"Destinations\",\n icon: IconArrowUpRight,\n section: \"operations\",\n },\n {\n id: \"identities\",\n to: \"/identities\",\n label: \"Identities\",\n icon: IconFingerprint,\n section: \"operations\",\n },\n {\n id: \"approvals\",\n to: \"/approvals\",\n label: \"Approvals\",\n icon: IconShieldCheck,\n section: \"operations\",\n },\n {\n id: \"audit\",\n to: \"/audit\",\n label: \"Audit\",\n icon: IconHistory,\n section: \"operations\",\n },\n {\n id: \"team\",\n to: \"/team\",\n label: \"Team\",\n icon: IconUsersGroup,\n section: \"operations\",\n },\n] as const satisfies readonly DispatchNavItem[];\n\nconst EMPTY_NAV_ITEMS: readonly DispatchNavItem[] = [];\n\nconst SIDEBAR_SUGGESTIONS = [\n \"Create a new app\",\n \"Grant a key to an app\",\n \"Check integration health\",\n];\n\nconst CHROMELESS_PATHS = [\"/approval\"];\n\n// Routes whose page renders its own toolbar (with NotificationsBell + AgentToggleButton).\n// Layout still mounts the sidebar + AgentSidebar, but skips its own Header so\n// there's no double-header.\nfunction pageOwnsToolbar(pathname: string): boolean {\n if (pathname === \"/tools\" || pathname.startsWith(\"/tools/\")) return true;\n if (pathname === \"/extensions\" || pathname.startsWith(\"/extensions/\"))\n return true;\n return false;\n}\n\ninterface WorkspaceInfo {\n name: string | null;\n displayName: string | null;\n appCount: number;\n}\n\nfunction sectionFor(item: DispatchNavItem): DispatchNavSection {\n return item.section ?? \"operations\";\n}\n\nfunction navItemMatchesPath(item: DispatchNavItem, pathname: string): boolean {\n if (item.match) {\n try {\n if (item.match(pathname)) return true;\n } catch {\n return false;\n }\n }\n return pathname === item.to || pathname.startsWith(`${item.to}/`);\n}\n\nfunction navItemsForSection(\n items: readonly DispatchNavItem[],\n section: DispatchNavSection,\n): DispatchNavItem[] {\n return items.filter((item) => sectionFor(item) === section);\n}\n\nexport function NavContent({\n onNavigate,\n extensions,\n}: {\n onNavigate?: () => void;\n extensions?: DispatchExtensionConfig;\n}) {\n const location = useLocation();\n const { data: workspace } = useActionQuery(\n \"get-workspace-info\",\n {},\n { staleTime: 60_000 },\n );\n const ws = workspace as WorkspaceInfo | undefined;\n const workspaceLabel = ws?.displayName ?? ws?.name ?? null;\n const extensionNavItems = extensions?.navItems ?? EMPTY_NAV_ITEMS;\n const primaryNavItems = [\n ...PRIMARY_NAV_ITEMS,\n ...navItemsForSection(extensionNavItems, \"primary\"),\n ];\n const operationsNavItems = [\n ...OPERATIONS_NAV_ITEMS,\n ...navItemsForSection(extensionNavItems, \"operations\"),\n ];\n const operationsOpen = operationsNavItems.some((item) =>\n navItemMatchesPath(item, location.pathname),\n );\n\n const renderNavItem = (item: DispatchNavItem) => {\n const Icon = item.icon;\n return (\n <li key={item.id}>\n <NavLink\n to={item.to}\n onClick={onNavigate}\n className={({ isActive }) => {\n const active =\n isActive || navItemMatchesPath(item, location.pathname);\n return cn(\n \"flex h-8 w-full items-center gap-2 rounded-md px-2 text-sm\",\n active\n ? \"bg-sidebar-accent font-medium text-sidebar-accent-foreground\"\n : \"text-sidebar-foreground/70 hover:bg-sidebar-accent hover:text-sidebar-accent-foreground\",\n );\n }}\n >\n {Icon ? (\n <Icon size={16} className=\"shrink-0\" />\n ) : (\n <span className=\"h-4 w-4 shrink-0\" aria-hidden=\"true\" />\n )}\n <span className=\"truncate\">{item.label}</span>\n </NavLink>\n </li>\n );\n };\n\n return (\n <>\n <div className=\"border-b px-4 py-3\">\n <div className=\"flex items-center gap-3\">\n <div className=\"flex h-9 w-9 items-center justify-center rounded-xl border bg-card text-foreground\">\n <img\n src={appPath(\"/agent-native-icon-light.svg\")}\n alt=\"\"\n aria-hidden=\"true\"\n className=\"block h-4 w-auto shrink-0 dark:hidden\"\n />\n <img\n src={appPath(\"/agent-native-icon-dark.svg\")}\n alt=\"\"\n aria-hidden=\"true\"\n className=\"hidden h-4 w-auto shrink-0 dark:block\"\n />\n </div>\n <div className=\"min-w-0\">\n <div className=\"truncate text-sm font-semibold text-foreground\">\n {workspaceLabel ?? \"Dispatch\"}\n </div>\n <div className=\"truncate text-xs text-muted-foreground\">\n {workspaceLabel\n ? `Workspace · ${ws?.appCount ?? 0} app${ws?.appCount === 1 ? \"\" : \"s\"}`\n : \"Workspace control plane\"}\n </div>\n </div>\n </div>\n </div>\n\n <nav className=\"flex-1 overflow-y-auto px-2 py-3\">\n <ul className=\"space-y-0.5\">{primaryNavItems.map(renderNavItem)}</ul>\n <details className=\"group mt-4\" open={operationsOpen}>\n <summary className=\"flex h-8 cursor-pointer list-none items-center justify-between rounded-md px-2 text-xs font-medium uppercase text-sidebar-foreground/50 hover:bg-sidebar-accent hover:text-sidebar-accent-foreground [&::-webkit-details-marker]:hidden\">\n <span>Operations</span>\n <IconChevronDown\n size={14}\n className=\"transition-transform group-open:rotate-180\"\n />\n </summary>\n <ul className=\"mt-1 space-y-0.5\">\n {operationsNavItems.map(renderNavItem)}\n </ul>\n </details>\n </nav>\n\n <div className=\"border-t px-2 py-2\">\n <ToolsSidebarSection />\n <FeedbackButton />\n </div>\n </>\n );\n}\n\nexport function Layout({\n children,\n extensions,\n}: {\n children: ReactNode;\n extensions?: DispatchExtensionConfig;\n}) {\n const location = useLocation();\n const [mobileOpen, setMobileOpen] = useState(false);\n const hasEmbeddedAgentChat =\n location.pathname === \"/\" || location.pathname === \"/overview\";\n\n if (CHROMELESS_PATHS.some((path) => location.pathname === path)) {\n return <>{children}</>;\n }\n\n const showHeader = !pageOwnsToolbar(location.pathname);\n const appContent = (\n <div className=\"flex h-full flex-1 flex-col overflow-hidden\">\n {showHeader ? (\n <Header\n onOpenMobile={() => setMobileOpen(true)}\n showAgentToggle={!hasEmbeddedAgentChat}\n />\n ) : null}\n <InvitationBanner />\n <main className=\"flex-1 overflow-y-auto\">\n {showHeader ? (\n <div className=\"mx-auto max-w-7xl space-y-5 px-4 py-6 sm:px-6\">\n {children}\n </div>\n ) : (\n children\n )}\n </main>\n </div>\n );\n\n return (\n <HeaderActionsProvider>\n <div className=\"flex h-screen w-full overflow-hidden bg-background\">\n <aside className=\"hidden 2xl:flex w-64 shrink-0 flex-col border-r bg-sidebar text-sidebar-foreground\">\n <NavContent extensions={extensions} />\n </aside>\n\n <Sheet open={mobileOpen} onOpenChange={setMobileOpen}>\n <SheetContent\n side=\"left\"\n className=\"w-72 p-0 bg-sidebar text-sidebar-foreground [&>button]:hidden\"\n >\n <SheetTitle className=\"sr-only\">Navigation</SheetTitle>\n <SheetDescription className=\"sr-only\">\n Workspace navigation links\n </SheetDescription>\n <div className=\"flex h-full w-full flex-col\">\n <NavContent\n extensions={extensions}\n onNavigate={() => setMobileOpen(false)}\n />\n </div>\n </SheetContent>\n </Sheet>\n\n {/*\n * Always mount AgentSidebar so home composer's sendToAgentChat\n * fallback can pop it via agent-panel:open. The toggle button stays\n * hidden on overview because the home composer is the primary input.\n */}\n <AgentSidebar\n position=\"right\"\n defaultOpen={false}\n emptyStateText=\"Create apps, grant keys, and route work across the workspace.\"\n suggestions={SIDEBAR_SUGGESTIONS}\n >\n {appContent}\n </AgentSidebar>\n </div>\n </HeaderActionsProvider>\n );\n}\n"]}
1
+ {"version":3,"file":"Layout.js","sourceRoot":"","sources":["../../../src/components/layout/Layout.tsx"],"names":[],"mappings":"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","sourcesContent":["import { useState, type ComponentType, type ReactNode } from \"react\";\nimport { NavLink, useLocation } from \"react-router\";\nimport {\n AgentSidebar,\n FeedbackButton,\n appPath,\n useActionQuery,\n} from \"@agent-native/core/client\";\nimport { InvitationBanner } from \"@agent-native/core/client/org\";\nimport { ToolsSidebarSection } from \"@agent-native/core/client/tools\";\nimport {\n IconArrowUpRight,\n IconApps,\n IconChartBar,\n IconBrandTelegram,\n IconKey,\n IconChevronDown,\n IconLayersSubtract,\n IconPlugConnected,\n IconBroadcast,\n IconFingerprint,\n IconHistory,\n IconPuzzle,\n IconShieldCheck,\n IconUsersGroup,\n} from \"@tabler/icons-react\";\nimport { cn } from \"@/lib/utils\";\nimport {\n Sheet,\n SheetContent,\n SheetDescription,\n SheetTitle,\n} from \"@/components/ui/sheet\";\nimport { Header } from \"./Header\";\nimport { HeaderActionsProvider } from \"./HeaderActions\";\n\nexport type DispatchNavSection = \"primary\" | \"operations\";\n\nexport type DispatchNavIcon = ComponentType<{\n size?: number | string;\n className?: string;\n}>;\n\nexport interface DispatchNavItem {\n /** Stable id used for keys and navigation.view. Avoid built-in ids. */\n id: string;\n /** React Router path for the tab, usually backed by an app/routes/*.tsx file. */\n to: string;\n label: string;\n icon?: DispatchNavIcon;\n /** Defaults to \"operations\", which is where local management tools usually fit. */\n section?: DispatchNavSection;\n /** Override active matching for nested or multi-route tools. */\n match?: (pathname: string) => boolean;\n}\n\nexport interface DispatchExtensionConfig {\n /** Extra sidebar tabs supplied by the generated workspace. */\n navItems?: readonly DispatchNavItem[];\n /** Extra React Query keys to invalidate when Dispatch receives DB sync events. */\n queryKeys?: readonly string[];\n}\n\nconst PRIMARY_NAV_ITEMS = [\n {\n id: \"overview\",\n to: \"/overview\",\n label: \"Overview\",\n icon: IconBroadcast,\n section: \"primary\",\n },\n {\n id: \"apps\",\n to: \"/apps\",\n label: \"Apps\",\n icon: IconApps,\n section: \"primary\",\n },\n {\n id: \"metrics\",\n to: \"/metrics\",\n label: \"Metrics\",\n icon: IconChartBar,\n section: \"primary\",\n },\n {\n id: \"vault\",\n to: \"/vault\",\n label: \"Vault\",\n icon: IconKey,\n section: \"primary\",\n },\n {\n id: \"integrations\",\n to: \"/integrations\",\n label: \"Integrations\",\n icon: IconPuzzle,\n section: \"primary\",\n },\n {\n id: \"agents\",\n to: \"/agents\",\n label: \"Agents\",\n icon: IconPlugConnected,\n section: \"primary\",\n },\n] as const satisfies readonly DispatchNavItem[];\n\nconst OPERATIONS_NAV_ITEMS = [\n {\n id: \"workspace\",\n to: \"/workspace\",\n label: \"Resources\",\n icon: IconLayersSubtract,\n section: \"operations\",\n },\n {\n id: \"messaging\",\n to: \"/messaging\",\n label: \"Messaging\",\n icon: IconBrandTelegram,\n section: \"operations\",\n },\n {\n id: \"destinations\",\n to: \"/destinations\",\n label: \"Destinations\",\n icon: IconArrowUpRight,\n section: \"operations\",\n },\n {\n id: \"identities\",\n to: \"/identities\",\n label: \"Identities\",\n icon: IconFingerprint,\n section: \"operations\",\n },\n {\n id: \"approvals\",\n to: \"/approvals\",\n label: \"Approvals\",\n icon: IconShieldCheck,\n section: \"operations\",\n },\n {\n id: \"audit\",\n to: \"/audit\",\n label: \"Audit\",\n icon: IconHistory,\n section: \"operations\",\n },\n {\n id: \"team\",\n to: \"/team\",\n label: \"Team\",\n icon: IconUsersGroup,\n section: \"operations\",\n },\n] as const satisfies readonly DispatchNavItem[];\n\nconst EMPTY_NAV_ITEMS: readonly DispatchNavItem[] = [];\n\nconst SIDEBAR_SUGGESTIONS = [\n \"Create a new app\",\n \"Grant a key to an app\",\n \"Check integration health\",\n];\n\nconst CHROMELESS_PATHS = [\"/approval\"];\n\n// Routes whose page renders its own toolbar (with NotificationsBell + AgentToggleButton).\n// Layout still mounts the sidebar + AgentSidebar, but skips its own Header so\n// there's no double-header.\nfunction pageOwnsToolbar(pathname: string): boolean {\n if (pathname === \"/tools\" || pathname.startsWith(\"/tools/\")) return true;\n if (pathname === \"/extensions\" || pathname.startsWith(\"/extensions/\"))\n return true;\n return false;\n}\n\ninterface WorkspaceInfo {\n name: string | null;\n displayName: string | null;\n appCount: number;\n}\n\nfunction sectionFor(item: DispatchNavItem): DispatchNavSection {\n return item.section ?? \"operations\";\n}\n\nfunction navItemMatchesPath(item: DispatchNavItem, pathname: string): boolean {\n if (item.match) {\n try {\n if (item.match(pathname)) return true;\n } catch {\n return false;\n }\n }\n return pathname === item.to || pathname.startsWith(`${item.to}/`);\n}\n\nfunction navItemsForSection(\n items: readonly DispatchNavItem[],\n section: DispatchNavSection,\n): DispatchNavItem[] {\n return items.filter((item) => sectionFor(item) === section);\n}\n\nexport function NavContent({\n onNavigate,\n extensions,\n}: {\n onNavigate?: () => void;\n extensions?: DispatchExtensionConfig;\n}) {\n const location = useLocation();\n const { data: workspace } = useActionQuery(\n \"get-workspace-info\",\n {},\n { staleTime: 60_000 },\n );\n const ws = workspace as WorkspaceInfo | undefined;\n const workspaceLabel = ws?.displayName ?? ws?.name ?? null;\n const extensionNavItems = extensions?.navItems ?? EMPTY_NAV_ITEMS;\n const primaryNavItems = [\n ...PRIMARY_NAV_ITEMS,\n ...navItemsForSection(extensionNavItems, \"primary\"),\n ];\n const operationsNavItems = [\n ...OPERATIONS_NAV_ITEMS,\n ...navItemsForSection(extensionNavItems, \"operations\"),\n ];\n const operationsOpen = operationsNavItems.some((item) =>\n navItemMatchesPath(item, location.pathname),\n );\n\n const renderNavItem = (item: DispatchNavItem) => {\n const Icon = item.icon;\n return (\n <li key={item.id}>\n <NavLink\n to={item.to}\n onClick={onNavigate}\n className={({ isActive }) => {\n const active =\n isActive || navItemMatchesPath(item, location.pathname);\n return cn(\n \"flex h-8 w-full items-center gap-2 rounded-md px-2 text-sm\",\n active\n ? \"bg-sidebar-accent font-medium text-sidebar-accent-foreground\"\n : \"text-sidebar-foreground/70 hover:bg-sidebar-accent hover:text-sidebar-accent-foreground\",\n );\n }}\n >\n {Icon ? (\n <Icon size={16} className=\"shrink-0\" />\n ) : (\n <span className=\"h-4 w-4 shrink-0\" aria-hidden=\"true\" />\n )}\n <span className=\"truncate\">{item.label}</span>\n </NavLink>\n </li>\n );\n };\n\n return (\n <>\n <div className=\"border-b px-4 py-3\">\n <div className=\"flex items-center gap-3\">\n <div className=\"flex h-9 w-9 items-center justify-center rounded-xl border bg-card text-foreground\">\n <img\n src={appPath(\"/agent-native-icon-light.svg\")}\n alt=\"\"\n aria-hidden=\"true\"\n className=\"block h-4 w-auto shrink-0 dark:hidden\"\n />\n <img\n src={appPath(\"/agent-native-icon-dark.svg\")}\n alt=\"\"\n aria-hidden=\"true\"\n className=\"hidden h-4 w-auto shrink-0 dark:block\"\n />\n </div>\n <div className=\"min-w-0\">\n <div className=\"truncate text-sm font-semibold text-foreground\">\n {workspaceLabel ?? \"Dispatch\"}\n </div>\n <div className=\"truncate text-xs text-muted-foreground\">\n {workspaceLabel\n ? `Workspace · ${ws?.appCount ?? 0} app${ws?.appCount === 1 ? \"\" : \"s\"}`\n : \"Workspace control plane\"}\n </div>\n </div>\n </div>\n </div>\n\n <nav className=\"flex-1 overflow-y-auto px-2 py-3\">\n <ul className=\"space-y-0.5\">{primaryNavItems.map(renderNavItem)}</ul>\n <details className=\"group mt-4\" open={operationsOpen}>\n <summary className=\"flex h-8 cursor-pointer list-none items-center justify-between rounded-md px-2 text-xs font-medium uppercase text-sidebar-foreground/50 hover:bg-sidebar-accent hover:text-sidebar-accent-foreground [&::-webkit-details-marker]:hidden\">\n <span>Operations</span>\n <IconChevronDown\n size={14}\n className=\"transition-transform group-open:rotate-180\"\n />\n </summary>\n <ul className=\"mt-1 space-y-0.5\">\n {operationsNavItems.map(renderNavItem)}\n </ul>\n </details>\n </nav>\n\n <div className=\"border-t px-2 py-2\">\n <ToolsSidebarSection />\n <FeedbackButton />\n </div>\n </>\n );\n}\n\nexport function Layout({\n children,\n extensions,\n}: {\n children: ReactNode;\n extensions?: DispatchExtensionConfig;\n}) {\n const location = useLocation();\n const [mobileOpen, setMobileOpen] = useState(false);\n\n if (CHROMELESS_PATHS.some((path) => location.pathname === path)) {\n return <>{children}</>;\n }\n\n const showHeader = !pageOwnsToolbar(location.pathname);\n const appContent = (\n <div className=\"flex h-full flex-1 flex-col overflow-hidden\">\n {showHeader ? <Header onOpenMobile={() => setMobileOpen(true)} /> : null}\n <InvitationBanner />\n <main className=\"flex-1 overflow-y-auto\">\n {showHeader ? (\n <div className=\"mx-auto max-w-7xl space-y-5 px-4 py-6 sm:px-6\">\n {children}\n </div>\n ) : (\n children\n )}\n </main>\n </div>\n );\n\n return (\n <HeaderActionsProvider>\n <div className=\"flex h-screen w-full overflow-hidden bg-background\">\n <aside className=\"hidden lg:flex w-64 shrink-0 flex-col border-r bg-sidebar text-sidebar-foreground\">\n <NavContent extensions={extensions} />\n </aside>\n\n <Sheet open={mobileOpen} onOpenChange={setMobileOpen}>\n <SheetContent\n side=\"left\"\n className=\"w-72 p-0 bg-sidebar text-sidebar-foreground [&>button]:hidden\"\n >\n <SheetTitle className=\"sr-only\">Navigation</SheetTitle>\n <SheetDescription className=\"sr-only\">\n Workspace navigation links\n </SheetDescription>\n <div className=\"flex h-full w-full flex-col\">\n <NavContent\n extensions={extensions}\n onNavigate={() => setMobileOpen(false)}\n />\n </div>\n </SheetContent>\n </Sheet>\n\n {/*\n * Always mount AgentSidebar so home composer's sendToAgentChat\n * fallback can pop it via agent-panel:open.\n */}\n <AgentSidebar\n position=\"right\"\n defaultOpen={false}\n emptyStateText=\"Create apps, grant keys, and route work across the workspace.\"\n suggestions={SIDEBAR_SUGGESTIONS}\n >\n {appContent}\n </AgentSidebar>\n </div>\n </HeaderActionsProvider>\n );\n}\n"]}
@@ -1 +1 @@
1
- {"version":3,"file":"sidebar.d.ts","sourceRoot":"","sources":["../../../src/components/ui/sidebar.tsx"],"names":[],"mappings":"AAAA,OAAO,KAAK,KAAK,MAAM,OAAO,CAAC;AAE/B,OAAO,EAAE,YAAY,EAAO,MAAM,0BAA0B,CAAC;AAe7D,OAAO,EAEL,cAAc,EAGf,MAAM,yBAAyB,CAAC;AASjC,KAAK,cAAc,GAAG;IACpB,KAAK,EAAE,UAAU,GAAG,WAAW,CAAC;IAChC,IAAI,EAAE,OAAO,CAAC;IACd,OAAO,EAAE,CAAC,IAAI,EAAE,OAAO,KAAK,IAAI,CAAC;IACjC,UAAU,EAAE,OAAO,CAAC;IACpB,aAAa,EAAE,CAAC,IAAI,EAAE,OAAO,KAAK,IAAI,CAAC;IACvC,QAAQ,EAAE,OAAO,CAAC;IAClB,aAAa,EAAE,MAAM,IAAI,CAAC;CAC3B,CAAC;AAEF,QAAA,MAAM,cAAc,+BAAmD,CAAC;AAExE,iBAAS,UAAU,mBAOlB;AAED,QAAA,MAAM,eAAe;kBAGH,OAAO;WACd,OAAO;mBACC,CAAC,IAAI,EAAE,OAAO,KAAK,IAAI;gDA6GzC,CAAC;AAGF,QAAA,MAAM,OAAO;WAGF,MAAM,GAAG,OAAO;cACb,SAAS,GAAG,UAAU,GAAG,OAAO;kBAC5B,WAAW,GAAG,MAAM,GAAG,MAAM;gDAmG9C,CAAC;AAGF,QAAA,MAAM,cAAc,8KAuBlB,CAAC;AAGH,QAAA,MAAM,WAAW,kLA0Bf,CAAC;AAGH,QAAA,MAAM,YAAY,6JAehB,CAAC;AAGH,QAAA,MAAM,YAAY,mOAehB,CAAC;AAGH,QAAA,MAAM,aAAa,mKAYjB,CAAC;AAGH,QAAA,MAAM,aAAa,mKAYjB,CAAC;AAGH,QAAA,MAAM,gBAAgB,iOAYpB,CAAC;AAGH,QAAA,MAAM,cAAc,mKAelB,CAAC;AAGH,QAAA,MAAM,YAAY,mKAYhB,CAAC;AAGH,QAAA,MAAM,iBAAiB;cAEqB,OAAO;gDAgBjD,CAAC;AAGH,QAAA,MAAM,kBAAkB;cAEuB,OAAO;mDAkBpD,CAAC;AAGH,QAAA,MAAM,mBAAmB,mKAUvB,CAAC;AAGH,QAAA,MAAM,WAAW,yKAUf,CAAC;AAGH,QAAA,MAAM,eAAe,kKAUnB,CAAC;AAyBH,QAAA,MAAM,iBAAiB;cAGT,OAAO;eACN,OAAO;cACR,MAAM,GAAG,KAAK,CAAC,cAAc,CAAC,OAAO,cAAc,CAAC;;;;oHAmDjE,CAAC;AAGF,QAAA,MAAM,iBAAiB;cAGT,OAAO;kBACH,OAAO;mDAwBvB,CAAC;AAGH,QAAA,MAAM,gBAAgB,mKAkBpB,CAAC;AAGH,QAAA,MAAM,mBAAmB;eAGV,OAAO;gDAgCpB,CAAC;AAGH,QAAA,MAAM,cAAc,yKAclB,CAAC;AAGH,QAAA,MAAM,kBAAkB,kKAG6B,CAAC;AAGtD,QAAA,MAAM,oBAAoB;cAGZ,OAAO;WACV,IAAI,GAAG,IAAI;eACP,OAAO;mDAsBpB,CAAC;AAGH,OAAO,EACL,OAAO,EACP,cAAc,EACd,aAAa,EACb,YAAY,EACZ,kBAAkB,EAClB,mBAAmB,EACnB,iBAAiB,EACjB,aAAa,EACb,YAAY,EACZ,YAAY,EACZ,WAAW,EACX,iBAAiB,EACjB,gBAAgB,EAChB,iBAAiB,EACjB,eAAe,EACf,mBAAmB,EACnB,cAAc,EACd,oBAAoB,EACpB,kBAAkB,EAClB,eAAe,EACf,WAAW,EACX,gBAAgB,EAChB,cAAc,EACd,UAAU,GACX,CAAC"}
1
+ {"version":3,"file":"sidebar.d.ts","sourceRoot":"","sources":["../../../src/components/ui/sidebar.tsx"],"names":[],"mappings":"AAAA,OAAO,KAAK,KAAK,MAAM,OAAO,CAAC;AAE/B,OAAO,EAAE,YAAY,EAAO,MAAM,0BAA0B,CAAC;AAe7D,OAAO,EAEL,cAAc,EAGf,MAAM,yBAAyB,CAAC;AASjC,KAAK,cAAc,GAAG;IACpB,KAAK,EAAE,UAAU,GAAG,WAAW,CAAC;IAChC,IAAI,EAAE,OAAO,CAAC;IACd,OAAO,EAAE,CAAC,IAAI,EAAE,OAAO,KAAK,IAAI,CAAC;IACjC,UAAU,EAAE,OAAO,CAAC;IACpB,aAAa,EAAE,CAAC,IAAI,EAAE,OAAO,KAAK,IAAI,CAAC;IACvC,QAAQ,EAAE,OAAO,CAAC;IAClB,aAAa,EAAE,MAAM,IAAI,CAAC;CAC3B,CAAC;AAEF,QAAA,MAAM,cAAc,+BAAmD,CAAC;AAExE,iBAAS,UAAU,mBAOlB;AAED,QAAA,MAAM,eAAe;kBAGH,OAAO;WACd,OAAO;mBACC,CAAC,IAAI,EAAE,OAAO,KAAK,IAAI;gDA6GzC,CAAC;AAGF,QAAA,MAAM,OAAO;WAGF,MAAM,GAAG,OAAO;cACb,SAAS,GAAG,UAAU,GAAG,OAAO;kBAC5B,WAAW,GAAG,MAAM,GAAG,MAAM;gDAmG9C,CAAC;AAGF,QAAA,MAAM,cAAc,8KAuBlB,CAAC;AAGH,QAAA,MAAM,WAAW,kLA8Bf,CAAC;AAGH,QAAA,MAAM,YAAY,6JAehB,CAAC;AAGH,QAAA,MAAM,YAAY,mOAehB,CAAC;AAGH,QAAA,MAAM,aAAa,mKAYjB,CAAC;AAGH,QAAA,MAAM,aAAa,mKAYjB,CAAC;AAGH,QAAA,MAAM,gBAAgB,iOAYpB,CAAC;AAGH,QAAA,MAAM,cAAc,mKAelB,CAAC;AAGH,QAAA,MAAM,YAAY,mKAYhB,CAAC;AAGH,QAAA,MAAM,iBAAiB;cAEqB,OAAO;gDAgBjD,CAAC;AAGH,QAAA,MAAM,kBAAkB;cAEuB,OAAO;mDAkBpD,CAAC;AAGH,QAAA,MAAM,mBAAmB,mKAUvB,CAAC;AAGH,QAAA,MAAM,WAAW,yKAUf,CAAC;AAGH,QAAA,MAAM,eAAe,kKAUnB,CAAC;AAyBH,QAAA,MAAM,iBAAiB;cAGT,OAAO;eACN,OAAO;cACR,MAAM,GAAG,KAAK,CAAC,cAAc,CAAC,OAAO,cAAc,CAAC;;;;oHAmDjE,CAAC;AAGF,QAAA,MAAM,iBAAiB;cAGT,OAAO;kBACH,OAAO;mDAwBvB,CAAC;AAGH,QAAA,MAAM,gBAAgB,mKAkBpB,CAAC;AAGH,QAAA,MAAM,mBAAmB;eAGV,OAAO;gDAgCpB,CAAC;AAGH,QAAA,MAAM,cAAc,yKAclB,CAAC;AAGH,QAAA,MAAM,kBAAkB,kKAG6B,CAAC;AAGtD,QAAA,MAAM,oBAAoB;cAGZ,OAAO;WACV,IAAI,GAAG,IAAI;eACP,OAAO;mDAsBpB,CAAC;AAGH,OAAO,EACL,OAAO,EACP,cAAc,EACd,aAAa,EACb,YAAY,EACZ,kBAAkB,EAClB,mBAAmB,EACnB,iBAAiB,EACjB,aAAa,EACb,YAAY,EACZ,YAAY,EACZ,WAAW,EACX,iBAAiB,EACjB,gBAAgB,EAChB,iBAAiB,EACjB,eAAe,EACf,mBAAmB,EACnB,cAAc,EACd,oBAAoB,EACpB,kBAAkB,EAClB,eAAe,EACf,WAAW,EACX,gBAAgB,EAChB,cAAc,EACd,UAAU,GACX,CAAC"}
@@ -119,7 +119,7 @@ const SidebarTrigger = React.forwardRef(({ className, onClick, ...props }, ref)
119
119
  SidebarTrigger.displayName = "SidebarTrigger";
120
120
  const SidebarRail = React.forwardRef(({ className, ...props }, ref) => {
121
121
  const { toggleSidebar } = useSidebar();
122
- return (_jsx("button", { ref: ref, "data-sidebar": "rail", "aria-label": "Toggle Sidebar", tabIndex: -1, onClick: toggleSidebar, title: "Toggle Sidebar", className: cn("absolute inset-y-0 z-20 hidden w-4 -translate-x-1/2 transition-all ease-linear after:absolute after:inset-y-0 after:left-1/2 after:w-[2px] hover:after:bg-sidebar-border group-data-[side=left]:-right-4 group-data-[side=right]:left-0 sm:flex", "[[data-side=left]_&]:cursor-w-resize [[data-side=right]_&]:cursor-e-resize", "[[data-side=left][data-state=collapsed]_&]:cursor-e-resize [[data-side=right][data-state=collapsed]_&]:cursor-w-resize", "group-data-[collapsible=offcanvas]:translate-x-0 group-data-[collapsible=offcanvas]:after:left-full group-data-[collapsible=offcanvas]:hover:bg-sidebar", "[[data-side=left][data-collapsible=offcanvas]_&]:-right-2", "[[data-side=right][data-collapsible=offcanvas]_&]:-left-2", className), ...props }));
122
+ return (_jsxs(Tooltip, { children: [_jsx(TooltipTrigger, { asChild: true, children: _jsx("button", { ref: ref, "data-sidebar": "rail", "aria-label": "Toggle Sidebar", tabIndex: -1, onClick: toggleSidebar, className: cn("absolute inset-y-0 z-20 hidden w-4 -translate-x-1/2 transition-all ease-linear after:absolute after:inset-y-0 after:left-1/2 after:w-[2px] hover:after:bg-sidebar-border group-data-[side=left]:-right-4 group-data-[side=right]:left-0 sm:flex", "[[data-side=left]_&]:cursor-w-resize [[data-side=right]_&]:cursor-e-resize", "[[data-side=left][data-state=collapsed]_&]:cursor-e-resize [[data-side=right][data-state=collapsed]_&]:cursor-w-resize", "group-data-[collapsible=offcanvas]:translate-x-0 group-data-[collapsible=offcanvas]:after:left-full group-data-[collapsible=offcanvas]:hover:bg-sidebar", "[[data-side=left][data-collapsible=offcanvas]_&]:-right-2", "[[data-side=right][data-collapsible=offcanvas]_&]:-left-2", className), ...props }) }), _jsx(TooltipContent, { children: "Toggle Sidebar" })] }));
123
123
  });
124
124
  SidebarRail.displayName = "SidebarRail";
125
125
  const SidebarInset = React.forwardRef(({ className, ...props }, ref) => {