@agent-native/core 0.110.2 → 0.111.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 (380) hide show
  1. package/corpus/README.md +1 -1
  2. package/corpus/core/CHANGELOG.md +17 -0
  3. package/corpus/core/docs/content/components.mdx +7 -0
  4. package/corpus/core/docs/content/locales/ar-SA/components.mdx +4 -2
  5. package/corpus/core/docs/content/locales/de-DE/components.mdx +4 -2
  6. package/corpus/core/docs/content/locales/es-ES/components.mdx +4 -2
  7. package/corpus/core/docs/content/locales/fr-FR/components.mdx +4 -2
  8. package/corpus/core/docs/content/locales/hi-IN/components.mdx +3 -2
  9. package/corpus/core/docs/content/locales/ja-JP/components.mdx +3 -2
  10. package/corpus/core/docs/content/locales/ko-KR/components.mdx +3 -2
  11. package/corpus/core/docs/content/locales/pt-BR/components.mdx +4 -2
  12. package/corpus/core/docs/content/locales/zh-CN/components.mdx +3 -2
  13. package/corpus/core/docs/content/locales/zh-TW/components.mdx +3 -2
  14. package/corpus/core/docs/content/toolkit-agent-ux.mdx +8 -3
  15. package/corpus/core/migration-manifest.json +133 -269
  16. package/corpus/core/package.json +32 -33
  17. package/corpus/core/scripts/check-dist-imports.mjs +25 -1
  18. package/corpus/core/scripts/finalize-build.mjs +59 -2
  19. package/corpus/core/src/client/AgentAskPopover.tsx +1 -1
  20. package/corpus/core/src/client/AgentPanel.tsx +1 -1
  21. package/corpus/core/src/client/AssistantChat.tsx +12 -14
  22. package/corpus/core/src/client/NewWorkspaceAppFlow.tsx +1 -1
  23. package/corpus/core/src/client/agent-chat-adapter.ts +1 -1
  24. package/corpus/core/src/client/blocks/RegistryBlockDataProvider.tsx +121 -0
  25. package/corpus/core/src/client/blocks/index.ts +6 -0
  26. package/corpus/core/src/client/chat/attachment-adapters.ts +4 -5
  27. package/corpus/core/src/client/chat/index.ts +0 -1
  28. package/corpus/core/src/client/chat/message-components.tsx +2 -2
  29. package/corpus/core/src/client/code-agent-chat-adapter.ts +2 -2
  30. package/corpus/core/src/client/collab/index.ts +0 -22
  31. package/corpus/core/src/client/composer/index.ts +5 -66
  32. package/corpus/core/src/client/composer/runtime-adapters.tsx +123 -0
  33. package/corpus/core/src/client/composer/use-mention-search.ts +2 -79
  34. package/corpus/core/src/client/composer/wired-components.tsx +53 -0
  35. package/corpus/core/src/client/extensions/ExtensionViewer.tsx +1 -1
  36. package/corpus/core/src/client/extensions/ExtensionsListPage.tsx +1 -1
  37. package/corpus/core/src/client/extensions/ExtensionsSidebarSection.tsx +1 -1
  38. package/corpus/core/src/client/index.ts +0 -156
  39. package/corpus/core/src/client/resources/ResourceEditor.tsx +29 -681
  40. package/corpus/core/src/client/resources/ResourcesPanel.tsx +1 -1
  41. package/corpus/core/src/client/settings/AutomationsSection.tsx +1 -1
  42. package/corpus/core/src/client/sharing/index.ts +0 -4
  43. package/corpus/core/src/client/tombstone/agent-presence-chip.ts +17 -0
  44. package/corpus/core/src/client/tombstone/editor.ts +265 -0
  45. package/corpus/core/src/client/tombstone/live-cursor-overlay.ts +21 -0
  46. package/corpus/core/src/client/tombstone/presence-bar.ts +17 -0
  47. package/corpus/core/src/client/tombstone/recent-edit-highlights.ts +17 -0
  48. package/corpus/core/src/client/tombstone/remote-selection-rings.ts +21 -0
  49. package/corpus/core/src/client/tombstone/rich-markdown-editor.ts +265 -0
  50. package/corpus/core/src/client/tombstone/ui-dialog.ts +49 -0
  51. package/corpus/core/src/client/tombstone/ui-dropdown-menu.ts +69 -0
  52. package/corpus/core/src/client/tombstone/ui-hover-card.ts +21 -0
  53. package/corpus/core/src/client/tombstone/ui-popover.ts +25 -0
  54. package/corpus/core/src/client/tombstone/ui-sheet.ts +49 -0
  55. package/corpus/core/src/client/tombstone/ui-tooltip.ts +29 -0
  56. package/corpus/core/src/client/tombstone/visual-style-controls.ts +61 -0
  57. package/corpus/core/src/client/uploads/index.ts +5 -0
  58. package/corpus/core/src/client/{rich-markdown-editor/uploadEditorImage.ts → uploads/upload-editor-image.ts} +11 -4
  59. package/corpus/core/src/package-lifecycle/tombstone.ts +16 -2
  60. package/corpus/core/src/package-lifecycle/upgrade-error.ts +23 -5
  61. package/corpus/core/src/testing.ts +1 -4
  62. package/corpus/core/src/vite/client.ts +62 -22
  63. package/corpus/templates/content/app/components/editor/VisualEditor.tsx +2 -4
  64. package/corpus/templates/content/app/components/editor/extensions/registryBlocks.ts +1 -1
  65. package/corpus/templates/content/app/components/editor/registrySlashItems.ts +53 -52
  66. package/corpus/templates/plan/app/components/editor/PlanBlockNode.tsx +2 -2
  67. package/corpus/templates/plan/app/components/editor/planSlashCommands.ts +1 -1
  68. package/corpus/templates/plan/app/components/plan/DocumentArea.tsx +1 -1
  69. package/corpus/templates/plan/app/components/plan/PlanImageNode.tsx +1 -1
  70. package/corpus/templates/plan/app/components/plan/PlanMarkdownEditor.tsx +1 -1
  71. package/dist/catalog.json +1 -0
  72. package/dist/client/AgentAskPopover.js +1 -1
  73. package/dist/client/AgentAskPopover.js.map +1 -1
  74. package/dist/client/AgentPanel.js +1 -1
  75. package/dist/client/AgentPanel.js.map +1 -1
  76. package/dist/client/AssistantChat.d.ts +2 -2
  77. package/dist/client/AssistantChat.d.ts.map +1 -1
  78. package/dist/client/AssistantChat.js +5 -6
  79. package/dist/client/AssistantChat.js.map +1 -1
  80. package/dist/client/NewWorkspaceAppFlow.js +1 -1
  81. package/dist/client/NewWorkspaceAppFlow.js.map +1 -1
  82. package/dist/client/agent-chat-adapter.d.ts.map +1 -1
  83. package/dist/client/agent-chat-adapter.js +1 -1
  84. package/dist/client/agent-chat-adapter.js.map +1 -1
  85. package/dist/client/blocks/RegistryBlockDataProvider.d.ts +7 -0
  86. package/dist/client/blocks/RegistryBlockDataProvider.d.ts.map +1 -0
  87. package/dist/client/blocks/RegistryBlockDataProvider.js +54 -0
  88. package/dist/client/blocks/RegistryBlockDataProvider.js.map +1 -0
  89. package/dist/client/blocks/index.d.ts +2 -0
  90. package/dist/client/blocks/index.d.ts.map +1 -1
  91. package/dist/client/blocks/index.js +1 -0
  92. package/dist/client/blocks/index.js.map +1 -1
  93. package/dist/client/chat/attachment-adapters.d.ts.map +1 -1
  94. package/dist/client/chat/attachment-adapters.js +1 -1
  95. package/dist/client/chat/attachment-adapters.js.map +1 -1
  96. package/dist/client/chat/index.d.ts +0 -1
  97. package/dist/client/chat/index.d.ts.map +1 -1
  98. package/dist/client/chat/index.js +0 -1
  99. package/dist/client/chat/index.js.map +1 -1
  100. package/dist/client/chat/message-components.d.ts.map +1 -1
  101. package/dist/client/chat/message-components.js +2 -2
  102. package/dist/client/chat/message-components.js.map +1 -1
  103. package/dist/client/code-agent-chat-adapter.d.ts.map +1 -1
  104. package/dist/client/code-agent-chat-adapter.js +1 -1
  105. package/dist/client/code-agent-chat-adapter.js.map +1 -1
  106. package/dist/client/collab/index.d.ts +0 -5
  107. package/dist/client/collab/index.d.ts.map +1 -1
  108. package/dist/client/collab/index.js +0 -5
  109. package/dist/client/collab/index.js.map +1 -1
  110. package/dist/client/composer/index.d.ts +3 -11
  111. package/dist/client/composer/index.d.ts.map +1 -1
  112. package/dist/client/composer/index.js +3 -10
  113. package/dist/client/composer/index.js.map +1 -1
  114. package/dist/client/composer/runtime-adapters.d.ts +5 -0
  115. package/dist/client/composer/runtime-adapters.d.ts.map +1 -0
  116. package/dist/client/composer/runtime-adapters.js +85 -0
  117. package/dist/client/composer/runtime-adapters.js.map +1 -0
  118. package/dist/client/composer/use-mention-search.d.ts +1 -2
  119. package/dist/client/composer/use-mention-search.d.ts.map +1 -1
  120. package/dist/client/composer/use-mention-search.js +2 -69
  121. package/dist/client/composer/use-mention-search.js.map +1 -1
  122. package/dist/client/composer/wired-components.d.ts +10 -0
  123. package/dist/client/composer/wired-components.d.ts.map +1 -0
  124. package/dist/client/composer/wired-components.js +20 -0
  125. package/dist/client/composer/wired-components.js.map +1 -0
  126. package/dist/client/extensions/ExtensionViewer.js +1 -1
  127. package/dist/client/extensions/ExtensionViewer.js.map +1 -1
  128. package/dist/client/extensions/ExtensionsListPage.js +1 -1
  129. package/dist/client/extensions/ExtensionsListPage.js.map +1 -1
  130. package/dist/client/extensions/ExtensionsSidebarSection.js +1 -1
  131. package/dist/client/extensions/ExtensionsSidebarSection.js.map +1 -1
  132. package/dist/client/index.d.ts +0 -10
  133. package/dist/client/index.d.ts.map +1 -1
  134. package/dist/client/index.js +0 -26
  135. package/dist/client/index.js.map +1 -1
  136. package/dist/client/resources/ResourceEditor.d.ts.map +1 -1
  137. package/dist/client/resources/ResourceEditor.js +14 -532
  138. package/dist/client/resources/ResourceEditor.js.map +1 -1
  139. package/dist/client/resources/ResourcesPanel.js +1 -1
  140. package/dist/client/resources/ResourcesPanel.js.map +1 -1
  141. package/dist/client/settings/AutomationsSection.js +1 -1
  142. package/dist/client/settings/AutomationsSection.js.map +1 -1
  143. package/dist/client/sharing/index.d.ts +0 -1
  144. package/dist/client/sharing/index.d.ts.map +1 -1
  145. package/dist/client/sharing/index.js +0 -1
  146. package/dist/client/sharing/index.js.map +1 -1
  147. package/dist/client/tombstone/agent-presence-chip.d.ts +6 -0
  148. package/dist/client/tombstone/agent-presence-chip.d.ts.map +1 -0
  149. package/dist/client/tombstone/agent-presence-chip.js +5 -0
  150. package/dist/client/tombstone/agent-presence-chip.js.map +1 -0
  151. package/dist/client/tombstone/editor.d.ts +128 -0
  152. package/dist/client/tombstone/editor.d.ts.map +1 -0
  153. package/dist/client/tombstone/editor.js +76 -0
  154. package/dist/client/tombstone/editor.js.map +1 -0
  155. package/dist/client/tombstone/live-cursor-overlay.d.ts +8 -0
  156. package/dist/client/tombstone/live-cursor-overlay.d.ts.map +1 -0
  157. package/dist/client/tombstone/live-cursor-overlay.js +5 -0
  158. package/dist/client/tombstone/live-cursor-overlay.js.map +1 -0
  159. package/dist/client/tombstone/presence-bar.d.ts +6 -0
  160. package/dist/client/tombstone/presence-bar.d.ts.map +1 -0
  161. package/dist/client/tombstone/presence-bar.js +5 -0
  162. package/dist/client/tombstone/presence-bar.js.map +1 -0
  163. package/dist/client/tombstone/recent-edit-highlights.d.ts +6 -0
  164. package/dist/client/tombstone/recent-edit-highlights.d.ts.map +1 -0
  165. package/dist/client/tombstone/recent-edit-highlights.js +5 -0
  166. package/dist/client/tombstone/recent-edit-highlights.js.map +1 -0
  167. package/dist/client/tombstone/remote-selection-rings.d.ts +8 -0
  168. package/dist/client/tombstone/remote-selection-rings.d.ts.map +1 -0
  169. package/dist/client/tombstone/remote-selection-rings.js +5 -0
  170. package/dist/client/tombstone/remote-selection-rings.js.map +1 -0
  171. package/dist/client/tombstone/rich-markdown-editor.d.ts +128 -0
  172. package/dist/client/tombstone/rich-markdown-editor.d.ts.map +1 -0
  173. package/dist/client/tombstone/rich-markdown-editor.js +76 -0
  174. package/dist/client/tombstone/rich-markdown-editor.js.map +1 -0
  175. package/dist/client/tombstone/ui-dialog.d.ts +22 -0
  176. package/dist/client/tombstone/ui-dialog.d.ts.map +1 -0
  177. package/dist/client/tombstone/ui-dialog.js +23 -0
  178. package/dist/client/tombstone/ui-dialog.js.map +1 -0
  179. package/dist/client/tombstone/ui-dropdown-menu.d.ts +32 -0
  180. package/dist/client/tombstone/ui-dropdown-menu.d.ts.map +1 -0
  181. package/dist/client/tombstone/ui-dropdown-menu.js +33 -0
  182. package/dist/client/tombstone/ui-dropdown-menu.js.map +1 -0
  183. package/dist/client/tombstone/ui-hover-card.d.ts +8 -0
  184. package/dist/client/tombstone/ui-hover-card.d.ts.map +1 -0
  185. package/dist/client/tombstone/ui-hover-card.js +9 -0
  186. package/dist/client/tombstone/ui-hover-card.js.map +1 -0
  187. package/dist/client/tombstone/ui-popover.d.ts +10 -0
  188. package/dist/client/tombstone/ui-popover.d.ts.map +1 -0
  189. package/dist/client/tombstone/ui-popover.js +11 -0
  190. package/dist/client/tombstone/ui-popover.js.map +1 -0
  191. package/dist/client/tombstone/ui-sheet.d.ts +22 -0
  192. package/dist/client/tombstone/ui-sheet.d.ts.map +1 -0
  193. package/dist/client/tombstone/ui-sheet.js +23 -0
  194. package/dist/client/tombstone/ui-sheet.js.map +1 -0
  195. package/dist/client/tombstone/ui-tooltip.d.ts +12 -0
  196. package/dist/client/tombstone/ui-tooltip.d.ts.map +1 -0
  197. package/dist/client/tombstone/ui-tooltip.js +13 -0
  198. package/dist/client/tombstone/ui-tooltip.js.map +1 -0
  199. package/dist/client/tombstone/visual-style-controls.d.ts +28 -0
  200. package/dist/client/tombstone/visual-style-controls.d.ts.map +1 -0
  201. package/dist/client/tombstone/visual-style-controls.js +23 -0
  202. package/dist/client/tombstone/visual-style-controls.js.map +1 -0
  203. package/dist/client/uploads/index.d.ts +1 -0
  204. package/dist/client/uploads/index.d.ts.map +1 -1
  205. package/dist/client/uploads/index.js +1 -0
  206. package/dist/client/uploads/index.js.map +1 -1
  207. package/dist/client/{rich-markdown-editor/uploadEditorImage.d.ts → uploads/upload-editor-image.d.ts} +8 -4
  208. package/dist/client/uploads/upload-editor-image.d.ts.map +1 -0
  209. package/dist/client/{rich-markdown-editor/uploadEditorImage.js → uploads/upload-editor-image.js} +2 -2
  210. package/dist/client/uploads/upload-editor-image.js.map +1 -0
  211. package/dist/collab/struct-routes.d.ts +1 -1
  212. package/dist/notifications/routes.d.ts +3 -3
  213. package/dist/package-lifecycle/tombstone.d.ts.map +1 -1
  214. package/dist/package-lifecycle/tombstone.js +13 -3
  215. package/dist/package-lifecycle/tombstone.js.map +1 -1
  216. package/dist/package-lifecycle/upgrade-error.d.ts +2 -2
  217. package/dist/package-lifecycle/upgrade-error.d.ts.map +1 -1
  218. package/dist/package-lifecycle/upgrade-error.js +8 -5
  219. package/dist/package-lifecycle/upgrade-error.js.map +1 -1
  220. package/dist/secrets/routes.d.ts +9 -9
  221. package/dist/server/agent-engine-api-key-route.d.ts +1 -1
  222. package/dist/server/transcribe-voice.d.ts +1 -1
  223. package/dist/testing.d.ts +1 -3
  224. package/dist/testing.d.ts.map +1 -1
  225. package/dist/testing.js +1 -3
  226. package/dist/testing.js.map +1 -1
  227. package/dist/vite/client.d.ts.map +1 -1
  228. package/dist/vite/client.js +26 -22
  229. package/dist/vite/client.js.map +1 -1
  230. package/docs/content/components.mdx +7 -0
  231. package/docs/content/locales/ar-SA/components.mdx +4 -2
  232. package/docs/content/locales/de-DE/components.mdx +4 -2
  233. package/docs/content/locales/es-ES/components.mdx +4 -2
  234. package/docs/content/locales/fr-FR/components.mdx +4 -2
  235. package/docs/content/locales/hi-IN/components.mdx +3 -2
  236. package/docs/content/locales/ja-JP/components.mdx +3 -2
  237. package/docs/content/locales/ko-KR/components.mdx +3 -2
  238. package/docs/content/locales/pt-BR/components.mdx +4 -2
  239. package/docs/content/locales/zh-CN/components.mdx +3 -2
  240. package/docs/content/locales/zh-TW/components.mdx +3 -2
  241. package/docs/content/toolkit-agent-ux.mdx +8 -3
  242. package/migration-manifest.json +133 -269
  243. package/package.json +31 -32
  244. package/corpus/core/src/client/composer/AgentComposerFrame.tsx +0 -59
  245. package/corpus/core/src/client/composer/ComposerPlusMenu.tsx +0 -988
  246. package/corpus/core/src/client/composer/MentionPopover.tsx +0 -412
  247. package/corpus/core/src/client/composer/PastedTextChip.tsx +0 -150
  248. package/corpus/core/src/client/composer/PromptComposer.tsx +0 -714
  249. package/corpus/core/src/client/composer/RealtimeVoiceMode.tsx +0 -860
  250. package/corpus/core/src/client/composer/TiptapComposer.tsx +0 -2928
  251. package/corpus/core/src/client/composer/VoiceButton.tsx +0 -262
  252. package/corpus/core/src/client/composer/asset-picker-url.ts +0 -80
  253. package/corpus/core/src/client/composer/attachment-accept.ts +0 -71
  254. package/corpus/core/src/client/composer/draft-key.ts +0 -7
  255. package/corpus/core/src/client/composer/extensions/FileReference.tsx +0 -55
  256. package/corpus/core/src/client/composer/extensions/MentionReference.tsx +0 -93
  257. package/corpus/core/src/client/composer/extensions/SkillReference.tsx +0 -56
  258. package/corpus/core/src/client/composer/pasted-text.ts +0 -160
  259. package/corpus/core/src/client/composer/prompt-attachments.ts +0 -70
  260. package/corpus/core/src/client/composer/realtime-voice-audio-level.ts +0 -64
  261. package/corpus/core/src/client/composer/realtime-voice-transcript.ts +0 -134
  262. package/corpus/core/src/client/composer/types.ts +0 -66
  263. package/corpus/core/src/client/composer/use-file-search.ts +0 -63
  264. package/corpus/core/src/client/composer/use-skills.ts +0 -44
  265. package/corpus/core/src/client/composer/useRealtimeVoiceMode.tsx +0 -2095
  266. package/corpus/core/src/client/composer/useVoiceDictation.ts +0 -1155
  267. package/corpus/core/src/client/editor/index.ts +0 -1
  268. package/corpus/core/src/client/rich-markdown-editor/RegistryBlockNode.tsx +0 -799
  269. package/corpus/core/src/client/rich-markdown-editor/index.ts +0 -70
  270. package/corpus/core/src/client/rich-markdown-editor/registrySlashCommands.ts +0 -112
  271. package/dist/client/composer/AgentComposerFrame.d.ts +0 -19
  272. package/dist/client/composer/AgentComposerFrame.d.ts.map +0 -1
  273. package/dist/client/composer/AgentComposerFrame.js +0 -14
  274. package/dist/client/composer/AgentComposerFrame.js.map +0 -1
  275. package/dist/client/composer/ComposerPlusMenu.d.ts +0 -17
  276. package/dist/client/composer/ComposerPlusMenu.d.ts.map +0 -1
  277. package/dist/client/composer/ComposerPlusMenu.js +0 -501
  278. package/dist/client/composer/ComposerPlusMenu.js.map +0 -1
  279. package/dist/client/composer/MentionPopover.d.ts +0 -29
  280. package/dist/client/composer/MentionPopover.d.ts.map +0 -1
  281. package/dist/client/composer/MentionPopover.js +0 -180
  282. package/dist/client/composer/MentionPopover.js.map +0 -1
  283. package/dist/client/composer/PastedTextChip.d.ts +0 -9
  284. package/dist/client/composer/PastedTextChip.d.ts.map +0 -1
  285. package/dist/client/composer/PastedTextChip.js +0 -47
  286. package/dist/client/composer/PastedTextChip.js.map +0 -1
  287. package/dist/client/composer/PromptComposer.d.ts +0 -115
  288. package/dist/client/composer/PromptComposer.d.ts.map +0 -1
  289. package/dist/client/composer/PromptComposer.js +0 -299
  290. package/dist/client/composer/PromptComposer.js.map +0 -1
  291. package/dist/client/composer/RealtimeVoiceMode.d.ts +0 -104
  292. package/dist/client/composer/RealtimeVoiceMode.d.ts.map +0 -1
  293. package/dist/client/composer/RealtimeVoiceMode.js +0 -245
  294. package/dist/client/composer/RealtimeVoiceMode.js.map +0 -1
  295. package/dist/client/composer/TiptapComposer.d.ts +0 -222
  296. package/dist/client/composer/TiptapComposer.d.ts.map +0 -1
  297. package/dist/client/composer/TiptapComposer.js +0 -1834
  298. package/dist/client/composer/TiptapComposer.js.map +0 -1
  299. package/dist/client/composer/VoiceButton.d.ts +0 -23
  300. package/dist/client/composer/VoiceButton.d.ts.map +0 -1
  301. package/dist/client/composer/VoiceButton.js +0 -100
  302. package/dist/client/composer/VoiceButton.js.map +0 -1
  303. package/dist/client/composer/asset-picker-url.d.ts +0 -16
  304. package/dist/client/composer/asset-picker-url.d.ts.map +0 -1
  305. package/dist/client/composer/asset-picker-url.js +0 -64
  306. package/dist/client/composer/asset-picker-url.js.map +0 -1
  307. package/dist/client/composer/attachment-accept.d.ts +0 -9
  308. package/dist/client/composer/attachment-accept.d.ts.map +0 -1
  309. package/dist/client/composer/attachment-accept.js +0 -65
  310. package/dist/client/composer/attachment-accept.js.map +0 -1
  311. package/dist/client/composer/draft-key.d.ts +0 -2
  312. package/dist/client/composer/draft-key.d.ts.map +0 -1
  313. package/dist/client/composer/draft-key.js +0 -8
  314. package/dist/client/composer/draft-key.js.map +0 -1
  315. package/dist/client/composer/extensions/FileReference.d.ts +0 -3
  316. package/dist/client/composer/extensions/FileReference.d.ts.map +0 -1
  317. package/dist/client/composer/extensions/FileReference.js +0 -36
  318. package/dist/client/composer/extensions/FileReference.js.map +0 -1
  319. package/dist/client/composer/extensions/MentionReference.d.ts +0 -3
  320. package/dist/client/composer/extensions/MentionReference.d.ts.map +0 -1
  321. package/dist/client/composer/extensions/MentionReference.js +0 -66
  322. package/dist/client/composer/extensions/MentionReference.js.map +0 -1
  323. package/dist/client/composer/extensions/SkillReference.d.ts +0 -3
  324. package/dist/client/composer/extensions/SkillReference.d.ts.map +0 -1
  325. package/dist/client/composer/extensions/SkillReference.js +0 -40
  326. package/dist/client/composer/extensions/SkillReference.js.map +0 -1
  327. package/dist/client/composer/pasted-text.d.ts +0 -31
  328. package/dist/client/composer/pasted-text.d.ts.map +0 -1
  329. package/dist/client/composer/pasted-text.js +0 -130
  330. package/dist/client/composer/pasted-text.js.map +0 -1
  331. package/dist/client/composer/prompt-attachments.d.ts +0 -11
  332. package/dist/client/composer/prompt-attachments.d.ts.map +0 -1
  333. package/dist/client/composer/prompt-attachments.js +0 -45
  334. package/dist/client/composer/prompt-attachments.js.map +0 -1
  335. package/dist/client/composer/realtime-voice-audio-level.d.ts +0 -14
  336. package/dist/client/composer/realtime-voice-audio-level.d.ts.map +0 -1
  337. package/dist/client/composer/realtime-voice-audio-level.js +0 -47
  338. package/dist/client/composer/realtime-voice-audio-level.js.map +0 -1
  339. package/dist/client/composer/realtime-voice-transcript.d.ts +0 -26
  340. package/dist/client/composer/realtime-voice-transcript.d.ts.map +0 -1
  341. package/dist/client/composer/realtime-voice-transcript.js +0 -103
  342. package/dist/client/composer/realtime-voice-transcript.js.map +0 -1
  343. package/dist/client/composer/types.d.ts +0 -60
  344. package/dist/client/composer/types.d.ts.map +0 -1
  345. package/dist/client/composer/types.js +0 -2
  346. package/dist/client/composer/types.js.map +0 -1
  347. package/dist/client/composer/use-file-search.d.ts +0 -6
  348. package/dist/client/composer/use-file-search.d.ts.map +0 -1
  349. package/dist/client/composer/use-file-search.js +0 -52
  350. package/dist/client/composer/use-file-search.js.map +0 -1
  351. package/dist/client/composer/use-skills.d.ts +0 -7
  352. package/dist/client/composer/use-skills.d.ts.map +0 -1
  353. package/dist/client/composer/use-skills.js +0 -39
  354. package/dist/client/composer/use-skills.js.map +0 -1
  355. package/dist/client/composer/useRealtimeVoiceMode.d.ts +0 -172
  356. package/dist/client/composer/useRealtimeVoiceMode.d.ts.map +0 -1
  357. package/dist/client/composer/useRealtimeVoiceMode.js +0 -1648
  358. package/dist/client/composer/useRealtimeVoiceMode.js.map +0 -1
  359. package/dist/client/composer/useVoiceDictation.d.ts +0 -57
  360. package/dist/client/composer/useVoiceDictation.d.ts.map +0 -1
  361. package/dist/client/composer/useVoiceDictation.js +0 -975
  362. package/dist/client/composer/useVoiceDictation.js.map +0 -1
  363. package/dist/client/editor/index.d.ts +0 -2
  364. package/dist/client/editor/index.d.ts.map +0 -1
  365. package/dist/client/editor/index.js +0 -2
  366. package/dist/client/editor/index.js.map +0 -1
  367. package/dist/client/rich-markdown-editor/RegistryBlockNode.d.ts +0 -130
  368. package/dist/client/rich-markdown-editor/RegistryBlockNode.d.ts.map +0 -1
  369. package/dist/client/rich-markdown-editor/RegistryBlockNode.js +0 -426
  370. package/dist/client/rich-markdown-editor/RegistryBlockNode.js.map +0 -1
  371. package/dist/client/rich-markdown-editor/index.d.ts +0 -5
  372. package/dist/client/rich-markdown-editor/index.d.ts.map +0 -1
  373. package/dist/client/rich-markdown-editor/index.js +0 -5
  374. package/dist/client/rich-markdown-editor/index.js.map +0 -1
  375. package/dist/client/rich-markdown-editor/registrySlashCommands.d.ts +0 -60
  376. package/dist/client/rich-markdown-editor/registrySlashCommands.d.ts.map +0 -1
  377. package/dist/client/rich-markdown-editor/registrySlashCommands.js +0 -51
  378. package/dist/client/rich-markdown-editor/registrySlashCommands.js.map +0 -1
  379. package/dist/client/rich-markdown-editor/uploadEditorImage.d.ts.map +0 -1
  380. package/dist/client/rich-markdown-editor/uploadEditorImage.js.map +0 -1
@@ -1,988 +0,0 @@
1
- import { useComposerRuntime } from "@assistant-ui/react";
2
- import {
3
- IconPlus,
4
- IconUpload,
5
- IconBulb,
6
- IconClock,
7
- IconBolt,
8
- IconTool,
9
- IconPlugConnected,
10
- IconPhotoPlus,
11
- IconLoader2,
12
- IconArrowLeft,
13
- IconX,
14
- } from "@tabler/icons-react";
15
- import React, {
16
- useState,
17
- useRef,
18
- useEffect,
19
- useMemo,
20
- useCallback,
21
- } from "react";
22
- import { createPortal } from "react-dom";
23
-
24
- import { setAgentChatContextItem } from "../agent-chat.js";
25
- import { agentNativePath } from "../api-path.js";
26
- import {
27
- Popover,
28
- PopoverTrigger,
29
- PopoverContent,
30
- } from "../components/ui/popover.js";
31
- import {
32
- Tooltip,
33
- TooltipContent,
34
- TooltipTrigger,
35
- } from "../components/ui/tooltip.js";
36
- import { useT } from "../i18n.js";
37
- import { useOrg } from "../org/hooks.js";
38
- import { isMcpIntegrationCatalogAvailable } from "../resources/mcp-integration-catalog.js";
39
- import { McpIntegrationDialog } from "../resources/McpIntegrationDialog.js";
40
- import {
41
- useCreateMcpServer,
42
- type McpServerScope,
43
- } from "../resources/use-mcp-servers.js";
44
- import { cn } from "../utils.js";
45
- import {
46
- createAssetPickerHandoffId,
47
- isExternalAssetPickerUrl,
48
- standaloneAssetPickerUrl,
49
- } from "./asset-picker-url.js";
50
- import type { ComposerMode } from "./types.js";
51
-
52
- interface ComposerPlusMenuProps {
53
- onSelectMode?: (mode: ComposerMode) => void;
54
- onAttachmentError?: (message: string) => void;
55
- /**
56
- * "full" (default): full + menu with Upload File, Create Skill, Schedule Task,
57
- * Automation, Extension, MCP Server. "upload-only": clicking + opens the file
58
- * picker directly — no popover, no other modes. Use for prompt popovers
59
- * (create extension, create deck, create dashboard, etc.) where the only thing
60
- * to attach is a file.
61
- */
62
- mode?: "full" | "upload-only";
63
- }
64
-
65
- type View = "menu" | "skill-upload";
66
-
67
- const DEFAULT_ASSETS_PICKER_URL = "https://assets.agent-native.com/picker";
68
- const EMBED_PROTOCOL = "agent-native.embed";
69
- const EMBED_VERSION = 1;
70
-
71
- interface EmbedEnvelope<TPayload = unknown> {
72
- protocol?: string;
73
- version?: number;
74
- type?: string;
75
- name?: string;
76
- payload?: TPayload;
77
- }
78
-
79
- interface AssetPickerPayload {
80
- assetId?: unknown;
81
- handoffId?: unknown;
82
- url?: unknown;
83
- previewUrl?: unknown;
84
- downloadUrl?: unknown;
85
- embedUrl?: unknown;
86
- altText?: unknown;
87
- title?: unknown;
88
- prompt?: unknown;
89
- mediaType?: unknown;
90
- libraryId?: unknown;
91
- }
92
-
93
- function assetPickerUrl() {
94
- const env = (import.meta.env as Record<string, string | undefined>) ?? {};
95
- return env.VITE_AGENT_NATIVE_ASSETS_PICKER_URL || DEFAULT_ASSETS_PICKER_URL;
96
- }
97
-
98
- function withEmbeddedParams(url: string): string {
99
- try {
100
- const parsed = new URL(url, window.location.href);
101
- parsed.searchParams.set("embedded", "1");
102
- parsed.searchParams.set("mediaType", "image");
103
- return parsed.toString();
104
- } catch {
105
- const separator = url.includes("?") ? "&" : "?";
106
- return `${url}${separator}embedded=1&mediaType=image`;
107
- }
108
- }
109
-
110
- function assetPickerOrigin(url: string): string | null {
111
- try {
112
- return new URL(url, window.location.href).origin;
113
- } catch {
114
- return null;
115
- }
116
- }
117
-
118
- function embedEnvelope(
119
- type: "message" | "ready",
120
- options: { name?: string; payload?: unknown } = {},
121
- ): EmbedEnvelope {
122
- return {
123
- protocol: EMBED_PROTOCOL,
124
- version: EMBED_VERSION,
125
- type,
126
- ...options,
127
- };
128
- }
129
-
130
- function isEmbedEnvelope(value: unknown): value is EmbedEnvelope {
131
- if (!value || typeof value !== "object" || Array.isArray(value)) return false;
132
- const candidate = value as EmbedEnvelope;
133
- return (
134
- candidate.protocol === EMBED_PROTOCOL &&
135
- candidate.version === EMBED_VERSION &&
136
- typeof candidate.type === "string"
137
- );
138
- }
139
-
140
- function assetString(value: unknown): string | null {
141
- return typeof value === "string" && value.trim() ? value.trim() : null;
142
- }
143
-
144
- function assetImageSource(payload: unknown): string | null {
145
- if (!payload || typeof payload !== "object") return null;
146
- const asset = payload as AssetPickerPayload;
147
- return (
148
- assetString(asset.url) ??
149
- assetString(asset.previewUrl) ??
150
- assetString(asset.downloadUrl) ??
151
- assetString(asset.embedUrl)
152
- );
153
- }
154
-
155
- function assetTitle(payload: unknown, url: string): string {
156
- if (payload && typeof payload === "object") {
157
- const title = assetString((payload as AssetPickerPayload).title);
158
- if (title) return title;
159
- const prompt = assetString((payload as AssetPickerPayload).prompt);
160
- if (prompt) return prompt.slice(0, 80);
161
- }
162
- try {
163
- const name = new URL(url).pathname.split("/").filter(Boolean).pop();
164
- return name ? decodeURIComponent(name) : "Generated image";
165
- } catch {
166
- return "Generated image";
167
- }
168
- }
169
-
170
- function assetContext(payload: unknown, url: string): string {
171
- const lines = [`Image URL: ${url}`];
172
- if (payload && typeof payload === "object") {
173
- const asset = payload as AssetPickerPayload;
174
- const assetId = assetString(asset.assetId);
175
- const libraryId = assetString(asset.libraryId);
176
- const prompt = assetString(asset.prompt);
177
- const altText = assetString(asset.altText);
178
- if (assetId) lines.push(`Asset ID: ${assetId}`);
179
- if (libraryId) lines.push(`Library ID: ${libraryId}`);
180
- if (prompt) lines.push(`Prompt: ${prompt}`);
181
- if (altText) lines.push(`Alt text: ${altText}`);
182
- }
183
- return lines.join("\n");
184
- }
185
-
186
- function slugifyName(value: string): string {
187
- return (
188
- value
189
- .toLowerCase()
190
- .replace(/[^a-z0-9]+/g, "-")
191
- .replace(/^-+|-+$/g, "") || "uploaded-skill"
192
- );
193
- }
194
-
195
- function formatAttachmentError(error: unknown, fallback: string): string {
196
- return error instanceof Error ? error.message : fallback;
197
- }
198
-
199
- function UploadOnlyAttachButton({
200
- onAttachmentError,
201
- }: Pick<ComposerPlusMenuProps, "onAttachmentError">) {
202
- const composerRuntime = useComposerRuntime();
203
- const inputRef = useRef<HTMLInputElement>(null);
204
- const handleFilesSelected = async (files: FileList | null) => {
205
- if (!files || files.length === 0) return;
206
- try {
207
- await Promise.all(
208
- Array.from(files).map((file) => composerRuntime.addAttachment(file)),
209
- );
210
- } catch (error) {
211
- onAttachmentError?.(
212
- formatAttachmentError(error, "Could not upload the selected file."),
213
- );
214
- }
215
- };
216
-
217
- return (
218
- <>
219
- <input
220
- ref={inputRef}
221
- type="file"
222
- multiple
223
- className="hidden"
224
- onChange={(event) => {
225
- void handleFilesSelected(event.target.files);
226
- event.target.value = "";
227
- }}
228
- />
229
- <Tooltip>
230
- <TooltipTrigger asChild>
231
- <span className="inline-flex shrink-0">
232
- <button
233
- type="button"
234
- className="shrink-0 flex h-7 w-7 cursor-pointer items-center justify-center rounded-md text-muted-foreground hover:text-foreground hover:bg-accent/50"
235
- aria-label="Upload"
236
- onClick={() => inputRef.current?.click()}
237
- >
238
- <IconPlus className="h-4 w-4" />
239
- </button>
240
- </span>
241
- </TooltipTrigger>
242
- <TooltipContent>Upload</TooltipContent>
243
- </Tooltip>
244
- </>
245
- );
246
- }
247
-
248
- export function ComposerPlusMenu({
249
- onSelectMode,
250
- onAttachmentError,
251
- mode = "full",
252
- }: ComposerPlusMenuProps) {
253
- if (mode === "upload-only") {
254
- return <UploadOnlyAttachButton onAttachmentError={onAttachmentError} />;
255
- }
256
- return (
257
- <ComposerPlusMenuFull
258
- onSelectMode={onSelectMode}
259
- onAttachmentError={onAttachmentError}
260
- />
261
- );
262
- }
263
-
264
- function ComposerPlusMenuFull({
265
- onSelectMode,
266
- onAttachmentError,
267
- }: Pick<ComposerPlusMenuProps, "onSelectMode" | "onAttachmentError">) {
268
- const t = useT();
269
- const composerRuntime = useComposerRuntime();
270
- const [open, setOpen] = useState(false);
271
- const [assetsPickerOpen, setAssetsPickerOpen] = useState(false);
272
- const [mcpDialogOpen, setMcpDialogOpen] = useState(false);
273
- const [view, setView] = useState<View>("menu");
274
- const showMcpIntegrations = useMemo(
275
- () => isMcpIntegrationCatalogAvailable(),
276
- [],
277
- );
278
-
279
- const { data: org } = useOrg();
280
- const canCreateOrgMcp =
281
- !org?.orgId || org.role === "owner" || org.role === "admin";
282
- const hasOrg = !!org?.orgId;
283
- const defaultMcpScope: McpServerScope =
284
- hasOrg && canCreateOrgMcp ? "org" : "user";
285
- const createMcp = useCreateMcpServer();
286
-
287
- const fileUploadRef = useRef<HTMLInputElement>(null);
288
- const skillFileInputRef = useRef<HTMLInputElement>(null);
289
- const skillHoverTimerRef = useRef<number | null>(null);
290
- const [skillUploadSlug, setSkillUploadSlug] = useState("");
291
- const [skillUploadContent, setSkillUploadContent] = useState("");
292
- const [skillUploadFileName, setSkillUploadFileName] = useState("");
293
- const [skillUploadStatus, setSkillUploadStatus] = useState<{
294
- kind: "ok" | "err";
295
- message: string;
296
- } | null>(null);
297
- const [skillUploadBusy, setSkillUploadBusy] = useState(false);
298
- const [skillFlyoutOpen, setSkillFlyoutOpen] = useState(false);
299
- const [skillFlyoutSide, setSkillFlyoutSide] = useState<"right" | "left">(
300
- "right",
301
- );
302
- const skillFlyoutCloseTimerRef = useRef<number | null>(null);
303
- const openSkillFlyout = (rowEl?: HTMLElement | null) => {
304
- if (skillFlyoutCloseTimerRef.current) {
305
- window.clearTimeout(skillFlyoutCloseTimerRef.current);
306
- skillFlyoutCloseTimerRef.current = null;
307
- }
308
- if (rowEl && typeof window !== "undefined") {
309
- const rect = rowEl.getBoundingClientRect();
310
- const FLYOUT_WIDTH = 248;
311
- setSkillFlyoutSide(
312
- window.innerWidth - rect.right < FLYOUT_WIDTH ? "left" : "right",
313
- );
314
- }
315
- setSkillFlyoutOpen(true);
316
- };
317
- const scheduleSkillFlyoutClose = () => {
318
- if (skillFlyoutCloseTimerRef.current)
319
- window.clearTimeout(skillFlyoutCloseTimerRef.current);
320
- skillFlyoutCloseTimerRef.current = window.setTimeout(() => {
321
- setSkillFlyoutOpen(false);
322
- }, 160);
323
- };
324
-
325
- useEffect(() => {
326
- if (open) {
327
- setView("menu");
328
- setSkillUploadSlug("");
329
- setSkillUploadContent("");
330
- setSkillUploadFileName("");
331
- setSkillUploadStatus(null);
332
- setSkillUploadBusy(false);
333
- setSkillFlyoutOpen(false);
334
- }
335
- }, [open]);
336
-
337
- const handleSkillFileSelected = async (files: FileList | null) => {
338
- if (!files || files.length === 0) return;
339
- const file = files[0];
340
- const text = await file.text();
341
- const baseName = file.name.replace(/\.[^./]+$/, "");
342
- const slug = slugifyName(
343
- baseName.toLowerCase() === "skill" ? "uploaded-skill" : baseName,
344
- );
345
- setSkillUploadSlug(slug);
346
- setSkillUploadContent(text);
347
- setSkillUploadFileName(file.name);
348
- setSkillUploadStatus(null);
349
- setView("skill-upload");
350
- };
351
-
352
- const handleFilesSelected = async (files: FileList | null) => {
353
- if (!files || files.length === 0) return;
354
- try {
355
- await Promise.all(
356
- Array.from(files).map((file) => composerRuntime.addAttachment(file)),
357
- );
358
- } catch (error) {
359
- onAttachmentError?.(
360
- formatAttachmentError(error, "Could not upload the selected file."),
361
- );
362
- }
363
- };
364
-
365
- const submitSkillUpload = async () => {
366
- if (skillUploadBusy) return;
367
- const slug = slugifyName(skillUploadSlug || "uploaded-skill");
368
- const path = `skills/${slug}/SKILL.md`;
369
- setSkillUploadBusy(true);
370
- setSkillUploadStatus(null);
371
- try {
372
- const res = await fetch(agentNativePath("/_agent-native/resources"), {
373
- method: "POST",
374
- headers: { "Content-Type": "application/json" },
375
- body: JSON.stringify({
376
- path,
377
- content: skillUploadContent,
378
- mimeType: "text/markdown",
379
- shared: false,
380
- }),
381
- });
382
- if (!res.ok) {
383
- const body = await res.text().catch(() => "");
384
- throw new Error(body || `Upload failed (${res.status})`);
385
- }
386
- setSkillUploadStatus({
387
- kind: "ok",
388
- message: `Skill "${skillUploadFileName || `${slug}/SKILL.md`}" added`,
389
- });
390
- window.setTimeout(() => setOpen(false), 1200);
391
- } catch (err: any) {
392
- setSkillUploadStatus({
393
- kind: "err",
394
- message: err?.message || "Failed to save skill file",
395
- });
396
- } finally {
397
- setSkillUploadBusy(false);
398
- }
399
- };
400
-
401
- const menuItems: {
402
- icon: React.ReactNode;
403
- label: string;
404
- desc: string;
405
- action: () => void;
406
- hoverAction?: () => void;
407
- }[] = [
408
- {
409
- icon: <IconUpload className="h-3.5 w-3.5" />,
410
- label: "Upload File",
411
- desc: "Images, PDFs, text/code, JSON, CSV",
412
- action: () => {
413
- setOpen(false);
414
- setTimeout(() => fileUploadRef.current?.click(), 0);
415
- },
416
- },
417
- {
418
- icon: <IconPhotoPlus className="h-3.5 w-3.5" />,
419
- label: "Generate Image",
420
- desc: "Open the Assets image picker",
421
- action: () => {
422
- setOpen(false);
423
- setAssetsPickerOpen(true);
424
- },
425
- },
426
- {
427
- icon: <IconClock className="h-3.5 w-3.5" />,
428
- label: "Schedule Task",
429
- desc: "Run something on a schedule",
430
- action: () => {
431
- onSelectMode?.("job");
432
- setOpen(false);
433
- },
434
- },
435
- {
436
- icon: <IconBolt className="h-3.5 w-3.5" />,
437
- label: "Create Automation",
438
- desc: "Set up a when-X-do-Y rule",
439
- action: () => {
440
- onSelectMode?.("automation");
441
- setOpen(false);
442
- },
443
- },
444
- {
445
- icon: <IconTool className="h-3.5 w-3.5" />,
446
- label: "Create Extension",
447
- desc: "Build a mini app extension",
448
- action: () => {
449
- onSelectMode?.("extension");
450
- setOpen(false);
451
- },
452
- },
453
- ...(showMcpIntegrations
454
- ? [
455
- {
456
- icon: <IconPlugConnected className="h-3.5 w-3.5" />,
457
- label: t("mcpIntegrations.menuLabel"),
458
- desc: t("mcpIntegrations.menuDescription"),
459
- action: () => {
460
- setOpen(false);
461
- setMcpDialogOpen(true);
462
- },
463
- },
464
- ]
465
- : []),
466
- {
467
- icon: <IconBulb className="h-3.5 w-3.5" />,
468
- label: "Create Skill",
469
- desc: "Teach the agent a new ability",
470
- action: openSkillFlyout,
471
- hoverAction: openSkillFlyout,
472
- },
473
- ];
474
-
475
- return (
476
- <>
477
- {/* Hidden input to trigger the native file upload with explicit errors. */}
478
- <input
479
- ref={fileUploadRef}
480
- type="file"
481
- multiple
482
- className="hidden"
483
- onChange={(event) => {
484
- void handleFilesSelected(event.target.files);
485
- event.target.value = "";
486
- }}
487
- />
488
- <input
489
- ref={skillFileInputRef}
490
- type="file"
491
- accept=".md,text/markdown"
492
- className="hidden"
493
- onChange={(e) => {
494
- void handleSkillFileSelected(e.target.files);
495
- e.target.value = "";
496
- }}
497
- />
498
-
499
- <Popover open={open} onOpenChange={setOpen}>
500
- <Tooltip>
501
- <TooltipTrigger asChild>
502
- <PopoverTrigger asChild>
503
- <button
504
- type="button"
505
- className="shrink-0 flex h-7 w-7 items-center justify-center rounded-md text-muted-foreground hover:text-foreground hover:bg-accent/50 disabled:opacity-30 disabled:cursor-not-allowed"
506
- >
507
- <IconPlus className="h-4 w-4" />
508
- </button>
509
- </PopoverTrigger>
510
- </TooltipTrigger>
511
- <TooltipContent>Add...</TooltipContent>
512
- </Tooltip>
513
- <PopoverContent
514
- side="top"
515
- align="start"
516
- sideOffset={8}
517
- className={cn(
518
- "p-0 rounded-lg",
519
- view === "skill-upload"
520
- ? "max-h-[70vh] w-[calc(100vw-24px)] max-w-[380px] overflow-y-auto"
521
- : "w-[260px]",
522
- )}
523
- style={{ fontSize: 13, lineHeight: "normal" }}
524
- onOpenAutoFocus={(e) => e.preventDefault()}
525
- >
526
- {view === "menu" && (
527
- <div className="py-1">
528
- {menuItems.map((item) => {
529
- const isSkill = item.label === "Create Skill";
530
- return (
531
- <div
532
- key={item.label}
533
- className={cn("relative", isSkill && "group/skill")}
534
- onMouseEnter={(e) => {
535
- if (isSkill) {
536
- openSkillFlyout(e.currentTarget);
537
- return;
538
- }
539
- if (!item.hoverAction) return;
540
- if (skillHoverTimerRef.current)
541
- window.clearTimeout(skillHoverTimerRef.current);
542
- skillHoverTimerRef.current = window.setTimeout(() => {
543
- item.hoverAction?.();
544
- }, 180);
545
- }}
546
- onMouseLeave={() => {
547
- if (isSkill) {
548
- scheduleSkillFlyoutClose();
549
- return;
550
- }
551
- if (skillHoverTimerRef.current) {
552
- window.clearTimeout(skillHoverTimerRef.current);
553
- skillHoverTimerRef.current = null;
554
- }
555
- }}
556
- >
557
- <button
558
- type="button"
559
- onClick={item.action}
560
- className={cn(
561
- "flex w-full items-center gap-2.5 px-3 py-2 text-start hover:bg-accent/50",
562
- isSkill && skillFlyoutOpen && "bg-accent/50",
563
- )}
564
- >
565
- <span className="text-muted-foreground">{item.icon}</span>
566
- <div className="min-w-0 flex-1">
567
- <div className="text-[12px] font-medium text-foreground">
568
- {item.label}
569
- </div>
570
- <div className="mt-0.5 text-[10px] text-muted-foreground/60">
571
- {item.desc}
572
- </div>
573
- </div>
574
- {isSkill && (
575
- <span className="ms-auto text-muted-foreground/60">
576
-
577
- </span>
578
- )}
579
- </button>
580
- {isSkill && skillFlyoutOpen && (
581
- <div
582
- role="menu"
583
- onMouseEnter={() => openSkillFlyout()}
584
- onMouseLeave={scheduleSkillFlyoutClose}
585
- className={cn(
586
- "absolute top-0 z-20 w-[240px] rounded-lg border border-border bg-popover py-1 shadow-md",
587
- skillFlyoutSide === "right"
588
- ? "left-full ml-1"
589
- : "right-full mr-1",
590
- )}
591
- >
592
- <button
593
- type="button"
594
- onClick={() => {
595
- onSelectMode?.("skill");
596
- setSkillFlyoutOpen(false);
597
- setOpen(false);
598
- }}
599
- className="flex w-full items-center gap-2.5 px-3 py-2 text-start hover:bg-accent/50"
600
- >
601
- <span className="text-muted-foreground">
602
- <IconBulb className="h-3.5 w-3.5" />
603
- </span>
604
- <div className="min-w-0">
605
- <div className="text-[12px] font-medium text-foreground">
606
- Create new skill
607
- </div>
608
- <div className="mt-0.5 text-[10px] text-muted-foreground/60">
609
- Describe a skill and let the agent draft it
610
- </div>
611
- </div>
612
- </button>
613
- <button
614
- type="button"
615
- onClick={() => {
616
- setSkillFlyoutOpen(false);
617
- skillFileInputRef.current?.click();
618
- }}
619
- className="flex w-full items-center gap-2.5 px-3 py-2 text-start hover:bg-accent/50"
620
- >
621
- <span className="text-muted-foreground">
622
- <IconUpload className="h-3.5 w-3.5" />
623
- </span>
624
- <div className="min-w-0">
625
- <div className="text-[12px] font-medium text-foreground">
626
- Upload skill file
627
- </div>
628
- <div className="mt-0.5 text-[10px] text-muted-foreground/60">
629
- Import an existing SKILL.md file
630
- </div>
631
- </div>
632
- </button>
633
- </div>
634
- )}
635
- </div>
636
- );
637
- })}
638
- </div>
639
- )}
640
-
641
- {view === "skill-upload" && (
642
- <div className="p-3">
643
- <button
644
- type="button"
645
- onClick={() => setView("menu")}
646
- className="mb-1.5 flex items-center gap-1 text-[11px] text-muted-foreground hover:text-foreground"
647
- >
648
- <IconArrowLeft className="h-3 w-3 rtl:-scale-x-100" />
649
- Back
650
- </button>
651
- <label className="mb-1 block text-[11px] font-semibold text-foreground">
652
- Upload skill file
653
- </label>
654
- <p className="mb-2 text-[10px] leading-relaxed text-muted-foreground/60">
655
- Review the content from{" "}
656
- <span className="font-mono">
657
- {skillUploadFileName || "the selected file"}
658
- </span>{" "}
659
- before saving.
660
- </p>
661
- <label className="mb-1 block text-[10px] font-medium text-muted-foreground">
662
- Skill name
663
- </label>
664
- <input
665
- value={skillUploadSlug}
666
- onChange={(e) => setSkillUploadSlug(e.target.value)}
667
- className="mb-2 w-full rounded-md border border-border bg-background px-2.5 py-1.5 text-[12px] text-foreground outline-none placeholder:text-muted-foreground/50 focus:ring-1 focus:ring-accent"
668
- placeholder="my-skill"
669
- />
670
- <p className="mb-2 text-[10px] text-muted-foreground/60">
671
- Saved at{" "}
672
- <span className="font-mono">
673
- skills/{slugifyName(skillUploadSlug || "uploaded-skill")}
674
- /SKILL.md
675
- </span>
676
- </p>
677
- <label className="mb-1 block text-[10px] font-medium text-muted-foreground">
678
- Content
679
- </label>
680
- <textarea
681
- value={skillUploadContent}
682
- onChange={(e) => setSkillUploadContent(e.target.value)}
683
- rows={10}
684
- className="w-full rounded-md border border-border bg-background px-2.5 py-1.5 font-mono text-[11px] leading-relaxed text-foreground outline-none focus:ring-1 focus:ring-accent"
685
- />
686
- {skillUploadStatus && (
687
- <div
688
- className={cn(
689
- "mt-2 text-[11px] leading-snug",
690
- skillUploadStatus.kind === "ok"
691
- ? "text-green-600 dark:text-green-400"
692
- : "text-red-600 dark:text-red-400",
693
- )}
694
- >
695
- {skillUploadStatus.message}
696
- </div>
697
- )}
698
- <div className="mt-2.5 flex justify-end gap-2">
699
- <button
700
- type="button"
701
- onClick={() => setView("menu")}
702
- className="rounded-md px-3 py-1.5 text-[12px] font-medium text-muted-foreground hover:bg-accent/40"
703
- >
704
- Cancel
705
- </button>
706
- <button
707
- type="button"
708
- onClick={submitSkillUpload}
709
- disabled={
710
- skillUploadBusy ||
711
- !skillUploadContent.trim() ||
712
- !skillUploadSlug.trim()
713
- }
714
- className="rounded-md bg-accent px-3 py-1.5 text-[12px] font-medium text-foreground hover:bg-accent/80 disabled:opacity-40 disabled:pointer-events-none"
715
- >
716
- {skillUploadBusy ? (
717
- <IconLoader2 className="h-3 w-3 animate-spin" />
718
- ) : (
719
- "Save"
720
- )}
721
- </button>
722
- </div>
723
- </div>
724
- )}
725
- </PopoverContent>
726
- </Popover>
727
- <McpIntegrationDialog
728
- open={mcpDialogOpen}
729
- onOpenChange={setMcpDialogOpen}
730
- defaultScope={defaultMcpScope}
731
- canCreateOrgMcp={canCreateOrgMcp}
732
- hasOrg={hasOrg}
733
- onCreateMcpServer={(args) => createMcp.mutateAsync(args)}
734
- />
735
- <AssetsPickerModal
736
- open={assetsPickerOpen}
737
- onOpenChange={setAssetsPickerOpen}
738
- />
739
- </>
740
- );
741
- }
742
-
743
- function AssetsPickerModal({
744
- open,
745
- onOpenChange,
746
- }: {
747
- open: boolean;
748
- onOpenChange: (open: boolean) => void;
749
- }) {
750
- const iframeRef = useRef<HTMLIFrameElement | null>(null);
751
- const standaloneWindowRef = useRef<Window | null>(null);
752
- const [pickerReady, setPickerReady] = useState(false);
753
- const [standaloneHandoffId, setStandaloneHandoffId] = useState<string | null>(
754
- null,
755
- );
756
- const sourceUrl = useMemo(() => assetPickerUrl(), []);
757
- const externalPicker = useMemo(
758
- () =>
759
- typeof window !== "undefined" &&
760
- isExternalAssetPickerUrl(sourceUrl, window.location.origin),
761
- [sourceUrl],
762
- );
763
- const standaloneUrl = useMemo(
764
- () =>
765
- standaloneAssetPickerUrl(
766
- sourceUrl,
767
- typeof window !== "undefined" ? window.location.href : undefined,
768
- {
769
- handoffId: standaloneHandoffId ?? undefined,
770
- returnOrigin:
771
- typeof window !== "undefined" ? window.location.origin : undefined,
772
- },
773
- ),
774
- [sourceUrl, standaloneHandoffId],
775
- );
776
- const iframeUrl = useMemo(() => withEmbeddedParams(sourceUrl), [sourceUrl]);
777
- const targetOrigin = useMemo(() => assetPickerOrigin(iframeUrl), [iframeUrl]);
778
- const configurePicker = useCallback(() => {
779
- if (!targetOrigin) return;
780
- iframeRef.current?.contentWindow?.postMessage(
781
- embedEnvelope("message", {
782
- name: "configure",
783
- payload: { mediaType: "image", count: 3 },
784
- }),
785
- targetOrigin,
786
- );
787
- }, [targetOrigin]);
788
-
789
- useEffect(() => {
790
- if (open) {
791
- setPickerReady(false);
792
- if (externalPicker) {
793
- standaloneWindowRef.current = null;
794
- setStandaloneHandoffId(createAssetPickerHandoffId());
795
- } else {
796
- setStandaloneHandoffId(null);
797
- }
798
- return;
799
- }
800
- if (!standaloneWindowRef.current) setStandaloneHandoffId(null);
801
- }, [externalPicker, iframeUrl, open]);
802
-
803
- useEffect(() => {
804
- if (
805
- !targetOrigin ||
806
- (!open && !standaloneWindowRef.current) ||
807
- (externalPicker && !standaloneHandoffId)
808
- )
809
- return;
810
-
811
- const handleMessage = (event: MessageEvent) => {
812
- const expectedSource = externalPicker
813
- ? standaloneWindowRef.current
814
- : iframeRef.current?.contentWindow;
815
- if (!expectedSource || event.source !== expectedSource) return;
816
- if (event.origin !== targetOrigin) return;
817
- if (!isEmbedEnvelope(event.data)) return;
818
-
819
- if (event.data.type === "ready") {
820
- setPickerReady(true);
821
- configurePicker();
822
- return;
823
- }
824
-
825
- if (event.data.type !== "message") return;
826
- if (externalPicker) {
827
- const payload = event.data.payload;
828
- const handoffId =
829
- payload && typeof payload === "object"
830
- ? assetString((payload as AssetPickerPayload).handoffId)
831
- : null;
832
- if (handoffId !== standaloneHandoffId) return;
833
- }
834
- if (event.data.name === "close") {
835
- onOpenChange(false);
836
- return;
837
- }
838
- if (
839
- event.data.name !== "chooseImage" &&
840
- event.data.name !== "chooseAsset"
841
- )
842
- return;
843
-
844
- const url = assetImageSource(event.data.payload);
845
- if (!url) return;
846
- const title = assetTitle(event.data.payload, url);
847
- const assetId =
848
- event.data.payload && typeof event.data.payload === "object"
849
- ? assetString((event.data.payload as AssetPickerPayload).assetId)
850
- : null;
851
- setAgentChatContextItem({
852
- key: `asset-image:${assetId ?? url}`,
853
- title: `Image: ${title}`,
854
- context: assetContext(event.data.payload, url),
855
- });
856
- standaloneWindowRef.current = null;
857
- setStandaloneHandoffId(null);
858
- onOpenChange(false);
859
- };
860
-
861
- const handleKey = (event: KeyboardEvent) => {
862
- if (event.key === "Escape") onOpenChange(false);
863
- };
864
-
865
- window.addEventListener("message", handleMessage);
866
- window.addEventListener("keydown", handleKey);
867
- return () => {
868
- window.removeEventListener("message", handleMessage);
869
- window.removeEventListener("keydown", handleKey);
870
- };
871
- }, [
872
- configurePicker,
873
- externalPicker,
874
- onOpenChange,
875
- open,
876
- standaloneHandoffId,
877
- targetOrigin,
878
- ]);
879
-
880
- const openStandalonePicker = useCallback(
881
- (event: React.MouseEvent<HTMLAnchorElement>) => {
882
- if (!standaloneHandoffId) return;
883
- event.preventDefault();
884
- const pickerWindow = window.open(standaloneUrl, "_blank");
885
- if (!pickerWindow) return;
886
- standaloneWindowRef.current = pickerWindow;
887
- onOpenChange(false);
888
- },
889
- [onOpenChange, standaloneHandoffId, standaloneUrl],
890
- );
891
-
892
- if (!open || typeof document === "undefined") return null;
893
-
894
- return createPortal(
895
- <div
896
- className="fixed inset-0 z-[280] flex items-center justify-center bg-black/50 p-3"
897
- role="dialog"
898
- aria-modal="true"
899
- aria-labelledby="composer-assets-picker-title"
900
- onMouseDown={(event) => {
901
- if (event.target === event.currentTarget) onOpenChange(false);
902
- }}
903
- >
904
- <div className="flex h-[min(86vh,760px)] w-[min(96vw,1040px)] flex-col overflow-hidden rounded-xl border border-border bg-background shadow-2xl">
905
- <div className="flex h-12 shrink-0 items-center justify-between border-b border-border px-4">
906
- <div
907
- id="composer-assets-picker-title"
908
- className="text-sm font-medium text-foreground"
909
- >
910
- Generate image
911
- </div>
912
- <button
913
- type="button"
914
- onClick={() => onOpenChange(false)}
915
- className="flex h-8 w-8 items-center justify-center rounded-md text-muted-foreground hover:bg-accent hover:text-foreground"
916
- aria-label="Close image picker"
917
- >
918
- <IconX className="h-4 w-4" />
919
- </button>
920
- </div>
921
- {externalPicker ? (
922
- <div className="flex min-h-0 flex-1 flex-col items-center justify-center gap-3 p-8 text-center">
923
- <div className="max-w-md text-sm text-muted-foreground">
924
- Open Assets in a new tab to sign in and choose an image securely.
925
- </div>
926
- <a
927
- href={standaloneUrl}
928
- target="_blank"
929
- onClick={openStandalonePicker}
930
- className="inline-flex h-9 items-center justify-center rounded-md bg-primary px-4 text-sm font-medium text-primary-foreground hover:bg-primary/90"
931
- >
932
- Open Assets image picker
933
- </a>
934
- </div>
935
- ) : targetOrigin ? (
936
- <div className="relative min-h-0 flex-1 overflow-hidden bg-background">
937
- {!pickerReady && <AssetsPickerLoadingSkeleton />}
938
- <iframe
939
- ref={iframeRef}
940
- src={iframeUrl}
941
- title="Assets image picker"
942
- className={cn(
943
- "absolute inset-0 h-full w-full border-0 bg-background transition-opacity duration-150",
944
- pickerReady ? "opacity-100" : "pointer-events-none opacity-0",
945
- )}
946
- sandbox="allow-scripts allow-same-origin allow-forms allow-popups allow-downloads"
947
- allow="clipboard-read; clipboard-write; microphone; fullscreen"
948
- referrerPolicy="strict-origin-when-cross-origin"
949
- onLoad={() => {
950
- configurePicker();
951
- setPickerReady(true);
952
- }}
953
- />
954
- </div>
955
- ) : (
956
- <div className="flex min-h-0 flex-1 items-center justify-center p-8 text-center text-sm text-muted-foreground">
957
- The configured image picker URL is not valid.
958
- </div>
959
- )}
960
- </div>
961
- </div>,
962
- document.body,
963
- );
964
- }
965
-
966
- function AssetsPickerLoadingSkeleton() {
967
- return (
968
- <div
969
- className="absolute inset-0 flex flex-col gap-5 p-5"
970
- role="status"
971
- aria-label="Loading Assets picker"
972
- >
973
- <div className="flex items-center gap-3">
974
- <div className="h-9 flex-1 animate-pulse rounded-md bg-muted" />
975
- <div className="h-9 w-24 animate-pulse rounded-md bg-muted" />
976
- </div>
977
- <div className="grid min-h-0 flex-1 grid-cols-2 gap-4 sm:grid-cols-3 lg:grid-cols-4">
978
- {Array.from({ length: 8 }).map((_, index) => (
979
- <div key={index} className="flex min-w-0 flex-col gap-2">
980
- <div className="aspect-square w-full animate-pulse rounded-lg bg-muted" />
981
- <div className="h-3 w-3/4 animate-pulse rounded bg-muted" />
982
- <div className="h-3 w-1/2 animate-pulse rounded bg-muted" />
983
- </div>
984
- ))}
985
- </div>
986
- </div>
987
- );
988
- }