@parhelia/core 0.1.12556 → 0.1.12565

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 (587) hide show
  1. package/dist/agents-view/AgentCard.d.ts +6 -4
  2. package/dist/agents-view/AgentCard.js +143 -24
  3. package/dist/agents-view/AgentCard.js.map +1 -1
  4. package/dist/agents-view/AgentsInbox.d.ts +1 -1
  5. package/dist/agents-view/AgentsInbox.js +7 -92
  6. package/dist/agents-view/AgentsInbox.js.map +1 -1
  7. package/dist/agents-view/AgentsTitlebar.js +3 -2
  8. package/dist/agents-view/AgentsTitlebar.js.map +1 -1
  9. package/dist/agents-view/AgentsView.d.ts +6 -7
  10. package/dist/agents-view/AgentsView.js +191 -99
  11. package/dist/agents-view/AgentsView.js.map +1 -1
  12. package/dist/agents-view/AgentsWorkspaceView.d.ts +2 -6
  13. package/dist/agents-view/AgentsWorkspaceView.js +266 -113
  14. package/dist/agents-view/AgentsWorkspaceView.js.map +1 -1
  15. package/dist/agents-view/ProfileAgentsGroup.d.ts +2 -1
  16. package/dist/agents-view/ProfileAgentsGroup.js +4 -3
  17. package/dist/agents-view/ProfileAgentsGroup.js.map +1 -1
  18. package/dist/components/ActionButton.d.ts +1 -1
  19. package/dist/components/ActionButton.js.map +1 -1
  20. package/dist/components/FilterInput.d.ts +1 -1
  21. package/dist/components/FilterInput.js +1 -1
  22. package/dist/components/FilterInput.js.map +1 -1
  23. package/dist/components/ui/LanguageSelector.js +2 -4
  24. package/dist/components/ui/LanguageSelector.js.map +1 -1
  25. package/dist/components/ui/PlaceholderInput.js +3 -3
  26. package/dist/components/ui/PlaceholderInput.js.map +1 -1
  27. package/dist/components/ui/PlaceholderInputTypes.js +1 -1
  28. package/dist/components/ui/PlaceholderInputTypes.js.map +1 -1
  29. package/dist/components/ui/alert-dialog.d.ts +1 -1
  30. package/dist/components/ui/alert-dialog.js +6 -10
  31. package/dist/components/ui/alert-dialog.js.map +1 -1
  32. package/dist/components/ui/button.d.ts +4 -4
  33. package/dist/components/ui/button.js +4 -1
  34. package/dist/components/ui/button.js.map +1 -1
  35. package/dist/components/ui/context-menu.d.ts +1 -1
  36. package/dist/components/ui/context-menu.js +12 -4
  37. package/dist/components/ui/context-menu.js.map +1 -1
  38. package/dist/components/ui/copy-button.d.ts +2 -1
  39. package/dist/components/ui/copy-button.js +2 -2
  40. package/dist/components/ui/copy-button.js.map +1 -1
  41. package/dist/components/ui/dialog.d.ts +1 -1
  42. package/dist/components/ui/dialog.js +21 -126
  43. package/dist/components/ui/dialog.js.map +1 -1
  44. package/dist/components/ui/input.d.ts +1 -1
  45. package/dist/components/ui/input.js +5 -3
  46. package/dist/components/ui/input.js.map +1 -1
  47. package/dist/components/ui/paste-button.d.ts +2 -1
  48. package/dist/components/ui/paste-button.js +2 -2
  49. package/dist/components/ui/paste-button.js.map +1 -1
  50. package/dist/components/ui/popover.js +1 -9
  51. package/dist/components/ui/popover.js.map +1 -1
  52. package/dist/components/ui/select.js +1 -1
  53. package/dist/components/ui/select.js.map +1 -1
  54. package/dist/components/ui/styled-dialog-title.js +1 -1
  55. package/dist/components/ui/styled-dialog-title.js.map +1 -1
  56. package/dist/components/ui/tabs.d.ts +1 -1
  57. package/dist/components/ui/tabs.js +4 -11
  58. package/dist/components/ui/tabs.js.map +1 -1
  59. package/dist/config/config.d.ts +4 -2
  60. package/dist/config/config.js +250 -70
  61. package/dist/config/config.js.map +1 -1
  62. package/dist/config/notificationRoutes.js +14 -0
  63. package/dist/config/notificationRoutes.js.map +1 -1
  64. package/dist/config/types/workspace.d.ts +6 -0
  65. package/dist/config/types.d.ts +63 -12
  66. package/dist/config/types.js.map +1 -1
  67. package/dist/editor/ConfirmationDialog.js +20 -4
  68. package/dist/editor/ConfirmationDialog.js.map +1 -1
  69. package/dist/editor/ContentTree.d.ts +2 -1
  70. package/dist/editor/ContentTree.js +93 -32
  71. package/dist/editor/ContentTree.js.map +1 -1
  72. package/dist/editor/Editor.js +87 -22
  73. package/dist/editor/Editor.js.map +1 -1
  74. package/dist/editor/FieldHistory.js +84 -36
  75. package/dist/editor/FieldHistory.js.map +1 -1
  76. package/dist/editor/FieldListField.js +21 -9
  77. package/dist/editor/FieldListField.js.map +1 -1
  78. package/dist/editor/FieldListFieldWithFallbacks.js +23 -2
  79. package/dist/editor/FieldListFieldWithFallbacks.js.map +1 -1
  80. package/dist/editor/GlobalMenuBar.js +29 -2
  81. package/dist/editor/GlobalMenuBar.js.map +1 -1
  82. package/dist/editor/ImageEditor.js +5 -2
  83. package/dist/editor/ImageEditor.js.map +1 -1
  84. package/dist/editor/ItemInfo.js +36 -1
  85. package/dist/editor/ItemInfo.js.map +1 -1
  86. package/dist/editor/LinkEditorDialog.js +3 -0
  87. package/dist/editor/LinkEditorDialog.js.map +1 -1
  88. package/dist/editor/MainLayout.d.ts +0 -2
  89. package/dist/editor/MainLayout.js +65 -8
  90. package/dist/editor/MainLayout.js.map +1 -1
  91. package/dist/editor/MigrationsView.js +29 -5
  92. package/dist/editor/MigrationsView.js.map +1 -1
  93. package/dist/editor/MobileLayout.js +37 -12
  94. package/dist/editor/MobileLayout.js.map +1 -1
  95. package/dist/editor/PictureCropper.js +54 -45
  96. package/dist/editor/PictureCropper.js.map +1 -1
  97. package/dist/editor/PictureEditor.js +17 -15
  98. package/dist/editor/PictureEditor.js.map +1 -1
  99. package/dist/editor/QuickItemSwitcher.js +21 -21
  100. package/dist/editor/QuickItemSwitcher.js.map +1 -1
  101. package/dist/editor/SetupWizard.js +52 -12
  102. package/dist/editor/SetupWizard.js.map +1 -1
  103. package/dist/editor/Titlebar.js +7 -2
  104. package/dist/editor/Titlebar.js.map +1 -1
  105. package/dist/editor/ai/AgentCostDisplay.d.ts +1 -0
  106. package/dist/editor/ai/AgentCostDisplay.js +1 -1
  107. package/dist/editor/ai/AgentCostDisplay.js.map +1 -1
  108. package/dist/editor/ai/AgentDocumentList.js +32 -14
  109. package/dist/editor/ai/AgentDocumentList.js.map +1 -1
  110. package/dist/editor/ai/AgentGreeting.js +3 -2
  111. package/dist/editor/ai/AgentGreeting.js.map +1 -1
  112. package/dist/editor/ai/AgentProfileSelector.js +2 -1
  113. package/dist/editor/ai/AgentProfileSelector.js.map +1 -1
  114. package/dist/editor/ai/AgentStatusBadge.d.ts +0 -5
  115. package/dist/editor/ai/AgentStatusBadge.js +67 -65
  116. package/dist/editor/ai/AgentStatusBadge.js.map +1 -1
  117. package/dist/editor/ai/AgentTerminal.d.ts +14 -2
  118. package/dist/editor/ai/AgentTerminal.js +2406 -496
  119. package/dist/editor/ai/AgentTerminal.js.map +1 -1
  120. package/dist/editor/ai/AgentTerminalStatusBar.d.ts +8 -3
  121. package/dist/editor/ai/AgentTerminalStatusBar.js +481 -56
  122. package/dist/editor/ai/AgentTerminalStatusBar.js.map +1 -1
  123. package/dist/editor/ai/Agents.js +161 -113
  124. package/dist/editor/ai/Agents.js.map +1 -1
  125. package/dist/editor/ai/AiResponseMessage.d.ts +10 -1
  126. package/dist/editor/ai/AiResponseMessage.js +267 -26
  127. package/dist/editor/ai/AiResponseMessage.js.map +1 -1
  128. package/dist/editor/ai/ContextInfoBar.d.ts +2 -3
  129. package/dist/editor/ai/ContextInfoBar.js +64 -7
  130. package/dist/editor/ai/ContextInfoBar.js.map +1 -1
  131. package/dist/editor/ai/GuidanceOverlay.js +17 -11
  132. package/dist/editor/ai/GuidanceOverlay.js.map +1 -1
  133. package/dist/editor/ai/InlineAiDialog.d.ts +1 -1
  134. package/dist/editor/ai/InlineAiDialog.js +514 -192
  135. package/dist/editor/ai/InlineAiDialog.js.map +1 -1
  136. package/dist/editor/ai/InlineAiTrigger.js +115 -12
  137. package/dist/editor/ai/InlineAiTrigger.js.map +1 -1
  138. package/dist/editor/ai/MediaImage.js +40 -8
  139. package/dist/editor/ai/MediaImage.js.map +1 -1
  140. package/dist/editor/ai/SpawnedAgentsPanel.js +10 -12
  141. package/dist/editor/ai/SpawnedAgentsPanel.js.map +1 -1
  142. package/dist/editor/ai/ToolCallDisplay.d.ts +22 -2
  143. package/dist/editor/ai/ToolCallDisplay.js +542 -150
  144. package/dist/editor/ai/ToolCallDisplay.js.map +1 -1
  145. package/dist/editor/ai/agentDiagnostics.d.ts +7 -0
  146. package/dist/editor/ai/agentDiagnostics.js.map +1 -1
  147. package/dist/editor/ai/dialogs/AgentDialogHandler.d.ts +1 -8
  148. package/dist/editor/ai/dialogs/AgentDialogHandler.js +379 -42
  149. package/dist/editor/ai/dialogs/AgentDialogHandler.js.map +1 -1
  150. package/dist/editor/ai/dialogs/QuestionnaireInline.d.ts +5 -1
  151. package/dist/editor/ai/dialogs/QuestionnaireInline.js +628 -60
  152. package/dist/editor/ai/dialogs/QuestionnaireInline.js.map +1 -1
  153. package/dist/editor/ai/dialogs/agentDialogTypes.d.ts +115 -0
  154. package/dist/editor/ai/dialogs/agentDialogTypes.js +2 -0
  155. package/dist/editor/ai/dialogs/agentDialogTypes.js.map +1 -1
  156. package/dist/editor/ai/types.d.ts +3 -1
  157. package/dist/editor/ai/useAgentStatus.d.ts +2 -1
  158. package/dist/editor/ai/useAgentStatus.js +90 -100
  159. package/dist/editor/ai/useAgentStatus.js.map +1 -1
  160. package/dist/editor/ai/useInlineAiPosition.js +45 -5
  161. package/dist/editor/ai/useInlineAiPosition.js.map +1 -1
  162. package/dist/editor/client/AboutDialog.js +4 -2
  163. package/dist/editor/client/AboutDialog.js.map +1 -1
  164. package/dist/editor/client/EditorShell.d.ts +4 -1
  165. package/dist/editor/client/EditorShell.js +770 -237
  166. package/dist/editor/client/EditorShell.js.map +1 -1
  167. package/dist/editor/client/editContext.d.ts +33 -19
  168. package/dist/editor/client/editContext.js.map +1 -1
  169. package/dist/editor/client/helpers.js +6 -0
  170. package/dist/editor/client/helpers.js.map +1 -1
  171. package/dist/editor/client/hooks/useEditorUrlSync.js +1 -2
  172. package/dist/editor/client/hooks/useEditorUrlSync.js.map +1 -1
  173. package/dist/editor/client/hooks/useEditorWebSocket.d.ts +10 -0
  174. package/dist/editor/client/hooks/useEditorWebSocket.js +209 -14
  175. package/dist/editor/client/hooks/useEditorWebSocket.js.map +1 -1
  176. package/dist/editor/client/hooks/useQuota.d.ts +8 -0
  177. package/dist/editor/client/hooks/useQuota.js.map +1 -1
  178. package/dist/editor/client/hooks/useSocketMessageHandler.js +73 -15
  179. package/dist/editor/client/hooks/useSocketMessageHandler.js.map +1 -1
  180. package/dist/editor/client/itemsRepository.js +10 -6
  181. package/dist/editor/client/itemsRepository.js.map +1 -1
  182. package/dist/editor/client/navigation.js +35 -3
  183. package/dist/editor/client/navigation.js.map +1 -1
  184. package/dist/editor/client/operations.d.ts +6 -3
  185. package/dist/editor/client/operations.js +208 -30
  186. package/dist/editor/client/operations.js.map +1 -1
  187. package/dist/editor/client/pageModelBuilder.js +4 -31
  188. package/dist/editor/client/pageModelBuilder.js.map +1 -1
  189. package/dist/editor/client/ui/DevModeIndicator.js +2 -2
  190. package/dist/editor/client/ui/DevModeIndicator.js.map +1 -1
  191. package/dist/editor/client/ui/EditorChrome.d.ts +0 -6
  192. package/dist/editor/client/ui/EditorChrome.js +55 -72
  193. package/dist/editor/client/ui/EditorChrome.js.map +1 -1
  194. package/dist/editor/client/ui/FullscreenControls.js +5 -3
  195. package/dist/editor/client/ui/FullscreenControls.js.map +1 -1
  196. package/dist/editor/commands/commands.d.ts +11 -1
  197. package/dist/editor/commands/commands.js +12 -1
  198. package/dist/editor/commands/commands.js.map +1 -1
  199. package/dist/editor/commands/componentCommands.js +109 -55
  200. package/dist/editor/commands/componentCommands.js.map +1 -1
  201. package/dist/editor/commands/customCommandConverter.d.ts +8 -1
  202. package/dist/editor/commands/customCommandConverter.js +35 -5
  203. package/dist/editor/commands/customCommandConverter.js.map +1 -1
  204. package/dist/editor/commands/handlers/agentHandler.js +2 -1
  205. package/dist/editor/commands/handlers/agentHandler.js.map +1 -1
  206. package/dist/editor/commands/itemCommands.d.ts +3 -0
  207. package/dist/editor/commands/itemCommands.js +93 -10
  208. package/dist/editor/commands/itemCommands.js.map +1 -1
  209. package/dist/editor/commands/undo.d.ts +9 -15
  210. package/dist/editor/commands/undo.js +24 -0
  211. package/dist/editor/commands/undo.js.map +1 -1
  212. package/dist/editor/context-menu/InsertMenu.js +83 -39
  213. package/dist/editor/context-menu/InsertMenu.js.map +1 -1
  214. package/dist/editor/field-types/MultiLineText.js +1 -1
  215. package/dist/editor/field-types/MultiLineText.js.map +1 -1
  216. package/dist/editor/field-types/RawEditor.js +1 -1
  217. package/dist/editor/field-types/RichTextEditor.js +13 -5
  218. package/dist/editor/field-types/RichTextEditor.js.map +1 -1
  219. package/dist/editor/field-types/RichTextEditorComponent.js +37 -3
  220. package/dist/editor/field-types/RichTextEditorComponent.js.map +1 -1
  221. package/dist/editor/field-types/SingleLineText.js +1 -1
  222. package/dist/editor/field-types/TreeListEditor.js +3 -2
  223. package/dist/editor/field-types/TreeListEditor.js.map +1 -1
  224. package/dist/editor/field-types/richtext/components/ReactSlate.css +23 -5
  225. package/dist/editor/field-types/richtext/components/ReactSlate.d.ts +2 -0
  226. package/dist/editor/field-types/richtext/components/ReactSlate.js +28 -4
  227. package/dist/editor/field-types/richtext/components/ReactSlate.js.map +1 -1
  228. package/dist/editor/field-types/richtext/components/ToolbarButton.js +4 -2
  229. package/dist/editor/field-types/richtext/components/ToolbarButton.js.map +1 -1
  230. package/dist/editor/field-types/richtext/contextMenuFactory.d.ts +13 -0
  231. package/dist/editor/field-types/richtext/contextMenuFactory.js +181 -24
  232. package/dist/editor/field-types/richtext/contextMenuFactory.js.map +1 -1
  233. package/dist/editor/field-types/richtext/types.d.ts +2 -0
  234. package/dist/editor/field-types/richtext/types.js.map +1 -1
  235. package/dist/editor/field-types/richtext/utils/plugins.js +4 -0
  236. package/dist/editor/field-types/richtext/utils/plugins.js.map +1 -1
  237. package/dist/editor/field-types/textContextMenuFactory.js +3 -2
  238. package/dist/editor/field-types/textContextMenuFactory.js.map +1 -1
  239. package/dist/editor/media-selector/AiImageSearchPrompt.js +4 -2
  240. package/dist/editor/media-selector/AiImageSearchPrompt.js.map +1 -1
  241. package/dist/editor/media-selector/MediaFolderBrowser.js +1 -1
  242. package/dist/editor/media-selector/MediaFolderBrowser.js.map +1 -1
  243. package/dist/editor/media-selector/MediaSelector.js +7 -1
  244. package/dist/editor/media-selector/MediaSelector.js.map +1 -1
  245. package/dist/editor/media-selector/TreeSelector.js +40 -35
  246. package/dist/editor/media-selector/TreeSelector.js.map +1 -1
  247. package/dist/editor/menubar/ActiveUsers.js +1 -1
  248. package/dist/editor/menubar/ActiveUsers.js.map +1 -1
  249. package/dist/editor/menubar/GenericToolbar.js +4 -2
  250. package/dist/editor/menubar/GenericToolbar.js.map +1 -1
  251. package/dist/editor/menubar/ItemLanguageVersion.js +2 -2
  252. package/dist/editor/menubar/ItemLanguageVersion.js.map +1 -1
  253. package/dist/editor/menubar/PageSelector.js +26 -147
  254. package/dist/editor/menubar/PageSelector.js.map +1 -1
  255. package/dist/editor/menubar/Separator.js +1 -1
  256. package/dist/editor/menubar/VersionSelector.js +2 -4
  257. package/dist/editor/menubar/VersionSelector.js.map +1 -1
  258. package/dist/editor/menubar/WorkflowButton.js +39 -12
  259. package/dist/editor/menubar/WorkflowButton.js.map +1 -1
  260. package/dist/editor/menubar/toolbar-sections/CustomCommandsToolbar.js +16 -38
  261. package/dist/editor/menubar/toolbar-sections/CustomCommandsToolbar.js.map +1 -1
  262. package/dist/editor/menubar/toolbar-sections/EditControls.js +3 -3
  263. package/dist/editor/menubar/toolbar-sections/EditControls.js.map +1 -1
  264. package/dist/editor/menubar/toolbar-sections/HelpButton.js +1 -0
  265. package/dist/editor/menubar/toolbar-sections/HelpButton.js.map +1 -1
  266. package/dist/editor/menubar/toolbar-sections/ManualBrowser.d.ts +6 -10
  267. package/dist/editor/menubar/toolbar-sections/ManualBrowser.js +597 -220
  268. package/dist/editor/menubar/toolbar-sections/ManualBrowser.js.map +1 -1
  269. package/dist/editor/menubar/toolbar-sections/UtilityControls.js +13 -2
  270. package/dist/editor/menubar/toolbar-sections/UtilityControls.js.map +1 -1
  271. package/dist/editor/page-editor-chrome/CommentHighlighting.js +42 -1
  272. package/dist/editor/page-editor-chrome/CommentHighlighting.js.map +1 -1
  273. package/dist/editor/page-editor-chrome/FrameMenu.js +1 -1
  274. package/dist/editor/page-editor-chrome/FrameMenu.js.map +1 -1
  275. package/dist/editor/page-editor-chrome/InlineEditor.js +97 -48
  276. package/dist/editor/page-editor-chrome/InlineEditor.js.map +1 -1
  277. package/dist/editor/page-editor-chrome/PlaceholderDropZone.js +38 -17
  278. package/dist/editor/page-editor-chrome/PlaceholderDropZone.js.map +1 -1
  279. package/dist/editor/page-editor-chrome/PlaceholderDropZones.js +17 -11
  280. package/dist/editor/page-editor-chrome/PlaceholderDropZones.js.map +1 -1
  281. package/dist/editor/page-editor-chrome/useInlineAICompletion.js +301 -301
  282. package/dist/editor/page-editor-chrome/useInlineAICompletion.js.map +1 -1
  283. package/dist/editor/page-viewer/DeviceToolbar.js +1 -1
  284. package/dist/editor/page-viewer/DeviceToolbar.js.map +1 -1
  285. package/dist/editor/page-viewer/EditorForm.js +69 -11
  286. package/dist/editor/page-viewer/EditorForm.js.map +1 -1
  287. package/dist/editor/page-viewer/MiniMap.d.ts +2 -4
  288. package/dist/editor/page-viewer/MiniMap.js +91 -28
  289. package/dist/editor/page-viewer/MiniMap.js.map +1 -1
  290. package/dist/editor/page-viewer/PageViewer.d.ts +3 -1
  291. package/dist/editor/page-viewer/PageViewer.js +92 -19
  292. package/dist/editor/page-viewer/PageViewer.js.map +1 -1
  293. package/dist/editor/page-viewer/PageViewerFrame.d.ts +2 -1
  294. package/dist/editor/page-viewer/PageViewerFrame.js +348 -115
  295. package/dist/editor/page-viewer/PageViewerFrame.js.map +1 -1
  296. package/dist/editor/page-viewer/pageModelSkeletonBuilder.js +114 -49
  297. package/dist/editor/page-viewer/pageModelSkeletonBuilder.js.map +1 -1
  298. package/dist/editor/page-viewer/pageViewContext.d.ts +1 -0
  299. package/dist/editor/page-viewer/pageViewContext.js +51 -14
  300. package/dist/editor/page-viewer/pageViewContext.js.map +1 -1
  301. package/dist/editor/pageModel.d.ts +14 -1
  302. package/dist/editor/reviews/Comment.js +26 -12
  303. package/dist/editor/reviews/Comment.js.map +1 -1
  304. package/dist/editor/reviews/CommentDisplayPopover.js +7 -5
  305. package/dist/editor/reviews/CommentDisplayPopover.js.map +1 -1
  306. package/dist/editor/reviews/CommentView.js +19 -4
  307. package/dist/editor/reviews/CommentView.js.map +1 -1
  308. package/dist/editor/reviews/Comments.js +89 -72
  309. package/dist/editor/reviews/Comments.js.map +1 -1
  310. package/dist/editor/reviews/CreateReviewDialog.js +281 -177
  311. package/dist/editor/reviews/CreateReviewDialog.js.map +1 -1
  312. package/dist/editor/reviews/DecisionsMatrix.js +96 -25
  313. package/dist/editor/reviews/DecisionsMatrix.js.map +1 -1
  314. package/dist/editor/reviews/DiffView.js +7 -14
  315. package/dist/editor/reviews/DiffView.js.map +1 -1
  316. package/dist/editor/reviews/EditReviewSettingsDialog.js +6 -4
  317. package/dist/editor/reviews/EditReviewSettingsDialog.js.map +1 -1
  318. package/dist/editor/reviews/MultiReviewManager.js +25 -3
  319. package/dist/editor/reviews/MultiReviewManager.js.map +1 -1
  320. package/dist/editor/reviews/PagesPanel.js +31 -15
  321. package/dist/editor/reviews/PagesPanel.js.map +1 -1
  322. package/dist/editor/reviews/PreviewInfo.js +1 -4
  323. package/dist/editor/reviews/PreviewInfo.js.map +1 -1
  324. package/dist/editor/reviews/ReviewCard.js +13 -7
  325. package/dist/editor/reviews/ReviewCard.js.map +1 -1
  326. package/dist/editor/reviews/ReviewDetail.js +3 -2
  327. package/dist/editor/reviews/ReviewDetail.js.map +1 -1
  328. package/dist/editor/reviews/ReviewsList.js +7 -3
  329. package/dist/editor/reviews/ReviewsList.js.map +1 -1
  330. package/dist/editor/reviews/SuggestedEdit.js +34 -3
  331. package/dist/editor/reviews/SuggestedEdit.js.map +1 -1
  332. package/dist/editor/reviews/SuggestionDisplayPopover.js +31 -5
  333. package/dist/editor/reviews/SuggestionDisplayPopover.js.map +1 -1
  334. package/dist/editor/reviews/commentAi.js +25 -6
  335. package/dist/editor/reviews/commentAi.js.map +1 -1
  336. package/dist/editor/reviews/reviewCommands.js +4 -1
  337. package/dist/editor/reviews/reviewCommands.js.map +1 -1
  338. package/dist/editor/reviews/useMultiReview.js +2 -2
  339. package/dist/editor/reviews/useMultiReview.js.map +1 -1
  340. package/dist/editor/reviews/useReviews.d.ts +2 -2
  341. package/dist/editor/reviews/useReviews.js +12 -30
  342. package/dist/editor/reviews/useReviews.js.map +1 -1
  343. package/dist/editor/services/agentErrorMessage.d.ts +1 -0
  344. package/dist/editor/services/agentErrorMessage.js +91 -0
  345. package/dist/editor/services/agentErrorMessage.js.map +1 -0
  346. package/dist/editor/services/agentService.d.ts +229 -5
  347. package/dist/editor/services/agentService.js +292 -39
  348. package/dist/editor/services/agentService.js.map +1 -1
  349. package/dist/editor/services/agentStatus.d.ts +1 -0
  350. package/dist/editor/services/agentStatus.js +19 -0
  351. package/dist/editor/services/agentStatus.js.map +1 -1
  352. package/dist/editor/services/aiService.d.ts +57 -1
  353. package/dist/editor/services/aiService.js +79 -6
  354. package/dist/editor/services/aiService.js.map +1 -1
  355. package/dist/editor/services/contentService.d.ts +6 -3
  356. package/dist/editor/services/contentService.js +13 -12
  357. package/dist/editor/services/contentService.js.map +1 -1
  358. package/dist/editor/services/editService.d.ts +52 -1
  359. package/dist/editor/services/editService.js +94 -2
  360. package/dist/editor/services/editService.js.map +1 -1
  361. package/dist/editor/services/indexService.js +1 -1
  362. package/dist/editor/services/indexService.js.map +1 -1
  363. package/dist/editor/services/reviewsService.d.ts +3 -6
  364. package/dist/editor/services/reviewsService.js +2 -11
  365. package/dist/editor/services/reviewsService.js.map +1 -1
  366. package/dist/editor/services/serviceHelper.d.ts +2 -1
  367. package/dist/editor/services/serviceHelper.js +112 -20
  368. package/dist/editor/services/serviceHelper.js.map +1 -1
  369. package/dist/editor/services/systemService.d.ts +2 -1
  370. package/dist/editor/services/systemService.js +3 -0
  371. package/dist/editor/services/systemService.js.map +1 -1
  372. package/dist/editor/services-server/api.d.ts +1 -2
  373. package/dist/editor/services-server/api.js +11 -6
  374. package/dist/editor/services-server/api.js.map +1 -1
  375. package/dist/editor/settings/About.js +317 -3
  376. package/dist/editor/settings/About.js.map +1 -1
  377. package/dist/editor/settings/QuotaInfo.js +210 -4
  378. package/dist/editor/settings/QuotaInfo.js.map +1 -1
  379. package/dist/editor/settings/SettingsView.js +25 -23
  380. package/dist/editor/settings/SettingsView.js.map +1 -1
  381. package/dist/editor/settings/Status.js +7 -6
  382. package/dist/editor/settings/Status.js.map +1 -1
  383. package/dist/editor/settings/index/useIndexStatus.js +20 -22
  384. package/dist/editor/settings/index/useIndexStatus.js.map +1 -1
  385. package/dist/editor/settings/panels/AgentsPanel.d.ts +0 -4
  386. package/dist/editor/settings/panels/AgentsPanel.js +95 -121
  387. package/dist/editor/settings/panels/AgentsPanel.js.map +1 -1
  388. package/dist/editor/settings/panels/ModelsPanel.js +329 -108
  389. package/dist/editor/settings/panels/ModelsPanel.js.map +1 -1
  390. package/dist/editor/settings/panels/ProvidersPanel.d.ts +1 -1
  391. package/dist/editor/settings/panels/ProvidersPanel.js +86 -59
  392. package/dist/editor/settings/panels/ProvidersPanel.js.map +1 -1
  393. package/dist/editor/settings/panels/SearchConfigPanel.js +4 -4
  394. package/dist/editor/settings/panels/SearchConfigPanel.js.map +1 -1
  395. package/dist/editor/settings/panels/index.d.ts +3 -2
  396. package/dist/editor/settings/panels/index.js +3 -2
  397. package/dist/editor/settings/panels/index.js.map +1 -1
  398. package/dist/editor/settings/status/coreStatusChecks.js +124 -19
  399. package/dist/editor/settings/status/coreStatusChecks.js.map +1 -1
  400. package/dist/editor/settings/status/useStartupChecks.d.ts +3 -1
  401. package/dist/editor/settings/status/useStartupChecks.js +9 -5
  402. package/dist/editor/settings/status/useStartupChecks.js.map +1 -1
  403. package/dist/editor/setup-wizard/steps/CompleteStep.d.ts +2 -1
  404. package/dist/editor/setup-wizard/steps/CompleteStep.js +2 -1
  405. package/dist/editor/setup-wizard/steps/CompleteStep.js.map +1 -1
  406. package/dist/editor/sidebar/ComponentPalette.js +2 -1
  407. package/dist/editor/sidebar/ComponentPalette.js.map +1 -1
  408. package/dist/editor/sidebar/ComponentTree.d.ts +8 -1
  409. package/dist/editor/sidebar/ComponentTree.js +216 -69
  410. package/dist/editor/sidebar/ComponentTree.js.map +1 -1
  411. package/dist/editor/sidebar/EditHistory.js +22 -46
  412. package/dist/editor/sidebar/EditHistory.js.map +1 -1
  413. package/dist/editor/sidebar/Favorites.js +4 -8
  414. package/dist/editor/sidebar/Favorites.js.map +1 -1
  415. package/dist/editor/sidebar/MainContentTree.js +4 -3
  416. package/dist/editor/sidebar/MainContentTree.js.map +1 -1
  417. package/dist/editor/sidebar/OperationItem.js +21 -7
  418. package/dist/editor/sidebar/OperationItem.js.map +1 -1
  419. package/dist/editor/sidebar/SidebarPanel.d.ts +3 -1
  420. package/dist/editor/sidebar/SidebarPanel.js +44 -12
  421. package/dist/editor/sidebar/SidebarPanel.js.map +1 -1
  422. package/dist/editor/sidebar/SidebarStack.d.ts +2 -1
  423. package/dist/editor/sidebar/SidebarStack.js +4 -3
  424. package/dist/editor/sidebar/SidebarStack.js.map +1 -1
  425. package/dist/editor/sidebar/Validation.js +24 -12
  426. package/dist/editor/sidebar/Validation.js.map +1 -1
  427. package/dist/editor/sidebar/Workbox.js +53 -3
  428. package/dist/editor/sidebar/Workbox.js.map +1 -1
  429. package/dist/editor/sidebar/WorkspaceRail.d.ts +0 -1
  430. package/dist/editor/sidebar/WorkspaceRail.js +56 -167
  431. package/dist/editor/sidebar/WorkspaceRail.js.map +1 -1
  432. package/dist/editor/tree-indicators/GutterColumns.d.ts +3 -1
  433. package/dist/editor/tree-indicators/GutterColumns.js +26 -5
  434. package/dist/editor/tree-indicators/GutterColumns.js.map +1 -1
  435. package/dist/editor/tree-indicators/GutterContext.d.ts +4 -0
  436. package/dist/editor/tree-indicators/GutterContext.js +23 -0
  437. package/dist/editor/tree-indicators/GutterContext.js.map +1 -1
  438. package/dist/editor/tree-indicators/index.d.ts +0 -1
  439. package/dist/editor/tree-indicators/index.js +0 -1
  440. package/dist/editor/tree-indicators/index.js.map +1 -1
  441. package/dist/editor/tree-indicators/types.d.ts +12 -1
  442. package/dist/editor/ui/CopyMoveTargetSelectorDialog.js +1 -1
  443. package/dist/editor/ui/CopyMoveTargetSelectorDialog.js.map +1 -1
  444. package/dist/editor/ui/Icons.js +1 -1
  445. package/dist/editor/ui/Icons.js.map +1 -1
  446. package/dist/editor/ui/ItemNameDialogNew.d.ts +2 -0
  447. package/dist/editor/ui/ItemNameDialogNew.js +33 -17
  448. package/dist/editor/ui/ItemNameDialogNew.js.map +1 -1
  449. package/dist/editor/ui/ItemSearch.js +7 -11
  450. package/dist/editor/ui/ItemSearch.js.map +1 -1
  451. package/dist/editor/ui/SimpleIconButton.js +1 -1
  452. package/dist/editor/ui/SimpleIconButton.js.map +1 -1
  453. package/dist/editor/ui/SimpleTabs.d.ts +1 -0
  454. package/dist/editor/ui/SimpleTabs.js +45 -25
  455. package/dist/editor/ui/SimpleTabs.js.map +1 -1
  456. package/dist/editor/ui/Splitter.d.ts +1 -0
  457. package/dist/editor/ui/Splitter.js +102 -86
  458. package/dist/editor/ui/Splitter.js.map +1 -1
  459. package/dist/editor/ui/TemplateSelectorDialog.js +4 -4
  460. package/dist/editor/ui/TemplateSelectorDialog.js.map +1 -1
  461. package/dist/editor/ui/TreeListSelector.d.ts +6 -1
  462. package/dist/editor/ui/TreeListSelector.js +2 -2
  463. package/dist/editor/ui/TreeListSelector.js.map +1 -1
  464. package/dist/editor/utils/keyboardNavigation.d.ts +6 -20
  465. package/dist/editor/utils/keyboardNavigation.js +48 -140
  466. package/dist/editor/utils/keyboardNavigation.js.map +1 -1
  467. package/dist/editor/utils.js +19 -9
  468. package/dist/editor/utils.js.map +1 -1
  469. package/dist/editor/views/CompareView.d.ts +3 -1
  470. package/dist/editor/views/CompareView.js +7 -5
  471. package/dist/editor/views/CompareView.js.map +1 -1
  472. package/dist/editor/views/EditView.js +1 -1
  473. package/dist/editor/views/EditView.js.map +1 -1
  474. package/dist/editor/views/EditorSlot.js +27 -34
  475. package/dist/editor/views/EditorSlot.js.map +1 -1
  476. package/dist/editor/views/ItemEditor.js +7 -3
  477. package/dist/editor/views/ItemEditor.js.map +1 -1
  478. package/dist/editor/views/MediaFolderEditView.js +1 -1
  479. package/dist/editor/views/MediaFolderEditView.js.map +1 -1
  480. package/dist/editor/views/ParheliaView.js +5 -6
  481. package/dist/editor/views/ParheliaView.js.map +1 -1
  482. package/dist/editor/views/SingleEditView.d.ts +2 -1
  483. package/dist/editor/views/SingleEditView.js +10 -8
  484. package/dist/editor/views/SingleEditView.js.map +1 -1
  485. package/dist/editor/views/editorSlotContext.js +35 -6
  486. package/dist/editor/views/editorSlotContext.js.map +1 -1
  487. package/dist/index.d.ts +16 -2
  488. package/dist/index.js +11 -0
  489. package/dist/index.js.map +1 -1
  490. package/dist/revision.d.ts +2 -2
  491. package/dist/revision.js +2 -2
  492. package/dist/setup/services/setupWizardService.d.ts +40 -13
  493. package/dist/setup/services/setupWizardService.js +32 -17
  494. package/dist/setup/services/setupWizardService.js.map +1 -1
  495. package/dist/setup/wizard/steps/AddModelDialog.js +12 -3
  496. package/dist/setup/wizard/steps/AddModelDialog.js.map +1 -1
  497. package/dist/setup/wizard/steps/ImportModelDialog.js +39 -22
  498. package/dist/setup/wizard/steps/ImportModelDialog.js.map +1 -1
  499. package/dist/splash-screen/ModernSplashScreen.js +112 -32
  500. package/dist/splash-screen/ModernSplashScreen.js.map +1 -1
  501. package/dist/splash-screen/NewPage.js +33 -50
  502. package/dist/splash-screen/NewPage.js.map +1 -1
  503. package/dist/splash-screen/OpenPage.js +2 -6
  504. package/dist/splash-screen/OpenPage.js.map +1 -1
  505. package/dist/splash-screen/ParheliaAssistantChat.js +12 -29
  506. package/dist/splash-screen/ParheliaAssistantChat.js.map +1 -1
  507. package/dist/splash-screen/ParheliaLogo.js +87 -37
  508. package/dist/splash-screen/ParheliaLogo.js.map +1 -1
  509. package/dist/splash-screen/RecentPages.js +3 -3
  510. package/dist/splash-screen/RecentPages.js.map +1 -1
  511. package/dist/tour/Tour.d.ts +2 -1
  512. package/dist/tour/Tour.js +256 -75
  513. package/dist/tour/Tour.js.map +1 -1
  514. package/dist/tour/default-tour.js +222 -96
  515. package/dist/tour/default-tour.js.map +1 -1
  516. package/dist/types.d.ts +63 -29
  517. package/package.json +19 -15
  518. package/styles.css +39 -10
  519. package/dist/editor/ComponentInfo.d.ts +0 -4
  520. package/dist/editor/ComponentInfo.js +0 -41
  521. package/dist/editor/ComponentInfo.js.map +0 -1
  522. package/dist/editor/ai/HelpTerminal.d.ts +0 -5
  523. package/dist/editor/ai/HelpTerminal.js +0 -166
  524. package/dist/editor/ai/HelpTerminal.js.map +0 -1
  525. package/dist/editor/field-types/ReactQuill.d.ts +0 -125
  526. package/dist/editor/field-types/ReactQuill.js +0 -385
  527. package/dist/editor/field-types/ReactQuill.js.map +0 -1
  528. package/dist/editor/services-server/graphQL.d.ts +0 -29
  529. package/dist/editor/services-server/graphQL.js +0 -53
  530. package/dist/editor/services-server/graphQL.js.map +0 -1
  531. package/dist/editor/settings/AllAgentsPanel.d.ts +0 -5
  532. package/dist/editor/settings/AllAgentsPanel.js +0 -139
  533. package/dist/editor/settings/AllAgentsPanel.js.map +0 -1
  534. package/dist/editor/settings/LatestFeedback.d.ts +0 -1
  535. package/dist/editor/settings/LatestFeedback.js +0 -136
  536. package/dist/editor/settings/LatestFeedback.js.map +0 -1
  537. package/dist/editor/settings/Setup.d.ts +0 -1
  538. package/dist/editor/settings/Setup.js +0 -211
  539. package/dist/editor/settings/Setup.js.map +0 -1
  540. package/dist/editor/settings/panels/DatabasePanel.d.ts +0 -6
  541. package/dist/editor/settings/panels/DatabasePanel.js +0 -50
  542. package/dist/editor/settings/panels/DatabasePanel.js.map +0 -1
  543. package/dist/editor/settings/setup-steps/AiSetupStep/EmbeddingsModelSection.d.ts +0 -2
  544. package/dist/editor/settings/setup-steps/AiSetupStep/EmbeddingsModelSection.js +0 -195
  545. package/dist/editor/settings/setup-steps/AiSetupStep/EmbeddingsModelSection.js.map +0 -1
  546. package/dist/editor/settings/setup-steps/AiSetupStep/index.d.ts +0 -2
  547. package/dist/editor/settings/setup-steps/AiSetupStep/index.js +0 -21
  548. package/dist/editor/settings/setup-steps/AiSetupStep/index.js.map +0 -1
  549. package/dist/editor/settings/setup-steps/AiSetupStep/provider/ProviderSection.d.ts +0 -1
  550. package/dist/editor/settings/setup-steps/AiSetupStep/provider/ProviderSection.js +0 -233
  551. package/dist/editor/settings/setup-steps/AiSetupStep/provider/ProviderSection.js.map +0 -1
  552. package/dist/editor/settings/setup-steps/AiSetupStep/required-containers/RequiredContainersList.d.ts +0 -15
  553. package/dist/editor/settings/setup-steps/AiSetupStep/required-containers/RequiredContainersList.js +0 -14
  554. package/dist/editor/settings/setup-steps/AiSetupStep/required-containers/RequiredContainersList.js.map +0 -1
  555. package/dist/editor/settings/setup-steps/AiSetupStep/required-containers/RequiredContainersSection.d.ts +0 -1
  556. package/dist/editor/settings/setup-steps/AiSetupStep/required-containers/RequiredContainersSection.js +0 -94
  557. package/dist/editor/settings/setup-steps/AiSetupStep/required-containers/RequiredContainersSection.js.map +0 -1
  558. package/dist/editor/settings/setup-steps/AiSetupStep/types.d.ts +0 -1
  559. package/dist/editor/settings/setup-steps/AiSetupStep/types.js +0 -2
  560. package/dist/editor/settings/setup-steps/AiSetupStep/types.js.map +0 -1
  561. package/dist/editor/settings/setup-steps/AiSetupStep/utils.d.ts +0 -5
  562. package/dist/editor/settings/setup-steps/AiSetupStep/utils.js +0 -44
  563. package/dist/editor/settings/setup-steps/AiSetupStep/utils.js.map +0 -1
  564. package/dist/editor/settings/setup-steps/IndexSetupStep.d.ts +0 -2
  565. package/dist/editor/settings/setup-steps/IndexSetupStep.js +0 -36
  566. package/dist/editor/settings/setup-steps/IndexSetupStep.js.map +0 -1
  567. package/dist/editor/settings/setup-steps/SettingsSetupStep.d.ts +0 -2
  568. package/dist/editor/settings/setup-steps/SettingsSetupStep.js +0 -111
  569. package/dist/editor/settings/setup-steps/SettingsSetupStep.js.map +0 -1
  570. package/dist/editor/settings/setup-steps/SetupOverview.d.ts +0 -14
  571. package/dist/editor/settings/setup-steps/SetupOverview.js +0 -38
  572. package/dist/editor/settings/setup-steps/SetupOverview.js.map +0 -1
  573. package/dist/editor/sidebar/Debug.d.ts +0 -1
  574. package/dist/editor/sidebar/Debug.js +0 -70
  575. package/dist/editor/sidebar/Debug.js.map +0 -1
  576. package/dist/editor/sidebar/GraphQL.d.ts +0 -2
  577. package/dist/editor/sidebar/GraphQL.js +0 -234
  578. package/dist/editor/sidebar/GraphQL.js.map +0 -1
  579. package/dist/editor/sidebar/LeftToolbar.d.ts +0 -1
  580. package/dist/editor/sidebar/LeftToolbar.js +0 -12
  581. package/dist/editor/sidebar/LeftToolbar.js.map +0 -1
  582. package/dist/editor/sidebar/NavigationSidebar.d.ts +0 -4
  583. package/dist/editor/sidebar/NavigationSidebar.js +0 -254
  584. package/dist/editor/sidebar/NavigationSidebar.js.map +0 -1
  585. package/dist/editor/tree-indicators/GutterSelector.d.ts +0 -5
  586. package/dist/editor/tree-indicators/GutterSelector.js +0 -91
  587. package/dist/editor/tree-indicators/GutterSelector.js.map +0 -1
@@ -1,27 +1,188 @@
1
1
  "use client";
2
2
  import { jsx as _jsx, Fragment as _Fragment, jsxs as _jsxs } from "react/jsx-runtime";
3
3
  import { useState, useCallback, useRef, useEffect, useLayoutEffect, useMemo } from "react";
4
- import { Sparkles, Check, X, Loader2, SendHorizonal, Wand2, RotateCcw, Type, Scissors, Maximize2, Feather, Briefcase, History, HelpCircle, Cpu, } from "lucide-react";
4
+ import { Sparkles, Check, X, SendHorizonal, Wand2, RotateCcw, Maximize2, History, Cpu, RotateCw, StopCircle, } from "lucide-react";
5
5
  import { Button } from "../../components/ui/button";
6
+ import { Badge } from "../../components/ui/badge";
6
7
  import { Textarea } from "../../components/ui/textarea";
7
8
  import { Popover, PopoverTrigger, PopoverContent } from "../../components/ui/popover";
8
9
  import { cn } from "../../lib/utils";
10
+ import { sanitizeSvg } from "../../lib/sanitize";
9
11
  import { useEditContext } from "../client/editContext";
10
12
  import { startAgent, closeAgent } from "../services/agentService";
11
13
  import { getAiTextEditPrompts, getEditorSettings } from "../services/systemService";
12
14
  import { loadAiProfiles } from "../services/aiService";
15
+ import { localStorageService } from "../services/localStorageService";
13
16
  // Default Profile ID for the Inline Text Editor profile
14
17
  const DEFAULT_INLINE_TEXT_EDITOR_PROFILE_ID = "d7e8f9a0-b1c2-4d3e-a5f6-789012345678";
15
- // Map of supported icons for quick actions
16
- const ICON_MAP = {
17
- Type,
18
- Scissors,
19
- Maximize2,
20
- Feather,
21
- Briefcase,
22
- Sparkles,
23
- Wand2,
24
- };
18
+ const AI_TEXT_EDIT_MODELS_STORAGE_KEY = "aiTextEdit.selectedModelIds";
19
+ /** Normalize profile ID to a stable key (lowercase, no braces) so storage works regardless of API casing. */
20
+ function normalizeProfileIdForStorage(profileId) {
21
+ return profileId.replace(/^\{|\}$/g, "").toLowerCase();
22
+ }
23
+ function getStoredModelIds(profileId) {
24
+ try {
25
+ const parsed = localStorageService.getItem(AI_TEXT_EDIT_MODELS_STORAGE_KEY);
26
+ if (!parsed)
27
+ return null;
28
+ const normalizedKey = normalizeProfileIdForStorage(profileId);
29
+ // Prefer exact normalized key, then find any key that normalizes to the same
30
+ let ids = parsed?.[normalizedKey] ?? null;
31
+ if (!ids && parsed && typeof parsed === "object") {
32
+ for (const key of Object.keys(parsed)) {
33
+ if (normalizeProfileIdForStorage(key) === normalizedKey) {
34
+ ids = parsed[key] ?? null;
35
+ break;
36
+ }
37
+ }
38
+ }
39
+ return Array.isArray(ids) && ids.length > 0 ? ids : null;
40
+ }
41
+ catch {
42
+ return null;
43
+ }
44
+ }
45
+ function setStoredModelIds(profileId, modelIds) {
46
+ try {
47
+ const parsed = localStorageService.getItem(AI_TEXT_EDIT_MODELS_STORAGE_KEY) || {};
48
+ const normalizedKey = normalizeProfileIdForStorage(profileId);
49
+ // Merge: keep other profiles' keys as-is, but normalize keys we care about so we don't accumulate duplicates
50
+ const data = {};
51
+ const seen = new Set();
52
+ for (const key of Object.keys(parsed)) {
53
+ const n = normalizeProfileIdForStorage(key);
54
+ if (seen.has(n))
55
+ continue;
56
+ seen.add(n);
57
+ data[n] = parsed[key] ?? [];
58
+ }
59
+ data[normalizedKey] = modelIds;
60
+ localStorageService.setItem(AI_TEXT_EDIT_MODELS_STORAGE_KEY, data);
61
+ }
62
+ catch {
63
+ // ignore
64
+ }
65
+ }
66
+ const AI_TEXT_EDIT_RESPONSE_FORMAT_INSTRUCTION = `Return ONLY valid JSON (no markdown, no code fences, no extra text).
67
+ Use exactly one of these shapes:
68
+ {"replacementText":"<the modified text>"}
69
+ {"error":"<short explanation of why you cannot complete this request>"}`;
70
+ function tryExtractFirstJsonObject(input) {
71
+ const start = input.indexOf("{");
72
+ if (start < 0)
73
+ return null;
74
+ let depth = 0;
75
+ let inString = false;
76
+ let escaped = false;
77
+ for (let i = start; i < input.length; i++) {
78
+ const ch = input[i];
79
+ if (inString) {
80
+ if (escaped) {
81
+ escaped = false;
82
+ }
83
+ else if (ch === "\\") {
84
+ escaped = true;
85
+ }
86
+ else if (ch === "\"") {
87
+ inString = false;
88
+ }
89
+ continue;
90
+ }
91
+ if (ch === "\"") {
92
+ inString = true;
93
+ continue;
94
+ }
95
+ if (ch === "{")
96
+ depth++;
97
+ if (ch === "}") {
98
+ depth--;
99
+ if (depth === 0) {
100
+ return input.slice(start, i + 1);
101
+ }
102
+ }
103
+ }
104
+ return null;
105
+ }
106
+ function cleanAgentResponse(raw) {
107
+ return raw
108
+ .trim()
109
+ .replace(/^```[\s\S]*?\n/, "")
110
+ .replace(/\n```$/, "")
111
+ .trim();
112
+ }
113
+ function parseAiTextEditResponse(raw) {
114
+ const cleaned = cleanAgentResponse(raw);
115
+ if (!cleaned) {
116
+ return { error: "AI returned an empty response." };
117
+ }
118
+ try {
119
+ let parsed = JSON.parse(cleaned);
120
+ // Some models return JSON wrapped as a JSON string; parse one extra level.
121
+ if (typeof parsed === "string") {
122
+ const reparsed = JSON.parse(parsed);
123
+ parsed = reparsed;
124
+ }
125
+ const parsedObj = parsed;
126
+ if (!parsedObj || typeof parsedObj !== "object") {
127
+ return { error: "AI returned an invalid response format." };
128
+ }
129
+ if (typeof parsedObj.error === "string" && parsedObj.error.trim().length > 0) {
130
+ return { error: parsedObj.error.trim() };
131
+ }
132
+ if (typeof parsedObj.replacementText === "string") {
133
+ return { replacementText: parsedObj.replacementText };
134
+ }
135
+ return { error: "AI response is missing `replacementText` or `error`." };
136
+ }
137
+ catch {
138
+ const extractedJson = tryExtractFirstJsonObject(cleaned);
139
+ if (extractedJson) {
140
+ try {
141
+ const recovered = JSON.parse(extractedJson);
142
+ if (recovered && typeof recovered === "object") {
143
+ if (typeof recovered.error === "string" && recovered.error.trim()) {
144
+ return { error: recovered.error.trim() };
145
+ }
146
+ if (typeof recovered.replacementText === "string") {
147
+ return { replacementText: recovered.replacementText };
148
+ }
149
+ }
150
+ }
151
+ catch {
152
+ // ignore and fall through to regular error handling
153
+ }
154
+ }
155
+ if (cleaned && !cleaned.includes("{")) {
156
+ return { error: cleaned.slice(0, 300) };
157
+ }
158
+ return { error: "AI returned invalid JSON. Please try again." };
159
+ }
160
+ }
161
+ function extractAgentErrorMessage(message) {
162
+ const payload = message?.payload ?? {};
163
+ const payloadData = payload?.data ?? {};
164
+ const candidates = [
165
+ payload?.error,
166
+ payload?.Error,
167
+ payload?.message,
168
+ payload?.Message,
169
+ payload?.statusMessage,
170
+ payload?.StatusMessage,
171
+ payloadData?.error,
172
+ payloadData?.Error,
173
+ payloadData?.message,
174
+ payloadData?.Message,
175
+ payloadData?.statusMessage,
176
+ payloadData?.StatusMessage,
177
+ message?.data?.error,
178
+ ];
179
+ for (const candidate of candidates) {
180
+ if (typeof candidate === "string" && candidate.trim()) {
181
+ return candidate.trim();
182
+ }
183
+ }
184
+ return null;
185
+ }
25
186
  export function InlineAiDialog({ selectedText = "", contextBefore, contextAfter, onAccept, onClose, position, className, }) {
26
187
  const editContext = useEditContext();
27
188
  const [state, setState] = useState("input");
@@ -32,15 +193,18 @@ export function InlineAiDialog({ selectedText = "", contextBefore, contextAfter,
32
193
  const [quickActions, setQuickActions] = useState([]);
33
194
  const [profileId, setProfileId] = useState(DEFAULT_INLINE_TEXT_EDITOR_PROFILE_ID);
34
195
  const [activeProfile, setActiveProfile] = useState(undefined);
35
- const [selectedModelId, setSelectedModelId] = useState(undefined);
196
+ const [selectedModelIds, setSelectedModelIds] = useState([]);
197
+ const [modelRuns, setModelRuns] = useState({});
36
198
  const inputRef = useRef(null);
37
199
  const dialogRef = useRef(null);
38
200
  const [isLarge, setIsLarge] = useState(false);
39
201
  const [clampedPosition, setClampedPosition] = useState(position);
40
- // Agent state - persisted across refinements
41
- const agentIdRef = useRef(null);
202
+ // Agent state for the current multi-model run
203
+ const activeAgentIdsRef = useRef(new Set());
42
204
  const unsubscribeRef = useRef(null);
43
- const resultRef = useRef("");
205
+ const modelRunsRef = useRef({});
206
+ const latestRawContentRef = useRef({});
207
+ const lastParsedRawRef = useRef({});
44
208
  // Model popover state
45
209
  const [modelPopoverOpen, setModelPopoverOpen] = useState(false);
46
210
  // ALT+letter quick select state
@@ -50,14 +214,29 @@ export function InlineAiDialog({ selectedText = "", contextBefore, contextAfter,
50
214
  // Available models from the profile
51
215
  const availableModels = activeProfile?.models || [];
52
216
  const hasMultipleModels = availableModels.length > 1;
53
- // Get the selected model name for display
54
- const selectedModelName = useMemo(() => {
55
- if (!selectedModelId || !availableModels.length)
217
+ // Build the selected model list (fallback to first model if somehow stale)
218
+ const selectedModels = useMemo(() => {
219
+ if (!availableModels.length)
220
+ return [];
221
+ const byId = new Map(availableModels.map((m) => [m.id, m]));
222
+ const selected = selectedModelIds.map((id) => byId.get(id)).filter(Boolean);
223
+ return selected.length ? selected : availableModels.slice(0, 1);
224
+ }, [selectedModelIds, availableModels]);
225
+ const selectedModelSummary = useMemo(() => {
226
+ if (!selectedModels.length)
56
227
  return null;
57
- const model = availableModels.find(m => m.id === selectedModelId);
58
- return model?.name || null;
59
- }, [selectedModelId, availableModels]);
60
- // Load settings and prompts on mount
228
+ if (selectedModels.length === 1)
229
+ return selectedModels[0]?.name || null;
230
+ return `${selectedModels.length} models selected`;
231
+ }, [selectedModels]);
232
+ const successfulRuns = useMemo(() => Object.values(modelRuns).filter((run) => run.status === "done" && typeof run.replacementText === "string" && run.replacementText.length > 0), [modelRuns]);
233
+ const hasMultipleResults = successfulRuns.length > 1;
234
+ // Automatically switch to larger mode when showing more than one response
235
+ useEffect(() => {
236
+ if (state === "preview" && hasMultipleResults) {
237
+ setIsLarge(true);
238
+ }
239
+ }, [state, hasMultipleResults]);
61
240
  useEffect(() => {
62
241
  const loadSettings = async () => {
63
242
  try {
@@ -85,13 +264,19 @@ export function InlineAiDialog({ selectedText = "", contextBefore, contextAfter,
85
264
  return;
86
265
  try {
87
266
  const profiles = await loadAiProfiles();
88
- const profile = profiles.find(p => p.id === profileId);
267
+ const normalizedProfileId = normalizeProfileIdForStorage(profileId);
268
+ const profile = profiles.find((p) => normalizeProfileIdForStorage(p.id) === normalizedProfileId);
89
269
  if (profile) {
90
270
  setActiveProfile(profile);
91
- // Set default model
271
+ const availableModelIds = new Set((profile.models ?? []).map((m) => m.id));
92
272
  const defaultModelId = profile.defaultModelId || profile.models?.[0]?.id;
93
- if (defaultModelId) {
94
- setSelectedModelId(defaultModelId);
273
+ const stored = getStoredModelIds(profileId);
274
+ const validStored = stored?.filter((id) => availableModelIds.has(id));
275
+ if (validStored?.length) {
276
+ setSelectedModelIds(validStored);
277
+ }
278
+ else if (defaultModelId) {
279
+ setSelectedModelIds([defaultModelId]);
95
280
  }
96
281
  }
97
282
  }
@@ -101,136 +286,230 @@ export function InlineAiDialog({ selectedText = "", contextBefore, contextAfter,
101
286
  };
102
287
  loadProfile();
103
288
  }, [profileId]);
289
+ useEffect(() => {
290
+ modelRunsRef.current = modelRuns;
291
+ }, [modelRuns]);
292
+ // Persist model selection to localStorage when it or profileId changes
293
+ useEffect(() => {
294
+ if (profileId && selectedModelIds.length > 0) {
295
+ setStoredModelIds(profileId, selectedModelIds);
296
+ }
297
+ }, [profileId, selectedModelIds]);
104
298
  // Focus input on mount
105
299
  useEffect(() => {
106
300
  if (inputRef.current) {
107
301
  inputRef.current.focus();
108
302
  }
109
303
  }, []);
110
- // Cleanup on unmount
111
- useEffect(() => {
112
- return () => {
113
- // Unsubscribe from WebSocket
114
- if (unsubscribeRef.current) {
115
- unsubscribeRef.current();
116
- }
117
- // Close the agent if it exists
118
- if (agentIdRef.current) {
119
- closeAgent(agentIdRef.current).catch(() => { });
120
- }
121
- };
304
+ const evaluateRunCompletion = useCallback((runs) => {
305
+ const values = Object.values(runs);
306
+ if (!values.length)
307
+ return;
308
+ const allTerminal = values.every((run) => run.status === "done" || run.status === "error");
309
+ if (!allTerminal)
310
+ return;
311
+ const doneRuns = values.filter((run) => run.status === "done" && run.replacementText?.length);
312
+ if (doneRuns.length === 0) {
313
+ setError("All selected models failed. See each model’s card for details. You can retry or change your instruction.");
314
+ setResult("");
315
+ // Stay in preview so the user sees per-model error cards and can Retry/Discard
316
+ return;
317
+ }
318
+ if (doneRuns.length === 1) {
319
+ setResult(doneRuns[0]?.replacementText ?? "");
320
+ }
321
+ else {
322
+ setResult("");
323
+ }
324
+ setError(null);
325
+ // State is already "preview" – we show results side-by-side as they stream in
122
326
  }, []);
123
- // Subscribe to WebSocket messages for the agent
124
- const subscribeToAgent = useCallback((agentId) => {
327
+ const updateModelRun = useCallback((agentId, updater) => {
328
+ setModelRuns((prev) => {
329
+ const current = prev[agentId];
330
+ if (!current)
331
+ return prev;
332
+ const updated = updater(current);
333
+ const next = { ...prev, [agentId]: updated };
334
+ modelRunsRef.current = next;
335
+ evaluateRunCompletion(next);
336
+ return next;
337
+ });
338
+ }, [evaluateRunCompletion]);
339
+ const subscribeAgent = useCallback((agentId) => {
125
340
  const socket = globalThis.editorSocket;
126
341
  if (!socket || socket.readyState !== WebSocket.OPEN) {
127
342
  console.warn("[InlineAiDialog] WebSocket not available");
128
343
  return;
129
344
  }
130
- // Send subscription message
131
345
  socket.send(JSON.stringify({
132
346
  type: "agent:subscribe",
133
- agentId: agentId,
347
+ agentId,
134
348
  }));
135
- // Add message listener via editContext
136
- if (editContext?.addSocketMessageListener) {
137
- const handleMessage = (message) => {
138
- // Only handle messages for our agent
139
- if (message.agentId !== agentId && message.payload?.agentId !== agentId) {
349
+ }, []);
350
+ const unsubscribeAllAgents = useCallback(() => {
351
+ const socket = globalThis.editorSocket;
352
+ if (!socket || socket.readyState !== WebSocket.OPEN)
353
+ return;
354
+ for (const agentId of activeAgentIdsRef.current) {
355
+ socket.send(JSON.stringify({
356
+ type: "agent:unsubscribe",
357
+ agentId,
358
+ }));
359
+ }
360
+ }, []);
361
+ const closeAllActiveAgents = useCallback(() => {
362
+ for (const agentId of activeAgentIdsRef.current) {
363
+ closeAgent(agentId).catch(() => { });
364
+ }
365
+ activeAgentIdsRef.current.clear();
366
+ latestRawContentRef.current = {};
367
+ lastParsedRawRef.current = {};
368
+ }, []);
369
+ const handleStopModelRun = useCallback((agentId) => {
370
+ activeAgentIdsRef.current.delete(agentId);
371
+ delete latestRawContentRef.current[agentId];
372
+ delete lastParsedRawRef.current[agentId];
373
+ closeAgent(agentId).catch(() => { });
374
+ updateModelRun(agentId, (current) => ({
375
+ ...current,
376
+ status: "error",
377
+ error: "Stopped by user",
378
+ }));
379
+ }, [updateModelRun]);
380
+ // Cleanup on unmount
381
+ useEffect(() => {
382
+ return () => {
383
+ unsubscribeAllAgents();
384
+ if (unsubscribeRef.current) {
385
+ unsubscribeRef.current();
386
+ }
387
+ closeAllActiveAgents();
388
+ };
389
+ }, [unsubscribeAllAgents, closeAllActiveAgents]);
390
+ const ensureSocketListener = useCallback(() => {
391
+ if (!editContext?.addSocketMessageListener || unsubscribeRef.current) {
392
+ return;
393
+ }
394
+ const handleMessage = (message) => {
395
+ const messageAgentId = message.agentId || message.payload?.agentId;
396
+ if (!messageAgentId || !activeAgentIdsRef.current.has(messageAgentId)) {
397
+ return;
398
+ }
399
+ const msgType = message.type;
400
+ if (msgType === "agent:run:delta") {
401
+ const deltaData = message.payload?.data;
402
+ const content = deltaData?.deltaContent || "";
403
+ const isIncremental = deltaData?.isIncremental !== false;
404
+ if (!content)
140
405
  return;
406
+ const previousRaw = latestRawContentRef.current[messageAgentId] || "";
407
+ const nextRaw = isIncremental ? previousRaw + content : content;
408
+ latestRawContentRef.current[messageAgentId] = nextRaw;
409
+ const existingRun = modelRunsRef.current[messageAgentId];
410
+ if (existingRun) {
411
+ modelRunsRef.current = {
412
+ ...modelRunsRef.current,
413
+ [messageAgentId]: {
414
+ ...existingRun,
415
+ status: "streaming",
416
+ rawContent: nextRaw,
417
+ },
418
+ };
141
419
  }
142
- const msgType = message.type;
143
- if (msgType === "agent:run:delta") {
144
- // Content chunks come via agent:run:delta with data.deltaContent
145
- const deltaData = message.payload?.data;
146
- const content = deltaData?.deltaContent || "";
147
- const isIncremental = deltaData?.isIncremental !== false;
148
- if (content) {
149
- if (isIncremental) {
150
- // Incremental: append to existing
151
- resultRef.current += content;
152
- }
153
- else {
154
- // Non-incremental: replace with totalContent or use deltaContent as full content
155
- resultRef.current = content;
156
- }
157
- // Clean up markdown formatting
158
- const cleanResult = resultRef.current
159
- .replace(/^```[\s\S]*?\n/, "")
160
- .replace(/\n```$/, "")
161
- .trim();
162
- setResult(cleanResult);
163
- }
420
+ updateModelRun(messageAgentId, (current) => {
421
+ const nextRawContent = isIncremental ? current.rawContent + content : content;
422
+ return {
423
+ ...current,
424
+ status: "streaming",
425
+ rawContent: nextRawContent,
426
+ };
427
+ });
428
+ }
429
+ else if (msgType === "agent:run:status" || msgType === "agent:status:update") {
430
+ const statusData = message.payload?.data || message.payload || {};
431
+ const normalizedStatus = (statusData.state || statusData.status || "").toString().toLowerCase();
432
+ if (normalizedStatus === "error") {
433
+ const errorMsg = extractAgentErrorMessage(message) || "AI could not complete this request.";
434
+ updateModelRun(messageAgentId, (current) => {
435
+ if (current.status === "done")
436
+ return current; // don't overwrite success
437
+ return { ...current, status: "error", error: errorMsg };
438
+ });
439
+ }
440
+ }
441
+ else if (msgType === "agent:run:error" || msgType === "agent:error") {
442
+ const errorMsg = extractAgentErrorMessage(message) || "AI could not complete this request.";
443
+ updateModelRun(messageAgentId, (current) => {
444
+ if (current.status === "done")
445
+ return current; // don't overwrite success
446
+ return { ...current, status: "error", error: errorMsg };
447
+ });
448
+ }
449
+ else if (msgType === "agent:message:complete" || msgType === "agent:run:complete") {
450
+ const lifecycleError = extractAgentErrorMessage(message);
451
+ if (lifecycleError) {
452
+ updateModelRun(messageAgentId, (current) => ({
453
+ ...current,
454
+ status: "error",
455
+ error: lifecycleError,
456
+ }));
457
+ return;
164
458
  }
165
- else if (msgType === "agent:message:complete" || msgType === "agent:run:complete") {
166
- // Message complete - switch to preview state
167
- setState("preview");
459
+ const current = modelRunsRef.current[messageAgentId];
460
+ const rawContentToParse = latestRawContentRef.current[messageAgentId] ?? current?.rawContent ?? "";
461
+ if (lastParsedRawRef.current[messageAgentId] === rawContentToParse) {
462
+ return;
168
463
  }
169
- else if (msgType === "agent:error") {
170
- // Error occurred
171
- const errorMsg = message.payload?.error || message.data?.error || "An error occurred";
172
- setError(errorMsg);
173
- setState("input");
464
+ lastParsedRawRef.current[messageAgentId] = rawContentToParse;
465
+ const parsed = parseAiTextEditResponse(rawContentToParse);
466
+ if (parsed.error) {
467
+ updateModelRun(messageAgentId, (run) => ({
468
+ ...run,
469
+ status: "error",
470
+ error: parsed.error,
471
+ }));
174
472
  }
175
- else if (msgType === "agent:status:update") {
176
- // Status update - check for running/completed
177
- const status = message.payload?.status;
178
- if (status === "completed" || status === "idle") {
179
- setState("preview");
180
- }
181
- else if (status === "error") {
182
- setError(message.payload?.message || "Agent error");
183
- setState("input");
184
- }
473
+ else {
474
+ updateModelRun(messageAgentId, (run) => ({
475
+ ...run,
476
+ status: "done",
477
+ replacementText: parsed.replacementText ?? "",
478
+ error: undefined,
479
+ }));
185
480
  }
186
- };
187
- unsubscribeRef.current = editContext.addSocketMessageListener(handleMessage);
188
- }
189
- }, [editContext]);
190
- // Unsubscribe from current agent
191
- const unsubscribeFromAgent = useCallback(() => {
192
- if (unsubscribeRef.current) {
193
- unsubscribeRef.current();
194
- unsubscribeRef.current = null;
195
- }
196
- if (agentIdRef.current) {
197
- const socket = globalThis.editorSocket;
198
- if (socket && socket.readyState === WebSocket.OPEN) {
199
- socket.send(JSON.stringify({
200
- type: "agent:unsubscribe",
201
- agentId: agentIdRef.current,
202
- }));
203
481
  }
204
- }
205
- }, []);
482
+ };
483
+ unsubscribeRef.current = editContext.addSocketMessageListener(handleMessage);
484
+ }, [editContext, updateModelRun]);
206
485
  const executeAiModification = useCallback(async (customInstruction) => {
207
486
  if (!editContext)
208
487
  return;
209
- setState("loading");
488
+ if (!selectedModels.length) {
489
+ setError("Select at least one model.");
490
+ return;
491
+ }
210
492
  setError(null);
211
- resultRef.current = "";
212
493
  setResult("");
494
+ setModelRuns({});
495
+ modelRunsRef.current = {};
496
+ latestRawContentRef.current = {};
497
+ lastParsedRawRef.current = {};
498
+ unsubscribeAllAgents();
499
+ closeAllActiveAgents();
213
500
  try {
214
- // Create new agent ID if this is first request, otherwise reuse for refinement
215
- const isNewAgent = !agentIdRef.current;
216
- if (isNewAgent) {
217
- agentIdRef.current = crypto.randomUUID();
218
- }
219
- const agentId = agentIdRef.current;
220
- // Build the message - include context on first message
221
- let message;
222
- if (isNewAgent) {
223
- // Include context around the selection if available
224
- const hasContext = contextBefore || contextAfter;
225
- const contextInfo = hasContext
226
- ? `CONTEXT (text surrounding the selection):
501
+ // Build the message with context around the selection if available
502
+ const hasContext = contextBefore || contextAfter;
503
+ const contextInfo = hasContext
504
+ ? `CONTEXT (text surrounding the selection):
227
505
  Before: "${contextBefore || ""}"
228
506
  After: "${contextAfter || ""}"
229
507
 
230
508
  `
231
- : "";
232
- if (selectedText) {
233
- message = `${contextInfo}I need you to modify ONLY the following selected portion of the text:
509
+ : "";
510
+ let message;
511
+ if (selectedText) {
512
+ message = `${contextInfo}I need you to modify ONLY the following selected portion of the text:
234
513
 
235
514
  SELECTED TEXT TO MODIFY:
236
515
  """
@@ -239,31 +518,22 @@ ${selectedText}
239
518
 
240
519
  ${customInstruction}
241
520
 
242
- Remember: Return ONLY the modified version of the selected text, not the entire field.`;
243
- }
244
- else {
245
- message = `${contextInfo}I need you to generate text at the cursor position.
521
+ Return ONLY the modified version of the selected text, not the entire field.
522
+ ${AI_TEXT_EDIT_RESPONSE_FORMAT_INSTRUCTION}`;
523
+ }
524
+ else {
525
+ message = `${contextInfo}I need you to generate text at the cursor position.
246
526
 
247
527
  ${customInstruction}
248
528
 
249
- Remember: Return ONLY the text to insert at the cursor position, not the entire field.`;
250
- }
251
- }
252
- else {
253
- // For refinements, just send the instruction
254
- message = customInstruction;
529
+ Return ONLY the text to insert at the cursor position, not the entire field.
530
+ ${AI_TEXT_EDIT_RESPONSE_FORMAT_INSTRUCTION}`;
255
531
  }
256
- // Subscribe to WebSocket before starting
257
- if (isNewAgent) {
258
- subscribeToAgent(agentId);
259
- }
260
- // Track conversation history
261
532
  setConversationHistory((prev) => [...prev, customInstruction]);
262
- // Build context based on profile's editorContextMode setting
263
533
  let agentContext = undefined;
264
534
  const contextMode = activeProfile?.editorContextMode;
265
535
  const shouldIncludeContext = contextMode === "onCreate" || contextMode === "live";
266
- if (shouldIncludeContext && isNewAgent) {
536
+ if (shouldIncludeContext) {
267
537
  const item = editContext.currentItemDescriptor;
268
538
  if (item) {
269
539
  agentContext = {
@@ -293,25 +563,66 @@ Remember: Return ONLY the text to insert at the cursor position, not the entire
293
563
  };
294
564
  }
295
565
  }
296
- // Start the agent
297
- const request = {
298
- agentId,
299
- message,
300
- sessionId: editContext.sessionId,
301
- profileId: profileId,
302
- mode: "autonomous",
303
- model: selectedModelId,
304
- context: agentContext,
305
- };
306
- console.log("[InlineAiDialog] Starting agent:", agentId, agentContext ? "with context" : "without context");
307
- await startAgent(request);
566
+ ensureSocketListener();
567
+ const initialRuns = {};
568
+ for (const model of selectedModels) {
569
+ const agentId = crypto.randomUUID();
570
+ activeAgentIdsRef.current.add(agentId);
571
+ latestRawContentRef.current[agentId] = "";
572
+ delete lastParsedRawRef.current[agentId];
573
+ initialRuns[agentId] = {
574
+ agentId,
575
+ modelId: model.id,
576
+ modelName: model.name,
577
+ status: "pending",
578
+ rawContent: "",
579
+ };
580
+ }
581
+ setModelRuns(initialRuns);
582
+ modelRunsRef.current = initialRuns;
583
+ setState("preview"); // Show results immediately side-by-side as they stream in
584
+ await Promise.all(Object.values(initialRuns).map(async (run) => {
585
+ subscribeAgent(run.agentId);
586
+ try {
587
+ await startAgent({
588
+ agentId: run.agentId,
589
+ message,
590
+ sessionId: editContext.sessionId,
591
+ profileId: profileId,
592
+ mode: "autonomous",
593
+ model: run.modelId,
594
+ context: agentContext,
595
+ });
596
+ }
597
+ catch (runErr) {
598
+ const errorMsg = runErr instanceof Error ? runErr.message : "Failed to start model run";
599
+ updateModelRun(run.agentId, (current) => ({
600
+ ...current,
601
+ status: "error",
602
+ error: errorMsg,
603
+ }));
604
+ }
605
+ }));
308
606
  }
309
607
  catch (err) {
310
608
  console.error("AI modification error:", err);
311
609
  setError(err instanceof Error ? err.message : "An error occurred");
312
610
  setState("input");
313
611
  }
314
- }, [editContext, selectedText, contextBefore, contextAfter, subscribeToAgent, profileId, selectedModelId, activeProfile]);
612
+ }, [
613
+ editContext,
614
+ selectedText,
615
+ contextBefore,
616
+ contextAfter,
617
+ profileId,
618
+ activeProfile,
619
+ selectedModels,
620
+ closeAllActiveAgents,
621
+ unsubscribeAllAgents,
622
+ ensureSocketListener,
623
+ subscribeAgent,
624
+ updateModelRun,
625
+ ]);
315
626
  const handleQuickAction = useCallback((action) => {
316
627
  executeAiModification(action.instruction);
317
628
  }, [executeAiModification]);
@@ -387,38 +698,50 @@ Remember: Return ONLY the text to insert at the cursor position, not the entire
387
698
  }
388
699
  };
389
700
  }, [state, isAltPressed, altSearchBuffer, quickActions, handleQuickAction]);
390
- const handleAccept = useCallback(() => {
391
- if (result) {
392
- onAccept(result);
393
- }
394
- }, [result, onAccept]);
701
+ const handleUseRunResult = useCallback((replacementText) => {
702
+ if (!replacementText)
703
+ return;
704
+ onAccept(replacementText);
705
+ }, [onAccept]);
706
+ const toggleModelSelection = useCallback((modelId) => {
707
+ setSelectedModelIds((prev) => {
708
+ if (prev.includes(modelId)) {
709
+ if (prev.length === 1) {
710
+ return prev;
711
+ }
712
+ return prev.filter((id) => id !== modelId);
713
+ }
714
+ return [...prev, modelId];
715
+ });
716
+ }, []);
395
717
  const handleTryAgain = useCallback(() => {
396
718
  // Go back to input state to refine
397
719
  setState("input");
398
720
  setResult("");
399
- resultRef.current = "";
400
- // Keep the agent for conversation history
401
721
  }, []);
402
- const handleStartOver = useCallback(() => {
403
- // Close existing agent and start fresh
404
- unsubscribeFromAgent();
405
- if (agentIdRef.current) {
406
- closeAgent(agentIdRef.current).catch(() => { });
407
- agentIdRef.current = null;
722
+ const handleRetry = useCallback(() => {
723
+ const lastInstruction = conversationHistory[conversationHistory.length - 1];
724
+ if (lastInstruction) {
725
+ executeAiModification(lastInstruction);
408
726
  }
727
+ }, [conversationHistory, executeAiModification]);
728
+ const handleStartOver = useCallback(() => {
729
+ unsubscribeAllAgents();
730
+ closeAllActiveAgents();
731
+ setModelRuns({});
732
+ modelRunsRef.current = {};
733
+ latestRawContentRef.current = {};
734
+ lastParsedRawRef.current = {};
409
735
  setState("input");
410
736
  setResult("");
411
- resultRef.current = "";
412
737
  setConversationHistory([]);
413
738
  setError(null);
414
- }, [unsubscribeFromAgent]);
739
+ }, [unsubscribeAllAgents, closeAllActiveAgents]);
415
740
  const handleClose = useCallback(() => {
416
- unsubscribeFromAgent();
417
- if (agentIdRef.current) {
418
- closeAgent(agentIdRef.current).catch(() => { });
419
- }
741
+ unsubscribeAllAgents();
742
+ closeAllActiveAgents();
420
743
  onClose();
421
- }, [unsubscribeFromAgent, onClose]);
744
+ }, [unsubscribeAllAgents, closeAllActiveAgents, onClose]);
422
745
  const toggleLarge = useCallback(() => {
423
746
  setIsLarge((prev) => !prev);
424
747
  }, []);
@@ -493,7 +816,7 @@ Remember: Return ONLY the text to insert at the cursor position, not the entire
493
816
  resizeObserver.disconnect();
494
817
  };
495
818
  // Re-clamp when the content changes (height changes) or when the requested position changes.
496
- }, [position?.x, position?.y, state, result, selectedText, isLarge]);
819
+ }, [position?.x, position?.y, state, result, selectedText, isLarge, modelRuns, hasMultipleResults]);
497
820
  return (_jsxs("div", { ref: dialogRef, className: cn("bg-white/95 backdrop-blur-sm rounded-xl shadow-[0_10px_40px_rgba(0,0,0,0.1)] border border-gray-100 max-h-[80vh] flex flex-col overflow-hidden agent-inline-dialog transition-all duration-300 ease-in-out", isLarge ? "w-[800px]" : "w-[420px]", "animate-in fade-in-0 zoom-in-95 duration-200 ease-out", className), style: clampedPosition
498
821
  ? {
499
822
  position: "fixed",
@@ -502,14 +825,13 @@ Remember: Return ONLY the text to insert at the cursor position, not the entire
502
825
  zIndex: 95,
503
826
  }
504
827
  : undefined, onKeyDown: handleKeyDown, children: [_jsxs("div", { className: "flex-shrink-0 flex items-center gap-2.5 px-4 py-3 bg-gradient-to-r from-violet-500/5 to-purple-500/5 border-b border-gray-100", children: [_jsx("div", { className: "flex items-center justify-center w-6 h-6 rounded-lg bg-violet-600 shadow-sm shadow-violet-200", children: _jsx(Sparkles, { className: "w-3.5 h-3.5 text-white" }) }), _jsxs("div", { className: "flex flex-col", children: [_jsx("span", { className: "text-sm font-semibold text-gray-800 leading-tight", children: "AI Text Edit" }), conversationHistory.length > 0 && (_jsxs("span", { className: "text-[10px] text-gray-400 font-medium", children: [conversationHistory.length, " ", conversationHistory.length === 1 ? "turn" : "turns", " in history"] }))] }), _jsxs("div", { className: "ml-auto flex items-center gap-1", children: [_jsx("button", { onClick: toggleLarge, className: cn("p-1.5 hover:bg-gray-100 rounded-lg transition-all duration-200 group", isLarge && "bg-violet-50 text-violet-600 hover:bg-violet-100"), title: isLarge ? "Make smaller" : "Make larger", children: _jsx(Maximize2, { className: cn("w-4 h-4 text-gray-400 group-hover:text-gray-600", isLarge && "text-violet-600") }) }), _jsx("button", { onClick: handleClose, className: "p-1.5 hover:bg-gray-100 rounded-lg transition-all duration-200 group", title: "Close", children: _jsx(X, { className: "w-4 h-4 text-gray-400 group-hover:text-gray-600" }) })] })] }), selectedText && (_jsxs("div", { className: "flex-shrink-0 px-4 py-3 bg-gray-50/50 border-b border-gray-100", children: [_jsxs("div", { className: "flex items-center gap-1.5 text-[10px] font-bold text-gray-400 uppercase tracking-wider mb-2", children: [_jsx("div", { className: "w-1.5 h-1.5 rounded-full bg-gray-200" }), "Selected Content"] }), _jsxs("div", { className: "relative max-h-48 overflow-y-auto whitespace-pre-wrap transition-all duration-300", children: [_jsx("div", { className: "absolute left-0 top-0 bottom-0 w-0.5 bg-violet-200 rounded-full" }), _jsx("div", { className: "pl-3", children: renderTextWithContext(selectedText) })] })] })), _jsxs("div", { className: "p-4 min-h-0 flex-1 overflow-y-auto", children: [state === "input" && (_jsxs("div", { className: "space-y-4", children: [_jsxs("div", { className: "space-y-2", children: [isAltPressed && (_jsxs("div", { className: "flex items-center gap-2 text-xs text-violet-600 bg-violet-50 px-2.5 py-1.5 rounded-lg animate-in fade-in duration-150", children: [_jsx("kbd", { className: "px-1.5 py-0.5 bg-violet-100 rounded text-[10px] font-mono font-bold", children: "ALT" }), _jsx("span", { className: "font-medium", children: altSearchBuffer ? (_jsxs(_Fragment, { children: ["Type to select: ", _jsx("span", { className: "font-bold", children: altSearchBuffer })] })) : ("Type first letters of an action...") })] })), _jsx("div", { className: "flex flex-wrap gap-2", children: quickActions.map((action) => {
505
- const isSvgIcon = action.icon?.trim().startsWith("<svg") || action.icon?.trim().startsWith("<?xml");
506
- const IconComponent = !isSvgIcon ? (ICON_MAP[action.icon] || HelpCircle) : null;
828
+ const hasSvgIcon = action.icon?.trim() && (action.icon.trim().startsWith("<svg") || action.icon.trim().startsWith("<?xml"));
507
829
  const labelLower = action.label.toLowerCase();
508
830
  const isMatch = isAltPressed && altSearchBuffer && labelLower.startsWith(altSearchBuffer);
509
831
  const isPartialMatch = isAltPressed && altSearchBuffer && labelLower.includes(altSearchBuffer) && !isMatch;
510
- return (_jsxs("button", { onClick: () => handleQuickAction(action), className: cn("flex items-center gap-1.5 px-2.5 py-1.5 text-xs font-medium rounded-lg transition-all duration-200", "bg-white border border-gray-200 text-gray-600", "hover:border-violet-300 hover:text-violet-700 hover:bg-violet-50", "active:scale-95 shadow-sm hover:shadow-md", isMatch && "border-violet-400 bg-violet-100 text-violet-700 ring-2 ring-violet-300", isPartialMatch && "border-violet-200 bg-violet-50/50", isAltPressed && !isMatch && !isPartialMatch && "opacity-50"), children: [isSvgIcon ? (_jsx("div", { className: "w-3.5 h-3.5 flex items-center justify-center [&>svg]:w-full [&>svg]:h-full", dangerouslySetInnerHTML: {
511
- __html: action.icon,
512
- } })) : (IconComponent && _jsx(IconComponent, { className: "w-3.5 h-3.5" })), isAltPressed && altSearchBuffer ? (_jsxs("span", { children: [_jsx("span", { className: cn(isMatch && "font-bold underline underline-offset-2"), children: action.label.slice(0, altSearchBuffer.length) }), action.label.slice(altSearchBuffer.length)] })) : (action.label)] }, action.id));
832
+ return (_jsxs("button", { onClick: () => handleQuickAction(action), className: cn("flex items-center gap-1.5 px-2.5 py-1.5 text-xs font-medium rounded-lg transition-all duration-200", "bg-white border border-gray-200 text-gray-600", "hover:border-violet-300 hover:text-violet-700 hover:bg-violet-50", "active:scale-95 shadow-sm hover:shadow-md", isMatch && "border-violet-400 bg-violet-100 text-violet-700 ring-2 ring-violet-300", isPartialMatch && "border-violet-200 bg-violet-50/50", isAltPressed && !isMatch && !isPartialMatch && "opacity-50"), children: [hasSvgIcon && (_jsx("div", { className: "w-3.5 h-3.5 flex items-center justify-center [&>svg]:w-full [&>svg]:h-full shrink-0", dangerouslySetInnerHTML: {
833
+ __html: sanitizeSvg(action.icon.trim()),
834
+ } })), isAltPressed && altSearchBuffer ? (_jsxs("span", { children: [_jsx("span", { className: cn(isMatch && "font-bold underline underline-offset-2"), children: action.label.slice(0, altSearchBuffer.length) }), action.label.slice(altSearchBuffer.length)] })) : (action.label)] }, action.id));
513
835
  }) })] }), _jsxs("form", { onSubmit: (e) => {
514
836
  e.preventDefault();
515
837
  if (instruction.trim()) {
@@ -518,27 +840,27 @@ Remember: Return ONLY the text to insert at the cursor position, not the entire
518
840
  }
519
841
  }, className: "relative group", children: [_jsx(Textarea, { ref: inputRef, value: instruction, onChange: (e) => setInstruction(e.target.value), onKeyDown: handleTextareaKeyDown, placeholder: conversationHistory.length > 0
520
842
  ? "How can I improve this further?"
521
- : "Describe the change you want...", className: cn("w-full py-3 pl-3 pr-14 text-sm rounded-2xl border border-gray-200", "focus:border-violet-400 focus:ring-4 focus:ring-violet-500/10", "outline-none transition-all duration-200 bg-gray-50/30 resize-none", isLarge ? "min-h-[200px]" : "min-h-[100px]") }), _jsxs("div", { className: "absolute right-2 bottom-2 flex items-center gap-1", children: [hasMultipleModels && (_jsxs(Popover, { open: modelPopoverOpen, onOpenChange: setModelPopoverOpen, children: [_jsx(PopoverTrigger, { asChild: true, children: _jsx("button", { type: "button", className: cn("p-1.5 rounded-lg transition-all duration-200", "text-gray-400 hover:text-violet-600 hover:bg-violet-50", modelPopoverOpen && "text-violet-600 bg-violet-50"), title: selectedModelName ? `Model: ${selectedModelName}` : "Select model", children: _jsx(Cpu, { className: "w-3.5 h-3.5" }) }) }), _jsxs(PopoverContent, { className: "w-48 p-1.5", align: "end", sideOffset: 8, children: [_jsx("div", { className: "text-[10px] font-semibold text-gray-400 uppercase tracking-wider px-2 py-1", children: "Model" }), _jsx("div", { className: "space-y-0.5", children: availableModels.map((model) => (_jsx("button", { type: "button", onClick: () => {
522
- setSelectedModelId(model.id);
523
- setModelPopoverOpen(false);
524
- }, className: cn("w-full text-left px-2 py-1.5 text-xs rounded-md transition-colors", selectedModelId === model.id
843
+ : "Describe the change you want...", className: cn("w-full py-3 pl-3 pr-14 text-xs rounded-2xl border border-gray-200", "focus:border-violet-400 focus:ring-4 focus:ring-violet-500/10", "outline-none transition-all duration-200 bg-gray-50/30 resize-none", isLarge ? "min-h-[200px]" : "min-h-[100px]") }), _jsxs("div", { className: "absolute right-2 bottom-2 flex items-center gap-1", children: [hasMultipleModels && (_jsxs(Popover, { open: modelPopoverOpen, onOpenChange: setModelPopoverOpen, children: [_jsx(PopoverTrigger, { asChild: true, children: _jsx("button", { type: "button", className: cn("p-1.5 rounded-lg transition-all duration-200", "text-gray-400 hover:text-violet-600 hover:bg-violet-50", modelPopoverOpen && "text-violet-600 bg-violet-50"), title: selectedModelSummary ? `Models: ${selectedModelSummary}` : "Select models", children: _jsx(Cpu, { className: "w-3.5 h-3.5" }) }) }), _jsxs(PopoverContent, { className: "w-56 p-1.5", align: "end", sideOffset: 8, children: [_jsxs("div", { className: "flex items-center justify-between px-2 py-1", children: [_jsx("span", { className: "text-[10px] font-semibold text-gray-400 uppercase tracking-wider", children: "Models" }), _jsxs("span", { className: "text-[10px] text-violet-600 font-medium", children: [selectedModels.length, " selected"] })] }), _jsx("div", { className: "space-y-0.5", children: availableModels.map((model) => (_jsxs("button", { type: "button", onClick: () => toggleModelSelection(model.id), className: cn("w-full text-left px-2 py-1.5 text-xs rounded-md transition-colors flex items-center gap-2", selectedModelIds.includes(model.id)
525
844
  ? "bg-violet-100 text-violet-700 font-medium"
526
- : "text-gray-600 hover:bg-gray-100"), children: model.name }, model.id))) })] })] })), _jsx("button", { type: "submit", disabled: !instruction.trim(), className: cn("p-2.5 rounded-xl transition-all duration-300", instruction.trim()
845
+ : "text-gray-600 hover:bg-gray-100"), children: [_jsx("span", { className: cn("w-3.5 h-3.5 rounded border flex items-center justify-center", selectedModelIds.includes(model.id)
846
+ ? "border-violet-600 bg-violet-600 text-white"
847
+ : "border-gray-300 bg-white text-transparent"), children: _jsx(Check, { className: "w-3 h-3" }) }), model.name] }, model.id))) })] })] })), _jsx("button", { type: "submit", disabled: !instruction.trim() || selectedModels.length === 0, className: cn("p-2.5 rounded-xl transition-all duration-300", instruction.trim() && selectedModels.length > 0
527
848
  ? "bg-violet-600 text-white shadow-lg shadow-violet-200 hover:bg-violet-700 hover:-translate-y-0.5"
528
- : "bg-gray-100 text-gray-400 cursor-not-allowed"), title: "Send (Enter)", children: _jsx(SendHorizonal, { className: "w-4 h-4" }) })] })] }), conversationHistory.length > 0 && (_jsxs("div", { className: "flex items-center justify-between pt-1", children: [_jsxs("div", { className: "flex items-center gap-1.5 text-[10px] text-gray-400 font-medium", children: [_jsx(History, { className: "w-3 h-3" }), "Conversation active"] }), _jsxs("button", { onClick: handleStartOver, className: "text-[10px] font-bold text-violet-600 hover:text-violet-700 uppercase tracking-tight flex items-center gap-1 transition-colors", children: [_jsx(RotateCcw, { className: "w-3 h-3" }), "Clear History"] })] })), error && (_jsxs("div", { className: "text-xs text-red-600 bg-red-50 px-3 py-2 rounded-lg border border-red-100 flex items-start gap-2 animate-in fade-in slide-in-from-top-1 duration-200", children: [_jsx(X, { className: "w-3.5 h-3.5 mt-0.5 shrink-0" }), _jsx("span", { children: error })] }))] })), state === "loading" && (_jsxs("div", { className: "flex flex-col items-center justify-center py-10 space-y-4", children: [_jsxs("div", { className: "relative", children: [_jsx("div", { className: "absolute inset-0 bg-violet-200 rounded-full animate-ping opacity-20" }), _jsx("div", { className: "relative bg-violet-50 p-4 rounded-full", children: _jsx(Loader2, { className: "w-8 h-8 text-violet-600 animate-spin" }) })] }), _jsxs("div", { className: "text-center", children: [_jsx("span", { className: "text-sm font-semibold text-gray-800 block", children: "AI is thinking..." }), _jsx("span", { className: "text-xs text-gray-500 mt-1 block px-10", children: "Updating your text based on your instructions." })] }), result && (_jsx("div", { className: "w-full mt-4 px-4 py-3 bg-violet-50/50 border border-violet-100 rounded-xl max-h-32 overflow-y-auto animate-in fade-in duration-300 whitespace-pre-wrap", children: renderTextWithContext(result, true) }))] })), state === "preview" && (_jsxs("div", { className: "space-y-4 animate-in fade-in slide-in-from-bottom-2 duration-300", children: [_jsxs("div", { children: [_jsxs("div", { className: "flex items-center gap-1.5 text-[10px] font-bold text-green-600 uppercase tracking-wider mb-2", children: [_jsx("div", { className: "w-1.5 h-1.5 rounded-full bg-green-500" }), "Suggested Edit"] }), _jsx("div", { className: "px-4 py-3 bg-green-50/50 border border-green-100 rounded-xl overflow-y-auto shadow-inner whitespace-pre-wrap transition-all duration-300", style: { maxHeight: isLarge ? '500px' : '192px' }, children: renderTextWithContext(result, true) })] }), _jsxs("form", { onSubmit: (e) => {
849
+ : "bg-gray-100 text-gray-400 cursor-not-allowed"), title: "Send (Enter)", children: _jsx(SendHorizonal, { className: "w-4 h-4" }) })] })] }), conversationHistory.length > 0 && (_jsxs("div", { className: "flex items-center justify-between pt-1", children: [_jsxs("div", { className: "flex items-center gap-1.5 text-[10px] text-gray-400 font-medium", children: [_jsx(History, { className: "w-3 h-3" }), "Conversation active"] }), _jsxs("button", { onClick: handleStartOver, className: "text-[10px] font-bold text-violet-600 hover:text-violet-700 uppercase tracking-tight flex items-center gap-1 transition-colors", children: [_jsx(RotateCcw, { className: "w-3 h-3" }), "Clear History"] })] })), error && (_jsxs("div", { className: "text-xs text-red-600 bg-red-50 px-3 py-2 rounded-lg border border-red-100 flex items-start gap-2 animate-in fade-in slide-in-from-top-1 duration-200", children: [_jsx(X, { className: "w-3.5 h-3.5 mt-0.5 shrink-0" }), _jsx("span", { children: error })] }))] })), state === "preview" && (_jsxs("div", { className: "space-y-4 animate-in fade-in slide-in-from-bottom-2 duration-300", children: [Object.keys(modelRuns).length > 0 && (_jsxs("div", { className: "space-y-2", children: [_jsxs("div", { className: "flex items-center gap-1.5 text-[10px] font-bold text-gray-500 uppercase tracking-wider", children: [_jsx("div", { className: "w-1.5 h-1.5 rounded-full bg-violet-400" }), Object.values(modelRuns).some((r) => r.status === "pending" || r.status === "streaming")
850
+ ? "Responses (live)"
851
+ : "Model responses"] }), _jsx("div", { className: "flex gap-3 overflow-x-auto pb-1", children: Object.values(modelRuns).map((run) => (_jsxs("div", { className: cn("min-w-[280px] flex-1 rounded-xl p-3 flex flex-col gap-2 border", run.status === "done" && "border-green-100 bg-green-50/40", run.status === "error" && "border-red-100 bg-red-50/30", (run.status === "pending" || run.status === "streaming") && "border-violet-100 bg-violet-50/30"), children: [_jsxs("div", { className: "flex items-center justify-between gap-2", children: [_jsx("div", { className: "text-xs font-semibold text-gray-700 truncate", children: run.modelName }), _jsxs("div", { className: "flex items-center gap-2 shrink-0", children: [(run.status === "pending" || run.status === "streaming") && (_jsx("button", { type: "button", onClick: () => handleStopModelRun(run.agentId), className: "p-1.5 rounded-lg text-gray-500 hover:text-red-600 hover:bg-red-50 transition-colors", title: "Stop this model", children: _jsx(StopCircle, { className: "w-4 h-4" }) })), _jsxs(Badge, { variant: "outline", className: cn("text-[10px]", run.status === "done" && "border-green-300 text-green-700", run.status === "error" && "border-red-300 text-red-700", (run.status === "pending" || run.status === "streaming") && "border-violet-300 text-violet-700"), children: [run.status === "pending" && "Queued", run.status === "streaming" && "Streaming…", run.status === "done" && "Ready", run.status === "error" && "Error"] })] })] }), _jsxs("div", { className: cn("text-xs whitespace-pre-wrap rounded-lg p-2 overflow-y-auto border min-h-[80px]", run.status === "done" && "bg-white/80 border-green-100", run.status === "error" && "bg-white/80 border-red-100 text-red-700", (run.status === "pending" || run.status === "streaming") && "bg-white/60 border-violet-100"), style: { maxHeight: isLarge ? "420px" : "200px" }, children: [run.status === "pending" && (_jsx("span", { className: "text-gray-400 italic", children: "Starting\u2026" })), run.status === "streaming" && (_jsx(_Fragment, { children: run.rawContent?.trim() ? (renderTextWithContext(run.rawContent, false)) : (_jsx("span", { className: "text-gray-400 italic", children: "Waiting for response\u2026" })) })), run.status === "done" && run.replacementText != null && (_jsxs(_Fragment, { children: [renderTextWithContext(run.replacementText, true), _jsxs(Button, { size: "sm", onClick: () => handleUseRunResult(run.replacementText), className: "mt-2 bg-violet-600 hover:bg-violet-700 text-white rounded-lg font-semibold w-full", children: [_jsx(Check, { className: "w-4 h-4 mr-1.5" }), "Use this"] })] })), run.status === "error" && (_jsx("div", { className: "text-red-700", children: run.error || "Something went wrong." }))] })] }, run.agentId))) })] })), _jsxs("form", { onSubmit: (e) => {
529
852
  e.preventDefault();
530
853
  if (instruction.trim()) {
531
854
  executeAiModification(instruction.trim());
532
855
  setInstruction("");
533
856
  }
534
- }, className: "relative group", children: [_jsx(Textarea, { ref: inputRef, value: instruction, onChange: (e) => setInstruction(e.target.value), onKeyDown: handleTextareaKeyDown, placeholder: "Not quite right? Ask for a change...", className: cn("w-full min-h-[80px] py-3 pl-3 pr-14 text-sm rounded-2xl border border-gray-200", "focus:border-violet-400 focus:ring-4 focus:ring-violet-500/10", "outline-none transition-all duration-200 bg-gray-50/30 resize-none") }), _jsxs("div", { className: "absolute right-2 bottom-2 flex items-center gap-1", children: [hasMultipleModels && (_jsxs(Popover, { open: modelPopoverOpen, onOpenChange: setModelPopoverOpen, children: [_jsx(PopoverTrigger, { asChild: true, children: _jsx("button", { type: "button", className: cn("p-1.5 rounded-lg transition-all duration-200", "text-gray-400 hover:text-violet-600 hover:bg-violet-50", modelPopoverOpen && "text-violet-600 bg-violet-50"), title: selectedModelName ? `Model: ${selectedModelName}` : "Select model", children: _jsx(Cpu, { className: "w-3.5 h-3.5" }) }) }), _jsxs(PopoverContent, { className: "w-48 p-1.5", align: "end", sideOffset: 8, children: [_jsx("div", { className: "text-[10px] font-semibold text-gray-400 uppercase tracking-wider px-2 py-1", children: "Model" }), _jsx("div", { className: "space-y-0.5", children: availableModels.map((model) => (_jsx("button", { type: "button", onClick: () => {
535
- setSelectedModelId(model.id);
536
- setModelPopoverOpen(false);
537
- }, className: cn("w-full text-left px-2 py-1.5 text-xs rounded-md transition-colors", selectedModelId === model.id
857
+ }, className: "relative group", children: [_jsx(Textarea, { ref: inputRef, value: instruction, onChange: (e) => setInstruction(e.target.value), onKeyDown: handleTextareaKeyDown, placeholder: "Not quite right? Ask for a change...", className: cn("w-full min-h-[80px] py-3 pl-3 pr-14 text-xs rounded-2xl border border-gray-200", "focus:border-violet-400 focus:ring-4 focus:ring-violet-500/10", "outline-none transition-all duration-200 bg-gray-50/30 resize-none") }), _jsxs("div", { className: "absolute right-2 bottom-2 flex items-center gap-1", children: [hasMultipleModels && (_jsxs(Popover, { open: modelPopoverOpen, onOpenChange: setModelPopoverOpen, children: [_jsx(PopoverTrigger, { asChild: true, children: _jsx("button", { type: "button", className: cn("p-1.5 rounded-lg transition-all duration-200", "text-gray-400 hover:text-violet-600 hover:bg-violet-50", modelPopoverOpen && "text-violet-600 bg-violet-50"), title: selectedModelSummary ? `Models: ${selectedModelSummary}` : "Select models", children: _jsx(Cpu, { className: "w-3.5 h-3.5" }) }) }), _jsxs(PopoverContent, { className: "w-56 p-1.5", align: "end", sideOffset: 8, children: [_jsxs("div", { className: "flex items-center justify-between px-2 py-1", children: [_jsx("span", { className: "text-[10px] font-semibold text-gray-400 uppercase tracking-wider", children: "Models" }), _jsxs("span", { className: "text-[10px] text-violet-600 font-medium", children: [selectedModels.length, " selected"] })] }), _jsx("div", { className: "space-y-0.5", children: availableModels.map((model) => (_jsxs("button", { type: "button", onClick: () => toggleModelSelection(model.id), className: cn("w-full text-left px-2 py-1.5 text-xs rounded-md transition-colors flex items-center gap-2", selectedModelIds.includes(model.id)
538
858
  ? "bg-violet-100 text-violet-700 font-medium"
539
- : "text-gray-600 hover:bg-gray-100"), children: model.name }, model.id))) })] })] })), _jsx("button", { type: "submit", disabled: !instruction.trim(), className: cn("p-2.5 rounded-xl transition-all duration-300", instruction.trim()
859
+ : "text-gray-600 hover:bg-gray-100"), children: [_jsx("span", { className: cn("w-3.5 h-3.5 rounded border flex items-center justify-center", selectedModelIds.includes(model.id)
860
+ ? "border-violet-600 bg-violet-600 text-white"
861
+ : "border-gray-300 bg-white text-transparent"), children: _jsx(Check, { className: "w-3 h-3" }) }), model.name] }, model.id))) })] })] })), _jsx("button", { type: "submit", disabled: !instruction.trim() || selectedModels.length === 0, className: cn("p-2.5 rounded-xl transition-all duration-300", instruction.trim() && selectedModels.length > 0
540
862
  ? "bg-violet-600 text-white shadow-lg shadow-violet-200 hover:bg-violet-700 hover:-translate-y-0.5"
541
- : "bg-gray-100 text-gray-400 cursor-not-allowed"), title: "Refine (Enter)", children: _jsx(Wand2, { className: "w-4 h-4" }) })] })] }), _jsxs("div", { className: "flex gap-2.5 pt-1", children: [_jsxs(Button, { variant: "ghost", size: "sm", onClick: handleStartOver, className: "flex-1 text-gray-500 hover:text-gray-700 hover:bg-gray-100 rounded-xl font-medium", children: [_jsx(RotateCcw, { className: "w-4 h-4 mr-2" }), "Discard"] }), _jsxs(Button, { size: "sm", onClick: handleAccept, className: "flex-[1.5] bg-violet-600 hover:bg-violet-700 text-white shadow-md shadow-violet-200 rounded-xl font-semibold", children: [_jsx(Check, { className: "w-4 h-4 mr-2" }), "Replace Selection"] })] })] }))] })] }));
863
+ : "bg-gray-100 text-gray-400 cursor-not-allowed"), title: "Refine (Enter)", children: _jsx(Wand2, { className: "w-4 h-4" }) })] })] }), _jsxs("div", { className: "flex gap-2.5 pt-1", children: [_jsxs(Button, { variant: "ghost", size: "sm", onClick: handleStartOver, className: "flex-1 text-gray-500 hover:text-gray-700 hover:bg-gray-100 rounded-xl font-medium", children: [_jsx(RotateCcw, { className: "w-4 h-4 mr-2" }), "Discard"] }), _jsxs(Button, { variant: "ghost", size: "sm", onClick: handleRetry, disabled: conversationHistory.length === 0, className: "flex-1 text-violet-600 hover:text-violet-700 hover:bg-violet-50 rounded-xl font-medium disabled:opacity-50 disabled:pointer-events-none", title: "Run the same request again", children: [_jsx(RotateCw, { className: "w-4 h-4 mr-2" }), "Retry"] })] })] }))] })] }));
542
864
  }
543
865
  export default InlineAiDialog;
544
866
  //# sourceMappingURL=InlineAiDialog.js.map