@agent-native/core 0.20.8 → 0.21.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 (142) hide show
  1. package/dist/action.d.ts +61 -0
  2. package/dist/action.d.ts.map +1 -1
  3. package/dist/action.js +14 -0
  4. package/dist/action.js.map +1 -1
  5. package/dist/agent/production-agent.d.ts +4 -0
  6. package/dist/agent/production-agent.d.ts.map +1 -1
  7. package/dist/agent/production-agent.js +19 -7
  8. package/dist/agent/production-agent.js.map +1 -1
  9. package/dist/agent/types.d.ts +2 -0
  10. package/dist/agent/types.d.ts.map +1 -1
  11. package/dist/agent/types.js.map +1 -1
  12. package/dist/cli/code-agent-executor.d.ts.map +1 -1
  13. package/dist/cli/code-agent-executor.js +1 -0
  14. package/dist/cli/code-agent-executor.js.map +1 -1
  15. package/dist/cli/connect.d.ts +26 -4
  16. package/dist/cli/connect.d.ts.map +1 -1
  17. package/dist/cli/connect.js +578 -10
  18. package/dist/cli/connect.js.map +1 -1
  19. package/dist/cli/templates-meta.d.ts.map +1 -1
  20. package/dist/cli/templates-meta.js +1 -0
  21. package/dist/cli/templates-meta.js.map +1 -1
  22. package/dist/client/AssistantChat.d.ts.map +1 -1
  23. package/dist/client/AssistantChat.js +6 -5
  24. package/dist/client/AssistantChat.js.map +1 -1
  25. package/dist/client/agent-chat-adapter.d.ts.map +1 -1
  26. package/dist/client/agent-chat-adapter.js +25 -4
  27. package/dist/client/agent-chat-adapter.js.map +1 -1
  28. package/dist/client/code-agent-chat-adapter.js +1 -0
  29. package/dist/client/code-agent-chat-adapter.js.map +1 -1
  30. package/dist/client/composer/TiptapComposer.js +1 -1
  31. package/dist/client/composer/TiptapComposer.js.map +1 -1
  32. package/dist/client/conversation/AgentConversation.d.ts.map +1 -1
  33. package/dist/client/conversation/AgentConversation.js +3 -2
  34. package/dist/client/conversation/AgentConversation.js.map +1 -1
  35. package/dist/client/conversation/code-agent-transcript.js +1 -0
  36. package/dist/client/conversation/code-agent-transcript.js.map +1 -1
  37. package/dist/client/conversation/types.d.ts +2 -0
  38. package/dist/client/conversation/types.d.ts.map +1 -1
  39. package/dist/client/conversation/types.js.map +1 -1
  40. package/dist/client/extensions/EmbeddedExtension.d.ts.map +1 -1
  41. package/dist/client/extensions/EmbeddedExtension.js +2 -1
  42. package/dist/client/extensions/EmbeddedExtension.js.map +1 -1
  43. package/dist/client/extensions/ExtensionEditor.d.ts.map +1 -1
  44. package/dist/client/extensions/ExtensionEditor.js +6 -3
  45. package/dist/client/extensions/ExtensionEditor.js.map +1 -1
  46. package/dist/client/extensions/ExtensionViewer.d.ts.map +1 -1
  47. package/dist/client/extensions/ExtensionViewer.js +66 -2
  48. package/dist/client/extensions/ExtensionViewer.js.map +1 -1
  49. package/dist/client/extensions/ExtensionsListPage.d.ts.map +1 -1
  50. package/dist/client/extensions/ExtensionsListPage.js +2 -1
  51. package/dist/client/extensions/ExtensionsListPage.js.map +1 -1
  52. package/dist/client/extensions/ExtensionsSidebarSection.d.ts.map +1 -1
  53. package/dist/client/extensions/ExtensionsSidebarSection.js +5 -7
  54. package/dist/client/extensions/ExtensionsSidebarSection.js.map +1 -1
  55. package/dist/client/extensions/index.d.ts +1 -0
  56. package/dist/client/extensions/index.d.ts.map +1 -1
  57. package/dist/client/extensions/index.js +1 -0
  58. package/dist/client/extensions/index.js.map +1 -1
  59. package/dist/client/index.d.ts +1 -0
  60. package/dist/client/index.d.ts.map +1 -1
  61. package/dist/client/index.js +1 -0
  62. package/dist/client/index.js.map +1 -1
  63. package/dist/client/mcp-apps/McpAppRenderer.d.ts +10 -0
  64. package/dist/client/mcp-apps/McpAppRenderer.d.ts.map +1 -0
  65. package/dist/client/mcp-apps/McpAppRenderer.js +296 -0
  66. package/dist/client/mcp-apps/McpAppRenderer.js.map +1 -0
  67. package/dist/client/sse-event-processor.d.ts +3 -0
  68. package/dist/client/sse-event-processor.d.ts.map +1 -1
  69. package/dist/client/sse-event-processor.js +2 -0
  70. package/dist/client/sse-event-processor.js.map +1 -1
  71. package/dist/code-agents/transcript-normalizer.d.ts +2 -0
  72. package/dist/code-agents/transcript-normalizer.d.ts.map +1 -1
  73. package/dist/code-agents/transcript-normalizer.js +17 -0
  74. package/dist/code-agents/transcript-normalizer.js.map +1 -1
  75. package/dist/db/client.d.ts +19 -0
  76. package/dist/db/client.d.ts.map +1 -1
  77. package/dist/db/client.js +139 -6
  78. package/dist/db/client.js.map +1 -1
  79. package/dist/extensions/actions.d.ts.map +1 -1
  80. package/dist/extensions/actions.js +6 -2
  81. package/dist/extensions/actions.js.map +1 -1
  82. package/dist/extensions/path.d.ts +6 -0
  83. package/dist/extensions/path.d.ts.map +1 -0
  84. package/dist/extensions/path.js +38 -0
  85. package/dist/extensions/path.js.map +1 -0
  86. package/dist/index.browser.d.ts +1 -1
  87. package/dist/index.browser.d.ts.map +1 -1
  88. package/dist/index.browser.js +1 -1
  89. package/dist/index.browser.js.map +1 -1
  90. package/dist/index.d.ts +1 -1
  91. package/dist/index.d.ts.map +1 -1
  92. package/dist/index.js +1 -1
  93. package/dist/index.js.map +1 -1
  94. package/dist/mcp/build-server.d.ts.map +1 -1
  95. package/dist/mcp/build-server.js +154 -4
  96. package/dist/mcp/build-server.js.map +1 -1
  97. package/dist/mcp/connect-store.d.ts +1 -1
  98. package/dist/mcp/connect-store.d.ts.map +1 -1
  99. package/dist/mcp/connect-store.js +1 -1
  100. package/dist/mcp/connect-store.js.map +1 -1
  101. package/dist/mcp/stdio.d.ts +2 -2
  102. package/dist/mcp/stdio.d.ts.map +1 -1
  103. package/dist/mcp/stdio.js +26 -8
  104. package/dist/mcp/stdio.js.map +1 -1
  105. package/dist/mcp-client/app-result.d.ts +40 -0
  106. package/dist/mcp-client/app-result.d.ts.map +1 -0
  107. package/dist/mcp-client/app-result.js +19 -0
  108. package/dist/mcp-client/app-result.js.map +1 -0
  109. package/dist/mcp-client/index.d.ts +5 -2
  110. package/dist/mcp-client/index.d.ts.map +1 -1
  111. package/dist/mcp-client/index.js +185 -23
  112. package/dist/mcp-client/index.js.map +1 -1
  113. package/dist/mcp-client/manager.d.ts +16 -0
  114. package/dist/mcp-client/manager.d.ts.map +1 -1
  115. package/dist/mcp-client/manager.js +58 -1
  116. package/dist/mcp-client/manager.js.map +1 -1
  117. package/dist/mcp-client/routes.d.ts +4 -1
  118. package/dist/mcp-client/routes.d.ts.map +1 -1
  119. package/dist/mcp-client/routes.js +146 -0
  120. package/dist/mcp-client/routes.js.map +1 -1
  121. package/dist/server/agent-chat-plugin.d.ts.map +1 -1
  122. package/dist/server/agent-chat-plugin.js +8 -1
  123. package/dist/server/agent-chat-plugin.js.map +1 -1
  124. package/dist/server/auth.d.ts +2 -0
  125. package/dist/server/auth.d.ts.map +1 -1
  126. package/dist/server/auth.js +2 -2
  127. package/dist/server/auth.js.map +1 -1
  128. package/dist/server/framework-request-handler.d.ts +4 -2
  129. package/dist/server/framework-request-handler.d.ts.map +1 -1
  130. package/dist/server/framework-request-handler.js +25 -11
  131. package/dist/server/framework-request-handler.js.map +1 -1
  132. package/dist/server/index.d.ts +1 -1
  133. package/dist/server/index.d.ts.map +1 -1
  134. package/dist/server/index.js +1 -1
  135. package/dist/server/index.js.map +1 -1
  136. package/dist/styles/agent-conversation.css +53 -0
  137. package/docs/content/actions.md +25 -2
  138. package/docs/content/external-agents.md +62 -8
  139. package/docs/content/key-concepts.md +1 -1
  140. package/docs/content/mcp-clients.md +1 -1
  141. package/docs/content/mcp-protocol.md +16 -11
  142. package/package.json +2 -1
@@ -1 +1 @@
1
- {"version":3,"file":"ExtensionEditor.js","sourceRoot":"","sources":["../../../src/client/extensions/ExtensionEditor.tsx"],"names":[],"mappings":"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","sourcesContent":["import { agentNativePath } from \"../api-path.js\";\nimport { useState, useEffect } from \"react\";\nimport { useQuery, useQueryClient } from \"@tanstack/react-query\";\nimport { Link, useNavigate } from \"react-router\";\nimport {\n IconArrowLeft,\n IconDeviceFloppy,\n IconDots,\n IconTrash,\n IconX,\n} from \"@tabler/icons-react\";\nimport {\n Popover,\n PopoverContent,\n PopoverTrigger,\n} from \"../components/ui/popover.js\";\nimport { cn } from \"../utils.js\";\nimport {\n Tooltip,\n TooltipContent,\n TooltipProvider,\n TooltipTrigger,\n} from \"../components/ui/tooltip.js\";\nimport {\n deleteOrHideExtension,\n invalidateExtensionRemoval,\n} from \"./delete-extension.js\";\n\ninterface SlotDeclaration {\n id: string;\n extensionId: string;\n slotId: string;\n}\n\ninterface Extension {\n id: string;\n name: string;\n description?: string;\n content?: string;\n canDelete?: boolean;\n}\n\nexport interface ExtensionEditorProps {\n extensionId?: string;\n}\n\nexport function ExtensionEditor({ extensionId }: ExtensionEditorProps) {\n const navigate = useNavigate();\n const queryClient = useQueryClient();\n const isEdit = !!extensionId;\n\n const [name, setName] = useState(\"\");\n const [description, setDescription] = useState(\"\");\n const [content, setContent] = useState(\"\");\n const [saving, setSaving] = useState(false);\n const [deleting, setDeleting] = useState(false);\n const [menuOpen, setMenuOpen] = useState(false);\n const [confirmingDelete, setConfirmingDelete] = useState(false);\n\n const { data: slots = [] } = useQuery<SlotDeclaration[]>({\n queryKey: [\"extension-slots\", extensionId],\n queryFn: async () => {\n const res = await fetch(\n agentNativePath(`/_agent-native/slots/extension/${extensionId}`),\n );\n if (!res.ok) return [];\n return res.json();\n },\n enabled: isEdit && menuOpen,\n });\n\n const { data: existingTool } = useQuery<Extension>({\n queryKey: [\"extension\", extensionId],\n queryFn: async () => {\n const res = await fetch(\n agentNativePath(`/_agent-native/extensions/${extensionId}`),\n );\n if (!res.ok) throw new Error(\"Failed to fetch extension\");\n return res.json();\n },\n enabled: isEdit,\n });\n\n useEffect(() => {\n if (existingTool) {\n setName(existingTool.name ?? \"\");\n setDescription(existingTool.description ?? \"\");\n setContent(existingTool.content ?? \"\");\n }\n }, [existingTool]);\n\n const handleSave = async () => {\n if (!name.trim()) return;\n setSaving(true);\n try {\n const body = JSON.stringify({\n name: name.trim(),\n description: description.trim() || undefined,\n content,\n });\n\n if (isEdit) {\n const res = await fetch(\n agentNativePath(`/_agent-native/extensions/${extensionId}`),\n {\n method: \"PUT\",\n headers: { \"Content-Type\": \"application/json\" },\n body,\n },\n );\n if (!res.ok) throw new Error(\"Update failed\");\n queryClient.invalidateQueries({ queryKey: [\"extension\", extensionId] });\n queryClient.invalidateQueries({ queryKey: [\"extensions\"] });\n navigate(`/extensions/${extensionId}`);\n } else {\n const res = await fetch(agentNativePath(\"/_agent-native/extensions\"), {\n method: \"POST\",\n headers: { \"Content-Type\": \"application/json\" },\n body,\n });\n if (!res.ok) throw new Error(\"Create failed\");\n const created = await res.json();\n queryClient.invalidateQueries({ queryKey: [\"extensions\"] });\n navigate(`/extensions/${created.id}`);\n }\n } finally {\n setSaving(false);\n }\n };\n\n const handleDelete = async () => {\n if (!extensionId) return;\n setDeleting(true);\n const prev = queryClient.getQueryData<Extension[]>([\"extensions\"]);\n try {\n queryClient.setQueryData<Extension[]>([\"extensions\"], (old) =>\n (old ?? []).filter((t) => t.id !== extensionId),\n );\n\n await deleteOrHideExtension({\n id: extensionId,\n canDelete: existingTool?.canDelete,\n });\n invalidateExtensionRemoval(queryClient, extensionId);\n slots.forEach((s) =>\n queryClient.invalidateQueries({\n queryKey: [\"slot-installs\", s.slotId],\n }),\n );\n navigate(\"/extensions\");\n } catch {\n if (prev) queryClient.setQueryData([\"extensions\"], prev);\n } finally {\n setDeleting(false);\n setConfirmingDelete(false);\n setMenuOpen(false);\n }\n };\n\n const handleRemoveFromSlot = async (slotId: string) => {\n if (!extensionId) return;\n try {\n await fetch(\n agentNativePath(\n `/_agent-native/slots/${encodeURIComponent(slotId)}/install/${encodeURIComponent(extensionId)}`,\n ),\n { method: \"DELETE\" },\n );\n } finally {\n queryClient.invalidateQueries({ queryKey: [\"slot-installs\", slotId] });\n }\n };\n\n return (\n <TooltipProvider delayDuration={200}>\n <div className=\"flex h-full flex-col\">\n <header className=\"flex items-center justify-between border-b px-4 py-3\">\n <div className=\"flex items-center gap-3\">\n <Link\n to={isEdit ? `/extensions/${extensionId}` : \"/extensions\"}\n className=\"inline-flex cursor-pointer items-center justify-center rounded-md p-1 text-muted-foreground hover:bg-accent hover:text-accent-foreground\"\n aria-label=\"Back\"\n >\n <IconArrowLeft className=\"h-4 w-4\" />\n </Link>\n <h1 className=\"text-sm font-semibold\">\n {isEdit ? \"Edit Extension\" : \"New Extension\"}\n </h1>\n </div>\n <div className=\"flex items-center gap-2\">\n <button\n type=\"button\"\n onClick={handleSave}\n disabled={saving || !name.trim()}\n className={cn(\n \"inline-flex cursor-pointer items-center justify-center gap-1.5 rounded-md bg-primary px-3 py-1.5 text-sm text-primary-foreground hover:bg-primary/90\",\n (saving || !name.trim()) && \"opacity-60\",\n )}\n >\n <IconDeviceFloppy className=\"h-3.5 w-3.5\" />\n {saving ? \"Saving...\" : isEdit ? \"Save\" : \"Create\"}\n </button>\n {isEdit && (\n <Popover\n open={menuOpen}\n onOpenChange={(o) => {\n setMenuOpen(o);\n if (!o) setConfirmingDelete(false);\n }}\n >\n <Tooltip>\n <TooltipTrigger asChild>\n <PopoverTrigger asChild>\n <button\n type=\"button\"\n className=\"inline-flex h-8 w-8 cursor-pointer items-center justify-center rounded-md text-muted-foreground hover:bg-accent hover:text-accent-foreground\"\n aria-label=\"More options\"\n >\n <IconDots className=\"h-4 w-4\" />\n </button>\n </PopoverTrigger>\n </TooltipTrigger>\n <TooltipContent>More options</TooltipContent>\n </Tooltip>\n <PopoverContent align=\"end\" sideOffset={4} className=\"w-72 p-0\">\n {!confirmingDelete ? (\n <>\n <div className=\"px-3 py-2 border-b border-border/40\">\n <p className=\"text-[12px] font-medium\">Appears in</p>\n {slots.length === 0 ? (\n <p className=\"text-[11px] text-muted-foreground/70 mt-0.5\">\n Not installed in any widget areas. Ask the agent to\n add it somewhere.\n </p>\n ) : (\n <p className=\"text-[11px] text-muted-foreground/70 mt-0.5\">\n This extension can render in {slots.length} widget\n area\n {slots.length === 1 ? \"\" : \"s\"}.\n </p>\n )}\n </div>\n {slots.length > 0 && (\n <div className=\"max-h-48 overflow-y-auto py-1\">\n {slots.map((s) => (\n <div\n key={s.id}\n className=\"flex items-center gap-2 px-3 py-1.5 text-[12px]\"\n >\n <span className=\"flex-1 truncate font-mono text-[11px] text-muted-foreground\">\n {s.slotId}\n </span>\n <Tooltip>\n <TooltipTrigger asChild>\n <button\n type=\"button\"\n onClick={() =>\n handleRemoveFromSlot(s.slotId)\n }\n className=\"rounded p-1 text-muted-foreground/60 hover:bg-accent hover:text-foreground cursor-pointer\"\n aria-label=\"Remove from this widget area\"\n >\n <IconX className=\"h-3.5 w-3.5\" />\n </button>\n </TooltipTrigger>\n <TooltipContent>\n Remove from this widget area (for me)\n </TooltipContent>\n </Tooltip>\n </div>\n ))}\n </div>\n )}\n <div className=\"border-t border-border/40 p-1\">\n <button\n type=\"button\"\n onClick={() => setConfirmingDelete(true)}\n className=\"flex w-full items-center gap-2 rounded-sm px-2 py-1.5 text-[12px] text-destructive hover:bg-destructive/10 cursor-pointer text-left\"\n >\n <IconTrash className=\"h-3.5 w-3.5\" />\n <span>\n {existingTool?.canDelete === false\n ? \"Remove from my list...\"\n : \"Delete extension...\"}\n </span>\n </button>\n </div>\n </>\n ) : (\n <div className=\"flex flex-col gap-2 p-3\">\n <p className=\"text-[12px]\">\n {existingTool?.canDelete === false\n ? \"Remove \"\n : \"Delete \"}\n <span className=\"font-medium\">{name}</span>?\n {existingTool?.canDelete === false\n ? \" This hides it from your Extensions list without deleting it for anyone else.\"\n : \" This removes the extension everywhere, for everyone it's shared with.\"}\n </p>\n <div className=\"flex justify-end gap-1\">\n <button\n type=\"button\"\n onClick={() => setConfirmingDelete(false)}\n className=\"rounded-md px-2 py-1 text-[12px] hover:bg-accent cursor-pointer\"\n >\n Cancel\n </button>\n <button\n type=\"button\"\n onClick={handleDelete}\n disabled={deleting}\n className={cn(\n \"rounded-md bg-destructive px-2 py-1 text-[12px] text-destructive-foreground hover:bg-destructive/90 cursor-pointer\",\n deleting && \"opacity-60\",\n )}\n >\n {deleting\n ? existingTool?.canDelete === false\n ? \"Removing...\"\n : \"Deleting...\"\n : existingTool?.canDelete === false\n ? \"Remove\"\n : \"Delete\"}\n </button>\n </div>\n </div>\n )}\n </PopoverContent>\n </Popover>\n )}\n </div>\n </header>\n\n <div className=\"flex flex-1 overflow-hidden\">\n <div className=\"flex w-1/2 flex-col gap-4 overflow-auto border-r p-4\">\n <div>\n <label className=\"mb-1.5 block text-sm font-medium text-foreground\">\n Name\n </label>\n <input\n type=\"text\"\n value={name}\n onChange={(e) => setName(e.target.value)}\n placeholder=\"My Extension\"\n className=\"h-9 w-full rounded-md border border-input bg-background px-3 text-sm text-foreground placeholder:text-muted-foreground focus:outline-none focus:ring-2 focus:ring-ring focus:ring-offset-2 focus:ring-offset-background\"\n />\n </div>\n\n <div>\n <label className=\"mb-1.5 block text-sm font-medium text-foreground\">\n Description\n </label>\n <textarea\n value={description}\n onChange={(e) => setDescription(e.target.value)}\n placeholder=\"What does this extension do?\"\n rows={2}\n className=\"w-full resize-none rounded-md border border-input bg-background px-3 py-2 text-sm text-foreground placeholder:text-muted-foreground focus:outline-none focus:ring-2 focus:ring-ring focus:ring-offset-2 focus:ring-offset-background\"\n />\n </div>\n\n <div className=\"flex flex-1 flex-col\">\n <label className=\"mb-1.5 block text-sm font-medium text-foreground\">\n Content\n </label>\n <textarea\n value={content}\n onChange={(e) => setContent(e.target.value)}\n placeholder=\"<html>...</html>\"\n className=\"flex-1 resize-none rounded-md border border-input bg-background p-3 font-mono text-sm text-foreground placeholder:text-muted-foreground focus:outline-none focus:ring-2 focus:ring-ring focus:ring-offset-2 focus:ring-offset-background\"\n spellCheck={false}\n />\n </div>\n </div>\n\n <div className=\"w-1/2\">\n {content ? (\n <iframe\n srcDoc={content}\n className=\"h-full w-full border-0\"\n sandbox=\"allow-scripts allow-forms\"\n title=\"Extension preview\"\n />\n ) : (\n <div className=\"flex h-full items-center justify-center text-sm text-muted-foreground\">\n Preview will appear here\n </div>\n )}\n </div>\n </div>\n </div>\n </TooltipProvider>\n );\n}\n"]}
1
+ {"version":3,"file":"ExtensionEditor.js","sourceRoot":"","sources":["../../../src/client/extensions/ExtensionEditor.tsx"],"names":[],"mappings":";AAAA,OAAO,EAAE,eAAe,EAAE,MAAM,gBAAgB,CAAC;AACjD,OAAO,EAAE,QAAQ,EAAE,SAAS,EAAE,MAAM,OAAO,CAAC;AAC5C,OAAO,EAAE,QAAQ,EAAE,cAAc,EAAE,MAAM,uBAAuB,CAAC;AACjE,OAAO,EAAE,IAAI,EAAE,WAAW,EAAE,MAAM,cAAc,CAAC;AACjD,OAAO,EACL,aAAa,EACb,gBAAgB,EAChB,QAAQ,EACR,SAAS,EACT,KAAK,GACN,MAAM,qBAAqB,CAAC;AAC7B,OAAO,EACL,OAAO,EACP,cAAc,EACd,cAAc,GACf,MAAM,6BAA6B,CAAC;AACrC,OAAO,EAAE,EAAE,EAAE,MAAM,aAAa,CAAC;AACjC,OAAO,EACL,OAAO,EACP,cAAc,EACd,eAAe,EACf,cAAc,GACf,MAAM,6BAA6B,CAAC;AACrC,OAAO,EACL,qBAAqB,EACrB,0BAA0B,GAC3B,MAAM,uBAAuB,CAAC;AAC/B,OAAO,EAAE,aAAa,EAAE,MAAM,0BAA0B,CAAC;AAoBzD,MAAM,UAAU,eAAe,CAAC,EAAE,WAAW,EAAwB;IACnE,MAAM,QAAQ,GAAG,WAAW,EAAE,CAAC;IAC/B,MAAM,WAAW,GAAG,cAAc,EAAE,CAAC;IACrC,MAAM,MAAM,GAAG,CAAC,CAAC,WAAW,CAAC;IAE7B,MAAM,CAAC,IAAI,EAAE,OAAO,CAAC,GAAG,QAAQ,CAAC,EAAE,CAAC,CAAC;IACrC,MAAM,CAAC,WAAW,EAAE,cAAc,CAAC,GAAG,QAAQ,CAAC,EAAE,CAAC,CAAC;IACnD,MAAM,CAAC,OAAO,EAAE,UAAU,CAAC,GAAG,QAAQ,CAAC,EAAE,CAAC,CAAC;IAC3C,MAAM,CAAC,MAAM,EAAE,SAAS,CAAC,GAAG,QAAQ,CAAC,KAAK,CAAC,CAAC;IAC5C,MAAM,CAAC,QAAQ,EAAE,WAAW,CAAC,GAAG,QAAQ,CAAC,KAAK,CAAC,CAAC;IAChD,MAAM,CAAC,QAAQ,EAAE,WAAW,CAAC,GAAG,QAAQ,CAAC,KAAK,CAAC,CAAC;IAChD,MAAM,CAAC,gBAAgB,EAAE,mBAAmB,CAAC,GAAG,QAAQ,CAAC,KAAK,CAAC,CAAC;IAEhE,MAAM,EAAE,IAAI,EAAE,KAAK,GAAG,EAAE,EAAE,GAAG,QAAQ,CAAoB;QACvD,QAAQ,EAAE,CAAC,iBAAiB,EAAE,WAAW,CAAC;QAC1C,OAAO,EAAE,KAAK,IAAI,EAAE;YAClB,MAAM,GAAG,GAAG,MAAM,KAAK,CACrB,eAAe,CAAC,kCAAkC,WAAW,EAAE,CAAC,CACjE,CAAC;YACF,IAAI,CAAC,GAAG,CAAC,EAAE;gBAAE,OAAO,EAAE,CAAC;YACvB,OAAO,GAAG,CAAC,IAAI,EAAE,CAAC;QACpB,CAAC;QACD,OAAO,EAAE,MAAM,IAAI,QAAQ;KAC5B,CAAC,CAAC;IAEH,MAAM,EAAE,IAAI,EAAE,YAAY,EAAE,GAAG,QAAQ,CAAY;QACjD,QAAQ,EAAE,CAAC,WAAW,EAAE,WAAW,CAAC;QACpC,OAAO,EAAE,KAAK,IAAI,EAAE;YAClB,MAAM,GAAG,GAAG,MAAM,KAAK,CACrB,eAAe,CAAC,6BAA6B,WAAW,EAAE,CAAC,CAC5D,CAAC;YACF,IAAI,CAAC,GAAG,CAAC,EAAE;gBAAE,MAAM,IAAI,KAAK,CAAC,2BAA2B,CAAC,CAAC;YAC1D,OAAO,GAAG,CAAC,IAAI,EAAE,CAAC;QACpB,CAAC;QACD,OAAO,EAAE,MAAM;KAChB,CAAC,CAAC;IAEH,SAAS,CAAC,GAAG,EAAE;QACb,IAAI,YAAY,EAAE,CAAC;YACjB,OAAO,CAAC,YAAY,CAAC,IAAI,IAAI,EAAE,CAAC,CAAC;YACjC,cAAc,CAAC,YAAY,CAAC,WAAW,IAAI,EAAE,CAAC,CAAC;YAC/C,UAAU,CAAC,YAAY,CAAC,OAAO,IAAI,EAAE,CAAC,CAAC;QACzC,CAAC;IACH,CAAC,EAAE,CAAC,YAAY,CAAC,CAAC,CAAC;IAEnB,MAAM,UAAU,GAAG,KAAK,IAAI,EAAE;QAC5B,IAAI,CAAC,IAAI,CAAC,IAAI,EAAE;YAAE,OAAO;QACzB,SAAS,CAAC,IAAI,CAAC,CAAC;QAChB,IAAI,CAAC;YACH,MAAM,IAAI,GAAG,IAAI,CAAC,SAAS,CAAC;gBAC1B,IAAI,EAAE,IAAI,CAAC,IAAI,EAAE;gBACjB,WAAW,EAAE,WAAW,CAAC,IAAI,EAAE,IAAI,SAAS;gBAC5C,OAAO;aACR,CAAC,CAAC;YAEH,IAAI,MAAM,EAAE,CAAC;gBACX,MAAM,GAAG,GAAG,MAAM,KAAK,CACrB,eAAe,CAAC,6BAA6B,WAAW,EAAE,CAAC,EAC3D;oBACE,MAAM,EAAE,KAAK;oBACb,OAAO,EAAE,EAAE,cAAc,EAAE,kBAAkB,EAAE;oBAC/C,IAAI;iBACL,CACF,CAAC;gBACF,IAAI,CAAC,GAAG,CAAC,EAAE;oBAAE,MAAM,IAAI,KAAK,CAAC,eAAe,CAAC,CAAC;gBAC9C,WAAW,CAAC,iBAAiB,CAAC,EAAE,QAAQ,EAAE,CAAC,WAAW,EAAE,WAAW,CAAC,EAAE,CAAC,CAAC;gBACxE,WAAW,CAAC,iBAAiB,CAAC,EAAE,QAAQ,EAAE,CAAC,YAAY,CAAC,EAAE,CAAC,CAAC;gBAC5D,QAAQ,CAAC,aAAa,CAAC,WAAW,EAAE,IAAI,CAAC,IAAI,EAAE,CAAC,CAAC,CAAC;YACpD,CAAC;iBAAM,CAAC;gBACN,MAAM,GAAG,GAAG,MAAM,KAAK,CAAC,eAAe,CAAC,2BAA2B,CAAC,EAAE;oBACpE,MAAM,EAAE,MAAM;oBACd,OAAO,EAAE,EAAE,cAAc,EAAE,kBAAkB,EAAE;oBAC/C,IAAI;iBACL,CAAC,CAAC;gBACH,IAAI,CAAC,GAAG,CAAC,EAAE;oBAAE,MAAM,IAAI,KAAK,CAAC,eAAe,CAAC,CAAC;gBAC9C,MAAM,OAAO,GAAG,MAAM,GAAG,CAAC,IAAI,EAAE,CAAC;gBACjC,WAAW,CAAC,iBAAiB,CAAC,EAAE,QAAQ,EAAE,CAAC,YAAY,CAAC,EAAE,CAAC,CAAC;gBAC5D,QAAQ,CAAC,aAAa,CAAC,OAAO,CAAC,EAAE,EAAE,OAAO,CAAC,IAAI,IAAI,IAAI,CAAC,IAAI,EAAE,CAAC,CAAC,CAAC;YACnE,CAAC;QACH,CAAC;gBAAS,CAAC;YACT,SAAS,CAAC,KAAK,CAAC,CAAC;QACnB,CAAC;IACH,CAAC,CAAC;IAEF,MAAM,YAAY,GAAG,KAAK,IAAI,EAAE;QAC9B,IAAI,CAAC,WAAW;YAAE,OAAO;QACzB,WAAW,CAAC,IAAI,CAAC,CAAC;QAClB,MAAM,IAAI,GAAG,WAAW,CAAC,YAAY,CAAc,CAAC,YAAY,CAAC,CAAC,CAAC;QACnE,IAAI,CAAC;YACH,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;YAEF,MAAM,qBAAqB,CAAC;gBAC1B,EAAE,EAAE,WAAW;gBACf,SAAS,EAAE,YAAY,EAAE,SAAS;aACnC,CAAC,CAAC;YACH,0BAA0B,CAAC,WAAW,EAAE,WAAW,CAAC,CAAC;YACrD,KAAK,CAAC,OAAO,CAAC,CAAC,CAAC,EAAE,EAAE,CAClB,WAAW,CAAC,iBAAiB,CAAC;gBAC5B,QAAQ,EAAE,CAAC,eAAe,EAAE,CAAC,CAAC,MAAM,CAAC;aACtC,CAAC,CACH,CAAC;YACF,QAAQ,CAAC,aAAa,CAAC,CAAC;QAC1B,CAAC;QAAC,MAAM,CAAC;YACP,IAAI,IAAI;gBAAE,WAAW,CAAC,YAAY,CAAC,CAAC,YAAY,CAAC,EAAE,IAAI,CAAC,CAAC;QAC3D,CAAC;gBAAS,CAAC;YACT,WAAW,CAAC,KAAK,CAAC,CAAC;YACnB,mBAAmB,CAAC,KAAK,CAAC,CAAC;YAC3B,WAAW,CAAC,KAAK,CAAC,CAAC;QACrB,CAAC;IACH,CAAC,CAAC;IAEF,MAAM,oBAAoB,GAAG,KAAK,EAAE,MAAc,EAAE,EAAE;QACpD,IAAI,CAAC,WAAW;YAAE,OAAO;QACzB,IAAI,CAAC;YACH,MAAM,KAAK,CACT,eAAe,CACb,wBAAwB,kBAAkB,CAAC,MAAM,CAAC,YAAY,kBAAkB,CAAC,WAAW,CAAC,EAAE,CAChG,EACD,EAAE,MAAM,EAAE,QAAQ,EAAE,CACrB,CAAC;QACJ,CAAC;gBAAS,CAAC;YACT,WAAW,CAAC,iBAAiB,CAAC,EAAE,QAAQ,EAAE,CAAC,eAAe,EAAE,MAAM,CAAC,EAAE,CAAC,CAAC;QACzE,CAAC;IACH,CAAC,CAAC;IAEF,OAAO,CACL,KAAC,eAAe,IAAC,aAAa,EAAE,GAAG,YACjC,eAAK,SAAS,EAAC,sBAAsB,aACnC,kBAAQ,SAAS,EAAC,sDAAsD,aACtE,eAAK,SAAS,EAAC,yBAAyB,aACtC,KAAC,IAAI,IACH,EAAE,EACA,WAAW;wCACT,CAAC,CAAC,aAAa,CAAC,WAAW,EAAE,YAAY,EAAE,IAAI,IAAI,IAAI,CAAC;wCACxD,CAAC,CAAC,aAAa,EAEnB,SAAS,EAAC,0IAA0I,gBACzI,MAAM,YAEjB,KAAC,aAAa,IAAC,SAAS,EAAC,SAAS,GAAG,GAChC,EACP,aAAI,SAAS,EAAC,uBAAuB,YAClC,MAAM,CAAC,CAAC,CAAC,gBAAgB,CAAC,CAAC,CAAC,eAAe,GACzC,IACD,EACN,eAAK,SAAS,EAAC,yBAAyB,aACtC,kBACE,IAAI,EAAC,QAAQ,EACb,OAAO,EAAE,UAAU,EACnB,QAAQ,EAAE,MAAM,IAAI,CAAC,IAAI,CAAC,IAAI,EAAE,EAChC,SAAS,EAAE,EAAE,CACX,sJAAsJ,EACtJ,CAAC,MAAM,IAAI,CAAC,IAAI,CAAC,IAAI,EAAE,CAAC,IAAI,YAAY,CACzC,aAED,KAAC,gBAAgB,IAAC,SAAS,EAAC,aAAa,GAAG,EAC3C,MAAM,CAAC,CAAC,CAAC,WAAW,CAAC,CAAC,CAAC,MAAM,CAAC,CAAC,CAAC,MAAM,CAAC,CAAC,CAAC,QAAQ,IAC3C,EACR,MAAM,IAAI,CACT,MAAC,OAAO,IACN,IAAI,EAAE,QAAQ,EACd,YAAY,EAAE,CAAC,CAAC,EAAE,EAAE;wCAClB,WAAW,CAAC,CAAC,CAAC,CAAC;wCACf,IAAI,CAAC,CAAC;4CAAE,mBAAmB,CAAC,KAAK,CAAC,CAAC;oCACrC,CAAC,aAED,MAAC,OAAO,eACN,KAAC,cAAc,IAAC,OAAO,kBACrB,KAAC,cAAc,IAAC,OAAO,kBACrB,iBACE,IAAI,EAAC,QAAQ,EACb,SAAS,EAAC,8IAA8I,gBAC7I,cAAc,YAEzB,KAAC,QAAQ,IAAC,SAAS,EAAC,SAAS,GAAG,GACzB,GACM,GACF,EACjB,KAAC,cAAc,+BAA8B,IACrC,EACV,KAAC,cAAc,IAAC,KAAK,EAAC,KAAK,EAAC,UAAU,EAAE,CAAC,EAAE,SAAS,EAAC,UAAU,YAC5D,CAAC,gBAAgB,CAAC,CAAC,CAAC,CACnB,8BACE,eAAK,SAAS,EAAC,qCAAqC,aAClD,YAAG,SAAS,EAAC,yBAAyB,2BAAe,EACpD,KAAK,CAAC,MAAM,KAAK,CAAC,CAAC,CAAC,CAAC,CACpB,YAAG,SAAS,EAAC,6CAA6C,sFAGtD,CACL,CAAC,CAAC,CAAC,CACF,aAAG,SAAS,EAAC,6CAA6C,8CAC1B,KAAK,CAAC,MAAM,kBAEzC,KAAK,CAAC,MAAM,KAAK,CAAC,CAAC,CAAC,CAAC,EAAE,CAAC,CAAC,CAAC,GAAG,SAC5B,CACL,IACG,EACL,KAAK,CAAC,MAAM,GAAG,CAAC,IAAI,CACnB,cAAK,SAAS,EAAC,+BAA+B,YAC3C,KAAK,CAAC,GAAG,CAAC,CAAC,CAAC,EAAE,EAAE,CAAC,CAChB,eAEE,SAAS,EAAC,iDAAiD,aAE3D,eAAM,SAAS,EAAC,6DAA6D,YAC1E,CAAC,CAAC,MAAM,GACJ,EACP,MAAC,OAAO,eACN,KAAC,cAAc,IAAC,OAAO,kBACrB,iBACE,IAAI,EAAC,QAAQ,EACb,OAAO,EAAE,GAAG,EAAE,CACZ,oBAAoB,CAAC,CAAC,CAAC,MAAM,CAAC,EAEhC,SAAS,EAAC,2FAA2F,gBAC1F,8BAA8B,YAEzC,KAAC,KAAK,IAAC,SAAS,EAAC,aAAa,GAAG,GAC1B,GACM,EACjB,KAAC,cAAc,wDAEE,IACT,KAtBL,CAAC,CAAC,EAAE,CAuBL,CACP,CAAC,GACE,CACP,EACD,cAAK,SAAS,EAAC,+BAA+B,YAC5C,kBACE,IAAI,EAAC,QAAQ,EACb,OAAO,EAAE,GAAG,EAAE,CAAC,mBAAmB,CAAC,IAAI,CAAC,EACxC,SAAS,EAAC,qIAAqI,aAE/I,KAAC,SAAS,IAAC,SAAS,EAAC,aAAa,GAAG,EACrC,yBACG,YAAY,EAAE,SAAS,KAAK,KAAK;wEAChC,CAAC,CAAC,wBAAwB;wEAC1B,CAAC,CAAC,qBAAqB,GACpB,IACA,GACL,IACL,CACJ,CAAC,CAAC,CAAC,CACF,eAAK,SAAS,EAAC,yBAAyB,aACtC,aAAG,SAAS,EAAC,aAAa,aACvB,YAAY,EAAE,SAAS,KAAK,KAAK;gEAChC,CAAC,CAAC,SAAS;gEACX,CAAC,CAAC,SAAS,EACb,eAAM,SAAS,EAAC,aAAa,YAAE,IAAI,GAAQ,OAC1C,YAAY,EAAE,SAAS,KAAK,KAAK;gEAChC,CAAC,CAAC,+EAA+E;gEACjF,CAAC,CAAC,wEAAwE,IAC1E,EACJ,eAAK,SAAS,EAAC,wBAAwB,aACrC,iBACE,IAAI,EAAC,QAAQ,EACb,OAAO,EAAE,GAAG,EAAE,CAAC,mBAAmB,CAAC,KAAK,CAAC,EACzC,SAAS,EAAC,iEAAiE,uBAGpE,EACT,iBACE,IAAI,EAAC,QAAQ,EACb,OAAO,EAAE,YAAY,EACrB,QAAQ,EAAE,QAAQ,EAClB,SAAS,EAAE,EAAE,CACX,oHAAoH,EACpH,QAAQ,IAAI,YAAY,CACzB,YAEA,QAAQ;oEACP,CAAC,CAAC,YAAY,EAAE,SAAS,KAAK,KAAK;wEACjC,CAAC,CAAC,aAAa;wEACf,CAAC,CAAC,aAAa;oEACjB,CAAC,CAAC,YAAY,EAAE,SAAS,KAAK,KAAK;wEACjC,CAAC,CAAC,QAAQ;wEACV,CAAC,CAAC,QAAQ,GACP,IACL,IACF,CACP,GACc,IACT,CACX,IACG,IACC,EAET,eAAK,SAAS,EAAC,6BAA6B,aAC1C,eAAK,SAAS,EAAC,sDAAsD,aACnE,0BACE,gBAAO,SAAS,EAAC,kDAAkD,qBAE3D,EACR,gBACE,IAAI,EAAC,MAAM,EACX,KAAK,EAAE,IAAI,EACX,QAAQ,EAAE,CAAC,CAAC,EAAE,EAAE,CAAC,OAAO,CAAC,CAAC,CAAC,MAAM,CAAC,KAAK,CAAC,EACxC,WAAW,EAAC,cAAc,EAC1B,SAAS,EAAC,yNAAyN,GACnO,IACE,EAEN,0BACE,gBAAO,SAAS,EAAC,kDAAkD,4BAE3D,EACR,mBACE,KAAK,EAAE,WAAW,EAClB,QAAQ,EAAE,CAAC,CAAC,EAAE,EAAE,CAAC,cAAc,CAAC,CAAC,CAAC,MAAM,CAAC,KAAK,CAAC,EAC/C,WAAW,EAAC,8BAA8B,EAC1C,IAAI,EAAE,CAAC,EACP,SAAS,EAAC,sOAAsO,GAChP,IACE,EAEN,eAAK,SAAS,EAAC,sBAAsB,aACnC,gBAAO,SAAS,EAAC,kDAAkD,wBAE3D,EACR,mBACE,KAAK,EAAE,OAAO,EACd,QAAQ,EAAE,CAAC,CAAC,EAAE,EAAE,CAAC,UAAU,CAAC,CAAC,CAAC,MAAM,CAAC,KAAK,CAAC,EAC3C,WAAW,EAAC,kBAAkB,EAC9B,SAAS,EAAC,0OAA0O,EACpP,UAAU,EAAE,KAAK,GACjB,IACE,IACF,EAEN,cAAK,SAAS,EAAC,OAAO,YACnB,OAAO,CAAC,CAAC,CAAC,CACT,iBACE,MAAM,EAAE,OAAO,EACf,SAAS,EAAC,wBAAwB,EAClC,OAAO,EAAC,2BAA2B,EACnC,KAAK,EAAC,mBAAmB,GACzB,CACH,CAAC,CAAC,CAAC,CACF,cAAK,SAAS,EAAC,uEAAuE,yCAEhF,CACP,GACG,IACF,IACF,GACU,CACnB,CAAC;AACJ,CAAC","sourcesContent":["import { agentNativePath } from \"../api-path.js\";\nimport { useState, useEffect } from \"react\";\nimport { useQuery, useQueryClient } from \"@tanstack/react-query\";\nimport { Link, useNavigate } from \"react-router\";\nimport {\n IconArrowLeft,\n IconDeviceFloppy,\n IconDots,\n IconTrash,\n IconX,\n} from \"@tabler/icons-react\";\nimport {\n Popover,\n PopoverContent,\n PopoverTrigger,\n} from \"../components/ui/popover.js\";\nimport { cn } from \"../utils.js\";\nimport {\n Tooltip,\n TooltipContent,\n TooltipProvider,\n TooltipTrigger,\n} from \"../components/ui/tooltip.js\";\nimport {\n deleteOrHideExtension,\n invalidateExtensionRemoval,\n} from \"./delete-extension.js\";\nimport { extensionPath } from \"../../extensions/path.js\";\n\ninterface SlotDeclaration {\n id: string;\n extensionId: string;\n slotId: string;\n}\n\ninterface Extension {\n id: string;\n name: string;\n description?: string;\n content?: string;\n canDelete?: boolean;\n}\n\nexport interface ExtensionEditorProps {\n extensionId?: string;\n}\n\nexport function ExtensionEditor({ extensionId }: ExtensionEditorProps) {\n const navigate = useNavigate();\n const queryClient = useQueryClient();\n const isEdit = !!extensionId;\n\n const [name, setName] = useState(\"\");\n const [description, setDescription] = useState(\"\");\n const [content, setContent] = useState(\"\");\n const [saving, setSaving] = useState(false);\n const [deleting, setDeleting] = useState(false);\n const [menuOpen, setMenuOpen] = useState(false);\n const [confirmingDelete, setConfirmingDelete] = useState(false);\n\n const { data: slots = [] } = useQuery<SlotDeclaration[]>({\n queryKey: [\"extension-slots\", extensionId],\n queryFn: async () => {\n const res = await fetch(\n agentNativePath(`/_agent-native/slots/extension/${extensionId}`),\n );\n if (!res.ok) return [];\n return res.json();\n },\n enabled: isEdit && menuOpen,\n });\n\n const { data: existingTool } = useQuery<Extension>({\n queryKey: [\"extension\", extensionId],\n queryFn: async () => {\n const res = await fetch(\n agentNativePath(`/_agent-native/extensions/${extensionId}`),\n );\n if (!res.ok) throw new Error(\"Failed to fetch extension\");\n return res.json();\n },\n enabled: isEdit,\n });\n\n useEffect(() => {\n if (existingTool) {\n setName(existingTool.name ?? \"\");\n setDescription(existingTool.description ?? \"\");\n setContent(existingTool.content ?? \"\");\n }\n }, [existingTool]);\n\n const handleSave = async () => {\n if (!name.trim()) return;\n setSaving(true);\n try {\n const body = JSON.stringify({\n name: name.trim(),\n description: description.trim() || undefined,\n content,\n });\n\n if (isEdit) {\n const res = await fetch(\n agentNativePath(`/_agent-native/extensions/${extensionId}`),\n {\n method: \"PUT\",\n headers: { \"Content-Type\": \"application/json\" },\n body,\n },\n );\n if (!res.ok) throw new Error(\"Update failed\");\n queryClient.invalidateQueries({ queryKey: [\"extension\", extensionId] });\n queryClient.invalidateQueries({ queryKey: [\"extensions\"] });\n navigate(extensionPath(extensionId, name.trim()));\n } else {\n const res = await fetch(agentNativePath(\"/_agent-native/extensions\"), {\n method: \"POST\",\n headers: { \"Content-Type\": \"application/json\" },\n body,\n });\n if (!res.ok) throw new Error(\"Create failed\");\n const created = await res.json();\n queryClient.invalidateQueries({ queryKey: [\"extensions\"] });\n navigate(extensionPath(created.id, created.name ?? name.trim()));\n }\n } finally {\n setSaving(false);\n }\n };\n\n const handleDelete = async () => {\n if (!extensionId) return;\n setDeleting(true);\n const prev = queryClient.getQueryData<Extension[]>([\"extensions\"]);\n try {\n queryClient.setQueryData<Extension[]>([\"extensions\"], (old) =>\n (old ?? []).filter((t) => t.id !== extensionId),\n );\n\n await deleteOrHideExtension({\n id: extensionId,\n canDelete: existingTool?.canDelete,\n });\n invalidateExtensionRemoval(queryClient, extensionId);\n slots.forEach((s) =>\n queryClient.invalidateQueries({\n queryKey: [\"slot-installs\", s.slotId],\n }),\n );\n navigate(\"/extensions\");\n } catch {\n if (prev) queryClient.setQueryData([\"extensions\"], prev);\n } finally {\n setDeleting(false);\n setConfirmingDelete(false);\n setMenuOpen(false);\n }\n };\n\n const handleRemoveFromSlot = async (slotId: string) => {\n if (!extensionId) return;\n try {\n await fetch(\n agentNativePath(\n `/_agent-native/slots/${encodeURIComponent(slotId)}/install/${encodeURIComponent(extensionId)}`,\n ),\n { method: \"DELETE\" },\n );\n } finally {\n queryClient.invalidateQueries({ queryKey: [\"slot-installs\", slotId] });\n }\n };\n\n return (\n <TooltipProvider delayDuration={200}>\n <div className=\"flex h-full flex-col\">\n <header className=\"flex items-center justify-between border-b px-4 py-3\">\n <div className=\"flex items-center gap-3\">\n <Link\n to={\n extensionId\n ? extensionPath(extensionId, existingTool?.name ?? name)\n : \"/extensions\"\n }\n className=\"inline-flex cursor-pointer items-center justify-center rounded-md p-1 text-muted-foreground hover:bg-accent hover:text-accent-foreground\"\n aria-label=\"Back\"\n >\n <IconArrowLeft className=\"h-4 w-4\" />\n </Link>\n <h1 className=\"text-sm font-semibold\">\n {isEdit ? \"Edit Extension\" : \"New Extension\"}\n </h1>\n </div>\n <div className=\"flex items-center gap-2\">\n <button\n type=\"button\"\n onClick={handleSave}\n disabled={saving || !name.trim()}\n className={cn(\n \"inline-flex cursor-pointer items-center justify-center gap-1.5 rounded-md bg-primary px-3 py-1.5 text-sm text-primary-foreground hover:bg-primary/90\",\n (saving || !name.trim()) && \"opacity-60\",\n )}\n >\n <IconDeviceFloppy className=\"h-3.5 w-3.5\" />\n {saving ? \"Saving...\" : isEdit ? \"Save\" : \"Create\"}\n </button>\n {isEdit && (\n <Popover\n open={menuOpen}\n onOpenChange={(o) => {\n setMenuOpen(o);\n if (!o) setConfirmingDelete(false);\n }}\n >\n <Tooltip>\n <TooltipTrigger asChild>\n <PopoverTrigger asChild>\n <button\n type=\"button\"\n className=\"inline-flex h-8 w-8 cursor-pointer items-center justify-center rounded-md text-muted-foreground hover:bg-accent hover:text-accent-foreground\"\n aria-label=\"More options\"\n >\n <IconDots className=\"h-4 w-4\" />\n </button>\n </PopoverTrigger>\n </TooltipTrigger>\n <TooltipContent>More options</TooltipContent>\n </Tooltip>\n <PopoverContent align=\"end\" sideOffset={4} className=\"w-72 p-0\">\n {!confirmingDelete ? (\n <>\n <div className=\"px-3 py-2 border-b border-border/40\">\n <p className=\"text-[12px] font-medium\">Appears in</p>\n {slots.length === 0 ? (\n <p className=\"text-[11px] text-muted-foreground/70 mt-0.5\">\n Not installed in any widget areas. Ask the agent to\n add it somewhere.\n </p>\n ) : (\n <p className=\"text-[11px] text-muted-foreground/70 mt-0.5\">\n This extension can render in {slots.length} widget\n area\n {slots.length === 1 ? \"\" : \"s\"}.\n </p>\n )}\n </div>\n {slots.length > 0 && (\n <div className=\"max-h-48 overflow-y-auto py-1\">\n {slots.map((s) => (\n <div\n key={s.id}\n className=\"flex items-center gap-2 px-3 py-1.5 text-[12px]\"\n >\n <span className=\"flex-1 truncate font-mono text-[11px] text-muted-foreground\">\n {s.slotId}\n </span>\n <Tooltip>\n <TooltipTrigger asChild>\n <button\n type=\"button\"\n onClick={() =>\n handleRemoveFromSlot(s.slotId)\n }\n className=\"rounded p-1 text-muted-foreground/60 hover:bg-accent hover:text-foreground cursor-pointer\"\n aria-label=\"Remove from this widget area\"\n >\n <IconX className=\"h-3.5 w-3.5\" />\n </button>\n </TooltipTrigger>\n <TooltipContent>\n Remove from this widget area (for me)\n </TooltipContent>\n </Tooltip>\n </div>\n ))}\n </div>\n )}\n <div className=\"border-t border-border/40 p-1\">\n <button\n type=\"button\"\n onClick={() => setConfirmingDelete(true)}\n className=\"flex w-full items-center gap-2 rounded-sm px-2 py-1.5 text-[12px] text-destructive hover:bg-destructive/10 cursor-pointer text-left\"\n >\n <IconTrash className=\"h-3.5 w-3.5\" />\n <span>\n {existingTool?.canDelete === false\n ? \"Remove from my list...\"\n : \"Delete extension...\"}\n </span>\n </button>\n </div>\n </>\n ) : (\n <div className=\"flex flex-col gap-2 p-3\">\n <p className=\"text-[12px]\">\n {existingTool?.canDelete === false\n ? \"Remove \"\n : \"Delete \"}\n <span className=\"font-medium\">{name}</span>?\n {existingTool?.canDelete === false\n ? \" This hides it from your Extensions list without deleting it for anyone else.\"\n : \" This removes the extension everywhere, for everyone it's shared with.\"}\n </p>\n <div className=\"flex justify-end gap-1\">\n <button\n type=\"button\"\n onClick={() => setConfirmingDelete(false)}\n className=\"rounded-md px-2 py-1 text-[12px] hover:bg-accent cursor-pointer\"\n >\n Cancel\n </button>\n <button\n type=\"button\"\n onClick={handleDelete}\n disabled={deleting}\n className={cn(\n \"rounded-md bg-destructive px-2 py-1 text-[12px] text-destructive-foreground hover:bg-destructive/90 cursor-pointer\",\n deleting && \"opacity-60\",\n )}\n >\n {deleting\n ? existingTool?.canDelete === false\n ? \"Removing...\"\n : \"Deleting...\"\n : existingTool?.canDelete === false\n ? \"Remove\"\n : \"Delete\"}\n </button>\n </div>\n </div>\n )}\n </PopoverContent>\n </Popover>\n )}\n </div>\n </header>\n\n <div className=\"flex flex-1 overflow-hidden\">\n <div className=\"flex w-1/2 flex-col gap-4 overflow-auto border-r p-4\">\n <div>\n <label className=\"mb-1.5 block text-sm font-medium text-foreground\">\n Name\n </label>\n <input\n type=\"text\"\n value={name}\n onChange={(e) => setName(e.target.value)}\n placeholder=\"My Extension\"\n className=\"h-9 w-full rounded-md border border-input bg-background px-3 text-sm text-foreground placeholder:text-muted-foreground focus:outline-none focus:ring-2 focus:ring-ring focus:ring-offset-2 focus:ring-offset-background\"\n />\n </div>\n\n <div>\n <label className=\"mb-1.5 block text-sm font-medium text-foreground\">\n Description\n </label>\n <textarea\n value={description}\n onChange={(e) => setDescription(e.target.value)}\n placeholder=\"What does this extension do?\"\n rows={2}\n className=\"w-full resize-none rounded-md border border-input bg-background px-3 py-2 text-sm text-foreground placeholder:text-muted-foreground focus:outline-none focus:ring-2 focus:ring-ring focus:ring-offset-2 focus:ring-offset-background\"\n />\n </div>\n\n <div className=\"flex flex-1 flex-col\">\n <label className=\"mb-1.5 block text-sm font-medium text-foreground\">\n Content\n </label>\n <textarea\n value={content}\n onChange={(e) => setContent(e.target.value)}\n placeholder=\"<html>...</html>\"\n className=\"flex-1 resize-none rounded-md border border-input bg-background p-3 font-mono text-sm text-foreground placeholder:text-muted-foreground focus:outline-none focus:ring-2 focus:ring-ring focus:ring-offset-2 focus:ring-offset-background\"\n spellCheck={false}\n />\n </div>\n </div>\n\n <div className=\"w-1/2\">\n {content ? (\n <iframe\n srcDoc={content}\n className=\"h-full w-full border-0\"\n sandbox=\"allow-scripts allow-forms\"\n title=\"Extension preview\"\n />\n ) : (\n <div className=\"flex h-full items-center justify-center text-sm text-muted-foreground\">\n Preview will appear here\n </div>\n )}\n </div>\n </div>\n </div>\n </TooltipProvider>\n );\n}\n"]}
@@ -1 +1 @@
1
- {"version":3,"file":"ExtensionViewer.d.ts","sourceRoot":"","sources":["../../../src/client/extensions/ExtensionViewer.tsx"],"names":[],"mappings":"AA2FA,MAAM,WAAW,oBAAoB;IACnC,WAAW,EAAE,MAAM,CAAC;CACrB;AAgFD,wBAAgB,eAAe,CAAC,EAAE,WAAW,EAAE,EAAE,oBAAoB,2CAmfpE"}
1
+ {"version":3,"file":"ExtensionViewer.d.ts","sourceRoot":"","sources":["../../../src/client/extensions/ExtensionViewer.tsx"],"names":[],"mappings":"AA4FA,MAAM,WAAW,oBAAoB;IACnC,WAAW,EAAE,MAAM,CAAC;CACrB;AAgID,wBAAgB,eAAe,CAAC,EAAE,WAAW,EAAE,EAAE,oBAAoB,2CA6gBpE"}
@@ -1,8 +1,8 @@
1
1
  import { jsx as _jsx, jsxs as _jsxs, Fragment as _Fragment } from "react/jsx-runtime";
2
- import { agentNativePath } from "../api-path.js";
2
+ import { agentNativePath, appPath } from "../api-path.js";
3
3
  import { useState, useEffect, useRef, useCallback, useMemo } from "react";
4
4
  import { useQuery, useQueryClient } from "@tanstack/react-query";
5
- import { Link, useNavigate } from "react-router";
5
+ import { Link, useLocation, useNavigate } from "react-router";
6
6
  import { IconArrowLeft, IconChevronRight, IconDots, IconLoader2, IconPencil, IconRefresh, IconTrash, IconX, } from "@tabler/icons-react";
7
7
  import { ShareButton } from "../sharing/ShareButton.js";
8
8
  import { AgentToggleButton } from "../AgentPanel.js";
@@ -13,6 +13,7 @@ import { Popover, PopoverContent, PopoverTrigger, } from "../components/ui/popov
13
13
  import { isAllowedExtensionPath, sanitizeExtensionRequestOptions, checkBridgePolicy, } from "./iframe-bridge.js";
14
14
  import { Tooltip, TooltipContent, TooltipProvider, TooltipTrigger, } from "../components/ui/tooltip.js";
15
15
  import { deleteOrHideExtension, invalidateExtensionRemoval, } from "./delete-extension.js";
16
+ import { extensionPath, isExtensionPathname } from "../../extensions/path.js";
16
17
  const THEME_CSS_VARS = [
17
18
  "--background",
18
19
  "--foreground",
@@ -53,6 +54,50 @@ function getParentThemeVars() {
53
54
  }
54
55
  return vars;
55
56
  }
57
+ function readExtensionTitleSuffix() {
58
+ const current = typeof document !== "undefined" ? document.title.trim() : "";
59
+ const match = current.match(/^(?:Extension|Tool)s?\s+(?:\u2014|-)\s+(.+)$/);
60
+ return match?.[1]?.trim() || null;
61
+ }
62
+ function extensionDocumentTitle(name, suffix) {
63
+ return suffix ? `${name} \u2014 ${suffix}` : `${name} \u2014 Extensions`;
64
+ }
65
+ function applyCanonicalLink(path) {
66
+ if (typeof document === "undefined" || typeof window === "undefined") {
67
+ return () => { };
68
+ }
69
+ let link = document.querySelector('link[rel="canonical"]');
70
+ const created = !link;
71
+ const previousHref = link?.getAttribute("href") ?? null;
72
+ const previousMarker = link?.dataset.agentNativeExtensionCanonical;
73
+ if (!link) {
74
+ link = document.createElement("link");
75
+ link.rel = "canonical";
76
+ document.head.appendChild(link);
77
+ }
78
+ link.dataset.agentNativeExtensionCanonical = "true";
79
+ link.href = new URL(appPath(path), window.location.origin).toString();
80
+ return () => {
81
+ if (!link)
82
+ return;
83
+ if (created) {
84
+ link.remove();
85
+ return;
86
+ }
87
+ if (previousHref === null) {
88
+ link.removeAttribute("href");
89
+ }
90
+ else {
91
+ link.href = previousHref;
92
+ }
93
+ if (previousMarker === undefined) {
94
+ delete link.dataset.agentNativeExtensionCanonical;
95
+ }
96
+ else {
97
+ link.dataset.agentNativeExtensionCanonical = previousMarker;
98
+ }
99
+ };
100
+ }
56
101
  function EditToolPopover({ extension, onOpenChange, }) {
57
102
  const [open, setOpen] = useState(false);
58
103
  const setOpenAndNotify = (v) => {
@@ -97,6 +142,8 @@ function EditToolPopover({ extension, onOpenChange, }) {
97
142
  return (_jsxs(Popover, { open: open, onOpenChange: setOpenAndNotify, children: [_jsxs(Tooltip, { children: [_jsx(TooltipTrigger, { asChild: true, children: _jsx(PopoverTrigger, { asChild: true, children: _jsx("button", { type: "button", className: "inline-flex items-center justify-center rounded-md h-8 w-8 text-muted-foreground hover:bg-accent hover:text-accent-foreground cursor-pointer", children: _jsx(IconPencil, { className: "h-4 w-4" }) }) }) }), _jsx(TooltipContent, { children: "Edit" })] }), _jsxs(PopoverContent, { align: "end", sideOffset: 6, className: "w-[420px] p-3", children: [_jsx("p", { className: "px-1 pb-2 text-sm font-semibold text-foreground", children: "Edit extension" }), _jsx(PromptComposer, { autoFocus: true, placeholder: "What would you like to change?", draftScope: `extensions:edit:${extension.id}`, onSubmit: handleSubmit })] })] }));
98
143
  }
99
144
  export function ExtensionViewer({ extensionId }) {
145
+ const location = useLocation();
146
+ const navigate = useNavigate();
100
147
  const [isDark, setIsDark] = useState(false);
101
148
  const [iframeReady, setIframeReady] = useState(false);
102
149
  const iframeRef = useRef(null);
@@ -105,6 +152,7 @@ export function ExtensionViewer({ extensionId }) {
105
152
  const [renameValue, setRenameValue] = useState("");
106
153
  const [refreshKey, setRefreshKey] = useState(0);
107
154
  const renameInputRef = useRef(null);
155
+ const titleSuffixRef = useRef(undefined);
108
156
  // Tracks how many toolbar popovers are open. Iframes capture pointer events
109
157
  // from areas they visually overlap, so when a popover opens above the iframe,
110
158
  // hover and click on the popover items get swallowed by the iframe. Disabling
@@ -344,6 +392,22 @@ export function ExtensionViewer({ extensionId }) {
344
392
  },
345
393
  });
346
394
  toolRef.current = extension ?? null;
395
+ useEffect(() => {
396
+ if (!extension)
397
+ return;
398
+ const canonicalPath = extensionPath(extension.id, extension.name);
399
+ if (titleSuffixRef.current === undefined) {
400
+ titleSuffixRef.current = readExtensionTitleSuffix();
401
+ }
402
+ document.title = extensionDocumentTitle(extension.name, titleSuffixRef.current);
403
+ if (isExtensionPathname(location.pathname, extension.id) &&
404
+ location.pathname !== canonicalPath) {
405
+ navigate(`${canonicalPath}${location.search}${location.hash}`, {
406
+ replace: true,
407
+ });
408
+ }
409
+ return applyCanonicalLink(canonicalPath);
410
+ }, [extension, location.hash, location.pathname, location.search, navigate]);
347
411
  const iframeSrc = useMemo(() => agentNativePath(`/_agent-native/extensions/${extensionId}/render?dark=${document.documentElement.classList.contains("dark")}&v=${encodeURIComponent(extension?.updatedAt ?? "")}&r=${refreshKey}`), [extensionId, extension?.updatedAt, refreshKey]);
348
412
  useEffect(() => {
349
413
  setIframeReady(false);
@@ -1 +1 @@
1
- {"version":3,"file":"ExtensionViewer.js","sourceRoot":"","sources":["../../../src/client/extensions/ExtensionViewer.tsx"],"names":[],"mappings":"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","sourcesContent":["import { agentNativePath } from \"../api-path.js\";\nimport { useState, useEffect, useRef, useCallback, useMemo } from \"react\";\nimport { useQuery, useQueryClient } from \"@tanstack/react-query\";\nimport { Link, useNavigate } from \"react-router\";\nimport {\n IconArrowLeft,\n IconChevronRight,\n IconDots,\n IconLoader2,\n IconPencil,\n IconRefresh,\n IconTrash,\n IconX,\n} from \"@tabler/icons-react\";\nimport { ShareButton } from \"../sharing/ShareButton.js\";\nimport { AgentToggleButton } from \"../AgentPanel.js\";\nimport { NotificationsBell } from \"../notifications/NotificationsBell.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 isAllowedExtensionPath,\n sanitizeExtensionRequestOptions,\n checkBridgePolicy,\n type ExtensionBridgeRole,\n} from \"./iframe-bridge.js\";\nimport {\n Tooltip,\n TooltipContent,\n TooltipProvider,\n TooltipTrigger,\n} from \"../components/ui/tooltip.js\";\nimport {\n deleteOrHideExtension,\n invalidateExtensionRemoval,\n} from \"./delete-extension.js\";\n\nconst THEME_CSS_VARS = [\n \"--background\",\n \"--foreground\",\n \"--card\",\n \"--card-foreground\",\n \"--popover\",\n \"--popover-foreground\",\n \"--primary\",\n \"--primary-foreground\",\n \"--secondary\",\n \"--secondary-foreground\",\n \"--muted\",\n \"--muted-foreground\",\n \"--accent\",\n \"--accent-foreground\",\n \"--destructive\",\n \"--destructive-foreground\",\n \"--border\",\n \"--input\",\n \"--ring\",\n \"--radius\",\n \"--sidebar-background\",\n \"--sidebar-foreground\",\n \"--sidebar-primary\",\n \"--sidebar-primary-foreground\",\n \"--sidebar-accent\",\n \"--sidebar-accent-foreground\",\n \"--sidebar-border\",\n \"--sidebar-ring\",\n];\n\nfunction getParentThemeVars(): Record<string, string> {\n const computed = getComputedStyle(document.documentElement);\n const vars: Record<string, string> = {};\n for (const name of THEME_CSS_VARS) {\n const val = computed.getPropertyValue(name).trim();\n if (val) vars[name] = val;\n }\n return vars;\n}\n\ninterface Extension {\n id: string;\n name: string;\n description?: string;\n content?: string;\n updatedAt?: string;\n canDelete?: boolean;\n}\n\nexport interface ExtensionViewerProps {\n extensionId: string;\n}\n\nfunction EditToolPopover({\n extension,\n onOpenChange,\n}: {\n extension: Extension;\n onOpenChange?: (open: boolean) => void;\n}) {\n const [open, setOpen] = useState(false);\n const setOpenAndNotify = (v: boolean) => {\n setOpen(v);\n onOpenChange?.(v);\n };\n\n // Radix's outside-click detection runs in the parent document, so a click\n // inside the extension iframe (or any other iframe) never fires it. The browser\n // does shift focus to the iframe though, which blurs the parent window — we\n // hook that to close the popover so it behaves like a normal click-outside.\n useEffect(() => {\n if (!open) return;\n const handleBlur = () => {\n // Defer until after the focus actually lands so document.activeElement\n // reflects the iframe (or whatever the user clicked on).\n setTimeout(() => {\n if (document.activeElement?.tagName === \"IFRAME\")\n setOpenAndNotify(false);\n }, 0);\n };\n window.addEventListener(\"blur\", handleBlur);\n return () => window.removeEventListener(\"blur\", handleBlur);\n }, [open]);\n\n const handleSubmit = (text: string) => {\n const trimmed = text.trim();\n if (!trimmed) return;\n sendToAgentChat({\n message: `Update extension \"${extension.name}\" (${extension.id}): ${trimmed}`,\n context: [\n `The user is viewing extension \"${extension.name}\" (id: ${extension.id}) and wants to edit it.`,\n \"This is an existing sandboxed Alpine.js extension stored in SQL. Use list-extensions/update-extension for this extension id.\",\n \"Do not call connect-builder and do not route this to a source-code change flow.\",\n ].join(\"\\n\"),\n submit: true,\n openSidebar: true,\n newTab: true,\n });\n setOpenAndNotify(false);\n };\n\n return (\n <Popover open={open} onOpenChange={setOpenAndNotify}>\n <Tooltip>\n <TooltipTrigger asChild>\n <PopoverTrigger asChild>\n <button\n type=\"button\"\n className=\"inline-flex items-center justify-center rounded-md h-8 w-8 text-muted-foreground hover:bg-accent hover:text-accent-foreground cursor-pointer\"\n >\n <IconPencil className=\"h-4 w-4\" />\n </button>\n </PopoverTrigger>\n </TooltipTrigger>\n <TooltipContent>Edit</TooltipContent>\n </Tooltip>\n <PopoverContent align=\"end\" sideOffset={6} className=\"w-[420px] p-3\">\n <p className=\"px-1 pb-2 text-sm font-semibold text-foreground\">\n Edit extension\n </p>\n <PromptComposer\n autoFocus\n placeholder=\"What would you like to change?\"\n draftScope={`extensions:edit:${extension.id}`}\n onSubmit={handleSubmit}\n />\n </PopoverContent>\n </Popover>\n );\n}\n\nexport function ExtensionViewer({ extensionId }: ExtensionViewerProps) {\n const [isDark, setIsDark] = useState(false);\n const [iframeReady, setIframeReady] = useState(false);\n const iframeRef = useRef<HTMLIFrameElement | null>(null);\n const toolRef = useRef<Extension | null>(null);\n const [isRenaming, setIsRenaming] = useState(false);\n const [renameValue, setRenameValue] = useState(\"\");\n const [refreshKey, setRefreshKey] = useState(0);\n const renameInputRef = useRef<HTMLInputElement | null>(null);\n // Tracks how many toolbar popovers are open. Iframes capture pointer events\n // from areas they visually overlap, so when a popover opens above the iframe,\n // hover and click on the popover items get swallowed by the iframe. Disabling\n // pointer-events on the iframe while any popover is open lets the popover\n // receive its own events. Each popover increments on open / decrements on\n // close, so concurrent popovers (rare) compose correctly.\n const [openPopoverCount, setOpenPopoverCount] = useState(0);\n const onPopoverOpenChange = useCallback((open: boolean) => {\n setOpenPopoverCount((c) => Math.max(0, c + (open ? 1 : -1)));\n }, []);\n const queryClient = useQueryClient();\n // (audit H4) Role plumbed through from the iframe's render binding. Until\n // the iframe announces its role we deny non-trivial helper calls — that\n // way a malicious extension body that races the announcement can't briefly\n // operate at higher privilege than the viewer's actual role.\n const bridgeContextRef = useRef<{\n role: ExtensionBridgeRole;\n isAuthor: boolean;\n }>({\n role: \"viewer\",\n isAuthor: false,\n });\n\n useEffect(() => {\n setIsDark(document.documentElement.classList.contains(\"dark\"));\n\n const observer = new MutationObserver(() => {\n setIsDark(document.documentElement.classList.contains(\"dark\"));\n });\n observer.observe(document.documentElement, {\n attributes: true,\n attributeFilter: [\"class\"],\n });\n return () => observer.disconnect();\n }, []);\n\n const sendThemeToIframe = () => {\n const win = iframeRef.current?.contentWindow;\n if (!win) return;\n win.postMessage(\n {\n type: \"agent-native-theme-update\",\n isDark: document.documentElement.classList.contains(\"dark\"),\n vars: getParentThemeVars(),\n },\n \"*\",\n );\n };\n\n useEffect(() => {\n if (!iframeReady) return;\n sendThemeToIframe();\n }, [isDark, iframeReady]);\n\n useEffect(() => {\n const handleMessage = async (event: MessageEvent) => {\n if (event.source !== iframeRef.current?.contentWindow) return;\n const message = event.data;\n if (!message) return;\n\n if (message.type === \"agent-native-extension-binding\") {\n // (audit H4) The iframe announced its render binding. Trust the role\n // value because the iframe's binding is generated server-side in\n // extensions/routes.ts (resolveAccess), not by user-authored content.\n const binding = message.binding ?? {};\n const role: ExtensionBridgeRole =\n binding.role === \"owner\" ||\n binding.role === \"admin\" ||\n binding.role === \"editor\" ||\n binding.role === \"viewer\"\n ? binding.role\n : \"viewer\";\n bridgeContextRef.current = {\n role,\n isAuthor: !!binding.isAuthor,\n };\n return;\n }\n\n if (\n message.type === \"agent-native-extension-consent-granted\" ||\n message.type === \"agent-native-extension-consent-cancelled\"\n ) {\n // (audit C1) The consent stub fired; force a reload of the iframe so\n // the next render returns the extension body (granted) or stays on the\n // stub (cancelled — viewer can also navigate away).\n if (message.type === \"agent-native-extension-consent-granted\") {\n // Invalidate the cached extension record — author may have edited\n // since the cache was warmed.\n queryClient.invalidateQueries({\n queryKey: [\"extension\", extensionId],\n });\n setRefreshKey((k) => k + 1);\n }\n return;\n }\n\n if (message.type === \"agent-native-extension-keydown\") {\n document.dispatchEvent(\n new KeyboardEvent(\"keydown\", {\n key: message.key,\n code: message.code,\n metaKey: !!message.metaKey,\n ctrlKey: !!message.ctrlKey,\n shiftKey: !!message.shiftKey,\n altKey: !!message.altKey,\n bubbles: true,\n cancelable: true,\n }),\n );\n return;\n }\n\n if (message.type === \"agent-native-extension-error-fix\") {\n const t = toolRef.current;\n if (!t) return;\n const errors: string[] = message.errors || [];\n const errorDetails: Array<{ message: string; stack: string }> =\n message.errorDetails || [];\n const consoleLogs: Array<{ level: string; message: string }> =\n message.consoleLogs || [];\n const networkLogs: Array<{\n path: string;\n method: string;\n ok?: boolean;\n status?: number;\n error?: string;\n }> = message.networkLogs || [];\n\n const detailedTrace = errorDetails\n .map((e) => (e.stack ? `${e.message}\\n${e.stack}` : e.message))\n .join(\"\\n\\n\");\n\n // Force a fresh read from the server. toolRef.current is bound to the\n // React Query cache, which is the same state the agent's previous\n // (broken) turn just wrote — without this, Fix-in-same-chat ends up\n // patching the agent's prior attempt from chat history instead of the\n // current DB row, which is why users had to open a new chat to\n // recover. Cache-bust so we never read a stale fetch.\n let freshContent: string | undefined;\n try {\n const res = await fetch(\n agentNativePath(`/_agent-native/extensions/${t.id}`),\n { cache: \"no-store\" },\n );\n if (res.ok) {\n const fresh = (await res.json()) as Extension;\n freshContent =\n typeof fresh?.content === \"string\" ? fresh.content : undefined;\n }\n } catch {\n // Fall through with the cached value — agent can still re-read via\n // its get-extension tool.\n }\n\n const contextParts = [\n `The user is viewing extension \"${t.name}\" (id: ${t.id}) and there are runtime errors that need fixing.`,\n `\\nFull error details:\\n${detailedTrace}`,\n ];\n\n if (consoleLogs.length > 0) {\n const consoleStr = consoleLogs\n .map((l) => `[${l.level}] ${l.message}`)\n .join(\"\\n\");\n contextParts.push(`\\nRecent console output:\\n${consoleStr}`);\n }\n\n if (networkLogs.length > 0) {\n const netStr = networkLogs\n .map(\n (l) =>\n `${l.method} ${l.path} → ${l.ok ? l.status : \"FAILED: \" + (l.error || l.status)}`,\n )\n .join(\"\\n\");\n contextParts.push(`\\nRecent network requests:\\n${netStr}`);\n }\n\n if (freshContent) {\n contextParts.push(\n `\\nCurrent extension content (just re-read from the database — this is the authoritative source, not anything you may have written in a previous turn):\\n\\`\\`\\`html\\n${freshContent}\\n\\`\\`\\``,\n );\n }\n\n sendToAgentChat({\n message: `Fix runtime errors in this extension. The content snapshot below was just re-read from the database — treat it as authoritative and ignore any prior version you may have generated in this chat. If in doubt, call get-extension first.\\n\\nErrors:\\n${errors.join(\"\\n\")}`,\n context: contextParts.join(\"\\n\"),\n submit: true,\n openSidebar: true,\n });\n return;\n }\n\n if (message.type !== \"agent-native-extension-request\") return;\n\n const requestId = String(message.requestId ?? \"\");\n const path = String(message.path ?? \"\");\n const respond = (payload: Record<string, unknown>) => {\n iframeRef.current?.contentWindow?.postMessage(\n {\n type: \"agent-native-extension-response\",\n requestId,\n ...payload,\n },\n \"*\",\n );\n };\n\n if (!requestId || !isAllowedExtensionPath(path, extensionId)) {\n respond({ error: \"Extension request path is not allowed\" });\n return;\n }\n\n try {\n const options = sanitizeExtensionRequestOptions(message.options);\n // (audit H4) Role-aware policy gate: viewer-shared extensions can read\n // but not write. Decided here in the parent before the request\n // leaves; the server enforces a second layer.\n const policy = checkBridgePolicy(\n path,\n options.method ?? \"GET\",\n bridgeContextRef.current,\n );\n if (!policy.ok) {\n respond({\n response: {\n ok: false,\n status: 403,\n statusText: \"Forbidden\",\n body: { error: policy.error },\n },\n });\n return;\n }\n // (audit H5) Tag every outbound bridge request with the\n // X-Agent-Native-Extension-Bridge sentinel so the action-routes layer can\n // enforce per-action `toolCallable` opt-in. The header is added by\n // the parent — it is NOT taken from the iframe-supplied options\n // (which were filtered by sanitizeExtensionRequestOptions).\n const finalHeaders = new Headers(options.headers ?? undefined);\n finalHeaders.set(\"X-Agent-Native-Extension-Bridge\", \"1\");\n finalHeaders.set(\"X-Agent-Native-Extension-Id\", extensionId);\n finalHeaders.set(\"X-Agent-Native-Tool-Bridge\", \"1\");\n finalHeaders.set(\"X-Agent-Native-Tool-Id\", extensionId);\n const res = await fetch(agentNativePath(path), {\n ...options,\n headers: finalHeaders,\n credentials: \"same-origin\",\n });\n const text = await res.text();\n let body: unknown = text;\n if (text) {\n try {\n body = JSON.parse(text);\n } catch {\n body = text;\n }\n }\n respond({\n response: {\n ok: res.ok,\n status: res.status,\n statusText: res.statusText,\n body,\n },\n });\n } catch (err: any) {\n respond({ error: err?.message ?? \"Extension host request failed\" });\n }\n };\n\n window.addEventListener(\"message\", handleMessage);\n return () => window.removeEventListener(\"message\", handleMessage);\n }, [extensionId, queryClient]);\n\n const { data: extension, isLoading } = useQuery<Extension | null>({\n queryKey: [\"extension\", extensionId],\n queryFn: async () => {\n const res = await fetch(\n agentNativePath(`/_agent-native/extensions/${extensionId}`),\n );\n if (res.status === 403 || res.status === 404) return null;\n if (!res.ok) throw new Error(\"Failed to fetch extension\");\n return res.json();\n },\n });\n\n toolRef.current = extension ?? null;\n\n const iframeSrc = useMemo(\n () =>\n agentNativePath(\n `/_agent-native/extensions/${extensionId}/render?dark=${document.documentElement.classList.contains(\"dark\")}&v=${encodeURIComponent(extension?.updatedAt ?? \"\")}&r=${refreshKey}`,\n ),\n [extensionId, extension?.updatedAt, refreshKey],\n );\n\n useEffect(() => {\n setIframeReady(false);\n // Reset role to deny-by-default on every reload — the new render's\n // binding announcement re-establishes the role before any helper call.\n bridgeContextRef.current = { role: \"viewer\", isAuthor: false };\n }, [extensionId, extension?.updatedAt, refreshKey]);\n\n const startRename = useCallback(() => {\n if (!extension) return;\n setRenameValue(extension.name);\n setIsRenaming(true);\n requestAnimationFrame(() => renameInputRef.current?.select());\n }, [extension]);\n\n const submitRename = useCallback(async () => {\n const trimmed = renameValue.trim();\n if (!trimmed || !extension || trimmed === extension.name) {\n setIsRenaming(false);\n return;\n }\n queryClient.setQueryData<Extension>([\"extension\", extensionId], (old) =>\n old ? { ...old, name: trimmed } : old,\n );\n queryClient.setQueryData<Extension[]>([\"extensions\"], (old) =>\n (old ?? []).map((t) =>\n t.id === extensionId ? { ...t, name: trimmed } : t,\n ),\n );\n setIsRenaming(false);\n try {\n await fetch(agentNativePath(`/_agent-native/extensions/${extensionId}`), {\n method: \"PUT\",\n headers: { \"Content-Type\": \"application/json\" },\n body: JSON.stringify({ name: trimmed }),\n });\n queryClient.invalidateQueries({ queryKey: [\"extension\", extensionId] });\n queryClient.invalidateQueries({ queryKey: [\"extensions\"] });\n } catch {\n queryClient.invalidateQueries({ queryKey: [\"extension\", extensionId] });\n queryClient.invalidateQueries({ queryKey: [\"extensions\"] });\n }\n }, [renameValue, extension, extensionId, queryClient]);\n\n if (isLoading) {\n return (\n <div className=\"flex h-full flex-col\">\n <div className=\"flex h-12 items-center gap-2 px-3 border-b shrink-0\">\n <div className=\"h-3.5 w-3.5 rounded bg-muted animate-pulse\" />\n <div className=\"h-3.5 w-24 rounded bg-muted animate-pulse\" />\n </div>\n <div className=\"flex-1 bg-muted/20 animate-pulse\" />\n </div>\n );\n }\n\n if (!extension) {\n return (\n <div className=\"flex h-full items-center justify-center text-sm text-muted-foreground\">\n Extension not found\n </div>\n );\n }\n\n return (\n <TooltipProvider delayDuration={200}>\n <div className=\"flex h-full w-full flex-col\">\n <div className=\"flex h-12 shrink-0 items-center justify-between gap-3 border-b px-3\">\n <div className=\"flex min-w-0 items-center gap-3\">\n <Tooltip>\n <TooltipTrigger asChild>\n <Link\n to=\"/\"\n className=\"inline-flex h-8 shrink-0 items-center justify-center gap-1.5 rounded-md px-2 text-xs font-medium text-muted-foreground hover:bg-accent hover:text-accent-foreground\"\n aria-label=\"Back to app\"\n >\n <IconArrowLeft className=\"h-4 w-4\" />\n <span className=\"hidden sm:inline\">Back to app</span>\n </Link>\n </TooltipTrigger>\n <TooltipContent>Back to app</TooltipContent>\n </Tooltip>\n <nav\n aria-label=\"Extension breadcrumb\"\n className=\"group/name flex min-w-0 items-center gap-1 text-sm\"\n >\n <Link\n to=\"/extensions\"\n className=\"shrink-0 text-muted-foreground hover:text-foreground\"\n >\n Extensions\n </Link>\n <IconChevronRight className=\"h-3.5 w-3.5 shrink-0 text-muted-foreground/60\" />\n {isRenaming ? (\n <input\n ref={renameInputRef}\n value={renameValue}\n onChange={(e) => setRenameValue(e.target.value)}\n onBlur={submitRename}\n onKeyDown={(e) => {\n if (e.key === \"Enter\") submitRename();\n if (e.key === \"Escape\") setIsRenaming(false);\n }}\n className=\"min-w-0 bg-transparent px-0 py-0 text-sm font-medium outline-none border-b border-primary\"\n />\n ) : (\n <>\n <span className=\"truncate text-sm font-medium\">\n {extension.name}\n </span>\n <Tooltip>\n <TooltipTrigger asChild>\n <button\n type=\"button\"\n onClick={startRename}\n className=\"shrink-0 cursor-pointer rounded p-0.5 text-muted-foreground/40 opacity-0 group-hover/name:opacity-100 hover:text-foreground\"\n >\n <IconPencil className=\"h-3 w-3\" />\n </button>\n </TooltipTrigger>\n <TooltipContent>Rename</TooltipContent>\n </Tooltip>\n </>\n )}\n </nav>\n </div>\n <div className=\"flex shrink-0 items-center gap-1\">\n <Tooltip>\n <TooltipTrigger asChild>\n <button\n type=\"button\"\n onClick={() => setRefreshKey((k) => k + 1)}\n className=\"inline-flex items-center justify-center rounded-md h-8 w-8 text-muted-foreground hover:bg-accent hover:text-accent-foreground cursor-pointer\"\n >\n <IconRefresh className=\"h-4 w-4\" />\n </button>\n </TooltipTrigger>\n <TooltipContent>Refresh</TooltipContent>\n </Tooltip>\n <EditToolPopover\n extension={extension}\n onOpenChange={onPopoverOpenChange}\n />\n <ShareButton\n resourceType=\"extension\"\n resourceId={extensionId}\n resourceTitle={extension.name}\n onOpenChange={onPopoverOpenChange}\n accessNote={\n <>\n Extensions can be shared inside your organization only — they\n run with the viewer's credentials, so cross-org access isn't\n supported.\n </>\n }\n />\n <ToolMoreMenu\n extensionId={extensionId}\n toolName={extension.name}\n canDelete={extension.canDelete}\n onOpenChange={onPopoverOpenChange}\n />\n <NotificationsBell />\n <AgentToggleButton />\n </div>\n </div>\n <div className=\"relative flex-1 min-h-0\">\n {!iframeReady && (\n <div className=\"absolute inset-0 flex items-center justify-center bg-background z-10\">\n <IconLoader2\n className=\"size-5 animate-spin text-muted-foreground\"\n role=\"status\"\n aria-label=\"Loading\"\n />\n </div>\n )}\n <iframe\n ref={iframeRef}\n key={`${extension.updatedAt}-${refreshKey}`}\n src={iframeSrc}\n className=\"h-full w-full border-0\"\n sandbox=\"allow-scripts allow-forms\"\n title={extension.name}\n style={{\n pointerEvents: openPopoverCount > 0 ? \"none\" : \"auto\",\n }}\n onLoad={() => {\n sendThemeToIframe();\n setTimeout(() => setIframeReady(true), 150);\n }}\n />\n </div>\n </div>\n </TooltipProvider>\n );\n}\n\ninterface SlotDeclaration {\n id: string;\n extensionId: string;\n slotId: string;\n}\n\nfunction ToolMoreMenu({\n extensionId,\n toolName,\n canDelete,\n onOpenChange,\n}: {\n extensionId: string;\n toolName: string;\n canDelete?: boolean;\n onOpenChange?: (open: boolean) => void;\n}) {\n const [open, setOpen] = useState(false);\n const [confirmingDelete, setConfirmingDelete] = useState(false);\n const queryClient = useQueryClient();\n const navigate = useNavigate();\n const setOpenAndNotify = (v: boolean) => {\n setOpen(v);\n onOpenChange?.(v);\n };\n\n const { data: slots = [] } = useQuery<SlotDeclaration[]>({\n queryKey: [\"extension-slots\", extensionId],\n queryFn: async () => {\n const res = await fetch(\n agentNativePath(`/_agent-native/slots/extension/${extensionId}`),\n );\n if (!res.ok) return [];\n return res.json();\n },\n enabled: open,\n });\n\n const closeMenu = () => {\n setOpenAndNotify(false);\n setConfirmingDelete(false);\n };\n\n const removeFromSlot = async (slotId: string) => {\n try {\n await fetch(\n agentNativePath(\n `/_agent-native/slots/${encodeURIComponent(slotId)}/install/${encodeURIComponent(extensionId)}`,\n ),\n { method: \"DELETE\" },\n );\n } finally {\n queryClient.invalidateQueries({ queryKey: [\"slot-installs\", slotId] });\n }\n };\n\n const deleteExtension = async () => {\n closeMenu();\n try {\n await deleteOrHideExtension({ id: extensionId, canDelete });\n invalidateExtensionRemoval(queryClient, extensionId);\n slots.forEach((s) =>\n queryClient.invalidateQueries({\n queryKey: [\"slot-installs\", s.slotId],\n }),\n );\n navigate(\"/extensions\");\n } catch {\n queryClient.invalidateQueries({ queryKey: [\"extension\", extensionId] });\n }\n };\n\n return (\n <Popover\n open={open}\n onOpenChange={(o) => {\n setOpenAndNotify(o);\n if (!o) setConfirmingDelete(false);\n }}\n >\n <Tooltip>\n <TooltipTrigger asChild>\n <PopoverTrigger asChild>\n <button\n type=\"button\"\n className=\"inline-flex items-center justify-center rounded-md h-8 w-8 text-muted-foreground hover:bg-accent hover:text-accent-foreground cursor-pointer\"\n aria-label=\"More options\"\n >\n <IconDots className=\"h-4 w-4\" />\n </button>\n </PopoverTrigger>\n </TooltipTrigger>\n <TooltipContent>More options</TooltipContent>\n </Tooltip>\n <PopoverContent align=\"end\" sideOffset={4} className=\"w-72 p-0\">\n {!confirmingDelete ? (\n <>\n <div className=\"px-3 py-2 border-b border-border/40\">\n <p className=\"text-[12px] font-medium\">Appears in</p>\n {slots.length === 0 ? (\n <p className=\"text-[11px] text-muted-foreground/70 mt-0.5\">\n Not installed in any widget areas. Ask the agent to add it\n somewhere.\n </p>\n ) : (\n <p className=\"text-[11px] text-muted-foreground/70 mt-0.5\">\n This extension can render in {slots.length} widget area\n {slots.length === 1 ? \"\" : \"s\"}.\n </p>\n )}\n </div>\n {slots.length > 0 && (\n <div className=\"max-h-48 overflow-y-auto py-1\">\n {slots.map((s) => (\n <div\n key={s.id}\n className=\"flex items-center gap-2 px-3 py-1.5 text-[12px]\"\n >\n <span className=\"flex-1 truncate font-mono text-[11px] text-muted-foreground\">\n {s.slotId}\n </span>\n <Tooltip>\n <TooltipTrigger asChild>\n <button\n type=\"button\"\n onClick={() => removeFromSlot(s.slotId)}\n className=\"rounded p-1 text-muted-foreground/60 hover:bg-accent hover:text-foreground cursor-pointer\"\n aria-label=\"Remove from this widget area\"\n >\n <IconX className=\"h-3.5 w-3.5\" />\n </button>\n </TooltipTrigger>\n <TooltipContent>\n Remove from this widget area (for me)\n </TooltipContent>\n </Tooltip>\n </div>\n ))}\n </div>\n )}\n <div className=\"border-t border-border/40 p-1\">\n <button\n type=\"button\"\n onClick={() => setConfirmingDelete(true)}\n className=\"flex w-full items-center gap-2 rounded-sm px-2 py-1.5 text-[12px] text-destructive hover:bg-destructive/10 cursor-pointer text-left\"\n >\n <IconTrash className=\"h-3.5 w-3.5\" />\n <span>\n {canDelete === false\n ? \"Remove from my list...\"\n : \"Delete extension...\"}\n </span>\n </button>\n </div>\n </>\n ) : (\n <div className=\"flex flex-col gap-2 p-3\">\n <p className=\"text-[12px]\">\n {canDelete === false ? \"Remove \" : \"Delete \"}\n <span className=\"font-medium\">{toolName}</span>?\n {canDelete === false\n ? \" This hides it from your Extensions list without deleting it for anyone else.\"\n : \" This removes the extension everywhere, for everyone it's shared with.\"}\n </p>\n <div className=\"flex justify-end gap-1\">\n <button\n type=\"button\"\n onClick={() => setConfirmingDelete(false)}\n className=\"rounded-md px-2 py-1 text-[12px] hover:bg-accent cursor-pointer\"\n >\n Cancel\n </button>\n <button\n type=\"button\"\n onClick={deleteExtension}\n className=\"rounded-md bg-destructive px-2 py-1 text-[12px] text-destructive-foreground hover:bg-destructive/90 cursor-pointer\"\n >\n {canDelete === false ? \"Remove\" : \"Delete\"}\n </button>\n </div>\n </div>\n )}\n </PopoverContent>\n </Popover>\n );\n}\n"]}
1
+ {"version":3,"file":"ExtensionViewer.js","sourceRoot":"","sources":["../../../src/client/extensions/ExtensionViewer.tsx"],"names":[],"mappings":"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","sourcesContent":["import { agentNativePath, appPath } from \"../api-path.js\";\nimport { useState, useEffect, useRef, useCallback, useMemo } from \"react\";\nimport { useQuery, useQueryClient } from \"@tanstack/react-query\";\nimport { Link, useLocation, useNavigate } from \"react-router\";\nimport {\n IconArrowLeft,\n IconChevronRight,\n IconDots,\n IconLoader2,\n IconPencil,\n IconRefresh,\n IconTrash,\n IconX,\n} from \"@tabler/icons-react\";\nimport { ShareButton } from \"../sharing/ShareButton.js\";\nimport { AgentToggleButton } from \"../AgentPanel.js\";\nimport { NotificationsBell } from \"../notifications/NotificationsBell.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 isAllowedExtensionPath,\n sanitizeExtensionRequestOptions,\n checkBridgePolicy,\n type ExtensionBridgeRole,\n} from \"./iframe-bridge.js\";\nimport {\n Tooltip,\n TooltipContent,\n TooltipProvider,\n TooltipTrigger,\n} from \"../components/ui/tooltip.js\";\nimport {\n deleteOrHideExtension,\n invalidateExtensionRemoval,\n} from \"./delete-extension.js\";\nimport { extensionPath, isExtensionPathname } from \"../../extensions/path.js\";\n\nconst THEME_CSS_VARS = [\n \"--background\",\n \"--foreground\",\n \"--card\",\n \"--card-foreground\",\n \"--popover\",\n \"--popover-foreground\",\n \"--primary\",\n \"--primary-foreground\",\n \"--secondary\",\n \"--secondary-foreground\",\n \"--muted\",\n \"--muted-foreground\",\n \"--accent\",\n \"--accent-foreground\",\n \"--destructive\",\n \"--destructive-foreground\",\n \"--border\",\n \"--input\",\n \"--ring\",\n \"--radius\",\n \"--sidebar-background\",\n \"--sidebar-foreground\",\n \"--sidebar-primary\",\n \"--sidebar-primary-foreground\",\n \"--sidebar-accent\",\n \"--sidebar-accent-foreground\",\n \"--sidebar-border\",\n \"--sidebar-ring\",\n];\n\nfunction getParentThemeVars(): Record<string, string> {\n const computed = getComputedStyle(document.documentElement);\n const vars: Record<string, string> = {};\n for (const name of THEME_CSS_VARS) {\n const val = computed.getPropertyValue(name).trim();\n if (val) vars[name] = val;\n }\n return vars;\n}\n\ninterface Extension {\n id: string;\n name: string;\n description?: string;\n content?: string;\n updatedAt?: string;\n canDelete?: boolean;\n}\n\nexport interface ExtensionViewerProps {\n extensionId: string;\n}\n\nfunction readExtensionTitleSuffix(): string | null {\n const current = typeof document !== \"undefined\" ? document.title.trim() : \"\";\n const match = current.match(/^(?:Extension|Tool)s?\\s+(?:\\u2014|-)\\s+(.+)$/);\n return match?.[1]?.trim() || null;\n}\n\nfunction extensionDocumentTitle(name: string, suffix: string | null): string {\n return suffix ? `${name} \\u2014 ${suffix}` : `${name} \\u2014 Extensions`;\n}\n\nfunction applyCanonicalLink(path: string): () => void {\n if (typeof document === \"undefined\" || typeof window === \"undefined\") {\n return () => {};\n }\n\n let link = document.querySelector<HTMLLinkElement>('link[rel=\"canonical\"]');\n const created = !link;\n const previousHref = link?.getAttribute(\"href\") ?? null;\n const previousMarker = link?.dataset.agentNativeExtensionCanonical;\n\n if (!link) {\n link = document.createElement(\"link\");\n link.rel = \"canonical\";\n document.head.appendChild(link);\n }\n\n link.dataset.agentNativeExtensionCanonical = \"true\";\n link.href = new URL(appPath(path), window.location.origin).toString();\n\n return () => {\n if (!link) return;\n if (created) {\n link.remove();\n return;\n }\n if (previousHref === null) {\n link.removeAttribute(\"href\");\n } else {\n link.href = previousHref;\n }\n if (previousMarker === undefined) {\n delete link.dataset.agentNativeExtensionCanonical;\n } else {\n link.dataset.agentNativeExtensionCanonical = previousMarker;\n }\n };\n}\n\nfunction EditToolPopover({\n extension,\n onOpenChange,\n}: {\n extension: Extension;\n onOpenChange?: (open: boolean) => void;\n}) {\n const [open, setOpen] = useState(false);\n const setOpenAndNotify = (v: boolean) => {\n setOpen(v);\n onOpenChange?.(v);\n };\n\n // Radix's outside-click detection runs in the parent document, so a click\n // inside the extension iframe (or any other iframe) never fires it. The browser\n // does shift focus to the iframe though, which blurs the parent window — we\n // hook that to close the popover so it behaves like a normal click-outside.\n useEffect(() => {\n if (!open) return;\n const handleBlur = () => {\n // Defer until after the focus actually lands so document.activeElement\n // reflects the iframe (or whatever the user clicked on).\n setTimeout(() => {\n if (document.activeElement?.tagName === \"IFRAME\")\n setOpenAndNotify(false);\n }, 0);\n };\n window.addEventListener(\"blur\", handleBlur);\n return () => window.removeEventListener(\"blur\", handleBlur);\n }, [open]);\n\n const handleSubmit = (text: string) => {\n const trimmed = text.trim();\n if (!trimmed) return;\n sendToAgentChat({\n message: `Update extension \"${extension.name}\" (${extension.id}): ${trimmed}`,\n context: [\n `The user is viewing extension \"${extension.name}\" (id: ${extension.id}) and wants to edit it.`,\n \"This is an existing sandboxed Alpine.js extension stored in SQL. Use list-extensions/update-extension for this extension id.\",\n \"Do not call connect-builder and do not route this to a source-code change flow.\",\n ].join(\"\\n\"),\n submit: true,\n openSidebar: true,\n newTab: true,\n });\n setOpenAndNotify(false);\n };\n\n return (\n <Popover open={open} onOpenChange={setOpenAndNotify}>\n <Tooltip>\n <TooltipTrigger asChild>\n <PopoverTrigger asChild>\n <button\n type=\"button\"\n className=\"inline-flex items-center justify-center rounded-md h-8 w-8 text-muted-foreground hover:bg-accent hover:text-accent-foreground cursor-pointer\"\n >\n <IconPencil className=\"h-4 w-4\" />\n </button>\n </PopoverTrigger>\n </TooltipTrigger>\n <TooltipContent>Edit</TooltipContent>\n </Tooltip>\n <PopoverContent align=\"end\" sideOffset={6} className=\"w-[420px] p-3\">\n <p className=\"px-1 pb-2 text-sm font-semibold text-foreground\">\n Edit extension\n </p>\n <PromptComposer\n autoFocus\n placeholder=\"What would you like to change?\"\n draftScope={`extensions:edit:${extension.id}`}\n onSubmit={handleSubmit}\n />\n </PopoverContent>\n </Popover>\n );\n}\n\nexport function ExtensionViewer({ extensionId }: ExtensionViewerProps) {\n const location = useLocation();\n const navigate = useNavigate();\n const [isDark, setIsDark] = useState(false);\n const [iframeReady, setIframeReady] = useState(false);\n const iframeRef = useRef<HTMLIFrameElement | null>(null);\n const toolRef = useRef<Extension | null>(null);\n const [isRenaming, setIsRenaming] = useState(false);\n const [renameValue, setRenameValue] = useState(\"\");\n const [refreshKey, setRefreshKey] = useState(0);\n const renameInputRef = useRef<HTMLInputElement | null>(null);\n const titleSuffixRef = useRef<string | null | undefined>(undefined);\n // Tracks how many toolbar popovers are open. Iframes capture pointer events\n // from areas they visually overlap, so when a popover opens above the iframe,\n // hover and click on the popover items get swallowed by the iframe. Disabling\n // pointer-events on the iframe while any popover is open lets the popover\n // receive its own events. Each popover increments on open / decrements on\n // close, so concurrent popovers (rare) compose correctly.\n const [openPopoverCount, setOpenPopoverCount] = useState(0);\n const onPopoverOpenChange = useCallback((open: boolean) => {\n setOpenPopoverCount((c) => Math.max(0, c + (open ? 1 : -1)));\n }, []);\n const queryClient = useQueryClient();\n // (audit H4) Role plumbed through from the iframe's render binding. Until\n // the iframe announces its role we deny non-trivial helper calls — that\n // way a malicious extension body that races the announcement can't briefly\n // operate at higher privilege than the viewer's actual role.\n const bridgeContextRef = useRef<{\n role: ExtensionBridgeRole;\n isAuthor: boolean;\n }>({\n role: \"viewer\",\n isAuthor: false,\n });\n\n useEffect(() => {\n setIsDark(document.documentElement.classList.contains(\"dark\"));\n\n const observer = new MutationObserver(() => {\n setIsDark(document.documentElement.classList.contains(\"dark\"));\n });\n observer.observe(document.documentElement, {\n attributes: true,\n attributeFilter: [\"class\"],\n });\n return () => observer.disconnect();\n }, []);\n\n const sendThemeToIframe = () => {\n const win = iframeRef.current?.contentWindow;\n if (!win) return;\n win.postMessage(\n {\n type: \"agent-native-theme-update\",\n isDark: document.documentElement.classList.contains(\"dark\"),\n vars: getParentThemeVars(),\n },\n \"*\",\n );\n };\n\n useEffect(() => {\n if (!iframeReady) return;\n sendThemeToIframe();\n }, [isDark, iframeReady]);\n\n useEffect(() => {\n const handleMessage = async (event: MessageEvent) => {\n if (event.source !== iframeRef.current?.contentWindow) return;\n const message = event.data;\n if (!message) return;\n\n if (message.type === \"agent-native-extension-binding\") {\n // (audit H4) The iframe announced its render binding. Trust the role\n // value because the iframe's binding is generated server-side in\n // extensions/routes.ts (resolveAccess), not by user-authored content.\n const binding = message.binding ?? {};\n const role: ExtensionBridgeRole =\n binding.role === \"owner\" ||\n binding.role === \"admin\" ||\n binding.role === \"editor\" ||\n binding.role === \"viewer\"\n ? binding.role\n : \"viewer\";\n bridgeContextRef.current = {\n role,\n isAuthor: !!binding.isAuthor,\n };\n return;\n }\n\n if (\n message.type === \"agent-native-extension-consent-granted\" ||\n message.type === \"agent-native-extension-consent-cancelled\"\n ) {\n // (audit C1) The consent stub fired; force a reload of the iframe so\n // the next render returns the extension body (granted) or stays on the\n // stub (cancelled — viewer can also navigate away).\n if (message.type === \"agent-native-extension-consent-granted\") {\n // Invalidate the cached extension record — author may have edited\n // since the cache was warmed.\n queryClient.invalidateQueries({\n queryKey: [\"extension\", extensionId],\n });\n setRefreshKey((k) => k + 1);\n }\n return;\n }\n\n if (message.type === \"agent-native-extension-keydown\") {\n document.dispatchEvent(\n new KeyboardEvent(\"keydown\", {\n key: message.key,\n code: message.code,\n metaKey: !!message.metaKey,\n ctrlKey: !!message.ctrlKey,\n shiftKey: !!message.shiftKey,\n altKey: !!message.altKey,\n bubbles: true,\n cancelable: true,\n }),\n );\n return;\n }\n\n if (message.type === \"agent-native-extension-error-fix\") {\n const t = toolRef.current;\n if (!t) return;\n const errors: string[] = message.errors || [];\n const errorDetails: Array<{ message: string; stack: string }> =\n message.errorDetails || [];\n const consoleLogs: Array<{ level: string; message: string }> =\n message.consoleLogs || [];\n const networkLogs: Array<{\n path: string;\n method: string;\n ok?: boolean;\n status?: number;\n error?: string;\n }> = message.networkLogs || [];\n\n const detailedTrace = errorDetails\n .map((e) => (e.stack ? `${e.message}\\n${e.stack}` : e.message))\n .join(\"\\n\\n\");\n\n // Force a fresh read from the server. toolRef.current is bound to the\n // React Query cache, which is the same state the agent's previous\n // (broken) turn just wrote — without this, Fix-in-same-chat ends up\n // patching the agent's prior attempt from chat history instead of the\n // current DB row, which is why users had to open a new chat to\n // recover. Cache-bust so we never read a stale fetch.\n let freshContent: string | undefined;\n try {\n const res = await fetch(\n agentNativePath(`/_agent-native/extensions/${t.id}`),\n { cache: \"no-store\" },\n );\n if (res.ok) {\n const fresh = (await res.json()) as Extension;\n freshContent =\n typeof fresh?.content === \"string\" ? fresh.content : undefined;\n }\n } catch {\n // Fall through with the cached value — agent can still re-read via\n // its get-extension tool.\n }\n\n const contextParts = [\n `The user is viewing extension \"${t.name}\" (id: ${t.id}) and there are runtime errors that need fixing.`,\n `\\nFull error details:\\n${detailedTrace}`,\n ];\n\n if (consoleLogs.length > 0) {\n const consoleStr = consoleLogs\n .map((l) => `[${l.level}] ${l.message}`)\n .join(\"\\n\");\n contextParts.push(`\\nRecent console output:\\n${consoleStr}`);\n }\n\n if (networkLogs.length > 0) {\n const netStr = networkLogs\n .map(\n (l) =>\n `${l.method} ${l.path} → ${l.ok ? l.status : \"FAILED: \" + (l.error || l.status)}`,\n )\n .join(\"\\n\");\n contextParts.push(`\\nRecent network requests:\\n${netStr}`);\n }\n\n if (freshContent) {\n contextParts.push(\n `\\nCurrent extension content (just re-read from the database — this is the authoritative source, not anything you may have written in a previous turn):\\n\\`\\`\\`html\\n${freshContent}\\n\\`\\`\\``,\n );\n }\n\n sendToAgentChat({\n message: `Fix runtime errors in this extension. The content snapshot below was just re-read from the database — treat it as authoritative and ignore any prior version you may have generated in this chat. If in doubt, call get-extension first.\\n\\nErrors:\\n${errors.join(\"\\n\")}`,\n context: contextParts.join(\"\\n\"),\n submit: true,\n openSidebar: true,\n });\n return;\n }\n\n if (message.type !== \"agent-native-extension-request\") return;\n\n const requestId = String(message.requestId ?? \"\");\n const path = String(message.path ?? \"\");\n const respond = (payload: Record<string, unknown>) => {\n iframeRef.current?.contentWindow?.postMessage(\n {\n type: \"agent-native-extension-response\",\n requestId,\n ...payload,\n },\n \"*\",\n );\n };\n\n if (!requestId || !isAllowedExtensionPath(path, extensionId)) {\n respond({ error: \"Extension request path is not allowed\" });\n return;\n }\n\n try {\n const options = sanitizeExtensionRequestOptions(message.options);\n // (audit H4) Role-aware policy gate: viewer-shared extensions can read\n // but not write. Decided here in the parent before the request\n // leaves; the server enforces a second layer.\n const policy = checkBridgePolicy(\n path,\n options.method ?? \"GET\",\n bridgeContextRef.current,\n );\n if (!policy.ok) {\n respond({\n response: {\n ok: false,\n status: 403,\n statusText: \"Forbidden\",\n body: { error: policy.error },\n },\n });\n return;\n }\n // (audit H5) Tag every outbound bridge request with the\n // X-Agent-Native-Extension-Bridge sentinel so the action-routes layer can\n // enforce per-action `toolCallable` opt-in. The header is added by\n // the parent — it is NOT taken from the iframe-supplied options\n // (which were filtered by sanitizeExtensionRequestOptions).\n const finalHeaders = new Headers(options.headers ?? undefined);\n finalHeaders.set(\"X-Agent-Native-Extension-Bridge\", \"1\");\n finalHeaders.set(\"X-Agent-Native-Extension-Id\", extensionId);\n finalHeaders.set(\"X-Agent-Native-Tool-Bridge\", \"1\");\n finalHeaders.set(\"X-Agent-Native-Tool-Id\", extensionId);\n const res = await fetch(agentNativePath(path), {\n ...options,\n headers: finalHeaders,\n credentials: \"same-origin\",\n });\n const text = await res.text();\n let body: unknown = text;\n if (text) {\n try {\n body = JSON.parse(text);\n } catch {\n body = text;\n }\n }\n respond({\n response: {\n ok: res.ok,\n status: res.status,\n statusText: res.statusText,\n body,\n },\n });\n } catch (err: any) {\n respond({ error: err?.message ?? \"Extension host request failed\" });\n }\n };\n\n window.addEventListener(\"message\", handleMessage);\n return () => window.removeEventListener(\"message\", handleMessage);\n }, [extensionId, queryClient]);\n\n const { data: extension, isLoading } = useQuery<Extension | null>({\n queryKey: [\"extension\", extensionId],\n queryFn: async () => {\n const res = await fetch(\n agentNativePath(`/_agent-native/extensions/${extensionId}`),\n );\n if (res.status === 403 || res.status === 404) return null;\n if (!res.ok) throw new Error(\"Failed to fetch extension\");\n return res.json();\n },\n });\n\n toolRef.current = extension ?? null;\n\n useEffect(() => {\n if (!extension) return;\n const canonicalPath = extensionPath(extension.id, extension.name);\n if (titleSuffixRef.current === undefined) {\n titleSuffixRef.current = readExtensionTitleSuffix();\n }\n document.title = extensionDocumentTitle(\n extension.name,\n titleSuffixRef.current,\n );\n\n if (\n isExtensionPathname(location.pathname, extension.id) &&\n location.pathname !== canonicalPath\n ) {\n navigate(`${canonicalPath}${location.search}${location.hash}`, {\n replace: true,\n });\n }\n\n return applyCanonicalLink(canonicalPath);\n }, [extension, location.hash, location.pathname, location.search, navigate]);\n\n const iframeSrc = useMemo(\n () =>\n agentNativePath(\n `/_agent-native/extensions/${extensionId}/render?dark=${document.documentElement.classList.contains(\"dark\")}&v=${encodeURIComponent(extension?.updatedAt ?? \"\")}&r=${refreshKey}`,\n ),\n [extensionId, extension?.updatedAt, refreshKey],\n );\n\n useEffect(() => {\n setIframeReady(false);\n // Reset role to deny-by-default on every reload — the new render's\n // binding announcement re-establishes the role before any helper call.\n bridgeContextRef.current = { role: \"viewer\", isAuthor: false };\n }, [extensionId, extension?.updatedAt, refreshKey]);\n\n const startRename = useCallback(() => {\n if (!extension) return;\n setRenameValue(extension.name);\n setIsRenaming(true);\n requestAnimationFrame(() => renameInputRef.current?.select());\n }, [extension]);\n\n const submitRename = useCallback(async () => {\n const trimmed = renameValue.trim();\n if (!trimmed || !extension || trimmed === extension.name) {\n setIsRenaming(false);\n return;\n }\n queryClient.setQueryData<Extension>([\"extension\", extensionId], (old) =>\n old ? { ...old, name: trimmed } : old,\n );\n queryClient.setQueryData<Extension[]>([\"extensions\"], (old) =>\n (old ?? []).map((t) =>\n t.id === extensionId ? { ...t, name: trimmed } : t,\n ),\n );\n setIsRenaming(false);\n try {\n await fetch(agentNativePath(`/_agent-native/extensions/${extensionId}`), {\n method: \"PUT\",\n headers: { \"Content-Type\": \"application/json\" },\n body: JSON.stringify({ name: trimmed }),\n });\n queryClient.invalidateQueries({ queryKey: [\"extension\", extensionId] });\n queryClient.invalidateQueries({ queryKey: [\"extensions\"] });\n } catch {\n queryClient.invalidateQueries({ queryKey: [\"extension\", extensionId] });\n queryClient.invalidateQueries({ queryKey: [\"extensions\"] });\n }\n }, [renameValue, extension, extensionId, queryClient]);\n\n if (isLoading) {\n return (\n <div className=\"flex h-full flex-col\">\n <div className=\"flex h-12 items-center gap-2 px-3 border-b shrink-0\">\n <div className=\"h-3.5 w-3.5 rounded bg-muted animate-pulse\" />\n <div className=\"h-3.5 w-24 rounded bg-muted animate-pulse\" />\n </div>\n <div className=\"flex-1 bg-muted/20 animate-pulse\" />\n </div>\n );\n }\n\n if (!extension) {\n return (\n <div className=\"flex h-full items-center justify-center text-sm text-muted-foreground\">\n Extension not found\n </div>\n );\n }\n\n return (\n <TooltipProvider delayDuration={200}>\n <div className=\"flex h-full w-full flex-col\">\n <div className=\"flex h-12 shrink-0 items-center justify-between gap-3 border-b px-3\">\n <div className=\"flex min-w-0 items-center gap-3\">\n <Tooltip>\n <TooltipTrigger asChild>\n <Link\n to=\"/\"\n className=\"inline-flex h-8 shrink-0 items-center justify-center gap-1.5 rounded-md px-2 text-xs font-medium text-muted-foreground hover:bg-accent hover:text-accent-foreground\"\n aria-label=\"Back to app\"\n >\n <IconArrowLeft className=\"h-4 w-4\" />\n <span className=\"hidden sm:inline\">Back to app</span>\n </Link>\n </TooltipTrigger>\n <TooltipContent>Back to app</TooltipContent>\n </Tooltip>\n <nav\n aria-label=\"Extension breadcrumb\"\n className=\"group/name flex min-w-0 items-center gap-1 text-sm\"\n >\n <Link\n to=\"/extensions\"\n className=\"shrink-0 text-muted-foreground hover:text-foreground\"\n >\n Extensions\n </Link>\n <IconChevronRight className=\"h-3.5 w-3.5 shrink-0 text-muted-foreground/60\" />\n {isRenaming ? (\n <input\n ref={renameInputRef}\n value={renameValue}\n onChange={(e) => setRenameValue(e.target.value)}\n onBlur={submitRename}\n onKeyDown={(e) => {\n if (e.key === \"Enter\") submitRename();\n if (e.key === \"Escape\") setIsRenaming(false);\n }}\n className=\"min-w-0 bg-transparent px-0 py-0 text-sm font-medium outline-none border-b border-primary\"\n />\n ) : (\n <>\n <span className=\"truncate text-sm font-medium\">\n {extension.name}\n </span>\n <Tooltip>\n <TooltipTrigger asChild>\n <button\n type=\"button\"\n onClick={startRename}\n className=\"shrink-0 cursor-pointer rounded p-0.5 text-muted-foreground/40 opacity-0 group-hover/name:opacity-100 hover:text-foreground\"\n >\n <IconPencil className=\"h-3 w-3\" />\n </button>\n </TooltipTrigger>\n <TooltipContent>Rename</TooltipContent>\n </Tooltip>\n </>\n )}\n </nav>\n </div>\n <div className=\"flex shrink-0 items-center gap-1\">\n <Tooltip>\n <TooltipTrigger asChild>\n <button\n type=\"button\"\n onClick={() => setRefreshKey((k) => k + 1)}\n className=\"inline-flex items-center justify-center rounded-md h-8 w-8 text-muted-foreground hover:bg-accent hover:text-accent-foreground cursor-pointer\"\n >\n <IconRefresh className=\"h-4 w-4\" />\n </button>\n </TooltipTrigger>\n <TooltipContent>Refresh</TooltipContent>\n </Tooltip>\n <EditToolPopover\n extension={extension}\n onOpenChange={onPopoverOpenChange}\n />\n <ShareButton\n resourceType=\"extension\"\n resourceId={extensionId}\n resourceTitle={extension.name}\n onOpenChange={onPopoverOpenChange}\n accessNote={\n <>\n Extensions can be shared inside your organization only — they\n run with the viewer's credentials, so cross-org access isn't\n supported.\n </>\n }\n />\n <ToolMoreMenu\n extensionId={extensionId}\n toolName={extension.name}\n canDelete={extension.canDelete}\n onOpenChange={onPopoverOpenChange}\n />\n <NotificationsBell />\n <AgentToggleButton />\n </div>\n </div>\n <div className=\"relative flex-1 min-h-0\">\n {!iframeReady && (\n <div className=\"absolute inset-0 flex items-center justify-center bg-background z-10\">\n <IconLoader2\n className=\"size-5 animate-spin text-muted-foreground\"\n role=\"status\"\n aria-label=\"Loading\"\n />\n </div>\n )}\n <iframe\n ref={iframeRef}\n key={`${extension.updatedAt}-${refreshKey}`}\n src={iframeSrc}\n className=\"h-full w-full border-0\"\n sandbox=\"allow-scripts allow-forms\"\n title={extension.name}\n style={{\n pointerEvents: openPopoverCount > 0 ? \"none\" : \"auto\",\n }}\n onLoad={() => {\n sendThemeToIframe();\n setTimeout(() => setIframeReady(true), 150);\n }}\n />\n </div>\n </div>\n </TooltipProvider>\n );\n}\n\ninterface SlotDeclaration {\n id: string;\n extensionId: string;\n slotId: string;\n}\n\nfunction ToolMoreMenu({\n extensionId,\n toolName,\n canDelete,\n onOpenChange,\n}: {\n extensionId: string;\n toolName: string;\n canDelete?: boolean;\n onOpenChange?: (open: boolean) => void;\n}) {\n const [open, setOpen] = useState(false);\n const [confirmingDelete, setConfirmingDelete] = useState(false);\n const queryClient = useQueryClient();\n const navigate = useNavigate();\n const setOpenAndNotify = (v: boolean) => {\n setOpen(v);\n onOpenChange?.(v);\n };\n\n const { data: slots = [] } = useQuery<SlotDeclaration[]>({\n queryKey: [\"extension-slots\", extensionId],\n queryFn: async () => {\n const res = await fetch(\n agentNativePath(`/_agent-native/slots/extension/${extensionId}`),\n );\n if (!res.ok) return [];\n return res.json();\n },\n enabled: open,\n });\n\n const closeMenu = () => {\n setOpenAndNotify(false);\n setConfirmingDelete(false);\n };\n\n const removeFromSlot = async (slotId: string) => {\n try {\n await fetch(\n agentNativePath(\n `/_agent-native/slots/${encodeURIComponent(slotId)}/install/${encodeURIComponent(extensionId)}`,\n ),\n { method: \"DELETE\" },\n );\n } finally {\n queryClient.invalidateQueries({ queryKey: [\"slot-installs\", slotId] });\n }\n };\n\n const deleteExtension = async () => {\n closeMenu();\n try {\n await deleteOrHideExtension({ id: extensionId, canDelete });\n invalidateExtensionRemoval(queryClient, extensionId);\n slots.forEach((s) =>\n queryClient.invalidateQueries({\n queryKey: [\"slot-installs\", s.slotId],\n }),\n );\n navigate(\"/extensions\");\n } catch {\n queryClient.invalidateQueries({ queryKey: [\"extension\", extensionId] });\n }\n };\n\n return (\n <Popover\n open={open}\n onOpenChange={(o) => {\n setOpenAndNotify(o);\n if (!o) setConfirmingDelete(false);\n }}\n >\n <Tooltip>\n <TooltipTrigger asChild>\n <PopoverTrigger asChild>\n <button\n type=\"button\"\n className=\"inline-flex items-center justify-center rounded-md h-8 w-8 text-muted-foreground hover:bg-accent hover:text-accent-foreground cursor-pointer\"\n aria-label=\"More options\"\n >\n <IconDots className=\"h-4 w-4\" />\n </button>\n </PopoverTrigger>\n </TooltipTrigger>\n <TooltipContent>More options</TooltipContent>\n </Tooltip>\n <PopoverContent align=\"end\" sideOffset={4} className=\"w-72 p-0\">\n {!confirmingDelete ? (\n <>\n <div className=\"px-3 py-2 border-b border-border/40\">\n <p className=\"text-[12px] font-medium\">Appears in</p>\n {slots.length === 0 ? (\n <p className=\"text-[11px] text-muted-foreground/70 mt-0.5\">\n Not installed in any widget areas. Ask the agent to add it\n somewhere.\n </p>\n ) : (\n <p className=\"text-[11px] text-muted-foreground/70 mt-0.5\">\n This extension can render in {slots.length} widget area\n {slots.length === 1 ? \"\" : \"s\"}.\n </p>\n )}\n </div>\n {slots.length > 0 && (\n <div className=\"max-h-48 overflow-y-auto py-1\">\n {slots.map((s) => (\n <div\n key={s.id}\n className=\"flex items-center gap-2 px-3 py-1.5 text-[12px]\"\n >\n <span className=\"flex-1 truncate font-mono text-[11px] text-muted-foreground\">\n {s.slotId}\n </span>\n <Tooltip>\n <TooltipTrigger asChild>\n <button\n type=\"button\"\n onClick={() => removeFromSlot(s.slotId)}\n className=\"rounded p-1 text-muted-foreground/60 hover:bg-accent hover:text-foreground cursor-pointer\"\n aria-label=\"Remove from this widget area\"\n >\n <IconX className=\"h-3.5 w-3.5\" />\n </button>\n </TooltipTrigger>\n <TooltipContent>\n Remove from this widget area (for me)\n </TooltipContent>\n </Tooltip>\n </div>\n ))}\n </div>\n )}\n <div className=\"border-t border-border/40 p-1\">\n <button\n type=\"button\"\n onClick={() => setConfirmingDelete(true)}\n className=\"flex w-full items-center gap-2 rounded-sm px-2 py-1.5 text-[12px] text-destructive hover:bg-destructive/10 cursor-pointer text-left\"\n >\n <IconTrash className=\"h-3.5 w-3.5\" />\n <span>\n {canDelete === false\n ? \"Remove from my list...\"\n : \"Delete extension...\"}\n </span>\n </button>\n </div>\n </>\n ) : (\n <div className=\"flex flex-col gap-2 p-3\">\n <p className=\"text-[12px]\">\n {canDelete === false ? \"Remove \" : \"Delete \"}\n <span className=\"font-medium\">{toolName}</span>?\n {canDelete === false\n ? \" This hides it from your Extensions list without deleting it for anyone else.\"\n : \" This removes the extension everywhere, for everyone it's shared with.\"}\n </p>\n <div className=\"flex justify-end gap-1\">\n <button\n type=\"button\"\n onClick={() => setConfirmingDelete(false)}\n className=\"rounded-md px-2 py-1 text-[12px] hover:bg-accent cursor-pointer\"\n >\n Cancel\n </button>\n <button\n type=\"button\"\n onClick={deleteExtension}\n className=\"rounded-md bg-destructive px-2 py-1 text-[12px] text-destructive-foreground hover:bg-destructive/90 cursor-pointer\"\n >\n {canDelete === false ? \"Remove\" : \"Delete\"}\n </button>\n </div>\n </div>\n )}\n </PopoverContent>\n </Popover>\n );\n}\n"]}
@@ -1 +1 @@
1
- {"version":3,"file":"ExtensionsListPage.d.ts","sourceRoot":"","sources":["../../../src/client/extensions/ExtensionsListPage.tsx"],"names":[],"mappings":"AA8EA,wBAAgB,kBAAkB,4CAwOjC"}
1
+ {"version":3,"file":"ExtensionsListPage.d.ts","sourceRoot":"","sources":["../../../src/client/extensions/ExtensionsListPage.tsx"],"names":[],"mappings":"AA+EA,wBAAgB,kBAAkB,4CAwOjC"}
@@ -12,6 +12,7 @@ import { PromptComposer } from "../composer/PromptComposer.js";
12
12
  import { Popover, PopoverContent, PopoverTrigger, } from "../components/ui/popover.js";
13
13
  import { TOOLS_ORDER_CHANGE_EVENT, applyToolsOrder, getToolsOrder, } from "./extension-order.js";
14
14
  import { deleteOrHideExtension, invalidateExtensionRemoval, } from "./delete-extension.js";
15
+ import { extensionPath } from "../../extensions/path.js";
15
16
  let lastCreateSubmission = null;
16
17
  function submitCreateTool(prompt) {
17
18
  const trimmed = prompt.trim();
@@ -92,7 +93,7 @@ export function ExtensionsListPage() {
92
93
  queryClient.invalidateQueries({ queryKey: ["extensions"] });
93
94
  }
94
95
  };
95
- return (_jsxs("div", { className: "flex h-full w-full flex-col", children: [_jsxs("header", { className: "flex h-12 items-center justify-between border-b px-4 shrink-0", children: [_jsxs("div", { className: "flex items-center gap-2", children: [_jsx(Link, { to: "/", className: "inline-flex h-8 w-8 items-center justify-center rounded-md text-muted-foreground hover:bg-accent hover:text-foreground", "aria-label": "Back to app", children: _jsx(IconArrowLeft, { className: "h-4 w-4" }) }), _jsx("h1", { className: "text-sm font-semibold", children: "Extensions" })] }), _jsxs("div", { className: "flex items-center gap-2", children: [_jsxs(Popover, { open: showCreate, onOpenChange: setShowCreate, children: [_jsx(PopoverTrigger, { asChild: true, children: _jsxs("button", { type: "button", className: "inline-flex cursor-pointer items-center justify-center gap-1.5 rounded-md bg-primary px-3 py-1.5 text-sm font-medium text-primary-foreground hover:bg-primary/90", children: [_jsx(IconPlus, { className: "h-4 w-4" }), "New Extension"] }) }), _jsxs(PopoverContent, { align: "end", sideOffset: 6, 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:create-popover", onSubmit: handleCreate })] })] }), _jsx(NotificationsBell, {}), _jsx(AgentToggleButton, {})] })] }), _jsx("div", { className: "flex-1 overflow-auto px-5 py-8 sm:px-8 sm:py-10", children: isLoading ? (_jsx("div", { className: "grid grid-cols-1 gap-5 sm:grid-cols-2 lg:grid-cols-3", children: Array.from({ length: 6 }).map((_, i) => (_jsxs("div", { className: "rounded-lg border border-border bg-card p-5", children: [_jsx("div", { className: "mb-3 h-10 w-10 rounded-lg bg-muted animate-pulse" }), _jsx("div", { className: "mb-2 h-4 w-2/3 rounded bg-muted animate-pulse" }), _jsx("div", { className: "h-3 w-4/5 rounded bg-muted animate-pulse" })] }, i))) })) : toolList.length === 0 ? (_jsx("div", { className: "flex min-h-[calc(100vh-9rem)] flex-col items-center justify-start px-2 pb-12 pt-[clamp(5rem,18vh,11rem)] sm:pb-16", children: _jsxs("div", { className: "mx-auto flex w-full max-w-[34rem] flex-col gap-7", children: [_jsxs("div", { className: "flex flex-col items-center gap-3 text-center", children: [_jsx(IconTool, { className: "h-10 w-10 text-muted-foreground/40" }), _jsxs("div", { className: "space-y-1.5", children: [_jsx("p", { className: "text-base font-semibold text-foreground", children: "Create your first extension" }), _jsx("p", { className: "mx-auto max-w-sm text-sm text-muted-foreground", children: "Describe a small app and the agent will build it." })] })] }), _jsx(CreateToolInput, { className: "w-full" })] }) })) : (_jsx("div", { className: "grid grid-cols-1 gap-5 sm:grid-cols-2 lg:grid-cols-3", children: toolList.map((extension) => (_jsxs("div", { className: cn("group relative rounded-lg border border-border bg-card", "hover:border-primary/30 hover:shadow-sm"), children: [_jsxs(Link, { to: `/extensions/${extension.id}`, className: "block p-5 pr-12", children: [_jsx("div", { className: "mb-3 flex h-10 w-10 items-center justify-center rounded-lg bg-muted text-muted-foreground group-hover:bg-primary/10 group-hover:text-primary", children: _jsx(IconTool, { className: "h-5 w-5" }) }), _jsx("h3", { className: "mb-1 text-sm font-semibold text-foreground", children: extension.name }), extension.description && (_jsx("p", { className: "line-clamp-2 text-xs text-muted-foreground", children: extension.description }))] }), _jsxs(Popover, { open: confirmDeleteId === extension.id, onOpenChange: (open) => setConfirmDeleteId(open ? extension.id : null), children: [_jsx(PopoverTrigger, { asChild: true, children: _jsx("button", { type: "button", className: "absolute right-3 top-3 inline-flex h-8 w-8 items-center justify-center rounded-md text-muted-foreground opacity-0 hover:bg-accent hover:text-foreground focus:opacity-100 focus:outline-none focus:ring-2 focus:ring-ring group-hover:opacity-100", "aria-label": `Options for ${extension.name}`, children: _jsx(IconDotsVertical, { className: "h-4 w-4" }) }) }), _jsx(PopoverContent, { align: "end", sideOffset: 4, className: "w-64 p-0", children: _jsxs("div", { className: "p-3", children: [_jsxs("p", { className: "text-[12px]", children: [extension.canDelete === false ? "Remove " : "Delete ", _jsx("span", { className: "font-medium", children: extension.name }), "?", extension.canDelete === false
96
+ return (_jsxs("div", { className: "flex h-full w-full flex-col", children: [_jsxs("header", { className: "flex h-12 items-center justify-between border-b px-4 shrink-0", children: [_jsxs("div", { className: "flex items-center gap-2", children: [_jsx(Link, { to: "/", className: "inline-flex h-8 w-8 items-center justify-center rounded-md text-muted-foreground hover:bg-accent hover:text-foreground", "aria-label": "Back to app", children: _jsx(IconArrowLeft, { className: "h-4 w-4" }) }), _jsx("h1", { className: "text-sm font-semibold", children: "Extensions" })] }), _jsxs("div", { className: "flex items-center gap-2", children: [_jsxs(Popover, { open: showCreate, onOpenChange: setShowCreate, children: [_jsx(PopoverTrigger, { asChild: true, children: _jsxs("button", { type: "button", className: "inline-flex cursor-pointer items-center justify-center gap-1.5 rounded-md bg-primary px-3 py-1.5 text-sm font-medium text-primary-foreground hover:bg-primary/90", children: [_jsx(IconPlus, { className: "h-4 w-4" }), "New Extension"] }) }), _jsxs(PopoverContent, { align: "end", sideOffset: 6, 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:create-popover", onSubmit: handleCreate })] })] }), _jsx(NotificationsBell, {}), _jsx(AgentToggleButton, {})] })] }), _jsx("div", { className: "flex-1 overflow-auto px-5 py-8 sm:px-8 sm:py-10", children: isLoading ? (_jsx("div", { className: "grid grid-cols-1 gap-5 sm:grid-cols-2 lg:grid-cols-3", children: Array.from({ length: 6 }).map((_, i) => (_jsxs("div", { className: "rounded-lg border border-border bg-card p-5", children: [_jsx("div", { className: "mb-3 h-10 w-10 rounded-lg bg-muted animate-pulse" }), _jsx("div", { className: "mb-2 h-4 w-2/3 rounded bg-muted animate-pulse" }), _jsx("div", { className: "h-3 w-4/5 rounded bg-muted animate-pulse" })] }, i))) })) : toolList.length === 0 ? (_jsx("div", { className: "flex min-h-[calc(100vh-9rem)] flex-col items-center justify-start px-2 pb-12 pt-[clamp(5rem,18vh,11rem)] sm:pb-16", children: _jsxs("div", { className: "mx-auto flex w-full max-w-[34rem] flex-col gap-7", children: [_jsxs("div", { className: "flex flex-col items-center gap-3 text-center", children: [_jsx(IconTool, { className: "h-10 w-10 text-muted-foreground/40" }), _jsxs("div", { className: "space-y-1.5", children: [_jsx("p", { className: "text-base font-semibold text-foreground", children: "Create your first extension" }), _jsx("p", { className: "mx-auto max-w-sm text-sm text-muted-foreground", children: "Describe a small app and the agent will build it." })] })] }), _jsx(CreateToolInput, { className: "w-full" })] }) })) : (_jsx("div", { className: "grid grid-cols-1 gap-5 sm:grid-cols-2 lg:grid-cols-3", children: toolList.map((extension) => (_jsxs("div", { className: cn("group relative rounded-lg border border-border bg-card", "hover:border-primary/30 hover:shadow-sm"), children: [_jsxs(Link, { to: extensionPath(extension.id, extension.name), className: "block p-5 pr-12", children: [_jsx("div", { className: "mb-3 flex h-10 w-10 items-center justify-center rounded-lg bg-muted text-muted-foreground group-hover:bg-primary/10 group-hover:text-primary", children: _jsx(IconTool, { className: "h-5 w-5" }) }), _jsx("h3", { className: "mb-1 text-sm font-semibold text-foreground", children: extension.name }), extension.description && (_jsx("p", { className: "line-clamp-2 text-xs text-muted-foreground", children: extension.description }))] }), _jsxs(Popover, { open: confirmDeleteId === extension.id, onOpenChange: (open) => setConfirmDeleteId(open ? extension.id : null), children: [_jsx(PopoverTrigger, { asChild: true, children: _jsx("button", { type: "button", className: "absolute right-3 top-3 inline-flex h-8 w-8 items-center justify-center rounded-md text-muted-foreground opacity-0 hover:bg-accent hover:text-foreground focus:opacity-100 focus:outline-none focus:ring-2 focus:ring-ring group-hover:opacity-100", "aria-label": `Options for ${extension.name}`, children: _jsx(IconDotsVertical, { className: "h-4 w-4" }) }) }), _jsx(PopoverContent, { align: "end", sideOffset: 4, className: "w-64 p-0", children: _jsxs("div", { className: "p-3", children: [_jsxs("p", { className: "text-[12px]", children: [extension.canDelete === false ? "Remove " : "Delete ", _jsx("span", { className: "font-medium", children: extension.name }), "?", extension.canDelete === false
96
97
  ? " This hides it from your Extensions list without deleting it for anyone else."
97
98
  : " This removes it everywhere it is shared."] }), _jsxs("div", { className: "mt-3 flex justify-end gap-1", children: [_jsx("button", { type: "button", onClick: () => setConfirmDeleteId(null), className: "rounded-md px-2 py-1 text-[12px] hover:bg-accent", children: "Cancel" }), _jsxs("button", { type: "button", onClick: () => handleDelete(extension), disabled: deletingId === extension.id, className: cn("inline-flex items-center gap-1.5 rounded-md bg-destructive px-2 py-1 text-[12px] text-destructive-foreground hover:bg-destructive/90", deletingId === extension.id && "opacity-60"), children: [_jsx(IconTrash, { className: "h-3.5 w-3.5" }), deletingId === extension.id
98
99
  ? extension.canDelete === false