@agent-native/core 0.10.0 → 0.11.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (117) hide show
  1. package/dist/a2a/caller-auth.d.ts +12 -0
  2. package/dist/a2a/caller-auth.d.ts.map +1 -0
  3. package/dist/a2a/caller-auth.js +54 -0
  4. package/dist/a2a/caller-auth.js.map +1 -0
  5. package/dist/action.d.ts +17 -0
  6. package/dist/action.d.ts.map +1 -1
  7. package/dist/action.js +22 -0
  8. package/dist/action.js.map +1 -1
  9. package/dist/agent/production-agent.d.ts.map +1 -1
  10. package/dist/agent/production-agent.js +32 -19
  11. package/dist/agent/production-agent.js.map +1 -1
  12. package/dist/client/AgentPanel.d.ts.map +1 -1
  13. package/dist/client/AgentPanel.js +3 -3
  14. package/dist/client/AgentPanel.js.map +1 -1
  15. package/dist/client/AssistantChat.d.ts.map +1 -1
  16. package/dist/client/AssistantChat.js +17 -6
  17. package/dist/client/AssistantChat.js.map +1 -1
  18. package/dist/client/components/ui/dropdown-menu.d.ts +28 -0
  19. package/dist/client/components/ui/dropdown-menu.d.ts.map +1 -0
  20. package/dist/client/components/ui/dropdown-menu.js +34 -0
  21. package/dist/client/components/ui/dropdown-menu.js.map +1 -0
  22. package/dist/client/composer/TiptapComposer.js +1 -1
  23. package/dist/client/composer/TiptapComposer.js.map +1 -1
  24. package/dist/client/extensions/EmbeddedExtension.d.ts.map +1 -1
  25. package/dist/client/extensions/EmbeddedExtension.js +2 -0
  26. package/dist/client/extensions/EmbeddedExtension.js.map +1 -1
  27. package/dist/client/extensions/ExtensionSlot.js +14 -1
  28. package/dist/client/extensions/ExtensionSlot.js.map +1 -1
  29. package/dist/client/extensions/ExtensionViewer.d.ts.map +1 -1
  30. package/dist/client/extensions/ExtensionViewer.js +2 -0
  31. package/dist/client/extensions/ExtensionViewer.js.map +1 -1
  32. package/dist/client/extensions/ExtensionsListPage.d.ts.map +1 -1
  33. package/dist/client/extensions/ExtensionsListPage.js +2 -2
  34. package/dist/client/extensions/ExtensionsListPage.js.map +1 -1
  35. package/dist/client/extensions/ExtensionsSidebarSection.d.ts.map +1 -1
  36. package/dist/client/extensions/ExtensionsSidebarSection.js +6 -17
  37. package/dist/client/extensions/ExtensionsSidebarSection.js.map +1 -1
  38. package/dist/client/extensions/iframe-bridge.d.ts.map +1 -1
  39. package/dist/client/extensions/iframe-bridge.js +5 -8
  40. package/dist/client/extensions/iframe-bridge.js.map +1 -1
  41. package/dist/client/org/OrgSwitcher.d.ts +7 -1
  42. package/dist/client/org/OrgSwitcher.d.ts.map +1 -1
  43. package/dist/client/org/OrgSwitcher.js +8 -3
  44. package/dist/client/org/OrgSwitcher.js.map +1 -1
  45. package/dist/client/org/TeamPage.d.ts.map +1 -1
  46. package/dist/client/org/TeamPage.js +153 -20
  47. package/dist/client/org/TeamPage.js.map +1 -1
  48. package/dist/client/org/hooks.d.ts +29 -1
  49. package/dist/client/org/hooks.d.ts.map +1 -1
  50. package/dist/client/org/hooks.js +39 -2
  51. package/dist/client/org/hooks.js.map +1 -1
  52. package/dist/client/org/index.d.ts +2 -1
  53. package/dist/client/org/index.d.ts.map +1 -1
  54. package/dist/client/org/index.js +1 -1
  55. package/dist/client/org/index.js.map +1 -1
  56. package/dist/client/resources/ResourceTree.d.ts.map +1 -1
  57. package/dist/client/resources/ResourceTree.js +11 -3
  58. package/dist/client/resources/ResourceTree.js.map +1 -1
  59. package/dist/client/resources/ResourcesPanel.d.ts.map +1 -1
  60. package/dist/client/resources/ResourcesPanel.js +21 -5
  61. package/dist/client/resources/ResourcesPanel.js.map +1 -1
  62. package/dist/client/settings/SettingsPanel.d.ts.map +1 -1
  63. package/dist/client/settings/SettingsPanel.js +39 -3
  64. package/dist/client/settings/SettingsPanel.js.map +1 -1
  65. package/dist/deploy/build.d.ts.map +1 -1
  66. package/dist/deploy/build.js +20 -49
  67. package/dist/deploy/build.js.map +1 -1
  68. package/dist/index.browser.d.ts +1 -1
  69. package/dist/index.browser.d.ts.map +1 -1
  70. package/dist/index.browser.js +1 -1
  71. package/dist/index.browser.js.map +1 -1
  72. package/dist/index.d.ts +1 -1
  73. package/dist/index.d.ts.map +1 -1
  74. package/dist/index.js +1 -1
  75. package/dist/index.js.map +1 -1
  76. package/dist/org/accept-pending.d.ts.map +1 -1
  77. package/dist/org/accept-pending.js +5 -3
  78. package/dist/org/accept-pending.js.map +1 -1
  79. package/dist/org/free-email-providers.d.ts +18 -0
  80. package/dist/org/free-email-providers.d.ts.map +1 -0
  81. package/dist/org/free-email-providers.js +124 -0
  82. package/dist/org/free-email-providers.js.map +1 -0
  83. package/dist/org/handlers.d.ts +29 -5
  84. package/dist/org/handlers.d.ts.map +1 -1
  85. package/dist/org/handlers.js +178 -37
  86. package/dist/org/handlers.js.map +1 -1
  87. package/dist/org/index.d.ts +2 -1
  88. package/dist/org/index.d.ts.map +1 -1
  89. package/dist/org/index.js +2 -1
  90. package/dist/org/index.js.map +1 -1
  91. package/dist/org/migrations.d.ts.map +1 -1
  92. package/dist/org/migrations.js +4 -0
  93. package/dist/org/migrations.js.map +1 -1
  94. package/dist/org/plugin.d.ts.map +1 -1
  95. package/dist/org/plugin.js +13 -4
  96. package/dist/org/plugin.js.map +1 -1
  97. package/dist/org/schema.d.ts +19 -0
  98. package/dist/org/schema.d.ts.map +1 -1
  99. package/dist/org/schema.js +1 -0
  100. package/dist/org/schema.js.map +1 -1
  101. package/dist/org/types.d.ts +1 -0
  102. package/dist/org/types.d.ts.map +1 -1
  103. package/dist/org/types.js.map +1 -1
  104. package/dist/resources/metadata.d.ts +1 -0
  105. package/dist/resources/metadata.d.ts.map +1 -1
  106. package/dist/resources/metadata.js +13 -3
  107. package/dist/resources/metadata.js.map +1 -1
  108. package/dist/resources/store.d.ts.map +1 -1
  109. package/dist/resources/store.js +44 -6
  110. package/dist/resources/store.js.map +1 -1
  111. package/dist/server/agent-chat-plugin.d.ts.map +1 -1
  112. package/dist/server/agent-chat-plugin.js +38 -11
  113. package/dist/server/agent-chat-plugin.js.map +1 -1
  114. package/dist/server/google-oauth.d.ts.map +1 -1
  115. package/dist/server/google-oauth.js +10 -3
  116. package/dist/server/google-oauth.js.map +1 -1
  117. package/package.json +2 -1
@@ -1,13 +1,14 @@
1
1
  import { jsx as _jsx, jsxs as _jsxs } from "react/jsx-runtime";
2
2
  import { agentNativePath } from "../api-path.js";
3
- import { useState, useCallback, useMemo, useEffect } from "react";
3
+ import { useState, useCallback, useMemo } from "react";
4
4
  import { useQuery, useQueryClient } from "@tanstack/react-query";
5
5
  import { Link, useLocation, useNavigate } from "react-router";
6
- import { IconTool, IconPlus, IconStar, IconStarFilled, IconTrash, IconDots, IconHelpCircle, IconPencil, IconGripVertical, } from "@tabler/icons-react";
6
+ import { IconPlus, IconStar, IconStarFilled, IconTrash, IconDots, IconHelpCircle, IconPencil, IconGripVertical, } from "@tabler/icons-react";
7
7
  import { cn } from "../utils.js";
8
8
  import { sendToAgentChat } from "../agent-chat.js";
9
9
  import { PromptComposer } from "../composer/PromptComposer.js";
10
10
  import { Popover, PopoverContent, PopoverTrigger, } from "../components/ui/popover.js";
11
+ import { DropdownMenu, DropdownMenuContent, DropdownMenuItem, DropdownMenuTrigger, } from "../components/ui/dropdown-menu.js";
11
12
  import { applyToolsOrder, getToolsOrder, setToolsOrder, } from "./extension-order.js";
12
13
  import { Tooltip, TooltipContent, TooltipProvider, TooltipTrigger, } from "../components/ui/tooltip.js";
13
14
  const FAVORITES_KEY = "extensions-favorites";
@@ -130,14 +131,6 @@ export function ExtensionsSidebarSection() {
130
131
  queryClient.invalidateQueries({ queryKey: ["extension", extensionId] });
131
132
  }
132
133
  }, [renameValue, queryClient]);
133
- // Close menu on click outside
134
- useEffect(() => {
135
- if (!menuOpenId)
136
- return;
137
- const handler = () => setMenuOpenId(null);
138
- document.addEventListener("click", handler);
139
- return () => document.removeEventListener("click", handler);
140
- }, [menuOpenId]);
141
134
  const sortedTools = useMemo(() => {
142
135
  if (!extensions)
143
136
  return [];
@@ -173,14 +166,14 @@ export function ExtensionsSidebarSection() {
173
166
  if (!trimmed)
174
167
  return;
175
168
  sendToAgentChat({
176
- message: `Create a extension: ${trimmed}`,
169
+ message: `Create an extension: ${trimmed}`,
177
170
  submit: true,
178
171
  openSidebar: true,
179
172
  newTab: true,
180
173
  });
181
174
  setShowCreate(false);
182
175
  };
183
- return (_jsx(TooltipProvider, { delayDuration: 200, children: _jsxs("div", { className: "group/help relative min-w-0 py-2", children: [_jsxs("div", { className: cn("flex items-center justify-between px-3", sortedTools.length > 0 && "mb-1"), children: [_jsxs("span", { className: "inline-flex items-center gap-1.5 text-xs font-semibold uppercase tracking-wider text-muted-foreground", children: [_jsx(IconTool, { className: "h-3.5 w-3.5 shrink-0" }), "Extensions", _jsx("a", { href: "https://agent-native.com/docs/extensions", target: "_blank", rel: "noopener noreferrer", className: "opacity-0 group-hover/help:opacity-100 transition-opacity text-muted-foreground/50 hover:text-muted-foreground", "aria-label": "Extensions documentation", children: _jsx(IconHelpCircle, { className: "h-3 w-3" }) })] }), _jsxs(Popover, { open: showCreate, onOpenChange: setShowCreate, children: [_jsx(PopoverTrigger, { asChild: true, children: _jsx("button", { type: "button", className: "inline-flex h-5 w-5 cursor-pointer items-center justify-center rounded text-muted-foreground hover:bg-accent hover:text-accent-foreground", "aria-label": "New extension", children: _jsx(IconPlus, { className: "h-3.5 w-3.5" }) }) }), _jsxs(PopoverContent, { side: "right", align: "start", className: "w-[420px] p-3", children: [_jsx("p", { className: "px-1 pb-2 text-sm font-semibold text-foreground", children: "New extension" }), _jsx(PromptComposer, { autoFocus: true, placeholder: "Describe what you'd like to build...", draftScope: "extensions:sidebar-create", onSubmit: handleCreate })] })] })] }), isLoading ? (_jsx("div", { className: "min-w-0 space-y-0.5 px-1", children: [1, 2, 3].map((i) => (_jsx("div", { className: "flex items-center rounded-md px-2 py-1.5", children: _jsx("div", { className: "h-3 rounded bg-muted animate-pulse", style: { width: `${60 + i * 20}px` } }) }, i))) })) : sortedTools.length === 0 ? null : (_jsx("div", { className: "min-w-0 space-y-0.5 px-1", children: sortedTools.map((extension) => {
176
+ return (_jsx(TooltipProvider, { delayDuration: 200, children: _jsxs("div", { className: "group/help relative min-w-0 py-2", children: [_jsxs("div", { className: cn("flex items-center justify-between px-3", sortedTools.length > 0 && "mb-1"), children: [_jsxs("span", { className: "inline-flex items-center gap-1.5 text-xs font-semibold uppercase tracking-wider text-muted-foreground", children: ["Extensions", _jsx("a", { href: "https://agent-native.com/docs/extensions", target: "_blank", rel: "noopener noreferrer", className: "opacity-0 group-hover/help:opacity-100 transition-opacity text-muted-foreground/50 hover:text-muted-foreground", "aria-label": "Extensions documentation", children: _jsx(IconHelpCircle, { className: "h-3 w-3" }) })] }), _jsxs(Popover, { open: showCreate, onOpenChange: setShowCreate, children: [_jsx(PopoverTrigger, { asChild: true, children: _jsx("button", { type: "button", className: "inline-flex h-5 w-5 cursor-pointer items-center justify-center rounded text-muted-foreground hover:bg-accent hover:text-accent-foreground", "aria-label": "New extension", children: _jsx(IconPlus, { className: "h-3.5 w-3.5" }) }) }), _jsxs(PopoverContent, { side: "right", align: "start", className: "w-[420px] p-3", children: [_jsx("p", { className: "px-1 pb-2 text-sm font-semibold text-foreground", children: "New extension" }), _jsx(PromptComposer, { autoFocus: true, placeholder: "Describe what you'd like to build...", draftScope: "extensions:sidebar-create", onSubmit: handleCreate })] })] })] }), isLoading ? (_jsx("div", { className: "min-w-0 space-y-0.5 px-1", children: [1, 2, 3].map((i) => (_jsx("div", { className: "flex items-center rounded-md px-2 py-1.5", children: _jsx("div", { className: "h-3 rounded bg-muted animate-pulse", style: { width: `${60 + i * 20}px` } }) }, i))) })) : sortedTools.length === 0 ? null : (_jsx("div", { className: "min-w-0 space-y-0.5 px-1", children: sortedTools.map((extension) => {
184
177
  const isActive = location.pathname === `/extensions/${extension.id}` ||
185
178
  location.pathname === `/extensions/${extension.id}/edit`;
186
179
  const isFav = favoriteIds.has(extension.id);
@@ -227,11 +220,7 @@ export function ExtensionsSidebarSection() {
227
220
  toggleFavorite(extension.id);
228
221
  }, className: cn("pointer-events-auto cursor-pointer rounded p-0.5 transition-colors", isFav
229
222
  ? "text-yellow-500"
230
- : "text-muted-foreground/40 hover:text-yellow-500"), "aria-label": isFav ? "Unfavorite" : "Favorite", children: isFav ? (_jsx(IconStarFilled, { className: "h-3 w-3" })) : (_jsx(IconStar, { className: "h-3 w-3" })) }), _jsxs("div", { className: "relative", children: [_jsx("button", { type: "button", onClick: (e) => {
231
- e.preventDefault();
232
- e.stopPropagation();
233
- setMenuOpenId(menuOpenId === extension.id ? null : extension.id);
234
- }, className: "pointer-events-auto cursor-pointer rounded p-0.5 text-muted-foreground/40 transition-colors hover:text-foreground", "aria-label": "Extension actions", children: _jsx(IconDots, { className: "h-3 w-3" }) }), menuOpenId === extension.id && (_jsxs("div", { className: "absolute right-0 top-full z-50 mt-1 min-w-[120px] rounded-md border border-border bg-popover p-1 text-popover-foreground shadow-md", onClick: (e) => e.stopPropagation(), children: [_jsxs("button", { type: "button", onClick: () => startRename(extension), className: "flex w-full cursor-pointer items-center gap-2 rounded-sm px-2 py-1.5 text-sm hover:bg-accent", children: [_jsx(IconPencil, { className: "h-3.5 w-3.5" }), "Rename"] }), _jsxs("button", { type: "button", onClick: () => handleDelete(extension.id), className: "flex w-full cursor-pointer items-center gap-2 rounded-sm px-2 py-1.5 text-sm text-destructive hover:bg-accent", children: [_jsx(IconTrash, { className: "h-3.5 w-3.5" }), "Delete"] })] }))] })] })] }, extension.id));
223
+ : "text-muted-foreground/40 hover:text-yellow-500"), "aria-label": isFav ? "Unfavorite" : "Favorite", children: isFav ? (_jsx(IconStarFilled, { className: "h-3 w-3" })) : (_jsx(IconStar, { className: "h-3 w-3" })) }), _jsxs(DropdownMenu, { open: menuOpenId === extension.id, onOpenChange: (open) => setMenuOpenId(open ? extension.id : null), children: [_jsx(DropdownMenuTrigger, { asChild: true, children: _jsx("button", { type: "button", className: "pointer-events-auto cursor-pointer rounded p-0.5 text-muted-foreground/40 transition-colors hover:text-foreground", "aria-label": "Extension actions", children: _jsx(IconDots, { className: "h-3 w-3" }) }) }), _jsxs(DropdownMenuContent, { align: "end", sideOffset: 4, className: "min-w-[140px]", children: [_jsxs(DropdownMenuItem, { onSelect: () => startRename(extension), children: [_jsx(IconPencil, { className: "h-3.5 w-3.5" }), "Rename"] }), _jsxs(DropdownMenuItem, { onSelect: () => handleDelete(extension.id), className: "text-destructive focus:text-destructive", children: [_jsx(IconTrash, { className: "h-3.5 w-3.5" }), "Delete"] })] })] })] })] }, extension.id));
235
224
  }) }))] }) }));
236
225
  }
237
226
  //# sourceMappingURL=ExtensionsSidebarSection.js.map
@@ -1 +1 @@
1
- {"version":3,"file":"ExtensionsSidebarSection.js","sourceRoot":"","sources":["../../../src/client/extensions/ExtensionsSidebarSection.tsx"],"names":[],"mappings":"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","sourcesContent":["import { agentNativePath } from \"../api-path.js\";\nimport { useState, useCallback, useMemo, useEffect } from \"react\";\nimport { useQuery, useQueryClient } from \"@tanstack/react-query\";\nimport { Link, useLocation, useNavigate } from \"react-router\";\nimport {\n IconTool,\n IconPlus,\n IconStar,\n IconStarFilled,\n IconTrash,\n IconDots,\n IconHelpCircle,\n IconPencil,\n IconGripVertical,\n} from \"@tabler/icons-react\";\nimport { cn } from \"../utils.js\";\nimport { sendToAgentChat } from \"../agent-chat.js\";\nimport { PromptComposer } from \"../composer/PromptComposer.js\";\nimport {\n Popover,\n PopoverContent,\n PopoverTrigger,\n} from \"../components/ui/popover.js\";\nimport {\n applyToolsOrder,\n getToolsOrder,\n setToolsOrder,\n} from \"./extension-order.js\";\nimport {\n Tooltip,\n TooltipContent,\n TooltipProvider,\n TooltipTrigger,\n} from \"../components/ui/tooltip.js\";\n\ninterface Extension {\n id: string;\n name: string;\n description?: string;\n icon?: string;\n}\n\nconst FAVORITES_KEY = \"extensions-favorites\";\n\nfunction getFavorites(): Set<string> {\n try {\n const raw = localStorage.getItem(FAVORITES_KEY);\n if (!raw) return new Set();\n const parsed = JSON.parse(raw);\n return new Set(Array.isArray(parsed) ? parsed : []);\n } catch {\n return new Set();\n }\n}\n\nfunction saveFavorites(ids: Set<string>) {\n try {\n localStorage.setItem(FAVORITES_KEY, JSON.stringify(Array.from(ids)));\n } catch {\n // localStorage unavailable — ignore\n }\n}\n\nexport function ExtensionsSidebarSection() {\n const location = useLocation();\n const navigate = useNavigate();\n const queryClient = useQueryClient();\n const [favoriteIds, setFavoriteIds] = useState<Set<string>>(() =>\n typeof window !== \"undefined\" ? getFavorites() : new Set(),\n );\n const [menuOpenId, setMenuOpenId] = useState<string | null>(null);\n const [renamingId, setRenamingId] = useState<string | null>(null);\n const [renameValue, setRenameValue] = useState(\"\");\n const [showCreate, setShowCreate] = useState(false);\n const [toolOrderState, setToolOrderState] = useState<string[]>(() =>\n typeof window !== \"undefined\" ? getToolsOrder() : [],\n );\n const [draggingId, setDraggingId] = useState<string | null>(null);\n const [dragOverId, setDragOverId] = useState<string | null>(null);\n\n const { data: extensions, isLoading } = useQuery<Extension[]>({\n queryKey: [\"extensions\"],\n queryFn: async () => {\n const res = await fetch(agentNativePath(\"/_agent-native/extensions\"));\n if (!res.ok) return [];\n return res.json();\n },\n });\n\n const toggleFavorite = useCallback((id: string) => {\n setFavoriteIds((prev) => {\n const next = new Set(prev);\n if (next.has(id)) {\n next.delete(id);\n } else {\n next.add(id);\n }\n saveFavorites(next);\n return next;\n });\n }, []);\n\n const handleDelete = useCallback(\n async (extensionId: string) => {\n setMenuOpenId(null);\n const prev = queryClient.getQueryData<Extension[]>([\"extensions\"]);\n queryClient.setQueryData<Extension[]>([\"extensions\"], (old) =>\n (old ?? []).filter((t) => t.id !== extensionId),\n );\n try {\n const res = await fetch(\n agentNativePath(`/_agent-native/extensions/${extensionId}`),\n {\n method: \"DELETE\",\n },\n );\n if (!res.ok) throw new Error(\"Delete failed\");\n queryClient.removeQueries({ queryKey: [\"extension\", extensionId] });\n queryClient.invalidateQueries({ queryKey: [\"extensions\"] });\n setFavoriteIds((prev) => {\n const next = new Set(prev);\n next.delete(extensionId);\n saveFavorites(next);\n return next;\n });\n setToolOrderState((prev) => {\n const next = prev.filter((id) => id !== extensionId);\n if (next.length !== prev.length) setToolsOrder(next);\n return next;\n });\n if (\n location.pathname === `/extensions/${extensionId}` ||\n location.pathname === `/extensions/${extensionId}/edit`\n ) {\n navigate(\"/extensions\");\n }\n } catch {\n if (prev) queryClient.setQueryData([\"extensions\"], prev);\n }\n },\n [location.pathname, navigate, queryClient],\n );\n\n const startRename = useCallback((extension: Extension) => {\n setMenuOpenId(null);\n setRenameValue(extension.name);\n setRenamingId(extension.id);\n }, []);\n\n const submitRename = useCallback(\n async (extensionId: string) => {\n const trimmed = renameValue.trim();\n setRenamingId(null);\n if (!trimmed) return;\n const prev = queryClient.getQueryData<Extension[]>([\"extensions\"]);\n const existing = prev?.find((t) => t.id === extensionId);\n if (!existing || trimmed === existing.name) return;\n queryClient.setQueryData<Extension[]>([\"extensions\"], (old) =>\n (old ?? []).map((t) =>\n t.id === extensionId ? { ...t, name: trimmed } : t,\n ),\n );\n queryClient.setQueryData<Extension>([\"extension\", extensionId], (old) =>\n old ? { ...old, name: trimmed } : old,\n );\n try {\n await fetch(\n agentNativePath(`/_agent-native/extensions/${extensionId}`),\n {\n method: \"PUT\",\n headers: { \"Content-Type\": \"application/json\" },\n body: JSON.stringify({ name: trimmed }),\n },\n );\n queryClient.invalidateQueries({ queryKey: [\"extensions\"] });\n queryClient.invalidateQueries({ queryKey: [\"extension\", extensionId] });\n } catch {\n if (prev) queryClient.setQueryData([\"extensions\"], prev);\n queryClient.invalidateQueries({ queryKey: [\"extension\", extensionId] });\n }\n },\n [renameValue, queryClient],\n );\n\n // Close menu on click outside\n useEffect(() => {\n if (!menuOpenId) return;\n const handler = () => setMenuOpenId(null);\n document.addEventListener(\"click\", handler);\n return () => document.removeEventListener(\"click\", handler);\n }, [menuOpenId]);\n\n const sortedTools = useMemo(() => {\n if (!extensions) return [];\n const defaultSorted = [...extensions].sort((a, b) => {\n const aFav = favoriteIds.has(a.id) ? 0 : 1;\n const bFav = favoriteIds.has(b.id) ? 0 : 1;\n if (aFav !== bFav) return aFav - bFav;\n return a.name.localeCompare(b.name);\n });\n return toolOrderState.length > 0\n ? applyToolsOrder(defaultSorted, toolOrderState)\n : defaultSorted;\n }, [extensions, favoriteIds, toolOrderState]);\n\n const reorderTool = useCallback(\n (activeId: string, overId: string) => {\n if (activeId === overId) return;\n const ids = sortedTools.map((extension) => extension.id);\n const oldIndex = ids.indexOf(activeId);\n const newIndex = ids.indexOf(overId);\n if (oldIndex === -1 || newIndex === -1) return;\n const next = [...ids];\n const [moved] = next.splice(oldIndex, 1);\n if (!moved) return;\n next.splice(newIndex, 0, moved);\n setToolsOrder(next);\n setToolOrderState(next);\n },\n [sortedTools],\n );\n\n const handleCreate = (text: string) => {\n const trimmed = text.trim();\n if (!trimmed) return;\n sendToAgentChat({\n message: `Create a extension: ${trimmed}`,\n submit: true,\n openSidebar: true,\n newTab: true,\n });\n setShowCreate(false);\n };\n\n return (\n <TooltipProvider delayDuration={200}>\n <div className=\"group/help relative min-w-0 py-2\">\n <div\n className={cn(\n \"flex items-center justify-between px-3\",\n sortedTools.length > 0 && \"mb-1\",\n )}\n >\n <span className=\"inline-flex items-center gap-1.5 text-xs font-semibold uppercase tracking-wider text-muted-foreground\">\n <IconTool className=\"h-3.5 w-3.5 shrink-0\" />\n Extensions\n <a\n href=\"https://agent-native.com/docs/extensions\"\n target=\"_blank\"\n rel=\"noopener noreferrer\"\n className=\"opacity-0 group-hover/help:opacity-100 transition-opacity text-muted-foreground/50 hover:text-muted-foreground\"\n aria-label=\"Extensions documentation\"\n >\n <IconHelpCircle className=\"h-3 w-3\" />\n </a>\n </span>\n <Popover open={showCreate} onOpenChange={setShowCreate}>\n <PopoverTrigger asChild>\n <button\n type=\"button\"\n className=\"inline-flex h-5 w-5 cursor-pointer items-center justify-center rounded text-muted-foreground hover:bg-accent hover:text-accent-foreground\"\n aria-label=\"New extension\"\n >\n <IconPlus className=\"h-3.5 w-3.5\" />\n </button>\n </PopoverTrigger>\n <PopoverContent\n side=\"right\"\n align=\"start\"\n className=\"w-[420px] p-3\"\n >\n <p className=\"px-1 pb-2 text-sm font-semibold text-foreground\">\n New extension\n </p>\n <PromptComposer\n autoFocus\n placeholder=\"Describe what you'd like to build...\"\n draftScope=\"extensions:sidebar-create\"\n onSubmit={handleCreate}\n />\n </PopoverContent>\n </Popover>\n </div>\n\n {isLoading ? (\n <div className=\"min-w-0 space-y-0.5 px-1\">\n {[1, 2, 3].map((i) => (\n <div key={i} className=\"flex items-center rounded-md px-2 py-1.5\">\n <div\n className=\"h-3 rounded bg-muted animate-pulse\"\n style={{ width: `${60 + i * 20}px` }}\n />\n </div>\n ))}\n </div>\n ) : sortedTools.length === 0 ? null : (\n <div className=\"min-w-0 space-y-0.5 px-1\">\n {sortedTools.map((extension) => {\n const isActive =\n location.pathname === `/extensions/${extension.id}` ||\n location.pathname === `/extensions/${extension.id}/edit`;\n const isFav = favoriteIds.has(extension.id);\n const isRenamingThis = renamingId === extension.id;\n const actionsVisible =\n menuOpenId === extension.id || isRenamingThis;\n\n return (\n <div\n key={extension.id}\n onDragOver={(e) => {\n if (!draggingId || draggingId === extension.id) return;\n e.preventDefault();\n e.dataTransfer.dropEffect = \"move\";\n setDragOverId(extension.id);\n }}\n onDragLeave={() => {\n setDragOverId((current) =>\n current === extension.id ? null : current,\n );\n }}\n onDrop={(e) => {\n e.preventDefault();\n const activeId =\n draggingId || e.dataTransfer.getData(\"text/plain\");\n setDraggingId(null);\n setDragOverId(null);\n if (activeId) reorderTool(activeId, extension.id);\n }}\n className={cn(\n \"group/extension relative flex items-center min-w-0 rounded-md\",\n draggingId === extension.id && \"opacity-50\",\n dragOverId === extension.id &&\n draggingId !== extension.id &&\n \"bg-accent/60\",\n )}\n >\n <Tooltip>\n <TooltipTrigger asChild>\n <button\n type=\"button\"\n draggable\n onDragStart={(e) => {\n setDraggingId(extension.id);\n setDragOverId(null);\n e.dataTransfer.effectAllowed = \"move\";\n e.dataTransfer.setData(\"text/plain\", extension.id);\n }}\n onDragEnd={() => {\n setDraggingId(null);\n setDragOverId(null);\n }}\n className=\"-ml-2 cursor-grab rounded p-0.5 text-muted-foreground/30 opacity-0 transition-colors hover:text-muted-foreground/70 active:cursor-grabbing group-hover/extension:opacity-100 group-focus-within/extension:opacity-100\"\n aria-label={`Reorder ${extension.name}`}\n >\n <IconGripVertical className=\"h-3 w-3\" />\n </button>\n </TooltipTrigger>\n <TooltipContent>Drag to reorder</TooltipContent>\n </Tooltip>\n <Link\n to={`/extensions/${extension.id}`}\n className={cn(\n \"flex min-w-0 flex-1 items-center rounded-md px-2 py-1.5 pr-12 text-xs transition-[padding,color,background-color] md:pr-2 md:group-hover/extension:pr-12 md:group-focus-within/extension:pr-12\",\n actionsVisible && \"md:pr-12\",\n isActive\n ? \"bg-accent text-accent-foreground font-medium\"\n : \"text-muted-foreground hover:bg-accent/50 hover:text-accent-foreground\",\n )}\n >\n {isRenamingThis ? (\n <input\n autoFocus\n value={renameValue}\n onChange={(e) => setRenameValue(e.target.value)}\n onBlur={() => submitRename(extension.id)}\n onKeyDown={(e) => {\n if (e.key === \"Enter\") submitRename(extension.id);\n if (e.key === \"Escape\") setRenamingId(null);\n }}\n onClick={(e) => {\n e.preventDefault();\n e.stopPropagation();\n }}\n className=\"min-w-0 flex-1 truncate border-b border-primary bg-transparent px-0 py-0 text-xs outline-none\"\n />\n ) : (\n <span className=\"block truncate\">{extension.name}</span>\n )}\n </Link>\n\n <div\n className={cn(\n \"pointer-events-none absolute right-1 top-1/2 flex -translate-y-1/2 items-center gap-0.5 opacity-100 transition-opacity md:opacity-0 md:group-hover/extension:opacity-100 md:group-focus-within/extension:opacity-100\",\n actionsVisible && \"md:opacity-100\",\n )}\n >\n <button\n type=\"button\"\n onClick={(e) => {\n e.preventDefault();\n e.stopPropagation();\n toggleFavorite(extension.id);\n }}\n className={cn(\n \"pointer-events-auto cursor-pointer rounded p-0.5 transition-colors\",\n isFav\n ? \"text-yellow-500\"\n : \"text-muted-foreground/40 hover:text-yellow-500\",\n )}\n aria-label={isFav ? \"Unfavorite\" : \"Favorite\"}\n >\n {isFav ? (\n <IconStarFilled className=\"h-3 w-3\" />\n ) : (\n <IconStar className=\"h-3 w-3\" />\n )}\n </button>\n\n <div className=\"relative\">\n <button\n type=\"button\"\n onClick={(e) => {\n e.preventDefault();\n e.stopPropagation();\n setMenuOpenId(\n menuOpenId === extension.id ? null : extension.id,\n );\n }}\n className=\"pointer-events-auto cursor-pointer rounded p-0.5 text-muted-foreground/40 transition-colors hover:text-foreground\"\n aria-label=\"Extension actions\"\n >\n <IconDots className=\"h-3 w-3\" />\n </button>\n\n {menuOpenId === extension.id && (\n <div\n className=\"absolute right-0 top-full z-50 mt-1 min-w-[120px] rounded-md border border-border bg-popover p-1 text-popover-foreground shadow-md\"\n onClick={(e) => e.stopPropagation()}\n >\n <button\n type=\"button\"\n onClick={() => startRename(extension)}\n className=\"flex w-full cursor-pointer items-center gap-2 rounded-sm px-2 py-1.5 text-sm hover:bg-accent\"\n >\n <IconPencil className=\"h-3.5 w-3.5\" />\n Rename\n </button>\n <button\n type=\"button\"\n onClick={() => handleDelete(extension.id)}\n className=\"flex w-full cursor-pointer items-center gap-2 rounded-sm px-2 py-1.5 text-sm text-destructive hover:bg-accent\"\n >\n <IconTrash className=\"h-3.5 w-3.5\" />\n Delete\n </button>\n </div>\n )}\n </div>\n </div>\n </div>\n );\n })}\n </div>\n )}\n </div>\n </TooltipProvider>\n );\n}\n"]}
1
+ {"version":3,"file":"ExtensionsSidebarSection.js","sourceRoot":"","sources":["../../../src/client/extensions/ExtensionsSidebarSection.tsx"],"names":[],"mappings":";AAAA,OAAO,EAAE,eAAe,EAAE,MAAM,gBAAgB,CAAC;AACjD,OAAO,EAAE,QAAQ,EAAE,WAAW,EAAE,OAAO,EAAE,MAAM,OAAO,CAAC;AACvD,OAAO,EAAE,QAAQ,EAAE,cAAc,EAAE,MAAM,uBAAuB,CAAC;AACjE,OAAO,EAAE,IAAI,EAAE,WAAW,EAAE,WAAW,EAAE,MAAM,cAAc,CAAC;AAC9D,OAAO,EACL,QAAQ,EACR,QAAQ,EACR,cAAc,EACd,SAAS,EACT,QAAQ,EACR,cAAc,EACd,UAAU,EACV,gBAAgB,GACjB,MAAM,qBAAqB,CAAC;AAC7B,OAAO,EAAE,EAAE,EAAE,MAAM,aAAa,CAAC;AACjC,OAAO,EAAE,eAAe,EAAE,MAAM,kBAAkB,CAAC;AACnD,OAAO,EAAE,cAAc,EAAE,MAAM,+BAA+B,CAAC;AAC/D,OAAO,EACL,OAAO,EACP,cAAc,EACd,cAAc,GACf,MAAM,6BAA6B,CAAC;AACrC,OAAO,EACL,YAAY,EACZ,mBAAmB,EACnB,gBAAgB,EAChB,mBAAmB,GACpB,MAAM,mCAAmC,CAAC;AAC3C,OAAO,EACL,eAAe,EACf,aAAa,EACb,aAAa,GACd,MAAM,sBAAsB,CAAC;AAC9B,OAAO,EACL,OAAO,EACP,cAAc,EACd,eAAe,EACf,cAAc,GACf,MAAM,6BAA6B,CAAC;AASrC,MAAM,aAAa,GAAG,sBAAsB,CAAC;AAE7C,SAAS,YAAY;IACnB,IAAI,CAAC;QACH,MAAM,GAAG,GAAG,YAAY,CAAC,OAAO,CAAC,aAAa,CAAC,CAAC;QAChD,IAAI,CAAC,GAAG;YAAE,OAAO,IAAI,GAAG,EAAE,CAAC;QAC3B,MAAM,MAAM,GAAG,IAAI,CAAC,KAAK,CAAC,GAAG,CAAC,CAAC;QAC/B,OAAO,IAAI,GAAG,CAAC,KAAK,CAAC,OAAO,CAAC,MAAM,CAAC,CAAC,CAAC,CAAC,MAAM,CAAC,CAAC,CAAC,EAAE,CAAC,CAAC;IACtD,CAAC;IAAC,MAAM,CAAC;QACP,OAAO,IAAI,GAAG,EAAE,CAAC;IACnB,CAAC;AACH,CAAC;AAED,SAAS,aAAa,CAAC,GAAgB;IACrC,IAAI,CAAC;QACH,YAAY,CAAC,OAAO,CAAC,aAAa,EAAE,IAAI,CAAC,SAAS,CAAC,KAAK,CAAC,IAAI,CAAC,GAAG,CAAC,CAAC,CAAC,CAAC;IACvE,CAAC;IAAC,MAAM,CAAC;QACP,oCAAoC;IACtC,CAAC;AACH,CAAC;AAED,MAAM,UAAU,wBAAwB;IACtC,MAAM,QAAQ,GAAG,WAAW,EAAE,CAAC;IAC/B,MAAM,QAAQ,GAAG,WAAW,EAAE,CAAC;IAC/B,MAAM,WAAW,GAAG,cAAc,EAAE,CAAC;IACrC,MAAM,CAAC,WAAW,EAAE,cAAc,CAAC,GAAG,QAAQ,CAAc,GAAG,EAAE,CAC/D,OAAO,MAAM,KAAK,WAAW,CAAC,CAAC,CAAC,YAAY,EAAE,CAAC,CAAC,CAAC,IAAI,GAAG,EAAE,CAC3D,CAAC;IACF,MAAM,CAAC,UAAU,EAAE,aAAa,CAAC,GAAG,QAAQ,CAAgB,IAAI,CAAC,CAAC;IAClE,MAAM,CAAC,UAAU,EAAE,aAAa,CAAC,GAAG,QAAQ,CAAgB,IAAI,CAAC,CAAC;IAClE,MAAM,CAAC,WAAW,EAAE,cAAc,CAAC,GAAG,QAAQ,CAAC,EAAE,CAAC,CAAC;IACnD,MAAM,CAAC,UAAU,EAAE,aAAa,CAAC,GAAG,QAAQ,CAAC,KAAK,CAAC,CAAC;IACpD,MAAM,CAAC,cAAc,EAAE,iBAAiB,CAAC,GAAG,QAAQ,CAAW,GAAG,EAAE,CAClE,OAAO,MAAM,KAAK,WAAW,CAAC,CAAC,CAAC,aAAa,EAAE,CAAC,CAAC,CAAC,EAAE,CACrD,CAAC;IACF,MAAM,CAAC,UAAU,EAAE,aAAa,CAAC,GAAG,QAAQ,CAAgB,IAAI,CAAC,CAAC;IAClE,MAAM,CAAC,UAAU,EAAE,aAAa,CAAC,GAAG,QAAQ,CAAgB,IAAI,CAAC,CAAC;IAElE,MAAM,EAAE,IAAI,EAAE,UAAU,EAAE,SAAS,EAAE,GAAG,QAAQ,CAAc;QAC5D,QAAQ,EAAE,CAAC,YAAY,CAAC;QACxB,OAAO,EAAE,KAAK,IAAI,EAAE;YAClB,MAAM,GAAG,GAAG,MAAM,KAAK,CAAC,eAAe,CAAC,2BAA2B,CAAC,CAAC,CAAC;YACtE,IAAI,CAAC,GAAG,CAAC,EAAE;gBAAE,OAAO,EAAE,CAAC;YACvB,OAAO,GAAG,CAAC,IAAI,EAAE,CAAC;QACpB,CAAC;KACF,CAAC,CAAC;IAEH,MAAM,cAAc,GAAG,WAAW,CAAC,CAAC,EAAU,EAAE,EAAE;QAChD,cAAc,CAAC,CAAC,IAAI,EAAE,EAAE;YACtB,MAAM,IAAI,GAAG,IAAI,GAAG,CAAC,IAAI,CAAC,CAAC;YAC3B,IAAI,IAAI,CAAC,GAAG,CAAC,EAAE,CAAC,EAAE,CAAC;gBACjB,IAAI,CAAC,MAAM,CAAC,EAAE,CAAC,CAAC;YAClB,CAAC;iBAAM,CAAC;gBACN,IAAI,CAAC,GAAG,CAAC,EAAE,CAAC,CAAC;YACf,CAAC;YACD,aAAa,CAAC,IAAI,CAAC,CAAC;YACpB,OAAO,IAAI,CAAC;QACd,CAAC,CAAC,CAAC;IACL,CAAC,EAAE,EAAE,CAAC,CAAC;IAEP,MAAM,YAAY,GAAG,WAAW,CAC9B,KAAK,EAAE,WAAmB,EAAE,EAAE;QAC5B,aAAa,CAAC,IAAI,CAAC,CAAC;QACpB,MAAM,IAAI,GAAG,WAAW,CAAC,YAAY,CAAc,CAAC,YAAY,CAAC,CAAC,CAAC;QACnE,WAAW,CAAC,YAAY,CAAc,CAAC,YAAY,CAAC,EAAE,CAAC,GAAG,EAAE,EAAE,CAC5D,CAAC,GAAG,IAAI,EAAE,CAAC,CAAC,MAAM,CAAC,CAAC,CAAC,EAAE,EAAE,CAAC,CAAC,CAAC,EAAE,KAAK,WAAW,CAAC,CAChD,CAAC;QACF,IAAI,CAAC;YACH,MAAM,GAAG,GAAG,MAAM,KAAK,CACrB,eAAe,CAAC,6BAA6B,WAAW,EAAE,CAAC,EAC3D;gBACE,MAAM,EAAE,QAAQ;aACjB,CACF,CAAC;YACF,IAAI,CAAC,GAAG,CAAC,EAAE;gBAAE,MAAM,IAAI,KAAK,CAAC,eAAe,CAAC,CAAC;YAC9C,WAAW,CAAC,aAAa,CAAC,EAAE,QAAQ,EAAE,CAAC,WAAW,EAAE,WAAW,CAAC,EAAE,CAAC,CAAC;YACpE,WAAW,CAAC,iBAAiB,CAAC,EAAE,QAAQ,EAAE,CAAC,YAAY,CAAC,EAAE,CAAC,CAAC;YAC5D,cAAc,CAAC,CAAC,IAAI,EAAE,EAAE;gBACtB,MAAM,IAAI,GAAG,IAAI,GAAG,CAAC,IAAI,CAAC,CAAC;gBAC3B,IAAI,CAAC,MAAM,CAAC,WAAW,CAAC,CAAC;gBACzB,aAAa,CAAC,IAAI,CAAC,CAAC;gBACpB,OAAO,IAAI,CAAC;YACd,CAAC,CAAC,CAAC;YACH,iBAAiB,CAAC,CAAC,IAAI,EAAE,EAAE;gBACzB,MAAM,IAAI,GAAG,IAAI,CAAC,MAAM,CAAC,CAAC,EAAE,EAAE,EAAE,CAAC,EAAE,KAAK,WAAW,CAAC,CAAC;gBACrD,IAAI,IAAI,CAAC,MAAM,KAAK,IAAI,CAAC,MAAM;oBAAE,aAAa,CAAC,IAAI,CAAC,CAAC;gBACrD,OAAO,IAAI,CAAC;YACd,CAAC,CAAC,CAAC;YACH,IACE,QAAQ,CAAC,QAAQ,KAAK,eAAe,WAAW,EAAE;gBAClD,QAAQ,CAAC,QAAQ,KAAK,eAAe,WAAW,OAAO,EACvD,CAAC;gBACD,QAAQ,CAAC,aAAa,CAAC,CAAC;YAC1B,CAAC;QACH,CAAC;QAAC,MAAM,CAAC;YACP,IAAI,IAAI;gBAAE,WAAW,CAAC,YAAY,CAAC,CAAC,YAAY,CAAC,EAAE,IAAI,CAAC,CAAC;QAC3D,CAAC;IACH,CAAC,EACD,CAAC,QAAQ,CAAC,QAAQ,EAAE,QAAQ,EAAE,WAAW,CAAC,CAC3C,CAAC;IAEF,MAAM,WAAW,GAAG,WAAW,CAAC,CAAC,SAAoB,EAAE,EAAE;QACvD,aAAa,CAAC,IAAI,CAAC,CAAC;QACpB,cAAc,CAAC,SAAS,CAAC,IAAI,CAAC,CAAC;QAC/B,aAAa,CAAC,SAAS,CAAC,EAAE,CAAC,CAAC;IAC9B,CAAC,EAAE,EAAE,CAAC,CAAC;IAEP,MAAM,YAAY,GAAG,WAAW,CAC9B,KAAK,EAAE,WAAmB,EAAE,EAAE;QAC5B,MAAM,OAAO,GAAG,WAAW,CAAC,IAAI,EAAE,CAAC;QACnC,aAAa,CAAC,IAAI,CAAC,CAAC;QACpB,IAAI,CAAC,OAAO;YAAE,OAAO;QACrB,MAAM,IAAI,GAAG,WAAW,CAAC,YAAY,CAAc,CAAC,YAAY,CAAC,CAAC,CAAC;QACnE,MAAM,QAAQ,GAAG,IAAI,EAAE,IAAI,CAAC,CAAC,CAAC,EAAE,EAAE,CAAC,CAAC,CAAC,EAAE,KAAK,WAAW,CAAC,CAAC;QACzD,IAAI,CAAC,QAAQ,IAAI,OAAO,KAAK,QAAQ,CAAC,IAAI;YAAE,OAAO;QACnD,WAAW,CAAC,YAAY,CAAc,CAAC,YAAY,CAAC,EAAE,CAAC,GAAG,EAAE,EAAE,CAC5D,CAAC,GAAG,IAAI,EAAE,CAAC,CAAC,GAAG,CAAC,CAAC,CAAC,EAAE,EAAE,CACpB,CAAC,CAAC,EAAE,KAAK,WAAW,CAAC,CAAC,CAAC,EAAE,GAAG,CAAC,EAAE,IAAI,EAAE,OAAO,EAAE,CAAC,CAAC,CAAC,CAAC,CACnD,CACF,CAAC;QACF,WAAW,CAAC,YAAY,CAAY,CAAC,WAAW,EAAE,WAAW,CAAC,EAAE,CAAC,GAAG,EAAE,EAAE,CACtE,GAAG,CAAC,CAAC,CAAC,EAAE,GAAG,GAAG,EAAE,IAAI,EAAE,OAAO,EAAE,CAAC,CAAC,CAAC,GAAG,CACtC,CAAC;QACF,IAAI,CAAC;YACH,MAAM,KAAK,CACT,eAAe,CAAC,6BAA6B,WAAW,EAAE,CAAC,EAC3D;gBACE,MAAM,EAAE,KAAK;gBACb,OAAO,EAAE,EAAE,cAAc,EAAE,kBAAkB,EAAE;gBAC/C,IAAI,EAAE,IAAI,CAAC,SAAS,CAAC,EAAE,IAAI,EAAE,OAAO,EAAE,CAAC;aACxC,CACF,CAAC;YACF,WAAW,CAAC,iBAAiB,CAAC,EAAE,QAAQ,EAAE,CAAC,YAAY,CAAC,EAAE,CAAC,CAAC;YAC5D,WAAW,CAAC,iBAAiB,CAAC,EAAE,QAAQ,EAAE,CAAC,WAAW,EAAE,WAAW,CAAC,EAAE,CAAC,CAAC;QAC1E,CAAC;QAAC,MAAM,CAAC;YACP,IAAI,IAAI;gBAAE,WAAW,CAAC,YAAY,CAAC,CAAC,YAAY,CAAC,EAAE,IAAI,CAAC,CAAC;YACzD,WAAW,CAAC,iBAAiB,CAAC,EAAE,QAAQ,EAAE,CAAC,WAAW,EAAE,WAAW,CAAC,EAAE,CAAC,CAAC;QAC1E,CAAC;IACH,CAAC,EACD,CAAC,WAAW,EAAE,WAAW,CAAC,CAC3B,CAAC;IAEF,MAAM,WAAW,GAAG,OAAO,CAAC,GAAG,EAAE;QAC/B,IAAI,CAAC,UAAU;YAAE,OAAO,EAAE,CAAC;QAC3B,MAAM,aAAa,GAAG,CAAC,GAAG,UAAU,CAAC,CAAC,IAAI,CAAC,CAAC,CAAC,EAAE,CAAC,EAAE,EAAE;YAClD,MAAM,IAAI,GAAG,WAAW,CAAC,GAAG,CAAC,CAAC,CAAC,EAAE,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC;YAC3C,MAAM,IAAI,GAAG,WAAW,CAAC,GAAG,CAAC,CAAC,CAAC,EAAE,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC;YAC3C,IAAI,IAAI,KAAK,IAAI;gBAAE,OAAO,IAAI,GAAG,IAAI,CAAC;YACtC,OAAO,CAAC,CAAC,IAAI,CAAC,aAAa,CAAC,CAAC,CAAC,IAAI,CAAC,CAAC;QACtC,CAAC,CAAC,CAAC;QACH,OAAO,cAAc,CAAC,MAAM,GAAG,CAAC;YAC9B,CAAC,CAAC,eAAe,CAAC,aAAa,EAAE,cAAc,CAAC;YAChD,CAAC,CAAC,aAAa,CAAC;IACpB,CAAC,EAAE,CAAC,UAAU,EAAE,WAAW,EAAE,cAAc,CAAC,CAAC,CAAC;IAE9C,MAAM,WAAW,GAAG,WAAW,CAC7B,CAAC,QAAgB,EAAE,MAAc,EAAE,EAAE;QACnC,IAAI,QAAQ,KAAK,MAAM;YAAE,OAAO;QAChC,MAAM,GAAG,GAAG,WAAW,CAAC,GAAG,CAAC,CAAC,SAAS,EAAE,EAAE,CAAC,SAAS,CAAC,EAAE,CAAC,CAAC;QACzD,MAAM,QAAQ,GAAG,GAAG,CAAC,OAAO,CAAC,QAAQ,CAAC,CAAC;QACvC,MAAM,QAAQ,GAAG,GAAG,CAAC,OAAO,CAAC,MAAM,CAAC,CAAC;QACrC,IAAI,QAAQ,KAAK,CAAC,CAAC,IAAI,QAAQ,KAAK,CAAC,CAAC;YAAE,OAAO;QAC/C,MAAM,IAAI,GAAG,CAAC,GAAG,GAAG,CAAC,CAAC;QACtB,MAAM,CAAC,KAAK,CAAC,GAAG,IAAI,CAAC,MAAM,CAAC,QAAQ,EAAE,CAAC,CAAC,CAAC;QACzC,IAAI,CAAC,KAAK;YAAE,OAAO;QACnB,IAAI,CAAC,MAAM,CAAC,QAAQ,EAAE,CAAC,EAAE,KAAK,CAAC,CAAC;QAChC,aAAa,CAAC,IAAI,CAAC,CAAC;QACpB,iBAAiB,CAAC,IAAI,CAAC,CAAC;IAC1B,CAAC,EACD,CAAC,WAAW,CAAC,CACd,CAAC;IAEF,MAAM,YAAY,GAAG,CAAC,IAAY,EAAE,EAAE;QACpC,MAAM,OAAO,GAAG,IAAI,CAAC,IAAI,EAAE,CAAC;QAC5B,IAAI,CAAC,OAAO;YAAE,OAAO;QACrB,eAAe,CAAC;YACd,OAAO,EAAE,wBAAwB,OAAO,EAAE;YAC1C,MAAM,EAAE,IAAI;YACZ,WAAW,EAAE,IAAI;YACjB,MAAM,EAAE,IAAI;SACb,CAAC,CAAC;QACH,aAAa,CAAC,KAAK,CAAC,CAAC;IACvB,CAAC,CAAC;IAEF,OAAO,CACL,KAAC,eAAe,IAAC,aAAa,EAAE,GAAG,YACjC,eAAK,SAAS,EAAC,kCAAkC,aAC/C,eACE,SAAS,EAAE,EAAE,CACX,wCAAwC,EACxC,WAAW,CAAC,MAAM,GAAG,CAAC,IAAI,MAAM,CACjC,aAED,gBAAM,SAAS,EAAC,uGAAuG,2BAErH,YACE,IAAI,EAAC,0CAA0C,EAC/C,MAAM,EAAC,QAAQ,EACf,GAAG,EAAC,qBAAqB,EACzB,SAAS,EAAC,gHAAgH,gBAC/G,0BAA0B,YAErC,KAAC,cAAc,IAAC,SAAS,EAAC,SAAS,GAAG,GACpC,IACC,EACP,MAAC,OAAO,IAAC,IAAI,EAAE,UAAU,EAAE,YAAY,EAAE,aAAa,aACpD,KAAC,cAAc,IAAC,OAAO,kBACrB,iBACE,IAAI,EAAC,QAAQ,EACb,SAAS,EAAC,2IAA2I,gBAC1I,eAAe,YAE1B,KAAC,QAAQ,IAAC,SAAS,EAAC,aAAa,GAAG,GAC7B,GACM,EACjB,MAAC,cAAc,IACb,IAAI,EAAC,OAAO,EACZ,KAAK,EAAC,OAAO,EACb,SAAS,EAAC,eAAe,aAEzB,YAAG,SAAS,EAAC,iDAAiD,8BAE1D,EACJ,KAAC,cAAc,IACb,SAAS,QACT,WAAW,EAAC,sCAAsC,EAClD,UAAU,EAAC,2BAA2B,EACtC,QAAQ,EAAE,YAAY,GACtB,IACa,IACT,IACN,EAEL,SAAS,CAAC,CAAC,CAAC,CACX,cAAK,SAAS,EAAC,0BAA0B,YACtC,CAAC,CAAC,EAAE,CAAC,EAAE,CAAC,CAAC,CAAC,GAAG,CAAC,CAAC,CAAC,EAAE,EAAE,CAAC,CACpB,cAAa,SAAS,EAAC,0CAA0C,YAC/D,cACE,SAAS,EAAC,oCAAoC,EAC9C,KAAK,EAAE,EAAE,KAAK,EAAE,GAAG,EAAE,GAAG,CAAC,GAAG,EAAE,IAAI,EAAE,GACpC,IAJM,CAAC,CAKL,CACP,CAAC,GACE,CACP,CAAC,CAAC,CAAC,WAAW,CAAC,MAAM,KAAK,CAAC,CAAC,CAAC,CAAC,IAAI,CAAC,CAAC,CAAC,CACpC,cAAK,SAAS,EAAC,0BAA0B,YACtC,WAAW,CAAC,GAAG,CAAC,CAAC,SAAS,EAAE,EAAE;wBAC7B,MAAM,QAAQ,GACZ,QAAQ,CAAC,QAAQ,KAAK,eAAe,SAAS,CAAC,EAAE,EAAE;4BACnD,QAAQ,CAAC,QAAQ,KAAK,eAAe,SAAS,CAAC,EAAE,OAAO,CAAC;wBAC3D,MAAM,KAAK,GAAG,WAAW,CAAC,GAAG,CAAC,SAAS,CAAC,EAAE,CAAC,CAAC;wBAC5C,MAAM,cAAc,GAAG,UAAU,KAAK,SAAS,CAAC,EAAE,CAAC;wBACnD,MAAM,cAAc,GAClB,UAAU,KAAK,SAAS,CAAC,EAAE,IAAI,cAAc,CAAC;wBAEhD,OAAO,CACL,eAEE,UAAU,EAAE,CAAC,CAAC,EAAE,EAAE;gCAChB,IAAI,CAAC,UAAU,IAAI,UAAU,KAAK,SAAS,CAAC,EAAE;oCAAE,OAAO;gCACvD,CAAC,CAAC,cAAc,EAAE,CAAC;gCACnB,CAAC,CAAC,YAAY,CAAC,UAAU,GAAG,MAAM,CAAC;gCACnC,aAAa,CAAC,SAAS,CAAC,EAAE,CAAC,CAAC;4BAC9B,CAAC,EACD,WAAW,EAAE,GAAG,EAAE;gCAChB,aAAa,CAAC,CAAC,OAAO,EAAE,EAAE,CACxB,OAAO,KAAK,SAAS,CAAC,EAAE,CAAC,CAAC,CAAC,IAAI,CAAC,CAAC,CAAC,OAAO,CAC1C,CAAC;4BACJ,CAAC,EACD,MAAM,EAAE,CAAC,CAAC,EAAE,EAAE;gCACZ,CAAC,CAAC,cAAc,EAAE,CAAC;gCACnB,MAAM,QAAQ,GACZ,UAAU,IAAI,CAAC,CAAC,YAAY,CAAC,OAAO,CAAC,YAAY,CAAC,CAAC;gCACrD,aAAa,CAAC,IAAI,CAAC,CAAC;gCACpB,aAAa,CAAC,IAAI,CAAC,CAAC;gCACpB,IAAI,QAAQ;oCAAE,WAAW,CAAC,QAAQ,EAAE,SAAS,CAAC,EAAE,CAAC,CAAC;4BACpD,CAAC,EACD,SAAS,EAAE,EAAE,CACX,+DAA+D,EAC/D,UAAU,KAAK,SAAS,CAAC,EAAE,IAAI,YAAY,EAC3C,UAAU,KAAK,SAAS,CAAC,EAAE;gCACzB,UAAU,KAAK,SAAS,CAAC,EAAE;gCAC3B,cAAc,CACjB,aAED,MAAC,OAAO,eACN,KAAC,cAAc,IAAC,OAAO,kBACrB,iBACE,IAAI,EAAC,QAAQ,EACb,SAAS,QACT,WAAW,EAAE,CAAC,CAAC,EAAE,EAAE;oDACjB,aAAa,CAAC,SAAS,CAAC,EAAE,CAAC,CAAC;oDAC5B,aAAa,CAAC,IAAI,CAAC,CAAC;oDACpB,CAAC,CAAC,YAAY,CAAC,aAAa,GAAG,MAAM,CAAC;oDACtC,CAAC,CAAC,YAAY,CAAC,OAAO,CAAC,YAAY,EAAE,SAAS,CAAC,EAAE,CAAC,CAAC;gDACrD,CAAC,EACD,SAAS,EAAE,GAAG,EAAE;oDACd,aAAa,CAAC,IAAI,CAAC,CAAC;oDACpB,aAAa,CAAC,IAAI,CAAC,CAAC;gDACtB,CAAC,EACD,SAAS,EAAC,uNAAuN,gBACrN,WAAW,SAAS,CAAC,IAAI,EAAE,YAEvC,KAAC,gBAAgB,IAAC,SAAS,EAAC,SAAS,GAAG,GACjC,GACM,EACjB,KAAC,cAAc,kCAAiC,IACxC,EACV,KAAC,IAAI,IACH,EAAE,EAAE,eAAe,SAAS,CAAC,EAAE,EAAE,EACjC,SAAS,EAAE,EAAE,CACX,gMAAgM,EAChM,cAAc,IAAI,UAAU,EAC5B,QAAQ;wCACN,CAAC,CAAC,8CAA8C;wCAChD,CAAC,CAAC,uEAAuE,CAC5E,YAEA,cAAc,CAAC,CAAC,CAAC,CAChB,gBACE,SAAS,QACT,KAAK,EAAE,WAAW,EAClB,QAAQ,EAAE,CAAC,CAAC,EAAE,EAAE,CAAC,cAAc,CAAC,CAAC,CAAC,MAAM,CAAC,KAAK,CAAC,EAC/C,MAAM,EAAE,GAAG,EAAE,CAAC,YAAY,CAAC,SAAS,CAAC,EAAE,CAAC,EACxC,SAAS,EAAE,CAAC,CAAC,EAAE,EAAE;4CACf,IAAI,CAAC,CAAC,GAAG,KAAK,OAAO;gDAAE,YAAY,CAAC,SAAS,CAAC,EAAE,CAAC,CAAC;4CAClD,IAAI,CAAC,CAAC,GAAG,KAAK,QAAQ;gDAAE,aAAa,CAAC,IAAI,CAAC,CAAC;wCAC9C,CAAC,EACD,OAAO,EAAE,CAAC,CAAC,EAAE,EAAE;4CACb,CAAC,CAAC,cAAc,EAAE,CAAC;4CACnB,CAAC,CAAC,eAAe,EAAE,CAAC;wCACtB,CAAC,EACD,SAAS,EAAC,+FAA+F,GACzG,CACH,CAAC,CAAC,CAAC,CACF,eAAM,SAAS,EAAC,gBAAgB,YAAE,SAAS,CAAC,IAAI,GAAQ,CACzD,GACI,EAEP,eACE,SAAS,EAAE,EAAE,CACX,sNAAsN,EACtN,cAAc,IAAI,gBAAgB,CACnC,aAED,iBACE,IAAI,EAAC,QAAQ,EACb,OAAO,EAAE,CAAC,CAAC,EAAE,EAAE;gDACb,CAAC,CAAC,cAAc,EAAE,CAAC;gDACnB,CAAC,CAAC,eAAe,EAAE,CAAC;gDACpB,cAAc,CAAC,SAAS,CAAC,EAAE,CAAC,CAAC;4CAC/B,CAAC,EACD,SAAS,EAAE,EAAE,CACX,oEAAoE,EACpE,KAAK;gDACH,CAAC,CAAC,iBAAiB;gDACnB,CAAC,CAAC,gDAAgD,CACrD,gBACW,KAAK,CAAC,CAAC,CAAC,YAAY,CAAC,CAAC,CAAC,UAAU,YAE5C,KAAK,CAAC,CAAC,CAAC,CACP,KAAC,cAAc,IAAC,SAAS,EAAC,SAAS,GAAG,CACvC,CAAC,CAAC,CAAC,CACF,KAAC,QAAQ,IAAC,SAAS,EAAC,SAAS,GAAG,CACjC,GACM,EAET,MAAC,YAAY,IACX,IAAI,EAAE,UAAU,KAAK,SAAS,CAAC,EAAE,EACjC,YAAY,EAAE,CAAC,IAAI,EAAE,EAAE,CACrB,aAAa,CAAC,IAAI,CAAC,CAAC,CAAC,SAAS,CAAC,EAAE,CAAC,CAAC,CAAC,IAAI,CAAC,aAG3C,KAAC,mBAAmB,IAAC,OAAO,kBAC1B,iBACE,IAAI,EAAC,QAAQ,EACb,SAAS,EAAC,mHAAmH,gBAClH,mBAAmB,YAE9B,KAAC,QAAQ,IAAC,SAAS,EAAC,SAAS,GAAG,GACzB,GACW,EACtB,MAAC,mBAAmB,IAClB,KAAK,EAAC,KAAK,EACX,UAAU,EAAE,CAAC,EACb,SAAS,EAAC,eAAe,aAEzB,MAAC,gBAAgB,IACf,QAAQ,EAAE,GAAG,EAAE,CAAC,WAAW,CAAC,SAAS,CAAC,aAEtC,KAAC,UAAU,IAAC,SAAS,EAAC,aAAa,GAAG,cAErB,EACnB,MAAC,gBAAgB,IACf,QAAQ,EAAE,GAAG,EAAE,CAAC,YAAY,CAAC,SAAS,CAAC,EAAE,CAAC,EAC1C,SAAS,EAAC,yCAAyC,aAEnD,KAAC,SAAS,IAAC,SAAS,EAAC,aAAa,GAAG,cAEpB,IACC,IACT,IACX,KAjJD,SAAS,CAAC,EAAE,CAkJb,CACP,CAAC;oBACJ,CAAC,CAAC,GACE,CACP,IACG,GACU,CACnB,CAAC;AACJ,CAAC","sourcesContent":["import { agentNativePath } from \"../api-path.js\";\nimport { useState, useCallback, useMemo } from \"react\";\nimport { useQuery, useQueryClient } from \"@tanstack/react-query\";\nimport { Link, useLocation, useNavigate } from \"react-router\";\nimport {\n IconPlus,\n IconStar,\n IconStarFilled,\n IconTrash,\n IconDots,\n IconHelpCircle,\n IconPencil,\n IconGripVertical,\n} from \"@tabler/icons-react\";\nimport { cn } from \"../utils.js\";\nimport { sendToAgentChat } from \"../agent-chat.js\";\nimport { PromptComposer } from \"../composer/PromptComposer.js\";\nimport {\n Popover,\n PopoverContent,\n PopoverTrigger,\n} from \"../components/ui/popover.js\";\nimport {\n DropdownMenu,\n DropdownMenuContent,\n DropdownMenuItem,\n DropdownMenuTrigger,\n} from \"../components/ui/dropdown-menu.js\";\nimport {\n applyToolsOrder,\n getToolsOrder,\n setToolsOrder,\n} from \"./extension-order.js\";\nimport {\n Tooltip,\n TooltipContent,\n TooltipProvider,\n TooltipTrigger,\n} from \"../components/ui/tooltip.js\";\n\ninterface Extension {\n id: string;\n name: string;\n description?: string;\n icon?: string;\n}\n\nconst FAVORITES_KEY = \"extensions-favorites\";\n\nfunction getFavorites(): Set<string> {\n try {\n const raw = localStorage.getItem(FAVORITES_KEY);\n if (!raw) return new Set();\n const parsed = JSON.parse(raw);\n return new Set(Array.isArray(parsed) ? parsed : []);\n } catch {\n return new Set();\n }\n}\n\nfunction saveFavorites(ids: Set<string>) {\n try {\n localStorage.setItem(FAVORITES_KEY, JSON.stringify(Array.from(ids)));\n } catch {\n // localStorage unavailable — ignore\n }\n}\n\nexport function ExtensionsSidebarSection() {\n const location = useLocation();\n const navigate = useNavigate();\n const queryClient = useQueryClient();\n const [favoriteIds, setFavoriteIds] = useState<Set<string>>(() =>\n typeof window !== \"undefined\" ? getFavorites() : new Set(),\n );\n const [menuOpenId, setMenuOpenId] = useState<string | null>(null);\n const [renamingId, setRenamingId] = useState<string | null>(null);\n const [renameValue, setRenameValue] = useState(\"\");\n const [showCreate, setShowCreate] = useState(false);\n const [toolOrderState, setToolOrderState] = useState<string[]>(() =>\n typeof window !== \"undefined\" ? getToolsOrder() : [],\n );\n const [draggingId, setDraggingId] = useState<string | null>(null);\n const [dragOverId, setDragOverId] = useState<string | null>(null);\n\n const { data: extensions, isLoading } = useQuery<Extension[]>({\n queryKey: [\"extensions\"],\n queryFn: async () => {\n const res = await fetch(agentNativePath(\"/_agent-native/extensions\"));\n if (!res.ok) return [];\n return res.json();\n },\n });\n\n const toggleFavorite = useCallback((id: string) => {\n setFavoriteIds((prev) => {\n const next = new Set(prev);\n if (next.has(id)) {\n next.delete(id);\n } else {\n next.add(id);\n }\n saveFavorites(next);\n return next;\n });\n }, []);\n\n const handleDelete = useCallback(\n async (extensionId: string) => {\n setMenuOpenId(null);\n const prev = queryClient.getQueryData<Extension[]>([\"extensions\"]);\n queryClient.setQueryData<Extension[]>([\"extensions\"], (old) =>\n (old ?? []).filter((t) => t.id !== extensionId),\n );\n try {\n const res = await fetch(\n agentNativePath(`/_agent-native/extensions/${extensionId}`),\n {\n method: \"DELETE\",\n },\n );\n if (!res.ok) throw new Error(\"Delete failed\");\n queryClient.removeQueries({ queryKey: [\"extension\", extensionId] });\n queryClient.invalidateQueries({ queryKey: [\"extensions\"] });\n setFavoriteIds((prev) => {\n const next = new Set(prev);\n next.delete(extensionId);\n saveFavorites(next);\n return next;\n });\n setToolOrderState((prev) => {\n const next = prev.filter((id) => id !== extensionId);\n if (next.length !== prev.length) setToolsOrder(next);\n return next;\n });\n if (\n location.pathname === `/extensions/${extensionId}` ||\n location.pathname === `/extensions/${extensionId}/edit`\n ) {\n navigate(\"/extensions\");\n }\n } catch {\n if (prev) queryClient.setQueryData([\"extensions\"], prev);\n }\n },\n [location.pathname, navigate, queryClient],\n );\n\n const startRename = useCallback((extension: Extension) => {\n setMenuOpenId(null);\n setRenameValue(extension.name);\n setRenamingId(extension.id);\n }, []);\n\n const submitRename = useCallback(\n async (extensionId: string) => {\n const trimmed = renameValue.trim();\n setRenamingId(null);\n if (!trimmed) return;\n const prev = queryClient.getQueryData<Extension[]>([\"extensions\"]);\n const existing = prev?.find((t) => t.id === extensionId);\n if (!existing || trimmed === existing.name) return;\n queryClient.setQueryData<Extension[]>([\"extensions\"], (old) =>\n (old ?? []).map((t) =>\n t.id === extensionId ? { ...t, name: trimmed } : t,\n ),\n );\n queryClient.setQueryData<Extension>([\"extension\", extensionId], (old) =>\n old ? { ...old, name: trimmed } : old,\n );\n try {\n await fetch(\n agentNativePath(`/_agent-native/extensions/${extensionId}`),\n {\n method: \"PUT\",\n headers: { \"Content-Type\": \"application/json\" },\n body: JSON.stringify({ name: trimmed }),\n },\n );\n queryClient.invalidateQueries({ queryKey: [\"extensions\"] });\n queryClient.invalidateQueries({ queryKey: [\"extension\", extensionId] });\n } catch {\n if (prev) queryClient.setQueryData([\"extensions\"], prev);\n queryClient.invalidateQueries({ queryKey: [\"extension\", extensionId] });\n }\n },\n [renameValue, queryClient],\n );\n\n const sortedTools = useMemo(() => {\n if (!extensions) return [];\n const defaultSorted = [...extensions].sort((a, b) => {\n const aFav = favoriteIds.has(a.id) ? 0 : 1;\n const bFav = favoriteIds.has(b.id) ? 0 : 1;\n if (aFav !== bFav) return aFav - bFav;\n return a.name.localeCompare(b.name);\n });\n return toolOrderState.length > 0\n ? applyToolsOrder(defaultSorted, toolOrderState)\n : defaultSorted;\n }, [extensions, favoriteIds, toolOrderState]);\n\n const reorderTool = useCallback(\n (activeId: string, overId: string) => {\n if (activeId === overId) return;\n const ids = sortedTools.map((extension) => extension.id);\n const oldIndex = ids.indexOf(activeId);\n const newIndex = ids.indexOf(overId);\n if (oldIndex === -1 || newIndex === -1) return;\n const next = [...ids];\n const [moved] = next.splice(oldIndex, 1);\n if (!moved) return;\n next.splice(newIndex, 0, moved);\n setToolsOrder(next);\n setToolOrderState(next);\n },\n [sortedTools],\n );\n\n const handleCreate = (text: string) => {\n const trimmed = text.trim();\n if (!trimmed) return;\n sendToAgentChat({\n message: `Create an extension: ${trimmed}`,\n submit: true,\n openSidebar: true,\n newTab: true,\n });\n setShowCreate(false);\n };\n\n return (\n <TooltipProvider delayDuration={200}>\n <div className=\"group/help relative min-w-0 py-2\">\n <div\n className={cn(\n \"flex items-center justify-between px-3\",\n sortedTools.length > 0 && \"mb-1\",\n )}\n >\n <span className=\"inline-flex items-center gap-1.5 text-xs font-semibold uppercase tracking-wider text-muted-foreground\">\n Extensions\n <a\n href=\"https://agent-native.com/docs/extensions\"\n target=\"_blank\"\n rel=\"noopener noreferrer\"\n className=\"opacity-0 group-hover/help:opacity-100 transition-opacity text-muted-foreground/50 hover:text-muted-foreground\"\n aria-label=\"Extensions documentation\"\n >\n <IconHelpCircle className=\"h-3 w-3\" />\n </a>\n </span>\n <Popover open={showCreate} onOpenChange={setShowCreate}>\n <PopoverTrigger asChild>\n <button\n type=\"button\"\n className=\"inline-flex h-5 w-5 cursor-pointer items-center justify-center rounded text-muted-foreground hover:bg-accent hover:text-accent-foreground\"\n aria-label=\"New extension\"\n >\n <IconPlus className=\"h-3.5 w-3.5\" />\n </button>\n </PopoverTrigger>\n <PopoverContent\n side=\"right\"\n align=\"start\"\n className=\"w-[420px] p-3\"\n >\n <p className=\"px-1 pb-2 text-sm font-semibold text-foreground\">\n New extension\n </p>\n <PromptComposer\n autoFocus\n placeholder=\"Describe what you'd like to build...\"\n draftScope=\"extensions:sidebar-create\"\n onSubmit={handleCreate}\n />\n </PopoverContent>\n </Popover>\n </div>\n\n {isLoading ? (\n <div className=\"min-w-0 space-y-0.5 px-1\">\n {[1, 2, 3].map((i) => (\n <div key={i} className=\"flex items-center rounded-md px-2 py-1.5\">\n <div\n className=\"h-3 rounded bg-muted animate-pulse\"\n style={{ width: `${60 + i * 20}px` }}\n />\n </div>\n ))}\n </div>\n ) : sortedTools.length === 0 ? null : (\n <div className=\"min-w-0 space-y-0.5 px-1\">\n {sortedTools.map((extension) => {\n const isActive =\n location.pathname === `/extensions/${extension.id}` ||\n location.pathname === `/extensions/${extension.id}/edit`;\n const isFav = favoriteIds.has(extension.id);\n const isRenamingThis = renamingId === extension.id;\n const actionsVisible =\n menuOpenId === extension.id || isRenamingThis;\n\n return (\n <div\n key={extension.id}\n onDragOver={(e) => {\n if (!draggingId || draggingId === extension.id) return;\n e.preventDefault();\n e.dataTransfer.dropEffect = \"move\";\n setDragOverId(extension.id);\n }}\n onDragLeave={() => {\n setDragOverId((current) =>\n current === extension.id ? null : current,\n );\n }}\n onDrop={(e) => {\n e.preventDefault();\n const activeId =\n draggingId || e.dataTransfer.getData(\"text/plain\");\n setDraggingId(null);\n setDragOverId(null);\n if (activeId) reorderTool(activeId, extension.id);\n }}\n className={cn(\n \"group/extension relative flex items-center min-w-0 rounded-md\",\n draggingId === extension.id && \"opacity-50\",\n dragOverId === extension.id &&\n draggingId !== extension.id &&\n \"bg-accent/60\",\n )}\n >\n <Tooltip>\n <TooltipTrigger asChild>\n <button\n type=\"button\"\n draggable\n onDragStart={(e) => {\n setDraggingId(extension.id);\n setDragOverId(null);\n e.dataTransfer.effectAllowed = \"move\";\n e.dataTransfer.setData(\"text/plain\", extension.id);\n }}\n onDragEnd={() => {\n setDraggingId(null);\n setDragOverId(null);\n }}\n className=\"-ml-2 cursor-grab rounded p-0.5 text-muted-foreground/30 opacity-0 transition-colors hover:text-muted-foreground/70 active:cursor-grabbing group-hover/extension:opacity-100 group-focus-within/extension:opacity-100\"\n aria-label={`Reorder ${extension.name}`}\n >\n <IconGripVertical className=\"h-3 w-3\" />\n </button>\n </TooltipTrigger>\n <TooltipContent>Drag to reorder</TooltipContent>\n </Tooltip>\n <Link\n to={`/extensions/${extension.id}`}\n className={cn(\n \"flex min-w-0 flex-1 items-center rounded-md px-2 py-1.5 pr-12 text-xs transition-[padding,color,background-color] md:pr-2 md:group-hover/extension:pr-12 md:group-focus-within/extension:pr-12\",\n actionsVisible && \"md:pr-12\",\n isActive\n ? \"bg-accent text-accent-foreground font-medium\"\n : \"text-muted-foreground hover:bg-accent/50 hover:text-accent-foreground\",\n )}\n >\n {isRenamingThis ? (\n <input\n autoFocus\n value={renameValue}\n onChange={(e) => setRenameValue(e.target.value)}\n onBlur={() => submitRename(extension.id)}\n onKeyDown={(e) => {\n if (e.key === \"Enter\") submitRename(extension.id);\n if (e.key === \"Escape\") setRenamingId(null);\n }}\n onClick={(e) => {\n e.preventDefault();\n e.stopPropagation();\n }}\n className=\"min-w-0 flex-1 truncate border-b border-primary bg-transparent px-0 py-0 text-xs outline-none\"\n />\n ) : (\n <span className=\"block truncate\">{extension.name}</span>\n )}\n </Link>\n\n <div\n className={cn(\n \"pointer-events-none absolute right-1 top-1/2 flex -translate-y-1/2 items-center gap-0.5 opacity-100 transition-opacity md:opacity-0 md:group-hover/extension:opacity-100 md:group-focus-within/extension:opacity-100\",\n actionsVisible && \"md:opacity-100\",\n )}\n >\n <button\n type=\"button\"\n onClick={(e) => {\n e.preventDefault();\n e.stopPropagation();\n toggleFavorite(extension.id);\n }}\n className={cn(\n \"pointer-events-auto cursor-pointer rounded p-0.5 transition-colors\",\n isFav\n ? \"text-yellow-500\"\n : \"text-muted-foreground/40 hover:text-yellow-500\",\n )}\n aria-label={isFav ? \"Unfavorite\" : \"Favorite\"}\n >\n {isFav ? (\n <IconStarFilled className=\"h-3 w-3\" />\n ) : (\n <IconStar className=\"h-3 w-3\" />\n )}\n </button>\n\n <DropdownMenu\n open={menuOpenId === extension.id}\n onOpenChange={(open) =>\n setMenuOpenId(open ? extension.id : null)\n }\n >\n <DropdownMenuTrigger asChild>\n <button\n type=\"button\"\n className=\"pointer-events-auto cursor-pointer rounded p-0.5 text-muted-foreground/40 transition-colors hover:text-foreground\"\n aria-label=\"Extension actions\"\n >\n <IconDots className=\"h-3 w-3\" />\n </button>\n </DropdownMenuTrigger>\n <DropdownMenuContent\n align=\"end\"\n sideOffset={4}\n className=\"min-w-[140px]\"\n >\n <DropdownMenuItem\n onSelect={() => startRename(extension)}\n >\n <IconPencil className=\"h-3.5 w-3.5\" />\n Rename\n </DropdownMenuItem>\n <DropdownMenuItem\n onSelect={() => handleDelete(extension.id)}\n className=\"text-destructive focus:text-destructive\"\n >\n <IconTrash className=\"h-3.5 w-3.5\" />\n Delete\n </DropdownMenuItem>\n </DropdownMenuContent>\n </DropdownMenu>\n </div>\n </div>\n );\n })}\n </div>\n )}\n </div>\n </TooltipProvider>\n );\n}\n"]}
@@ -1 +1 @@
1
- {"version":3,"file":"iframe-bridge.d.ts","sourceRoot":"","sources":["../../../src/client/extensions/iframe-bridge.ts"],"names":[],"mappings":"AAgCA;;;;;;;;;;;;GAYG;AACH,wBAAgB,sBAAsB,CACpC,IAAI,EAAE,MAAM,EACZ,WAAW,EAAE,MAAM,GAClB,OAAO,CAuCT;AAED,wBAAgB,+BAA+B,CAAC,KAAK,EAAE,OAAO,GAAG,WAAW,CAiC3E;AAuCD,MAAM,MAAM,mBAAmB,GAAG,OAAO,GAAG,OAAO,GAAG,QAAQ,GAAG,QAAQ,CAAC;AAI1E,MAAM,WAAW,mBAAmB;IAClC,qDAAqD;IACrD,IAAI,EAAE,mBAAmB,CAAC;IAC1B;gEAC4D;IAC5D,QAAQ,EAAE,OAAO,CAAC;CACnB;AAED,MAAM,WAAW,kBAAkB;IACjC,EAAE,EAAE,OAAO,CAAC;IACZ,qEAAqE;IACrE,KAAK,CAAC,EAAE,MAAM,CAAC;CAChB;AAED;;;;;;;GAOG;AACH,wBAAgB,iBAAiB,CAC/B,IAAI,EAAE,MAAM,EACZ,MAAM,EAAE,MAAM,EACd,GAAG,EAAE,mBAAmB,GACvB,kBAAkB,CAiFpB"}
1
+ {"version":3,"file":"iframe-bridge.d.ts","sourceRoot":"","sources":["../../../src/client/extensions/iframe-bridge.ts"],"names":[],"mappings":"AAgCA;;;;;;;;;;;;GAYG;AACH,wBAAgB,sBAAsB,CACpC,IAAI,EAAE,MAAM,EACZ,WAAW,EAAE,MAAM,GAClB,OAAO,CAuCT;AAED,wBAAgB,+BAA+B,CAAC,KAAK,EAAE,OAAO,GAAG,WAAW,CAiC3E;AAuCD,MAAM,MAAM,mBAAmB,GAAG,OAAO,GAAG,OAAO,GAAG,QAAQ,GAAG,QAAQ,CAAC;AAI1E,MAAM,WAAW,mBAAmB;IAClC,qDAAqD;IACrD,IAAI,EAAE,mBAAmB,CAAC;IAC1B;gEAC4D;IAC5D,QAAQ,EAAE,OAAO,CAAC;CACnB;AAED,MAAM,WAAW,kBAAkB;IACjC,EAAE,EAAE,OAAO,CAAC;IACZ,qEAAqE;IACrE,KAAK,CAAC,EAAE,MAAM,CAAC;CAChB;AAED;;;;;;;GAOG;AACH,wBAAgB,iBAAiB,CAC/B,IAAI,EAAE,MAAM,EACZ,MAAM,EAAE,MAAM,EACd,GAAG,EAAE,mBAAmB,GACvB,kBAAkB,CA8EpB"}
@@ -151,15 +151,12 @@ export function checkBridgePolicy(path, method, ctx) {
151
151
  error: deniedMessage("dbExec", ctx.role),
152
152
  };
153
153
  }
154
- // Actions are denied entirely for viewers even GET actions can mutate
155
- // implicitly (e.g. "view" actions that create rows for analytics).
156
- // toolCallable opt-in (audit H5) is enforced server-side as a second
157
- // layer.
154
+ // Actions are allowed for viewers; action-routes enforces each action's
155
+ // `toolCallable` opt-out server-side. This keeps read-oriented widgets like
156
+ // inbox stats usable when shared while still blocking sensitive actions such
157
+ // as share/unshare through their per-action flags.
158
158
  if (path.startsWith("/_agent-native/actions/")) {
159
- return {
160
- ok: false,
161
- error: deniedMessage("appAction", ctx.role),
162
- };
159
+ return { ok: true };
163
160
  }
164
161
  // Extension-data writes/deletes are denied; reads (GET/HEAD) are allowed.
165
162
  // Match /_agent-native/extensions/data/<extensionId>/<collection>[/<itemId>].
@@ -1 +1 @@
1
- {"version":3,"file":"iframe-bridge.js","sourceRoot":"","sources":["../../../src/client/extensions/iframe-bridge.ts"],"names":[],"mappings":"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","sourcesContent":["const ALLOWED_METHODS = new Set([\n \"GET\",\n \"POST\",\n \"PUT\",\n \"PATCH\",\n \"DELETE\",\n \"HEAD\",\n]);\n\nconst BLOCKED_HEADERS = new Set([\n \"connection\",\n \"content-length\",\n \"cookie\",\n \"forwarded\",\n \"host\",\n \"keep-alive\",\n \"origin\",\n \"proxy-authenticate\",\n \"proxy-authorization\",\n \"referer\",\n \"set-cookie\",\n \"te\",\n \"trailer\",\n \"transfer-encoding\",\n \"upgrade\",\n \"x-forwarded-for\",\n \"x-forwarded-host\",\n \"x-forwarded-proto\",\n]);\n\nconst HEADER_NAME_RE = /^[!#$%&'*+.^_`|~0-9A-Za-z-]+$/;\n\n/**\n * Path allowlist for the extension postMessage bridge.\n *\n * Extensions can only call paths under `/_agent-native/*` (the framework's own\n * namespace). Template-defined `/api/*` routes are intentionally rejected:\n * those routes are written by app authors who may not consistently apply the\n * `accessFilter`/`assertAccess` access scoping helpers. A shared/org extension\n * running with the viewer's session should not be able to reach surfaces\n * outside the framework's own well-audited namespace.\n *\n * If a template needs a extension to reach a custom route, expose it via an\n * action (`defineAction` auto-mounts under `/_agent-native/actions/<name>`).\n */\nexport function isAllowedExtensionPath(\n path: string,\n extensionId: string,\n): boolean {\n if (!path.startsWith(\"/\") || path.startsWith(\"//\")) return false;\n if (path.includes(\"\\\\\") || path.includes(\"\\0\")) return false;\n\n let pathname: string;\n try {\n const parsed = new URL(path, \"http://agent-native.local\");\n if (parsed.origin !== \"http://agent-native.local\") return false;\n pathname = parsed.pathname;\n } catch {\n return false;\n }\n\n const rawPathname = path.split(\"?\")[0].split(\"#\")[0];\n if (pathname !== rawPathname || pathname.includes(\"..\")) return false;\n\n if (pathname.startsWith(\"/_agent-native/actions/\")) return true;\n if (pathname.startsWith(\"/_agent-native/application-state/\")) return true;\n\n if (pathname === \"/_agent-native/extensions/proxy\") return true;\n if (pathname === \"/_agent-native/extensions/sql/query\") return true;\n if (pathname === \"/_agent-native/extensions/sql/exec\") return true;\n\n const parts = pathname.split(\"/\");\n if (\n parts.length >= 6 &&\n parts.length <= 7 &&\n parts[1] === \"_agent-native\" &&\n parts[2] === \"extensions\" &&\n parts[3] === \"data\"\n ) {\n try {\n return decodeURIComponent(parts[4]) === extensionId;\n } catch {\n return false;\n }\n }\n\n return false;\n}\n\nexport function sanitizeExtensionRequestOptions(value: unknown): RequestInit {\n if (!value || typeof value !== \"object\") return {};\n const raw = value as Record<string, unknown>;\n const method =\n typeof raw.method === \"string\" && raw.method.trim()\n ? raw.method.toUpperCase()\n : \"GET\";\n if (!ALLOWED_METHODS.has(method)) {\n throw new Error(\"Extension request method is not allowed\");\n }\n\n const headers =\n raw.headers && typeof raw.headers === \"object\"\n ? Object.fromEntries(\n Object.entries(raw.headers as Record<string, unknown>)\n .filter(([key, val]) => isAllowedHeader(key) && val !== undefined)\n .map(([key, val]) => [key, String(val)]),\n )\n : undefined;\n const body =\n typeof raw.body === \"string\" ||\n raw.body instanceof Blob ||\n raw.body instanceof FormData\n ? raw.body\n : raw.body === undefined\n ? undefined\n : JSON.stringify(raw.body);\n\n return {\n method,\n headers,\n body: method === \"GET\" || method === \"HEAD\" ? undefined : body,\n };\n}\n\nfunction isAllowedHeader(name: string): boolean {\n const lower = name.toLowerCase();\n return HEADER_NAME_RE.test(name) && !BLOCKED_HEADERS.has(lower);\n}\n\n// ---------------------------------------------------------------------------\n// Role-aware bridge gating (audit H4)\n// ---------------------------------------------------------------------------\n//\n// The host bridge dispatches every iframe postMessage request with the\n// viewer's session cookie. That means a non-author viewer's session can be\n// used to call mutating actions, write SQL, and resolve secret references —\n// the very capabilities that motivate the C1 consent step. After consent has\n// been granted, we still want defense-in-depth: a viewer whose role is\n// \"viewer\" should not be able to (e.g.) chain `appAction('share-resource')`\n// or run `dbExec` writes against their own data through someone else's extension.\n//\n// Role table (lowest tier first):\n//\n// role | appFetch | extensionFetch | extensionData | dbQuery | dbExec | appAction\n// ---------|-----------------|-----------------|----------------|---------|--------|----------\n// viewer | GET only | GET only | get/list only | deny | deny | deny\n// editor | all methods | all methods | get/list/set/ | allow | allow* | allow\n// | | | remove | | |\n// admin | all methods | all methods | all | allow | allow* | allow\n// owner | all methods | all methods | all | allow | allow* | allow\n//\n// * dbExec destructive operations are independently blocked by the SQL\n// blocklist on the server (DROP / TRUNCATE / DELETE without WHERE etc).\n// The role gate sits in front of that — viewers can't reach the SQL\n// surface at all; editors and above hit the SQL gate as well.\n//\n// The SQL helpers are denied entirely for viewers (not just dbExec) because\n// the dbQuery surface in dev mode bypasses the production scoping shim and\n// can leak other users' rows in template tables that aren't in\n// SENSITIVE_SQL_RE.\n\nexport type ExtensionBridgeRole = \"owner\" | \"admin\" | \"editor\" | \"viewer\";\n\nconst READ_METHODS = new Set([\"GET\", \"HEAD\"]);\n\nexport interface BridgePolicyContext {\n /** Resolved role of the viewer on this extension. */\n role: ExtensionBridgeRole;\n /** True when viewer is the extension's owner_email — equivalent to role \"owner\"\n * but cheaper to plumb through from the render binding. */\n isAuthor: boolean;\n}\n\nexport interface BridgePolicyResult {\n ok: boolean;\n /** Human-readable error to send back to the iframe when ok=false. */\n error?: string;\n}\n\n/**\n * Decide whether the iframe is allowed to proxy this request given the\n * viewer's role on the extension. Authors (and owner/admin/editor in general)\n * keep the full bridge surface; viewers get a strictly read-only subset.\n *\n * Called BEFORE the request leaves the parent — so a denial is local-only\n * and never reveals server state to the iframe.\n */\nexport function checkBridgePolicy(\n path: string,\n method: string,\n ctx: BridgePolicyContext,\n): BridgePolicyResult {\n // Authors and the highest non-owner roles get the unrestricted bridge.\n if (ctx.isAuthor || ctx.role === \"owner\" || ctx.role === \"admin\") {\n return { ok: true };\n }\n\n // Editors get write access EXCEPT for the helper-specific destructive\n // operations the server still gates (the SQL blocklist + per-action\n // toolCallable flag, see audit H5).\n if (ctx.role === \"editor\") {\n return { ok: true };\n }\n\n // From here on: role === \"viewer\". Lock down everything beyond reads.\n const upperMethod = method.toUpperCase();\n\n // SQL is denied for viewers entirely (defense-in-depth: dev mode bypasses\n // the production scoping shim).\n if (path === \"/_agent-native/extensions/sql/query\") {\n return {\n ok: false,\n error: deniedMessage(\"dbQuery\", ctx.role),\n };\n }\n if (path === \"/_agent-native/extensions/sql/exec\") {\n return {\n ok: false,\n error: deniedMessage(\"dbExec\", ctx.role),\n };\n }\n\n // Actions are denied entirely for viewers — even GET actions can mutate\n // implicitly (e.g. \"view\" actions that create rows for analytics).\n // toolCallable opt-in (audit H5) is enforced server-side as a second\n // layer.\n if (path.startsWith(\"/_agent-native/actions/\")) {\n return {\n ok: false,\n error: deniedMessage(\"appAction\", ctx.role),\n };\n }\n\n // Extension-data writes/deletes are denied; reads (GET/HEAD) are allowed.\n // Match /_agent-native/extensions/data/<extensionId>/<collection>[/<itemId>].\n if (path.startsWith(\"/_agent-native/extensions/data/\")) {\n if (READ_METHODS.has(upperMethod)) return { ok: true };\n return {\n ok: false,\n error: deniedMessage(\"extensionData.set/remove\", ctx.role),\n };\n }\n\n // extensionFetch — outbound proxy. POSTed JSON body carries the upstream method.\n // The bridge can only see the path here, not the upstream method, so we\n // restrict by REQUEST method (POST to /proxy carries the actual upstream\n // method as { method: 'GET' | ... } in body). For viewers we pre-flight-\n // deny the proxy unless a future code path emits a GET to /proxy/preview.\n // In practice, extensionFetch always POSTs to /proxy, so a viewer's extensionFetch\n // is denied entirely. Adapt this if /proxy gains a GET preview surface.\n if (path === \"/_agent-native/extensions/proxy\") {\n return {\n ok: false,\n error: deniedMessage(\"extensionFetch\", ctx.role),\n };\n }\n\n // application-state — viewers can read but not write.\n if (path.startsWith(\"/_agent-native/application-state/\")) {\n if (READ_METHODS.has(upperMethod)) return { ok: true };\n return {\n ok: false,\n error: deniedMessage(\"appFetch (mutation)\", ctx.role),\n };\n }\n\n // Generic appFetch — reads only for viewers.\n if (READ_METHODS.has(upperMethod)) return { ok: true };\n return {\n ok: false,\n error: deniedMessage(\"appFetch\", ctx.role),\n };\n}\n\nfunction deniedMessage(helper: string, role: ExtensionBridgeRole): string {\n return `Helper '${helper}' is not allowed for role '${role}' on this extension`;\n}\n"]}
1
+ {"version":3,"file":"iframe-bridge.js","sourceRoot":"","sources":["../../../src/client/extensions/iframe-bridge.ts"],"names":[],"mappings":"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","sourcesContent":["const ALLOWED_METHODS = new Set([\n \"GET\",\n \"POST\",\n \"PUT\",\n \"PATCH\",\n \"DELETE\",\n \"HEAD\",\n]);\n\nconst BLOCKED_HEADERS = new Set([\n \"connection\",\n \"content-length\",\n \"cookie\",\n \"forwarded\",\n \"host\",\n \"keep-alive\",\n \"origin\",\n \"proxy-authenticate\",\n \"proxy-authorization\",\n \"referer\",\n \"set-cookie\",\n \"te\",\n \"trailer\",\n \"transfer-encoding\",\n \"upgrade\",\n \"x-forwarded-for\",\n \"x-forwarded-host\",\n \"x-forwarded-proto\",\n]);\n\nconst HEADER_NAME_RE = /^[!#$%&'*+.^_`|~0-9A-Za-z-]+$/;\n\n/**\n * Path allowlist for the extension postMessage bridge.\n *\n * Extensions can only call paths under `/_agent-native/*` (the framework's own\n * namespace). Template-defined `/api/*` routes are intentionally rejected:\n * those routes are written by app authors who may not consistently apply the\n * `accessFilter`/`assertAccess` access scoping helpers. A shared/org extension\n * running with the viewer's session should not be able to reach surfaces\n * outside the framework's own well-audited namespace.\n *\n * If a template needs a extension to reach a custom route, expose it via an\n * action (`defineAction` auto-mounts under `/_agent-native/actions/<name>`).\n */\nexport function isAllowedExtensionPath(\n path: string,\n extensionId: string,\n): boolean {\n if (!path.startsWith(\"/\") || path.startsWith(\"//\")) return false;\n if (path.includes(\"\\\\\") || path.includes(\"\\0\")) return false;\n\n let pathname: string;\n try {\n const parsed = new URL(path, \"http://agent-native.local\");\n if (parsed.origin !== \"http://agent-native.local\") return false;\n pathname = parsed.pathname;\n } catch {\n return false;\n }\n\n const rawPathname = path.split(\"?\")[0].split(\"#\")[0];\n if (pathname !== rawPathname || pathname.includes(\"..\")) return false;\n\n if (pathname.startsWith(\"/_agent-native/actions/\")) return true;\n if (pathname.startsWith(\"/_agent-native/application-state/\")) return true;\n\n if (pathname === \"/_agent-native/extensions/proxy\") return true;\n if (pathname === \"/_agent-native/extensions/sql/query\") return true;\n if (pathname === \"/_agent-native/extensions/sql/exec\") return true;\n\n const parts = pathname.split(\"/\");\n if (\n parts.length >= 6 &&\n parts.length <= 7 &&\n parts[1] === \"_agent-native\" &&\n parts[2] === \"extensions\" &&\n parts[3] === \"data\"\n ) {\n try {\n return decodeURIComponent(parts[4]) === extensionId;\n } catch {\n return false;\n }\n }\n\n return false;\n}\n\nexport function sanitizeExtensionRequestOptions(value: unknown): RequestInit {\n if (!value || typeof value !== \"object\") return {};\n const raw = value as Record<string, unknown>;\n const method =\n typeof raw.method === \"string\" && raw.method.trim()\n ? raw.method.toUpperCase()\n : \"GET\";\n if (!ALLOWED_METHODS.has(method)) {\n throw new Error(\"Extension request method is not allowed\");\n }\n\n const headers =\n raw.headers && typeof raw.headers === \"object\"\n ? Object.fromEntries(\n Object.entries(raw.headers as Record<string, unknown>)\n .filter(([key, val]) => isAllowedHeader(key) && val !== undefined)\n .map(([key, val]) => [key, String(val)]),\n )\n : undefined;\n const body =\n typeof raw.body === \"string\" ||\n raw.body instanceof Blob ||\n raw.body instanceof FormData\n ? raw.body\n : raw.body === undefined\n ? undefined\n : JSON.stringify(raw.body);\n\n return {\n method,\n headers,\n body: method === \"GET\" || method === \"HEAD\" ? undefined : body,\n };\n}\n\nfunction isAllowedHeader(name: string): boolean {\n const lower = name.toLowerCase();\n return HEADER_NAME_RE.test(name) && !BLOCKED_HEADERS.has(lower);\n}\n\n// ---------------------------------------------------------------------------\n// Role-aware bridge gating (audit H4)\n// ---------------------------------------------------------------------------\n//\n// The host bridge dispatches every iframe postMessage request with the\n// viewer's session cookie. That means a non-author viewer's session can be\n// used to call mutating actions, write SQL, and resolve secret references —\n// the very capabilities that motivate the C1 consent step. After consent has\n// been granted, we still want defense-in-depth: a viewer whose role is\n// \"viewer\" should not be able to (e.g.) chain `appAction('share-resource')`\n// or run `dbExec` writes against their own data through someone else's extension.\n//\n// Role table (lowest tier first):\n//\n// role | appFetch | extensionFetch | extensionData | dbQuery | dbExec | appAction\n// ---------|-----------------|-----------------|----------------|---------|--------|----------\n// viewer | GET only | GET only | get/list only | deny | deny | allow*\n// editor | all methods | all methods | get/list/set/ | allow | allow* | allow\n// | | | remove | | |\n// admin | all methods | all methods | all | allow | allow* | allow\n// owner | all methods | all methods | all | allow | allow* | allow\n//\n// * dbExec destructive operations are independently blocked by the SQL\n// blocklist on the server (DROP / TRUNCATE / DELETE without WHERE etc).\n// The role gate sits in front of that — viewers can't reach the SQL\n// surface at all; editors and above hit the SQL gate as well.\n//\n// The SQL helpers are denied entirely for viewers (not just dbExec) because\n// the dbQuery surface in dev mode bypasses the production scoping shim and\n// can leak other users' rows in template tables that aren't in\n// SENSITIVE_SQL_RE.\n\nexport type ExtensionBridgeRole = \"owner\" | \"admin\" | \"editor\" | \"viewer\";\n\nconst READ_METHODS = new Set([\"GET\", \"HEAD\"]);\n\nexport interface BridgePolicyContext {\n /** Resolved role of the viewer on this extension. */\n role: ExtensionBridgeRole;\n /** True when viewer is the extension's owner_email — equivalent to role \"owner\"\n * but cheaper to plumb through from the render binding. */\n isAuthor: boolean;\n}\n\nexport interface BridgePolicyResult {\n ok: boolean;\n /** Human-readable error to send back to the iframe when ok=false. */\n error?: string;\n}\n\n/**\n * Decide whether the iframe is allowed to proxy this request given the\n * viewer's role on the extension. Authors (and owner/admin/editor in general)\n * keep the full bridge surface; viewers get a strictly read-only subset.\n *\n * Called BEFORE the request leaves the parent — so a denial is local-only\n * and never reveals server state to the iframe.\n */\nexport function checkBridgePolicy(\n path: string,\n method: string,\n ctx: BridgePolicyContext,\n): BridgePolicyResult {\n // Authors and the highest non-owner roles get the unrestricted bridge.\n if (ctx.isAuthor || ctx.role === \"owner\" || ctx.role === \"admin\") {\n return { ok: true };\n }\n\n // Editors get write access EXCEPT for the helper-specific destructive\n // operations the server still gates (the SQL blocklist + per-action\n // toolCallable flag, see audit H5).\n if (ctx.role === \"editor\") {\n return { ok: true };\n }\n\n // From here on: role === \"viewer\". Lock down everything beyond reads.\n const upperMethod = method.toUpperCase();\n\n // SQL is denied for viewers entirely (defense-in-depth: dev mode bypasses\n // the production scoping shim).\n if (path === \"/_agent-native/extensions/sql/query\") {\n return {\n ok: false,\n error: deniedMessage(\"dbQuery\", ctx.role),\n };\n }\n if (path === \"/_agent-native/extensions/sql/exec\") {\n return {\n ok: false,\n error: deniedMessage(\"dbExec\", ctx.role),\n };\n }\n\n // Actions are allowed for viewers; action-routes enforces each action's\n // `toolCallable` opt-out server-side. This keeps read-oriented widgets like\n // inbox stats usable when shared while still blocking sensitive actions such\n // as share/unshare through their per-action flags.\n if (path.startsWith(\"/_agent-native/actions/\")) {\n return { ok: true };\n }\n\n // Extension-data writes/deletes are denied; reads (GET/HEAD) are allowed.\n // Match /_agent-native/extensions/data/<extensionId>/<collection>[/<itemId>].\n if (path.startsWith(\"/_agent-native/extensions/data/\")) {\n if (READ_METHODS.has(upperMethod)) return { ok: true };\n return {\n ok: false,\n error: deniedMessage(\"extensionData.set/remove\", ctx.role),\n };\n }\n\n // extensionFetch — outbound proxy. POSTed JSON body carries the upstream method.\n // The bridge can only see the path here, not the upstream method, so we\n // restrict by REQUEST method (POST to /proxy carries the actual upstream\n // method as { method: 'GET' | ... } in body). For viewers we pre-flight-\n // deny the proxy unless a future code path emits a GET to /proxy/preview.\n // In practice, extensionFetch always POSTs to /proxy, so a viewer's extensionFetch\n // is denied entirely. Adapt this if /proxy gains a GET preview surface.\n if (path === \"/_agent-native/extensions/proxy\") {\n return {\n ok: false,\n error: deniedMessage(\"extensionFetch\", ctx.role),\n };\n }\n\n // application-state — viewers can read but not write.\n if (path.startsWith(\"/_agent-native/application-state/\")) {\n if (READ_METHODS.has(upperMethod)) return { ok: true };\n return {\n ok: false,\n error: deniedMessage(\"appFetch (mutation)\", ctx.role),\n };\n }\n\n // Generic appFetch — reads only for viewers.\n if (READ_METHODS.has(upperMethod)) return { ok: true };\n return {\n ok: false,\n error: deniedMessage(\"appFetch\", ctx.role),\n };\n}\n\nfunction deniedMessage(helper: string, role: ExtensionBridgeRole): string {\n return `Helper '${helper}' is not allowed for role '${role}' on this extension`;\n}\n"]}
@@ -4,6 +4,12 @@ export interface OrgSwitcherProps {
4
4
  hideWhenSingle?: boolean;
5
5
  /** Keep the switcher's button height reserved while org state is loading. */
6
6
  reserveSpace?: boolean;
7
+ /**
8
+ * Where the "Workspace settings" item navigates to. Defaults to `/team`,
9
+ * which every framework template mounts via the shared `TeamPage`.
10
+ * Templates that mount the settings page elsewhere can override.
11
+ */
12
+ settingsPath?: string;
7
13
  }
8
14
  /**
9
15
  * Compact org switcher button. Shows the active org (or "Personal" when the
@@ -11,5 +17,5 @@ export interface OrgSwitcherProps {
11
17
  * invitations, inline forms to create a new org / invite a teammate, and a
12
18
  * sign-out item. Renders nothing in dev / no-auth mode.
13
19
  */
14
- export declare function OrgSwitcher({ className, hideWhenSingle, reserveSpace, }: OrgSwitcherProps): import("react/jsx-runtime").JSX.Element;
20
+ export declare function OrgSwitcher({ className, hideWhenSingle, reserveSpace, settingsPath, }: OrgSwitcherProps): import("react/jsx-runtime").JSX.Element;
15
21
  //# sourceMappingURL=OrgSwitcher.d.ts.map
@@ -1 +1 @@
1
- {"version":3,"file":"OrgSwitcher.d.ts","sourceRoot":"","sources":["../../../src/client/org/OrgSwitcher.tsx"],"names":[],"mappings":"AAsBA,MAAM,WAAW,gBAAgB;IAC/B,SAAS,CAAC,EAAE,MAAM,CAAC;IACnB,2EAA2E;IAC3E,cAAc,CAAC,EAAE,OAAO,CAAC;IACzB,6EAA6E;IAC7E,YAAY,CAAC,EAAE,OAAO,CAAC;CACxB;AAyBD;;;;;GAKG;AACH,wBAAgB,WAAW,CAAC,EAC1B,SAAS,EACT,cAAc,EACd,YAAY,GACb,EAAE,gBAAgB,2CA4YlB"}
1
+ {"version":3,"file":"OrgSwitcher.d.ts","sourceRoot":"","sources":["../../../src/client/org/OrgSwitcher.tsx"],"names":[],"mappings":"AAwBA,MAAM,WAAW,gBAAgB;IAC/B,SAAS,CAAC,EAAE,MAAM,CAAC;IACnB,2EAA2E;IAC3E,cAAc,CAAC,EAAE,OAAO,CAAC;IACzB,6EAA6E;IAC7E,YAAY,CAAC,EAAE,OAAO,CAAC;IACvB;;;;OAIG;IACH,YAAY,CAAC,EAAE,MAAM,CAAC;CACvB;AAyBD;;;;;GAKG;AACH,wBAAgB,WAAW,CAAC,EAC1B,SAAS,EACT,cAAc,EACd,YAAY,EACZ,YAAsB,GACvB,EAAE,gBAAgB,2CA0ZlB"}
@@ -1,7 +1,8 @@
1
1
  import { jsx as _jsx, jsxs as _jsxs, Fragment as _Fragment } from "react/jsx-runtime";
2
2
  import { useState } from "react";
3
+ import { useNavigate } from "react-router";
3
4
  import * as PopoverPrimitive from "@radix-ui/react-popover";
4
- import { IconBuilding, IconCheck, IconLoader2, IconLogout, IconPlus, IconSelector, IconUser, IconUserPlus, } from "@tabler/icons-react";
5
+ import { IconBuilding, IconCheck, IconLoader2, IconLogout, IconPlus, IconSelector, IconSettings, IconUser, IconUserPlus, } from "@tabler/icons-react";
5
6
  import { useOrg, useSwitchOrg, useCreateOrg, useInviteMember, useAcceptInvitation, useJoinByDomain, } from "./hooks.js";
6
7
  import { agentNativePath } from "../api-path.js";
7
8
  function personalLabelFromEmail(email) {
@@ -26,13 +27,14 @@ const SECTION_LABEL_CLASS = "px-2.5 pt-1 pb-0.5 text-[10px] uppercase tracking-w
26
27
  * invitations, inline forms to create a new org / invite a teammate, and a
27
28
  * sign-out item. Renders nothing in dev / no-auth mode.
28
29
  */
29
- export function OrgSwitcher({ className, hideWhenSingle, reserveSpace, }) {
30
+ export function OrgSwitcher({ className, hideWhenSingle, reserveSpace, settingsPath = "/team", }) {
30
31
  const { data: org, isLoading } = useOrg();
31
32
  const switchOrg = useSwitchOrg();
32
33
  const createOrg = useCreateOrg();
33
34
  const inviteMember = useInviteMember();
34
35
  const acceptInvitation = useAcceptInvitation();
35
36
  const joinByDomain = useJoinByDomain();
37
+ const navigate = useNavigate();
36
38
  const [open, setOpen] = useState(false);
37
39
  const [mode, setMode] = useState("list");
38
40
  const [newName, setNewName] = useState("");
@@ -123,7 +125,10 @@ export function OrgSwitcher({ className, hideWhenSingle, reserveSpace, }) {
123
125
  setJoiningOrgId(null);
124
126
  }
125
127
  }, disabled: joinByDomain.isPending, className: "rounded px-1.5 py-0.5 text-[11px] font-medium text-primary hover:bg-primary/10 disabled:opacity-50 cursor-pointer", children: isJoining ? (_jsx(IconLoader2, { className: "h-3 w-3 animate-spin" })) : ("Join") })] }, match.orgId));
126
- })] })), _jsx("div", { className: "my-1 h-px bg-border" }), _jsxs("button", { type: "button", onClick: () => setMode("create"), className: `${ITEM_CLASS} cursor-pointer`, children: [_jsx(IconPlus, { className: "h-3.5 w-3.5 shrink-0 text-muted-foreground" }), _jsx("span", { className: "flex-1 text-left", children: "Create organization" })] }), canInvite && (_jsxs("button", { type: "button", onClick: () => setMode("invite"), className: `${ITEM_CLASS} cursor-pointer`, children: [_jsx(IconUserPlus, { className: "h-3.5 w-3.5 shrink-0 text-muted-foreground" }), _jsx("span", { className: "flex-1 text-left", children: "Invite member" })] })), _jsx("div", { className: "my-1 h-px bg-border" }), _jsxs("button", { type: "button", onClick: handleSignOut, disabled: signingOut, className: `${ITEM_CLASS} cursor-pointer`, children: [signingOut ? (_jsx(IconLoader2, { className: "h-3.5 w-3.5 shrink-0 animate-spin text-muted-foreground" })) : (_jsx(IconLogout, { className: "h-3.5 w-3.5 shrink-0 text-muted-foreground" })), _jsxs("span", { className: "flex-1 text-left", children: ["Sign out", org.email ? (_jsxs("span", { className: "ml-1 text-muted-foreground", children: ["(", org.email, ")"] })) : null] })] }), (switchOrg.error ||
128
+ })] })), _jsx("div", { className: "my-1 h-px bg-border" }), inOrg && (_jsxs("button", { type: "button", onClick: () => {
129
+ setOpen(false);
130
+ navigate(settingsPath);
131
+ }, className: `${ITEM_CLASS} cursor-pointer`, children: [_jsx(IconSettings, { className: "h-3.5 w-3.5 shrink-0 text-muted-foreground" }), _jsx("span", { className: "flex-1 text-left", children: "Workspace settings" })] })), _jsxs("button", { type: "button", onClick: () => setMode("create"), className: `${ITEM_CLASS} cursor-pointer`, children: [_jsx(IconPlus, { className: "h-3.5 w-3.5 shrink-0 text-muted-foreground" }), _jsx("span", { className: "flex-1 text-left", children: "Create organization" })] }), canInvite && (_jsxs("button", { type: "button", onClick: () => setMode("invite"), className: `${ITEM_CLASS} cursor-pointer`, children: [_jsx(IconUserPlus, { className: "h-3.5 w-3.5 shrink-0 text-muted-foreground" }), _jsx("span", { className: "flex-1 text-left", children: "Invite member" })] })), _jsx("div", { className: "my-1 h-px bg-border" }), _jsxs("button", { type: "button", onClick: handleSignOut, disabled: signingOut, className: `${ITEM_CLASS} cursor-pointer`, children: [signingOut ? (_jsx(IconLoader2, { className: "h-3.5 w-3.5 shrink-0 animate-spin text-muted-foreground" })) : (_jsx(IconLogout, { className: "h-3.5 w-3.5 shrink-0 text-muted-foreground" })), _jsxs("span", { className: "flex-1 text-left", children: ["Sign out", org.email ? (_jsxs("span", { className: "ml-1 text-muted-foreground", children: ["(", org.email, ")"] })) : null] })] }), (switchOrg.error ||
127
132
  acceptInvitation.error ||
128
133
  joinByDomain.error) && (_jsx("div", { className: "px-2.5 pt-1 text-[11px] text-destructive", children: (switchOrg.error ||
129
134
  acceptInvitation.error ||
@@ -1 +1 @@
1
- {"version":3,"file":"OrgSwitcher.js","sourceRoot":"","sources":["../../../src/client/org/OrgSwitcher.tsx"],"names":[],"mappings":"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","sourcesContent":["import { useState } from \"react\";\nimport * as PopoverPrimitive from \"@radix-ui/react-popover\";\nimport {\n IconBuilding,\n IconCheck,\n IconLoader2,\n IconLogout,\n IconPlus,\n IconSelector,\n IconUser,\n IconUserPlus,\n} from \"@tabler/icons-react\";\nimport {\n useOrg,\n useSwitchOrg,\n useCreateOrg,\n useInviteMember,\n useAcceptInvitation,\n useJoinByDomain,\n} from \"./hooks.js\";\nimport { agentNativePath } from \"../api-path.js\";\n\nexport interface OrgSwitcherProps {\n className?: string;\n /** Hide entirely when the user only belongs to one org. Default: false. */\n hideWhenSingle?: boolean;\n /** Keep the switcher's button height reserved while org state is loading. */\n reserveSpace?: boolean;\n}\n\nfunction personalLabelFromEmail(email: string | null | undefined): string {\n if (!email) return \"Personal\";\n const local = email.split(\"@\")[0] ?? email;\n const cleaned = local.replace(/[._-]+/g, \" \").trim();\n if (!cleaned) return \"Personal\";\n return cleaned\n .split(\" \")\n .filter(Boolean)\n .map((w) => w.charAt(0).toUpperCase() + w.slice(1))\n .join(\" \");\n}\n\ntype Mode = \"list\" | \"create\" | \"invite\";\n\nconst POPOVER_CONTENT_CLASS =\n \"z-50 min-w-[14rem] rounded-md border border-border bg-popover py-1 text-popover-foreground shadow-md outline-none data-[state=open]:animate-in data-[state=closed]:animate-out data-[state=closed]:fade-out-0 data-[state=open]:fade-in-0 data-[state=closed]:zoom-out-95 data-[state=open]:zoom-in-95 data-[side=bottom]:slide-in-from-top-2 data-[side=left]:slide-in-from-right-2 data-[side=right]:slide-in-from-left-2 data-[side=top]:slide-in-from-bottom-2\";\n\nconst ITEM_CLASS =\n \"flex w-full items-center gap-2 px-2.5 py-1.5 text-xs text-foreground hover:bg-accent focus-visible:bg-accent focus:outline-none disabled:opacity-50 disabled:pointer-events-none\";\n\nconst SECTION_LABEL_CLASS =\n \"px-2.5 pt-1 pb-0.5 text-[10px] uppercase tracking-wide text-muted-foreground\";\n\n/**\n * Compact org switcher button. Shows the active org (or \"Personal\" when the\n * user has none); opens a popover with the user's other orgs, pending\n * invitations, inline forms to create a new org / invite a teammate, and a\n * sign-out item. Renders nothing in dev / no-auth mode.\n */\nexport function OrgSwitcher({\n className,\n hideWhenSingle,\n reserveSpace,\n}: OrgSwitcherProps) {\n const { data: org, isLoading } = useOrg();\n const switchOrg = useSwitchOrg();\n const createOrg = useCreateOrg();\n const inviteMember = useInviteMember();\n const acceptInvitation = useAcceptInvitation();\n const joinByDomain = useJoinByDomain();\n const [open, setOpen] = useState(false);\n const [mode, setMode] = useState<Mode>(\"list\");\n const [newName, setNewName] = useState(\"\");\n const [inviteEmail, setInviteEmail] = useState(\"\");\n const [signingOut, setSigningOut] = useState(false);\n const [joiningOrgId, setJoiningOrgId] = useState<string | null>(null);\n\n const handleOpenChange = (next: boolean) => {\n setOpen(next);\n if (!next) {\n setMode(\"list\");\n setNewName(\"\");\n setInviteEmail(\"\");\n }\n };\n\n const handleSignOut = async () => {\n if (signingOut) return;\n setSigningOut(true);\n try {\n await fetch(agentNativePath(\"/_agent-native/auth/logout\"), {\n method: \"POST\",\n credentials: \"include\",\n });\n } catch {\n /* fall through to reload — server may already have cleared the cookie */\n }\n window.location.reload();\n };\n\n if (!org) {\n return reserveSpace && isLoading ? (\n <div aria-hidden=\"true\" className={`h-8 ${className ?? \"\"}`} />\n ) : null;\n }\n\n const orgs = org.orgs ?? [];\n const pendingInvitations = org.pendingInvitations ?? [];\n const domainMatches = org.domainMatches ?? [];\n const orgCount = orgs.length;\n const hasAny =\n orgCount > 0 || pendingInvitations.length > 0 || domainMatches.length > 0;\n if (!hasAny && !org.email) {\n return reserveSpace ? (\n <div aria-hidden=\"true\" className={`h-8 ${className ?? \"\"}`} />\n ) : null;\n }\n if (\n hideWhenSingle &&\n orgCount < 2 &&\n pendingInvitations.length === 0 &&\n domainMatches.length === 0\n ) {\n return reserveSpace ? (\n <div aria-hidden=\"true\" className={`h-8 ${className ?? \"\"}`} />\n ) : null;\n }\n\n const canInvite =\n !!org.orgId && (org.role === \"owner\" || org.role === \"admin\");\n\n const personalLabel = personalLabelFromEmail(org.email);\n const inOrg = !!org.orgId;\n const buttonLabel = org.orgName ?? \"Personal\";\n const ButtonIcon = inOrg ? IconBuilding : IconUser;\n\n return (\n <PopoverPrimitive.Root open={open} onOpenChange={handleOpenChange}>\n <PopoverPrimitive.Trigger asChild>\n <button\n type=\"button\"\n className={`flex w-full items-center gap-2 rounded-md border border-border/50 px-2.5 py-1.5 text-xs font-medium text-muted-foreground hover:bg-accent/50 hover:text-foreground focus:outline-none focus-visible:ring-2 focus-visible:ring-ring cursor-pointer ${className ?? \"\"}`}\n >\n <ButtonIcon className=\"h-3.5 w-3.5 shrink-0\" />\n <span className=\"truncate flex-1 text-left\">{buttonLabel}</span>\n <IconSelector className=\"h-3 w-3 shrink-0 opacity-50\" />\n </button>\n </PopoverPrimitive.Trigger>\n <PopoverPrimitive.Portal>\n <PopoverPrimitive.Content\n side=\"top\"\n align=\"start\"\n sideOffset={6}\n collisionPadding={12}\n className={POPOVER_CONTENT_CLASS}\n onOpenAutoFocus={(e) => {\n // Don't auto-focus the first item — feels heavy on a switcher.\n if (mode === \"list\") e.preventDefault();\n }}\n >\n {mode === \"list\" && (\n <>\n {!inOrg && (\n <div\n className=\"flex w-full items-center gap-2 px-2.5 py-1.5 text-xs text-muted-foreground\"\n aria-disabled=\"true\"\n >\n <IconUser className=\"h-3.5 w-3.5 shrink-0\" />\n <span className=\"truncate flex-1 text-left\">\n Personal ({personalLabel})\n </span>\n </div>\n )}\n {orgs.length > 0 && (\n <div className={SECTION_LABEL_CLASS}>Organizations</div>\n )}\n {orgs.map((o) => (\n <button\n key={o.orgId}\n type=\"button\"\n onClick={async () => {\n if (o.orgId === org.orgId) {\n setOpen(false);\n return;\n }\n try {\n await switchOrg.mutateAsync(o.orgId);\n setOpen(false);\n } catch {\n /* error surfaced via switchOrg.error */\n }\n }}\n disabled={switchOrg.isPending}\n className={`${ITEM_CLASS} cursor-pointer`}\n >\n <IconBuilding className=\"h-3.5 w-3.5 shrink-0 text-muted-foreground\" />\n <span className=\"truncate flex-1 text-left\">{o.orgName}</span>\n {o.orgId === org.orgId && (\n <IconCheck className=\"h-3.5 w-3.5 shrink-0 text-muted-foreground\" />\n )}\n </button>\n ))}\n\n {pendingInvitations.length > 0 && (\n <>\n {orgs.length > 0 && <div className=\"my-1 h-px bg-border\" />}\n <div className={SECTION_LABEL_CLASS}>Invitations</div>\n {pendingInvitations.map((inv) => (\n <div\n key={inv.id}\n className=\"flex items-center gap-2 px-2.5 py-1.5 text-xs\"\n >\n <IconBuilding className=\"h-3.5 w-3.5 shrink-0 text-muted-foreground\" />\n <span className=\"truncate flex-1 text-foreground\">\n {inv.orgName}\n </span>\n <button\n type=\"button\"\n onClick={async () => {\n try {\n await acceptInvitation.mutateAsync(inv.id);\n setOpen(false);\n } catch {\n /* error surfaced via acceptInvitation.error */\n }\n }}\n disabled={acceptInvitation.isPending}\n className=\"rounded px-1.5 py-0.5 text-[11px] font-medium text-primary hover:bg-primary/10 disabled:opacity-50 cursor-pointer\"\n >\n {acceptInvitation.isPending ? (\n <IconLoader2 className=\"h-3 w-3 animate-spin\" />\n ) : (\n \"Join\"\n )}\n </button>\n </div>\n ))}\n </>\n )}\n\n {domainMatches.length > 0 && (\n <>\n {(orgs.length > 0 || pendingInvitations.length > 0) && (\n <div className=\"my-1 h-px bg-border\" />\n )}\n <div className={SECTION_LABEL_CLASS}>Join your team</div>\n {domainMatches.map((match) => {\n const isJoining =\n joinByDomain.isPending && joiningOrgId === match.orgId;\n return (\n <div\n key={match.orgId}\n className=\"flex items-center gap-2 px-2.5 py-1.5 text-xs\"\n >\n <IconBuilding className=\"h-3.5 w-3.5 shrink-0 text-muted-foreground\" />\n <span className=\"truncate flex-1 text-foreground\">\n {match.orgName}\n </span>\n <button\n type=\"button\"\n onClick={async () => {\n setJoiningOrgId(match.orgId);\n try {\n await joinByDomain.mutateAsync(match.orgId);\n setOpen(false);\n } catch {\n /* error surfaced via joinByDomain.error */\n } finally {\n setJoiningOrgId(null);\n }\n }}\n disabled={joinByDomain.isPending}\n className=\"rounded px-1.5 py-0.5 text-[11px] font-medium text-primary hover:bg-primary/10 disabled:opacity-50 cursor-pointer\"\n >\n {isJoining ? (\n <IconLoader2 className=\"h-3 w-3 animate-spin\" />\n ) : (\n \"Join\"\n )}\n </button>\n </div>\n );\n })}\n </>\n )}\n\n <div className=\"my-1 h-px bg-border\" />\n <button\n type=\"button\"\n onClick={() => setMode(\"create\")}\n className={`${ITEM_CLASS} cursor-pointer`}\n >\n <IconPlus className=\"h-3.5 w-3.5 shrink-0 text-muted-foreground\" />\n <span className=\"flex-1 text-left\">Create organization</span>\n </button>\n {canInvite && (\n <button\n type=\"button\"\n onClick={() => setMode(\"invite\")}\n className={`${ITEM_CLASS} cursor-pointer`}\n >\n <IconUserPlus className=\"h-3.5 w-3.5 shrink-0 text-muted-foreground\" />\n <span className=\"flex-1 text-left\">Invite member</span>\n </button>\n )}\n\n <div className=\"my-1 h-px bg-border\" />\n <button\n type=\"button\"\n onClick={handleSignOut}\n disabled={signingOut}\n className={`${ITEM_CLASS} cursor-pointer`}\n >\n {signingOut ? (\n <IconLoader2 className=\"h-3.5 w-3.5 shrink-0 animate-spin text-muted-foreground\" />\n ) : (\n <IconLogout className=\"h-3.5 w-3.5 shrink-0 text-muted-foreground\" />\n )}\n <span className=\"flex-1 text-left\">\n Sign out\n {org.email ? (\n <span className=\"ml-1 text-muted-foreground\">\n ({org.email})\n </span>\n ) : null}\n </span>\n </button>\n\n {(switchOrg.error ||\n acceptInvitation.error ||\n joinByDomain.error) && (\n <div className=\"px-2.5 pt-1 text-[11px] text-destructive\">\n {\n (\n (switchOrg.error ||\n acceptInvitation.error ||\n joinByDomain.error) as Error\n ).message\n }\n </div>\n )}\n </>\n )}\n\n {mode === \"create\" && (\n <form\n onSubmit={async (e) => {\n e.preventDefault();\n const name = newName.trim();\n if (!name) return;\n try {\n await createOrg.mutateAsync(name);\n setOpen(false);\n } catch {\n /* error surfaced via createOrg.error */\n }\n }}\n className=\"px-2 py-1.5\"\n >\n <div className=\"px-0.5 pb-1 text-[10px] uppercase tracking-wide text-muted-foreground\">\n New organization\n </div>\n <input\n autoFocus\n value={newName}\n onChange={(e) => setNewName(e.target.value)}\n placeholder=\"Organization name\"\n disabled={createOrg.isPending}\n className=\"w-full rounded-md border border-input bg-background px-2 py-1.5 text-xs outline-none focus:ring-2 focus:ring-ring disabled:opacity-50\"\n />\n {createOrg.error && (\n <div className=\"pt-1 text-[11px] text-destructive\">\n {(createOrg.error as Error).message}\n </div>\n )}\n <div className=\"flex items-center gap-1.5 pt-1.5\">\n <button\n type=\"button\"\n onClick={() => setMode(\"list\")}\n disabled={createOrg.isPending}\n className=\"flex-1 rounded-md px-2 py-1 text-xs text-muted-foreground hover:bg-accent disabled:opacity-50 cursor-pointer\"\n >\n Cancel\n </button>\n <button\n type=\"submit\"\n disabled={createOrg.isPending || !newName.trim()}\n className=\"flex-1 rounded-md bg-primary px-2 py-1 text-xs font-medium text-primary-foreground hover:opacity-90 disabled:opacity-50 cursor-pointer\"\n >\n {createOrg.isPending ? (\n <IconLoader2 className=\"mx-auto h-3 w-3 animate-spin\" />\n ) : (\n \"Create\"\n )}\n </button>\n </div>\n </form>\n )}\n\n {mode === \"invite\" && (\n <form\n onSubmit={async (e) => {\n e.preventDefault();\n const email = inviteEmail.trim();\n if (!email) return;\n try {\n await inviteMember.mutateAsync(email);\n setInviteEmail(\"\");\n setMode(\"list\");\n } catch {\n /* error surfaced via inviteMember.error */\n }\n }}\n className=\"px-2 py-1.5\"\n >\n <div className=\"px-0.5 pb-1 text-[10px] uppercase tracking-wide text-muted-foreground\">\n Invite to {org.orgName}\n </div>\n <input\n autoFocus\n type=\"email\"\n value={inviteEmail}\n onChange={(e) => setInviteEmail(e.target.value)}\n placeholder=\"teammate@company.com\"\n disabled={inviteMember.isPending}\n className=\"w-full rounded-md border border-input bg-background px-2 py-1.5 text-xs outline-none focus:ring-2 focus:ring-ring disabled:opacity-50\"\n />\n {inviteMember.error && (\n <div className=\"pt-1 text-[11px] text-destructive\">\n {(inviteMember.error as Error).message}\n </div>\n )}\n <div className=\"flex items-center gap-1.5 pt-1.5\">\n <button\n type=\"button\"\n onClick={() => setMode(\"list\")}\n disabled={inviteMember.isPending}\n className=\"flex-1 rounded-md px-2 py-1 text-xs text-muted-foreground hover:bg-accent disabled:opacity-50 cursor-pointer\"\n >\n Cancel\n </button>\n <button\n type=\"submit\"\n disabled={inviteMember.isPending || !inviteEmail.trim()}\n className=\"flex-1 rounded-md bg-primary px-2 py-1 text-xs font-medium text-primary-foreground hover:opacity-90 disabled:opacity-50 cursor-pointer\"\n >\n {inviteMember.isPending ? (\n <IconLoader2 className=\"mx-auto h-3 w-3 animate-spin\" />\n ) : (\n \"Send invite\"\n )}\n </button>\n </div>\n </form>\n )}\n </PopoverPrimitive.Content>\n </PopoverPrimitive.Portal>\n </PopoverPrimitive.Root>\n );\n}\n"]}
1
+ {"version":3,"file":"OrgSwitcher.js","sourceRoot":"","sources":["../../../src/client/org/OrgSwitcher.tsx"],"names":[],"mappings":"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","sourcesContent":["import { useState } from \"react\";\nimport { useNavigate } from \"react-router\";\nimport * as PopoverPrimitive from \"@radix-ui/react-popover\";\nimport {\n IconBuilding,\n IconCheck,\n IconLoader2,\n IconLogout,\n IconPlus,\n IconSelector,\n IconSettings,\n IconUser,\n IconUserPlus,\n} from \"@tabler/icons-react\";\nimport {\n useOrg,\n useSwitchOrg,\n useCreateOrg,\n useInviteMember,\n useAcceptInvitation,\n useJoinByDomain,\n} from \"./hooks.js\";\nimport { agentNativePath } from \"../api-path.js\";\n\nexport interface OrgSwitcherProps {\n className?: string;\n /** Hide entirely when the user only belongs to one org. Default: false. */\n hideWhenSingle?: boolean;\n /** Keep the switcher's button height reserved while org state is loading. */\n reserveSpace?: boolean;\n /**\n * Where the \"Workspace settings\" item navigates to. Defaults to `/team`,\n * which every framework template mounts via the shared `TeamPage`.\n * Templates that mount the settings page elsewhere can override.\n */\n settingsPath?: string;\n}\n\nfunction personalLabelFromEmail(email: string | null | undefined): string {\n if (!email) return \"Personal\";\n const local = email.split(\"@\")[0] ?? email;\n const cleaned = local.replace(/[._-]+/g, \" \").trim();\n if (!cleaned) return \"Personal\";\n return cleaned\n .split(\" \")\n .filter(Boolean)\n .map((w) => w.charAt(0).toUpperCase() + w.slice(1))\n .join(\" \");\n}\n\ntype Mode = \"list\" | \"create\" | \"invite\";\n\nconst POPOVER_CONTENT_CLASS =\n \"z-50 min-w-[14rem] rounded-md border border-border bg-popover py-1 text-popover-foreground shadow-md outline-none data-[state=open]:animate-in data-[state=closed]:animate-out data-[state=closed]:fade-out-0 data-[state=open]:fade-in-0 data-[state=closed]:zoom-out-95 data-[state=open]:zoom-in-95 data-[side=bottom]:slide-in-from-top-2 data-[side=left]:slide-in-from-right-2 data-[side=right]:slide-in-from-left-2 data-[side=top]:slide-in-from-bottom-2\";\n\nconst ITEM_CLASS =\n \"flex w-full items-center gap-2 px-2.5 py-1.5 text-xs text-foreground hover:bg-accent focus-visible:bg-accent focus:outline-none disabled:opacity-50 disabled:pointer-events-none\";\n\nconst SECTION_LABEL_CLASS =\n \"px-2.5 pt-1 pb-0.5 text-[10px] uppercase tracking-wide text-muted-foreground\";\n\n/**\n * Compact org switcher button. Shows the active org (or \"Personal\" when the\n * user has none); opens a popover with the user's other orgs, pending\n * invitations, inline forms to create a new org / invite a teammate, and a\n * sign-out item. Renders nothing in dev / no-auth mode.\n */\nexport function OrgSwitcher({\n className,\n hideWhenSingle,\n reserveSpace,\n settingsPath = \"/team\",\n}: OrgSwitcherProps) {\n const { data: org, isLoading } = useOrg();\n const switchOrg = useSwitchOrg();\n const createOrg = useCreateOrg();\n const inviteMember = useInviteMember();\n const acceptInvitation = useAcceptInvitation();\n const joinByDomain = useJoinByDomain();\n const navigate = useNavigate();\n const [open, setOpen] = useState(false);\n const [mode, setMode] = useState<Mode>(\"list\");\n const [newName, setNewName] = useState(\"\");\n const [inviteEmail, setInviteEmail] = useState(\"\");\n const [signingOut, setSigningOut] = useState(false);\n const [joiningOrgId, setJoiningOrgId] = useState<string | null>(null);\n\n const handleOpenChange = (next: boolean) => {\n setOpen(next);\n if (!next) {\n setMode(\"list\");\n setNewName(\"\");\n setInviteEmail(\"\");\n }\n };\n\n const handleSignOut = async () => {\n if (signingOut) return;\n setSigningOut(true);\n try {\n await fetch(agentNativePath(\"/_agent-native/auth/logout\"), {\n method: \"POST\",\n credentials: \"include\",\n });\n } catch {\n /* fall through to reload — server may already have cleared the cookie */\n }\n window.location.reload();\n };\n\n if (!org) {\n return reserveSpace && isLoading ? (\n <div aria-hidden=\"true\" className={`h-8 ${className ?? \"\"}`} />\n ) : null;\n }\n\n const orgs = org.orgs ?? [];\n const pendingInvitations = org.pendingInvitations ?? [];\n const domainMatches = org.domainMatches ?? [];\n const orgCount = orgs.length;\n const hasAny =\n orgCount > 0 || pendingInvitations.length > 0 || domainMatches.length > 0;\n if (!hasAny && !org.email) {\n return reserveSpace ? (\n <div aria-hidden=\"true\" className={`h-8 ${className ?? \"\"}`} />\n ) : null;\n }\n if (\n hideWhenSingle &&\n orgCount < 2 &&\n pendingInvitations.length === 0 &&\n domainMatches.length === 0\n ) {\n return reserveSpace ? (\n <div aria-hidden=\"true\" className={`h-8 ${className ?? \"\"}`} />\n ) : null;\n }\n\n const canInvite =\n !!org.orgId && (org.role === \"owner\" || org.role === \"admin\");\n\n const personalLabel = personalLabelFromEmail(org.email);\n const inOrg = !!org.orgId;\n const buttonLabel = org.orgName ?? \"Personal\";\n const ButtonIcon = inOrg ? IconBuilding : IconUser;\n\n return (\n <PopoverPrimitive.Root open={open} onOpenChange={handleOpenChange}>\n <PopoverPrimitive.Trigger asChild>\n <button\n type=\"button\"\n className={`flex w-full items-center gap-2 rounded-md border border-border/50 px-2.5 py-1.5 text-xs font-medium text-muted-foreground hover:bg-accent/50 hover:text-foreground focus:outline-none focus-visible:ring-2 focus-visible:ring-ring cursor-pointer ${className ?? \"\"}`}\n >\n <ButtonIcon className=\"h-3.5 w-3.5 shrink-0\" />\n <span className=\"truncate flex-1 text-left\">{buttonLabel}</span>\n <IconSelector className=\"h-3 w-3 shrink-0 opacity-50\" />\n </button>\n </PopoverPrimitive.Trigger>\n <PopoverPrimitive.Portal>\n <PopoverPrimitive.Content\n side=\"top\"\n align=\"start\"\n sideOffset={6}\n collisionPadding={12}\n className={POPOVER_CONTENT_CLASS}\n onOpenAutoFocus={(e) => {\n // Don't auto-focus the first item — feels heavy on a switcher.\n if (mode === \"list\") e.preventDefault();\n }}\n >\n {mode === \"list\" && (\n <>\n {!inOrg && (\n <div\n className=\"flex w-full items-center gap-2 px-2.5 py-1.5 text-xs text-muted-foreground\"\n aria-disabled=\"true\"\n >\n <IconUser className=\"h-3.5 w-3.5 shrink-0\" />\n <span className=\"truncate flex-1 text-left\">\n Personal ({personalLabel})\n </span>\n </div>\n )}\n {orgs.length > 0 && (\n <div className={SECTION_LABEL_CLASS}>Organizations</div>\n )}\n {orgs.map((o) => (\n <button\n key={o.orgId}\n type=\"button\"\n onClick={async () => {\n if (o.orgId === org.orgId) {\n setOpen(false);\n return;\n }\n try {\n await switchOrg.mutateAsync(o.orgId);\n setOpen(false);\n } catch {\n /* error surfaced via switchOrg.error */\n }\n }}\n disabled={switchOrg.isPending}\n className={`${ITEM_CLASS} cursor-pointer`}\n >\n <IconBuilding className=\"h-3.5 w-3.5 shrink-0 text-muted-foreground\" />\n <span className=\"truncate flex-1 text-left\">{o.orgName}</span>\n {o.orgId === org.orgId && (\n <IconCheck className=\"h-3.5 w-3.5 shrink-0 text-muted-foreground\" />\n )}\n </button>\n ))}\n\n {pendingInvitations.length > 0 && (\n <>\n {orgs.length > 0 && <div className=\"my-1 h-px bg-border\" />}\n <div className={SECTION_LABEL_CLASS}>Invitations</div>\n {pendingInvitations.map((inv) => (\n <div\n key={inv.id}\n className=\"flex items-center gap-2 px-2.5 py-1.5 text-xs\"\n >\n <IconBuilding className=\"h-3.5 w-3.5 shrink-0 text-muted-foreground\" />\n <span className=\"truncate flex-1 text-foreground\">\n {inv.orgName}\n </span>\n <button\n type=\"button\"\n onClick={async () => {\n try {\n await acceptInvitation.mutateAsync(inv.id);\n setOpen(false);\n } catch {\n /* error surfaced via acceptInvitation.error */\n }\n }}\n disabled={acceptInvitation.isPending}\n className=\"rounded px-1.5 py-0.5 text-[11px] font-medium text-primary hover:bg-primary/10 disabled:opacity-50 cursor-pointer\"\n >\n {acceptInvitation.isPending ? (\n <IconLoader2 className=\"h-3 w-3 animate-spin\" />\n ) : (\n \"Join\"\n )}\n </button>\n </div>\n ))}\n </>\n )}\n\n {domainMatches.length > 0 && (\n <>\n {(orgs.length > 0 || pendingInvitations.length > 0) && (\n <div className=\"my-1 h-px bg-border\" />\n )}\n <div className={SECTION_LABEL_CLASS}>Join your team</div>\n {domainMatches.map((match) => {\n const isJoining =\n joinByDomain.isPending && joiningOrgId === match.orgId;\n return (\n <div\n key={match.orgId}\n className=\"flex items-center gap-2 px-2.5 py-1.5 text-xs\"\n >\n <IconBuilding className=\"h-3.5 w-3.5 shrink-0 text-muted-foreground\" />\n <span className=\"truncate flex-1 text-foreground\">\n {match.orgName}\n </span>\n <button\n type=\"button\"\n onClick={async () => {\n setJoiningOrgId(match.orgId);\n try {\n await joinByDomain.mutateAsync(match.orgId);\n setOpen(false);\n } catch {\n /* error surfaced via joinByDomain.error */\n } finally {\n setJoiningOrgId(null);\n }\n }}\n disabled={joinByDomain.isPending}\n className=\"rounded px-1.5 py-0.5 text-[11px] font-medium text-primary hover:bg-primary/10 disabled:opacity-50 cursor-pointer\"\n >\n {isJoining ? (\n <IconLoader2 className=\"h-3 w-3 animate-spin\" />\n ) : (\n \"Join\"\n )}\n </button>\n </div>\n );\n })}\n </>\n )}\n\n <div className=\"my-1 h-px bg-border\" />\n {inOrg && (\n <button\n type=\"button\"\n onClick={() => {\n setOpen(false);\n navigate(settingsPath);\n }}\n className={`${ITEM_CLASS} cursor-pointer`}\n >\n <IconSettings className=\"h-3.5 w-3.5 shrink-0 text-muted-foreground\" />\n <span className=\"flex-1 text-left\">Workspace settings</span>\n </button>\n )}\n <button\n type=\"button\"\n onClick={() => setMode(\"create\")}\n className={`${ITEM_CLASS} cursor-pointer`}\n >\n <IconPlus className=\"h-3.5 w-3.5 shrink-0 text-muted-foreground\" />\n <span className=\"flex-1 text-left\">Create organization</span>\n </button>\n {canInvite && (\n <button\n type=\"button\"\n onClick={() => setMode(\"invite\")}\n className={`${ITEM_CLASS} cursor-pointer`}\n >\n <IconUserPlus className=\"h-3.5 w-3.5 shrink-0 text-muted-foreground\" />\n <span className=\"flex-1 text-left\">Invite member</span>\n </button>\n )}\n\n <div className=\"my-1 h-px bg-border\" />\n <button\n type=\"button\"\n onClick={handleSignOut}\n disabled={signingOut}\n className={`${ITEM_CLASS} cursor-pointer`}\n >\n {signingOut ? (\n <IconLoader2 className=\"h-3.5 w-3.5 shrink-0 animate-spin text-muted-foreground\" />\n ) : (\n <IconLogout className=\"h-3.5 w-3.5 shrink-0 text-muted-foreground\" />\n )}\n <span className=\"flex-1 text-left\">\n Sign out\n {org.email ? (\n <span className=\"ml-1 text-muted-foreground\">\n ({org.email})\n </span>\n ) : null}\n </span>\n </button>\n\n {(switchOrg.error ||\n acceptInvitation.error ||\n joinByDomain.error) && (\n <div className=\"px-2.5 pt-1 text-[11px] text-destructive\">\n {\n (\n (switchOrg.error ||\n acceptInvitation.error ||\n joinByDomain.error) as Error\n ).message\n }\n </div>\n )}\n </>\n )}\n\n {mode === \"create\" && (\n <form\n onSubmit={async (e) => {\n e.preventDefault();\n const name = newName.trim();\n if (!name) return;\n try {\n await createOrg.mutateAsync(name);\n setOpen(false);\n } catch {\n /* error surfaced via createOrg.error */\n }\n }}\n className=\"px-2 py-1.5\"\n >\n <div className=\"px-0.5 pb-1 text-[10px] uppercase tracking-wide text-muted-foreground\">\n New organization\n </div>\n <input\n autoFocus\n value={newName}\n onChange={(e) => setNewName(e.target.value)}\n placeholder=\"Organization name\"\n disabled={createOrg.isPending}\n className=\"w-full rounded-md border border-input bg-background px-2 py-1.5 text-xs outline-none focus:ring-2 focus:ring-ring disabled:opacity-50\"\n />\n {createOrg.error && (\n <div className=\"pt-1 text-[11px] text-destructive\">\n {(createOrg.error as Error).message}\n </div>\n )}\n <div className=\"flex items-center gap-1.5 pt-1.5\">\n <button\n type=\"button\"\n onClick={() => setMode(\"list\")}\n disabled={createOrg.isPending}\n className=\"flex-1 rounded-md px-2 py-1 text-xs text-muted-foreground hover:bg-accent disabled:opacity-50 cursor-pointer\"\n >\n Cancel\n </button>\n <button\n type=\"submit\"\n disabled={createOrg.isPending || !newName.trim()}\n className=\"flex-1 rounded-md bg-primary px-2 py-1 text-xs font-medium text-primary-foreground hover:opacity-90 disabled:opacity-50 cursor-pointer\"\n >\n {createOrg.isPending ? (\n <IconLoader2 className=\"mx-auto h-3 w-3 animate-spin\" />\n ) : (\n \"Create\"\n )}\n </button>\n </div>\n </form>\n )}\n\n {mode === \"invite\" && (\n <form\n onSubmit={async (e) => {\n e.preventDefault();\n const email = inviteEmail.trim();\n if (!email) return;\n try {\n await inviteMember.mutateAsync(email);\n setInviteEmail(\"\");\n setMode(\"list\");\n } catch {\n /* error surfaced via inviteMember.error */\n }\n }}\n className=\"px-2 py-1.5\"\n >\n <div className=\"px-0.5 pb-1 text-[10px] uppercase tracking-wide text-muted-foreground\">\n Invite to {org.orgName}\n </div>\n <input\n autoFocus\n type=\"email\"\n value={inviteEmail}\n onChange={(e) => setInviteEmail(e.target.value)}\n placeholder=\"teammate@company.com\"\n disabled={inviteMember.isPending}\n className=\"w-full rounded-md border border-input bg-background px-2 py-1.5 text-xs outline-none focus:ring-2 focus:ring-ring disabled:opacity-50\"\n />\n {inviteMember.error && (\n <div className=\"pt-1 text-[11px] text-destructive\">\n {(inviteMember.error as Error).message}\n </div>\n )}\n <div className=\"flex items-center gap-1.5 pt-1.5\">\n <button\n type=\"button\"\n onClick={() => setMode(\"list\")}\n disabled={inviteMember.isPending}\n className=\"flex-1 rounded-md px-2 py-1 text-xs text-muted-foreground hover:bg-accent disabled:opacity-50 cursor-pointer\"\n >\n Cancel\n </button>\n <button\n type=\"submit\"\n disabled={inviteMember.isPending || !inviteEmail.trim()}\n className=\"flex-1 rounded-md bg-primary px-2 py-1 text-xs font-medium text-primary-foreground hover:opacity-90 disabled:opacity-50 cursor-pointer\"\n >\n {inviteMember.isPending ? (\n <IconLoader2 className=\"mx-auto h-3 w-3 animate-spin\" />\n ) : (\n \"Send invite\"\n )}\n </button>\n </div>\n </form>\n )}\n </PopoverPrimitive.Content>\n </PopoverPrimitive.Portal>\n </PopoverPrimitive.Root>\n );\n}\n"]}
@@ -1 +1 @@
1
- {"version":3,"file":"TeamPage.d.ts","sourceRoot":"","sources":["../../../src/client/org/TeamPage.tsx"],"names":[],"mappings":"AAAA,OAAO,EAAuB,KAAK,SAAS,EAAE,MAAM,OAAO,CAAC;AA6C5D,MAAM,WAAW,aAAa;IAC5B;;;OAGG;IACH,MAAM,CAAC,EAAE,CAAC,QAAQ,EAAE,SAAS,KAAK,SAAS,CAAC;IAC5C;;OAEG;IACH,KAAK,CAAC,EAAE,MAAM,CAAC;IACf;;;OAGG;IACH,oBAAoB,CAAC,EAAE,MAAM,CAAC;IAC9B;;;OAGG;IACH,SAAS,CAAC,EAAE,MAAM,CAAC;CACpB;AAwwBD;;;GAGG;AACH,wBAAgB,QAAQ,CAAC,EACvB,MAAM,EACN,KAAc,EACd,oBAAoB,EACpB,SAAS,GACV,EAAE,aAAa,2CAoCf"}
1
+ {"version":3,"file":"TeamPage.d.ts","sourceRoot":"","sources":["../../../src/client/org/TeamPage.tsx"],"names":[],"mappings":"AAAA,OAAO,EAA6B,KAAK,SAAS,EAAE,MAAM,OAAO,CAAC;AAgDlE,MAAM,WAAW,aAAa;IAC5B;;;OAGG;IACH,MAAM,CAAC,EAAE,CAAC,QAAQ,EAAE,SAAS,KAAK,SAAS,CAAC;IAC5C;;OAEG;IACH,KAAK,CAAC,EAAE,MAAM,CAAC;IACf;;;OAGG;IACH,oBAAoB,CAAC,EAAE,MAAM,CAAC;IAC9B;;;OAGG;IACH,SAAS,CAAC,EAAE,MAAM,CAAC;CACpB;AAmoCD;;;GAGG;AACH,wBAAgB,QAAQ,CAAC,EACvB,MAAM,EACN,KAAc,EACd,oBAAoB,EACpB,SAAS,GACV,EAAE,aAAa,2CAoCf"}