@agent-native/core 0.7.82 → 0.8.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 (265) hide show
  1. package/dist/action.js +1 -1
  2. package/dist/action.js.map +1 -1
  3. package/dist/agent/production-agent.d.ts.map +1 -1
  4. package/dist/agent/production-agent.js +8 -8
  5. package/dist/agent/production-agent.js.map +1 -1
  6. package/dist/agent/run-manager.d.ts +2 -0
  7. package/dist/agent/run-manager.d.ts.map +1 -1
  8. package/dist/agent/run-manager.js +44 -18
  9. package/dist/agent/run-manager.js.map +1 -1
  10. package/dist/agent/types.d.ts +1 -1
  11. package/dist/agent/types.d.ts.map +1 -1
  12. package/dist/agent/types.js.map +1 -1
  13. package/dist/cli/create.d.ts +1 -1
  14. package/dist/cli/create.d.ts.map +1 -1
  15. package/dist/cli/create.js +87 -19
  16. package/dist/cli/create.js.map +1 -1
  17. package/dist/cli/workspacify.d.ts.map +1 -1
  18. package/dist/cli/workspacify.js +12 -9
  19. package/dist/cli/workspacify.js.map +1 -1
  20. package/dist/client/AgentPanel.d.ts +1 -1
  21. package/dist/client/AgentPanel.d.ts.map +1 -1
  22. package/dist/client/AgentPanel.js +22 -1
  23. package/dist/client/AgentPanel.js.map +1 -1
  24. package/dist/client/FeedbackButton.d.ts +3 -2
  25. package/dist/client/FeedbackButton.d.ts.map +1 -1
  26. package/dist/client/FeedbackButton.js +18 -14
  27. package/dist/client/FeedbackButton.js.map +1 -1
  28. package/dist/client/agent-chat-adapter.d.ts.map +1 -1
  29. package/dist/client/agent-chat-adapter.js +254 -29
  30. package/dist/client/agent-chat-adapter.js.map +1 -1
  31. package/dist/client/agent-chat.d.ts +2 -0
  32. package/dist/client/agent-chat.d.ts.map +1 -1
  33. package/dist/client/agent-chat.js +11 -2
  34. package/dist/client/agent-chat.js.map +1 -1
  35. package/dist/client/builder-frame.d.ts +11 -0
  36. package/dist/client/builder-frame.d.ts.map +1 -1
  37. package/dist/client/builder-frame.js +40 -9
  38. package/dist/client/builder-frame.js.map +1 -1
  39. package/dist/client/composer/ComposerPlusMenu.js +1 -1
  40. package/dist/client/composer/ComposerPlusMenu.js.map +1 -1
  41. package/dist/client/composer/PromptComposer.d.ts +2 -0
  42. package/dist/client/composer/PromptComposer.d.ts.map +1 -1
  43. package/dist/client/composer/PromptComposer.js +3 -3
  44. package/dist/client/composer/PromptComposer.js.map +1 -1
  45. package/dist/client/composer/TiptapComposer.d.ts +3 -1
  46. package/dist/client/composer/TiptapComposer.d.ts.map +1 -1
  47. package/dist/client/composer/TiptapComposer.js +25 -13
  48. package/dist/client/composer/TiptapComposer.js.map +1 -1
  49. package/dist/client/composer/types.d.ts +1 -1
  50. package/dist/client/composer/types.d.ts.map +1 -1
  51. package/dist/client/composer/types.js.map +1 -1
  52. package/dist/client/extensions/EmbeddedExtension.d.ts +20 -0
  53. package/dist/client/extensions/EmbeddedExtension.d.ts.map +1 -0
  54. package/dist/client/{tools/EmbeddedTool.js → extensions/EmbeddedExtension.js} +41 -41
  55. package/dist/client/extensions/EmbeddedExtension.js.map +1 -0
  56. package/dist/client/extensions/ExtensionEditor.d.ts +5 -0
  57. package/dist/client/extensions/ExtensionEditor.d.ts.map +1 -0
  58. package/dist/client/extensions/ExtensionEditor.js +129 -0
  59. package/dist/client/extensions/ExtensionEditor.js.map +1 -0
  60. package/dist/client/{tools → extensions}/ExtensionSlot.d.ts +3 -3
  61. package/dist/client/extensions/ExtensionSlot.d.ts.map +1 -0
  62. package/dist/client/{tools → extensions}/ExtensionSlot.js +14 -14
  63. package/dist/client/extensions/ExtensionSlot.js.map +1 -0
  64. package/dist/client/extensions/ExtensionViewer.d.ts +5 -0
  65. package/dist/client/extensions/ExtensionViewer.d.ts.map +1 -0
  66. package/dist/client/{tools/ToolViewer.js → extensions/ExtensionViewer.js} +67 -65
  67. package/dist/client/extensions/ExtensionViewer.js.map +1 -0
  68. package/dist/client/extensions/ExtensionViewerPage.d.ts +2 -0
  69. package/dist/client/extensions/ExtensionViewerPage.d.ts.map +1 -0
  70. package/dist/client/{tools/ToolViewerPage.js → extensions/ExtensionViewerPage.js} +8 -8
  71. package/dist/client/extensions/ExtensionViewerPage.js.map +1 -0
  72. package/dist/client/extensions/ExtensionsListPage.d.ts +2 -0
  73. package/dist/client/extensions/ExtensionsListPage.d.ts.map +1 -0
  74. package/dist/client/extensions/ExtensionsListPage.js +67 -0
  75. package/dist/client/extensions/ExtensionsListPage.js.map +1 -0
  76. package/dist/client/extensions/ExtensionsSidebarSection.d.ts +2 -0
  77. package/dist/client/extensions/ExtensionsSidebarSection.d.ts.map +1 -0
  78. package/dist/client/{tools/ToolsSidebarSection.js → extensions/ExtensionsSidebarSection.js} +58 -58
  79. package/dist/client/extensions/ExtensionsSidebarSection.js.map +1 -0
  80. package/dist/client/{tools/tool-order.d.ts → extensions/extension-order.d.ts} +2 -2
  81. package/dist/client/extensions/extension-order.d.ts.map +1 -0
  82. package/dist/client/{tools/tool-order.js → extensions/extension-order.js} +3 -3
  83. package/dist/client/extensions/extension-order.js.map +1 -0
  84. package/dist/client/{tools → extensions}/iframe-bridge.d.ts +11 -11
  85. package/dist/client/extensions/iframe-bridge.d.ts.map +1 -0
  86. package/dist/client/{tools → extensions}/iframe-bridge.js +24 -24
  87. package/dist/client/extensions/iframe-bridge.js.map +1 -0
  88. package/dist/client/extensions/index.d.ts +14 -0
  89. package/dist/client/extensions/index.d.ts.map +1 -0
  90. package/dist/client/extensions/index.js +19 -0
  91. package/dist/client/extensions/index.js.map +1 -0
  92. package/dist/client/integrations/IntegrationsPanel.d.ts.map +1 -1
  93. package/dist/client/integrations/IntegrationsPanel.js +4 -1
  94. package/dist/client/integrations/IntegrationsPanel.js.map +1 -1
  95. package/dist/client/sse-event-processor.d.ts +2 -1
  96. package/dist/client/sse-event-processor.d.ts.map +1 -1
  97. package/dist/client/sse-event-processor.js +87 -6
  98. package/dist/client/sse-event-processor.js.map +1 -1
  99. package/dist/extensions/actions.d.ts +3 -0
  100. package/dist/extensions/actions.d.ts.map +1 -0
  101. package/dist/{tools → extensions}/actions.js +54 -51
  102. package/dist/extensions/actions.js.map +1 -0
  103. package/dist/{tools → extensions}/fetch-tool.d.ts +4 -0
  104. package/dist/extensions/fetch-tool.d.ts.map +1 -0
  105. package/dist/{tools → extensions}/fetch-tool.js +12 -7
  106. package/dist/extensions/fetch-tool.js.map +1 -0
  107. package/dist/extensions/html-shell.d.ts +56 -0
  108. package/dist/extensions/html-shell.d.ts.map +1 -0
  109. package/dist/{tools → extensions}/html-shell.js +101 -83
  110. package/dist/extensions/html-shell.js.map +1 -0
  111. package/dist/{tools → extensions}/proxy-security.d.ts +2 -2
  112. package/dist/extensions/proxy-security.d.ts.map +1 -0
  113. package/dist/{tools → extensions}/proxy-security.js +3 -3
  114. package/dist/extensions/proxy-security.js.map +1 -0
  115. package/dist/extensions/routes.d.ts +2 -0
  116. package/dist/extensions/routes.d.ts.map +1 -0
  117. package/dist/{tools → extensions}/routes.js +73 -69
  118. package/dist/extensions/routes.js.map +1 -0
  119. package/dist/{tools → extensions}/schema.d.ts +44 -38
  120. package/dist/extensions/schema.d.ts.map +1 -0
  121. package/dist/{tools → extensions}/schema.js +41 -34
  122. package/dist/extensions/schema.js.map +1 -0
  123. package/dist/extensions/slots/routes.d.ts +15 -0
  124. package/dist/extensions/slots/routes.d.ts.map +1 -0
  125. package/dist/{tools → extensions}/slots/routes.js +26 -26
  126. package/dist/extensions/slots/routes.js.map +1 -0
  127. package/dist/{tools → extensions}/slots/schema.d.ts +24 -21
  128. package/dist/extensions/slots/schema.d.ts.map +1 -0
  129. package/dist/extensions/slots/schema.js +79 -0
  130. package/dist/extensions/slots/schema.js.map +1 -0
  131. package/dist/extensions/slots/store.d.ts +66 -0
  132. package/dist/extensions/slots/store.d.ts.map +1 -0
  133. package/dist/extensions/slots/store.js +238 -0
  134. package/dist/extensions/slots/store.js.map +1 -0
  135. package/dist/extensions/store.d.ts +40 -0
  136. package/dist/extensions/store.d.ts.map +1 -0
  137. package/dist/{tools → extensions}/store.js +59 -54
  138. package/dist/extensions/store.js.map +1 -0
  139. package/dist/extensions/theme.d.ts.map +1 -0
  140. package/dist/extensions/theme.js.map +1 -0
  141. package/dist/{tools → extensions}/url-safety.d.ts +5 -3
  142. package/dist/extensions/url-safety.d.ts.map +1 -0
  143. package/dist/{tools → extensions}/url-safety.js +11 -4
  144. package/dist/extensions/url-safety.js.map +1 -0
  145. package/dist/server/action-discovery.d.ts +15 -0
  146. package/dist/server/action-discovery.d.ts.map +1 -1
  147. package/dist/server/action-discovery.js +45 -0
  148. package/dist/server/action-discovery.js.map +1 -1
  149. package/dist/server/agent-chat-plugin.d.ts.map +1 -1
  150. package/dist/server/agent-chat-plugin.js +12 -10
  151. package/dist/server/agent-chat-plugin.js.map +1 -1
  152. package/dist/server/auth.d.ts +5 -4
  153. package/dist/server/auth.d.ts.map +1 -1
  154. package/dist/server/auth.js +80 -28
  155. package/dist/server/auth.js.map +1 -1
  156. package/dist/server/core-routes-plugin.d.ts +15 -0
  157. package/dist/server/core-routes-plugin.d.ts.map +1 -1
  158. package/dist/server/core-routes-plugin.js +65 -13
  159. package/dist/server/core-routes-plugin.js.map +1 -1
  160. package/dist/server/csrf.d.ts +3 -2
  161. package/dist/server/csrf.d.ts.map +1 -1
  162. package/dist/server/csrf.js +3 -2
  163. package/dist/server/csrf.js.map +1 -1
  164. package/dist/server/google-oauth.d.ts.map +1 -1
  165. package/dist/server/google-oauth.js +15 -3
  166. package/dist/server/google-oauth.js.map +1 -1
  167. package/dist/server/index.d.ts +2 -2
  168. package/dist/server/index.d.ts.map +1 -1
  169. package/dist/server/index.js +1 -1
  170. package/dist/server/index.js.map +1 -1
  171. package/dist/shared/workspace-app-id.d.ts +1 -1
  172. package/dist/shared/workspace-app-id.d.ts.map +1 -1
  173. package/dist/shared/workspace-app-id.js +5 -1
  174. package/dist/shared/workspace-app-id.js.map +1 -1
  175. package/dist/templates/workspace-root/README.md +5 -4
  176. package/dist/usage/store.d.ts +1 -1
  177. package/dist/usage/store.d.ts.map +1 -1
  178. package/dist/usage/store.js +1 -1
  179. package/dist/usage/store.js.map +1 -1
  180. package/dist/vite/client.d.ts.map +1 -1
  181. package/dist/vite/client.js +17 -1
  182. package/dist/vite/client.js.map +1 -1
  183. package/docs/content/actions.md +10 -10
  184. package/docs/content/extensions.md +230 -0
  185. package/docs/content/key-concepts.md +2 -2
  186. package/docs/content/server.md +13 -13
  187. package/docs/content/sharing.md +2 -2
  188. package/docs/content/template-analytics.md +10 -0
  189. package/docs/content/template-calendar.md +10 -0
  190. package/docs/content/template-clips.md +10 -0
  191. package/docs/content/template-content.md +10 -0
  192. package/docs/content/template-dispatch.md +15 -0
  193. package/docs/content/template-forms.md +10 -0
  194. package/docs/content/template-mail.md +10 -0
  195. package/docs/content/template-slides.md +11 -1
  196. package/docs/content/template-starter.md +10 -0
  197. package/docs/content/template-video.md +10 -0
  198. package/docs/content/what-is-agent-native.md +1 -1
  199. package/package.json +22 -17
  200. package/src/templates/workspace-root/README.md +5 -4
  201. package/dist/client/tools/EmbeddedTool.d.ts +0 -20
  202. package/dist/client/tools/EmbeddedTool.d.ts.map +0 -1
  203. package/dist/client/tools/EmbeddedTool.js.map +0 -1
  204. package/dist/client/tools/ExtensionSlot.d.ts.map +0 -1
  205. package/dist/client/tools/ExtensionSlot.js.map +0 -1
  206. package/dist/client/tools/ToolEditor.d.ts +0 -5
  207. package/dist/client/tools/ToolEditor.d.ts.map +0 -1
  208. package/dist/client/tools/ToolEditor.js +0 -129
  209. package/dist/client/tools/ToolEditor.js.map +0 -1
  210. package/dist/client/tools/ToolViewer.d.ts +0 -5
  211. package/dist/client/tools/ToolViewer.d.ts.map +0 -1
  212. package/dist/client/tools/ToolViewer.js.map +0 -1
  213. package/dist/client/tools/ToolViewerPage.d.ts +0 -2
  214. package/dist/client/tools/ToolViewerPage.d.ts.map +0 -1
  215. package/dist/client/tools/ToolViewerPage.js.map +0 -1
  216. package/dist/client/tools/ToolsListPage.d.ts +0 -2
  217. package/dist/client/tools/ToolsListPage.d.ts.map +0 -1
  218. package/dist/client/tools/ToolsListPage.js +0 -67
  219. package/dist/client/tools/ToolsListPage.js.map +0 -1
  220. package/dist/client/tools/ToolsSidebarSection.d.ts +0 -2
  221. package/dist/client/tools/ToolsSidebarSection.d.ts.map +0 -1
  222. package/dist/client/tools/ToolsSidebarSection.js.map +0 -1
  223. package/dist/client/tools/iframe-bridge.d.ts.map +0 -1
  224. package/dist/client/tools/iframe-bridge.js.map +0 -1
  225. package/dist/client/tools/index.d.ts +0 -8
  226. package/dist/client/tools/index.d.ts.map +0 -1
  227. package/dist/client/tools/index.js +0 -8
  228. package/dist/client/tools/index.js.map +0 -1
  229. package/dist/client/tools/tool-order.d.ts.map +0 -1
  230. package/dist/client/tools/tool-order.js.map +0 -1
  231. package/dist/tools/actions.d.ts +0 -3
  232. package/dist/tools/actions.d.ts.map +0 -1
  233. package/dist/tools/actions.js.map +0 -1
  234. package/dist/tools/fetch-tool.d.ts.map +0 -1
  235. package/dist/tools/fetch-tool.js.map +0 -1
  236. package/dist/tools/html-shell.d.ts +0 -45
  237. package/dist/tools/html-shell.d.ts.map +0 -1
  238. package/dist/tools/html-shell.js.map +0 -1
  239. package/dist/tools/proxy-security.d.ts.map +0 -1
  240. package/dist/tools/proxy-security.js.map +0 -1
  241. package/dist/tools/routes.d.ts +0 -2
  242. package/dist/tools/routes.d.ts.map +0 -1
  243. package/dist/tools/routes.js.map +0 -1
  244. package/dist/tools/schema.d.ts.map +0 -1
  245. package/dist/tools/schema.js.map +0 -1
  246. package/dist/tools/slots/routes.d.ts +0 -15
  247. package/dist/tools/slots/routes.d.ts.map +0 -1
  248. package/dist/tools/slots/routes.js.map +0 -1
  249. package/dist/tools/slots/schema.d.ts.map +0 -1
  250. package/dist/tools/slots/schema.js +0 -76
  251. package/dist/tools/slots/schema.js.map +0 -1
  252. package/dist/tools/slots/store.d.ts +0 -66
  253. package/dist/tools/slots/store.d.ts.map +0 -1
  254. package/dist/tools/slots/store.js +0 -227
  255. package/dist/tools/slots/store.js.map +0 -1
  256. package/dist/tools/store.d.ts +0 -40
  257. package/dist/tools/store.d.ts.map +0 -1
  258. package/dist/tools/store.js.map +0 -1
  259. package/dist/tools/theme.d.ts.map +0 -1
  260. package/dist/tools/theme.js.map +0 -1
  261. package/dist/tools/url-safety.d.ts.map +0 -1
  262. package/dist/tools/url-safety.js.map +0 -1
  263. package/docs/content/tools.md +0 -205
  264. /package/dist/{tools → extensions}/theme.d.ts +0 -0
  265. /package/dist/{tools → extensions}/theme.js +0 -0
@@ -0,0 +1 @@
1
+ {"version":3,"file":"ExtensionViewer.d.ts","sourceRoot":"","sources":["../../../src/client/extensions/ExtensionViewer.tsx"],"names":[],"mappings":"AA8EA,MAAM,WAAW,oBAAoB;IACnC,WAAW,EAAE,MAAM,CAAC;CACrB;AA4DD,wBAAgB,eAAe,CAAC,EAAE,WAAW,EAAE,EAAE,oBAAoB,2CAkZpE"}
@@ -10,7 +10,7 @@ import { NotificationsBell } from "../notifications/NotificationsBell.js";
10
10
  import { sendToAgentChat } from "../agent-chat.js";
11
11
  import { PromptComposer } from "../composer/PromptComposer.js";
12
12
  import { Popover, PopoverContent, PopoverTrigger, } from "../components/ui/popover.js";
13
- import { isAllowedToolPath, sanitizeToolRequestOptions, checkBridgePolicy, } from "./iframe-bridge.js";
13
+ import { isAllowedExtensionPath, sanitizeExtensionRequestOptions, checkBridgePolicy, } from "./iframe-bridge.js";
14
14
  const THEME_CSS_VARS = [
15
15
  "--background",
16
16
  "--foreground",
@@ -51,10 +51,10 @@ function getParentThemeVars() {
51
51
  }
52
52
  return vars;
53
53
  }
54
- function EditToolPopover({ tool }) {
54
+ function EditToolPopover({ extension }) {
55
55
  const [open, setOpen] = useState(false);
56
56
  // Radix's outside-click detection runs in the parent document, so a click
57
- // inside the tool iframe (or any other iframe) never fires it. The browser
57
+ // inside the extension iframe (or any other iframe) never fires it. The browser
58
58
  // does shift focus to the iframe though, which blurs the parent window — we
59
59
  // hook that to close the popover so it behaves like a normal click-outside.
60
60
  useEffect(() => {
@@ -77,15 +77,15 @@ function EditToolPopover({ tool }) {
77
77
  return;
78
78
  sendToAgentChat({
79
79
  message: trimmed,
80
- context: `The user is viewing tool "${tool.name}" (id: ${tool.id}) and wants to edit it.`,
80
+ context: `The user is viewing extension "${extension.name}" (id: ${extension.id}) and wants to edit it.`,
81
81
  submit: true,
82
82
  openSidebar: true,
83
83
  });
84
84
  setOpen(false);
85
85
  };
86
- return (_jsxs(Popover, { open: open, onOpenChange: setOpen, 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", title: "Edit", children: _jsx(IconPencil, { className: "h-4 w-4" }) }) }), _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 tool" }), _jsx(PromptComposer, { autoFocus: true, placeholder: "What would you like to change?", draftScope: `tools:edit:${tool.id}`, onSubmit: handleSubmit })] })] }));
86
+ return (_jsxs(Popover, { open: open, onOpenChange: setOpen, 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", title: "Edit", children: _jsx(IconPencil, { className: "h-4 w-4" }) }) }), _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 })] })] }));
87
87
  }
88
- export function ToolViewer({ toolId }) {
88
+ export function ExtensionViewer({ extensionId }) {
89
89
  const [isDark, setIsDark] = useState(false);
90
90
  const [iframeReady, setIframeReady] = useState(false);
91
91
  const iframeRef = useRef(null);
@@ -97,7 +97,7 @@ export function ToolViewer({ toolId }) {
97
97
  const queryClient = useQueryClient();
98
98
  // (audit H4) Role plumbed through from the iframe's render binding. Until
99
99
  // the iframe announces its role we deny non-trivial helper calls — that
100
- // way a malicious tool body that races the announcement can't briefly
100
+ // way a malicious extension body that races the announcement can't briefly
101
101
  // operate at higher privilege than the viewer's actual role.
102
102
  const bridgeContextRef = useRef({
103
103
  role: "viewer",
@@ -136,10 +136,10 @@ export function ToolViewer({ toolId }) {
136
136
  const message = event.data;
137
137
  if (!message)
138
138
  return;
139
- if (message.type === "agent-native-tool-binding") {
139
+ if (message.type === "agent-native-extension-binding") {
140
140
  // (audit H4) The iframe announced its render binding. Trust the role
141
141
  // value because the iframe's binding is generated server-side in
142
- // tools/routes.ts (resolveAccess), not by user-authored content.
142
+ // extensions/routes.ts (resolveAccess), not by user-authored content.
143
143
  const binding = message.binding ?? {};
144
144
  const role = binding.role === "owner" ||
145
145
  binding.role === "admin" ||
@@ -153,20 +153,22 @@ export function ToolViewer({ toolId }) {
153
153
  };
154
154
  return;
155
155
  }
156
- if (message.type === "agent-native-tool-consent-granted" ||
157
- message.type === "agent-native-tool-consent-cancelled") {
156
+ if (message.type === "agent-native-extension-consent-granted" ||
157
+ message.type === "agent-native-extension-consent-cancelled") {
158
158
  // (audit C1) The consent stub fired; force a reload of the iframe so
159
- // the next render returns the tool body (granted) or stays on the
159
+ // the next render returns the extension body (granted) or stays on the
160
160
  // stub (cancelled — viewer can also navigate away).
161
- if (message.type === "agent-native-tool-consent-granted") {
162
- // Invalidate the cached tool record — author may have edited
161
+ if (message.type === "agent-native-extension-consent-granted") {
162
+ // Invalidate the cached extension record — author may have edited
163
163
  // since the cache was warmed.
164
- queryClient.invalidateQueries({ queryKey: ["tool", toolId] });
164
+ queryClient.invalidateQueries({
165
+ queryKey: ["extension", extensionId],
166
+ });
165
167
  setRefreshKey((k) => k + 1);
166
168
  }
167
169
  return;
168
170
  }
169
- if (message.type === "agent-native-tool-keydown") {
171
+ if (message.type === "agent-native-extension-keydown") {
170
172
  document.dispatchEvent(new KeyboardEvent("keydown", {
171
173
  key: message.key,
172
174
  code: message.code,
@@ -179,7 +181,7 @@ export function ToolViewer({ toolId }) {
179
181
  }));
180
182
  return;
181
183
  }
182
- if (message.type === "agent-native-tool-error-fix") {
184
+ if (message.type === "agent-native-extension-error-fix") {
183
185
  const t = toolRef.current;
184
186
  if (!t)
185
187
  return;
@@ -191,7 +193,7 @@ export function ToolViewer({ toolId }) {
191
193
  .map((e) => (e.stack ? `${e.message}\n${e.stack}` : e.message))
192
194
  .join("\n\n");
193
195
  const contextParts = [
194
- `The user is viewing tool "${t.name}" (id: ${t.id}) and there are runtime errors that need fixing.`,
196
+ `The user is viewing extension "${t.name}" (id: ${t.id}) and there are runtime errors that need fixing.`,
195
197
  `\nFull error details:\n${detailedTrace}`,
196
198
  ];
197
199
  if (consoleLogs.length > 0) {
@@ -207,31 +209,31 @@ export function ToolViewer({ toolId }) {
207
209
  contextParts.push(`\nRecent network requests:\n${netStr}`);
208
210
  }
209
211
  sendToAgentChat({
210
- message: `Fix runtime errors in this tool:\n${errors.join("\n")}`,
212
+ message: `Fix runtime errors in this extension:\n${errors.join("\n")}`,
211
213
  context: contextParts.join("\n"),
212
214
  submit: true,
213
215
  openSidebar: true,
214
216
  });
215
217
  return;
216
218
  }
217
- if (message.type !== "agent-native-tool-request")
219
+ if (message.type !== "agent-native-extension-request")
218
220
  return;
219
221
  const requestId = String(message.requestId ?? "");
220
222
  const path = String(message.path ?? "");
221
223
  const respond = (payload) => {
222
224
  iframeRef.current?.contentWindow?.postMessage({
223
- type: "agent-native-tool-response",
225
+ type: "agent-native-extension-response",
224
226
  requestId,
225
227
  ...payload,
226
228
  }, "*");
227
229
  };
228
- if (!requestId || !isAllowedToolPath(path, toolId)) {
229
- respond({ error: "Tool request path is not allowed" });
230
+ if (!requestId || !isAllowedExtensionPath(path, extensionId)) {
231
+ respond({ error: "Extension request path is not allowed" });
230
232
  return;
231
233
  }
232
234
  try {
233
- const options = sanitizeToolRequestOptions(message.options);
234
- // (audit H4) Role-aware policy gate: viewer-shared tools can read
235
+ const options = sanitizeExtensionRequestOptions(message.options);
236
+ // (audit H4) Role-aware policy gate: viewer-shared extensions can read
235
237
  // but not write. Decided here in the parent before the request
236
238
  // leaves; the server enforces a second layer.
237
239
  const policy = checkBridgePolicy(path, options.method ?? "GET", bridgeContextRef.current);
@@ -247,13 +249,13 @@ export function ToolViewer({ toolId }) {
247
249
  return;
248
250
  }
249
251
  // (audit H5) Tag every outbound bridge request with the
250
- // X-Agent-Native-Tool-Bridge sentinel so the action-routes layer can
252
+ // X-Agent-Native-Extension-Bridge sentinel so the action-routes layer can
251
253
  // enforce per-action `toolCallable` opt-in. The header is added by
252
254
  // the parent — it is NOT taken from the iframe-supplied options
253
- // (which were filtered by sanitizeToolRequestOptions).
255
+ // (which were filtered by sanitizeExtensionRequestOptions).
254
256
  const finalHeaders = new Headers(options.headers ?? undefined);
255
- finalHeaders.set("X-Agent-Native-Tool-Bridge", "1");
256
- finalHeaders.set("X-Agent-Native-Tool-Id", toolId);
257
+ finalHeaders.set("X-Agent-Native-Extension-Bridge", "1");
258
+ finalHeaders.set("X-Agent-Native-Extension-Id", extensionId);
257
259
  const res = await fetch(agentNativePath(path), {
258
260
  ...options,
259
261
  headers: finalHeaders,
@@ -279,84 +281,84 @@ export function ToolViewer({ toolId }) {
279
281
  });
280
282
  }
281
283
  catch (err) {
282
- respond({ error: err?.message ?? "Tool host request failed" });
284
+ respond({ error: err?.message ?? "Extension host request failed" });
283
285
  }
284
286
  };
285
287
  window.addEventListener("message", handleMessage);
286
288
  return () => window.removeEventListener("message", handleMessage);
287
- }, [toolId, queryClient]);
288
- const { data: tool, isLoading } = useQuery({
289
- queryKey: ["tool", toolId],
289
+ }, [extensionId, queryClient]);
290
+ const { data: extension, isLoading } = useQuery({
291
+ queryKey: ["extension", extensionId],
290
292
  queryFn: async () => {
291
- const res = await fetch(agentNativePath(`/_agent-native/tools/${toolId}`));
293
+ const res = await fetch(agentNativePath(`/_agent-native/extensions/${extensionId}`));
292
294
  if (!res.ok)
293
- throw new Error("Failed to fetch tool");
295
+ throw new Error("Failed to fetch extension");
294
296
  return res.json();
295
297
  },
296
298
  });
297
- toolRef.current = tool ?? null;
298
- const iframeSrc = useMemo(() => agentNativePath(`/_agent-native/tools/${toolId}/render?dark=${document.documentElement.classList.contains("dark")}&v=${encodeURIComponent(tool?.updatedAt ?? "")}&r=${refreshKey}`), [toolId, tool?.updatedAt, refreshKey]);
299
+ toolRef.current = extension ?? null;
300
+ 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]);
299
301
  useEffect(() => {
300
302
  setIframeReady(false);
301
303
  // Reset role to deny-by-default on every reload — the new render's
302
304
  // binding announcement re-establishes the role before any helper call.
303
305
  bridgeContextRef.current = { role: "viewer", isAuthor: false };
304
- }, [toolId, tool?.updatedAt, refreshKey]);
306
+ }, [extensionId, extension?.updatedAt, refreshKey]);
305
307
  const startRename = useCallback(() => {
306
- if (!tool)
308
+ if (!extension)
307
309
  return;
308
- setRenameValue(tool.name);
310
+ setRenameValue(extension.name);
309
311
  setIsRenaming(true);
310
312
  requestAnimationFrame(() => renameInputRef.current?.select());
311
- }, [tool]);
313
+ }, [extension]);
312
314
  const submitRename = useCallback(async () => {
313
315
  const trimmed = renameValue.trim();
314
- if (!trimmed || !tool || trimmed === tool.name) {
316
+ if (!trimmed || !extension || trimmed === extension.name) {
315
317
  setIsRenaming(false);
316
318
  return;
317
319
  }
318
- queryClient.setQueryData(["tool", toolId], (old) => old ? { ...old, name: trimmed } : old);
319
- queryClient.setQueryData(["tools"], (old) => (old ?? []).map((t) => (t.id === toolId ? { ...t, name: trimmed } : t)));
320
+ queryClient.setQueryData(["extension", extensionId], (old) => old ? { ...old, name: trimmed } : old);
321
+ queryClient.setQueryData(["extensions"], (old) => (old ?? []).map((t) => t.id === extensionId ? { ...t, name: trimmed } : t));
320
322
  setIsRenaming(false);
321
323
  try {
322
- await fetch(agentNativePath(`/_agent-native/tools/${toolId}`), {
324
+ await fetch(agentNativePath(`/_agent-native/extensions/${extensionId}`), {
323
325
  method: "PUT",
324
326
  headers: { "Content-Type": "application/json" },
325
327
  body: JSON.stringify({ name: trimmed }),
326
328
  });
327
- queryClient.invalidateQueries({ queryKey: ["tool", toolId] });
328
- queryClient.invalidateQueries({ queryKey: ["tools"] });
329
+ queryClient.invalidateQueries({ queryKey: ["extension", extensionId] });
330
+ queryClient.invalidateQueries({ queryKey: ["extensions"] });
329
331
  }
330
332
  catch {
331
- queryClient.invalidateQueries({ queryKey: ["tool", toolId] });
332
- queryClient.invalidateQueries({ queryKey: ["tools"] });
333
+ queryClient.invalidateQueries({ queryKey: ["extension", extensionId] });
334
+ queryClient.invalidateQueries({ queryKey: ["extensions"] });
333
335
  }
334
- }, [renameValue, tool, toolId, queryClient]);
336
+ }, [renameValue, extension, extensionId, queryClient]);
335
337
  if (isLoading) {
336
338
  return (_jsxs("div", { className: "flex h-full flex-col", children: [_jsxs("div", { className: "flex h-12 items-center gap-2 px-3 border-b shrink-0", children: [_jsx("div", { className: "h-3.5 w-3.5 rounded bg-muted animate-pulse" }), _jsx("div", { className: "h-3.5 w-24 rounded bg-muted animate-pulse" })] }), _jsx("div", { className: "flex-1 bg-muted/20 animate-pulse" })] }));
337
339
  }
338
- if (!tool) {
339
- return (_jsx("div", { className: "flex h-full items-center justify-center text-sm text-muted-foreground", children: "Tool not found" }));
340
+ if (!extension) {
341
+ return (_jsx("div", { className: "flex h-full items-center justify-center text-sm text-muted-foreground", children: "Extension not found" }));
340
342
  }
341
343
  return (_jsxs("div", { className: "flex h-full w-full flex-col", children: [_jsxs("div", { className: "flex h-12 items-center justify-between border-b px-3 shrink-0", children: [_jsx("div", { className: "group/name flex items-center gap-1", children: isRenaming ? (_jsx("input", { ref: renameInputRef, value: renameValue, onChange: (e) => setRenameValue(e.target.value), onBlur: submitRename, onKeyDown: (e) => {
342
344
  if (e.key === "Enter")
343
345
  submitRename();
344
346
  if (e.key === "Escape")
345
347
  setIsRenaming(false);
346
- }, className: "text-sm font-medium bg-transparent border-b border-primary outline-none py-0 px-0" })) : (_jsxs(_Fragment, { children: [_jsx("span", { className: "text-sm font-medium", children: tool.name }), _jsx("button", { type: "button", onClick: startRename, className: "cursor-pointer rounded p-0.5 text-muted-foreground/40 opacity-0 group-hover/name:opacity-100 hover:text-foreground", title: "Rename", children: _jsx(IconPencil, { className: "h-3 w-3" }) })] })) }), _jsxs("div", { className: "flex items-center gap-1", children: [_jsx("button", { type: "button", onClick: () => setRefreshKey((k) => k + 1), 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", title: "Refresh", children: _jsx(IconRefresh, { className: "h-4 w-4" }) }), _jsx(EditToolPopover, { tool: tool }), _jsx(ShareButton, { resourceType: "tool", resourceId: toolId, resourceTitle: tool.name }), _jsx(ToolMoreMenu, { toolId: toolId, toolName: tool.name }), _jsx(NotificationsBell, {}), _jsx(AgentToggleButton, { className: "h-8 w-8 rounded-md hover:bg-accent" })] })] }), _jsxs("div", { className: "relative flex-1 min-h-0", children: [!iframeReady && (_jsx("div", { className: "absolute inset-0 flex items-center justify-center bg-background z-10", children: _jsx(IconLoader2, { className: "size-5 animate-spin text-muted-foreground", role: "status", "aria-label": "Loading" }) })), _jsx("iframe", { ref: iframeRef, src: iframeSrc, className: "h-full w-full border-0", sandbox: "allow-scripts allow-forms", title: tool.name, onLoad: () => {
348
+ }, className: "text-sm font-medium bg-transparent border-b border-primary outline-none py-0 px-0" })) : (_jsxs(_Fragment, { children: [_jsx("span", { className: "text-sm font-medium", children: extension.name }), _jsx("button", { type: "button", onClick: startRename, className: "cursor-pointer rounded p-0.5 text-muted-foreground/40 opacity-0 group-hover/name:opacity-100 hover:text-foreground", title: "Rename", children: _jsx(IconPencil, { className: "h-3 w-3" }) })] })) }), _jsxs("div", { className: "flex items-center gap-1", children: [_jsx("button", { type: "button", onClick: () => setRefreshKey((k) => k + 1), 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", title: "Refresh", children: _jsx(IconRefresh, { className: "h-4 w-4" }) }), _jsx(EditToolPopover, { extension: extension }), _jsx(ShareButton, { resourceType: "extension", resourceId: extensionId, resourceTitle: extension.name }), _jsx(ToolMoreMenu, { extensionId: extensionId, toolName: extension.name }), _jsx(NotificationsBell, {}), _jsx(AgentToggleButton, { className: "h-8 w-8 rounded-md hover:bg-accent" })] })] }), _jsxs("div", { className: "relative flex-1 min-h-0", children: [!iframeReady && (_jsx("div", { className: "absolute inset-0 flex items-center justify-center bg-background z-10", children: _jsx(IconLoader2, { className: "size-5 animate-spin text-muted-foreground", role: "status", "aria-label": "Loading" }) })), _jsx("iframe", { ref: iframeRef, src: iframeSrc, className: "h-full w-full border-0", sandbox: "allow-scripts allow-forms", title: extension.name, onLoad: () => {
347
349
  sendThemeToIframe();
348
350
  setTimeout(() => setIframeReady(true), 150);
349
- } }, `${tool.updatedAt}-${refreshKey}`)] })] }));
351
+ } }, `${extension.updatedAt}-${refreshKey}`)] })] }));
350
352
  }
351
- function ToolMoreMenu({ toolId, toolName, }) {
353
+ function ToolMoreMenu({ extensionId, toolName, }) {
352
354
  const [open, setOpen] = useState(false);
353
355
  const [confirmingDelete, setConfirmingDelete] = useState(false);
354
356
  const queryClient = useQueryClient();
355
357
  const navigate = useNavigate();
356
358
  const { data: slots = [] } = useQuery({
357
- queryKey: ["tool-slots", toolId],
359
+ queryKey: ["extension-slots", extensionId],
358
360
  queryFn: async () => {
359
- const res = await fetch(agentNativePath(`/_agent-native/slots/tool/${toolId}`));
361
+ const res = await fetch(agentNativePath(`/_agent-native/slots/extension/${extensionId}`));
360
362
  if (!res.ok)
361
363
  return [];
362
364
  return res.json();
@@ -369,32 +371,32 @@ function ToolMoreMenu({ toolId, toolName, }) {
369
371
  };
370
372
  const removeFromSlot = async (slotId) => {
371
373
  try {
372
- await fetch(agentNativePath(`/_agent-native/slots/${encodeURIComponent(slotId)}/install/${encodeURIComponent(toolId)}`), { method: "DELETE" });
374
+ await fetch(agentNativePath(`/_agent-native/slots/${encodeURIComponent(slotId)}/install/${encodeURIComponent(extensionId)}`), { method: "DELETE" });
373
375
  }
374
376
  finally {
375
377
  queryClient.invalidateQueries({ queryKey: ["slot-installs", slotId] });
376
378
  }
377
379
  };
378
- const deleteTool = async () => {
380
+ const deleteExtension = async () => {
379
381
  closeMenu();
380
382
  try {
381
- await fetch(agentNativePath(`/_agent-native/tools/${toolId}`), {
383
+ await fetch(agentNativePath(`/_agent-native/extensions/${extensionId}`), {
382
384
  method: "DELETE",
383
385
  });
384
386
  }
385
387
  finally {
386
- queryClient.invalidateQueries({ queryKey: ["tool", toolId] });
387
- queryClient.invalidateQueries({ queryKey: ["tools"] });
388
+ queryClient.invalidateQueries({ queryKey: ["extension", extensionId] });
389
+ queryClient.invalidateQueries({ queryKey: ["extensions"] });
388
390
  slots.forEach((s) => queryClient.invalidateQueries({
389
391
  queryKey: ["slot-installs", s.slotId],
390
392
  }));
391
- navigate("/tools");
393
+ navigate("/extensions");
392
394
  }
393
395
  };
394
396
  return (_jsxs(Popover, { open: open, onOpenChange: (o) => {
395
397
  setOpen(o);
396
398
  if (!o)
397
399
  setConfirmingDelete(false);
398
- }, 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", title: "More options", "aria-label": "More options", children: _jsx(IconDots, { className: "h-4 w-4" }) }) }), _jsx(PopoverContent, { align: "end", sideOffset: 4, className: "w-72 p-0", children: !confirmingDelete ? (_jsxs(_Fragment, { children: [_jsxs("div", { className: "px-3 py-2 border-b border-border/40", children: [_jsx("p", { className: "text-[12px] font-medium", children: "Appears in" }), slots.length === 0 ? (_jsx("p", { className: "text-[11px] text-muted-foreground/70 mt-0.5", children: "Not installed in any widget areas. Ask the agent to add it somewhere." })) : (_jsxs("p", { className: "text-[11px] text-muted-foreground/70 mt-0.5", children: ["This tool can render in ", slots.length, " widget area", slots.length === 1 ? "" : "s", "."] }))] }), slots.length > 0 && (_jsx("div", { className: "max-h-48 overflow-y-auto py-1", children: slots.map((s) => (_jsxs("div", { className: "flex items-center gap-2 px-3 py-1.5 text-[12px]", children: [_jsx("span", { className: "flex-1 truncate font-mono text-[11px] text-muted-foreground", children: s.slotId }), _jsx("button", { type: "button", onClick: () => removeFromSlot(s.slotId), className: "rounded p-1 text-muted-foreground/60 hover:bg-accent hover:text-foreground cursor-pointer", title: "Remove from this widget area (for me)", "aria-label": "Remove from this widget area", children: _jsx(IconX, { className: "h-3.5 w-3.5" }) })] }, s.id))) })), _jsx("div", { className: "border-t border-border/40 p-1", children: _jsxs("button", { type: "button", onClick: () => setConfirmingDelete(true), 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", children: [_jsx(IconTrash, { className: "h-3.5 w-3.5" }), _jsx("span", { children: "Delete tool\u2026" })] }) })] })) : (_jsxs("div", { className: "flex flex-col gap-2 p-3", children: [_jsxs("p", { className: "text-[12px]", children: ["Delete ", _jsx("span", { className: "font-medium", children: toolName }), "? This removes the tool everywhere, for everyone it's shared with."] }), _jsxs("div", { className: "flex justify-end gap-1", children: [_jsx("button", { type: "button", onClick: () => setConfirmingDelete(false), className: "rounded-md px-2 py-1 text-[12px] hover:bg-accent cursor-pointer", children: "Cancel" }), _jsx("button", { type: "button", onClick: deleteTool, className: "rounded-md bg-destructive px-2 py-1 text-[12px] text-destructive-foreground hover:bg-destructive/90 cursor-pointer", children: "Delete" })] })] })) })] }));
400
+ }, 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", title: "More options", "aria-label": "More options", children: _jsx(IconDots, { className: "h-4 w-4" }) }) }), _jsx(PopoverContent, { align: "end", sideOffset: 4, className: "w-72 p-0", children: !confirmingDelete ? (_jsxs(_Fragment, { children: [_jsxs("div", { className: "px-3 py-2 border-b border-border/40", children: [_jsx("p", { className: "text-[12px] font-medium", children: "Appears in" }), slots.length === 0 ? (_jsx("p", { className: "text-[11px] text-muted-foreground/70 mt-0.5", children: "Not installed in any widget areas. Ask the agent to add it somewhere." })) : (_jsxs("p", { className: "text-[11px] text-muted-foreground/70 mt-0.5", children: ["This extension can render in ", slots.length, " widget area", slots.length === 1 ? "" : "s", "."] }))] }), slots.length > 0 && (_jsx("div", { className: "max-h-48 overflow-y-auto py-1", children: slots.map((s) => (_jsxs("div", { className: "flex items-center gap-2 px-3 py-1.5 text-[12px]", children: [_jsx("span", { className: "flex-1 truncate font-mono text-[11px] text-muted-foreground", children: s.slotId }), _jsx("button", { type: "button", onClick: () => removeFromSlot(s.slotId), className: "rounded p-1 text-muted-foreground/60 hover:bg-accent hover:text-foreground cursor-pointer", title: "Remove from this widget area (for me)", "aria-label": "Remove from this widget area", children: _jsx(IconX, { className: "h-3.5 w-3.5" }) })] }, s.id))) })), _jsx("div", { className: "border-t border-border/40 p-1", children: _jsxs("button", { type: "button", onClick: () => setConfirmingDelete(true), 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", children: [_jsx(IconTrash, { className: "h-3.5 w-3.5" }), _jsx("span", { children: "Delete extension\u2026" })] }) })] })) : (_jsxs("div", { className: "flex flex-col gap-2 p-3", children: [_jsxs("p", { className: "text-[12px]", children: ["Delete ", _jsx("span", { className: "font-medium", children: toolName }), "? This removes the extension everywhere, for everyone it's shared with."] }), _jsxs("div", { className: "flex justify-end gap-1", children: [_jsx("button", { type: "button", onClick: () => setConfirmingDelete(false), className: "rounded-md px-2 py-1 text-[12px] hover:bg-accent cursor-pointer", children: "Cancel" }), _jsx("button", { type: "button", onClick: deleteExtension, className: "rounded-md bg-destructive px-2 py-1 text-[12px] text-destructive-foreground hover:bg-destructive/90 cursor-pointer", children: "Delete" })] })] })) })] }));
399
401
  }
400
- //# sourceMappingURL=ToolViewer.js.map
402
+ //# sourceMappingURL=ExtensionViewer.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"ExtensionViewer.js","sourceRoot":"","sources":["../../../src/client/extensions/ExtensionViewer.tsx"],"names":[],"mappings":";AAAA,OAAO,EAAE,eAAe,EAAE,MAAM,gBAAgB,CAAC;AACjD,OAAO,EAAE,QAAQ,EAAE,SAAS,EAAE,MAAM,EAAE,WAAW,EAAE,OAAO,EAAE,MAAM,OAAO,CAAC;AAC1E,OAAO,EAAE,QAAQ,EAAE,cAAc,EAAE,MAAM,uBAAuB,CAAC;AACjE,OAAO,EAAE,WAAW,EAAE,MAAM,cAAc,CAAC;AAC3C,OAAO,EACL,QAAQ,EACR,WAAW,EACX,UAAU,EACV,WAAW,EACX,SAAS,EACT,KAAK,GACN,MAAM,qBAAqB,CAAC;AAC7B,OAAO,EAAE,WAAW,EAAE,MAAM,2BAA2B,CAAC;AACxD,OAAO,EAAE,iBAAiB,EAAE,MAAM,kBAAkB,CAAC;AACrD,OAAO,EAAE,iBAAiB,EAAE,MAAM,uCAAuC,CAAC;AAC1E,OAAO,EAAE,eAAe,EAAE,MAAM,kBAAkB,CAAC;AACnD,OAAO,EAAE,cAAc,EAAE,MAAM,+BAA+B,CAAC;AAC/D,OAAO,EACL,OAAO,EACP,cAAc,EACd,cAAc,GACf,MAAM,6BAA6B,CAAC;AACrC,OAAO,EACL,sBAAsB,EACtB,+BAA+B,EAC/B,iBAAiB,GAElB,MAAM,oBAAoB,CAAC;AAE5B,MAAM,cAAc,GAAG;IACrB,cAAc;IACd,cAAc;IACd,QAAQ;IACR,mBAAmB;IACnB,WAAW;IACX,sBAAsB;IACtB,WAAW;IACX,sBAAsB;IACtB,aAAa;IACb,wBAAwB;IACxB,SAAS;IACT,oBAAoB;IACpB,UAAU;IACV,qBAAqB;IACrB,eAAe;IACf,0BAA0B;IAC1B,UAAU;IACV,SAAS;IACT,QAAQ;IACR,UAAU;IACV,sBAAsB;IACtB,sBAAsB;IACtB,mBAAmB;IACnB,8BAA8B;IAC9B,kBAAkB;IAClB,6BAA6B;IAC7B,kBAAkB;IAClB,gBAAgB;CACjB,CAAC;AAEF,SAAS,kBAAkB;IACzB,MAAM,QAAQ,GAAG,gBAAgB,CAAC,QAAQ,CAAC,eAAe,CAAC,CAAC;IAC5D,MAAM,IAAI,GAA2B,EAAE,CAAC;IACxC,KAAK,MAAM,IAAI,IAAI,cAAc,EAAE,CAAC;QAClC,MAAM,GAAG,GAAG,QAAQ,CAAC,gBAAgB,CAAC,IAAI,CAAC,CAAC,IAAI,EAAE,CAAC;QACnD,IAAI,GAAG;YAAE,IAAI,CAAC,IAAI,CAAC,GAAG,GAAG,CAAC;IAC5B,CAAC;IACD,OAAO,IAAI,CAAC;AACd,CAAC;AAcD,SAAS,eAAe,CAAC,EAAE,SAAS,EAA4B;IAC9D,MAAM,CAAC,IAAI,EAAE,OAAO,CAAC,GAAG,QAAQ,CAAC,KAAK,CAAC,CAAC;IAExC,0EAA0E;IAC1E,gFAAgF;IAChF,4EAA4E;IAC5E,4EAA4E;IAC5E,SAAS,CAAC,GAAG,EAAE;QACb,IAAI,CAAC,IAAI;YAAE,OAAO;QAClB,MAAM,UAAU,GAAG,GAAG,EAAE;YACtB,uEAAuE;YACvE,yDAAyD;YACzD,UAAU,CAAC,GAAG,EAAE;gBACd,IAAI,QAAQ,CAAC,aAAa,EAAE,OAAO,KAAK,QAAQ;oBAAE,OAAO,CAAC,KAAK,CAAC,CAAC;YACnE,CAAC,EAAE,CAAC,CAAC,CAAC;QACR,CAAC,CAAC;QACF,MAAM,CAAC,gBAAgB,CAAC,MAAM,EAAE,UAAU,CAAC,CAAC;QAC5C,OAAO,GAAG,EAAE,CAAC,MAAM,CAAC,mBAAmB,CAAC,MAAM,EAAE,UAAU,CAAC,CAAC;IAC9D,CAAC,EAAE,CAAC,IAAI,CAAC,CAAC,CAAC;IAEX,MAAM,YAAY,GAAG,CAAC,IAAY,EAAE,EAAE;QACpC,MAAM,OAAO,GAAG,IAAI,CAAC,IAAI,EAAE,CAAC;QAC5B,IAAI,CAAC,OAAO;YAAE,OAAO;QACrB,eAAe,CAAC;YACd,OAAO,EAAE,OAAO;YAChB,OAAO,EAAE,kCAAkC,SAAS,CAAC,IAAI,UAAU,SAAS,CAAC,EAAE,yBAAyB;YACxG,MAAM,EAAE,IAAI;YACZ,WAAW,EAAE,IAAI;SAClB,CAAC,CAAC;QACH,OAAO,CAAC,KAAK,CAAC,CAAC;IACjB,CAAC,CAAC;IAEF,OAAO,CACL,MAAC,OAAO,IAAC,IAAI,EAAE,IAAI,EAAE,YAAY,EAAE,OAAO,aACxC,KAAC,cAAc,IAAC,OAAO,kBACrB,iBACE,IAAI,EAAC,QAAQ,EACb,SAAS,EAAC,8IAA8I,EACxJ,KAAK,EAAC,MAAM,YAEZ,KAAC,UAAU,IAAC,SAAS,EAAC,SAAS,GAAG,GAC3B,GACM,EACjB,MAAC,cAAc,IAAC,KAAK,EAAC,KAAK,EAAC,UAAU,EAAE,CAAC,EAAE,SAAS,EAAC,eAAe,aAClE,YAAG,SAAS,EAAC,iDAAiD,+BAE1D,EACJ,KAAC,cAAc,IACb,SAAS,QACT,WAAW,EAAC,gCAAgC,EAC5C,UAAU,EAAE,mBAAmB,SAAS,CAAC,EAAE,EAAE,EAC7C,QAAQ,EAAE,YAAY,GACtB,IACa,IACT,CACX,CAAC;AACJ,CAAC;AAED,MAAM,UAAU,eAAe,CAAC,EAAE,WAAW,EAAwB;IACnE,MAAM,CAAC,MAAM,EAAE,SAAS,CAAC,GAAG,QAAQ,CAAC,KAAK,CAAC,CAAC;IAC5C,MAAM,CAAC,WAAW,EAAE,cAAc,CAAC,GAAG,QAAQ,CAAC,KAAK,CAAC,CAAC;IACtD,MAAM,SAAS,GAAG,MAAM,CAA2B,IAAI,CAAC,CAAC;IACzD,MAAM,OAAO,GAAG,MAAM,CAAmB,IAAI,CAAC,CAAC;IAC/C,MAAM,CAAC,UAAU,EAAE,aAAa,CAAC,GAAG,QAAQ,CAAC,KAAK,CAAC,CAAC;IACpD,MAAM,CAAC,WAAW,EAAE,cAAc,CAAC,GAAG,QAAQ,CAAC,EAAE,CAAC,CAAC;IACnD,MAAM,CAAC,UAAU,EAAE,aAAa,CAAC,GAAG,QAAQ,CAAC,CAAC,CAAC,CAAC;IAChD,MAAM,cAAc,GAAG,MAAM,CAA0B,IAAI,CAAC,CAAC;IAC7D,MAAM,WAAW,GAAG,cAAc,EAAE,CAAC;IACrC,0EAA0E;IAC1E,wEAAwE;IACxE,2EAA2E;IAC3E,6DAA6D;IAC7D,MAAM,gBAAgB,GAAG,MAAM,CAG5B;QACD,IAAI,EAAE,QAAQ;QACd,QAAQ,EAAE,KAAK;KAChB,CAAC,CAAC;IAEH,SAAS,CAAC,GAAG,EAAE;QACb,SAAS,CAAC,QAAQ,CAAC,eAAe,CAAC,SAAS,CAAC,QAAQ,CAAC,MAAM,CAAC,CAAC,CAAC;QAE/D,MAAM,QAAQ,GAAG,IAAI,gBAAgB,CAAC,GAAG,EAAE;YACzC,SAAS,CAAC,QAAQ,CAAC,eAAe,CAAC,SAAS,CAAC,QAAQ,CAAC,MAAM,CAAC,CAAC,CAAC;QACjE,CAAC,CAAC,CAAC;QACH,QAAQ,CAAC,OAAO,CAAC,QAAQ,CAAC,eAAe,EAAE;YACzC,UAAU,EAAE,IAAI;YAChB,eAAe,EAAE,CAAC,OAAO,CAAC;SAC3B,CAAC,CAAC;QACH,OAAO,GAAG,EAAE,CAAC,QAAQ,CAAC,UAAU,EAAE,CAAC;IACrC,CAAC,EAAE,EAAE,CAAC,CAAC;IAEP,MAAM,iBAAiB,GAAG,GAAG,EAAE;QAC7B,MAAM,GAAG,GAAG,SAAS,CAAC,OAAO,EAAE,aAAa,CAAC;QAC7C,IAAI,CAAC,GAAG;YAAE,OAAO;QACjB,GAAG,CAAC,WAAW,CACb;YACE,IAAI,EAAE,2BAA2B;YACjC,MAAM,EAAE,QAAQ,CAAC,eAAe,CAAC,SAAS,CAAC,QAAQ,CAAC,MAAM,CAAC;YAC3D,IAAI,EAAE,kBAAkB,EAAE;SAC3B,EACD,GAAG,CACJ,CAAC;IACJ,CAAC,CAAC;IAEF,SAAS,CAAC,GAAG,EAAE;QACb,IAAI,CAAC,WAAW;YAAE,OAAO;QACzB,iBAAiB,EAAE,CAAC;IACtB,CAAC,EAAE,CAAC,MAAM,EAAE,WAAW,CAAC,CAAC,CAAC;IAE1B,SAAS,CAAC,GAAG,EAAE;QACb,MAAM,aAAa,GAAG,KAAK,EAAE,KAAmB,EAAE,EAAE;YAClD,IAAI,KAAK,CAAC,MAAM,KAAK,SAAS,CAAC,OAAO,EAAE,aAAa;gBAAE,OAAO;YAC9D,MAAM,OAAO,GAAG,KAAK,CAAC,IAAI,CAAC;YAC3B,IAAI,CAAC,OAAO;gBAAE,OAAO;YAErB,IAAI,OAAO,CAAC,IAAI,KAAK,gCAAgC,EAAE,CAAC;gBACtD,qEAAqE;gBACrE,iEAAiE;gBACjE,sEAAsE;gBACtE,MAAM,OAAO,GAAG,OAAO,CAAC,OAAO,IAAI,EAAE,CAAC;gBACtC,MAAM,IAAI,GACR,OAAO,CAAC,IAAI,KAAK,OAAO;oBACxB,OAAO,CAAC,IAAI,KAAK,OAAO;oBACxB,OAAO,CAAC,IAAI,KAAK,QAAQ;oBACzB,OAAO,CAAC,IAAI,KAAK,QAAQ;oBACvB,CAAC,CAAC,OAAO,CAAC,IAAI;oBACd,CAAC,CAAC,QAAQ,CAAC;gBACf,gBAAgB,CAAC,OAAO,GAAG;oBACzB,IAAI;oBACJ,QAAQ,EAAE,CAAC,CAAC,OAAO,CAAC,QAAQ;iBAC7B,CAAC;gBACF,OAAO;YACT,CAAC;YAED,IACE,OAAO,CAAC,IAAI,KAAK,wCAAwC;gBACzD,OAAO,CAAC,IAAI,KAAK,0CAA0C,EAC3D,CAAC;gBACD,qEAAqE;gBACrE,uEAAuE;gBACvE,oDAAoD;gBACpD,IAAI,OAAO,CAAC,IAAI,KAAK,wCAAwC,EAAE,CAAC;oBAC9D,kEAAkE;oBAClE,8BAA8B;oBAC9B,WAAW,CAAC,iBAAiB,CAAC;wBAC5B,QAAQ,EAAE,CAAC,WAAW,EAAE,WAAW,CAAC;qBACrC,CAAC,CAAC;oBACH,aAAa,CAAC,CAAC,CAAC,EAAE,EAAE,CAAC,CAAC,GAAG,CAAC,CAAC,CAAC;gBAC9B,CAAC;gBACD,OAAO;YACT,CAAC;YAED,IAAI,OAAO,CAAC,IAAI,KAAK,gCAAgC,EAAE,CAAC;gBACtD,QAAQ,CAAC,aAAa,CACpB,IAAI,aAAa,CAAC,SAAS,EAAE;oBAC3B,GAAG,EAAE,OAAO,CAAC,GAAG;oBAChB,IAAI,EAAE,OAAO,CAAC,IAAI;oBAClB,OAAO,EAAE,CAAC,CAAC,OAAO,CAAC,OAAO;oBAC1B,OAAO,EAAE,CAAC,CAAC,OAAO,CAAC,OAAO;oBAC1B,QAAQ,EAAE,CAAC,CAAC,OAAO,CAAC,QAAQ;oBAC5B,MAAM,EAAE,CAAC,CAAC,OAAO,CAAC,MAAM;oBACxB,OAAO,EAAE,IAAI;oBACb,UAAU,EAAE,IAAI;iBACjB,CAAC,CACH,CAAC;gBACF,OAAO;YACT,CAAC;YAED,IAAI,OAAO,CAAC,IAAI,KAAK,kCAAkC,EAAE,CAAC;gBACxD,MAAM,CAAC,GAAG,OAAO,CAAC,OAAO,CAAC;gBAC1B,IAAI,CAAC,CAAC;oBAAE,OAAO;gBACf,MAAM,MAAM,GAAa,OAAO,CAAC,MAAM,IAAI,EAAE,CAAC;gBAC9C,MAAM,YAAY,GAChB,OAAO,CAAC,YAAY,IAAI,EAAE,CAAC;gBAC7B,MAAM,WAAW,GACf,OAAO,CAAC,WAAW,IAAI,EAAE,CAAC;gBAC5B,MAAM,WAAW,GAMZ,OAAO,CAAC,WAAW,IAAI,EAAE,CAAC;gBAE/B,MAAM,aAAa,GAAG,YAAY;qBAC/B,GAAG,CAAC,CAAC,CAAC,EAAE,EAAE,CAAC,CAAC,CAAC,CAAC,KAAK,CAAC,CAAC,CAAC,GAAG,CAAC,CAAC,OAAO,KAAK,CAAC,CAAC,KAAK,EAAE,CAAC,CAAC,CAAC,CAAC,CAAC,OAAO,CAAC,CAAC;qBAC9D,IAAI,CAAC,MAAM,CAAC,CAAC;gBAEhB,MAAM,YAAY,GAAG;oBACnB,kCAAkC,CAAC,CAAC,IAAI,UAAU,CAAC,CAAC,EAAE,kDAAkD;oBACxG,0BAA0B,aAAa,EAAE;iBAC1C,CAAC;gBAEF,IAAI,WAAW,CAAC,MAAM,GAAG,CAAC,EAAE,CAAC;oBAC3B,MAAM,UAAU,GAAG,WAAW;yBAC3B,GAAG,CAAC,CAAC,CAAC,EAAE,EAAE,CAAC,IAAI,CAAC,CAAC,KAAK,KAAK,CAAC,CAAC,OAAO,EAAE,CAAC;yBACvC,IAAI,CAAC,IAAI,CAAC,CAAC;oBACd,YAAY,CAAC,IAAI,CAAC,6BAA6B,UAAU,EAAE,CAAC,CAAC;gBAC/D,CAAC;gBAED,IAAI,WAAW,CAAC,MAAM,GAAG,CAAC,EAAE,CAAC;oBAC3B,MAAM,MAAM,GAAG,WAAW;yBACvB,GAAG,CACF,CAAC,CAAC,EAAE,EAAE,CACJ,GAAG,CAAC,CAAC,MAAM,IAAI,CAAC,CAAC,IAAI,MAAM,CAAC,CAAC,EAAE,CAAC,CAAC,CAAC,CAAC,CAAC,MAAM,CAAC,CAAC,CAAC,UAAU,GAAG,CAAC,CAAC,CAAC,KAAK,IAAI,CAAC,CAAC,MAAM,CAAC,EAAE,CACpF;yBACA,IAAI,CAAC,IAAI,CAAC,CAAC;oBACd,YAAY,CAAC,IAAI,CAAC,+BAA+B,MAAM,EAAE,CAAC,CAAC;gBAC7D,CAAC;gBAED,eAAe,CAAC;oBACd,OAAO,EAAE,0CAA0C,MAAM,CAAC,IAAI,CAAC,IAAI,CAAC,EAAE;oBACtE,OAAO,EAAE,YAAY,CAAC,IAAI,CAAC,IAAI,CAAC;oBAChC,MAAM,EAAE,IAAI;oBACZ,WAAW,EAAE,IAAI;iBAClB,CAAC,CAAC;gBACH,OAAO;YACT,CAAC;YAED,IAAI,OAAO,CAAC,IAAI,KAAK,gCAAgC;gBAAE,OAAO;YAE9D,MAAM,SAAS,GAAG,MAAM,CAAC,OAAO,CAAC,SAAS,IAAI,EAAE,CAAC,CAAC;YAClD,MAAM,IAAI,GAAG,MAAM,CAAC,OAAO,CAAC,IAAI,IAAI,EAAE,CAAC,CAAC;YACxC,MAAM,OAAO,GAAG,CAAC,OAAgC,EAAE,EAAE;gBACnD,SAAS,CAAC,OAAO,EAAE,aAAa,EAAE,WAAW,CAC3C;oBACE,IAAI,EAAE,iCAAiC;oBACvC,SAAS;oBACT,GAAG,OAAO;iBACX,EACD,GAAG,CACJ,CAAC;YACJ,CAAC,CAAC;YAEF,IAAI,CAAC,SAAS,IAAI,CAAC,sBAAsB,CAAC,IAAI,EAAE,WAAW,CAAC,EAAE,CAAC;gBAC7D,OAAO,CAAC,EAAE,KAAK,EAAE,uCAAuC,EAAE,CAAC,CAAC;gBAC5D,OAAO;YACT,CAAC;YAED,IAAI,CAAC;gBACH,MAAM,OAAO,GAAG,+BAA+B,CAAC,OAAO,CAAC,OAAO,CAAC,CAAC;gBACjE,uEAAuE;gBACvE,+DAA+D;gBAC/D,8CAA8C;gBAC9C,MAAM,MAAM,GAAG,iBAAiB,CAC9B,IAAI,EACJ,OAAO,CAAC,MAAM,IAAI,KAAK,EACvB,gBAAgB,CAAC,OAAO,CACzB,CAAC;gBACF,IAAI,CAAC,MAAM,CAAC,EAAE,EAAE,CAAC;oBACf,OAAO,CAAC;wBACN,QAAQ,EAAE;4BACR,EAAE,EAAE,KAAK;4BACT,MAAM,EAAE,GAAG;4BACX,UAAU,EAAE,WAAW;4BACvB,IAAI,EAAE,EAAE,KAAK,EAAE,MAAM,CAAC,KAAK,EAAE;yBAC9B;qBACF,CAAC,CAAC;oBACH,OAAO;gBACT,CAAC;gBACD,wDAAwD;gBACxD,0EAA0E;gBAC1E,mEAAmE;gBACnE,gEAAgE;gBAChE,4DAA4D;gBAC5D,MAAM,YAAY,GAAG,IAAI,OAAO,CAAC,OAAO,CAAC,OAAO,IAAI,SAAS,CAAC,CAAC;gBAC/D,YAAY,CAAC,GAAG,CAAC,iCAAiC,EAAE,GAAG,CAAC,CAAC;gBACzD,YAAY,CAAC,GAAG,CAAC,6BAA6B,EAAE,WAAW,CAAC,CAAC;gBAC7D,MAAM,GAAG,GAAG,MAAM,KAAK,CAAC,eAAe,CAAC,IAAI,CAAC,EAAE;oBAC7C,GAAG,OAAO;oBACV,OAAO,EAAE,YAAY;oBACrB,WAAW,EAAE,aAAa;iBAC3B,CAAC,CAAC;gBACH,MAAM,IAAI,GAAG,MAAM,GAAG,CAAC,IAAI,EAAE,CAAC;gBAC9B,IAAI,IAAI,GAAY,IAAI,CAAC;gBACzB,IAAI,IAAI,EAAE,CAAC;oBACT,IAAI,CAAC;wBACH,IAAI,GAAG,IAAI,CAAC,KAAK,CAAC,IAAI,CAAC,CAAC;oBAC1B,CAAC;oBAAC,MAAM,CAAC;wBACP,IAAI,GAAG,IAAI,CAAC;oBACd,CAAC;gBACH,CAAC;gBACD,OAAO,CAAC;oBACN,QAAQ,EAAE;wBACR,EAAE,EAAE,GAAG,CAAC,EAAE;wBACV,MAAM,EAAE,GAAG,CAAC,MAAM;wBAClB,UAAU,EAAE,GAAG,CAAC,UAAU;wBAC1B,IAAI;qBACL;iBACF,CAAC,CAAC;YACL,CAAC;YAAC,OAAO,GAAQ,EAAE,CAAC;gBAClB,OAAO,CAAC,EAAE,KAAK,EAAE,GAAG,EAAE,OAAO,IAAI,+BAA+B,EAAE,CAAC,CAAC;YACtE,CAAC;QACH,CAAC,CAAC;QAEF,MAAM,CAAC,gBAAgB,CAAC,SAAS,EAAE,aAAa,CAAC,CAAC;QAClD,OAAO,GAAG,EAAE,CAAC,MAAM,CAAC,mBAAmB,CAAC,SAAS,EAAE,aAAa,CAAC,CAAC;IACpE,CAAC,EAAE,CAAC,WAAW,EAAE,WAAW,CAAC,CAAC,CAAC;IAE/B,MAAM,EAAE,IAAI,EAAE,SAAS,EAAE,SAAS,EAAE,GAAG,QAAQ,CAAY;QACzD,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;KACF,CAAC,CAAC;IAEH,OAAO,CAAC,OAAO,GAAG,SAAS,IAAI,IAAI,CAAC;IAEpC,MAAM,SAAS,GAAG,OAAO,CACvB,GAAG,EAAE,CACH,eAAe,CACb,6BAA6B,WAAW,gBAAgB,QAAQ,CAAC,eAAe,CAAC,SAAS,CAAC,QAAQ,CAAC,MAAM,CAAC,MAAM,kBAAkB,CAAC,SAAS,EAAE,SAAS,IAAI,EAAE,CAAC,MAAM,UAAU,EAAE,CAClL,EACH,CAAC,WAAW,EAAE,SAAS,EAAE,SAAS,EAAE,UAAU,CAAC,CAChD,CAAC;IAEF,SAAS,CAAC,GAAG,EAAE;QACb,cAAc,CAAC,KAAK,CAAC,CAAC;QACtB,mEAAmE;QACnE,uEAAuE;QACvE,gBAAgB,CAAC,OAAO,GAAG,EAAE,IAAI,EAAE,QAAQ,EAAE,QAAQ,EAAE,KAAK,EAAE,CAAC;IACjE,CAAC,EAAE,CAAC,WAAW,EAAE,SAAS,EAAE,SAAS,EAAE,UAAU,CAAC,CAAC,CAAC;IAEpD,MAAM,WAAW,GAAG,WAAW,CAAC,GAAG,EAAE;QACnC,IAAI,CAAC,SAAS;YAAE,OAAO;QACvB,cAAc,CAAC,SAAS,CAAC,IAAI,CAAC,CAAC;QAC/B,aAAa,CAAC,IAAI,CAAC,CAAC;QACpB,qBAAqB,CAAC,GAAG,EAAE,CAAC,cAAc,CAAC,OAAO,EAAE,MAAM,EAAE,CAAC,CAAC;IAChE,CAAC,EAAE,CAAC,SAAS,CAAC,CAAC,CAAC;IAEhB,MAAM,YAAY,GAAG,WAAW,CAAC,KAAK,IAAI,EAAE;QAC1C,MAAM,OAAO,GAAG,WAAW,CAAC,IAAI,EAAE,CAAC;QACnC,IAAI,CAAC,OAAO,IAAI,CAAC,SAAS,IAAI,OAAO,KAAK,SAAS,CAAC,IAAI,EAAE,CAAC;YACzD,aAAa,CAAC,KAAK,CAAC,CAAC;YACrB,OAAO;QACT,CAAC;QACD,WAAW,CAAC,YAAY,CAAY,CAAC,WAAW,EAAE,WAAW,CAAC,EAAE,CAAC,GAAG,EAAE,EAAE,CACtE,GAAG,CAAC,CAAC,CAAC,EAAE,GAAG,GAAG,EAAE,IAAI,EAAE,OAAO,EAAE,CAAC,CAAC,CAAC,GAAG,CACtC,CAAC;QACF,WAAW,CAAC,YAAY,CAAc,CAAC,YAAY,CAAC,EAAE,CAAC,GAAG,EAAE,EAAE,CAC5D,CAAC,GAAG,IAAI,EAAE,CAAC,CAAC,GAAG,CAAC,CAAC,CAAC,EAAE,EAAE,CACpB,CAAC,CAAC,EAAE,KAAK,WAAW,CAAC,CAAC,CAAC,EAAE,GAAG,CAAC,EAAE,IAAI,EAAE,OAAO,EAAE,CAAC,CAAC,CAAC,CAAC,CACnD,CACF,CAAC;QACF,aAAa,CAAC,KAAK,CAAC,CAAC;QACrB,IAAI,CAAC;YACH,MAAM,KAAK,CAAC,eAAe,CAAC,6BAA6B,WAAW,EAAE,CAAC,EAAE;gBACvE,MAAM,EAAE,KAAK;gBACb,OAAO,EAAE,EAAE,cAAc,EAAE,kBAAkB,EAAE;gBAC/C,IAAI,EAAE,IAAI,CAAC,SAAS,CAAC,EAAE,IAAI,EAAE,OAAO,EAAE,CAAC;aACxC,CAAC,CAAC;YACH,WAAW,CAAC,iBAAiB,CAAC,EAAE,QAAQ,EAAE,CAAC,WAAW,EAAE,WAAW,CAAC,EAAE,CAAC,CAAC;YACxE,WAAW,CAAC,iBAAiB,CAAC,EAAE,QAAQ,EAAE,CAAC,YAAY,CAAC,EAAE,CAAC,CAAC;QAC9D,CAAC;QAAC,MAAM,CAAC;YACP,WAAW,CAAC,iBAAiB,CAAC,EAAE,QAAQ,EAAE,CAAC,WAAW,EAAE,WAAW,CAAC,EAAE,CAAC,CAAC;YACxE,WAAW,CAAC,iBAAiB,CAAC,EAAE,QAAQ,EAAE,CAAC,YAAY,CAAC,EAAE,CAAC,CAAC;QAC9D,CAAC;IACH,CAAC,EAAE,CAAC,WAAW,EAAE,SAAS,EAAE,WAAW,EAAE,WAAW,CAAC,CAAC,CAAC;IAEvD,IAAI,SAAS,EAAE,CAAC;QACd,OAAO,CACL,eAAK,SAAS,EAAC,sBAAsB,aACnC,eAAK,SAAS,EAAC,qDAAqD,aAClE,cAAK,SAAS,EAAC,4CAA4C,GAAG,EAC9D,cAAK,SAAS,EAAC,2CAA2C,GAAG,IACzD,EACN,cAAK,SAAS,EAAC,kCAAkC,GAAG,IAChD,CACP,CAAC;IACJ,CAAC;IAED,IAAI,CAAC,SAAS,EAAE,CAAC;QACf,OAAO,CACL,cAAK,SAAS,EAAC,uEAAuE,oCAEhF,CACP,CAAC;IACJ,CAAC;IAED,OAAO,CACL,eAAK,SAAS,EAAC,6BAA6B,aAC1C,eAAK,SAAS,EAAC,+DAA+D,aAC5E,cAAK,SAAS,EAAC,oCAAoC,YAChD,UAAU,CAAC,CAAC,CAAC,CACZ,gBACE,GAAG,EAAE,cAAc,EACnB,KAAK,EAAE,WAAW,EAClB,QAAQ,EAAE,CAAC,CAAC,EAAE,EAAE,CAAC,cAAc,CAAC,CAAC,CAAC,MAAM,CAAC,KAAK,CAAC,EAC/C,MAAM,EAAE,YAAY,EACpB,SAAS,EAAE,CAAC,CAAC,EAAE,EAAE;gCACf,IAAI,CAAC,CAAC,GAAG,KAAK,OAAO;oCAAE,YAAY,EAAE,CAAC;gCACtC,IAAI,CAAC,CAAC,GAAG,KAAK,QAAQ;oCAAE,aAAa,CAAC,KAAK,CAAC,CAAC;4BAC/C,CAAC,EACD,SAAS,EAAC,mFAAmF,GAC7F,CACH,CAAC,CAAC,CAAC,CACF,8BACE,eAAM,SAAS,EAAC,qBAAqB,YAAE,SAAS,CAAC,IAAI,GAAQ,EAC7D,iBACE,IAAI,EAAC,QAAQ,EACb,OAAO,EAAE,WAAW,EACpB,SAAS,EAAC,oHAAoH,EAC9H,KAAK,EAAC,QAAQ,YAEd,KAAC,UAAU,IAAC,SAAS,EAAC,SAAS,GAAG,GAC3B,IACR,CACJ,GACG,EACN,eAAK,SAAS,EAAC,yBAAyB,aACtC,iBACE,IAAI,EAAC,QAAQ,EACb,OAAO,EAAE,GAAG,EAAE,CAAC,aAAa,CAAC,CAAC,CAAC,EAAE,EAAE,CAAC,CAAC,GAAG,CAAC,CAAC,EAC1C,SAAS,EAAC,8IAA8I,EACxJ,KAAK,EAAC,SAAS,YAEf,KAAC,WAAW,IAAC,SAAS,EAAC,SAAS,GAAG,GAC5B,EACT,KAAC,eAAe,IAAC,SAAS,EAAE,SAAS,GAAI,EACzC,KAAC,WAAW,IACV,YAAY,EAAC,WAAW,EACxB,UAAU,EAAE,WAAW,EACvB,aAAa,EAAE,SAAS,CAAC,IAAI,GAC7B,EACF,KAAC,YAAY,IAAC,WAAW,EAAE,WAAW,EAAE,QAAQ,EAAE,SAAS,CAAC,IAAI,GAAI,EACpE,KAAC,iBAAiB,KAAG,EACrB,KAAC,iBAAiB,IAAC,SAAS,EAAC,oCAAoC,GAAG,IAChE,IACF,EACN,eAAK,SAAS,EAAC,yBAAyB,aACrC,CAAC,WAAW,IAAI,CACf,cAAK,SAAS,EAAC,sEAAsE,YACnF,KAAC,WAAW,IACV,SAAS,EAAC,2CAA2C,EACrD,IAAI,EAAC,QAAQ,gBACF,SAAS,GACpB,GACE,CACP,EACD,iBACE,GAAG,EAAE,SAAS,EAEd,GAAG,EAAE,SAAS,EACd,SAAS,EAAC,wBAAwB,EAClC,OAAO,EAAC,2BAA2B,EACnC,KAAK,EAAE,SAAS,CAAC,IAAI,EACrB,MAAM,EAAE,GAAG,EAAE;4BACX,iBAAiB,EAAE,CAAC;4BACpB,UAAU,CAAC,GAAG,EAAE,CAAC,cAAc,CAAC,IAAI,CAAC,EAAE,GAAG,CAAC,CAAC;wBAC9C,CAAC,IARI,GAAG,SAAS,CAAC,SAAS,IAAI,UAAU,EAAE,CAS3C,IACE,IACF,CACP,CAAC;AACJ,CAAC;AAQD,SAAS,YAAY,CAAC,EACpB,WAAW,EACX,QAAQ,GAIT;IACC,MAAM,CAAC,IAAI,EAAE,OAAO,CAAC,GAAG,QAAQ,CAAC,KAAK,CAAC,CAAC;IACxC,MAAM,CAAC,gBAAgB,EAAE,mBAAmB,CAAC,GAAG,QAAQ,CAAC,KAAK,CAAC,CAAC;IAChE,MAAM,WAAW,GAAG,cAAc,EAAE,CAAC;IACrC,MAAM,QAAQ,GAAG,WAAW,EAAE,CAAC;IAE/B,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,IAAI;KACd,CAAC,CAAC;IAEH,MAAM,SAAS,GAAG,GAAG,EAAE;QACrB,OAAO,CAAC,KAAK,CAAC,CAAC;QACf,mBAAmB,CAAC,KAAK,CAAC,CAAC;IAC7B,CAAC,CAAC;IAEF,MAAM,cAAc,GAAG,KAAK,EAAE,MAAc,EAAE,EAAE;QAC9C,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,MAAM,eAAe,GAAG,KAAK,IAAI,EAAE;QACjC,SAAS,EAAE,CAAC;QACZ,IAAI,CAAC;YACH,MAAM,KAAK,CAAC,eAAe,CAAC,6BAA6B,WAAW,EAAE,CAAC,EAAE;gBACvE,MAAM,EAAE,QAAQ;aACjB,CAAC,CAAC;QACL,CAAC;gBAAS,CAAC;YACT,WAAW,CAAC,iBAAiB,CAAC,EAAE,QAAQ,EAAE,CAAC,WAAW,EAAE,WAAW,CAAC,EAAE,CAAC,CAAC;YACxE,WAAW,CAAC,iBAAiB,CAAC,EAAE,QAAQ,EAAE,CAAC,YAAY,CAAC,EAAE,CAAC,CAAC;YAC5D,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;IACH,CAAC,CAAC;IAEF,OAAO,CACL,MAAC,OAAO,IACN,IAAI,EAAE,IAAI,EACV,YAAY,EAAE,CAAC,CAAC,EAAE,EAAE;YAClB,OAAO,CAAC,CAAC,CAAC,CAAC;YACX,IAAI,CAAC,CAAC;gBAAE,mBAAmB,CAAC,KAAK,CAAC,CAAC;QACrC,CAAC,aAED,KAAC,cAAc,IAAC,OAAO,kBACrB,iBACE,IAAI,EAAC,QAAQ,EACb,SAAS,EAAC,8IAA8I,EACxJ,KAAK,EAAC,cAAc,gBACT,cAAc,YAEzB,KAAC,QAAQ,IAAC,SAAS,EAAC,SAAS,GAAG,GACzB,GACM,EACjB,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,kBACzC,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,iBACE,IAAI,EAAC,QAAQ,EACb,OAAO,EAAE,GAAG,EAAE,CAAC,cAAc,CAAC,CAAC,CAAC,MAAM,CAAC,EACvC,SAAS,EAAC,2FAA2F,EACrG,KAAK,EAAC,uCAAuC,gBAClC,8BAA8B,YAEzC,KAAC,KAAK,IAAC,SAAS,EAAC,aAAa,GAAG,GAC1B,KAdJ,CAAC,CAAC,EAAE,CAeL,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,oDAA8B,IACvB,GACL,IACL,CACJ,CAAC,CAAC,CAAC,CACF,eAAK,SAAS,EAAC,yBAAyB,aACtC,aAAG,SAAS,EAAC,aAAa,wBACjB,eAAM,SAAS,EAAC,aAAa,YAAE,QAAQ,GAAQ,+EAEpD,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,eAAe,EACxB,SAAS,EAAC,oHAAoH,uBAGvH,IACL,IACF,CACP,GACc,IACT,CACX,CAAC;AACJ,CAAC","sourcesContent":["import { agentNativePath } from \"../api-path.js\";\nimport { useState, useEffect, useRef, useCallback, useMemo } from \"react\";\nimport { useQuery, useQueryClient } from \"@tanstack/react-query\";\nimport { useNavigate } from \"react-router\";\nimport {\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\";\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}\n\nexport interface ExtensionViewerProps {\n extensionId: string;\n}\n\nfunction EditToolPopover({ extension }: { extension: Extension }) {\n const [open, setOpen] = useState(false);\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\") setOpen(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: trimmed,\n context: `The user is viewing extension \"${extension.name}\" (id: ${extension.id}) and wants to edit it.`,\n submit: true,\n openSidebar: true,\n });\n setOpen(false);\n };\n\n return (\n <Popover open={open} onOpenChange={setOpen}>\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 title=\"Edit\"\n >\n <IconPencil className=\"h-4 w-4\" />\n </button>\n </PopoverTrigger>\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 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 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 sendToAgentChat({\n message: `Fix runtime errors in this extension:\\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 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>({\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 });\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 <div className=\"flex h-full w-full flex-col\">\n <div className=\"flex h-12 items-center justify-between border-b px-3 shrink-0\">\n <div className=\"group/name flex items-center gap-1\">\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=\"text-sm font-medium bg-transparent border-b border-primary outline-none py-0 px-0\"\n />\n ) : (\n <>\n <span className=\"text-sm font-medium\">{extension.name}</span>\n <button\n type=\"button\"\n onClick={startRename}\n className=\"cursor-pointer rounded p-0.5 text-muted-foreground/40 opacity-0 group-hover/name:opacity-100 hover:text-foreground\"\n title=\"Rename\"\n >\n <IconPencil className=\"h-3 w-3\" />\n </button>\n </>\n )}\n </div>\n <div className=\"flex items-center gap-1\">\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 title=\"Refresh\"\n >\n <IconRefresh className=\"h-4 w-4\" />\n </button>\n <EditToolPopover extension={extension} />\n <ShareButton\n resourceType=\"extension\"\n resourceId={extensionId}\n resourceTitle={extension.name}\n />\n <ToolMoreMenu extensionId={extensionId} toolName={extension.name} />\n <NotificationsBell />\n <AgentToggleButton className=\"h-8 w-8 rounded-md hover:bg-accent\" />\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 onLoad={() => {\n sendThemeToIframe();\n setTimeout(() => setIframeReady(true), 150);\n }}\n />\n </div>\n </div>\n );\n}\n\ninterface SlotDeclaration {\n id: string;\n extensionId: string;\n slotId: string;\n}\n\nfunction ToolMoreMenu({\n extensionId,\n toolName,\n}: {\n extensionId: string;\n toolName: string;\n}) {\n const [open, setOpen] = useState(false);\n const [confirmingDelete, setConfirmingDelete] = useState(false);\n const queryClient = useQueryClient();\n const navigate = useNavigate();\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 setOpen(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 fetch(agentNativePath(`/_agent-native/extensions/${extensionId}`), {\n method: \"DELETE\",\n });\n } finally {\n queryClient.invalidateQueries({ queryKey: [\"extension\", extensionId] });\n queryClient.invalidateQueries({ queryKey: [\"extensions\"] });\n slots.forEach((s) =>\n queryClient.invalidateQueries({\n queryKey: [\"slot-installs\", s.slotId],\n }),\n );\n navigate(\"/extensions\");\n }\n };\n\n return (\n <Popover\n open={open}\n onOpenChange={(o) => {\n setOpen(o);\n if (!o) setConfirmingDelete(false);\n }}\n >\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 title=\"More options\"\n aria-label=\"More options\"\n >\n <IconDots className=\"h-4 w-4\" />\n </button>\n </PopoverTrigger>\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 <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 title=\"Remove from this widget area (for me)\"\n aria-label=\"Remove from this widget area\"\n >\n <IconX className=\"h-3.5 w-3.5\" />\n </button>\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>Delete extension…</span>\n </button>\n </div>\n </>\n ) : (\n <div className=\"flex flex-col gap-2 p-3\">\n <p className=\"text-[12px]\">\n Delete <span className=\"font-medium\">{toolName}</span>? This\n 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 Delete\n </button>\n </div>\n </div>\n )}\n </PopoverContent>\n </Popover>\n );\n}\n"]}
@@ -0,0 +1,2 @@
1
+ export declare function ExtensionViewerPage(): import("react/jsx-runtime").JSX.Element;
2
+ //# sourceMappingURL=ExtensionViewerPage.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"ExtensionViewerPage.d.ts","sourceRoot":"","sources":["../../../src/client/extensions/ExtensionViewerPage.tsx"],"names":[],"mappings":"AAMA,wBAAgB,mBAAmB,4CAiBlC"}
@@ -2,23 +2,23 @@ import { jsx as _jsx } from "react/jsx-runtime";
2
2
  import { agentNativePath } from "../api-path.js";
3
3
  import { useEffect } from "react";
4
4
  import { useParams } from "react-router";
5
- import { ToolViewer } from "./ToolViewer.js";
6
- import { ToolsListPage } from "./ToolsListPage.js";
7
- export function ToolViewerPage() {
5
+ import { ExtensionViewer } from "./ExtensionViewer.js";
6
+ import { ExtensionsListPage } from "./ExtensionsListPage.js";
7
+ export function ExtensionViewerPage() {
8
8
  const { id } = useParams();
9
9
  useEffect(() => {
10
10
  fetch(agentNativePath("/_agent-native/application-state/navigation"), {
11
11
  method: "PUT",
12
12
  headers: { "Content-Type": "application/json" },
13
- body: JSON.stringify({ value: { view: "tools", toolId: id } }),
13
+ body: JSON.stringify({ value: { view: "extensions", extensionId: id } }),
14
14
  }).catch(() => { });
15
15
  }, [id]);
16
16
  if (id === "new") {
17
- // No manual editor — tools are created via the agent
18
- return _jsx(ToolsListPage, {});
17
+ // No manual editor — extensions are created via the agent
18
+ return _jsx(ExtensionsListPage, {});
19
19
  }
20
20
  if (!id)
21
21
  return null;
22
- return _jsx(ToolViewer, { toolId: id });
22
+ return _jsx(ExtensionViewer, { extensionId: id });
23
23
  }
24
- //# sourceMappingURL=ToolViewerPage.js.map
24
+ //# sourceMappingURL=ExtensionViewerPage.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"ExtensionViewerPage.js","sourceRoot":"","sources":["../../../src/client/extensions/ExtensionViewerPage.tsx"],"names":[],"mappings":";AAAA,OAAO,EAAE,eAAe,EAAE,MAAM,gBAAgB,CAAC;AACjD,OAAO,EAAE,SAAS,EAAE,MAAM,OAAO,CAAC;AAClC,OAAO,EAAE,SAAS,EAAE,MAAM,cAAc,CAAC;AACzC,OAAO,EAAE,eAAe,EAAE,MAAM,sBAAsB,CAAC;AACvD,OAAO,EAAE,kBAAkB,EAAE,MAAM,yBAAyB,CAAC;AAE7D,MAAM,UAAU,mBAAmB;IACjC,MAAM,EAAE,EAAE,EAAE,GAAG,SAAS,EAAkB,CAAC;IAE3C,SAAS,CAAC,GAAG,EAAE;QACb,KAAK,CAAC,eAAe,CAAC,6CAA6C,CAAC,EAAE;YACpE,MAAM,EAAE,KAAK;YACb,OAAO,EAAE,EAAE,cAAc,EAAE,kBAAkB,EAAE;YAC/C,IAAI,EAAE,IAAI,CAAC,SAAS,CAAC,EAAE,KAAK,EAAE,EAAE,IAAI,EAAE,YAAY,EAAE,WAAW,EAAE,EAAE,EAAE,EAAE,CAAC;SACzE,CAAC,CAAC,KAAK,CAAC,GAAG,EAAE,GAAE,CAAC,CAAC,CAAC;IACrB,CAAC,EAAE,CAAC,EAAE,CAAC,CAAC,CAAC;IAET,IAAI,EAAE,KAAK,KAAK,EAAE,CAAC;QACjB,0DAA0D;QAC1D,OAAO,KAAC,kBAAkB,KAAG,CAAC;IAChC,CAAC;IACD,IAAI,CAAC,EAAE;QAAE,OAAO,IAAI,CAAC;IACrB,OAAO,KAAC,eAAe,IAAC,WAAW,EAAE,EAAE,GAAI,CAAC;AAC9C,CAAC","sourcesContent":["import { agentNativePath } from \"../api-path.js\";\nimport { useEffect } from \"react\";\nimport { useParams } from \"react-router\";\nimport { ExtensionViewer } from \"./ExtensionViewer.js\";\nimport { ExtensionsListPage } from \"./ExtensionsListPage.js\";\n\nexport function ExtensionViewerPage() {\n const { id } = useParams<{ id: string }>();\n\n useEffect(() => {\n fetch(agentNativePath(\"/_agent-native/application-state/navigation\"), {\n method: \"PUT\",\n headers: { \"Content-Type\": \"application/json\" },\n body: JSON.stringify({ value: { view: \"extensions\", extensionId: id } }),\n }).catch(() => {});\n }, [id]);\n\n if (id === \"new\") {\n // No manual editor — extensions are created via the agent\n return <ExtensionsListPage />;\n }\n if (!id) return null;\n return <ExtensionViewer extensionId={id} />;\n}\n"]}
@@ -0,0 +1,2 @@
1
+ export declare function ExtensionsListPage(): import("react/jsx-runtime").JSX.Element;
2
+ //# sourceMappingURL=ExtensionsListPage.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"ExtensionsListPage.d.ts","sourceRoot":"","sources":["../../../src/client/extensions/ExtensionsListPage.tsx"],"names":[],"mappings":"AAqDA,wBAAgB,kBAAkB,4CAsIjC"}
@@ -0,0 +1,67 @@
1
+ import { jsx as _jsx, jsxs as _jsxs } from "react/jsx-runtime";
2
+ import { agentNativePath } from "../api-path.js";
3
+ import { useState, useEffect } from "react";
4
+ import { useQuery } from "@tanstack/react-query";
5
+ import { Link } from "react-router";
6
+ import { IconPlus, IconTool } from "@tabler/icons-react";
7
+ import { cn } from "../utils.js";
8
+ import { AgentToggleButton } from "../AgentPanel.js";
9
+ import { NotificationsBell } from "../notifications/NotificationsBell.js";
10
+ import { sendToAgentChat } from "../agent-chat.js";
11
+ import { PromptComposer } from "../composer/PromptComposer.js";
12
+ import { Popover, PopoverContent, PopoverTrigger, } from "../components/ui/popover.js";
13
+ import { TOOLS_ORDER_CHANGE_EVENT, applyToolsOrder, getToolsOrder, } from "./extension-order.js";
14
+ function submitCreateTool(prompt) {
15
+ const trimmed = prompt.trim();
16
+ if (!trimmed)
17
+ return;
18
+ sendToAgentChat({
19
+ message: `Create a extension: ${trimmed}`,
20
+ submit: true,
21
+ openSidebar: true,
22
+ newTab: true,
23
+ });
24
+ }
25
+ function CreateToolInput({ className }) {
26
+ return (_jsxs("div", { className: cn("flex flex-col gap-2", className), children: [_jsx("p", { className: "text-sm font-semibold text-foreground", children: "New extension" }), _jsx(PromptComposer, { autoFocus: true, placeholder: "Describe what you'd like to build... e.g. a todo list, API dashboard, calculator", draftScope: "extensions:create", onSubmit: (text) => submitCreateTool(text) })] }));
27
+ }
28
+ export function ExtensionsListPage() {
29
+ const [showCreate, setShowCreate] = useState(false);
30
+ const [toolOrderState, setToolOrderState] = useState(() => typeof window !== "undefined" ? getToolsOrder() : []);
31
+ useEffect(() => {
32
+ fetch(agentNativePath("/_agent-native/application-state/navigation"), {
33
+ method: "PUT",
34
+ headers: { "Content-Type": "application/json" },
35
+ body: JSON.stringify({ value: { view: "extensions" } }),
36
+ }).catch(() => { });
37
+ }, []);
38
+ useEffect(() => {
39
+ if (typeof window === "undefined")
40
+ return;
41
+ const syncOrder = () => setToolOrderState(getToolsOrder());
42
+ window.addEventListener(TOOLS_ORDER_CHANGE_EVENT, syncOrder);
43
+ window.addEventListener("storage", syncOrder);
44
+ return () => {
45
+ window.removeEventListener(TOOLS_ORDER_CHANGE_EVENT, syncOrder);
46
+ window.removeEventListener("storage", syncOrder);
47
+ };
48
+ }, []);
49
+ const { data: extensions, isLoading } = useQuery({
50
+ queryKey: ["extensions"],
51
+ queryFn: async () => {
52
+ const res = await fetch(agentNativePath("/_agent-native/extensions"));
53
+ if (!res.ok)
54
+ return [];
55
+ return res.json();
56
+ },
57
+ });
58
+ const toolList = toolOrderState.length > 0
59
+ ? applyToolsOrder(extensions ?? [], toolOrderState)
60
+ : (extensions ?? []);
61
+ const handleCreate = (text) => {
62
+ submitCreateTool(text);
63
+ setShowCreate(false);
64
+ };
65
+ 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: [_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, { className: "h-8 w-8 rounded-md hover:bg-accent" })] })] }), _jsx("div", { className: "flex-1 overflow-auto p-6", children: isLoading ? (_jsx("div", { className: "grid grid-cols-1 gap-4 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 ? (_jsxs("div", { className: "flex flex-col items-center justify-center gap-4 py-16 text-center", children: [_jsx(IconTool, { className: "h-10 w-10 text-muted-foreground/40" }), _jsxs("div", { children: [_jsx("p", { className: "text-sm font-medium", children: "No extensions yet" }), _jsx("p", { className: "text-xs text-muted-foreground mt-1", children: "Describe what you'd like to build" })] }), _jsx(CreateToolInput, { className: "w-full max-w-sm" })] })) : (_jsx("div", { className: "grid grid-cols-1 gap-4 sm:grid-cols-2 lg:grid-cols-3", children: toolList.map((extension) => (_jsxs(Link, { to: `/extensions/${extension.id}`, className: cn("group cursor-pointer rounded-lg border border-border bg-card p-5", "hover:border-primary/30 hover:shadow-sm"), 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 }))] }, extension.id))) })) })] }));
66
+ }
67
+ //# sourceMappingURL=ExtensionsListPage.js.map