@agent-native/toolkit 0.0.0-beta-20260819143124

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 (1070) hide show
  1. package/README.md +151 -0
  2. package/agent-native.eject.json +588 -0
  3. package/dist/app-shell/header-actions.d.ts +18 -0
  4. package/dist/app-shell/header-actions.d.ts.map +1 -0
  5. package/dist/app-shell/header-actions.js +52 -0
  6. package/dist/app-shell/header-actions.js.map +1 -0
  7. package/dist/app-shell/index.d.ts +3 -0
  8. package/dist/app-shell/index.d.ts.map +1 -0
  9. package/dist/app-shell/index.js +3 -0
  10. package/dist/app-shell/index.js.map +1 -0
  11. package/dist/app-shell/sidebar-footer-actions.d.ts +14 -0
  12. package/dist/app-shell/sidebar-footer-actions.d.ts.map +1 -0
  13. package/dist/app-shell/sidebar-footer-actions.js +10 -0
  14. package/dist/app-shell/sidebar-footer-actions.js.map +1 -0
  15. package/dist/app-shell/sidebar-footer-actions.spec.d.ts +2 -0
  16. package/dist/app-shell/sidebar-footer-actions.spec.d.ts.map +1 -0
  17. package/dist/app-shell/sidebar-footer-actions.spec.js +43 -0
  18. package/dist/app-shell/sidebar-footer-actions.spec.js.map +1 -0
  19. package/dist/canvas-annotations/CanvasCommentPins.d.ts +68 -0
  20. package/dist/canvas-annotations/CanvasCommentPins.d.ts.map +1 -0
  21. package/dist/canvas-annotations/CanvasCommentPins.js +513 -0
  22. package/dist/canvas-annotations/CanvasCommentPins.js.map +1 -0
  23. package/dist/canvas-annotations/DrawOverlay.d.ts +108 -0
  24. package/dist/canvas-annotations/DrawOverlay.d.ts.map +1 -0
  25. package/dist/canvas-annotations/DrawOverlay.js +746 -0
  26. package/dist/canvas-annotations/DrawOverlay.js.map +1 -0
  27. package/dist/canvas-annotations/DrawOverlay.spec.d.ts +2 -0
  28. package/dist/canvas-annotations/DrawOverlay.spec.d.ts.map +1 -0
  29. package/dist/canvas-annotations/DrawOverlay.spec.js +111 -0
  30. package/dist/canvas-annotations/DrawOverlay.spec.js.map +1 -0
  31. package/dist/canvas-annotations/index.d.ts +4 -0
  32. package/dist/canvas-annotations/index.d.ts.map +1 -0
  33. package/dist/canvas-annotations/index.js +3 -0
  34. package/dist/canvas-annotations/index.js.map +1 -0
  35. package/dist/canvas-annotations/types.d.ts +8 -0
  36. package/dist/canvas-annotations/types.d.ts.map +1 -0
  37. package/dist/canvas-annotations/types.js +2 -0
  38. package/dist/canvas-annotations/types.js.map +1 -0
  39. package/dist/canvas-interactions/canvas-interactions.d.ts +334 -0
  40. package/dist/canvas-interactions/canvas-interactions.d.ts.map +1 -0
  41. package/dist/canvas-interactions/canvas-interactions.js +486 -0
  42. package/dist/canvas-interactions/canvas-interactions.js.map +1 -0
  43. package/dist/canvas-interactions/canvas-interactions.spec.d.ts +2 -0
  44. package/dist/canvas-interactions/canvas-interactions.spec.d.ts.map +1 -0
  45. package/dist/canvas-interactions/canvas-interactions.spec.js +593 -0
  46. package/dist/canvas-interactions/canvas-interactions.spec.js.map +1 -0
  47. package/dist/canvas-interactions/index.d.ts +2 -0
  48. package/dist/canvas-interactions/index.d.ts.map +1 -0
  49. package/dist/canvas-interactions/index.js +2 -0
  50. package/dist/canvas-interactions/index.js.map +1 -0
  51. package/dist/chat-history/ChatHistoryList.d.ts +103 -0
  52. package/dist/chat-history/ChatHistoryList.d.ts.map +1 -0
  53. package/dist/chat-history/ChatHistoryList.js +102 -0
  54. package/dist/chat-history/ChatHistoryList.js.map +1 -0
  55. package/dist/chat-history/ChatHistoryList.spec.d.ts +2 -0
  56. package/dist/chat-history/ChatHistoryList.spec.d.ts.map +1 -0
  57. package/dist/chat-history/ChatHistoryList.spec.js +293 -0
  58. package/dist/chat-history/ChatHistoryList.spec.js.map +1 -0
  59. package/dist/chat-history/ChatHistoryRail.d.ts +33 -0
  60. package/dist/chat-history/ChatHistoryRail.d.ts.map +1 -0
  61. package/dist/chat-history/ChatHistoryRail.js +35 -0
  62. package/dist/chat-history/ChatHistoryRail.js.map +1 -0
  63. package/dist/chat-history/ChatHistoryRail.spec.d.ts +2 -0
  64. package/dist/chat-history/ChatHistoryRail.spec.d.ts.map +1 -0
  65. package/dist/chat-history/ChatHistoryRail.spec.js +157 -0
  66. package/dist/chat-history/ChatHistoryRail.spec.js.map +1 -0
  67. package/dist/chat-history/index.d.ts +4 -0
  68. package/dist/chat-history/index.d.ts.map +1 -0
  69. package/dist/chat-history/index.js +4 -0
  70. package/dist/chat-history/index.js.map +1 -0
  71. package/dist/chat-history/useChatHistoryRailController.d.ts +26 -0
  72. package/dist/chat-history/useChatHistoryRailController.d.ts.map +1 -0
  73. package/dist/chat-history/useChatHistoryRailController.js +36 -0
  74. package/dist/chat-history/useChatHistoryRailController.js.map +1 -0
  75. package/dist/chat-history/useChatHistoryRailController.spec.d.ts +2 -0
  76. package/dist/chat-history/useChatHistoryRailController.spec.d.ts.map +1 -0
  77. package/dist/chat-history/useChatHistoryRailController.spec.js +101 -0
  78. package/dist/chat-history/useChatHistoryRailController.spec.js.map +1 -0
  79. package/dist/chat-history.css +469 -0
  80. package/dist/collab-ui/AgentPresenceChip.d.ts +12 -0
  81. package/dist/collab-ui/AgentPresenceChip.d.ts.map +1 -0
  82. package/dist/collab-ui/AgentPresenceChip.js +42 -0
  83. package/dist/collab-ui/AgentPresenceChip.js.map +1 -0
  84. package/dist/collab-ui/LiveCursorOverlay.d.ts +46 -0
  85. package/dist/collab-ui/LiveCursorOverlay.d.ts.map +1 -0
  86. package/dist/collab-ui/LiveCursorOverlay.js +125 -0
  87. package/dist/collab-ui/LiveCursorOverlay.js.map +1 -0
  88. package/dist/collab-ui/PresenceBar.d.ts +30 -0
  89. package/dist/collab-ui/PresenceBar.d.ts.map +1 -0
  90. package/dist/collab-ui/PresenceBar.js +172 -0
  91. package/dist/collab-ui/PresenceBar.js.map +1 -0
  92. package/dist/collab-ui/PresenceBar.spec.d.ts +2 -0
  93. package/dist/collab-ui/PresenceBar.spec.d.ts.map +1 -0
  94. package/dist/collab-ui/PresenceBar.spec.js +30 -0
  95. package/dist/collab-ui/PresenceBar.spec.js.map +1 -0
  96. package/dist/collab-ui/RecentEditHighlights.d.ts +46 -0
  97. package/dist/collab-ui/RecentEditHighlights.d.ts.map +1 -0
  98. package/dist/collab-ui/RecentEditHighlights.js +154 -0
  99. package/dist/collab-ui/RecentEditHighlights.js.map +1 -0
  100. package/dist/collab-ui/RemoteSelectionRings.d.ts +53 -0
  101. package/dist/collab-ui/RemoteSelectionRings.d.ts.map +1 -0
  102. package/dist/collab-ui/RemoteSelectionRings.js +130 -0
  103. package/dist/collab-ui/RemoteSelectionRings.js.map +1 -0
  104. package/dist/collab-ui/agent-identity.d.ts +9 -0
  105. package/dist/collab-ui/agent-identity.d.ts.map +1 -0
  106. package/dist/collab-ui/agent-identity.js +9 -0
  107. package/dist/collab-ui/agent-identity.js.map +1 -0
  108. package/dist/collab-ui/index.d.ts +9 -0
  109. package/dist/collab-ui/index.d.ts.map +1 -0
  110. package/dist/collab-ui/index.js +9 -0
  111. package/dist/collab-ui/index.js.map +1 -0
  112. package/dist/collab-ui/lead-client.d.ts +3 -0
  113. package/dist/collab-ui/lead-client.d.ts.map +1 -0
  114. package/dist/collab-ui/lead-client.js +29 -0
  115. package/dist/collab-ui/lead-client.js.map +1 -0
  116. package/dist/collab-ui/types.d.ts +48 -0
  117. package/dist/collab-ui/types.d.ts.map +1 -0
  118. package/dist/collab-ui/types.js +52 -0
  119. package/dist/collab-ui/types.js.map +1 -0
  120. package/dist/collab-ui/types.spec.d.ts +2 -0
  121. package/dist/collab-ui/types.spec.d.ts.map +1 -0
  122. package/dist/collab-ui/types.spec.js +15 -0
  123. package/dist/collab-ui/types.spec.js.map +1 -0
  124. package/dist/composer/AgentComposerFrame.d.ts +19 -0
  125. package/dist/composer/AgentComposerFrame.d.ts.map +1 -0
  126. package/dist/composer/AgentComposerFrame.js +17 -0
  127. package/dist/composer/AgentComposerFrame.js.map +1 -0
  128. package/dist/composer/ComposerPlusMenu.d.ts +30 -0
  129. package/dist/composer/ComposerPlusMenu.d.ts.map +1 -0
  130. package/dist/composer/ComposerPlusMenu.js +635 -0
  131. package/dist/composer/ComposerPlusMenu.js.map +1 -0
  132. package/dist/composer/ComposerPlusMenu.spec.d.ts +2 -0
  133. package/dist/composer/ComposerPlusMenu.spec.d.ts.map +1 -0
  134. package/dist/composer/ComposerPlusMenu.spec.js +12 -0
  135. package/dist/composer/ComposerPlusMenu.spec.js.map +1 -0
  136. package/dist/composer/MentionPopover.d.ts +29 -0
  137. package/dist/composer/MentionPopover.d.ts.map +1 -0
  138. package/dist/composer/MentionPopover.js +221 -0
  139. package/dist/composer/MentionPopover.js.map +1 -0
  140. package/dist/composer/PastedTextChip.d.ts +9 -0
  141. package/dist/composer/PastedTextChip.d.ts.map +1 -0
  142. package/dist/composer/PastedTextChip.js +71 -0
  143. package/dist/composer/PastedTextChip.js.map +1 -0
  144. package/dist/composer/PastedTextChip.spec.d.ts +2 -0
  145. package/dist/composer/PastedTextChip.spec.d.ts.map +1 -0
  146. package/dist/composer/PastedTextChip.spec.js +42 -0
  147. package/dist/composer/PastedTextChip.spec.js.map +1 -0
  148. package/dist/composer/PromptComposer.d.ts +151 -0
  149. package/dist/composer/PromptComposer.d.ts.map +1 -0
  150. package/dist/composer/PromptComposer.js +322 -0
  151. package/dist/composer/PromptComposer.js.map +1 -0
  152. package/dist/composer/PromptComposer.spec.d.ts +2 -0
  153. package/dist/composer/PromptComposer.spec.d.ts.map +1 -0
  154. package/dist/composer/PromptComposer.spec.js +87 -0
  155. package/dist/composer/PromptComposer.spec.js.map +1 -0
  156. package/dist/composer/RealtimeVoiceMode.d.ts +108 -0
  157. package/dist/composer/RealtimeVoiceMode.d.ts.map +1 -0
  158. package/dist/composer/RealtimeVoiceMode.js +312 -0
  159. package/dist/composer/RealtimeVoiceMode.js.map +1 -0
  160. package/dist/composer/RealtimeVoiceMode.spec.d.ts +2 -0
  161. package/dist/composer/RealtimeVoiceMode.spec.d.ts.map +1 -0
  162. package/dist/composer/RealtimeVoiceMode.spec.js +540 -0
  163. package/dist/composer/RealtimeVoiceMode.spec.js.map +1 -0
  164. package/dist/composer/TiptapComposer.d.ts +288 -0
  165. package/dist/composer/TiptapComposer.d.ts.map +1 -0
  166. package/dist/composer/TiptapComposer.js +2233 -0
  167. package/dist/composer/TiptapComposer.js.map +1 -0
  168. package/dist/composer/TiptapComposer.spec.d.ts +2 -0
  169. package/dist/composer/TiptapComposer.spec.d.ts.map +1 -0
  170. package/dist/composer/TiptapComposer.spec.js +415 -0
  171. package/dist/composer/TiptapComposer.spec.js.map +1 -0
  172. package/dist/composer/VoiceButton.d.ts +27 -0
  173. package/dist/composer/VoiceButton.d.ts.map +1 -0
  174. package/dist/composer/VoiceButton.js +151 -0
  175. package/dist/composer/VoiceButton.js.map +1 -0
  176. package/dist/composer/VoiceButton.spec.d.ts +2 -0
  177. package/dist/composer/VoiceButton.spec.d.ts.map +1 -0
  178. package/dist/composer/VoiceButton.spec.js +27 -0
  179. package/dist/composer/VoiceButton.spec.js.map +1 -0
  180. package/dist/composer/asset-picker-url.d.ts +16 -0
  181. package/dist/composer/asset-picker-url.d.ts.map +1 -0
  182. package/dist/composer/asset-picker-url.js +64 -0
  183. package/dist/composer/asset-picker-url.js.map +1 -0
  184. package/dist/composer/asset-picker-url.spec.d.ts +2 -0
  185. package/dist/composer/asset-picker-url.spec.d.ts.map +1 -0
  186. package/dist/composer/asset-picker-url.spec.js +23 -0
  187. package/dist/composer/asset-picker-url.spec.js.map +1 -0
  188. package/dist/composer/attachment-accept.d.ts +9 -0
  189. package/dist/composer/attachment-accept.d.ts.map +1 -0
  190. package/dist/composer/attachment-accept.js +69 -0
  191. package/dist/composer/attachment-accept.js.map +1 -0
  192. package/dist/composer/attachment-accept.spec.d.ts +2 -0
  193. package/dist/composer/attachment-accept.spec.d.ts.map +1 -0
  194. package/dist/composer/attachment-accept.spec.js +24 -0
  195. package/dist/composer/attachment-accept.spec.js.map +1 -0
  196. package/dist/composer/draft-key.d.ts +2 -0
  197. package/dist/composer/draft-key.d.ts.map +1 -0
  198. package/dist/composer/draft-key.js +8 -0
  199. package/dist/composer/draft-key.js.map +1 -0
  200. package/dist/composer/draft-key.spec.d.ts +2 -0
  201. package/dist/composer/draft-key.spec.d.ts.map +1 -0
  202. package/dist/composer/draft-key.spec.js +13 -0
  203. package/dist/composer/draft-key.spec.js.map +1 -0
  204. package/dist/composer/extensions/FileReference.d.ts +3 -0
  205. package/dist/composer/extensions/FileReference.d.ts.map +1 -0
  206. package/dist/composer/extensions/FileReference.js +36 -0
  207. package/dist/composer/extensions/FileReference.js.map +1 -0
  208. package/dist/composer/extensions/MentionReference.d.ts +3 -0
  209. package/dist/composer/extensions/MentionReference.d.ts.map +1 -0
  210. package/dist/composer/extensions/MentionReference.js +66 -0
  211. package/dist/composer/extensions/MentionReference.js.map +1 -0
  212. package/dist/composer/extensions/SkillReference.d.ts +3 -0
  213. package/dist/composer/extensions/SkillReference.d.ts.map +1 -0
  214. package/dist/composer/extensions/SkillReference.js +40 -0
  215. package/dist/composer/extensions/SkillReference.js.map +1 -0
  216. package/dist/composer/index.d.ts +16 -0
  217. package/dist/composer/index.d.ts.map +1 -0
  218. package/dist/composer/index.js +14 -0
  219. package/dist/composer/index.js.map +1 -0
  220. package/dist/composer/model-selection.d.ts +12 -0
  221. package/dist/composer/model-selection.d.ts.map +1 -0
  222. package/dist/composer/model-selection.js +31 -0
  223. package/dist/composer/model-selection.js.map +1 -0
  224. package/dist/composer/model-selection.spec.d.ts +2 -0
  225. package/dist/composer/model-selection.spec.d.ts.map +1 -0
  226. package/dist/composer/model-selection.spec.js +38 -0
  227. package/dist/composer/model-selection.spec.js.map +1 -0
  228. package/dist/composer/pasted-text.d.ts +31 -0
  229. package/dist/composer/pasted-text.d.ts.map +1 -0
  230. package/dist/composer/pasted-text.js +130 -0
  231. package/dist/composer/pasted-text.js.map +1 -0
  232. package/dist/composer/pasted-text.spec.d.ts +2 -0
  233. package/dist/composer/pasted-text.spec.d.ts.map +1 -0
  234. package/dist/composer/pasted-text.spec.js +107 -0
  235. package/dist/composer/pasted-text.spec.js.map +1 -0
  236. package/dist/composer/prompt-attachments.d.ts +18 -0
  237. package/dist/composer/prompt-attachments.d.ts.map +1 -0
  238. package/dist/composer/prompt-attachments.js +65 -0
  239. package/dist/composer/prompt-attachments.js.map +1 -0
  240. package/dist/composer/prompt-attachments.spec.d.ts +2 -0
  241. package/dist/composer/prompt-attachments.spec.d.ts.map +1 -0
  242. package/dist/composer/prompt-attachments.spec.js +63 -0
  243. package/dist/composer/prompt-attachments.spec.js.map +1 -0
  244. package/dist/composer/realtime-voice-audio-level.d.ts +14 -0
  245. package/dist/composer/realtime-voice-audio-level.d.ts.map +1 -0
  246. package/dist/composer/realtime-voice-audio-level.js +48 -0
  247. package/dist/composer/realtime-voice-audio-level.js.map +1 -0
  248. package/dist/composer/realtime-voice-audio-level.spec.d.ts +2 -0
  249. package/dist/composer/realtime-voice-audio-level.spec.d.ts.map +1 -0
  250. package/dist/composer/realtime-voice-audio-level.spec.js +32 -0
  251. package/dist/composer/realtime-voice-audio-level.spec.js.map +1 -0
  252. package/dist/composer/realtime-voice-transcript.d.ts +26 -0
  253. package/dist/composer/realtime-voice-transcript.d.ts.map +1 -0
  254. package/dist/composer/realtime-voice-transcript.js +103 -0
  255. package/dist/composer/realtime-voice-transcript.js.map +1 -0
  256. package/dist/composer/realtime-voice-transcript.spec.d.ts +2 -0
  257. package/dist/composer/realtime-voice-transcript.spec.d.ts.map +1 -0
  258. package/dist/composer/realtime-voice-transcript.spec.js +76 -0
  259. package/dist/composer/realtime-voice-transcript.spec.js.map +1 -0
  260. package/dist/composer/runtime-adapters.d.ts +169 -0
  261. package/dist/composer/runtime-adapters.d.ts.map +1 -0
  262. package/dist/composer/runtime-adapters.js +141 -0
  263. package/dist/composer/runtime-adapters.js.map +1 -0
  264. package/dist/composer/runtime-adapters.spec.d.ts +2 -0
  265. package/dist/composer/runtime-adapters.spec.d.ts.map +1 -0
  266. package/dist/composer/runtime-adapters.spec.js +69 -0
  267. package/dist/composer/runtime-adapters.spec.js.map +1 -0
  268. package/dist/composer/types.d.ts +60 -0
  269. package/dist/composer/types.d.ts.map +1 -0
  270. package/dist/composer/types.js +2 -0
  271. package/dist/composer/types.js.map +1 -0
  272. package/dist/composer/use-file-search.d.ts +6 -0
  273. package/dist/composer/use-file-search.d.ts.map +1 -0
  274. package/dist/composer/use-file-search.js +53 -0
  275. package/dist/composer/use-file-search.js.map +1 -0
  276. package/dist/composer/use-mention-search.d.ts +6 -0
  277. package/dist/composer/use-mention-search.d.ts.map +1 -0
  278. package/dist/composer/use-mention-search.js +75 -0
  279. package/dist/composer/use-mention-search.js.map +1 -0
  280. package/dist/composer/use-skills.d.ts +7 -0
  281. package/dist/composer/use-skills.d.ts.map +1 -0
  282. package/dist/composer/use-skills.js +40 -0
  283. package/dist/composer/use-skills.js.map +1 -0
  284. package/dist/composer/useRealtimeVoiceMode.d.ts +189 -0
  285. package/dist/composer/useRealtimeVoiceMode.d.ts.map +1 -0
  286. package/dist/composer/useRealtimeVoiceMode.js +1899 -0
  287. package/dist/composer/useRealtimeVoiceMode.js.map +1 -0
  288. package/dist/composer/useRealtimeVoiceMode.spec.d.ts +2 -0
  289. package/dist/composer/useRealtimeVoiceMode.spec.d.ts.map +1 -0
  290. package/dist/composer/useRealtimeVoiceMode.spec.js +716 -0
  291. package/dist/composer/useRealtimeVoiceMode.spec.js.map +1 -0
  292. package/dist/composer/useVoiceDictation.browser.spec.d.ts +2 -0
  293. package/dist/composer/useVoiceDictation.browser.spec.d.ts.map +1 -0
  294. package/dist/composer/useVoiceDictation.browser.spec.js +220 -0
  295. package/dist/composer/useVoiceDictation.browser.spec.js.map +1 -0
  296. package/dist/composer/useVoiceDictation.d.ts +58 -0
  297. package/dist/composer/useVoiceDictation.d.ts.map +1 -0
  298. package/dist/composer/useVoiceDictation.js +1058 -0
  299. package/dist/composer/useVoiceDictation.js.map +1 -0
  300. package/dist/composer/useVoiceDictation.spec.d.ts +2 -0
  301. package/dist/composer/useVoiceDictation.spec.d.ts.map +1 -0
  302. package/dist/composer/useVoiceDictation.spec.js +32 -0
  303. package/dist/composer/useVoiceDictation.spec.js.map +1 -0
  304. package/dist/conformance/__fixtures__/css-in-js-adapter.d.ts +7 -0
  305. package/dist/conformance/__fixtures__/css-in-js-adapter.d.ts.map +1 -0
  306. package/dist/conformance/__fixtures__/css-in-js-adapter.js +84 -0
  307. package/dist/conformance/__fixtures__/css-in-js-adapter.js.map +1 -0
  308. package/dist/conformance/conformance.spec.d.ts +2 -0
  309. package/dist/conformance/conformance.spec.d.ts.map +1 -0
  310. package/dist/conformance/conformance.spec.js +87 -0
  311. package/dist/conformance/conformance.spec.js.map +1 -0
  312. package/dist/conformance/index.d.ts +4 -0
  313. package/dist/conformance/index.d.ts.map +1 -0
  314. package/dist/conformance/index.js +4 -0
  315. package/dist/conformance/index.js.map +1 -0
  316. package/dist/conformance/runner.d.ts +12 -0
  317. package/dist/conformance/runner.d.ts.map +1 -0
  318. package/dist/conformance/runner.js +515 -0
  319. package/dist/conformance/runner.js.map +1 -0
  320. package/dist/conformance/types.d.ts +26 -0
  321. package/dist/conformance/types.d.ts.map +1 -0
  322. package/dist/conformance/types.js +13 -0
  323. package/dist/conformance/types.js.map +1 -0
  324. package/dist/conformance/version.d.ts +6 -0
  325. package/dist/conformance/version.d.ts.map +1 -0
  326. package/dist/conformance/version.js +14 -0
  327. package/dist/conformance/version.js.map +1 -0
  328. package/dist/context-ui/ContextMeter.d.ts +11 -0
  329. package/dist/context-ui/ContextMeter.d.ts.map +1 -0
  330. package/dist/context-ui/ContextMeter.js +40 -0
  331. package/dist/context-ui/ContextMeter.js.map +1 -0
  332. package/dist/context-ui/ContextMeter.spec.d.ts +2 -0
  333. package/dist/context-ui/ContextMeter.spec.d.ts.map +1 -0
  334. package/dist/context-ui/ContextMeter.spec.js +52 -0
  335. package/dist/context-ui/ContextMeter.spec.js.map +1 -0
  336. package/dist/context-ui/ContextSegmentRow.d.ts +16 -0
  337. package/dist/context-ui/ContextSegmentRow.d.ts.map +1 -0
  338. package/dist/context-ui/ContextSegmentRow.js +92 -0
  339. package/dist/context-ui/ContextSegmentRow.js.map +1 -0
  340. package/dist/context-ui/ContextTreemap.d.ts +8 -0
  341. package/dist/context-ui/ContextTreemap.d.ts.map +1 -0
  342. package/dist/context-ui/ContextTreemap.js +58 -0
  343. package/dist/context-ui/ContextTreemap.js.map +1 -0
  344. package/dist/context-ui/ContextXRayPanel.d.ts +14 -0
  345. package/dist/context-ui/ContextXRayPanel.d.ts.map +1 -0
  346. package/dist/context-ui/ContextXRayPanel.js +209 -0
  347. package/dist/context-ui/ContextXRayPanel.js.map +1 -0
  348. package/dist/context-ui/format.d.ts +6 -0
  349. package/dist/context-ui/format.d.ts.map +1 -0
  350. package/dist/context-ui/format.js +58 -0
  351. package/dist/context-ui/format.js.map +1 -0
  352. package/dist/context-ui/index.d.ts +7 -0
  353. package/dist/context-ui/index.d.ts.map +1 -0
  354. package/dist/context-ui/index.js +6 -0
  355. package/dist/context-ui/index.js.map +1 -0
  356. package/dist/context-ui/types.d.ts +41 -0
  357. package/dist/context-ui/types.d.ts.map +1 -0
  358. package/dist/context-ui/types.js +8 -0
  359. package/dist/context-ui/types.js.map +1 -0
  360. package/dist/dashboard/DataTable.d.ts +20 -0
  361. package/dist/dashboard/DataTable.d.ts.map +1 -0
  362. package/dist/dashboard/DataTable.js +87 -0
  363. package/dist/dashboard/DataTable.js.map +1 -0
  364. package/dist/dashboard/DateRangePicker.d.ts +15 -0
  365. package/dist/dashboard/DateRangePicker.d.ts.map +1 -0
  366. package/dist/dashboard/DateRangePicker.js +15 -0
  367. package/dist/dashboard/DateRangePicker.js.map +1 -0
  368. package/dist/dashboard/GenericChartPanel.d.ts +57 -0
  369. package/dist/dashboard/GenericChartPanel.d.ts.map +1 -0
  370. package/dist/dashboard/GenericChartPanel.js +119 -0
  371. package/dist/dashboard/GenericChartPanel.js.map +1 -0
  372. package/dist/dashboard/GenericChartPanel.spec.d.ts +2 -0
  373. package/dist/dashboard/GenericChartPanel.spec.d.ts.map +1 -0
  374. package/dist/dashboard/GenericChartPanel.spec.js +41 -0
  375. package/dist/dashboard/GenericChartPanel.spec.js.map +1 -0
  376. package/dist/dashboard/MetricCard.d.ts +14 -0
  377. package/dist/dashboard/MetricCard.d.ts.map +1 -0
  378. package/dist/dashboard/MetricCard.js +10 -0
  379. package/dist/dashboard/MetricCard.js.map +1 -0
  380. package/dist/dashboard/StatsCard.d.ts +16 -0
  381. package/dist/dashboard/StatsCard.d.ts.map +1 -0
  382. package/dist/dashboard/StatsCard.js +8 -0
  383. package/dist/dashboard/StatsCard.js.map +1 -0
  384. package/dist/dashboard/dashboard-layout.d.ts +49 -0
  385. package/dist/dashboard/dashboard-layout.d.ts.map +1 -0
  386. package/dist/dashboard/dashboard-layout.js +231 -0
  387. package/dist/dashboard/dashboard-layout.js.map +1 -0
  388. package/dist/dashboard/dashboard-layout.spec.d.ts +2 -0
  389. package/dist/dashboard/dashboard-layout.spec.d.ts.map +1 -0
  390. package/dist/dashboard/dashboard-layout.spec.js +52 -0
  391. package/dist/dashboard/dashboard-layout.spec.js.map +1 -0
  392. package/dist/dashboard/index.d.ts +7 -0
  393. package/dist/dashboard/index.d.ts.map +1 -0
  394. package/dist/dashboard/index.js +7 -0
  395. package/dist/dashboard/index.js.map +1 -0
  396. package/dist/data-grid/DataGrid.d.ts +92 -0
  397. package/dist/data-grid/DataGrid.d.ts.map +1 -0
  398. package/dist/data-grid/DataGrid.js +315 -0
  399. package/dist/data-grid/DataGrid.js.map +1 -0
  400. package/dist/data-grid/DataGrid.spec.d.ts +2 -0
  401. package/dist/data-grid/DataGrid.spec.d.ts.map +1 -0
  402. package/dist/data-grid/DataGrid.spec.js +134 -0
  403. package/dist/data-grid/DataGrid.spec.js.map +1 -0
  404. package/dist/data-grid/index.d.ts +2 -0
  405. package/dist/data-grid/index.d.ts.map +1 -0
  406. package/dist/data-grid/index.js +2 -0
  407. package/dist/data-grid/index.js.map +1 -0
  408. package/dist/design-system/components.d.ts +58 -0
  409. package/dist/design-system/components.d.ts.map +1 -0
  410. package/dist/design-system/components.js +88 -0
  411. package/dist/design-system/components.js.map +1 -0
  412. package/dist/design-system/context.d.ts +11 -0
  413. package/dist/design-system/context.d.ts.map +1 -0
  414. package/dist/design-system/context.js +17 -0
  415. package/dist/design-system/context.js.map +1 -0
  416. package/dist/design-system/default-adapter.d.ts +3 -0
  417. package/dist/design-system/default-adapter.d.ts.map +1 -0
  418. package/dist/design-system/default-adapter.js +172 -0
  419. package/dist/design-system/default-adapter.js.map +1 -0
  420. package/dist/design-system/default-adapter.spec.d.ts +2 -0
  421. package/dist/design-system/default-adapter.spec.d.ts.map +1 -0
  422. package/dist/design-system/default-adapter.spec.js +108 -0
  423. package/dist/design-system/default-adapter.spec.js.map +1 -0
  424. package/dist/design-system/definition.d.ts +9 -0
  425. package/dist/design-system/definition.d.ts.map +1 -0
  426. package/dist/design-system/definition.js +4 -0
  427. package/dist/design-system/definition.js.map +1 -0
  428. package/dist/design-system/design-system.spec.d.ts +2 -0
  429. package/dist/design-system/design-system.spec.d.ts.map +1 -0
  430. package/dist/design-system/design-system.spec.js +208 -0
  431. package/dist/design-system/design-system.spec.js.map +1 -0
  432. package/dist/design-system/error-boundary.d.ts +18 -0
  433. package/dist/design-system/error-boundary.d.ts.map +1 -0
  434. package/dist/design-system/error-boundary.js +16 -0
  435. package/dist/design-system/error-boundary.js.map +1 -0
  436. package/dist/design-system/index.d.ts +8 -0
  437. package/dist/design-system/index.d.ts.map +1 -0
  438. package/dist/design-system/index.js +8 -0
  439. package/dist/design-system/index.js.map +1 -0
  440. package/dist/design-system/theme.d.ts +30 -0
  441. package/dist/design-system/theme.d.ts.map +1 -0
  442. package/dist/design-system/theme.js +95 -0
  443. package/dist/design-system/theme.js.map +1 -0
  444. package/dist/design-system/theme.spec.d.ts +2 -0
  445. package/dist/design-system/theme.spec.d.ts.map +1 -0
  446. package/dist/design-system/theme.spec.js +43 -0
  447. package/dist/design-system/theme.spec.js.map +1 -0
  448. package/dist/design-system/types.d.ts +292 -0
  449. package/dist/design-system/types.d.ts.map +1 -0
  450. package/dist/design-system/types.js +2 -0
  451. package/dist/design-system/types.js.map +1 -0
  452. package/dist/design-tweaks/index.d.ts +2 -0
  453. package/dist/design-tweaks/index.d.ts.map +1 -0
  454. package/dist/design-tweaks/index.js +2 -0
  455. package/dist/design-tweaks/index.js.map +1 -0
  456. package/dist/design-tweaks/scrub-input-utils.d.ts +61 -0
  457. package/dist/design-tweaks/scrub-input-utils.d.ts.map +1 -0
  458. package/dist/design-tweaks/scrub-input-utils.js +235 -0
  459. package/dist/design-tweaks/scrub-input-utils.js.map +1 -0
  460. package/dist/design-tweaks/scrub-input.d.ts +70 -0
  461. package/dist/design-tweaks/scrub-input.d.ts.map +1 -0
  462. package/dist/design-tweaks/scrub-input.js +319 -0
  463. package/dist/design-tweaks/scrub-input.js.map +1 -0
  464. package/dist/design-tweaks/visual-style-controls.d.ts +90 -0
  465. package/dist/design-tweaks/visual-style-controls.d.ts.map +1 -0
  466. package/dist/design-tweaks/visual-style-controls.js +423 -0
  467. package/dist/design-tweaks/visual-style-controls.js.map +1 -0
  468. package/dist/design-tweaks/visual-style-controls.spec.d.ts +2 -0
  469. package/dist/design-tweaks/visual-style-controls.spec.d.ts.map +1 -0
  470. package/dist/design-tweaks/visual-style-controls.spec.js +84 -0
  471. package/dist/design-tweaks/visual-style-controls.spec.js.map +1 -0
  472. package/dist/editor/BubbleToolbar.d.ts +37 -0
  473. package/dist/editor/BubbleToolbar.d.ts.map +1 -0
  474. package/dist/editor/BubbleToolbar.js +171 -0
  475. package/dist/editor/BubbleToolbar.js.map +1 -0
  476. package/dist/editor/CodeBlockNode.d.ts +49 -0
  477. package/dist/editor/CodeBlockNode.d.ts.map +1 -0
  478. package/dist/editor/CodeBlockNode.js +127 -0
  479. package/dist/editor/CodeBlockNode.js.map +1 -0
  480. package/dist/editor/DragHandle.d.ts +103 -0
  481. package/dist/editor/DragHandle.d.ts.map +1 -0
  482. package/dist/editor/DragHandle.js +1101 -0
  483. package/dist/editor/DragHandle.js.map +1 -0
  484. package/dist/editor/DragHandle.spec.d.ts +2 -0
  485. package/dist/editor/DragHandle.spec.d.ts.map +1 -0
  486. package/dist/editor/DragHandle.spec.js +495 -0
  487. package/dist/editor/DragHandle.spec.js.map +1 -0
  488. package/dist/editor/ImageExtension.d.ts +63 -0
  489. package/dist/editor/ImageExtension.d.ts.map +1 -0
  490. package/dist/editor/ImageExtension.js +243 -0
  491. package/dist/editor/ImageExtension.js.map +1 -0
  492. package/dist/editor/ImageExtension.roundtrip.spec.d.ts +2 -0
  493. package/dist/editor/ImageExtension.roundtrip.spec.d.ts.map +1 -0
  494. package/dist/editor/ImageExtension.roundtrip.spec.js +103 -0
  495. package/dist/editor/ImageExtension.roundtrip.spec.js.map +1 -0
  496. package/dist/editor/RegistryBlockContext.d.ts +68 -0
  497. package/dist/editor/RegistryBlockContext.d.ts.map +1 -0
  498. package/dist/editor/RegistryBlockContext.js +10 -0
  499. package/dist/editor/RegistryBlockContext.js.map +1 -0
  500. package/dist/editor/RegistryBlockNode.d.ts +66 -0
  501. package/dist/editor/RegistryBlockNode.d.ts.map +1 -0
  502. package/dist/editor/RegistryBlockNode.js +406 -0
  503. package/dist/editor/RegistryBlockNode.js.map +1 -0
  504. package/dist/editor/RegistryBlockNode.spec.d.ts +2 -0
  505. package/dist/editor/RegistryBlockNode.spec.d.ts.map +1 -0
  506. package/dist/editor/RegistryBlockNode.spec.js +215 -0
  507. package/dist/editor/RegistryBlockNode.spec.js.map +1 -0
  508. package/dist/editor/RichMarkdownEditor.collab.spec.d.ts +2 -0
  509. package/dist/editor/RichMarkdownEditor.collab.spec.d.ts.map +1 -0
  510. package/dist/editor/RichMarkdownEditor.collab.spec.js +65 -0
  511. package/dist/editor/RichMarkdownEditor.collab.spec.js.map +1 -0
  512. package/dist/editor/RichMarkdownEditor.d.ts +52 -0
  513. package/dist/editor/RichMarkdownEditor.d.ts.map +1 -0
  514. package/dist/editor/RichMarkdownEditor.js +38 -0
  515. package/dist/editor/RichMarkdownEditor.js.map +1 -0
  516. package/dist/editor/RichMarkdownEditor.roundtrip.spec.d.ts +2 -0
  517. package/dist/editor/RichMarkdownEditor.roundtrip.spec.d.ts.map +1 -0
  518. package/dist/editor/RichMarkdownEditor.roundtrip.spec.js +186 -0
  519. package/dist/editor/RichMarkdownEditor.roundtrip.spec.js.map +1 -0
  520. package/dist/editor/RunId.d.ts +28 -0
  521. package/dist/editor/RunId.d.ts.map +1 -0
  522. package/dist/editor/RunId.js +60 -0
  523. package/dist/editor/RunId.js.map +1 -0
  524. package/dist/editor/SharedRichEditor.d.ts +112 -0
  525. package/dist/editor/SharedRichEditor.d.ts.map +1 -0
  526. package/dist/editor/SharedRichEditor.js +159 -0
  527. package/dist/editor/SharedRichEditor.js.map +1 -0
  528. package/dist/editor/SharedRichEditor.spec.d.ts +2 -0
  529. package/dist/editor/SharedRichEditor.spec.d.ts.map +1 -0
  530. package/dist/editor/SharedRichEditor.spec.js +63 -0
  531. package/dist/editor/SharedRichEditor.spec.js.map +1 -0
  532. package/dist/editor/SlashCommandMenu.d.ts +59 -0
  533. package/dist/editor/SlashCommandMenu.d.ts.map +1 -0
  534. package/dist/editor/SlashCommandMenu.js +279 -0
  535. package/dist/editor/SlashCommandMenu.js.map +1 -0
  536. package/dist/editor/SlashCommandMenu.spec.d.ts +2 -0
  537. package/dist/editor/SlashCommandMenu.spec.d.ts.map +1 -0
  538. package/dist/editor/SlashCommandMenu.spec.js +67 -0
  539. package/dist/editor/SlashCommandMenu.spec.js.map +1 -0
  540. package/dist/editor/disableHistory.spec.d.ts +2 -0
  541. package/dist/editor/disableHistory.spec.d.ts.map +1 -0
  542. package/dist/editor/disableHistory.spec.js +73 -0
  543. package/dist/editor/disableHistory.spec.js.map +1 -0
  544. package/dist/editor/extensions.d.ts +178 -0
  545. package/dist/editor/extensions.d.ts.map +1 -0
  546. package/dist/editor/extensions.js +264 -0
  547. package/dist/editor/extensions.js.map +1 -0
  548. package/dist/editor/gfmDoc.d.ts +24 -0
  549. package/dist/editor/gfmDoc.d.ts.map +1 -0
  550. package/dist/editor/gfmDoc.js +83 -0
  551. package/dist/editor/gfmDoc.js.map +1 -0
  552. package/dist/editor/gfmDoc.spec.d.ts +2 -0
  553. package/dist/editor/gfmDoc.spec.d.ts.map +1 -0
  554. package/dist/editor/gfmDoc.spec.js +194 -0
  555. package/dist/editor/gfmDoc.spec.js.map +1 -0
  556. package/dist/editor/index.d.ts +16 -0
  557. package/dist/editor/index.d.ts.map +1 -0
  558. package/dist/editor/index.js +15 -0
  559. package/dist/editor/index.js.map +1 -0
  560. package/dist/editor/registrySlashCommands.d.ts +68 -0
  561. package/dist/editor/registrySlashCommands.d.ts.map +1 -0
  562. package/dist/editor/registrySlashCommands.js +51 -0
  563. package/dist/editor/registrySlashCommands.js.map +1 -0
  564. package/dist/editor/structuralReorderUndo.spec.d.ts +2 -0
  565. package/dist/editor/structuralReorderUndo.spec.d.ts.map +1 -0
  566. package/dist/editor/structuralReorderUndo.spec.js +120 -0
  567. package/dist/editor/structuralReorderUndo.spec.js.map +1 -0
  568. package/dist/editor/surgical-apply.d.ts +66 -0
  569. package/dist/editor/surgical-apply.d.ts.map +1 -0
  570. package/dist/editor/surgical-apply.js +147 -0
  571. package/dist/editor/surgical-apply.js.map +1 -0
  572. package/dist/editor/surgical-apply.spec.d.ts +2 -0
  573. package/dist/editor/surgical-apply.spec.d.ts.map +1 -0
  574. package/dist/editor/surgical-apply.spec.js +257 -0
  575. package/dist/editor/surgical-apply.spec.js.map +1 -0
  576. package/dist/editor/useCollabReconcile.concurrent.spec.d.ts +2 -0
  577. package/dist/editor/useCollabReconcile.concurrent.spec.d.ts.map +1 -0
  578. package/dist/editor/useCollabReconcile.concurrent.spec.js +641 -0
  579. package/dist/editor/useCollabReconcile.concurrent.spec.js.map +1 -0
  580. package/dist/editor/useCollabReconcile.d.ts +117 -0
  581. package/dist/editor/useCollabReconcile.d.ts.map +1 -0
  582. package/dist/editor/useCollabReconcile.idempotent.spec.d.ts +2 -0
  583. package/dist/editor/useCollabReconcile.idempotent.spec.d.ts.map +1 -0
  584. package/dist/editor/useCollabReconcile.idempotent.spec.js +248 -0
  585. package/dist/editor/useCollabReconcile.idempotent.spec.js.map +1 -0
  586. package/dist/editor/useCollabReconcile.js +521 -0
  587. package/dist/editor/useCollabReconcile.js.map +1 -0
  588. package/dist/editor.css +587 -0
  589. package/dist/hooks/index.d.ts +3 -0
  590. package/dist/hooks/index.d.ts.map +1 -0
  591. package/dist/hooks/index.js +3 -0
  592. package/dist/hooks/index.js.map +1 -0
  593. package/dist/hooks/use-mobile.d.ts +2 -0
  594. package/dist/hooks/use-mobile.d.ts.map +1 -0
  595. package/dist/hooks/use-mobile.js +16 -0
  596. package/dist/hooks/use-mobile.js.map +1 -0
  597. package/dist/hooks/use-toast.d.ts +45 -0
  598. package/dist/hooks/use-toast.d.ts.map +1 -0
  599. package/dist/hooks/use-toast.js +127 -0
  600. package/dist/hooks/use-toast.js.map +1 -0
  601. package/dist/index.d.ts +11 -0
  602. package/dist/index.d.ts.map +1 -0
  603. package/dist/index.js +11 -0
  604. package/dist/index.js.map +1 -0
  605. package/dist/onboarding/index.d.ts +2 -0
  606. package/dist/onboarding/index.d.ts.map +1 -0
  607. package/dist/onboarding/index.js +2 -0
  608. package/dist/onboarding/index.js.map +1 -0
  609. package/dist/provider.d.ts +15 -0
  610. package/dist/provider.d.ts.map +1 -0
  611. package/dist/provider.js +60 -0
  612. package/dist/provider.js.map +1 -0
  613. package/dist/sharing/SharePrimitives.d.ts +42 -0
  614. package/dist/sharing/SharePrimitives.d.ts.map +1 -0
  615. package/dist/sharing/SharePrimitives.js +53 -0
  616. package/dist/sharing/SharePrimitives.js.map +1 -0
  617. package/dist/sharing/VisibilityBadge.d.ts +11 -0
  618. package/dist/sharing/VisibilityBadge.d.ts.map +1 -0
  619. package/dist/sharing/VisibilityBadge.js +19 -0
  620. package/dist/sharing/VisibilityBadge.js.map +1 -0
  621. package/dist/sharing/VisibilityBadge.spec.d.ts +2 -0
  622. package/dist/sharing/VisibilityBadge.spec.d.ts.map +1 -0
  623. package/dist/sharing/VisibilityBadge.spec.js +60 -0
  624. package/dist/sharing/VisibilityBadge.spec.js.map +1 -0
  625. package/dist/sharing/index.d.ts +3 -0
  626. package/dist/sharing/index.d.ts.map +1 -0
  627. package/dist/sharing/index.js +3 -0
  628. package/dist/sharing/index.js.map +1 -0
  629. package/dist/styles.css +232 -0
  630. package/dist/ui/accordion.d.ts +8 -0
  631. package/dist/ui/accordion.d.ts.map +1 -0
  632. package/dist/ui/accordion.js +14 -0
  633. package/dist/ui/accordion.js.map +1 -0
  634. package/dist/ui/alert-dialog.d.ts +21 -0
  635. package/dist/ui/alert-dialog.d.ts.map +1 -0
  636. package/dist/ui/alert-dialog.js +27 -0
  637. package/dist/ui/alert-dialog.js.map +1 -0
  638. package/dist/ui/alert.d.ts +9 -0
  639. package/dist/ui/alert.d.ts.map +1 -0
  640. package/dist/ui/alert.js +23 -0
  641. package/dist/ui/alert.js.map +1 -0
  642. package/dist/ui/aspect-ratio.d.ts +4 -0
  643. package/dist/ui/aspect-ratio.d.ts.map +1 -0
  644. package/dist/ui/aspect-ratio.js +4 -0
  645. package/dist/ui/aspect-ratio.js.map +1 -0
  646. package/dist/ui/avatar.d.ts +7 -0
  647. package/dist/ui/avatar.d.ts.map +1 -0
  648. package/dist/ui/avatar.js +12 -0
  649. package/dist/ui/avatar.js.map +1 -0
  650. package/dist/ui/badge.d.ts +10 -0
  651. package/dist/ui/badge.d.ts.map +1 -0
  652. package/dist/ui/badge.js +21 -0
  653. package/dist/ui/badge.js.map +1 -0
  654. package/dist/ui/breadcrumb.d.ts +20 -0
  655. package/dist/ui/breadcrumb.d.ts.map +1 -0
  656. package/dist/ui/breadcrumb.js +24 -0
  657. package/dist/ui/breadcrumb.js.map +1 -0
  658. package/dist/ui/button.d.ts +18 -0
  659. package/dist/ui/button.d.ts.map +1 -0
  660. package/dist/ui/button.js +67 -0
  661. package/dist/ui/button.js.map +1 -0
  662. package/dist/ui/calendar.d.ts +9 -0
  663. package/dist/ui/calendar.d.ts.map +1 -0
  664. package/dist/ui/calendar.js +74 -0
  665. package/dist/ui/calendar.js.map +1 -0
  666. package/dist/ui/card.d.ts +9 -0
  667. package/dist/ui/card.d.ts.map +1 -0
  668. package/dist/ui/card.js +17 -0
  669. package/dist/ui/card.js.map +1 -0
  670. package/dist/ui/carousel.d.ts +19 -0
  671. package/dist/ui/carousel.d.ts.map +1 -0
  672. package/dist/ui/carousel.js +99 -0
  673. package/dist/ui/carousel.js.map +1 -0
  674. package/dist/ui/chart.d.ts +80 -0
  675. package/dist/ui/chart.d.ts.map +1 -0
  676. package/dist/ui/chart.js +131 -0
  677. package/dist/ui/chart.js.map +1 -0
  678. package/dist/ui/checkbox.d.ts +5 -0
  679. package/dist/ui/checkbox.d.ts.map +1 -0
  680. package/dist/ui/checkbox.js +9 -0
  681. package/dist/ui/checkbox.js.map +1 -0
  682. package/dist/ui/collapsible.d.ts +6 -0
  683. package/dist/ui/collapsible.d.ts.map +1 -0
  684. package/dist/ui/collapsible.js +6 -0
  685. package/dist/ui/collapsible.js.map +1 -0
  686. package/dist/ui/command.d.ts +85 -0
  687. package/dist/ui/command.d.ts.map +1 -0
  688. package/dist/ui/command.js +29 -0
  689. package/dist/ui/command.js.map +1 -0
  690. package/dist/ui/command.spec.d.ts +2 -0
  691. package/dist/ui/command.spec.d.ts.map +1 -0
  692. package/dist/ui/command.spec.js +29 -0
  693. package/dist/ui/command.spec.js.map +1 -0
  694. package/dist/ui/context-menu.d.ts +28 -0
  695. package/dist/ui/context-menu.d.ts.map +1 -0
  696. package/dist/ui/context-menu.js +34 -0
  697. package/dist/ui/context-menu.js.map +1 -0
  698. package/dist/ui/date-picker.d.ts +10 -0
  699. package/dist/ui/date-picker.d.ts.map +1 -0
  700. package/dist/ui/date-picker.js +20 -0
  701. package/dist/ui/date-picker.js.map +1 -0
  702. package/dist/ui/dialog.d.ts +32 -0
  703. package/dist/ui/dialog.d.ts.map +1 -0
  704. package/dist/ui/dialog.js +26 -0
  705. package/dist/ui/dialog.js.map +1 -0
  706. package/dist/ui/dialog.spec.d.ts +2 -0
  707. package/dist/ui/dialog.spec.d.ts.map +1 -0
  708. package/dist/ui/dialog.spec.js +21 -0
  709. package/dist/ui/dialog.spec.js.map +1 -0
  710. package/dist/ui/drawer.d.ts +35 -0
  711. package/dist/ui/drawer.d.ts.map +1 -0
  712. package/dist/ui/drawer.js +25 -0
  713. package/dist/ui/drawer.js.map +1 -0
  714. package/dist/ui/dropdown-menu.d.ts +32 -0
  715. package/dist/ui/dropdown-menu.d.ts.map +1 -0
  716. package/dist/ui/dropdown-menu.js +42 -0
  717. package/dist/ui/dropdown-menu.js.map +1 -0
  718. package/dist/ui/form.d.ts +26 -0
  719. package/dist/ui/form.d.ts.map +1 -0
  720. package/dist/ui/form.js +63 -0
  721. package/dist/ui/form.js.map +1 -0
  722. package/dist/ui/hover-card.d.ts +7 -0
  723. package/dist/ui/hover-card.d.ts.map +1 -0
  724. package/dist/ui/hover-card.js +10 -0
  725. package/dist/ui/hover-card.js.map +1 -0
  726. package/dist/ui/index.d.ts +53 -0
  727. package/dist/ui/index.d.ts.map +1 -0
  728. package/dist/ui/index.js +53 -0
  729. package/dist/ui/index.js.map +1 -0
  730. package/dist/ui/input-otp.d.ts +35 -0
  731. package/dist/ui/input-otp.d.ts.map +1 -0
  732. package/dist/ui/input-otp.js +19 -0
  733. package/dist/ui/input-otp.js.map +1 -0
  734. package/dist/ui/input.d.ts +4 -0
  735. package/dist/ui/input.d.ts.map +1 -0
  736. package/dist/ui/input.js +9 -0
  737. package/dist/ui/input.js.map +1 -0
  738. package/dist/ui/label.d.ts +6 -0
  739. package/dist/ui/label.d.ts.map +1 -0
  740. package/dist/ui/label.js +10 -0
  741. package/dist/ui/label.js.map +1 -0
  742. package/dist/ui/logo.d.ts +7 -0
  743. package/dist/ui/logo.d.ts.map +1 -0
  744. package/dist/ui/logo.js +10 -0
  745. package/dist/ui/logo.js.map +1 -0
  746. package/dist/ui/menubar.d.ts +29 -0
  747. package/dist/ui/menubar.d.ts.map +1 -0
  748. package/dist/ui/menubar.js +36 -0
  749. package/dist/ui/menubar.js.map +1 -0
  750. package/dist/ui/navigation-menu.d.ts +13 -0
  751. package/dist/ui/navigation-menu.d.ts.map +1 -0
  752. package/dist/ui/navigation-menu.js +25 -0
  753. package/dist/ui/navigation-menu.js.map +1 -0
  754. package/dist/ui/pagination.d.ts +29 -0
  755. package/dist/ui/pagination.d.ts.map +1 -0
  756. package/dist/ui/pagination.js +24 -0
  757. package/dist/ui/pagination.js.map +1 -0
  758. package/dist/ui/popover.d.ts +11 -0
  759. package/dist/ui/popover.d.ts.map +1 -0
  760. package/dist/ui/popover.js +16 -0
  761. package/dist/ui/popover.js.map +1 -0
  762. package/dist/ui/progress.d.ts +5 -0
  763. package/dist/ui/progress.d.ts.map +1 -0
  764. package/dist/ui/progress.js +8 -0
  765. package/dist/ui/progress.js.map +1 -0
  766. package/dist/ui/radio-group.d.ts +6 -0
  767. package/dist/ui/radio-group.d.ts.map +1 -0
  768. package/dist/ui/radio-group.js +15 -0
  769. package/dist/ui/radio-group.js.map +1 -0
  770. package/dist/ui/resizable.d.ts +8 -0
  771. package/dist/ui/resizable.d.ts.map +1 -0
  772. package/dist/ui/resizable.js +9 -0
  773. package/dist/ui/resizable.js.map +1 -0
  774. package/dist/ui/scroll-area.d.ts +6 -0
  775. package/dist/ui/scroll-area.d.ts.map +1 -0
  776. package/dist/ui/scroll-area.js +12 -0
  777. package/dist/ui/scroll-area.js.map +1 -0
  778. package/dist/ui/select.d.ts +16 -0
  779. package/dist/ui/select.d.ts.map +1 -0
  780. package/dist/ui/select.js +27 -0
  781. package/dist/ui/select.js.map +1 -0
  782. package/dist/ui/separator.d.ts +5 -0
  783. package/dist/ui/separator.d.ts.map +1 -0
  784. package/dist/ui/separator.js +8 -0
  785. package/dist/ui/separator.js.map +1 -0
  786. package/dist/ui/sheet.d.ts +29 -0
  787. package/dist/ui/sheet.d.ts.map +1 -0
  788. package/dist/ui/sheet.js +37 -0
  789. package/dist/ui/sheet.js.map +1 -0
  790. package/dist/ui/sidebar.d.ts +71 -0
  791. package/dist/ui/sidebar.d.ts.map +1 -0
  792. package/dist/ui/sidebar.js +230 -0
  793. package/dist/ui/sidebar.js.map +1 -0
  794. package/dist/ui/skeleton.d.ts +3 -0
  795. package/dist/ui/skeleton.d.ts.map +1 -0
  796. package/dist/ui/skeleton.js +7 -0
  797. package/dist/ui/skeleton.js.map +1 -0
  798. package/dist/ui/slider.d.ts +5 -0
  799. package/dist/ui/slider.d.ts.map +1 -0
  800. package/dist/ui/slider.js +8 -0
  801. package/dist/ui/slider.js.map +1 -0
  802. package/dist/ui/sonner.d.ts +5 -0
  803. package/dist/ui/sonner.d.ts.map +1 -0
  804. package/dist/ui/sonner.js +25 -0
  805. package/dist/ui/sonner.js.map +1 -0
  806. package/dist/ui/spinner.d.ts +3 -0
  807. package/dist/ui/spinner.d.ts.map +1 -0
  808. package/dist/ui/spinner.js +7 -0
  809. package/dist/ui/spinner.js.map +1 -0
  810. package/dist/ui/switch.d.ts +5 -0
  811. package/dist/ui/switch.d.ts.map +1 -0
  812. package/dist/ui/switch.js +8 -0
  813. package/dist/ui/switch.js.map +1 -0
  814. package/dist/ui/table.d.ts +11 -0
  815. package/dist/ui/table.d.ts.map +1 -0
  816. package/dist/ui/table.js +21 -0
  817. package/dist/ui/table.js.map +1 -0
  818. package/dist/ui/tabs.d.ts +8 -0
  819. package/dist/ui/tabs.d.ts.map +1 -0
  820. package/dist/ui/tabs.js +13 -0
  821. package/dist/ui/tabs.js.map +1 -0
  822. package/dist/ui/textarea.d.ts +6 -0
  823. package/dist/ui/textarea.d.ts.map +1 -0
  824. package/dist/ui/textarea.js +9 -0
  825. package/dist/ui/textarea.js.map +1 -0
  826. package/dist/ui/toast.d.ts +16 -0
  827. package/dist/ui/toast.d.ts.map +1 -0
  828. package/dist/ui/toast.js +34 -0
  829. package/dist/ui/toast.js.map +1 -0
  830. package/dist/ui/toaster.d.ts +2 -0
  831. package/dist/ui/toaster.d.ts.map +1 -0
  832. package/dist/ui/toaster.js +10 -0
  833. package/dist/ui/toaster.js.map +1 -0
  834. package/dist/ui/toggle-group.d.ts +13 -0
  835. package/dist/ui/toggle-group.d.ts.map +1 -0
  836. package/dist/ui/toggle-group.js +21 -0
  837. package/dist/ui/toggle-group.js.map +1 -0
  838. package/dist/ui/toggle.d.ts +13 -0
  839. package/dist/ui/toggle.d.ts.map +1 -0
  840. package/dist/ui/toggle.js +26 -0
  841. package/dist/ui/toggle.js.map +1 -0
  842. package/dist/ui/tooltip.d.ts +11 -0
  843. package/dist/ui/tooltip.d.ts.map +1 -0
  844. package/dist/ui/tooltip.js +18 -0
  845. package/dist/ui/tooltip.js.map +1 -0
  846. package/dist/ui/use-toast.d.ts +3 -0
  847. package/dist/ui/use-toast.d.ts.map +1 -0
  848. package/dist/ui/use-toast.js +3 -0
  849. package/dist/ui/use-toast.js.map +1 -0
  850. package/dist/utils.d.ts +4 -0
  851. package/dist/utils.d.ts.map +1 -0
  852. package/dist/utils.js +7 -0
  853. package/dist/utils.js.map +1 -0
  854. package/migration-manifest.json +4 -0
  855. package/package.json +369 -0
  856. package/src/app-shell/header-actions.tsx +84 -0
  857. package/src/app-shell/index.ts +2 -0
  858. package/src/app-shell/sidebar-footer-actions.spec.tsx +81 -0
  859. package/src/app-shell/sidebar-footer-actions.tsx +45 -0
  860. package/src/canvas-annotations/CanvasCommentPins.tsx +861 -0
  861. package/src/canvas-annotations/DrawOverlay.spec.tsx +145 -0
  862. package/src/canvas-annotations/DrawOverlay.tsx +1233 -0
  863. package/src/canvas-annotations/index.ts +15 -0
  864. package/src/canvas-annotations/types.ts +14 -0
  865. package/src/canvas-interactions/canvas-interactions.spec.ts +765 -0
  866. package/src/canvas-interactions/canvas-interactions.ts +965 -0
  867. package/src/canvas-interactions/index.ts +67 -0
  868. package/src/chat-history/ChatHistoryList.spec.tsx +485 -0
  869. package/src/chat-history/ChatHistoryList.tsx +481 -0
  870. package/src/chat-history/ChatHistoryRail.spec.tsx +312 -0
  871. package/src/chat-history/ChatHistoryRail.tsx +150 -0
  872. package/src/chat-history/index.ts +21 -0
  873. package/src/chat-history/useChatHistoryRailController.spec.tsx +131 -0
  874. package/src/chat-history/useChatHistoryRailController.ts +76 -0
  875. package/src/chat-history.css +469 -0
  876. package/src/collab-ui/AgentPresenceChip.tsx +69 -0
  877. package/src/collab-ui/LiveCursorOverlay.tsx +241 -0
  878. package/src/collab-ui/PresenceBar.spec.tsx +44 -0
  879. package/src/collab-ui/PresenceBar.tsx +373 -0
  880. package/src/collab-ui/RecentEditHighlights.tsx +239 -0
  881. package/src/collab-ui/RemoteSelectionRings.tsx +227 -0
  882. package/src/collab-ui/agent-identity.ts +16 -0
  883. package/src/collab-ui/index.ts +39 -0
  884. package/src/collab-ui/lead-client.ts +32 -0
  885. package/src/collab-ui/types.spec.ts +18 -0
  886. package/src/collab-ui/types.ts +96 -0
  887. package/src/composer/AgentComposerFrame.tsx +62 -0
  888. package/src/composer/ComposerPlusMenu.spec.ts +14 -0
  889. package/src/composer/ComposerPlusMenu.tsx +1266 -0
  890. package/src/composer/MentionPopover.tsx +483 -0
  891. package/src/composer/PastedTextChip.spec.tsx +58 -0
  892. package/src/composer/PastedTextChip.tsx +178 -0
  893. package/src/composer/PromptComposer.spec.ts +110 -0
  894. package/src/composer/PromptComposer.tsx +796 -0
  895. package/src/composer/RealtimeVoiceMode.spec.tsx +998 -0
  896. package/src/composer/RealtimeVoiceMode.tsx +1019 -0
  897. package/src/composer/TiptapComposer.spec.ts +592 -0
  898. package/src/composer/TiptapComposer.tsx +3746 -0
  899. package/src/composer/VoiceButton.spec.ts +49 -0
  900. package/src/composer/VoiceButton.tsx +329 -0
  901. package/src/composer/asset-picker-url.spec.ts +56 -0
  902. package/src/composer/asset-picker-url.ts +80 -0
  903. package/src/composer/attachment-accept.spec.ts +32 -0
  904. package/src/composer/attachment-accept.ts +75 -0
  905. package/src/composer/draft-key.spec.ts +19 -0
  906. package/src/composer/draft-key.ts +7 -0
  907. package/src/composer/extensions/FileReference.tsx +55 -0
  908. package/src/composer/extensions/MentionReference.tsx +93 -0
  909. package/src/composer/extensions/SkillReference.tsx +56 -0
  910. package/src/composer/index.ts +86 -0
  911. package/src/composer/model-selection.spec.ts +45 -0
  912. package/src/composer/model-selection.ts +51 -0
  913. package/src/composer/pasted-text.spec.ts +162 -0
  914. package/src/composer/pasted-text.ts +160 -0
  915. package/src/composer/prompt-attachments.spec.ts +80 -0
  916. package/src/composer/prompt-attachments.ts +93 -0
  917. package/src/composer/realtime-voice-audio-level.spec.ts +47 -0
  918. package/src/composer/realtime-voice-audio-level.ts +65 -0
  919. package/src/composer/realtime-voice-transcript.spec.ts +95 -0
  920. package/src/composer/realtime-voice-transcript.ts +134 -0
  921. package/src/composer/runtime-adapters.spec.tsx +102 -0
  922. package/src/composer/runtime-adapters.tsx +364 -0
  923. package/src/composer/types.ts +66 -0
  924. package/src/composer/use-file-search.ts +64 -0
  925. package/src/composer/use-mention-search.ts +90 -0
  926. package/src/composer/use-skills.ts +45 -0
  927. package/src/composer/useRealtimeVoiceMode.spec.ts +952 -0
  928. package/src/composer/useRealtimeVoiceMode.tsx +2388 -0
  929. package/src/composer/useVoiceDictation.browser.spec.tsx +265 -0
  930. package/src/composer/useVoiceDictation.spec.ts +45 -0
  931. package/src/composer/useVoiceDictation.ts +1256 -0
  932. package/src/conformance/__fixtures__/css-in-js-adapter.tsx +401 -0
  933. package/src/conformance/conformance.spec.tsx +143 -0
  934. package/src/conformance/index.ts +3 -0
  935. package/src/conformance/runner.tsx +862 -0
  936. package/src/conformance/types.ts +45 -0
  937. package/src/conformance/version.ts +22 -0
  938. package/src/context-ui/ContextMeter.spec.tsx +73 -0
  939. package/src/context-ui/ContextMeter.tsx +131 -0
  940. package/src/context-ui/ContextSegmentRow.tsx +273 -0
  941. package/src/context-ui/ContextTreemap.tsx +131 -0
  942. package/src/context-ui/ContextXRayPanel.tsx +491 -0
  943. package/src/context-ui/format.ts +42 -0
  944. package/src/context-ui/index.ts +15 -0
  945. package/src/context-ui/types.ts +57 -0
  946. package/src/dashboard/DataTable.tsx +273 -0
  947. package/src/dashboard/DateRangePicker.tsx +57 -0
  948. package/src/dashboard/GenericChartPanel.spec.tsx +53 -0
  949. package/src/dashboard/GenericChartPanel.tsx +461 -0
  950. package/src/dashboard/MetricCard.tsx +54 -0
  951. package/src/dashboard/StatsCard.tsx +49 -0
  952. package/src/dashboard/dashboard-layout.spec.ts +79 -0
  953. package/src/dashboard/dashboard-layout.ts +329 -0
  954. package/src/dashboard/index.ts +6 -0
  955. package/src/data-grid/DataGrid.spec.tsx +243 -0
  956. package/src/data-grid/DataGrid.tsx +754 -0
  957. package/src/data-grid/index.ts +15 -0
  958. package/src/design-system/components.tsx +196 -0
  959. package/src/design-system/context.tsx +31 -0
  960. package/src/design-system/default-adapter.spec.tsx +158 -0
  961. package/src/design-system/default-adapter.tsx +923 -0
  962. package/src/design-system/definition.ts +14 -0
  963. package/src/design-system/design-system.spec.tsx +356 -0
  964. package/src/design-system/error-boundary.tsx +37 -0
  965. package/src/design-system/index.ts +7 -0
  966. package/src/design-system/theme.spec.ts +61 -0
  967. package/src/design-system/theme.ts +145 -0
  968. package/src/design-system/types.ts +367 -0
  969. package/src/design-tweaks/index.ts +1 -0
  970. package/src/design-tweaks/scrub-input-utils.ts +311 -0
  971. package/src/design-tweaks/scrub-input.tsx +525 -0
  972. package/src/design-tweaks/visual-style-controls.spec.tsx +172 -0
  973. package/src/design-tweaks/visual-style-controls.tsx +1043 -0
  974. package/src/editor/BubbleToolbar.tsx +253 -0
  975. package/src/editor/CodeBlockNode.tsx +254 -0
  976. package/src/editor/DragHandle.spec.ts +694 -0
  977. package/src/editor/DragHandle.ts +1491 -0
  978. package/src/editor/ImageExtension.roundtrip.spec.ts +117 -0
  979. package/src/editor/ImageExtension.ts +306 -0
  980. package/src/editor/RegistryBlockContext.tsx +107 -0
  981. package/src/editor/RegistryBlockNode.spec.ts +279 -0
  982. package/src/editor/RegistryBlockNode.tsx +652 -0
  983. package/src/editor/RichMarkdownEditor.collab.spec.ts +79 -0
  984. package/src/editor/RichMarkdownEditor.roundtrip.spec.ts +226 -0
  985. package/src/editor/RichMarkdownEditor.tsx +81 -0
  986. package/src/editor/RunId.ts +61 -0
  987. package/src/editor/SharedRichEditor.spec.tsx +82 -0
  988. package/src/editor/SharedRichEditor.tsx +353 -0
  989. package/src/editor/SlashCommandMenu.spec.ts +90 -0
  990. package/src/editor/SlashCommandMenu.tsx +396 -0
  991. package/src/editor/disableHistory.spec.ts +85 -0
  992. package/src/editor/extensions.ts +454 -0
  993. package/src/editor/gfmDoc.spec.ts +230 -0
  994. package/src/editor/gfmDoc.ts +92 -0
  995. package/src/editor/index.ts +96 -0
  996. package/src/editor/registrySlashCommands.ts +131 -0
  997. package/src/editor/structuralReorderUndo.spec.ts +144 -0
  998. package/src/editor/surgical-apply.spec.ts +279 -0
  999. package/src/editor/surgical-apply.ts +192 -0
  1000. package/src/editor/useCollabReconcile.concurrent.spec.ts +781 -0
  1001. package/src/editor/useCollabReconcile.idempotent.spec.ts +324 -0
  1002. package/src/editor/useCollabReconcile.ts +684 -0
  1003. package/src/editor.css +587 -0
  1004. package/src/hooks/index.ts +2 -0
  1005. package/src/hooks/use-mobile.tsx +21 -0
  1006. package/src/hooks/use-toast.ts +188 -0
  1007. package/src/index.ts +10 -0
  1008. package/src/onboarding/index.ts +1 -0
  1009. package/src/provider.tsx +148 -0
  1010. package/src/sharing/SharePrimitives.tsx +224 -0
  1011. package/src/sharing/VisibilityBadge.spec.ts +96 -0
  1012. package/src/sharing/VisibilityBadge.tsx +37 -0
  1013. package/src/sharing/index.ts +16 -0
  1014. package/src/styles.css +232 -0
  1015. package/src/ui/accordion.tsx +56 -0
  1016. package/src/ui/alert-dialog.tsx +141 -0
  1017. package/src/ui/alert.tsx +59 -0
  1018. package/src/ui/aspect-ratio.tsx +5 -0
  1019. package/src/ui/avatar.tsx +48 -0
  1020. package/src/ui/badge.tsx +37 -0
  1021. package/src/ui/breadcrumb.tsx +115 -0
  1022. package/src/ui/button.tsx +167 -0
  1023. package/src/ui/calendar.tsx +214 -0
  1024. package/src/ui/card.tsx +86 -0
  1025. package/src/ui/carousel.tsx +260 -0
  1026. package/src/ui/chart.tsx +375 -0
  1027. package/src/ui/checkbox.tsx +28 -0
  1028. package/src/ui/collapsible.tsx +9 -0
  1029. package/src/ui/command.spec.tsx +51 -0
  1030. package/src/ui/command.tsx +174 -0
  1031. package/src/ui/context-menu.tsx +202 -0
  1032. package/src/ui/date-picker.tsx +67 -0
  1033. package/src/ui/dialog.spec.tsx +43 -0
  1034. package/src/ui/dialog.tsx +171 -0
  1035. package/src/ui/drawer.tsx +126 -0
  1036. package/src/ui/dropdown-menu.tsx +222 -0
  1037. package/src/ui/form.tsx +177 -0
  1038. package/src/ui/hover-card.tsx +27 -0
  1039. package/src/ui/index.ts +52 -0
  1040. package/src/ui/input-otp.tsx +69 -0
  1041. package/src/ui/input.tsx +22 -0
  1042. package/src/ui/label.tsx +24 -0
  1043. package/src/ui/logo.tsx +36 -0
  1044. package/src/ui/menubar.tsx +235 -0
  1045. package/src/ui/navigation-menu.tsx +128 -0
  1046. package/src/ui/pagination.tsx +121 -0
  1047. package/src/ui/popover.tsx +58 -0
  1048. package/src/ui/progress.tsx +27 -0
  1049. package/src/ui/radio-group.tsx +42 -0
  1050. package/src/ui/resizable.tsx +43 -0
  1051. package/src/ui/scroll-area.tsx +46 -0
  1052. package/src/ui/select.tsx +162 -0
  1053. package/src/ui/separator.tsx +29 -0
  1054. package/src/ui/sheet.tsx +160 -0
  1055. package/src/ui/sidebar.tsx +776 -0
  1056. package/src/ui/skeleton.tsx +18 -0
  1057. package/src/ui/slider.tsx +26 -0
  1058. package/src/ui/sonner.tsx +58 -0
  1059. package/src/ui/spinner.tsx +17 -0
  1060. package/src/ui/switch.tsx +27 -0
  1061. package/src/ui/table.tsx +110 -0
  1062. package/src/ui/tabs.tsx +53 -0
  1063. package/src/ui/textarea.tsx +23 -0
  1064. package/src/ui/toast.tsx +127 -0
  1065. package/src/ui/toaster.tsx +33 -0
  1066. package/src/ui/toggle-group.tsx +59 -0
  1067. package/src/ui/toggle.tsx +43 -0
  1068. package/src/ui/tooltip.tsx +57 -0
  1069. package/src/ui/use-toast.ts +3 -0
  1070. package/src/utils.ts +8 -0
@@ -0,0 +1,2233 @@
1
+ import { Fragment as _Fragment, jsx as _jsx, jsxs as _jsxs } from "react/jsx-runtime";
2
+ import { Skeleton } from "@agent-native/toolkit/ui/skeleton";
3
+ import { useComposer, useComposerRuntime } from "@assistant-ui/react";
4
+ import { IconArrowUp, IconCheck, IconChevronDown, IconChevronRight, IconBulb, IconClock, IconBolt, IconTool, IconX, IconClipboardList, IconKey, IconPencil, IconPlugConnected, IconHelpCircle, } from "@tabler/icons-react";
5
+ import Placeholder from "@tiptap/extension-placeholder";
6
+ import { useEditor, EditorContent } from "@tiptap/react";
7
+ import StarterKit from "@tiptap/starter-kit";
8
+ import { useState, useRef, useEffect, useCallback, useImperativeHandle, useMemo, } from "react";
9
+ import { Popover, PopoverAnchor, PopoverContent, PopoverTrigger, } from "../ui/popover.js";
10
+ import { Tooltip, TooltipContent, TooltipTrigger } from "../ui/tooltip.js";
11
+ import { ComposerPlusMenu, } from "./ComposerPlusMenu.js";
12
+ import { getComposerDraftKey } from "./draft-key.js";
13
+ import { FileReference } from "./extensions/FileReference.js";
14
+ import { MentionReference } from "./extensions/MentionReference.js";
15
+ import { SkillReference } from "./extensions/SkillReference.js";
16
+ import { MentionPopover } from "./MentionPopover.js";
17
+ import { isClaudeCodeAgentId, isLunaModel, resolvePreferredAgentModel, } from "./model-selection.js";
18
+ import { createPastedAttachmentFile, readClipboardPaste, shouldConvertClipboardToAttachment, } from "./pasted-text.js";
19
+ import { AGENT_CHAT_INSERT_REFERENCE_EVENT, AGENT_CHAT_INSERT_REFERENCE_MESSAGE_TYPE, DEFAULT_REASONING_EFFORT, formatPromptContextItems, getReasoningEffortOptionsForModel, reasoningEffortLabel, resolveReasoningEffortSelection, useComposerRuntimeAdapters, } from "./runtime-adapters.js";
20
+ import { useMentionSearch } from "./use-mention-search.js";
21
+ import { useSkills } from "./use-skills.js";
22
+ import { RealtimeVoiceModeBoundary } from "./useRealtimeVoiceMode.js";
23
+ import { useVoiceDictation } from "./useVoiceDictation.js";
24
+ import { VoiceButton, VoiceRecordingOverlay } from "./VoiceButton.js";
25
+ export const DEFAULT_VOICE_DICTATION_ENABLED = false;
26
+ export function canSubmitComposerContent(options) {
27
+ return (!options.disabled &&
28
+ (options.hasEditorContent || options.attachmentCount > 0));
29
+ }
30
+ const VOICE_TERMINAL_PUNCTUATION = /[.!?…。!?:;](?:["'”’»)\]}]*)$/;
31
+ export function formatVoiceTranscriptForComposer(text) {
32
+ const trimmed = text.trim();
33
+ if (!trimmed)
34
+ return "";
35
+ return `${trimmed}${VOICE_TERMINAL_PUNCTUATION.test(trimmed) ? "" : "."} `;
36
+ }
37
+ export function canRemoveVoicePreview(options) {
38
+ if (!options.previewText)
39
+ return false;
40
+ if (options.anchor < 1)
41
+ return false;
42
+ if (options.anchor + options.previewText.length > options.documentSize) {
43
+ return false;
44
+ }
45
+ return options.currentText === options.previewText;
46
+ }
47
+ export function resolveComposerPrimaryAction(options) {
48
+ return !options.canSubmit && options.hasStopButton ? "stop" : "send";
49
+ }
50
+ export function getComposerSendTooltipKey(willQueue) {
51
+ return willQueue ? "composer.queueMessage" : "composer.sendMessage";
52
+ }
53
+ export function resolveContextChipBackspaceAction(options) {
54
+ if (!options.cursorAtStart || options.contextItemKeys.length === 0) {
55
+ return null;
56
+ }
57
+ if (options.selectedKey &&
58
+ options.contextItemKeys.includes(options.selectedKey)) {
59
+ return { type: "remove", key: options.selectedKey };
60
+ }
61
+ return {
62
+ type: "select",
63
+ key: options.contextItemKeys[options.contextItemKeys.length - 1],
64
+ };
65
+ }
66
+ const MAX_DOCUMENT_ATTACHMENT_BYTES = 4 * 1024 * 1024;
67
+ function composerReferenceFromMentionItem(item) {
68
+ return {
69
+ label: item.label,
70
+ icon: item.icon || "file",
71
+ source: item.source,
72
+ refType: item.refType,
73
+ refId: item.refId || null,
74
+ refPath: item.refPath || null,
75
+ slotKey: item.slotKey,
76
+ slotLabel: item.slotLabel,
77
+ metadata: item.metadata,
78
+ clearsSlots: item.clearsSlots,
79
+ relatedReferences: item.relatedReferences,
80
+ };
81
+ }
82
+ function mentionReferenceAttrs(ref) {
83
+ return {
84
+ label: ref.label,
85
+ icon: ref.icon || "file",
86
+ source: ref.source,
87
+ refType: ref.refType,
88
+ refId: ref.refId || null,
89
+ refPath: ref.refPath || null,
90
+ slotKey: ref.slotKey || null,
91
+ slotLabel: ref.slotLabel || null,
92
+ metadata: ref.metadata || null,
93
+ };
94
+ }
95
+ function referenceFromComposerReference(ref) {
96
+ return {
97
+ type: ref.refType === "file"
98
+ ? "file"
99
+ : ref.refType === "agent"
100
+ ? "agent"
101
+ : ref.refType === "custom-agent"
102
+ ? "custom-agent"
103
+ : "mention",
104
+ path: ref.refPath || "",
105
+ name: ref.label,
106
+ source: ref.source || "",
107
+ refType: ref.refType,
108
+ refId: ref.refId || undefined,
109
+ slotKey: ref.slotKey,
110
+ slotLabel: ref.slotLabel,
111
+ metadata: ref.metadata,
112
+ };
113
+ }
114
+ function applySlotReferenceChanges(current, references) {
115
+ let next = current;
116
+ const applyOne = (ref) => {
117
+ for (const related of ref.relatedReferences ?? []) {
118
+ applyOne(related);
119
+ }
120
+ if (!ref.slotKey)
121
+ return;
122
+ const cleared = new Set([ref.slotKey, ...(ref.clearsSlots ?? [])]);
123
+ next = next.filter((existing) => !cleared.has(existing.slotKey ?? ""));
124
+ next = [...next, ref];
125
+ };
126
+ for (const ref of references) {
127
+ applyOne(ref);
128
+ }
129
+ return next;
130
+ }
131
+ function removeSlotReference(current, ref) {
132
+ const removed = new Set([ref.slotKey, ...(ref.clearsSlots ?? [])]);
133
+ return current.filter((existing) => !removed.has(existing.slotKey ?? ""));
134
+ }
135
+ function slotReferenceTitle(ref) {
136
+ return ref.slotLabel ? `${ref.slotLabel}: ${ref.label}` : ref.label;
137
+ }
138
+ function metadataString(metadata, key) {
139
+ const value = metadata?.[key];
140
+ return typeof value === "string" && value.trim() ? value.trim() : null;
141
+ }
142
+ function trimVoiceContextValue(value, maxChars) {
143
+ const trimmed = value.replace(/\0/g, "").trim();
144
+ if (!trimmed)
145
+ return null;
146
+ if (trimmed.length <= maxChars)
147
+ return trimmed;
148
+ return `${trimmed.slice(0, maxChars).trimEnd()}\n[truncated]`;
149
+ }
150
+ function filterMentionItemsForSlots(items, slotReferences) {
151
+ return items.filter((item) => {
152
+ const requiredSlotKey = metadataString(item.metadata, "requiredSlotKey");
153
+ const requiredRefId = metadataString(item.metadata, "requiredRefId");
154
+ if (!requiredSlotKey || !requiredRefId)
155
+ return true;
156
+ const selected = slotReferences.find((ref) => ref.slotKey === requiredSlotKey);
157
+ if (!selected?.refId)
158
+ return true;
159
+ return selected.refId === requiredRefId;
160
+ });
161
+ }
162
+ function isDocumentAttachment(value) {
163
+ if (value.type === "document")
164
+ return true;
165
+ const contentType = String(value.contentType ?? "").toLowerCase();
166
+ const name = String(value.name ?? "").toLowerCase();
167
+ return contentType === "application/pdf" || name.endsWith(".pdf");
168
+ }
169
+ export function getOversizedDocumentAttachmentError(attachments, options = {}) {
170
+ const maxBytes = options.maxBytes ?? MAX_DOCUMENT_ATTACHMENT_BYTES;
171
+ const label = options.label ?? "PDFs";
172
+ const t = options.translate;
173
+ for (const attachment of attachments) {
174
+ if (!attachment || typeof attachment !== "object")
175
+ continue;
176
+ const candidate = attachment;
177
+ if (!isDocumentAttachment(candidate))
178
+ continue;
179
+ const file = candidate.file;
180
+ if (!(file instanceof File))
181
+ continue;
182
+ if (file.size <= maxBytes)
183
+ continue;
184
+ const name = typeof candidate.name === "string" && candidate.name.trim()
185
+ ? candidate.name
186
+ : file.name;
187
+ const mb = (file.size / 1024 / 1024).toFixed(1);
188
+ const maxMb = (maxBytes / 1024 / 1024).toFixed(0);
189
+ return (t?.("agentChat.composer.documentTooLarge", {
190
+ defaultValue: '"{{name}}" is {{size}} MB. {{label}} are capped at {{maxSize}} MB to stay within message limits. Please reduce the file size or split it into smaller parts.',
191
+ name,
192
+ size: mb,
193
+ label,
194
+ maxSize: maxMb,
195
+ }) ??
196
+ `"${name}" is ${mb} MB. ${label} are capped at ${maxMb} MB to stay within message limits. Please reduce the file size or split it into smaller parts.`);
197
+ }
198
+ return null;
199
+ }
200
+ export function getComposerSubmitIntentForEnterKey(event, isMac) {
201
+ if (event.key !== "Enter" || event.shiftKey)
202
+ return null;
203
+ const queuedModifierPressed = isMac ? event.metaKey : event.ctrlKey;
204
+ if (queuedModifierPressed)
205
+ return "queued";
206
+ if (!event.metaKey && !event.ctrlKey)
207
+ return "immediate";
208
+ return null;
209
+ }
210
+ export function insertComposerHardBreakAndScrollIntoView(view) {
211
+ const hardBreak = view.state.schema.nodes.hardBreak;
212
+ if (!hardBreak)
213
+ return false;
214
+ view.dispatch(view.state.tr.replaceSelectionWith(hardBreak.create()).scrollIntoView());
215
+ return true;
216
+ }
217
+ export function getComposerPopoverPosition(view, pos) {
218
+ try {
219
+ const coords = view.coordsAtPos(pos);
220
+ if (!Number.isFinite(coords.top) || !Number.isFinite(coords.left)) {
221
+ return null;
222
+ }
223
+ return { top: coords.top, left: coords.left };
224
+ }
225
+ catch {
226
+ return null;
227
+ }
228
+ }
229
+ export function displayableComposerModeMessage(options) {
230
+ const modePrompt = options.trimmedText ||
231
+ (options.attachmentCount > 0
232
+ ? (options.attachedContextFallback ?? "Use the attached context.")
233
+ : "");
234
+ return `${options.messagePrefix}${modePrompt}`;
235
+ }
236
+ function uniquifyComposerImageFile(file) {
237
+ if (!file.type.startsWith("image/"))
238
+ return file;
239
+ const uniqueName = `${Date.now()}-${Math.random().toString(36).slice(2)}-${file.name}`;
240
+ return new File([file], uniqueName, { type: file.type });
241
+ }
242
+ function composerDocumentHasContent(doc) {
243
+ if (doc.textContent.trim().length > 0)
244
+ return true;
245
+ let hasContent = false;
246
+ doc.descendants((node) => {
247
+ if (node.type.name === "mentionReference" ||
248
+ node.type.name === "fileReference" ||
249
+ node.type.name === "skillReference") {
250
+ hasContent = true;
251
+ return false;
252
+ }
253
+ return true;
254
+ });
255
+ return hasContent;
256
+ }
257
+ export function handleComposerFileDrop(options) {
258
+ const droppedFiles = Array.from(options.event.dataTransfer?.files ?? []);
259
+ if (droppedFiles.length === 0)
260
+ return false;
261
+ options.event.preventDefault();
262
+ options.event.stopPropagation();
263
+ const attachments = droppedFiles.map(uniquifyComposerImageFile);
264
+ void Promise.all(attachments.map((file) => options.addAttachment(file))).catch((error) => {
265
+ options.onError?.(error);
266
+ });
267
+ return true;
268
+ }
269
+ function builtInCommands(t) {
270
+ return [
271
+ {
272
+ name: "clear",
273
+ description: t("agentChat.commands.clearShort", {
274
+ defaultValue: "Start a new chat",
275
+ }),
276
+ icon: "clear",
277
+ },
278
+ {
279
+ name: "new",
280
+ description: t("agentChat.commands.newShort", {
281
+ defaultValue: "Start a new chat",
282
+ }),
283
+ icon: "new",
284
+ },
285
+ {
286
+ name: "history",
287
+ description: t("agentChat.commands.history", {
288
+ defaultValue: "Browse all chats",
289
+ }),
290
+ icon: "history",
291
+ },
292
+ {
293
+ name: "plan",
294
+ description: t("agentChat.commands.plan", {
295
+ defaultValue: "Switch to read-only planning",
296
+ }),
297
+ icon: "plan",
298
+ },
299
+ {
300
+ name: "act",
301
+ description: t("agentChat.commands.act", {
302
+ defaultValue: "Switch back to acting",
303
+ }),
304
+ icon: "act",
305
+ },
306
+ {
307
+ name: "help",
308
+ description: t("agentChat.commands.help", {
309
+ defaultValue: "Show available commands",
310
+ }),
311
+ icon: "help",
312
+ },
313
+ ];
314
+ }
315
+ function normalizeSlashCommandName(name) {
316
+ return name.replace(/^\/+/, "").trim().toLowerCase();
317
+ }
318
+ function mergeSlashCommands(commands) {
319
+ const seen = new Set();
320
+ const merged = [];
321
+ for (const command of commands) {
322
+ const name = normalizeSlashCommandName(command.name);
323
+ if (!name || seen.has(name))
324
+ continue;
325
+ seen.add(name);
326
+ merged.push({ ...command, name });
327
+ }
328
+ return merged;
329
+ }
330
+ function mergeSlashSkills(skills) {
331
+ const seen = new Set();
332
+ const merged = [];
333
+ for (const skill of skills) {
334
+ const key = `${skill.source ?? ""}:${skill.path ?? ""}:${skill.name}`;
335
+ if (!skill.name || seen.has(key))
336
+ continue;
337
+ seen.add(key);
338
+ merged.push(skill);
339
+ }
340
+ return merged;
341
+ }
342
+ const COMPOSER_MODE_CONFIGS = {
343
+ skill: {
344
+ icon: IconBulb,
345
+ getContext: (prompt) => `The user wants to create an agent skill. Their description: "${prompt}"
346
+
347
+ Follow the create-skill pattern to build this. Before writing:
348
+
349
+ 1. **Determine the skill name** — derive a hyphen-case name from the description (e.g. "code review" → "code-review")
350
+ 2. **Determine the skill type** — Pattern (architectural rule), Workflow (step-by-step), or Generator (scaffolding)
351
+ 3. **Write the skill** as a personal resource at path "skills/<name>/SKILL.md" using the \`resources\` tool with \`action: "write"\`
352
+
353
+ The skill file MUST have YAML frontmatter with name and description (under 40 words), then markdown with:
354
+ - Clear rule/purpose statement
355
+ - Why this skill exists
356
+ - How to follow it (with code examples where helpful)
357
+ - Common violations to avoid
358
+ - Related skills
359
+
360
+ After creating, update the shared AGENTS.md resource to reference the new skill in its skills table.
361
+
362
+ Keep the skill concise (under 500 lines) and actionable.`,
363
+ },
364
+ job: {
365
+ icon: IconClock,
366
+ getContext: (prompt) => `The user wants to create a recurring job. Their description: "${prompt}"
367
+
368
+ Use the manage-jobs tool with action "create" to create this. You need to:
369
+ 1. Derive a hyphen-case name from the description
370
+ 2. Convert the schedule to a cron expression (e.g., "every weekday at 9am" → "0 9 * * 1-5")
371
+ 3. Write clear, self-contained instructions for what the agent should do each time the job runs
372
+ 4. Create it in personal scope
373
+
374
+ The job will run automatically on the schedule. Make the instructions specific — include which actions to call and what to do with results.`,
375
+ },
376
+ automation: {
377
+ icon: IconBolt,
378
+ beforeSend: () => {
379
+ window.dispatchEvent(new CustomEvent("agent-panel:set-mode", {
380
+ detail: { mode: "chat" },
381
+ }));
382
+ },
383
+ getContext: (prompt) => `The user wants to create a new automation. Scope: personal. Their description: "${prompt}"
384
+
385
+ Use manage-automations with action=define to create it. Ask clarifying questions if needed about what event to trigger on, conditions, and what actions to take.`,
386
+ },
387
+ extension: {
388
+ icon: IconTool,
389
+ getContext: (prompt) => `The user wants to create an interactive extension (sandboxed mini-app). Their description: "${prompt}"
390
+
391
+ Use the create-extension action with Alpine.js HTML content. The extension runs as a sandboxed iframe with Tailwind CSS and modest default canvas padding. For edge-to-edge layouts, put data-extension-layout="full-bleed" on the outermost element.
392
+
393
+ After creating the extension, navigate the user to it with the path returned by create-extension; extension URLs may include a friendly "/extensions/<id>/<slug>" suffix.
394
+
395
+ Make the extension functional and visually polished. Extensions can use extensionFetch() for external API calls, appAction()/appFetch() for app operations and app data writes, extensionData for per-extension persistence, and dbQuery() only for read-only inspection of existing app tables.
396
+
397
+ Prefer appAction()/appFetch() for app data. Some actions return JSON strings for CLI compatibility, so parse string results before counting rows or reading arrays. Do not guess raw SQL table names or columns for app data; use dbQuery() only when the table is known to exist in the current schema.`,
398
+ },
399
+ };
400
+ function localizedComposerModeConfig(mode, t) {
401
+ const config = COMPOSER_MODE_CONFIGS[mode];
402
+ const copies = {
403
+ skill: {
404
+ label: t("agentChat.composer.createSkill", {
405
+ defaultValue: "Create Skill",
406
+ }),
407
+ placeholder: t("agentChat.composer.describeSkill", {
408
+ defaultValue: "Describe the skill you want to create...",
409
+ }),
410
+ messagePrefix: t("agentChat.composer.createSkillPrefix", {
411
+ defaultValue: "Create a skill: ",
412
+ }),
413
+ },
414
+ job: {
415
+ label: t("agentChat.composer.scheduleTask", {
416
+ defaultValue: "Schedule Task",
417
+ }),
418
+ placeholder: t("agentChat.composer.describeSchedule", {
419
+ defaultValue: "Describe what should happen and when...",
420
+ }),
421
+ messagePrefix: t("agentChat.composer.scheduleTaskPrefix", {
422
+ defaultValue: "Create a recurring job: ",
423
+ }),
424
+ },
425
+ automation: {
426
+ label: t("agentChat.composer.createAutomation", {
427
+ defaultValue: "Create Automation",
428
+ }),
429
+ placeholder: t("agentChat.composer.describeAutomation", {
430
+ defaultValue: "Describe what you want to automate...",
431
+ }),
432
+ messagePrefix: t("agentChat.composer.createAutomationPrefix", {
433
+ defaultValue: "Create an automation: ",
434
+ }),
435
+ },
436
+ extension: {
437
+ label: t("agentChat.composer.createExtension", {
438
+ defaultValue: "Create Extension",
439
+ }),
440
+ placeholder: t("agentChat.composer.describeExtension", {
441
+ defaultValue: "Describe the interactive extension you want to build...",
442
+ }),
443
+ messagePrefix: t("agentChat.composer.createExtensionPrefix", {
444
+ defaultValue: "Create an extension: ",
445
+ }),
446
+ },
447
+ };
448
+ return { ...config, ...copies[mode] };
449
+ }
450
+ function ComposerModeChip({ mode, onRemove, }) {
451
+ const t = useComposerRuntimeAdapters().translate;
452
+ const config = localizedComposerModeConfig(mode, t);
453
+ const Icon = config.icon;
454
+ return (_jsxs("span", { className: "inline-flex items-center gap-1 rounded-md border border-border bg-muted/50 px-1.5 py-0.5 text-xs font-medium text-foreground", children: [_jsx(Icon, { className: "h-3 w-3 text-muted-foreground" }), config.label, _jsx("button", { type: "button", onClick: onRemove, className: "ms-0.5 rounded-sm text-muted-foreground hover:text-foreground cursor-pointer", children: _jsx(IconX, { className: "h-3 w-3" }) })] }));
455
+ }
456
+ function plainTextToDoc(text) {
457
+ const lines = text.length > 0 ? text.split(/\r?\n/) : [""];
458
+ return {
459
+ type: "doc",
460
+ content: lines.map((line) => ({
461
+ type: "paragraph",
462
+ content: line ? [{ type: "text", text: line }] : [],
463
+ })),
464
+ };
465
+ }
466
+ /** Tiptap keeps the Editor object truthy after destroy but clears commandManager. */
467
+ export function isComposerEditorUsable(editor) {
468
+ return Boolean(editor && editor.isDestroyed !== true);
469
+ }
470
+ export function createTiptapComposerExtensions(getPlaceholder) {
471
+ return [
472
+ StarterKit.configure({
473
+ heading: false,
474
+ horizontalRule: false,
475
+ bulletList: false,
476
+ orderedList: false,
477
+ listItem: false,
478
+ listKeymap: false,
479
+ blockquote: false,
480
+ codeBlock: false,
481
+ strike: false,
482
+ italic: false,
483
+ bold: false,
484
+ code: false,
485
+ dropcursor: false,
486
+ gapcursor: false,
487
+ link: false,
488
+ trailingNode: false,
489
+ underline: false,
490
+ }),
491
+ Placeholder.configure({
492
+ placeholder: () => getPlaceholder() ?? "",
493
+ emptyEditorClass: "is-editor-empty",
494
+ showOnlyCurrent: false,
495
+ }),
496
+ FileReference,
497
+ SkillReference,
498
+ MentionReference,
499
+ ];
500
+ }
501
+ function ModeSelector({ mode, onChange, planModeDisabled = false, planModeDisabledReason, }) {
502
+ const t = useComposerRuntimeAdapters().translate;
503
+ const [open, setOpen] = useState(false);
504
+ const resolvedPlanModeDisabledReason = planModeDisabledReason ??
505
+ t("agentChat.composer.planDesktopRequired", {
506
+ defaultValue: "Open Agent Native Desktop to use Plan mode.",
507
+ });
508
+ return (_jsxs(Popover, { open: open, onOpenChange: setOpen, children: [_jsx(PopoverTrigger, { asChild: true, children: _jsxs("button", { type: "button", "aria-label": mode === "build"
509
+ ? t("agentChat.composer.actMode", { defaultValue: "Act mode" })
510
+ : t("agentChat.plan.mode", { defaultValue: "Plan mode" }), "data-agent-composer-slot": "mode-button", className: "agent-composer-mode-button shrink-0 flex items-center gap-1 rounded-md px-2 py-1 text-[12px] font-medium text-muted-foreground hover:bg-accent/50 hover:text-foreground", children: [mode === "build"
511
+ ? t("agentChat.plan.act", { defaultValue: "Act" })
512
+ : t("agentChat.composer.plan", { defaultValue: "Plan" }), _jsx(IconChevronDown, { className: "h-3 w-3 opacity-60" })] }) }), _jsxs(PopoverContent, { side: "top", align: "end", sideOffset: 6, collisionPadding: 8, "data-agent-native-composer-popover": "true", className: "z-[260] w-60 rounded-lg border-border p-0 py-1 shadow-lg", style: { fontSize: 13 }, children: [_jsxs("button", { type: "button", onClick: () => {
513
+ onChange("build");
514
+ setOpen(false);
515
+ }, className: "flex w-full items-center gap-3 px-3 py-2 hover:bg-accent/50 text-start", children: [_jsx(IconPencil, { className: "h-4 w-4 shrink-0 text-muted-foreground" }), _jsxs("div", { className: "flex-1 min-w-0", children: [_jsx("span", { className: "font-medium text-foreground text-[13px]", children: t("agentChat.plan.act", { defaultValue: "Act" }) }), _jsx("p", { className: "text-[11px] text-muted-foreground mt-0.5", children: t("agentChat.composer.actDescription", {
516
+ defaultValue: "Use tools and make approved changes",
517
+ }) })] }), mode === "build" && (_jsx(IconCheck, { className: "size-4 shrink-0 text-primary" }))] }), _jsxs("button", { type: "button", disabled: planModeDisabled, title: planModeDisabled ? resolvedPlanModeDisabledReason : undefined, onClick: () => {
518
+ if (planModeDisabled)
519
+ return;
520
+ onChange("plan");
521
+ setOpen(false);
522
+ }, className: `flex w-full items-center gap-3 px-3 py-2 text-start ${planModeDisabled
523
+ ? "cursor-not-allowed opacity-60"
524
+ : "hover:bg-accent/50"}`, children: [_jsx(IconClipboardList, { className: "h-4 w-4 shrink-0 text-muted-foreground" }), _jsxs("div", { className: "flex-1 min-w-0", children: [_jsx("span", { className: "font-medium text-foreground text-[13px]", children: t("agentChat.composer.plan", { defaultValue: "Plan" }) }), _jsx("p", { className: "text-[11px] text-muted-foreground mt-0.5", children: planModeDisabled
525
+ ? resolvedPlanModeDisabledReason
526
+ : t("agentChat.composer.planDescription", {
527
+ defaultValue: "Read-only research and approval first",
528
+ }) })] }), mode === "plan" && !planModeDisabled && (_jsx(IconCheck, { className: "size-4 shrink-0 text-primary" }))] })] })] }));
529
+ }
530
+ const FRIENDLY_MODEL_NAMES = {
531
+ auto: "Default model",
532
+ "codex-cli": "Codex",
533
+ "claude-cli": "Claude Code",
534
+ "pi-cli": "Pi",
535
+ "opencode-cli": "OpenCode",
536
+ "claude-fable-5": "Fable 5",
537
+ "kimi-k2-5": "Kimi K2.5",
538
+ "deepseek-v3-1": "DeepSeek v3.1",
539
+ "z-ai/glm-5.2": "GLM 5.2",
540
+ };
541
+ const LOCAL_RUNTIME_ENGINES = new Set([
542
+ "codex-cli",
543
+ "claude-cli",
544
+ "pi-cli",
545
+ "opencode-cli",
546
+ ]);
547
+ function isOpenAiModelId(model) {
548
+ const normalizedModel = model.toLowerCase();
549
+ return (normalizedModel.startsWith("gpt-") ||
550
+ normalizedModel.startsWith("openai/gpt-"));
551
+ }
552
+ export function isOpenAiModelProviderGroup(group) {
553
+ const engine = group.engine.toLowerCase();
554
+ const label = group.label.toLowerCase();
555
+ if (engine === "codex-cli") {
556
+ return group.models.some(isOpenAiModelId);
557
+ }
558
+ return (engine.includes("openai") ||
559
+ label.includes("openai") ||
560
+ group.models.some(isOpenAiModelId));
561
+ }
562
+ const HARNESS_AGENTS_DOCS_URL = "https://www.agent-native.com/docs/harness-agents";
563
+ export const MODEL_SELECTOR_POPOVER_STYLE = {
564
+ fontSize: 13,
565
+ maxHeight: "min(500px, var(--radix-popover-content-available-height, 500px))",
566
+ };
567
+ const MODEL_SELECTOR_POPOVER_CLASS = "box-border w-64 rounded-lg border border-border bg-popover p-1 text-popover-foreground shadow-lg outline-none";
568
+ const PICKER_HELP_BUTTON_CLASS = "flex size-3 shrink-0 items-center justify-center rounded text-muted-foreground/60 hover:text-foreground";
569
+ const PICKER_HELP_ICON_CLASS = "size-2";
570
+ export function shouldShowModelSelectorSkeleton(isLoading, engineCount) {
571
+ return isLoading && engineCount === 0;
572
+ }
573
+ /**
574
+ * With nothing connected, every family is a dead "needs API key" row, so the
575
+ * picker shows only the connect CTAs. Never hide the list unless a CTA is
576
+ * there to replace it — an empty popover reads as more broken, not less.
577
+ */
578
+ export function shouldShowOnlyConnectPath(showBuilderCta, groups) {
579
+ return showBuilderCta && groups.every((group) => !group.configured);
580
+ }
581
+ function friendlyModelName(model, t) {
582
+ if (model === "auto") {
583
+ return (t?.("agentChat.composer.defaultModel", {
584
+ defaultValue: "Default model",
585
+ }) ?? "Default model");
586
+ }
587
+ if (FRIENDLY_MODEL_NAMES[model])
588
+ return FRIENDLY_MODEL_NAMES[model];
589
+ // Claude: claude-{tier}-{major}[-minor][-dateYYYYMMDD] → Tier Major[.Minor]
590
+ const claude = model.match(/^claude-(opus|sonnet|haiku)-(\d+)(?:-(\d+))?(?:-\d{8,})?$/);
591
+ if (claude) {
592
+ const tier = claude[1][0].toUpperCase() + claude[1].slice(1);
593
+ return `${tier} ${claude[2]}${claude[3] ? `.${claude[3]}` : ""}`;
594
+ }
595
+ // GPT: gpt-{major}-{minor}[-suffix] or gpt-{major}.{minor}[-suffix]
596
+ if (model.startsWith("gpt-")) {
597
+ const rest = model.slice(4);
598
+ const gpt = rest.match(/^(\d+)[.-](\d+)(?:[.-](.+))?$/);
599
+ if (gpt) {
600
+ const suffix = gpt[3]
601
+ ? " " +
602
+ gpt[3]
603
+ .split("-")
604
+ .map((s) => s[0].toUpperCase() + s.slice(1))
605
+ .join(" ")
606
+ : "";
607
+ return `GPT-${gpt[1]}.${gpt[2]}${suffix}`;
608
+ }
609
+ return `GPT-${rest}`;
610
+ }
611
+ if (/^o\d/.test(model))
612
+ return model;
613
+ // Gemini: gemini-{major}-{minor}-{variant}[-preview] → Gemini Major.Minor Variant
614
+ const geminiVersioned = model.match(/^gemini-(\d+)-(\d+)-(.+?)(?:-preview)?$/);
615
+ if (geminiVersioned) {
616
+ const variant = geminiVersioned[3]
617
+ .split("-")
618
+ .map((s) => s[0].toUpperCase() + s.slice(1))
619
+ .join(" ");
620
+ return `Gemini ${geminiVersioned[1]}.${geminiVersioned[2]} ${variant}`;
621
+ }
622
+ // Gemini: gemini-{version.parts}[-preview] → Gemini Version Parts
623
+ const gemini = model.match(/^gemini-(.+?)(?:-preview)?$/);
624
+ if (gemini) {
625
+ const parts = gemini[1]
626
+ .split("-")
627
+ .map((s) => s[0].toUpperCase() + s.slice(1))
628
+ .join(" ");
629
+ return `Gemini ${parts}`;
630
+ }
631
+ return model;
632
+ }
633
+ export function compactComposerModelName(model, t) {
634
+ const gpt56Variant = model.match(/^(?:openai\/)?gpt-5[.-]6[.-](sol|terra|luna)$/i)?.[1];
635
+ if (gpt56Variant) {
636
+ const variant = gpt56Variant[0].toUpperCase() + gpt56Variant.slice(1).toLowerCase();
637
+ return `GPT-5.6 ${variant}`;
638
+ }
639
+ return friendlyModelName(model, t);
640
+ }
641
+ export function compactComposerReasoningEffortLabel(effort, t) {
642
+ if (effort === "medium" || effort === "auto") {
643
+ return (t?.("agentChat.composer.reasoningMediumShort", {
644
+ defaultValue: "Med",
645
+ }) ?? "Med");
646
+ }
647
+ if (effort === "minimal") {
648
+ return (t?.("agentChat.composer.reasoningMinimalShort", {
649
+ defaultValue: "Min",
650
+ }) ?? "Min");
651
+ }
652
+ if (effort === "xhigh") {
653
+ return (t?.("agentChat.composer.reasoningExtraHighShort", {
654
+ defaultValue: "XHigh",
655
+ }) ?? "XHigh");
656
+ }
657
+ return t
658
+ ? localizedReasoningEffortLabel(t, effort, reasoningEffortLabel(effort))
659
+ : reasoningEffortLabel(effort);
660
+ }
661
+ function localizedReasoningEffortLabel(t, effort, defaultValue) {
662
+ switch (effort) {
663
+ case "auto":
664
+ return t("agentChat.composer.reasoningEffort.auto", { defaultValue });
665
+ case "none":
666
+ return t("agentChat.composer.reasoningEffort.none", { defaultValue });
667
+ case "minimal":
668
+ return t("agentChat.composer.reasoningEffort.minimal", { defaultValue });
669
+ case "low":
670
+ return t("agentChat.composer.reasoningEffort.low", { defaultValue });
671
+ case "medium":
672
+ return t("agentChat.composer.reasoningEffort.medium", { defaultValue });
673
+ case "high":
674
+ return t("agentChat.composer.reasoningEffort.high", { defaultValue });
675
+ case "xhigh":
676
+ return t("agentChat.composer.reasoningEffort.xhigh", { defaultValue });
677
+ case "max":
678
+ return t("agentChat.composer.reasoningEffort.max", { defaultValue });
679
+ }
680
+ }
681
+ /**
682
+ * Deduplicate models to only the latest version per family.
683
+ * e.g. [opus-4-7, opus-4-6, opus-4-5] → [opus-4-7]
684
+ */
685
+ function latestModelsOnly(models) {
686
+ const seen = new Set();
687
+ return models.filter((m) => {
688
+ // Claude: family = tier (opus/sonnet/haiku)
689
+ const claude = m.match(/^claude-(opus|sonnet|haiku)-/);
690
+ if (claude) {
691
+ if (seen.has(claude[1]))
692
+ return false;
693
+ seen.add(claude[1]);
694
+ return true;
695
+ }
696
+ // GPT: family = gpt-{major} (e.g. gpt-5.6-sol and gpt-5.6-luna are different)
697
+ // OpenAI effort: each is its own family
698
+ // Gemini: family = gemini-{major} + variant
699
+ const gemini = m.match(/^gemini-(\d+(?:\.\d+)?)-(.+?)(?:-preview)?$/);
700
+ if (gemini) {
701
+ const family = gemini[2]; // flash, pro, etc.
702
+ if (seen.has(`gemini-${family}`))
703
+ return false;
704
+ seen.add(`gemini-${family}`);
705
+ return true;
706
+ }
707
+ return true;
708
+ });
709
+ }
710
+ /**
711
+ * Coarse relative cost per model, rendered as a quiet `$`…`$$$` suffix.
712
+ *
713
+ * Tokens and their order mirror `MODEL_COST_ORDER` in `@agent-native/core`'s
714
+ * chat-model-groups, which sorts these same rows — the toolkit cannot import
715
+ * from core, so a new model family has to be added in both places. Tiers are
716
+ * each provider's own entry/mid/flagship ladder, not a cross-provider price
717
+ * claim; anything unlisted has no tier rather than a guessed one.
718
+ */
719
+ const MODEL_COST_TIERS = [
720
+ ["luna", 1],
721
+ ["terra", 2],
722
+ ["sol", 3],
723
+ ["haiku", 1],
724
+ ["sonnet", 2],
725
+ ["opus", 3],
726
+ ["fable", 3],
727
+ ["flash", 1],
728
+ ["pro", 3],
729
+ ];
730
+ export function composerModelCostTier(model) {
731
+ const normalized = model.toLowerCase();
732
+ return MODEL_COST_TIERS.find(([token]) => normalized.includes(token))?.[1];
733
+ }
734
+ function ModelCostTier({ model }) {
735
+ const t = useComposerRuntimeAdapters().translate;
736
+ const tier = composerModelCostTier(model);
737
+ if (!tier)
738
+ return null;
739
+ const costLabel = tier === 1
740
+ ? t("agentChat.composer.costLower", { defaultValue: "Lower cost" })
741
+ : tier === 2
742
+ ? t("agentChat.composer.costMedium", { defaultValue: "Medium cost" })
743
+ : t("agentChat.composer.costHigher", { defaultValue: "Higher cost" });
744
+ return _jsx("span", { className: "sr-only", children: costLabel });
745
+ }
746
+ export function getComposerReasoningEffortOptions(model) {
747
+ return model === "auto"
748
+ ? ["low", "medium", "high", "xhigh", "max"]
749
+ : getReasoningEffortOptionsForModel(model);
750
+ }
751
+ function ModelSelector({ model, effort, engines, agents, selectedAgent, agentOnly = false, hostedHarness = false, showAutoModelOption = true, modelListLoading = false, open: controlledOpen, onChange, onEffortChange, onAgentChange, onModelSelectorOpenChange, providerConnectStatusEnabled = true, onConnectProvider, onConnectLocalRuntime, imageModel, }) {
752
+ const adapters = useComposerRuntimeAdapters();
753
+ const t = adapters.translate;
754
+ const reasoning = adapters.models?.reasoning;
755
+ const defaultEffort = reasoning?.defaultEffort ?? DEFAULT_REASONING_EFFORT;
756
+ const [internalOpen, setInternalOpen] = useState(false);
757
+ const open = controlledOpen ?? internalOpen;
758
+ const isClaudeCodeAgent = isClaudeCodeAgentId(selectedAgent);
759
+ const autoModelGroup = showAutoModelOption
760
+ ? isClaudeCodeAgent
761
+ ? undefined
762
+ : engines.find((group) => group.models.includes("auto"))
763
+ : undefined;
764
+ const providerGroups = useMemo(() => engines
765
+ .map((group) => ({
766
+ ...group,
767
+ models: group.models.filter((candidate) => candidate !== "auto"),
768
+ }))
769
+ .filter((group) => group.models.length > 0), [engines]);
770
+ const isCodexAgent = selectedAgent === "codex" || selectedAgent === "codex-cli";
771
+ const modelProviderGroups = useMemo(() => {
772
+ const hasCodexLocalGroup = providerGroups.some((group) => group.engine === "codex-cli");
773
+ const groups = providerGroups.flatMap((group) => {
774
+ if (group.engine === "codex-cli") {
775
+ return isCodexAgent && isOpenAiModelProviderGroup(group) ? [group] : [];
776
+ }
777
+ if (isCodexAgent &&
778
+ hasCodexLocalGroup &&
779
+ group.engine === "ai-sdk:openai") {
780
+ return [];
781
+ }
782
+ if (LOCAL_RUNTIME_ENGINES.has(group.engine))
783
+ return [];
784
+ if (!isCodexAgent)
785
+ return [group];
786
+ if (!isOpenAiModelProviderGroup(group))
787
+ return [];
788
+ const isExplicitOpenAiProvider = group.engine.toLowerCase().includes("openai") ||
789
+ group.label.toLowerCase().includes("openai");
790
+ const models = isExplicitOpenAiProvider
791
+ ? group.models
792
+ : group.models.filter(isOpenAiModelId);
793
+ return models.length > 0 ? [{ ...group, models }] : [];
794
+ });
795
+ if (!isClaudeCodeAgent)
796
+ return groups;
797
+ return groups
798
+ .map((group) => ({
799
+ ...group,
800
+ models: group.models.filter((candidate) => !isLunaModel(candidate)),
801
+ }))
802
+ .filter((group) => group.models.length > 0);
803
+ }, [isClaudeCodeAgent, isCodexAgent, providerGroups]);
804
+ const preferredAgentModel = useMemo(() => resolvePreferredAgentModel(selectedAgent, providerGroups), [providerGroups, selectedAgent]);
805
+ useEffect(() => {
806
+ if (!isClaudeCodeAgent || !isLunaModel(model) || !preferredAgentModel) {
807
+ return;
808
+ }
809
+ if (preferredAgentModel.model === model &&
810
+ preferredAgentModel.engine ===
811
+ engines.find((group) => group.models.includes(model))?.engine) {
812
+ return;
813
+ }
814
+ onChange(preferredAgentModel.model, preferredAgentModel.engine);
815
+ }, [engines, isClaudeCodeAgent, model, onChange, preferredAgentModel]);
816
+ const effortOptions = agentOnly
817
+ ? []
818
+ : (reasoning?.getOptionsForModel?.(model) ??
819
+ getComposerReasoningEffortOptions(model));
820
+ const selectedEffort = reasoning?.resolve?.(model, effort) ??
821
+ resolveReasoningEffortSelection(model, effort ?? defaultEffort);
822
+ const effortLabel = useCallback((value) => localizedReasoningEffortLabel(t, value, (reasoning?.label ?? reasoningEffortLabel)(value)), [reasoning?.label, t]);
823
+ const selectedAgentOption = agents?.find((agent) => agent.id === (selectedAgent ?? "default"));
824
+ const selectedAgentLabel = selectedAgentOption?.label ?? "Default";
825
+ const selectedModelLabel = friendlyModelName(model, t).replace(/^GPT-/, "");
826
+ const [detailSection, setDetailSection] = useState(null);
827
+ const resolvedSection = detailSection ?? (agentOnly ? "agent" : "model");
828
+ const setPickerOpen = useCallback((nextOpen) => {
829
+ if (controlledOpen === undefined)
830
+ setInternalOpen(nextOpen);
831
+ if (nextOpen)
832
+ setDetailSection(agentOnly ? "agent" : null);
833
+ onModelSelectorOpenChange?.(nextOpen);
834
+ }, [agentOnly, controlledOpen, onModelSelectorOpenChange]);
835
+ const visibleProviderGroups = modelProviderGroups;
836
+ const showModelListSkeleton = shouldShowModelSelectorSkeleton(modelListLoading, engines.length);
837
+ // Keep setup actions beside model choices while any visible provider still
838
+ // needs configuration. The model rows remain visible so the user can see
839
+ // what becomes available after connecting or adding a key.
840
+ const builderFlow = adapters.builder.useConnectFlow({
841
+ enabled: providerConnectStatusEnabled,
842
+ trackingSource: "composer_builder_cta",
843
+ });
844
+ const hasConfiguredBuilderModels = providerGroups.some((group) => group.engine === "builder" && group.configured);
845
+ const hasConnectedSubscription = providerGroups.some((group) => group.configured && group.isSubscription);
846
+ const hasUnconfiguredVisibleModels = modelProviderGroups.some((group) => !group.configured);
847
+ const showBuilderAction = hasUnconfiguredVisibleModels &&
848
+ (Boolean(onConnectProvider) ||
849
+ (providerConnectStatusEnabled &&
850
+ !builderFlow.configured &&
851
+ !builderFlow.envManaged &&
852
+ !hasConfiguredBuilderModels &&
853
+ !hasConnectedSubscription));
854
+ const showAddKeysAction = hasUnconfiguredVisibleModels;
855
+ const showProviderActions = showBuilderAction || showAddKeysAction;
856
+ const onlyConnectPathAvailable = shouldShowOnlyConnectPath(showBuilderAction, providerGroups) &&
857
+ modelProviderGroups.length === 0;
858
+ const openLlmSettings = useCallback(() => {
859
+ try {
860
+ window.location.hash = "llm";
861
+ }
862
+ catch { }
863
+ window.dispatchEvent(new CustomEvent("agent-panel:open-settings"));
864
+ setPickerOpen(false);
865
+ }, [setPickerOpen]);
866
+ const connectLocalRuntime = useCallback((engine) => {
867
+ onConnectLocalRuntime?.(engine);
868
+ setPickerOpen(false);
869
+ }, [onConnectLocalRuntime, setPickerOpen]);
870
+ return (_jsxs(Popover, { open: open, onOpenChange: setPickerOpen, children: [_jsx(PopoverTrigger, { asChild: true, children: _jsxs("button", { type: "button", "data-agent-composer-slot": "model-button", "aria-label": `${t("agentChat.composer.model", {
871
+ defaultValue: "Model",
872
+ })}: ${friendlyModelName(model, t)}${effortOptions.length > 0
873
+ ? `. ${t("agentChat.composer.effort", {
874
+ defaultValue: "Effort",
875
+ })}: ${effortLabel(selectedEffort)}`
876
+ : ""}${selectedAgentOption && selectedAgentOption.id !== "default"
877
+ ? `. Agent: ${selectedAgentLabel}`
878
+ : ""}`, className: "agent-composer-model-button flex min-w-0 max-w-[10.5rem] shrink items-center gap-1 rounded-md px-2 py-1 text-[12px] font-medium text-muted-foreground hover:bg-accent/50 hover:text-foreground", children: [_jsxs("span", { className: "min-w-0 truncate", children: [selectedAgentOption?.icon ? (_jsx("span", { className: "me-1 inline-flex shrink-0 align-[-2px] text-muted-foreground", children: selectedAgentOption.icon })) : null, selectedAgentOption && selectedAgentOption.id !== "default"
879
+ ? selectedAgentLabel
880
+ : compactComposerModelName(model, t)] }), effortOptions.length > 0 && (_jsxs("span", { className: "agent-composer-model-effort min-w-0 shrink truncate text-muted-foreground/70", children: ["\u00B7 ", compactComposerReasoningEffortLabel(selectedEffort, t)] })), _jsx(IconChevronDown, { className: "h-3 w-3 shrink-0 opacity-60" })] }) }), _jsx(PopoverContent, { side: "top", align: "end", sideOffset: 6, collisionPadding: 8, "data-agent-native-composer-popover": "true", className: `z-[260] overflow-visible ${MODEL_SELECTOR_POPOVER_CLASS}`, style: MODEL_SELECTOR_POPOVER_STYLE, children: _jsxs(Popover, { open: detailSection !== null, onOpenChange: () => undefined, children: [_jsx(PopoverAnchor, { asChild: true, children: _jsxs("div", { className: "flex flex-col", role: "tablist", "aria-label": t("agentChat.composer.pickerSections", {
881
+ defaultValue: "Picker sections",
882
+ }), children: [agents && agents.length > 0 && (_jsxs("button", { type: "button", role: "tab", "aria-selected": resolvedSection === "agent", onClick: () => setDetailSection("agent"), onMouseEnter: () => setDetailSection("agent"), className: `flex w-full min-w-0 items-center gap-1 rounded-md px-2 py-2 text-start transition-colors ${resolvedSection === "agent"
883
+ ? "bg-accent text-foreground"
884
+ : "text-muted-foreground hover:bg-accent/50 hover:text-foreground"}`, children: [_jsxs("span", { className: "flex min-w-0 items-center", children: [_jsx("span", { className: "shrink-0 text-[12px] font-medium", children: "Agent" }), _jsxs(Tooltip, { children: [_jsx(TooltipTrigger, { asChild: true, children: _jsx("span", { role: "img", "aria-label": t("agentChat.composer.harnessAgentHelp", {
885
+ defaultValue: "Learn about harness agents",
886
+ }), onClick: (event) => event.stopPropagation(), className: `ms-1.5 ${PICKER_HELP_BUTTON_CLASS}`, children: _jsx(IconHelpCircle, { "aria-hidden": "true", className: PICKER_HELP_ICON_CLASS, strokeWidth: 1.8 }) }) }), _jsxs(TooltipContent, { side: "right", className: "z-[400] max-w-xs", children: [_jsx("span", { className: "block", children: hostedHarness
887
+ ? t("agentChat.composer.hostedHarnessDescription", {
888
+ defaultValue: "Hosted mode uses app tools only. For full coding with a repository and shell, use Agent Native Desktop.",
889
+ })
890
+ : t("agentChat.composer.harnessAgentDescription", {
891
+ defaultValue: "Harnesses run their own coding loop and local tools.",
892
+ }) }), _jsx("a", { href: HARNESS_AGENTS_DOCS_URL, target: "_blank", rel: "noreferrer", className: "mt-1 block underline underline-offset-2 hover:no-underline", children: t("agentChat.composer.learnMoreHarnessAgents", {
893
+ defaultValue: "Learn more about harness agents",
894
+ }) })] })] })] }), _jsx("span", { className: "ms-auto min-w-0 max-w-[6rem] truncate text-end text-[11px] text-muted-foreground/80", children: selectedAgentLabel }), _jsx(IconChevronRight, { className: "h-3 w-3 shrink-0 opacity-60 rtl:-scale-x-100" })] })), !agentOnly && (_jsxs("button", { type: "button", role: "tab", "aria-selected": resolvedSection === "model", onClick: () => setDetailSection("model"), onMouseEnter: () => setDetailSection("model"), className: `flex w-full min-w-0 items-center gap-1 rounded-md px-2 py-2 text-start transition-colors ${resolvedSection === "model"
895
+ ? "bg-accent text-foreground"
896
+ : "text-muted-foreground hover:bg-accent/50 hover:text-foreground"}`, children: [_jsx("span", { className: "shrink-0 text-[12px] font-medium", children: "Model" }), _jsx("span", { className: "ms-auto min-w-0 max-w-[6rem] truncate text-end text-[11px] text-muted-foreground/80", children: selectedModelLabel }), _jsx(IconChevronRight, { className: "h-3 w-3 shrink-0 opacity-60 rtl:-scale-x-100" })] })), !agentOnly && effortOptions.length > 0 && (_jsxs("button", { type: "button", role: "tab", "aria-selected": resolvedSection === "effort", onClick: () => setDetailSection("effort"), onMouseEnter: () => setDetailSection("effort"), className: `flex w-full min-w-0 items-center gap-1 rounded-md px-2 py-2 text-start transition-colors ${resolvedSection === "effort"
897
+ ? "bg-accent text-foreground"
898
+ : "text-muted-foreground hover:bg-accent/50 hover:text-foreground"}`, children: [_jsx("span", { className: "shrink-0 text-[12px] font-medium", children: t("agentChat.composer.effort", {
899
+ defaultValue: "Effort",
900
+ }) }), _jsx("span", { className: "ms-auto min-w-0 max-w-[6rem] truncate text-end text-[11px] text-muted-foreground/80", children: effortLabel(selectedEffort) }), _jsx(IconChevronRight, { className: "h-3 w-3 shrink-0 opacity-60 rtl:-scale-x-100" })] }))] }) }), _jsx(PopoverContent, { side: "right", align: "start", sideOffset: 4, alignOffset: -8, collisionPadding: 8, className: `z-[320] overflow-visible ${MODEL_SELECTOR_POPOVER_CLASS}`, style: MODEL_SELECTOR_POPOVER_STYLE, children: _jsx("div", { className: "max-h-[min(500px,var(--radix-popover-content-available-height,500px))] overflow-y-auto", children: _jsxs("div", { className: "min-h-0 min-w-0", role: "tabpanel", "aria-label": resolvedSection, children: [resolvedSection === "agent" && agents && (_jsx("div", { className: "flex flex-col", children: agents.map((agent) => {
901
+ const isSelected = agent.id === (selectedAgent ?? "default");
902
+ const isConfigured = agent.configured !== false;
903
+ const canConnect = !isConfigured && Boolean(onConnectLocalRuntime);
904
+ const statusLabel = agent.statusLabel ??
905
+ (!isConfigured ? "Unavailable" : undefined);
906
+ return (_jsxs("div", { className: "group flex items-center rounded-md hover:bg-accent/30", children: [_jsxs("button", { type: "button", disabled: !isConfigured || !onAgentChange, "aria-current": isSelected ? "true" : undefined, onClick: () => {
907
+ if (!isConfigured)
908
+ return;
909
+ onAgentChange?.(agent.id);
910
+ setPickerOpen(false);
911
+ }, className: `flex min-w-0 flex-1 items-center gap-0.5 px-2 py-2 text-start ${isConfigured
912
+ ? "hover:bg-accent/50"
913
+ : "cursor-default opacity-50"}`, children: [agent.icon ? (_jsx("span", { className: "flex size-4 shrink-0 items-center justify-center text-muted-foreground", "aria-hidden": "true", children: agent.icon })) : null, _jsx("span", { className: `min-w-0 truncate text-[12px] ${isSelected
914
+ ? "text-foreground"
915
+ : "text-muted-foreground"}`, children: agent.label }), agent.description && (_jsxs(Tooltip, { children: [_jsx(TooltipTrigger, { asChild: true, children: _jsx("span", { role: "img", "aria-label": `${agent.label} details`, onClick: (event) => event.stopPropagation(), className: PICKER_HELP_BUTTON_CLASS, children: _jsx(IconHelpCircle, { "aria-hidden": "true", className: PICKER_HELP_ICON_CLASS, strokeWidth: 1.8 }) }) }), _jsx(TooltipContent, { side: "left", className: "z-[400] max-w-xs", children: agent.description })] })), _jsx("span", { className: "min-w-0 flex-1", "aria-hidden": "true" }), isSelected && isConfigured && (_jsx(IconCheck, { className: "size-4 shrink-0 text-primary" }))] }), !isConfigured && statusLabel && (_jsx("button", { type: "button", disabled: !canConnect, className: "ms-auto max-w-[6rem] shrink-0 truncate px-2 py-2 text-end text-[10px] text-muted-foreground/70 opacity-0 transition-opacity group-hover:opacity-100 group-focus-within:opacity-100 hover:text-foreground focus-visible:opacity-100 disabled:cursor-default", onClick: () => {
916
+ if (canConnect)
917
+ connectLocalRuntime(agent.id);
918
+ }, children: statusLabel }))] }, agent.id));
919
+ }) })), resolvedSection === "model" && (_jsxs(_Fragment, { children: [showProviderActions && (_jsxs(_Fragment, { children: [showBuilderAction && (_jsxs(_Fragment, { children: [_jsxs("button", { type: "button", onClick: () => {
920
+ if (onConnectProvider) {
921
+ onConnectProvider();
922
+ }
923
+ else {
924
+ builderFlow.start();
925
+ }
926
+ }, disabled: !onConnectProvider && builderFlow.connecting, className: "flex w-full items-start gap-2 rounded-md px-2 py-2 text-start hover:bg-accent/50 disabled:opacity-60", children: [_jsx(IconPlugConnected, { className: "mt-0.5 h-4 w-4 shrink-0 text-primary" }), _jsxs("span", { className: "min-w-0 flex-1", children: [_jsx("span", { className: "block text-[12px] font-medium text-foreground", children: !onConnectProvider && builderFlow.connecting
927
+ ? t("agentPanel.connectingBuilder", {
928
+ defaultValue: "Connecting Builder.io…",
929
+ })
930
+ : t("agentPanel.connectBuilderIo", {
931
+ defaultValue: "Connect Builder.io",
932
+ }) }), _jsx("span", { className: "block text-[11px] text-muted-foreground", children: t("agentPanel.builderModelCredits", {
933
+ defaultValue: "Free credits for Claude, OpenAI & Gemini",
934
+ }) })] })] }), !onConnectProvider && builderFlow.error && (_jsx("p", { role: "alert", className: "px-2 pb-2 ps-8 text-[11px] text-destructive", children: builderFlow.error }))] })), showAddKeysAction && (_jsxs("button", { type: "button", onClick: openLlmSettings, className: "flex w-full items-start gap-2 rounded-md px-2 py-2 text-start hover:bg-accent/50", children: [_jsx(IconKey, { className: "mt-0.5 h-4 w-4 shrink-0 text-muted-foreground" }), _jsxs("span", { className: "min-w-0 flex-1", children: [_jsx("span", { className: "block text-[12px] font-medium text-foreground", children: t("agentPanel.addOwnKeys", {
935
+ defaultValue: "Add your own keys",
936
+ }) }), _jsx("span", { className: "block text-[11px] text-muted-foreground", children: t("agentPanel.configureProviderKeys", {
937
+ defaultValue: "Choose a cloud, gateway, or local provider",
938
+ }) })] })] }))] })), imageModel && imageModel.options.length > 0 && (_jsxs("div", { className: "mt-2 pt-1", children: [_jsx("div", { className: "px-2 py-1 text-[11px] font-medium uppercase tracking-wide text-muted-foreground", children: imageModel.label ??
939
+ t("agentChat.composer.imageModel", {
940
+ defaultValue: "Image model",
941
+ }) }), imageModel.options.map((option) => (_jsxs("button", { type: "button", onClick: () => {
942
+ imageModel.onChange(option.value);
943
+ setPickerOpen(false);
944
+ }, className: "flex w-full items-center gap-3 rounded-md px-2 py-2 text-start hover:bg-accent/50", children: [_jsx("span", { className: `min-w-0 flex-1 truncate text-[12px] ${option.value === imageModel.value
945
+ ? "text-foreground"
946
+ : "text-muted-foreground"}`, children: option.label }), option.value === imageModel.value && (_jsx(IconCheck, { className: "size-4 shrink-0 text-primary" }))] }, option.value)))] })), showModelListSkeleton && _jsx(ModelSelectorSkeleton, {}), isCodexAgent &&
947
+ !showModelListSkeleton &&
948
+ !onlyConnectPathAvailable &&
949
+ modelProviderGroups.length === 0 && (_jsxs("button", { type: "button", onClick: openLlmSettings, className: "flex w-full items-center rounded-md px-2 py-2 text-start hover:bg-accent/50", children: [_jsx("span", { className: "min-w-0 flex-1 truncate text-[12px] text-muted-foreground", children: t("agentChat.composer.noOpenAiModels", {
950
+ defaultValue: "No OpenAI models configured",
951
+ }) }), _jsx("span", { className: "shrink-0 text-[11px] text-muted-foreground/70", children: "Configure" })] })), autoModelGroup && !onlyConnectPathAvailable && (_jsxs("button", { type: "button", onClick: () => {
952
+ onChange("auto", autoModelGroup.engine);
953
+ setPickerOpen(false);
954
+ }, className: "mt-1 flex w-full items-center gap-3 rounded-md px-2 py-1.5 text-start hover:bg-accent/50", children: [_jsx("span", { className: `min-w-0 flex-1 truncate text-[13px] ${model === "auto"
955
+ ? "text-foreground"
956
+ : "text-muted-foreground"}`, children: t("agentChat.composer.auto", {
957
+ defaultValue: "Auto",
958
+ }) }), model === "auto" && (_jsx(IconCheck, { className: "size-4 shrink-0 text-primary" }))] })), !onlyConnectPathAvailable &&
959
+ visibleProviderGroups.map((group, groupIndex) => {
960
+ const models = latestModelsOnly(group.models);
961
+ const showProviderLabels = visibleProviderGroups.length > 1;
962
+ const isLocalRuntime = group.engine === "codex-cli" ||
963
+ group.engine === "claude-cli";
964
+ const canConnectLocalRuntime = isLocalRuntime && Boolean(onConnectLocalRuntime);
965
+ const statusLabel = group.statusLabel ??
966
+ (!group.configured
967
+ ? canConnectLocalRuntime
968
+ ? t("agentChat.auth.logIn", {
969
+ defaultValue: "Sign in",
970
+ })
971
+ : t("agentChat.composer.needsApiKey", {
972
+ defaultValue: "needs API key",
973
+ })
974
+ : undefined);
975
+ return (_jsxs("div", { className: showProviderLabels && groupIndex > 0
976
+ ? "mt-2 pt-1"
977
+ : "", children: [showProviderLabels && (_jsxs("div", { className: "group flex items-center px-2 py-1", children: [_jsx("span", { className: "shrink-0 text-[11px] font-medium uppercase tracking-wide text-muted-foreground", children: group.label }), !group.configured && statusLabel && (_jsx("button", { type: "button", "aria-label": statusLabel, className: "ms-auto max-w-[9rem] shrink-0 cursor-pointer truncate px-0 py-1 text-end text-[10px] text-muted-foreground/60 opacity-0 transition-opacity group-hover:opacity-100 group-focus-within:opacity-100 hover:text-foreground focus-visible:opacity-100", onClick: () => canConnectLocalRuntime
978
+ ? connectLocalRuntime(group.engine)
979
+ : openLlmSettings(), children: statusLabel })), group.configured && statusLabel && (_jsx("span", { className: "ms-auto max-w-[9rem] shrink-0 truncate py-1 text-end text-[10px] text-muted-foreground/70 opacity-0 transition-opacity group-hover:opacity-100 group-focus-within:opacity-100", children: statusLabel }))] })), models.map((m) => {
980
+ const isSelected = m === model && group.configured;
981
+ return (_jsxs("button", { type: "button", onClick: () => {
982
+ if (!group.configured) {
983
+ if (canConnectLocalRuntime) {
984
+ connectLocalRuntime(group.engine);
985
+ }
986
+ else {
987
+ openLlmSettings();
988
+ }
989
+ return;
990
+ }
991
+ onChange(m, group.engine);
992
+ const nextOptions = getReasoningEffortOptionsForModel(m);
993
+ if (nextOptions.length > 0 &&
994
+ !nextOptions.includes(selectedEffort)) {
995
+ onEffortChange?.(defaultEffort);
996
+ }
997
+ setPickerOpen(false);
998
+ }, className: `group flex w-full items-center gap-3 rounded-md px-2 py-2 text-start ${group.configured
999
+ ? "hover:bg-accent/50"
1000
+ : "cursor-default opacity-40"}`, children: [_jsx("span", { className: `min-w-0 flex-1 truncate text-[12px] ${isSelected
1001
+ ? "text-foreground"
1002
+ : "text-muted-foreground"}`, children: friendlyModelName(m, t) }), _jsx(ModelCostTier, { model: m }), !showProviderLabels && statusLabel && (_jsx("span", { className: "hidden max-w-[9rem] shrink-0 truncate text-[10px] text-muted-foreground/70 group-hover:inline", children: statusLabel })), isSelected && (_jsx(IconCheck, { className: "size-4 shrink-0 text-primary" }))] }, m));
1003
+ })] }, `${group.engine}:${group.label}`));
1004
+ })] })), resolvedSection === "effort" && effortOptions.length > 0 && (_jsx("div", { className: "flex flex-col", children: effortOptions.map((option) => (_jsxs("button", { type: "button", onClick: () => onEffortChange?.(option), className: "flex w-full items-center gap-3 rounded-md px-2 py-2 text-start hover:bg-accent/50", children: [_jsx("span", { className: `min-w-0 flex-1 truncate text-[12px] ${option === selectedEffort
1005
+ ? "text-foreground"
1006
+ : "text-muted-foreground"}`, children: effortLabel(option) }), option === selectedEffort && (_jsx(IconCheck, { className: "size-4 shrink-0 text-primary" }))] }, option))) }))] }) }) })] }) })] }));
1007
+ }
1008
+ function ModelSelectorSkeleton() {
1009
+ const t = useComposerRuntimeAdapters().translate;
1010
+ return (_jsxs("div", { className: "space-y-1 px-2 py-2", role: "status", "aria-label": t("agentChat.composer.loadingModels", {
1011
+ defaultValue: "Loading models",
1012
+ }), children: [_jsx("span", { className: "sr-only", children: t("agentChat.composer.loadingModelsProgress", {
1013
+ defaultValue: "Loading models…",
1014
+ }) }), ["w-24", "w-32", "w-20", "w-28"].map((width, index) => (_jsxs("div", { className: "flex items-center gap-1.5 px-1 py-1.5", children: [_jsx(Skeleton, { className: "size-3 rounded-sm" }), _jsx(Skeleton, { className: `h-3 ${width}` })] }, index)))] }));
1015
+ }
1016
+ export function TiptapComposer({ placeholder, disabled = false, maxDocumentAttachmentBytes = MAX_DOCUMENT_ATTACHMENT_BYTES, documentAttachmentLimitLabel = "PDFs", focusRef, initialText, initialTextKey, onSubmit, onBeforeSubmit, clearOnSubmit = true, onTextChange, actionButton, willQueue = false, extraActionButton, stopButton, attachButton, modeControl, toolbarSlot, layoutVariant = "default", slashCommands = [], slashSkills = [], includeDefaultSlashCommands = true, includeDefaultSlashSkills = true, onSlashCommand, execMode, onExecModeChange, planModeDisabled = false, planModeDisabledReason, voiceEnabled = DEFAULT_VOICE_DICTATION_ENABLED, selectedModel, selectedEffort, showAutoModelOption = true, modelSelectorOpen, availableModels, modelListLoading, onModelChange, onEffortChange, availableAgents, selectedAgent, agentOnly = false, hostedHarness, onAgentChange, onModelSelectorOpenChange, providerConnectStatusEnabled, onConnectProvider, onConnectLocalRuntime, imageModelMenu, draftScope, contextItems = [], onRemoveContextItem, plusMenuMode = "full", terminalModeControl, extensionTools = false, interceptBuildRequestsForBuilder = false, onAttachmentError, }) {
1017
+ const adapters = useComposerRuntimeAdapters();
1018
+ const t = adapters.translate;
1019
+ const sendButtonTooltip = t(getComposerSendTooltipKey(willQueue), {
1020
+ defaultValue: willQueue ? "Queue message" : "Send message",
1021
+ });
1022
+ const [popover, setPopover] = useState(null);
1023
+ const popoverRef = useRef(null);
1024
+ const composerRuntime = useComposerRuntime();
1025
+ const lastComposerRuntimeSyncRef = useRef(null);
1026
+ const submitInFlightRef = useRef(false);
1027
+ const [editorHasText, setEditorHasText] = useState(false);
1028
+ const [slotReferences, setSlotReferences] = useState([]);
1029
+ const [selectedContextItemKey, setSelectedContextItemKey] = useState(null);
1030
+ const composerText = useComposer((state) => state.text);
1031
+ const composerAttachments = useComposer((state) => state.attachments);
1032
+ const canSend = canSubmitComposerContent({
1033
+ hasEditorContent: editorHasText || slotReferences.length > 0,
1034
+ attachmentCount: composerAttachments.length,
1035
+ disabled,
1036
+ });
1037
+ const primaryAction = resolveComposerPrimaryAction({
1038
+ canSubmit: canSend,
1039
+ hasStopButton: Boolean(stopButton),
1040
+ });
1041
+ const hasContextRows = contextItems.length > 0 || slotReferences.length > 0;
1042
+ const [composerMode, setComposerMode] = useState(null);
1043
+ const composerModeRef = useRef(null);
1044
+ const isMac = typeof navigator !== "undefined" &&
1045
+ /Mac|iPhone|iPad/.test(navigator.userAgent);
1046
+ // Refs for values accessed in handleKeyDown (ProseMirror doesn't re-bind)
1047
+ const popoverStateRef = useRef(null);
1048
+ const onAttachmentErrorRef = useRef(onAttachmentError);
1049
+ onAttachmentErrorRef.current = onAttachmentError;
1050
+ const execModeRef = useRef(execMode);
1051
+ execModeRef.current = execMode;
1052
+ const onExecModeChangeRef = useRef(onExecModeChange);
1053
+ onExecModeChangeRef.current = onExecModeChange;
1054
+ const planModeDisabledRef = useRef(planModeDisabled);
1055
+ planModeDisabledRef.current = planModeDisabled;
1056
+ const { items: mentionItems, isLoading: mentionsLoading } = useMentionSearch(popover?.type === "@" ? popover.query : "", popover?.type === "@");
1057
+ const filteredMentionItems = useMemo(() => filterMentionItemsForSlots(mentionItems, slotReferences), [mentionItems, slotReferences]);
1058
+ const { skills, hint, isLoading: skillsLoading, } = useSkills(includeDefaultSlashSkills && popover?.type === "/");
1059
+ const allSlashCommands = useMemo(() => mergeSlashCommands([
1060
+ ...(includeDefaultSlashCommands ? builtInCommands(t) : []),
1061
+ ...slashCommands,
1062
+ ]), [includeDefaultSlashCommands, slashCommands, t]);
1063
+ const allSlashSkills = useMemo(() => mergeSlashSkills([
1064
+ ...(includeDefaultSlashSkills ? skills : []),
1065
+ ...slashSkills,
1066
+ ]), [includeDefaultSlashSkills, skills, slashSkills]);
1067
+ const filteredCommands = useMemo(() => {
1068
+ if (!popover || popover.type !== "/")
1069
+ return allSlashCommands;
1070
+ const q = popover.query.toLowerCase();
1071
+ if (!q)
1072
+ return allSlashCommands;
1073
+ return allSlashCommands.filter((c) => c.name.toLowerCase().includes(q) ||
1074
+ c.description.toLowerCase().includes(q));
1075
+ }, [allSlashCommands, popover]);
1076
+ const filteredSkills = useMemo(() => {
1077
+ if (!popover || popover.type !== "/")
1078
+ return allSlashSkills;
1079
+ const q = popover.query.toLowerCase();
1080
+ if (!q)
1081
+ return allSlashSkills;
1082
+ return allSlashSkills.filter((s) => s.name.toLowerCase().includes(q) ||
1083
+ s.description?.toLowerCase().includes(q));
1084
+ }, [allSlashSkills, popover]);
1085
+ // Keep refs in sync with state
1086
+ const mentionItemsRef = useRef(filteredMentionItems);
1087
+ mentionItemsRef.current = filteredMentionItems;
1088
+ const filteredCommandsRef = useRef(filteredCommands);
1089
+ filteredCommandsRef.current = filteredCommands;
1090
+ const filteredSkillsRef = useRef(filteredSkills);
1091
+ filteredSkillsRef.current = filteredSkills;
1092
+ const onSlashCommandRef = useRef(onSlashCommand);
1093
+ onSlashCommandRef.current = onSlashCommand;
1094
+ const onTextChangeRef = useRef(onTextChange);
1095
+ onTextChangeRef.current = onTextChange;
1096
+ const contextItemsRef = useRef(contextItems);
1097
+ contextItemsRef.current = contextItems;
1098
+ const onRemoveContextItemRef = useRef(onRemoveContextItem);
1099
+ onRemoveContextItemRef.current = onRemoveContextItem;
1100
+ const selectedContextItemKeyRef = useRef(null);
1101
+ selectedContextItemKeyRef.current = selectedContextItemKey;
1102
+ const initialTextKeyRef = useRef(undefined);
1103
+ const seenReferenceInsertIdsRef = useRef(new Set());
1104
+ useEffect(() => {
1105
+ if (selectedContextItemKey &&
1106
+ !contextItems.some((item) => item.key === selectedContextItemKey)) {
1107
+ selectedContextItemKeyRef.current = null;
1108
+ setSelectedContextItemKey(null);
1109
+ }
1110
+ }, [contextItems, selectedContextItemKey]);
1111
+ const closePopover = useCallback(() => {
1112
+ setPopover(null);
1113
+ popoverStateRef.current = null;
1114
+ }, []);
1115
+ // Persist draft to localStorage so hot-reloads don't lose the prompt
1116
+ const draftKey = getComposerDraftKey(draftScope);
1117
+ const draftTimerRef = useRef(undefined);
1118
+ useEffect(() => {
1119
+ return () => {
1120
+ clearTimeout(draftTimerRef.current);
1121
+ };
1122
+ }, []);
1123
+ useEffect(() => {
1124
+ lastComposerRuntimeSyncRef.current = null;
1125
+ }, [composerRuntime]);
1126
+ // Tiptap reads extension config once at init; ref keeps runtime prop
1127
+ // changes visible to Placeholder's function form.
1128
+ const resolvedPlaceholder = composerMode
1129
+ ? localizedComposerModeConfig(composerMode, t).placeholder
1130
+ : (placeholder ??
1131
+ t("agentChat.composer.messageAgent", {
1132
+ defaultValue: "Message agent...",
1133
+ }));
1134
+ const placeholderRef = useRef(resolvedPlaceholder);
1135
+ placeholderRef.current = resolvedPlaceholder;
1136
+ const editor = useEditor({
1137
+ extensions: createTiptapComposerExtensions(() => placeholderRef.current),
1138
+ editable: !disabled,
1139
+ onCreate: ({ editor: ed }) => {
1140
+ // Restore draft on mount
1141
+ try {
1142
+ if (initialText !== undefined) {
1143
+ ed.commands.setContent(plainTextToDoc(initialText));
1144
+ ed.commands.focus("end");
1145
+ setEditorHasText(composerDocumentHasContent(ed.state.doc));
1146
+ initialTextKeyRef.current = initialTextKey ?? initialText;
1147
+ }
1148
+ else {
1149
+ const saved = localStorage.getItem(draftKey);
1150
+ if (saved) {
1151
+ ed.commands.setContent(saved);
1152
+ ed.commands.focus("end");
1153
+ setEditorHasText(composerDocumentHasContent(ed.state.doc));
1154
+ }
1155
+ }
1156
+ onTextChangeRef.current?.(ed.state.doc.textContent.trim());
1157
+ }
1158
+ catch { }
1159
+ },
1160
+ onUpdate: ({ editor: ed }) => {
1161
+ // Drive the send button's enabled state from the actual editor contents;
1162
+ // the composer runtime is only synced on submit, so its isEmpty lags.
1163
+ setEditorHasText(composerDocumentHasContent(ed.state.doc));
1164
+ onTextChangeRef.current?.(ed.state.doc.textContent.trim());
1165
+ // Debounce-save draft to localStorage
1166
+ clearTimeout(draftTimerRef.current);
1167
+ draftTimerRef.current = setTimeout(() => {
1168
+ try {
1169
+ const html = ed.getHTML();
1170
+ const isEmpty = !composerDocumentHasContent(ed.state.doc);
1171
+ if (isEmpty) {
1172
+ localStorage.removeItem(draftKey);
1173
+ }
1174
+ else {
1175
+ localStorage.setItem(draftKey, html);
1176
+ }
1177
+ }
1178
+ catch { }
1179
+ }, 300);
1180
+ },
1181
+ onSelectionUpdate: ({ editor: ed }) => {
1182
+ const { from, to } = ed.state.selection;
1183
+ if (selectedContextItemKeyRef.current && (from !== to || from > 1)) {
1184
+ selectedContextItemKeyRef.current = null;
1185
+ setSelectedContextItemKey(null);
1186
+ }
1187
+ },
1188
+ editorProps: {
1189
+ attributes: {
1190
+ "data-agent-composer-variant": layoutVariant,
1191
+ "data-agent-composer-slot": "editor-input",
1192
+ class: "agent-composer-prosemirror flex-1 resize-none bg-transparent text-sm text-foreground outline-none leading-[1.625rem] min-h-[3.25rem] max-h-[10rem] overflow-y-auto",
1193
+ },
1194
+ handlePaste: (_view, event) => {
1195
+ const paste = readClipboardPaste(event.clipboardData);
1196
+ const pastedText = paste.text;
1197
+ const files = Array.from(event.clipboardData?.files ?? []).filter((file) => file.type.startsWith("image/"));
1198
+ if (files.length > 0) {
1199
+ event.preventDefault();
1200
+ const attachments = files.map((file) => {
1201
+ // SimpleImageAttachmentAdapter uses file.name as the attachment id.
1202
+ // Clipboard images (e.g. screenshots) are typically all named
1203
+ // "image.png", so a second paste would replace the first instead of
1204
+ // appending. Prepend a unique token so each paste gets a distinct id.
1205
+ const uniqueName = `${Date.now()}-${Math.random().toString(36).slice(2)}-${file.name}`;
1206
+ return new File([file], uniqueName, { type: file.type });
1207
+ });
1208
+ // Google Docs rich clipboard payloads can contain both embedded
1209
+ // image files and the document text. Since handling files means we
1210
+ // prevent Tiptap's default paste, preserve any text as its own chip
1211
+ // instead of silently dropping the source material.
1212
+ if (pastedText.trim()) {
1213
+ attachments.push(createPastedAttachmentFile(paste));
1214
+ }
1215
+ void Promise.all(attachments.map((file) => composerRuntime.addAttachment(file))).catch((error) => {
1216
+ const msg = error instanceof Error
1217
+ ? error.message
1218
+ : t("agentChat.composer.pastedImageError", {
1219
+ defaultValue: "Could not attach the pasted image. Try a different format.",
1220
+ });
1221
+ onAttachmentErrorRef.current?.(msg);
1222
+ });
1223
+ return true;
1224
+ }
1225
+ // Page-sized pastes turn into a `Pasted text` attachment chip so the
1226
+ // prompt stays readable while normal paragraphs and lists stay inline.
1227
+ // When the paste is HTML (e.g. an Alpine.js extension or a document the
1228
+ // user wants hosted), it's stored as a real .html attachment so it
1229
+ // travels the same rail as uploading that file — the agent reads it
1230
+ // verbatim via contentFromAttachment instead of retyping it inline,
1231
+ // which cuts off mid-stream on large files and triggers a spin.
1232
+ if (shouldConvertClipboardToAttachment(paste)) {
1233
+ event.preventDefault();
1234
+ void composerRuntime
1235
+ .addAttachment(createPastedAttachmentFile(paste))
1236
+ .catch((error) => {
1237
+ const msg = error instanceof Error
1238
+ ? error.message
1239
+ : t("agentChat.composer.pastedTextError", {
1240
+ defaultValue: "Could not attach the pasted text.",
1241
+ });
1242
+ onAttachmentErrorRef.current?.(msg);
1243
+ });
1244
+ return true;
1245
+ }
1246
+ return false;
1247
+ },
1248
+ handleDrop: (_view, event) => {
1249
+ // Drag-and-drop files (decks, images, PDFs, etc.) into the composer.
1250
+ // Mark handled drops as consumed so the chat-wide drop target does not
1251
+ // add the same file a second time.
1252
+ return handleComposerFileDrop({
1253
+ event: event,
1254
+ addAttachment: (file) => composerRuntime.addAttachment(file),
1255
+ onError: (error) => {
1256
+ const msg = error instanceof Error
1257
+ ? error.message
1258
+ : t("agentChat.composer.droppedFileError", {
1259
+ defaultValue: "Could not attach the dropped file. Try a different format.",
1260
+ });
1261
+ onAttachmentErrorRef.current?.(msg);
1262
+ },
1263
+ });
1264
+ },
1265
+ handleKeyDown: (view, event) => {
1266
+ const pop = popoverStateRef.current;
1267
+ // Handle popover keyboard nav
1268
+ if (pop) {
1269
+ if (event.key === "ArrowUp") {
1270
+ event.preventDefault();
1271
+ popoverRef.current?.moveUp();
1272
+ return true;
1273
+ }
1274
+ if (event.key === "ArrowDown") {
1275
+ event.preventDefault();
1276
+ popoverRef.current?.moveDown();
1277
+ return true;
1278
+ }
1279
+ if (event.key === "Enter") {
1280
+ event.preventDefault();
1281
+ const idx = popoverRef.current?.getSelectedIndex() ?? 0;
1282
+ const currentCommands = filteredCommandsRef.current;
1283
+ const currentSkills = filteredSkillsRef.current;
1284
+ if (pop.type === "@") {
1285
+ const item = popoverRef.current?.getSelectedMention();
1286
+ if (item)
1287
+ selectMention(view, pop, item);
1288
+ }
1289
+ else if (pop.type === "/") {
1290
+ const cmd = popoverRef.current?.getSelectedCommand();
1291
+ if (cmd) {
1292
+ executeCommand(view, pop, cmd);
1293
+ }
1294
+ else {
1295
+ const skillIdx = idx - currentCommands.length;
1296
+ if (currentSkills[skillIdx]) {
1297
+ selectSkill(view, pop, currentSkills[skillIdx]);
1298
+ }
1299
+ }
1300
+ }
1301
+ return true;
1302
+ }
1303
+ if (event.key === "Escape") {
1304
+ event.preventDefault();
1305
+ popoverStateRef.current = null;
1306
+ setPopover(null);
1307
+ return true;
1308
+ }
1309
+ if (event.key === " " && pop.query === "") {
1310
+ popoverStateRef.current = null;
1311
+ setPopover(null);
1312
+ return false;
1313
+ }
1314
+ }
1315
+ const { from, to } = view.state.selection;
1316
+ const cursorAtStart = from === to && from <= 1;
1317
+ if (event.key === "Backspace" && onRemoveContextItemRef.current) {
1318
+ const chipAction = resolveContextChipBackspaceAction({
1319
+ contextItemKeys: contextItemsRef.current.map((item) => item.key),
1320
+ selectedKey: selectedContextItemKeyRef.current,
1321
+ cursorAtStart,
1322
+ });
1323
+ if (chipAction) {
1324
+ event.preventDefault();
1325
+ if (chipAction.type === "select") {
1326
+ selectedContextItemKeyRef.current = chipAction.key;
1327
+ setSelectedContextItemKey(chipAction.key);
1328
+ }
1329
+ else {
1330
+ selectedContextItemKeyRef.current = null;
1331
+ setSelectedContextItemKey(null);
1332
+ contextItemsRef.current = contextItemsRef.current.filter((item) => item.key !== chipAction.key);
1333
+ onRemoveContextItemRef.current?.(chipAction.key);
1334
+ }
1335
+ return true;
1336
+ }
1337
+ }
1338
+ if (selectedContextItemKeyRef.current) {
1339
+ selectedContextItemKeyRef.current = null;
1340
+ setSelectedContextItemKey(null);
1341
+ }
1342
+ // Backspace removes composer mode chip when editor is empty
1343
+ if (event.key === "Backspace" && composerModeRef.current) {
1344
+ if (view.state.doc.textContent.trim() === "" &&
1345
+ from === to &&
1346
+ from <= 1) {
1347
+ setComposerMode(null);
1348
+ composerModeRef.current = null;
1349
+ return true;
1350
+ }
1351
+ }
1352
+ // Keyboard shortcut toggles Act/Plan mode from inside the editor.
1353
+ if (event.key === "Tab" && event.shiftKey) {
1354
+ event.preventDefault();
1355
+ const current = execModeRef.current;
1356
+ const cb = onExecModeChangeRef.current;
1357
+ if (current && cb) {
1358
+ const next = current === "build" ? "plan" : "build";
1359
+ if (next !== "plan" || !planModeDisabledRef.current) {
1360
+ cb(next);
1361
+ }
1362
+ }
1363
+ return true;
1364
+ }
1365
+ // Submit on Enter. Shift+Enter inserts a newline and keeps the
1366
+ // composer scrolled to the caret.
1367
+ // Cmd+Enter on macOS / Ctrl+Enter elsewhere marks the submit queued.
1368
+ if (event.key === "Enter" && event.shiftKey) {
1369
+ event.preventDefault();
1370
+ return insertComposerHardBreakAndScrollIntoView(view);
1371
+ }
1372
+ const submitIntent = getComposerSubmitIntentForEnterKey(event, isMac);
1373
+ if (submitIntent) {
1374
+ event.preventDefault();
1375
+ void submitComposer(submitIntent);
1376
+ return true;
1377
+ }
1378
+ // Detect @ trigger — only when preceded by start-of-text, space, or newline
1379
+ // (not after alphanumeric chars, which would indicate an email address)
1380
+ if (event.key === "@") {
1381
+ const { from } = view.state.selection;
1382
+ const textBefore = view.state.doc.textBetween(Math.max(0, from - 1), from);
1383
+ if (from === 1 || textBefore === "" || /\s/.test(textBefore)) {
1384
+ const position = getComposerPopoverPosition(view, from);
1385
+ if (!position)
1386
+ return false;
1387
+ setTimeout(() => {
1388
+ const state = {
1389
+ type: "@",
1390
+ position,
1391
+ startPos: view.state.selection.from,
1392
+ query: "",
1393
+ };
1394
+ popoverStateRef.current = state;
1395
+ setPopover(state);
1396
+ }, 0);
1397
+ }
1398
+ return false;
1399
+ }
1400
+ // Detect / trigger (only at start of line or after whitespace)
1401
+ if (event.key === "/") {
1402
+ const { from } = view.state.selection;
1403
+ const textBefore = view.state.doc.textBetween(Math.max(0, from - 1), from);
1404
+ if (from === 1 || textBefore === "" || /\s/.test(textBefore)) {
1405
+ const position = getComposerPopoverPosition(view, from);
1406
+ if (!position)
1407
+ return false;
1408
+ setTimeout(() => {
1409
+ const state = {
1410
+ type: "/",
1411
+ position,
1412
+ startPos: view.state.selection.from,
1413
+ query: "",
1414
+ };
1415
+ popoverStateRef.current = state;
1416
+ setPopover(state);
1417
+ }, 0);
1418
+ }
1419
+ return false;
1420
+ }
1421
+ return false;
1422
+ },
1423
+ },
1424
+ });
1425
+ // Placeholder decorations are computed by ProseMirror. Dispatching an empty
1426
+ // transaction makes a locale or composer-mode change visible immediately.
1427
+ useEffect(() => {
1428
+ if (!isComposerEditorUsable(editor))
1429
+ return;
1430
+ editor.view.dispatch(editor.state.tr.setSelection(editor.state.selection));
1431
+ }, [editor, resolvedPlaceholder]);
1432
+ // A tab can stay mounted while becoming the active composer later. Publish
1433
+ // its existing draft when the host starts observing it so contextual UI is
1434
+ // correct immediately after a tab switch, not only after the next keystroke.
1435
+ useEffect(() => {
1436
+ if (!isComposerEditorUsable(editor) || !onTextChange)
1437
+ return;
1438
+ onTextChange(editor.state.doc.textContent.trim());
1439
+ }, [editor, onTextChange]);
1440
+ const insertReference = useCallback((ref) => {
1441
+ const normalized = adapters.agentChat.normalizeReference(ref);
1442
+ const ed = editor;
1443
+ if (!normalized || !isComposerEditorUsable(ed))
1444
+ return;
1445
+ if (normalized.slotKey) {
1446
+ setSlotReferences((current) => applySlotReferenceChanges(current, [normalized]));
1447
+ ed.commands.focus("end");
1448
+ return;
1449
+ }
1450
+ if (normalized.relatedReferences?.some((item) => item.slotKey)) {
1451
+ setSlotReferences((current) => applySlotReferenceChanges(current, normalized.relatedReferences ?? []));
1452
+ }
1453
+ ed.chain()
1454
+ .focus()
1455
+ .insertContent({
1456
+ type: "mentionReference",
1457
+ attrs: mentionReferenceAttrs(normalized),
1458
+ })
1459
+ .insertContent(" ")
1460
+ .run();
1461
+ setEditorHasText(true);
1462
+ }, [editor]);
1463
+ const insertReferenceIfEmpty = useCallback((payload) => {
1464
+ const insertMessageId = typeof payload.insertMessageId === "string"
1465
+ ? payload.insertMessageId
1466
+ : "";
1467
+ if (insertMessageId) {
1468
+ if (seenReferenceInsertIdsRef.current.has(insertMessageId))
1469
+ return;
1470
+ seenReferenceInsertIdsRef.current.add(insertMessageId);
1471
+ }
1472
+ const ed = editor;
1473
+ if (!isComposerEditorUsable(ed) || disabled || composerModeRef.current)
1474
+ return;
1475
+ const normalized = adapters.agentChat.normalizeReference(payload);
1476
+ if (normalized?.slotKey) {
1477
+ insertReference(normalized);
1478
+ return;
1479
+ }
1480
+ if (composerAttachments.length > 0)
1481
+ return;
1482
+ if (composerDocumentHasContent(ed.state.doc))
1483
+ return;
1484
+ insertReference(payload);
1485
+ }, [composerAttachments.length, disabled, editor, insertReference]);
1486
+ useEffect(() => {
1487
+ if (typeof window === "undefined")
1488
+ return;
1489
+ const handleEvent = (event) => {
1490
+ const payload = event.detail;
1491
+ const normalized = adapters.agentChat.normalizeReference(payload);
1492
+ if (!normalized)
1493
+ return;
1494
+ insertReferenceIfEmpty({
1495
+ ...normalized,
1496
+ insertMessageId: typeof payload?.insertMessageId === "string"
1497
+ ? payload.insertMessageId
1498
+ : "",
1499
+ });
1500
+ };
1501
+ const handleMessage = (event) => {
1502
+ if (!adapters.builder.isTrustedFrameMessage(event) &&
1503
+ !adapters.builder.isTrustedBuilderMessage(event)) {
1504
+ return;
1505
+ }
1506
+ if (event.data?.type !== AGENT_CHAT_INSERT_REFERENCE_MESSAGE_TYPE) {
1507
+ return;
1508
+ }
1509
+ const payload = event.data.data;
1510
+ const normalized = adapters.agentChat.normalizeReference(payload);
1511
+ if (!normalized)
1512
+ return;
1513
+ insertReferenceIfEmpty({
1514
+ ...normalized,
1515
+ insertMessageId: typeof payload?.insertMessageId === "string"
1516
+ ? payload.insertMessageId
1517
+ : "",
1518
+ });
1519
+ };
1520
+ window.addEventListener(AGENT_CHAT_INSERT_REFERENCE_EVENT, handleEvent);
1521
+ window.addEventListener("message", handleMessage);
1522
+ return () => {
1523
+ window.removeEventListener(AGENT_CHAT_INSERT_REFERENCE_EVENT, handleEvent);
1524
+ window.removeEventListener("message", handleMessage);
1525
+ };
1526
+ }, [adapters, insertReferenceIfEmpty]);
1527
+ useImperativeHandle(focusRef, () => ({
1528
+ focus() {
1529
+ if (isComposerEditorUsable(editor))
1530
+ editor.commands.focus("end");
1531
+ },
1532
+ setText(text) {
1533
+ if (!isComposerEditorUsable(editor))
1534
+ return;
1535
+ editor.commands.setContent(plainTextToDoc(text));
1536
+ editor.commands.focus("end");
1537
+ const trimmed = editor.state.doc.textContent.trim();
1538
+ setEditorHasText(trimmed.length > 0);
1539
+ setSlotReferences([]);
1540
+ composerRuntime.setText(trimmed);
1541
+ onTextChangeRef.current?.(trimmed);
1542
+ try {
1543
+ if (trimmed) {
1544
+ localStorage.setItem(draftKey, editor.getHTML());
1545
+ }
1546
+ else {
1547
+ localStorage.removeItem(draftKey);
1548
+ }
1549
+ }
1550
+ catch { }
1551
+ },
1552
+ insertReference,
1553
+ }));
1554
+ const handleSelectMode = useCallback((mode) => {
1555
+ setComposerMode(mode);
1556
+ composerModeRef.current = mode;
1557
+ setTimeout(() => {
1558
+ if (isComposerEditorUsable(editor))
1559
+ editor.commands.focus("end");
1560
+ }, 50);
1561
+ }, [editor]);
1562
+ // --- Live voice transcription: text appears in the editor as the user speaks ---
1563
+ const voiceAnchorRef = useRef(null);
1564
+ const prevVoiceInsertRef = useRef("");
1565
+ const handleLiveUpdate = useCallback((finalText, interimText) => {
1566
+ const ed = editor;
1567
+ if (!isComposerEditorUsable(ed))
1568
+ return;
1569
+ if (voiceAnchorRef.current == null) {
1570
+ const { from } = ed.state.selection;
1571
+ const prevChar = from > 1 ? ed.state.doc.textBetween(from - 1, from) : "";
1572
+ if (prevChar && !/\s/.test(prevChar)) {
1573
+ ed.chain().insertContent(" ").run();
1574
+ }
1575
+ voiceAnchorRef.current = ed.state.selection.from;
1576
+ prevVoiceInsertRef.current = "";
1577
+ }
1578
+ const anchor = voiceAnchorRef.current;
1579
+ const prevLen = prevVoiceInsertRef.current.length;
1580
+ const newText = finalText + interimText;
1581
+ if (newText === prevVoiceInsertRef.current)
1582
+ return;
1583
+ ed.chain()
1584
+ .deleteRange({ from: anchor, to: anchor + prevLen })
1585
+ .insertContentAt(anchor, newText)
1586
+ .run();
1587
+ prevVoiceInsertRef.current = newText;
1588
+ }, [editor]);
1589
+ const insertTranscript = useCallback((text) => {
1590
+ const ed = editor;
1591
+ if (!isComposerEditorUsable(ed))
1592
+ return;
1593
+ const formattedText = formatVoiceTranscriptForComposer(text);
1594
+ const anchor = voiceAnchorRef.current;
1595
+ if (anchor != null) {
1596
+ const prevLen = prevVoiceInsertRef.current.length;
1597
+ if (formattedText) {
1598
+ ed.chain()
1599
+ .focus()
1600
+ .deleteRange({ from: anchor, to: anchor + prevLen })
1601
+ .insertContentAt(anchor, formattedText)
1602
+ .run();
1603
+ }
1604
+ else if (prevLen > 0) {
1605
+ ed.chain()
1606
+ .deleteRange({ from: anchor, to: anchor + prevLen })
1607
+ .run();
1608
+ }
1609
+ voiceAnchorRef.current = null;
1610
+ prevVoiceInsertRef.current = "";
1611
+ }
1612
+ else if (formattedText) {
1613
+ const { from } = ed.state.selection;
1614
+ const prevChar = from > 1 ? ed.state.doc.textBetween(from - 1, from) : "";
1615
+ const needsLead = prevChar && !/\s/.test(prevChar);
1616
+ ed.chain()
1617
+ .focus()
1618
+ .insertContent((needsLead ? " " : "") + formattedText)
1619
+ .run();
1620
+ }
1621
+ }, [editor]);
1622
+ const buildVoiceContextPack = useCallback(() => {
1623
+ const snippets = [];
1624
+ const activeContext = trimVoiceContextValue(adapters.agentChat.formatContextItems(contextItems) ||
1625
+ formatPromptContextItems(contextItems), 3200);
1626
+ if (activeContext) {
1627
+ snippets.push({
1628
+ label: t("agentChat.composer.activeAppContext", {
1629
+ defaultValue: "Active app context",
1630
+ }),
1631
+ value: activeContext,
1632
+ });
1633
+ }
1634
+ const selectedReferences = trimVoiceContextValue(slotReferences.map((ref) => slotReferenceTitle(ref)).join(", "), 1200);
1635
+ if (selectedReferences) {
1636
+ snippets.push({
1637
+ label: t("agentChat.composer.selectedReferences", {
1638
+ defaultValue: "Selected references",
1639
+ }),
1640
+ value: selectedReferences,
1641
+ });
1642
+ }
1643
+ const draft = isComposerEditorUsable(editor)
1644
+ ? trimVoiceContextValue(editor.state.doc.textContent, 1200)
1645
+ : null;
1646
+ if (draft) {
1647
+ snippets.push({
1648
+ label: t("agentChat.composer.currentDraft", {
1649
+ defaultValue: "Current draft",
1650
+ }),
1651
+ value: draft,
1652
+ });
1653
+ }
1654
+ if (typeof document !== "undefined") {
1655
+ const title = trimVoiceContextValue(document.title, 160);
1656
+ if (title) {
1657
+ snippets.push({
1658
+ label: t("agentChat.composer.pageTitle", {
1659
+ defaultValue: "Page title",
1660
+ }),
1661
+ value: title,
1662
+ });
1663
+ }
1664
+ }
1665
+ if (typeof window !== "undefined") {
1666
+ const route = trimVoiceContextValue(window.location.pathname, 240);
1667
+ if (route) {
1668
+ snippets.push({
1669
+ label: t("agentChat.composer.route", { defaultValue: "Route" }),
1670
+ value: route,
1671
+ });
1672
+ }
1673
+ }
1674
+ if (snippets.length === 0)
1675
+ return undefined;
1676
+ return {
1677
+ surface: "agent-composer",
1678
+ mode: "dictation",
1679
+ snippets,
1680
+ };
1681
+ }, [adapters, contextItems, editor, slotReferences, t]);
1682
+ const voice = useVoiceDictation({
1683
+ onTranscript: insertTranscript,
1684
+ onLiveUpdate: handleLiveUpdate,
1685
+ contextPack: buildVoiceContextPack,
1686
+ });
1687
+ // Clean up live text if voice session ends without a final transcript (cancel/error)
1688
+ useEffect(() => {
1689
+ if (voice.state === "idle" && voiceAnchorRef.current != null) {
1690
+ const anchor = voiceAnchorRef.current;
1691
+ const prevLen = prevVoiceInsertRef.current.length;
1692
+ if (isComposerEditorUsable(editor) && prevLen > 0) {
1693
+ const documentSize = editor.state.doc.content.size;
1694
+ const currentText = anchor >= 1 && anchor + prevLen <= documentSize
1695
+ ? editor.state.doc.textBetween(anchor, anchor + prevLen, "", "\n")
1696
+ : "";
1697
+ if (canRemoveVoicePreview({
1698
+ documentSize,
1699
+ anchor,
1700
+ previewText: prevVoiceInsertRef.current,
1701
+ currentText,
1702
+ })) {
1703
+ editor
1704
+ .chain()
1705
+ .deleteRange({ from: anchor, to: anchor + prevLen })
1706
+ .run();
1707
+ }
1708
+ }
1709
+ voiceAnchorRef.current = null;
1710
+ prevVoiceInsertRef.current = "";
1711
+ }
1712
+ }, [voice.state, editor]);
1713
+ // Global shortcut: Cmd/Ctrl + Shift + M toggles dictation. Escape cancels
1714
+ // while recording. Scoped to avoid firing when focus is outside the app.
1715
+ useEffect(() => {
1716
+ if (!voiceEnabled || !voice.supported)
1717
+ return;
1718
+ const handler = (e) => {
1719
+ // e.key can be undefined on some trusted keydown events (autofill/IME
1720
+ // quirks) — seen crashing in production (AGENT-NATIVE-BROWSER-S).
1721
+ const isToggleCombo = typeof e.key === "string" &&
1722
+ e.key.toLowerCase() === "m" &&
1723
+ e.shiftKey &&
1724
+ (e.metaKey || e.ctrlKey) &&
1725
+ !e.altKey;
1726
+ if (isToggleCombo) {
1727
+ e.preventDefault();
1728
+ if (voice.state === "recording" || voice.state === "starting") {
1729
+ voice.stop();
1730
+ }
1731
+ else if (voice.state !== "transcribing") {
1732
+ void voice.start();
1733
+ }
1734
+ return;
1735
+ }
1736
+ if (e.key === "Escape" &&
1737
+ (voice.state === "recording" || voice.state === "starting")) {
1738
+ e.preventDefault();
1739
+ voice.cancel();
1740
+ }
1741
+ };
1742
+ window.addEventListener("keydown", handler);
1743
+ return () => window.removeEventListener("keydown", handler);
1744
+ }, [voiceEnabled, voice]);
1745
+ const extractComposerPayload = useCallback(() => {
1746
+ const ed = editor;
1747
+ if (!isComposerEditorUsable(ed)) {
1748
+ return {
1749
+ text: slotReferences.map((ref) => slotReferenceTitle(ref)).join(", "),
1750
+ references: slotReferences.map(referenceFromComposerReference),
1751
+ };
1752
+ }
1753
+ const references = slotReferences.map(referenceFromComposerReference);
1754
+ // Build text that preserves @mentions (getText() strips them).
1755
+ // Walk the document and reconstruct with @name for mention/file/skill nodes.
1756
+ const textParts = [];
1757
+ ed.state.doc.descendants((node) => {
1758
+ if (node.isText) {
1759
+ textParts.push(node.text);
1760
+ }
1761
+ else if (node.type.name === "mentionReference") {
1762
+ textParts.push(`@[${node.attrs.label}|${node.attrs.icon || "file"}]`);
1763
+ }
1764
+ else if (node.type.name === "fileReference") {
1765
+ const label = node.attrs.path?.split("/").pop() || node.attrs.path;
1766
+ textParts.push(`@[${label}|file]`);
1767
+ }
1768
+ else if (node.type.name === "skillReference") {
1769
+ textParts.push(`/${node.attrs.name}`);
1770
+ }
1771
+ else if (node.type.name === "hardBreak") {
1772
+ textParts.push("\n");
1773
+ }
1774
+ else if (node.type.name === "paragraph" &&
1775
+ textParts.length > 0 &&
1776
+ textParts[textParts.length - 1] !== "\n") {
1777
+ textParts.push("\n");
1778
+ }
1779
+ });
1780
+ const rawText = textParts.join("").trim();
1781
+ const text = rawText ||
1782
+ slotReferences.map((ref) => slotReferenceTitle(ref)).join(", ");
1783
+ ed.state.doc.descendants((node) => {
1784
+ if (node.type.name === "fileReference") {
1785
+ // Legacy support
1786
+ references.push({
1787
+ type: "file",
1788
+ path: node.attrs.path,
1789
+ name: node.attrs.path?.split("/").pop() || node.attrs.path,
1790
+ source: node.attrs.source || "codebase",
1791
+ });
1792
+ }
1793
+ else if (node.type.name === "mentionReference") {
1794
+ const refType = node.attrs.refType;
1795
+ references.push({
1796
+ type: refType === "file"
1797
+ ? "file"
1798
+ : refType === "agent"
1799
+ ? "agent"
1800
+ : refType === "custom-agent"
1801
+ ? "custom-agent"
1802
+ : "mention",
1803
+ path: node.attrs.refPath || "",
1804
+ name: node.attrs.label,
1805
+ source: node.attrs.source,
1806
+ refType: node.attrs.refType,
1807
+ refId: node.attrs.refId,
1808
+ slotKey: node.attrs.slotKey,
1809
+ slotLabel: node.attrs.slotLabel,
1810
+ metadata: node.attrs.metadata,
1811
+ });
1812
+ }
1813
+ else if (node.type.name === "skillReference") {
1814
+ references.push({
1815
+ type: "skill",
1816
+ path: node.attrs.path,
1817
+ name: node.attrs.name,
1818
+ source: node.attrs.source || "codebase",
1819
+ });
1820
+ }
1821
+ });
1822
+ return { text, references };
1823
+ }, [editor, slotReferences]);
1824
+ const syncComposerRuntimeState = useCallback((text, references) => {
1825
+ const requestMode = execMode === "plan" ? "plan" : execMode === "build" ? "act" : undefined;
1826
+ const custom = {};
1827
+ if (references.length > 0) {
1828
+ custom.references = references;
1829
+ }
1830
+ if (requestMode) {
1831
+ custom.requestMode = requestMode;
1832
+ }
1833
+ const runConfig = Object.keys(custom).length > 0 ? { custom } : {};
1834
+ const runConfigSignature = JSON.stringify(runConfig);
1835
+ const last = lastComposerRuntimeSyncRef.current;
1836
+ if (last?.text === text &&
1837
+ last.runConfigSignature === runConfigSignature) {
1838
+ return;
1839
+ }
1840
+ composerRuntime.setText(text);
1841
+ composerRuntime.setRunConfig(runConfig);
1842
+ lastComposerRuntimeSyncRef.current = { text, runConfigSignature };
1843
+ }, [composerRuntime, execMode]);
1844
+ const resetComposerRuntimeState = useCallback(() => {
1845
+ const runConfigSignature = "{}";
1846
+ const last = lastComposerRuntimeSyncRef.current;
1847
+ if (last?.text === "" && last.runConfigSignature === runConfigSignature) {
1848
+ return;
1849
+ }
1850
+ composerRuntime.setText("");
1851
+ composerRuntime.setRunConfig({});
1852
+ lastComposerRuntimeSyncRef.current = { text: "", runConfigSignature };
1853
+ }, [composerRuntime]);
1854
+ const syncComposerState = useCallback(() => {
1855
+ const { text, references } = extractComposerPayload();
1856
+ syncComposerRuntimeState(text, references);
1857
+ return { text, references };
1858
+ }, [extractComposerPayload, syncComposerRuntimeState]);
1859
+ const clearEditorAfterSubmit = useCallback(() => {
1860
+ const ed = editor;
1861
+ if (!isComposerEditorUsable(ed))
1862
+ return;
1863
+ ed.commands.clearContent();
1864
+ setEditorHasText(false);
1865
+ setSlotReferences([]);
1866
+ resetComposerRuntimeState();
1867
+ try {
1868
+ localStorage.removeItem(draftKey);
1869
+ }
1870
+ catch { }
1871
+ closePopover();
1872
+ }, [closePopover, draftKey, editor, resetComposerRuntimeState]);
1873
+ const submitComposer = useCallback(async (intent = "immediate") => {
1874
+ const ed = editor;
1875
+ if (!isComposerEditorUsable(ed))
1876
+ return;
1877
+ if (submitInFlightRef.current)
1878
+ return;
1879
+ const { text, references } = syncComposerState();
1880
+ const attachments = composerRuntime.getState().attachments;
1881
+ if (!text.trim() && references.length === 0 && attachments.length === 0)
1882
+ return;
1883
+ const oversizedDocumentError = getOversizedDocumentAttachmentError(attachments, {
1884
+ maxBytes: maxDocumentAttachmentBytes,
1885
+ label: documentAttachmentLimitLabel,
1886
+ translate: t,
1887
+ });
1888
+ if (oversizedDocumentError) {
1889
+ onAttachmentErrorRef.current?.(oversizedDocumentError);
1890
+ return;
1891
+ }
1892
+ const cancelActiveVoice = () => {
1893
+ if (voice.state === "recording" ||
1894
+ voice.state === "starting" ||
1895
+ voice.state === "transcribing") {
1896
+ voice.cancel();
1897
+ }
1898
+ };
1899
+ // Intercept slash commands typed directly (e.g. "/clear" + Enter)
1900
+ const trimmed = text.trim();
1901
+ if (trimmed.startsWith("/") && references.length === 0) {
1902
+ const cmdName = normalizeSlashCommandName(trimmed);
1903
+ const matched = allSlashCommands.find((c) => c.name === cmdName);
1904
+ if (matched) {
1905
+ clearEditorAfterSubmit();
1906
+ onSlashCommandRef.current?.(matched.name);
1907
+ return;
1908
+ }
1909
+ }
1910
+ // Builder iframe delegation: when this app is mounted inside the
1911
+ // Builder.io webview and the user typed a "build me an app/agent"
1912
+ // prompt, hand it up to the parent Builder chat instead of sending
1913
+ // it to this app's domain agent. Builder is the code-writing agent;
1914
+ // the local agent (dispatch, mail, etc.) cannot scaffold workspace
1915
+ // apps from inside its own iframe.
1916
+ if (!composerMode &&
1917
+ interceptBuildRequestsForBuilder &&
1918
+ adapters.builder.tryDelegateBuildRequest(trimmed)) {
1919
+ cancelActiveVoice();
1920
+ clearEditorAfterSubmit();
1921
+ return;
1922
+ }
1923
+ if (onBeforeSubmit) {
1924
+ submitInFlightRef.current = true;
1925
+ try {
1926
+ const shouldSubmit = await onBeforeSubmit();
1927
+ if (!shouldSubmit)
1928
+ return;
1929
+ }
1930
+ finally {
1931
+ submitInFlightRef.current = false;
1932
+ }
1933
+ }
1934
+ if (!isComposerEditorUsable(ed))
1935
+ return;
1936
+ // Composer mode: send with context via agent chat bridge
1937
+ if (composerMode) {
1938
+ const config = localizedComposerModeConfig(composerMode, t);
1939
+ config.beforeSend?.();
1940
+ const message = displayableComposerModeMessage({
1941
+ messagePrefix: config.messagePrefix,
1942
+ trimmedText: trimmed,
1943
+ attachmentCount: attachments.length,
1944
+ attachedContextFallback: t("agentChat.composer.useAttachedContext", {
1945
+ defaultValue: "Use the attached context.",
1946
+ }),
1947
+ });
1948
+ const modePrompt = trimmed ||
1949
+ (attachments.length > 0
1950
+ ? t("agentChat.composer.useAttachedContext", {
1951
+ defaultValue: "Use the attached context.",
1952
+ })
1953
+ : "");
1954
+ if (attachments.length > 0) {
1955
+ composerRuntime.setText(`${message}\n\n<context>\n${config.getContext(modePrompt)}\n</context>`);
1956
+ composerRuntime.send();
1957
+ }
1958
+ else {
1959
+ adapters.agentChat.sendToAgentChat({
1960
+ message,
1961
+ context: config.getContext(modePrompt),
1962
+ mode: execMode === "plan"
1963
+ ? "plan"
1964
+ : execMode === "build"
1965
+ ? "act"
1966
+ : undefined,
1967
+ submit: true,
1968
+ });
1969
+ }
1970
+ cancelActiveVoice();
1971
+ if (isComposerEditorUsable(ed))
1972
+ ed.commands.clearContent();
1973
+ setEditorHasText(false);
1974
+ setSlotReferences([]);
1975
+ setComposerMode(null);
1976
+ composerModeRef.current = null;
1977
+ try {
1978
+ localStorage.removeItem(draftKey);
1979
+ }
1980
+ catch { }
1981
+ closePopover();
1982
+ return;
1983
+ }
1984
+ if (onSubmit) {
1985
+ try {
1986
+ await onSubmit(text, references, attachments, { intent });
1987
+ }
1988
+ catch {
1989
+ // Hosts own their submit errors. Keep the draft and attachments
1990
+ // available for recovery when a host rejects the submission.
1991
+ return;
1992
+ }
1993
+ // Clear any pending attachments now that the host has them.
1994
+ void composerRuntime.clearAttachments().catch(() => { });
1995
+ if (!clearOnSubmit) {
1996
+ closePopover();
1997
+ return;
1998
+ }
1999
+ cancelActiveVoice();
2000
+ clearEditorAfterSubmit();
2001
+ return;
2002
+ }
2003
+ else {
2004
+ composerRuntime.send();
2005
+ }
2006
+ cancelActiveVoice();
2007
+ if (isComposerEditorUsable(ed))
2008
+ ed.commands.clearContent();
2009
+ setEditorHasText(false);
2010
+ setSlotReferences([]);
2011
+ try {
2012
+ localStorage.removeItem(draftKey);
2013
+ }
2014
+ catch { }
2015
+ closePopover();
2016
+ }, [
2017
+ closePopover,
2018
+ clearEditorAfterSubmit,
2019
+ composerMode,
2020
+ composerRuntime,
2021
+ draftKey,
2022
+ editor,
2023
+ interceptBuildRequestsForBuilder,
2024
+ clearOnSubmit,
2025
+ onBeforeSubmit,
2026
+ onSubmit,
2027
+ syncComposerState,
2028
+ voice,
2029
+ allSlashCommands,
2030
+ t,
2031
+ ]);
2032
+ // Helper functions that operate on the editor view directly
2033
+ // These are called from handleKeyDown which can't use React state
2034
+ function selectMention(_view, pop, item) {
2035
+ const ed = editor;
2036
+ if (!isComposerEditorUsable(ed))
2037
+ return;
2038
+ const currentPos = ed.state.selection.from;
2039
+ // startPos is after the trigger char, so -1 to include the @ or /
2040
+ const deleteFrom = Math.max(0, pop.startPos - 1);
2041
+ ed.chain().focus().deleteRange({ from: deleteFrom, to: currentPos }).run();
2042
+ insertReference(composerReferenceFromMentionItem(item));
2043
+ popoverStateRef.current = null;
2044
+ setPopover(null);
2045
+ }
2046
+ function executeCommand(_view, pop, command) {
2047
+ const ed = editor;
2048
+ if (!isComposerEditorUsable(ed))
2049
+ return;
2050
+ const currentPos = ed.state.selection.from;
2051
+ const deleteFrom = Math.max(0, pop.startPos - 1);
2052
+ ed.chain().focus().deleteRange({ from: deleteFrom, to: currentPos }).run();
2053
+ popoverStateRef.current = null;
2054
+ setPopover(null);
2055
+ onSlashCommandRef.current?.(command.name);
2056
+ }
2057
+ function selectSkill(_view, pop, skill) {
2058
+ const ed = editor;
2059
+ if (!isComposerEditorUsable(ed))
2060
+ return;
2061
+ const currentPos = ed.state.selection.from;
2062
+ const deleteFrom = Math.max(0, pop.startPos - 1);
2063
+ ed.chain()
2064
+ .focus()
2065
+ .deleteRange({ from: deleteFrom, to: currentPos })
2066
+ .insertContent({
2067
+ type: "skillReference",
2068
+ attrs: { name: skill.name, path: skill.path, source: skill.source },
2069
+ })
2070
+ .insertContent(" ")
2071
+ .run();
2072
+ popoverStateRef.current = null;
2073
+ setPopover(null);
2074
+ }
2075
+ // Popover select handlers for click-based selection (from MentionPopover)
2076
+ const handleSelectMention = useCallback((item) => {
2077
+ if (!isComposerEditorUsable(editor) || !popover)
2078
+ return;
2079
+ const currentPos = editor.state.selection.from;
2080
+ const deleteFrom = Math.max(0, popover.startPos - 1);
2081
+ editor
2082
+ .chain()
2083
+ .focus()
2084
+ .deleteRange({ from: deleteFrom, to: currentPos })
2085
+ .run();
2086
+ insertReference(composerReferenceFromMentionItem(item));
2087
+ closePopover();
2088
+ }, [editor, popover, closePopover, insertReference]);
2089
+ const handleSelectCommand = useCallback((command) => {
2090
+ if (!isComposerEditorUsable(editor) || !popover)
2091
+ return;
2092
+ const currentPos = editor.state.selection.from;
2093
+ const deleteFrom = Math.max(0, popover.startPos - 1);
2094
+ editor
2095
+ .chain()
2096
+ .focus()
2097
+ .deleteRange({ from: deleteFrom, to: currentPos })
2098
+ .run();
2099
+ closePopover();
2100
+ onSlashCommand?.(command.name);
2101
+ }, [editor, popover, closePopover, onSlashCommand]);
2102
+ const handleSelectSkill = useCallback((skill) => {
2103
+ if (!isComposerEditorUsable(editor) || !popover)
2104
+ return;
2105
+ const currentPos = editor.state.selection.from;
2106
+ const deleteFrom = Math.max(0, popover.startPos - 1);
2107
+ editor
2108
+ .chain()
2109
+ .focus()
2110
+ .deleteRange({ from: deleteFrom, to: currentPos })
2111
+ .insertContent({
2112
+ type: "skillReference",
2113
+ attrs: { name: skill.name, path: skill.path, source: skill.source },
2114
+ })
2115
+ .insertContent(" ")
2116
+ .run();
2117
+ closePopover();
2118
+ }, [editor, popover, closePopover]);
2119
+ // Track query text as user types after trigger
2120
+ useEffect(() => {
2121
+ if (!isComposerEditorUsable(editor) || !popover)
2122
+ return;
2123
+ const updateHandler = () => {
2124
+ const pop = popoverStateRef.current;
2125
+ if (!pop)
2126
+ return;
2127
+ const { from } = editor.state.selection;
2128
+ const { startPos, type } = pop;
2129
+ if (from < startPos) {
2130
+ closePopover();
2131
+ return;
2132
+ }
2133
+ const text = editor.state.doc.textBetween(startPos, from);
2134
+ // Verify the trigger character is still there
2135
+ if (startPos > 0) {
2136
+ const triggerChar = editor.state.doc.textBetween(startPos - 1, startPos);
2137
+ if ((type === "@" && triggerChar !== "@") ||
2138
+ (type === "/" && triggerChar !== "/")) {
2139
+ closePopover();
2140
+ return;
2141
+ }
2142
+ }
2143
+ if (pop.query === text)
2144
+ return;
2145
+ const updated = { ...pop, query: text };
2146
+ popoverStateRef.current = updated;
2147
+ setPopover(updated);
2148
+ };
2149
+ editor.on("update", updateHandler);
2150
+ editor.on("selectionUpdate", updateHandler);
2151
+ return () => {
2152
+ if (isComposerEditorUsable(editor)) {
2153
+ editor.off("update", updateHandler);
2154
+ editor.off("selectionUpdate", updateHandler);
2155
+ }
2156
+ };
2157
+ }, [editor, popover, closePopover]);
2158
+ useEffect(() => {
2159
+ if (!isComposerEditorUsable(editor))
2160
+ return;
2161
+ if (composerText !== "")
2162
+ return;
2163
+ if (editor.isEmpty)
2164
+ return;
2165
+ editor.commands.clearContent();
2166
+ }, [composerText, editor]);
2167
+ useEffect(() => {
2168
+ if (!isComposerEditorUsable(editor) || initialText === undefined)
2169
+ return;
2170
+ const key = initialTextKey ?? initialText;
2171
+ if (initialTextKeyRef.current === key)
2172
+ return;
2173
+ initialTextKeyRef.current = key;
2174
+ editor.commands.setContent(plainTextToDoc(initialText));
2175
+ editor.commands.focus("end");
2176
+ const trimmed = editor.state.doc.textContent.trim();
2177
+ setEditorHasText(trimmed.length > 0);
2178
+ composerRuntime.setText(trimmed);
2179
+ onTextChangeRef.current?.(trimmed);
2180
+ try {
2181
+ if (trimmed) {
2182
+ localStorage.setItem(draftKey, editor.getHTML());
2183
+ }
2184
+ else {
2185
+ localStorage.removeItem(draftKey);
2186
+ }
2187
+ }
2188
+ catch { }
2189
+ }, [composerRuntime, draftKey, editor, initialText, initialTextKey]);
2190
+ // Tiptap only reads `editable` at init; prop changes need setEditable.
2191
+ useEffect(() => {
2192
+ if (!isComposerEditorUsable(editor))
2193
+ return;
2194
+ editor.setEditable(!disabled);
2195
+ if (disabled)
2196
+ editor.commands.blur();
2197
+ }, [editor, disabled]);
2198
+ return (_jsxs(RealtimeVoiceModeBoundary, { children: [_jsx("style", { children: `
2199
+ .aui-composer .ProseMirror p.is-editor-empty:first-child::before {
2200
+ content: attr(data-placeholder);
2201
+ color: var(--color-muted-foreground);
2202
+ opacity: 0.5;
2203
+ float: left;
2204
+ height: 0;
2205
+ pointer-events: none;
2206
+ }
2207
+ ` }), composerMode && (_jsx("div", { "data-agent-composer-variant": layoutVariant, "data-agent-composer-slot": "mode-row", className: "agent-composer-mode-row px-2.5 pt-2 pb-0", children: _jsx(ComposerModeChip, { mode: composerMode, onRemove: () => {
2208
+ setComposerMode(null);
2209
+ composerModeRef.current = null;
2210
+ if (isComposerEditorUsable(editor)) {
2211
+ editor.commands.focus("end");
2212
+ }
2213
+ } }) })), hasContextRows && (_jsxs("div", { "data-agent-composer-variant": layoutVariant, "data-agent-composer-slot": "context-row", className: "agent-composer-context-row flex flex-wrap gap-1.5 px-2.5 pt-2 pb-0", children: [slotReferences.map((ref) => (_jsxs("span", { className: "inline-flex max-w-full items-center gap-1.5 rounded-md border border-border bg-background px-2 py-1 text-[11px] font-medium text-foreground shadow-sm", children: [_jsx(IconClipboardList, { className: "h-3 w-3 shrink-0 text-muted-foreground" }), ref.slotLabel && (_jsx("span", { className: "shrink-0 text-muted-foreground", children: ref.slotLabel })), _jsx("span", { className: "min-w-0 truncate", children: ref.label }), _jsx("button", { type: "button", onClick: () => {
2214
+ setSlotReferences((current) => removeSlotReference(current, ref));
2215
+ if (isComposerEditorUsable(editor)) {
2216
+ editor.commands.focus("end");
2217
+ }
2218
+ }, "aria-label": t("agentChat.composer.removeReference", {
2219
+ defaultValue: "Remove {{name}} reference",
2220
+ name: slotReferenceTitle(ref),
2221
+ }), className: "ms-0.5 flex h-4 w-4 shrink-0 items-center justify-center rounded text-muted-foreground hover:bg-accent hover:text-foreground", children: _jsx(IconX, { className: "h-3 w-3" }) })] }, ref.slotKey))), contextItems.map((item) => (_jsxs("span", { "data-state": selectedContextItemKey === item.key ? "selected" : undefined, className: `inline-flex max-w-full items-center gap-1.5 rounded-md border px-2 py-1 text-[11px] font-medium text-foreground ${selectedContextItemKey === item.key
2222
+ ? "border-ring bg-accent ring-2 ring-ring/40"
2223
+ : "border-border bg-muted/50"}`, children: [_jsx(IconClipboardList, { className: "h-3 w-3 shrink-0 text-muted-foreground" }), _jsx("span", { className: "min-w-0 truncate", children: item.title }), _jsx("button", { type: "button", onClick: () => {
2224
+ selectedContextItemKeyRef.current = null;
2225
+ setSelectedContextItemKey(null);
2226
+ onRemoveContextItem?.(item.key);
2227
+ }, "aria-label": t("agentChat.composer.removeContext", {
2228
+ defaultValue: "Remove {{name}} context",
2229
+ name: item.title,
2230
+ }), className: "ms-0.5 flex h-4 w-4 shrink-0 items-center justify-center rounded text-muted-foreground hover:bg-accent hover:text-foreground", children: _jsx(IconX, { className: "h-3 w-3" }) })] }, item.key)))] })), _jsx("div", { "data-agent-composer-variant": layoutVariant, "data-agent-composer-slot": "editor-wrap", className: `agent-composer-editor-wrap ${composerMode || hasContextRows ? "px-2 pt-1 pb-1" : "px-2 pt-2 pb-1"}`, children: _jsx(EditorContent, { editor: editor, "data-agent-composer-variant": layoutVariant, "data-agent-composer-slot": "editor", className: "agent-composer-editor aui-composer flex-1 min-w-0 [&_.ProseMirror]:outline-none [&_.ProseMirror_p]:m-0 px-0.5" }) }), voiceEnabled && _jsx(VoiceRecordingOverlay, { voice: voice }), _jsxs("div", { "data-agent-composer-variant": layoutVariant, "data-agent-composer-slot": "toolbar", className: "agent-composer-toolbar flex items-center gap-1 px-2 py-1.5", children: [attachButton ??
2231
+ (plusMenuMode === "hidden" ? null : (_jsx(ComposerPlusMenu, { onSelectMode: handleSelectMode, mode: plusMenuMode, terminalModeControl: terminalModeControl, extensionTools: extensionTools, onAttachmentError: onAttachmentError }))), toolbarSlot ?? modeControl, _jsx("div", { "data-agent-composer-slot": "toolbar-spacer", className: "flex-1" }), selectedModel && availableModels && onModelChange && (_jsx(ModelSelector, { model: selectedModel, open: modelSelectorOpen, effort: selectedEffort, engines: availableModels, agents: availableAgents, selectedAgent: selectedAgent, agentOnly: agentOnly, hostedHarness: hostedHarness, showAutoModelOption: showAutoModelOption, modelListLoading: modelListLoading, onChange: onModelChange, onEffortChange: onEffortChange, onAgentChange: onAgentChange, onModelSelectorOpenChange: onModelSelectorOpenChange, providerConnectStatusEnabled: providerConnectStatusEnabled, onConnectProvider: onConnectProvider, onConnectLocalRuntime: onConnectLocalRuntime, imageModel: imageModelMenu })), execMode && onExecModeChange && (_jsx(ModeSelector, { mode: execMode, onChange: onExecModeChange, planModeDisabled: planModeDisabled, planModeDisabledReason: planModeDisabledReason })), actionButton ?? (_jsxs(_Fragment, { children: [extraActionButton, voiceEnabled && (_jsx(VoiceButton, { voice: voice, isMac: isMac, disabled: disabled })), primaryAction === "stop" ? (stopButton) : (_jsxs(Tooltip, { children: [_jsx(TooltipTrigger, { asChild: true, children: _jsx("button", { type: "button", onClick: () => void submitComposer("immediate"), disabled: !canSend, "data-agent-composer-slot": "send-button", className: "agent-composer-send-button shrink-0 flex h-7 w-7 items-center justify-center rounded-md bg-primary text-primary-foreground hover:opacity-90 transition-[opacity,transform] duration-150 active:scale-[0.97] disabled:opacity-30 disabled:cursor-not-allowed", children: _jsx(IconArrowUp, { className: "h-3.5 w-3.5" }) }) }), _jsx(TooltipContent, { children: sendButtonTooltip })] }))] }))] }), _jsx(MentionPopover, { ref: popoverRef, type: popover?.type ?? "@", position: popover?.position ?? null, mentionItems: filteredMentionItems, skills: filteredSkills, commands: filteredCommands, hint: hint, isLoading: popover?.type === "@" ? mentionsLoading : skillsLoading, query: popover?.query ?? "", onSelectMention: handleSelectMention, onSelectSkill: handleSelectSkill, onSelectCommand: handleSelectCommand, onClose: closePopover })] }));
2232
+ }
2233
+ //# sourceMappingURL=TiptapComposer.js.map