@parhelia/core 0.1.12882 → 0.1.12883

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 (414) hide show
  1. package/dist/agents-view/AgentsSidebar.js +1 -1
  2. package/dist/agents-view/AgentsSidebar.js.map +1 -1
  3. package/dist/agents-view/AgentsTitlebar.d.ts +1 -1
  4. package/dist/agents-view/AgentsTitlebar.js +3 -6
  5. package/dist/agents-view/AgentsTitlebar.js.map +1 -1
  6. package/dist/agents-view/AgentsView.d.ts +2 -2
  7. package/dist/agents-view/AgentsView.js +2 -2
  8. package/dist/agents-view/AgentsView.js.map +1 -1
  9. package/dist/agents-view/AgentsWorkspaceView.js +1 -12
  10. package/dist/agents-view/AgentsWorkspaceView.js.map +1 -1
  11. package/dist/agents-view/CreateAgentView.d.ts +1 -1
  12. package/dist/agents-view/CreateAgentView.js +1 -1
  13. package/dist/agents-view/DateAgentsGroup.js +12 -1
  14. package/dist/agents-view/DateAgentsGroup.js.map +1 -1
  15. package/dist/agents-view/ProfileAgentsGroup.js +16 -4
  16. package/dist/agents-view/ProfileAgentsGroup.js.map +1 -1
  17. package/dist/components/ui/card.d.ts +3 -1
  18. package/dist/components/ui/card.js +2 -2
  19. package/dist/components/ui/card.js.map +1 -1
  20. package/dist/components/ui/checkbox.js +1 -1
  21. package/dist/components/ui/checkbox.js.map +1 -1
  22. package/dist/components/ui/context-menu.d.ts +2 -1
  23. package/dist/components/ui/context-menu.js +6 -3
  24. package/dist/components/ui/context-menu.js.map +1 -1
  25. package/dist/components/ui/input.js +2 -2
  26. package/dist/components/ui/input.js.map +1 -1
  27. package/dist/components/ui/select.js +1 -1
  28. package/dist/components/ui/select.js.map +1 -1
  29. package/dist/components/ui/textarea.js +2 -2
  30. package/dist/components/ui/textarea.js.map +1 -1
  31. package/dist/config/config.js +91 -12
  32. package/dist/config/config.js.map +1 -1
  33. package/dist/editor/ContextMenu.d.ts +1 -0
  34. package/dist/editor/ContextMenu.js +4 -4
  35. package/dist/editor/ContextMenu.js.map +1 -1
  36. package/dist/editor/FieldActionsOverlay.d.ts +0 -1
  37. package/dist/editor/FieldActionsOverlay.js +1 -45
  38. package/dist/editor/FieldActionsOverlay.js.map +1 -1
  39. package/dist/editor/FieldHistory.d.ts +2 -1
  40. package/dist/editor/FieldHistory.js +13 -12
  41. package/dist/editor/FieldHistory.js.map +1 -1
  42. package/dist/editor/FieldListField.d.ts +1 -1
  43. package/dist/editor/FieldListField.js +24 -36
  44. package/dist/editor/FieldListField.js.map +1 -1
  45. package/dist/editor/ImageEditor.d.ts +6 -1
  46. package/dist/editor/ImageEditor.js +19 -3
  47. package/dist/editor/ImageEditor.js.map +1 -1
  48. package/dist/editor/LinkEditorDialog.d.ts +9 -2
  49. package/dist/editor/LinkEditorDialog.js +174 -70
  50. package/dist/editor/LinkEditorDialog.js.map +1 -1
  51. package/dist/editor/MainLayout.js +49 -6
  52. package/dist/editor/MainLayout.js.map +1 -1
  53. package/dist/editor/MobileLayout.js +33 -1
  54. package/dist/editor/MobileLayout.js.map +1 -1
  55. package/dist/editor/PictureCropper.js +45 -28
  56. package/dist/editor/PictureCropper.js.map +1 -1
  57. package/dist/editor/PictureEditor.d.ts +2 -1
  58. package/dist/editor/PictureEditor.js +5 -14
  59. package/dist/editor/PictureEditor.js.map +1 -1
  60. package/dist/editor/ai/AgentProfileSelector.js +7 -7
  61. package/dist/editor/ai/AgentProfileSelector.js.map +1 -1
  62. package/dist/editor/ai/Agents.js +20 -6
  63. package/dist/editor/ai/Agents.js.map +1 -1
  64. package/dist/editor/ai/GuidanceOverlay.js +1 -11
  65. package/dist/editor/ai/GuidanceOverlay.js.map +1 -1
  66. package/dist/editor/ai/InlineAiDialog.d.ts +1 -0
  67. package/dist/editor/ai/InlineAiDialog.js +254 -202
  68. package/dist/editor/ai/InlineAiDialog.js.map +1 -1
  69. package/dist/editor/ai/InlineAiTextEditTooltip.d.ts +8 -0
  70. package/dist/editor/ai/InlineAiTextEditTooltip.js +10 -0
  71. package/dist/editor/ai/InlineAiTextEditTooltip.js.map +1 -0
  72. package/dist/editor/ai/InlineAiTrigger.js +158 -31
  73. package/dist/editor/ai/InlineAiTrigger.js.map +1 -1
  74. package/dist/editor/ai/dialogs/capturePageDom.js +66 -36
  75. package/dist/editor/ai/dialogs/capturePageDom.js.map +1 -1
  76. package/dist/editor/ai/dialogs/capturePageScreenshot.js +281 -162
  77. package/dist/editor/ai/dialogs/capturePageScreenshot.js.map +1 -1
  78. package/dist/editor/ai/inlineAiTextEditLabels.d.ts +2 -0
  79. package/dist/editor/ai/inlineAiTextEditLabels.js +8 -0
  80. package/dist/editor/ai/inlineAiTextEditLabels.js.map +1 -0
  81. package/dist/editor/ai/prepareInlineAiTextSelection.d.ts +5 -0
  82. package/dist/editor/ai/prepareInlineAiTextSelection.js +86 -0
  83. package/dist/editor/ai/prepareInlineAiTextSelection.js.map +1 -0
  84. package/dist/editor/ai/terminal/agentSessionState.d.ts +3 -0
  85. package/dist/editor/ai/terminal/agentSessionState.js +3 -1
  86. package/dist/editor/ai/terminal/agentSessionState.js.map +1 -1
  87. package/dist/editor/ai/terminal/agentStartRequest.d.ts +2 -1
  88. package/dist/editor/ai/terminal/agentStartRequest.js +2 -1
  89. package/dist/editor/ai/terminal/agentStartRequest.js.map +1 -1
  90. package/dist/editor/ai/terminal/components/AgentCostDisplay.js +1 -1
  91. package/dist/editor/ai/terminal/components/AgentCostDisplay.js.map +1 -1
  92. package/dist/editor/ai/terminal/components/AgentDocumentList.d.ts +7 -0
  93. package/dist/editor/ai/terminal/components/AgentDocumentList.js +55 -13
  94. package/dist/editor/ai/terminal/components/AgentDocumentList.js.map +1 -1
  95. package/dist/editor/ai/terminal/components/AgentEditHistoryButton.d.ts +5 -0
  96. package/dist/editor/ai/terminal/components/AgentEditHistoryButton.js +12 -0
  97. package/dist/editor/ai/terminal/components/AgentEditHistoryButton.js.map +1 -0
  98. package/dist/editor/ai/terminal/components/AgentFullPromptControls.d.ts +3 -1
  99. package/dist/editor/ai/terminal/components/AgentFullPromptControls.js +22 -14
  100. package/dist/editor/ai/terminal/components/AgentFullPromptControls.js.map +1 -1
  101. package/dist/editor/ai/terminal/components/AgentModeSelector.js +4 -4
  102. package/dist/editor/ai/terminal/components/AgentModeSelector.js.map +1 -1
  103. package/dist/editor/ai/terminal/components/AgentPromptActionButtons.js +4 -4
  104. package/dist/editor/ai/terminal/components/AgentPromptActionButtons.js.map +1 -1
  105. package/dist/editor/ai/terminal/components/AgentPromptComposer.js +1 -1
  106. package/dist/editor/ai/terminal/components/AgentPromptComposer.js.map +1 -1
  107. package/dist/editor/ai/terminal/components/AgentPromptInputArea.d.ts +2 -1
  108. package/dist/editor/ai/terminal/components/AgentPromptInputArea.js +8 -11
  109. package/dist/editor/ai/terminal/components/AgentPromptInputArea.js.map +1 -1
  110. package/dist/editor/ai/terminal/components/AgentPromptTrayPopovers.d.ts +1 -4
  111. package/dist/editor/ai/terminal/components/AgentPromptTrayPopovers.js +31 -14
  112. package/dist/editor/ai/terminal/components/AgentPromptTrayPopovers.js.map +1 -1
  113. package/dist/editor/ai/terminal/components/AgentSettingsPopover.js +1 -1
  114. package/dist/editor/ai/terminal/components/AgentSettingsPopover.js.map +1 -1
  115. package/dist/editor/ai/terminal/components/AgentTerminalFullLayout.d.ts +2 -1
  116. package/dist/editor/ai/terminal/components/AgentTerminalFullLayout.js +2 -4
  117. package/dist/editor/ai/terminal/components/AgentTerminalFullLayout.js.map +1 -1
  118. package/dist/editor/ai/terminal/components/AgentTerminalMessageGroups.js +1 -1
  119. package/dist/editor/ai/terminal/components/AgentTerminalMessageGroups.js.map +1 -1
  120. package/dist/editor/ai/terminal/components/AgentTerminalView.js +13 -2
  121. package/dist/editor/ai/terminal/components/AgentTerminalView.js.map +1 -1
  122. package/dist/editor/ai/terminal/components/AiResponseMessage.js +11 -9
  123. package/dist/editor/ai/terminal/components/AiResponseMessage.js.map +1 -1
  124. package/dist/editor/ai/terminal/components/ContextInfoBar.js +22 -2
  125. package/dist/editor/ai/terminal/components/ContextInfoBar.js.map +1 -1
  126. package/dist/editor/ai/terminal/components/QueuedPromptsPanel.js +37 -26
  127. package/dist/editor/ai/terminal/components/QueuedPromptsPanel.js.map +1 -1
  128. package/dist/editor/ai/terminal/components/ToolCallDisplay.js +3 -1
  129. package/dist/editor/ai/terminal/components/ToolCallDisplay.js.map +1 -1
  130. package/dist/editor/ai/terminal/components/UserMessage.d.ts +2 -1
  131. package/dist/editor/ai/terminal/components/UserMessage.js +144 -8
  132. package/dist/editor/ai/terminal/components/UserMessage.js.map +1 -1
  133. package/dist/editor/ai/terminal/useAgentPromptComposerHandlers.js +1 -1
  134. package/dist/editor/ai/terminal/useAgentPromptComposerHandlers.js.map +1 -1
  135. package/dist/editor/ai/terminal/useAgentSessionSync.d.ts +1 -0
  136. package/dist/editor/ai/terminal/useAgentSubmitHandlers.d.ts +3 -1
  137. package/dist/editor/ai/terminal/useAgentSubmitHandlers.js +9 -3
  138. package/dist/editor/ai/terminal/useAgentSubmitHandlers.js.map +1 -1
  139. package/dist/editor/ai/terminal/useAgentTerminalController.js +7 -0
  140. package/dist/editor/ai/terminal/useAgentTerminalController.js.map +1 -1
  141. package/dist/editor/ai/terminal/useAgentTerminalUiState.js +1 -1
  142. package/dist/editor/ai/terminal/useAgentTerminalUiState.js.map +1 -1
  143. package/dist/editor/ai/terminal/useAgentUserMessageSocketHandler.js +3 -1
  144. package/dist/editor/ai/terminal/useAgentUserMessageSocketHandler.js.map +1 -1
  145. package/dist/editor/ai/useActiveAgentConversation.d.ts +3 -0
  146. package/dist/editor/ai/useActiveAgentConversation.js +32 -0
  147. package/dist/editor/ai/useActiveAgentConversation.js.map +1 -0
  148. package/dist/editor/ai/useInlineAiPosition.d.ts +10 -2
  149. package/dist/editor/ai/useInlineAiPosition.js +32 -71
  150. package/dist/editor/ai/useInlineAiPosition.js.map +1 -1
  151. package/dist/editor/ai-image-editor/AiImageResultOverlay.js +30 -62
  152. package/dist/editor/ai-image-editor/AiImageResultOverlay.js.map +1 -1
  153. package/dist/editor/bridge/BridgeClient.d.ts +80 -0
  154. package/dist/editor/bridge/BridgeClient.js +417 -0
  155. package/dist/editor/bridge/BridgeClient.js.map +1 -0
  156. package/dist/editor/client/EditorShell.d.ts +5 -1
  157. package/dist/editor/client/EditorShell.js +295 -127
  158. package/dist/editor/client/EditorShell.js.map +1 -1
  159. package/dist/editor/client/editContext.d.ts +58 -5
  160. package/dist/editor/client/editContext.js.map +1 -1
  161. package/dist/editor/client/fieldModificationStore.d.ts +1 -0
  162. package/dist/editor/client/fieldModificationStore.js +7 -2
  163. package/dist/editor/client/fieldModificationStore.js.map +1 -1
  164. package/dist/editor/client/hooks/useSocketMessageHandler.js +14 -17
  165. package/dist/editor/client/hooks/useSocketMessageHandler.js.map +1 -1
  166. package/dist/editor/client/itemsRepository.d.ts +2 -0
  167. package/dist/editor/client/itemsRepository.js +18 -9
  168. package/dist/editor/client/itemsRepository.js.map +1 -1
  169. package/dist/editor/client/operations.d.ts +1 -1
  170. package/dist/editor/client/operations.js +67 -21
  171. package/dist/editor/client/operations.js.map +1 -1
  172. package/dist/editor/client/pageModelBuilder.js +24 -7
  173. package/dist/editor/client/pageModelBuilder.js.map +1 -1
  174. package/dist/editor/client/ui/EditorChrome.js +1 -1
  175. package/dist/editor/client/ui/EditorChrome.js.map +1 -1
  176. package/dist/editor/commands/componentCommands.d.ts +3 -1
  177. package/dist/editor/commands/componentCommands.js +8 -3
  178. package/dist/editor/commands/componentCommands.js.map +1 -1
  179. package/dist/editor/field-types/DateFieldEditor.js +1 -1
  180. package/dist/editor/field-types/DateFieldEditor.js.map +1 -1
  181. package/dist/editor/field-types/DateTimeFieldEditor.js +1 -1
  182. package/dist/editor/field-types/DateTimeFieldEditor.js.map +1 -1
  183. package/dist/editor/field-types/DropLinkEditor.js +1 -1
  184. package/dist/editor/field-types/DropLinkEditor.js.map +1 -1
  185. package/dist/editor/field-types/DropListEditor.js +1 -1
  186. package/dist/editor/field-types/DropListEditor.js.map +1 -1
  187. package/dist/editor/field-types/ImageFieldEditor.js +1 -1
  188. package/dist/editor/field-types/ImageFieldEditor.js.map +1 -1
  189. package/dist/editor/field-types/InternalLinkFieldEditor.js +1 -1
  190. package/dist/editor/field-types/InternalLinkFieldEditor.js.map +1 -1
  191. package/dist/editor/field-types/LinkFieldEditor.js +15 -3
  192. package/dist/editor/field-types/LinkFieldEditor.js.map +1 -1
  193. package/dist/editor/field-types/MultiLineText.js +11 -4
  194. package/dist/editor/field-types/MultiLineText.js.map +1 -1
  195. package/dist/editor/field-types/NameValueListEditor.js +1 -1
  196. package/dist/editor/field-types/NameValueListEditor.js.map +1 -1
  197. package/dist/editor/field-types/PictureFieldEditor.js +2 -2
  198. package/dist/editor/field-types/PictureFieldEditor.js.map +1 -1
  199. package/dist/editor/field-types/RawEditor.js +9 -2
  200. package/dist/editor/field-types/RawEditor.js.map +1 -1
  201. package/dist/editor/field-types/RichTextEditorComponent.js +170 -77
  202. package/dist/editor/field-types/RichTextEditorComponent.js.map +1 -1
  203. package/dist/editor/field-types/SingleLineText.js +10 -3
  204. package/dist/editor/field-types/SingleLineText.js.map +1 -1
  205. package/dist/editor/field-types/TreeListEditor.js +1 -1
  206. package/dist/editor/field-types/TreeListEditor.js.map +1 -1
  207. package/dist/editor/field-types/richtext/bridgeRichTextProfile.d.ts +21 -0
  208. package/dist/editor/field-types/richtext/bridgeRichTextProfile.js +96 -0
  209. package/dist/editor/field-types/richtext/bridgeRichTextProfile.js.map +1 -0
  210. package/dist/editor/field-types/richtext/components/ReactSlate.css +44 -6
  211. package/dist/editor/field-types/richtext/components/ReactSlate.js +191 -36
  212. package/dist/editor/field-types/richtext/components/ReactSlate.js.map +1 -1
  213. package/dist/editor/field-types/richtext/components/SimpleRichTextEditor.css +5 -2
  214. package/dist/editor/field-types/richtext/components/SimpleToolbar.js +5 -4
  215. package/dist/editor/field-types/richtext/components/SimpleToolbar.js.map +1 -1
  216. package/dist/editor/field-types/richtext/contextMenuFactory.d.ts +2 -15
  217. package/dist/editor/field-types/richtext/contextMenuFactory.js +4 -435
  218. package/dist/editor/field-types/richtext/contextMenuFactory.js.map +1 -1
  219. package/dist/editor/field-types/richtext/richTextToolbarIcons.d.ts +7 -0
  220. package/dist/editor/field-types/richtext/richTextToolbarIcons.js +49 -0
  221. package/dist/editor/field-types/richtext/richTextToolbarIcons.js.map +1 -0
  222. package/dist/editor/field-types/richtext/types.d.ts +2 -0
  223. package/dist/editor/field-types/richtext/types.js.map +1 -1
  224. package/dist/editor/field-types/richtext/utils/conversion.js +23 -2
  225. package/dist/editor/field-types/richtext/utils/conversion.js.map +1 -1
  226. package/dist/editor/field-types/useFormFieldCaretPresence.d.ts +13 -0
  227. package/dist/editor/field-types/useFormFieldCaretPresence.js +92 -0
  228. package/dist/editor/field-types/useFormFieldCaretPresence.js.map +1 -0
  229. package/dist/editor/fieldTypes.d.ts +2 -0
  230. package/dist/editor/media-selector/TreeSelector.js +15 -15
  231. package/dist/editor/media-selector/TreeSelector.js.map +1 -1
  232. package/dist/editor/menubar/PageSelector.js +8 -2
  233. package/dist/editor/menubar/PageSelector.js.map +1 -1
  234. package/dist/editor/menubar/VersionPreviewCard.js +4 -249
  235. package/dist/editor/menubar/VersionPreviewCard.js.map +1 -1
  236. package/dist/editor/menubar/toolbar-sections/EditControls.js +2 -2
  237. package/dist/editor/menubar/toolbar-sections/EditControls.js.map +1 -1
  238. package/dist/editor/menubar/toolbar-sections/ManualBrowser.js +310 -187
  239. package/dist/editor/menubar/toolbar-sections/ManualBrowser.js.map +1 -1
  240. package/dist/editor/menubar/toolbar-sections/UtilityControls.js +3 -1
  241. package/dist/editor/menubar/toolbar-sections/UtilityControls.js.map +1 -1
  242. package/dist/editor/menubar/toolbar-sections/ViewportControls.js +1 -1
  243. package/dist/editor/page-editor-chrome/BridgeInlineFormatOverlay.d.ts +8 -0
  244. package/dist/editor/page-editor-chrome/BridgeInlineFormatOverlay.js +407 -0
  245. package/dist/editor/page-editor-chrome/BridgeInlineFormatOverlay.js.map +1 -0
  246. package/dist/editor/page-editor-chrome/CommentHighlightings.d.ts +5 -2
  247. package/dist/editor/page-editor-chrome/CommentHighlightings.js +340 -215
  248. package/dist/editor/page-editor-chrome/CommentHighlightings.js.map +1 -1
  249. package/dist/editor/page-editor-chrome/FeedbackHighlightBadge.d.ts +5 -1
  250. package/dist/editor/page-editor-chrome/FeedbackHighlightBadge.js +11 -4
  251. package/dist/editor/page-editor-chrome/FeedbackHighlightBadge.js.map +1 -1
  252. package/dist/editor/page-editor-chrome/FieldActionIndicator.js +21 -13
  253. package/dist/editor/page-editor-chrome/FieldActionIndicator.js.map +1 -1
  254. package/dist/editor/page-editor-chrome/FieldEditedIndicator.js +23 -29
  255. package/dist/editor/page-editor-chrome/FieldEditedIndicator.js.map +1 -1
  256. package/dist/editor/page-editor-chrome/FrameMenu.js +110 -19
  257. package/dist/editor/page-editor-chrome/FrameMenu.js.map +1 -1
  258. package/dist/editor/page-editor-chrome/LockedFieldIndicator.d.ts +3 -2
  259. package/dist/editor/page-editor-chrome/LockedFieldIndicator.js +148 -45
  260. package/dist/editor/page-editor-chrome/LockedFieldIndicator.js.map +1 -1
  261. package/dist/editor/page-editor-chrome/PageEditorChrome.d.ts +2 -0
  262. package/dist/editor/page-editor-chrome/PageEditorChrome.js +25 -21
  263. package/dist/editor/page-editor-chrome/PageEditorChrome.js.map +1 -1
  264. package/dist/editor/page-editor-chrome/PictureEditorOverlay.js +163 -128
  265. package/dist/editor/page-editor-chrome/PictureEditorOverlay.js.map +1 -1
  266. package/dist/editor/page-editor-chrome/PlaceholderDropZone.d.ts +1 -1
  267. package/dist/editor/page-editor-chrome/PlaceholderDropZone.js +6 -3
  268. package/dist/editor/page-editor-chrome/PlaceholderDropZone.js.map +1 -1
  269. package/dist/editor/page-editor-chrome/PlaceholderDropZones.d.ts +1 -2
  270. package/dist/editor/page-editor-chrome/PlaceholderDropZones.js +83 -146
  271. package/dist/editor/page-editor-chrome/PlaceholderDropZones.js.map +1 -1
  272. package/dist/editor/page-editor-chrome/SuggestionHighlightings.d.ts +5 -2
  273. package/dist/editor/page-editor-chrome/SuggestionHighlightings.js +144 -63
  274. package/dist/editor/page-editor-chrome/SuggestionHighlightings.js.map +1 -1
  275. package/dist/editor/page-editor-chrome/VersionDiffHighlightings.d.ts +1 -2
  276. package/dist/editor/page-editor-chrome/VersionDiffHighlightings.js +101 -30
  277. package/dist/editor/page-editor-chrome/VersionDiffHighlightings.js.map +1 -1
  278. package/dist/editor/page-editor-chrome/bridgeInlineFormatToolbarLayout.d.ts +24 -0
  279. package/dist/editor/page-editor-chrome/bridgeInlineFormatToolbarLayout.js +89 -0
  280. package/dist/editor/page-editor-chrome/bridgeInlineFormatToolbarLayout.js.map +1 -0
  281. package/dist/editor/page-editor-chrome/overlay/IframeOverlayProvider.d.ts +10 -1
  282. package/dist/editor/page-editor-chrome/overlay/IframeOverlayProvider.js +105 -122
  283. package/dist/editor/page-editor-chrome/overlay/IframeOverlayProvider.js.map +1 -1
  284. package/dist/editor/page-editor-chrome/overlay/geometry.d.ts +11 -4
  285. package/dist/editor/page-editor-chrome/overlay/geometry.js +139 -36
  286. package/dist/editor/page-editor-chrome/overlay/geometry.js.map +1 -1
  287. package/dist/editor/page-editor-chrome/useBridgeInlineEditing.d.ts +26 -0
  288. package/dist/editor/page-editor-chrome/useBridgeInlineEditing.js +228 -0
  289. package/dist/editor/page-editor-chrome/useBridgeInlineEditing.js.map +1 -0
  290. package/dist/editor/page-viewer/EditorForm.js +17 -1
  291. package/dist/editor/page-viewer/EditorForm.js.map +1 -1
  292. package/dist/editor/page-viewer/MiniMap.d.ts +2 -2
  293. package/dist/editor/page-viewer/MiniMap.js +176 -364
  294. package/dist/editor/page-viewer/MiniMap.js.map +1 -1
  295. package/dist/editor/page-viewer/PageViewer.js +63 -17
  296. package/dist/editor/page-viewer/PageViewer.js.map +1 -1
  297. package/dist/editor/page-viewer/PageViewerFrame.d.ts +0 -5
  298. package/dist/editor/page-viewer/PageViewerFrame.js +1685 -1512
  299. package/dist/editor/page-viewer/PageViewerFrame.js.map +1 -1
  300. package/dist/editor/page-viewer/bridgeFieldPatch.d.ts +20 -0
  301. package/dist/editor/page-viewer/bridgeFieldPatch.js +33 -0
  302. package/dist/editor/page-viewer/bridgeFieldPatch.js.map +1 -0
  303. package/dist/editor/page-viewer/pageViewContext.d.ts +32 -0
  304. package/dist/editor/page-viewer/pageViewContext.js +37 -6
  305. package/dist/editor/page-viewer/pageViewContext.js.map +1 -1
  306. package/dist/editor/reviews/Comment.d.ts +2 -1
  307. package/dist/editor/reviews/Comment.js +10 -5
  308. package/dist/editor/reviews/Comment.js.map +1 -1
  309. package/dist/editor/reviews/CommentDisplayPopover.js +2 -1
  310. package/dist/editor/reviews/CommentDisplayPopover.js.map +1 -1
  311. package/dist/editor/reviews/CommentEditor.d.ts +1 -0
  312. package/dist/editor/reviews/CommentEditor.js +3 -2
  313. package/dist/editor/reviews/CommentEditor.js.map +1 -1
  314. package/dist/editor/reviews/CommentPopover.js +69 -10
  315. package/dist/editor/reviews/CommentPopover.js.map +1 -1
  316. package/dist/editor/reviews/CommentView.js +24 -4
  317. package/dist/editor/reviews/CommentView.js.map +1 -1
  318. package/dist/editor/reviews/Comments.d.ts +0 -2
  319. package/dist/editor/reviews/Comments.js +31 -31
  320. package/dist/editor/reviews/Comments.js.map +1 -1
  321. package/dist/editor/reviews/FeedbackCard.d.ts +4 -2
  322. package/dist/editor/reviews/FeedbackCard.js +8 -10
  323. package/dist/editor/reviews/FeedbackCard.js.map +1 -1
  324. package/dist/editor/reviews/SuggestedEdit.js +4 -6
  325. package/dist/editor/reviews/SuggestedEdit.js.map +1 -1
  326. package/dist/editor/reviews/SuggestionCommentThread.js +3 -3
  327. package/dist/editor/reviews/SuggestionCommentThread.js.map +1 -1
  328. package/dist/editor/reviews/SuggestionDisplayPopover.js +3 -2
  329. package/dist/editor/reviews/SuggestionDisplayPopover.js.map +1 -1
  330. package/dist/editor/reviews/commentAi.js +96 -27
  331. package/dist/editor/reviews/commentAi.js.map +1 -1
  332. package/dist/editor/reviews/commentTransientSelection.d.ts +23 -0
  333. package/dist/editor/reviews/commentTransientSelection.js +7 -0
  334. package/dist/editor/reviews/commentTransientSelection.js.map +1 -0
  335. package/dist/editor/reviews/feedbackOrdering.d.ts +5 -0
  336. package/dist/editor/reviews/feedbackOrdering.js +27 -0
  337. package/dist/editor/reviews/feedbackOrdering.js.map +1 -0
  338. package/dist/editor/reviews/feedbackSelection.js +32 -4
  339. package/dist/editor/reviews/feedbackSelection.js.map +1 -1
  340. package/dist/editor/reviews/suggestedEditState.d.ts +12 -0
  341. package/dist/editor/reviews/suggestedEditState.js +90 -0
  342. package/dist/editor/reviews/suggestedEditState.js.map +1 -0
  343. package/dist/editor/reviews/suggestionDisplayValue.d.ts +43 -0
  344. package/dist/editor/reviews/suggestionDisplayValue.js +93 -0
  345. package/dist/editor/reviews/suggestionDisplayValue.js.map +1 -0
  346. package/dist/editor/services/agentService.d.ts +15 -0
  347. package/dist/editor/services/agentService.js +11 -1
  348. package/dist/editor/services/agentService.js.map +1 -1
  349. package/dist/editor/services/reviewsService.d.ts +2 -2
  350. package/dist/editor/services/reviewsService.js.map +1 -1
  351. package/dist/editor/settings/SettingsView.js +2 -2
  352. package/dist/editor/settings/SettingsView.js.map +1 -1
  353. package/dist/editor/settings/panels/ProjectTemplatesPanel.js +1 -1
  354. package/dist/editor/settings/panels/ProjectTemplatesPanel.js.map +1 -1
  355. package/dist/editor/settings/panels/ProvidersPanel.js +2 -3
  356. package/dist/editor/settings/panels/ProvidersPanel.js.map +1 -1
  357. package/dist/editor/sidebar/MorePanelsButton.js +1 -1
  358. package/dist/editor/sidebar/MorePanelsButton.js.map +1 -1
  359. package/dist/editor/sidebar/Validation.js +4 -1
  360. package/dist/editor/sidebar/Validation.js.map +1 -1
  361. package/dist/editor/sidebar/Workbox.js +1 -1
  362. package/dist/editor/sidebar/Workbox.js.map +1 -1
  363. package/dist/editor/template-wizard/TemplateStructureInlineEditor.js +1 -1
  364. package/dist/editor/template-wizard/TemplateStructureInlineEditor.js.map +1 -1
  365. package/dist/editor/ui/IconSelectorDialog.js +1 -1
  366. package/dist/editor/ui/IconSelectorDialog.js.map +1 -1
  367. package/dist/editor/ui/SimpleIconButton.d.ts +2 -2
  368. package/dist/editor/ui/SimpleIconButton.js +7 -1
  369. package/dist/editor/ui/SimpleIconButton.js.map +1 -1
  370. package/dist/editor/ui/Splitter.d.ts +1 -0
  371. package/dist/editor/ui/Splitter.js +12 -2
  372. package/dist/editor/ui/Splitter.js.map +1 -1
  373. package/dist/editor/ui/animationSettle.d.ts +32 -0
  374. package/dist/editor/ui/animationSettle.js +85 -0
  375. package/dist/editor/ui/animationSettle.js.map +1 -0
  376. package/dist/editor/utils/expandSelectionAtCaret.d.ts +15 -0
  377. package/dist/editor/utils/expandSelectionAtCaret.js +183 -0
  378. package/dist/editor/utils/expandSelectionAtCaret.js.map +1 -0
  379. package/dist/editor/utils.d.ts +1 -17
  380. package/dist/editor/utils.js +0 -143
  381. package/dist/editor/utils.js.map +1 -1
  382. package/dist/editor/version-diff/versionDiffTargets.d.ts +3 -8
  383. package/dist/editor/version-diff/versionDiffTargets.js +37 -94
  384. package/dist/editor/version-diff/versionDiffTargets.js.map +1 -1
  385. package/dist/revision.d.ts +2 -2
  386. package/dist/revision.js +2 -2
  387. package/dist/splash-screen/ModernSplashScreen.js +11 -3
  388. package/dist/splash-screen/ModernSplashScreen.js.map +1 -1
  389. package/dist/splash-screen/NewPage.js +7 -5
  390. package/dist/splash-screen/NewPage.js.map +1 -1
  391. package/dist/splash-screen/OpenPage.js +5 -3
  392. package/dist/splash-screen/OpenPage.js.map +1 -1
  393. package/dist/splash-screen/RecentPages.js +3 -3
  394. package/dist/splash-screen/RecentPages.js.map +1 -1
  395. package/dist/task-board/components/TaskDetailPanel.js +2 -1
  396. package/dist/task-board/components/TaskDetailPanel.js.map +1 -1
  397. package/dist/task-board/views/DependencyGraphView.d.ts +42 -1
  398. package/dist/task-board/views/DependencyGraphView.js +94 -0
  399. package/dist/task-board/views/DependencyGraphView.js.map +1 -1
  400. package/dist/types.d.ts +1 -0
  401. package/package.json +2 -1
  402. package/styles.css +96 -0
  403. package/dist/editor/page-editor-chrome/InlineEditor.d.ts +0 -7
  404. package/dist/editor/page-editor-chrome/InlineEditor.js +0 -1719
  405. package/dist/editor/page-editor-chrome/InlineEditor.js.map +0 -1
  406. package/dist/editor/page-editor-chrome/overlay/iframeAccess.d.ts +0 -2
  407. package/dist/editor/page-editor-chrome/overlay/iframeAccess.js +0 -21
  408. package/dist/editor/page-editor-chrome/overlay/iframeAccess.js.map +0 -1
  409. package/dist/editor/page-editor-chrome/useInlineAICompletion.d.ts +0 -7
  410. package/dist/editor/page-editor-chrome/useInlineAICompletion.js +0 -758
  411. package/dist/editor/page-editor-chrome/useInlineAICompletion.js.map +0 -1
  412. package/dist/editor/page-viewer/pageModelSkeletonBuilder.d.ts +0 -3
  413. package/dist/editor/page-viewer/pageModelSkeletonBuilder.js +0 -796
  414. package/dist/editor/page-viewer/pageModelSkeletonBuilder.js.map +0 -1
@@ -1,7 +1,7 @@
1
1
  "use client";
2
- import { jsx as _jsx, Fragment as _Fragment, jsxs as _jsxs } from "react/jsx-runtime";
3
- import { useState, useCallback, useRef, useEffect, useLayoutEffect, useMemo, } from "react";
4
- import { Sparkles, Check, X, SendHorizonal, Wand2, RotateCcw, Maximize2, History, Cpu, RotateCw, StopCircle, Bug, } from "lucide-react";
2
+ import { jsx as _jsx, jsxs as _jsxs, Fragment as _Fragment } from "react/jsx-runtime";
3
+ import { useState, useCallback, useRef, useEffect, useMemo, } from "react";
4
+ import { Check, X, ArrowUp, ChevronDown, ChevronLeft, Lightbulb, LoaderCircle, } from "lucide-react";
5
5
  import { Button } from "../../components/ui/button";
6
6
  import { Badge } from "../../components/ui/badge";
7
7
  import { Textarea } from "../../components/ui/textarea";
@@ -15,9 +15,11 @@ import { subscribeAgent as subscribeAgentRegistry } from "../services/agentSubsc
15
15
  import { getAiTextEditPrompts, getEditorSettings, } from "../services/systemService";
16
16
  import { loadAiProfiles } from "../services/aiService";
17
17
  import { localStorageService } from "../services/localStorageService";
18
+ import { diffWords } from "diff";
18
19
  // Default Profile ID for the Inline Text Editor profile
19
20
  const DEFAULT_INLINE_TEXT_EDITOR_PROFILE_ID = "8e53c90c-2eac-476b-b03d-d0c2cfbbcd8a";
20
21
  const AI_TEXT_EDIT_MODELS_STORAGE_KEY = "aiTextEdit.selectedModelIds";
22
+ const START_AGENT_TIMEOUT_MS = 15_000;
21
23
  /** Normalize profile ID to a stable key (lowercase, no braces) so storage works regardless of API casing. */
22
24
  function normalizeProfileIdForStorage(profileId) {
23
25
  return profileId.replace(/^\{|\}$/g, "").toLowerCase();
@@ -38,7 +40,7 @@ function getStoredModelIds(profileId) {
38
40
  }
39
41
  }
40
42
  }
41
- return Array.isArray(ids) && ids.length > 0 ? ids : null;
43
+ return Array.isArray(ids) ? ids : null;
42
44
  }
43
45
  catch {
44
46
  return null;
@@ -65,10 +67,29 @@ function setStoredModelIds(profileId, modelIds) {
65
67
  // ignore
66
68
  }
67
69
  }
68
- const AI_TEXT_EDIT_RESPONSE_FORMAT_INSTRUCTION = `Return ONLY valid JSON (no markdown, no code fences, no extra text).
70
+ function isActiveModelRunStatus(status) {
71
+ return (status === "pending" || status === "thinking" || status === "streaming");
72
+ }
73
+ const AI_TEXT_EDIT_SINGLE_RESPONSE_FORMAT_INSTRUCTION = `Return ONLY valid JSON (no markdown, no code fences, no extra text).
69
74
  Use exactly one of these shapes:
70
75
  {"replacementText":"<the modified text>"}
71
76
  {"error":"<short explanation of why you cannot complete this request>"}`;
77
+ function normalizeAiTextEditResultCount(resultCount) {
78
+ return typeof resultCount === "number" && Number.isFinite(resultCount)
79
+ ? Math.max(1, Math.min(20, Math.floor(resultCount)))
80
+ : 1;
81
+ }
82
+ function getAiTextEditResponseFormatInstruction(resultCount) {
83
+ const normalizedResultCount = normalizeAiTextEditResultCount(resultCount);
84
+ if (normalizedResultCount <= 1) {
85
+ return AI_TEXT_EDIT_SINGLE_RESPONSE_FORMAT_INSTRUCTION;
86
+ }
87
+ return `Return ONLY valid JSON (no markdown, no code fences, no extra text).
88
+ Use exactly one of these shapes:
89
+ {"replacementTexts":["<result 1>","<result 2>"]}
90
+ {"error":"<short explanation of why you cannot complete this request>"}
91
+ Return exactly ${normalizedResultCount} results in replacementTexts. Each array item must be a complete standalone replacement/insert text. Do not include numbering or bullets inside the values.`;
92
+ }
72
93
  function extractJsonObjectCandidates(input) {
73
94
  const candidates = [];
74
95
  for (let start = input.indexOf("{"); start >= 0; start = input.indexOf("{", start + 1)) {
@@ -170,6 +191,12 @@ function coerceAiTextEditResponse(parsed) {
170
191
  if (typeof parsedObj.replacementText === "string") {
171
192
  return { replacementText: parsedObj.replacementText };
172
193
  }
194
+ if (Array.isArray(parsedObj.replacementTexts)) {
195
+ const replacementTexts = parsedObj.replacementTexts.filter((value) => typeof value === "string");
196
+ if (replacementTexts.length > 0) {
197
+ return { replacementTexts };
198
+ }
199
+ }
173
200
  return null;
174
201
  }
175
202
  function tryParseAiTextEditJson(json) {
@@ -201,7 +228,9 @@ export function parseAiTextEditResponse(raw) {
201
228
  if (!parsed || typeof parsed !== "object") {
202
229
  return { error: "AI returned an invalid response format." };
203
230
  }
204
- return { error: "AI response is missing `replacementText` or `error`." };
231
+ return {
232
+ error: "AI response is missing `replacementText`, `replacementTexts`, or `error`.",
233
+ };
205
234
  }
206
235
  catch {
207
236
  // Fall through to candidate extraction for mixed prose/JSON responses.
@@ -244,11 +273,69 @@ function extractAgentErrorMessage(message) {
244
273
  }
245
274
  return null;
246
275
  }
276
+ function withTimeout(promise, timeoutMs, timeoutMessage) {
277
+ return new Promise((resolve, reject) => {
278
+ const timeoutId = window.setTimeout(() => {
279
+ reject(new Error(timeoutMessage));
280
+ }, timeoutMs);
281
+ promise.then((value) => {
282
+ window.clearTimeout(timeoutId);
283
+ resolve(value);
284
+ }, (error) => {
285
+ window.clearTimeout(timeoutId);
286
+ reject(error);
287
+ });
288
+ });
289
+ }
290
+ /**
291
+ * Shared instruction box: a rounded composer with the send button inside the
292
+ * textarea shell and the model selector below it.
293
+ */
294
+ function InstructionComposer({ inputRef, value, onChange, onSubmit, onKeyDown, placeholder, minHeightClass, submitTitle, canSubmit, models, hasMultipleModels, modelPopoverOpen, onModelPopoverOpenChange, selectedModelIds, selectedModelsCount, selectedModelSummary, onToggleModel, onFocusChange, }) {
295
+ const formRef = useRef(null);
296
+ const [focused, setFocused] = useState(false);
297
+ // Single line at rest; grows to its full height while focused or holding text.
298
+ const isExpanded = focused || value.trim().length > 0;
299
+ // Report focus up so the popover width follows the custom prompt field.
300
+ useEffect(() => {
301
+ onFocusChange?.(focused);
302
+ }, [focused, onFocusChange]);
303
+ useEffect(() => {
304
+ return () => onFocusChange?.(false);
305
+ }, [onFocusChange]);
306
+ // Collapse again once focus leaves the composer entirely. Interactions with the
307
+ // footer controls or the (portaled) model popover keep it expanded.
308
+ const handleBlur = () => {
309
+ window.setTimeout(() => {
310
+ const active = document.activeElement;
311
+ if (formRef.current?.contains(active ?? null) ||
312
+ (active instanceof Element &&
313
+ active.closest("[data-radix-popper-content-wrapper]"))) {
314
+ return;
315
+ }
316
+ setFocused(false);
317
+ }, 0);
318
+ };
319
+ return (_jsx("form", { ref: formRef, onSubmit: (event) => {
320
+ event.preventDefault();
321
+ onSubmit();
322
+ }, className: "w-full", children: _jsx("div", { className: "flex w-full items-start gap-2", children: _jsxs("div", { className: "flex min-w-0 flex-1 flex-col gap-2", children: [_jsxs("div", { className: "border-border-default focus-within:border-neutral-grey-100 focus-within:ring-neutral-grey-100/10 bg-neutral-grey-5/30 relative min-w-0 overflow-hidden rounded-[12px] border transition-colors duration-200 focus-within:ring-4", children: [_jsx(Textarea, { ref: inputRef, value: value, onChange: (event) => onChange(event.target.value), onKeyDown: onKeyDown, onFocus: () => setFocused(true), onBlur: handleBlur, placeholder: placeholder, rows: 1, className: cn("w-full resize-none rounded-none border-0 bg-transparent px-2 pr-11 text-xs shadow-none transition-colors duration-200 outline-none focus-visible:border-0 focus-visible:shadow-none", isExpanded
323
+ ? `${minHeightClass} pt-3 pb-10 leading-normal`
324
+ : "h-8 min-h-0 py-0 leading-8") }), _jsx("button", { type: "submit", disabled: !canSubmit, className: cn("absolute right-1.5 flex h-6 w-6 items-center justify-center rounded-[4px] p-0 transition-colors duration-200", isExpanded ? "bottom-1.5" : "top-1", canSubmit
325
+ ? "bg-neutral-grey-100 hover:bg-neutral-grey-100/90 text-white"
326
+ : "bg-neutral-grey-5 text-neutral-grey-50 cursor-not-allowed"), title: submitTitle, children: _jsx(ArrowUp, { className: "h-4 w-4" }) })] }), hasMultipleModels && (_jsx("div", { className: "flex items-center overflow-hidden", children: _jsxs(Popover, { open: modelPopoverOpen, onOpenChange: onModelPopoverOpenChange, children: [_jsx(PopoverTrigger, { asChild: true, children: _jsxs("button", { type: "button", className: cn("inline-flex items-center gap-1 rounded-[4px] px-2 py-1.5 text-[11px] font-medium transition-colors duration-200", "text-neutral-grey-50 hover:text-neutral-grey-100 hover:bg-neutral-grey-5", modelPopoverOpen &&
327
+ "text-neutral-grey-100 bg-neutral-grey-5"), title: selectedModelSummary
328
+ ? `Models: ${selectedModelSummary}`
329
+ : "Choose models", children: [_jsx("span", { className: "max-w-[150px] truncate", children: selectedModelSummary ?? "Choose models" }), _jsx(ChevronDown, { className: "h-3 w-3" })] }) }), _jsxs(PopoverContent, { className: "w-56 p-1.5", align: "start", sideOffset: 8, children: [_jsxs("div", { className: "badge-pad flex items-center justify-between", children: [_jsx("span", { className: "text-neutral-grey-50 text-[10px] font-semibold tracking-wider", children: "Models" }), _jsxs("span", { className: "text-neutral-grey-100 text-[10px] font-medium", children: [selectedModelsCount, " selected"] })] }), _jsx("div", { className: "space-y-0.5", children: models.map((model) => (_jsxs("button", { type: "button", onClick: () => onToggleModel(model.id), className: cn("flex w-full items-center gap-2 rounded-[4px] px-2 py-1.5 text-left text-xs transition-colors", selectedModelIds.includes(model.id)
330
+ ? "bg-neutral-grey-5 text-neutral-grey-100"
331
+ : "text-neutral-grey-50 hover:bg-neutral-grey-5"), children: [_jsx("span", { className: cn("flex h-3.5 w-3.5 items-center justify-center rounded border", selectedModelIds.includes(model.id)
332
+ ? "border-neutral-grey-100 bg-neutral-grey-100 text-white"
333
+ : "border-border-default bg-white text-transparent"), children: _jsx(Check, { className: "h-3 w-3" }) }), model.name] }, model.id))) })] })] }) }))] }) }) }));
334
+ }
247
335
  export function InlineAiDialog({ selectedText = "", contextBefore, contextAfter, onAccept, onClose, position, className, }) {
248
336
  const editContext = useEditContext();
249
337
  const [state, setState] = useState("input");
250
338
  const [instruction, setInstruction] = useState("");
251
- const [result, setResult] = useState("");
252
339
  const [error, setError] = useState(null);
253
340
  const [conversationHistory, setConversationHistory] = useState([]);
254
341
  const [quickActions, setQuickActions] = useState([]);
@@ -258,8 +345,6 @@ export function InlineAiDialog({ selectedText = "", contextBefore, contextAfter,
258
345
  const [modelRuns, setModelRuns] = useState({});
259
346
  const inputRef = useRef(null);
260
347
  const dialogRef = useRef(null);
261
- const [isLarge, setIsLarge] = useState(false);
262
- const [clampedPosition, setClampedPosition] = useState(position);
263
348
  // Agent state for the current multi-model run
264
349
  const activeAgentIdsRef = useRef(new Set());
265
350
  const unsubscribeRef = useRef(null);
@@ -268,6 +353,8 @@ export function InlineAiDialog({ selectedText = "", contextBefore, contextAfter,
268
353
  const lastParsedRawRef = useRef({});
269
354
  // Model popover state
270
355
  const [modelPopoverOpen, setModelPopoverOpen] = useState(false);
356
+ // Whether the custom-prompt composer is focused, so the popover can grow with it.
357
+ const [promptFocused, setPromptFocused] = useState(false);
271
358
  // ALT+letter quick select state
272
359
  const [altSearchBuffer, setAltSearchBuffer] = useState("");
273
360
  const [isAltPressed, setIsAltPressed] = useState(false);
@@ -283,7 +370,7 @@ export function InlineAiDialog({ selectedText = "", contextBefore, contextAfter,
283
370
  const selected = selectedModelIds
284
371
  .map((id) => byId.get(id))
285
372
  .filter(Boolean);
286
- return selected.length ? selected : availableModels.slice(0, 1);
373
+ return selected;
287
374
  }, [selectedModelIds, availableModels]);
288
375
  const selectedModelSummary = useMemo(() => {
289
376
  if (!selectedModels.length)
@@ -292,16 +379,6 @@ export function InlineAiDialog({ selectedText = "", contextBefore, contextAfter,
292
379
  return selectedModels[0]?.name || null;
293
380
  return `${selectedModels.length} models selected`;
294
381
  }, [selectedModels]);
295
- const successfulRuns = useMemo(() => Object.values(modelRuns).filter((run) => run.status === "done" &&
296
- typeof run.replacementText === "string" &&
297
- run.replacementText.length > 0), [modelRuns]);
298
- const hasMultipleResults = successfulRuns.length > 1;
299
- // Automatically switch to larger mode when showing more than one response
300
- useEffect(() => {
301
- if (state === "preview" && hasMultipleResults) {
302
- setIsLarge(true);
303
- }
304
- }, [state, hasMultipleResults]);
305
382
  useEffect(() => {
306
383
  const loadSettings = async () => {
307
384
  try {
@@ -340,7 +417,10 @@ export function InlineAiDialog({ selectedText = "", contextBefore, contextAfter,
340
417
  const defaultModelId = profile.defaultModelId || profile.models?.[0]?.id;
341
418
  const stored = getStoredModelIds(profileId);
342
419
  const validStored = stored?.filter((id) => availableModelIds.has(id));
343
- if (validStored?.length) {
420
+ if (stored && stored.length === 0) {
421
+ setSelectedModelIds([]);
422
+ }
423
+ else if (validStored?.length) {
344
424
  setSelectedModelIds(validStored);
345
425
  }
346
426
  else if (defaultModelId) {
@@ -359,16 +439,12 @@ export function InlineAiDialog({ selectedText = "", contextBefore, contextAfter,
359
439
  }, [modelRuns]);
360
440
  // Persist model selection to localStorage when it or profileId changes
361
441
  useEffect(() => {
362
- if (profileId && selectedModelIds.length > 0) {
442
+ if (profileId && activeProfile) {
363
443
  setStoredModelIds(profileId, selectedModelIds);
364
444
  }
365
- }, [profileId, selectedModelIds]);
366
- // Focus input on mount
367
- useEffect(() => {
368
- if (inputRef.current) {
369
- inputRef.current.focus();
370
- }
371
- }, []);
445
+ }, [profileId, activeProfile, selectedModelIds]);
446
+ // The custom-prompt composer starts collapsed (single line) and expands on
447
+ // focus, so the input is intentionally not auto-focused on mount.
372
448
  const evaluateRunCompletion = useCallback((runs) => {
373
449
  const values = Object.values(runs);
374
450
  if (!values.length)
@@ -376,19 +452,13 @@ export function InlineAiDialog({ selectedText = "", contextBefore, contextAfter,
376
452
  const allTerminal = values.every((run) => run.status === "done" || run.status === "error");
377
453
  if (!allTerminal)
378
454
  return;
379
- const doneRuns = values.filter((run) => run.status === "done" && run.replacementText?.length);
455
+ const doneRuns = values.filter((run) => run.status === "done" &&
456
+ (run.replacementTexts?.length || run.replacementText?.length));
380
457
  if (doneRuns.length === 0) {
381
458
  setError("All selected models failed. See each model’s card for details. You can retry or change your instruction.");
382
- setResult("");
383
459
  // Stay in preview so the user sees per-model error cards and can Retry/Discard
384
460
  return;
385
461
  }
386
- if (doneRuns.length === 1) {
387
- setResult(doneRuns[0]?.replacementText ?? "");
388
- }
389
- else {
390
- setResult("");
391
- }
392
462
  setError(null);
393
463
  // State is already "preview" – we show results side-by-side as they stream in
394
464
  }, []);
@@ -412,13 +482,6 @@ export function InlineAiDialog({ selectedText = "", contextBefore, contextAfter,
412
482
  return;
413
483
  subscriptionReleasesRef.current.set(agentId, subscribeAgentRegistry(agentId));
414
484
  }, []);
415
- const releaseAgentSubscription = useCallback((agentId) => {
416
- const release = subscriptionReleasesRef.current.get(agentId);
417
- if (release) {
418
- release();
419
- subscriptionReleasesRef.current.delete(agentId);
420
- }
421
- }, []);
422
485
  const unsubscribeAllAgents = useCallback(() => {
423
486
  for (const release of subscriptionReleasesRef.current.values()) {
424
487
  release();
@@ -433,22 +496,6 @@ export function InlineAiDialog({ selectedText = "", contextBefore, contextAfter,
433
496
  latestRawContentRef.current = {};
434
497
  lastParsedRawRef.current = {};
435
498
  }, []);
436
- const handleStopModelRun = useCallback((agentId) => {
437
- activeAgentIdsRef.current.delete(agentId);
438
- delete latestRawContentRef.current[agentId];
439
- delete lastParsedRawRef.current[agentId];
440
- releaseAgentSubscription(agentId);
441
- closeAgent(agentId).catch(() => { });
442
- updateModelRun(agentId, (current) => ({
443
- ...current,
444
- status: "error",
445
- error: "Stopped by user",
446
- }));
447
- }, [updateModelRun, releaseAgentSubscription]);
448
- const handleOpenAgentInSidePanel = useCallback((agentId) => {
449
- editContext?.openSidebar?.("agents-panel");
450
- window.dispatchEvent(new CustomEvent("editor:openAgent", { detail: { agentId } }));
451
- }, [editContext]);
452
499
  // Cleanup on unmount
453
500
  useEffect(() => {
454
501
  return () => {
@@ -515,6 +562,18 @@ export function InlineAiDialog({ selectedText = "", contextBefore, contextAfter,
515
562
  return { ...current, status: "error", error: errorMsg };
516
563
  });
517
564
  }
565
+ else if (normalizedStatus === "running" ||
566
+ normalizedStatus === "thinking" ||
567
+ normalizedStatus === "streamopen" ||
568
+ normalizedStatus === "executingtoolcalls" ||
569
+ normalizedStatus === "toolapprovalgranted" ||
570
+ normalizedStatus === "toolapprovalrejected") {
571
+ updateModelRun(messageAgentId, (current) => {
572
+ if (current.status !== "pending")
573
+ return current;
574
+ return { ...current, status: "thinking" };
575
+ });
576
+ }
518
577
  }
519
578
  else if (msgType === "agent:run:error" || msgType === "agent:error") {
520
579
  const errorMsg = extractAgentErrorMessage(message) ||
@@ -553,10 +612,13 @@ export function InlineAiDialog({ selectedText = "", contextBefore, contextAfter,
553
612
  }));
554
613
  }
555
614
  else {
615
+ const replacementTexts = parsed.replacementTexts ??
616
+ (parsed.replacementText != null ? [parsed.replacementText] : []);
556
617
  updateModelRun(messageAgentId, (run) => ({
557
618
  ...run,
558
619
  status: "done",
559
- replacementText: parsed.replacementText ?? "",
620
+ replacementText: replacementTexts[0] ?? "",
621
+ replacementTexts,
560
622
  error: undefined,
561
623
  }));
562
624
  }
@@ -565,7 +627,7 @@ export function InlineAiDialog({ selectedText = "", contextBefore, contextAfter,
565
627
  unsubscribeRef.current =
566
628
  editContext.addSocketMessageListener(handleMessage);
567
629
  }, [editContext, updateModelRun]);
568
- const executeAiModification = useCallback(async (customInstruction) => {
630
+ const executeAiModification = useCallback(async (customInstruction, resultCount = 1) => {
569
631
  if (!editContext)
570
632
  return;
571
633
  if (!selectedModels.length) {
@@ -573,7 +635,6 @@ export function InlineAiDialog({ selectedText = "", contextBefore, contextAfter,
573
635
  return;
574
636
  }
575
637
  setError(null);
576
- setResult("");
577
638
  setModelRuns({});
578
639
  modelRunsRef.current = {};
579
640
  latestRawContentRef.current = {};
@@ -590,6 +651,8 @@ After: "${contextAfter || ""}"
590
651
 
591
652
  `
592
653
  : "";
654
+ const responseFormatInstruction = getAiTextEditResponseFormatInstruction(resultCount);
655
+ const requestedResultCount = normalizeAiTextEditResultCount(resultCount);
593
656
  let message;
594
657
  if (selectedText) {
595
658
  message = `${contextInfo}I need you to modify ONLY the following selected portion of the text:
@@ -602,7 +665,7 @@ ${selectedText}
602
665
  ${customInstruction}
603
666
 
604
667
  Return ONLY the modified version of the selected text, not the entire field.
605
- ${AI_TEXT_EDIT_RESPONSE_FORMAT_INSTRUCTION}`;
668
+ ${responseFormatInstruction}`;
606
669
  }
607
670
  else {
608
671
  message = `${contextInfo}I need you to generate text at the cursor position.
@@ -610,7 +673,7 @@ ${AI_TEXT_EDIT_RESPONSE_FORMAT_INSTRUCTION}`;
610
673
  ${customInstruction}
611
674
 
612
675
  Return ONLY the text to insert at the cursor position, not the entire field.
613
- ${AI_TEXT_EDIT_RESPONSE_FORMAT_INSTRUCTION}`;
676
+ ${responseFormatInstruction}`;
614
677
  }
615
678
  setConversationHistory((prev) => [...prev, customInstruction]);
616
679
  let agentContext = undefined;
@@ -657,6 +720,7 @@ ${AI_TEXT_EDIT_RESPONSE_FORMAT_INSTRUCTION}`;
657
720
  agentId,
658
721
  modelId: model.id,
659
722
  modelName: model.name,
723
+ requestedResultCount,
660
724
  status: "pending",
661
725
  rawContent: "",
662
726
  };
@@ -667,7 +731,7 @@ ${AI_TEXT_EDIT_RESPONSE_FORMAT_INSTRUCTION}`;
667
731
  await Promise.all(Object.values(initialRuns).map(async (run) => {
668
732
  subscribeAgentInline(run.agentId);
669
733
  try {
670
- await startAgent({
734
+ await withTimeout(startAgent({
671
735
  agentId: run.agentId,
672
736
  message,
673
737
  sessionId: editContext.sessionId,
@@ -675,6 +739,11 @@ ${AI_TEXT_EDIT_RESPONSE_FORMAT_INSTRUCTION}`;
675
739
  mode: "autonomous",
676
740
  model: run.modelId,
677
741
  context: agentContext,
742
+ }), START_AGENT_TIMEOUT_MS, `Timed out starting ${run.modelName}. Please try again.`);
743
+ updateModelRun(run.agentId, (current) => {
744
+ if (current.status !== "pending")
745
+ return current;
746
+ return { ...current, status: "thinking" };
678
747
  });
679
748
  }
680
749
  catch (runErr) {
@@ -709,7 +778,7 @@ ${AI_TEXT_EDIT_RESPONSE_FORMAT_INSTRUCTION}`;
709
778
  updateModelRun,
710
779
  ]);
711
780
  const handleQuickAction = useCallback((action) => {
712
- executeAiModification(action.instruction);
781
+ executeAiModification(action.instruction, action.resultCount);
713
782
  }, [executeAiModification]);
714
783
  // ALT+letter quick select for quick actions
715
784
  useEffect(() => {
@@ -788,72 +857,131 @@ ${AI_TEXT_EDIT_RESPONSE_FORMAT_INSTRUCTION}`;
788
857
  return;
789
858
  onAccept(replacementText);
790
859
  }, [onAccept]);
860
+ const handleModelBadgeClick = useCallback((event, agentId) => {
861
+ if (!event.ctrlKey)
862
+ return;
863
+ event.preventDefault();
864
+ event.stopPropagation();
865
+ if (editContext?.isMobile) {
866
+ editContext.openSidebar("agents-panel");
867
+ }
868
+ else {
869
+ editContext?.setShowAgentsPanel(true);
870
+ }
871
+ const dispatchOpenAgent = () => {
872
+ window.dispatchEvent(new CustomEvent("editor:openAgent", {
873
+ detail: { agentId },
874
+ }));
875
+ };
876
+ if (editContext?.isMobile) {
877
+ window.setTimeout(dispatchOpenAgent, 500);
878
+ }
879
+ else {
880
+ dispatchOpenAgent();
881
+ }
882
+ }, [editContext]);
791
883
  const toggleModelSelection = useCallback((modelId) => {
792
884
  setSelectedModelIds((prev) => {
793
885
  if (prev.includes(modelId)) {
794
- if (prev.length === 1) {
795
- return prev;
796
- }
797
886
  return prev.filter((id) => id !== modelId);
798
887
  }
799
888
  return [...prev, modelId];
800
889
  });
801
890
  }, []);
802
891
  const handleTryAgain = useCallback(() => {
803
- // Go back to input state to refine
804
- setState("input");
805
- setResult("");
806
- }, []);
807
- const handleRetry = useCallback(() => {
808
- const lastInstruction = conversationHistory[conversationHistory.length - 1];
809
- if (lastInstruction) {
810
- executeAiModification(lastInstruction);
811
- }
812
- }, [conversationHistory, executeAiModification]);
813
- const handleStartOver = useCallback(() => {
814
892
  unsubscribeAllAgents();
815
893
  closeAllActiveAgents();
894
+ setState("input");
895
+ setInstruction("");
896
+ setError(null);
897
+ setConversationHistory([]);
816
898
  setModelRuns({});
817
899
  modelRunsRef.current = {};
818
900
  latestRawContentRef.current = {};
819
901
  lastParsedRawRef.current = {};
820
- setState("input");
821
- setResult("");
822
- setConversationHistory([]);
823
- setError(null);
824
902
  }, [unsubscribeAllAgents, closeAllActiveAgents]);
825
903
  const handleClose = useCallback(() => {
826
904
  unsubscribeAllAgents();
827
905
  closeAllActiveAgents();
828
906
  onClose();
829
907
  }, [unsubscribeAllAgents, closeAllActiveAgents, onClose]);
830
- const toggleLarge = useCallback(() => {
831
- setIsLarge((prev) => !prev);
832
- }, []);
908
+ useEffect(() => {
909
+ const handleEscapeKey = (event) => {
910
+ if (event.key !== "Escape")
911
+ return;
912
+ event.preventDefault();
913
+ event.stopPropagation();
914
+ handleClose();
915
+ };
916
+ document.addEventListener("keydown", handleEscapeKey, true);
917
+ return () => {
918
+ document.removeEventListener("keydown", handleEscapeKey, true);
919
+ };
920
+ }, [handleClose]);
833
921
  const renderTextWithContext = (centerText, isResult = false) => {
834
922
  const hasContext = contextBefore || contextAfter;
835
923
  // No context available - just show the selected text
836
924
  if (!hasContext) {
837
925
  return (_jsx("span", { className: cn("rounded px-0.5 font-medium", isResult
838
926
  ? "bg-feedback-green-light text-feedback-green"
839
- : "bg-highlight-10 text-highlight-100 italic"), children: centerText }));
927
+ : "bg-neutral-grey-5 text-neutral-grey-100 italic"), children: centerText }));
840
928
  }
841
929
  // Show context with ellipsis indicators
842
930
  return (_jsxs("div", { className: "text-xs leading-relaxed whitespace-pre-wrap", children: [contextBefore && (_jsxs(_Fragment, { children: [_jsx("span", { className: "text-neutral-grey-50", children: "..." }), _jsx("span", { className: "text-neutral-grey-50", children: contextBefore })] })), _jsx("span", { className: cn("mx-0.5 rounded px-0.5 font-medium", isResult
843
931
  ? "bg-feedback-green-light text-feedback-green"
844
- : "bg-highlight-10 text-highlight-100 italic"), children: centerText }), contextAfter && (_jsxs(_Fragment, { children: [_jsx("span", { className: "text-neutral-grey-50", children: contextAfter }), _jsx("span", { className: "text-neutral-grey-50", children: "..." })] }))] }));
932
+ : "bg-neutral-grey-5 text-neutral-grey-100 italic"), children: centerText }), contextAfter && (_jsxs(_Fragment, { children: [_jsx("span", { className: "text-neutral-grey-50", children: contextAfter }), _jsx("span", { className: "text-neutral-grey-50", children: "..." })] }))] }));
933
+ };
934
+ const renderSuggestionPreview = (replacementText) => {
935
+ const hasContext = contextBefore || contextAfter;
936
+ const hasOriginalSelection = selectedText.trim().length > 0;
937
+ const diff = hasOriginalSelection
938
+ ? diffWords(selectedText, replacementText)
939
+ : [];
940
+ const suggestedTextClass = "bg-feedback-green-light text-feedback-green rounded px-0.5";
941
+ return (_jsxs("div", { className: "font-mono text-sm whitespace-pre-wrap", children: [hasContext && contextBefore && (_jsxs("span", { className: "text-neutral-grey-50", children: [_jsx("span", { children: "..." }), _jsx("span", { children: contextBefore })] })), hasOriginalSelection ? (diff.map((part, index) => {
942
+ if (part.added) {
943
+ return (_jsx("span", { className: suggestedTextClass, children: part.value }, index));
944
+ }
945
+ if (part.removed) {
946
+ return null;
947
+ }
948
+ return (_jsx("span", { className: suggestedTextClass, children: part.value }, index));
949
+ })) : (_jsx("span", { className: suggestedTextClass, children: replacementText })), hasContext && contextAfter && (_jsxs("span", { className: "text-neutral-grey-50", children: [_jsx("span", { children: contextAfter }), _jsx("span", { children: "..." })] }))] }));
845
950
  };
951
+ const modelRunValues = useMemo(() => Object.values(modelRuns), [modelRuns]);
952
+ const useCompactResultList = useMemo(() => modelRunValues.some((run) => run.requestedResultCount > 1 ||
953
+ (run.replacementTexts?.length ?? 0) > 1), [modelRunValues]);
954
+ const compactSuggestions = useMemo(() => {
955
+ const seenSuggestions = new Set();
956
+ return modelRunValues.flatMap((run) => {
957
+ const replacementTexts = run.replacementTexts ??
958
+ (run.replacementText != null ? [run.replacementText] : []);
959
+ return replacementTexts
960
+ .filter((replacementText) => {
961
+ const dedupeKey = replacementText
962
+ .trim()
963
+ .replace(/\s+/g, " ")
964
+ .toLocaleLowerCase();
965
+ if (!dedupeKey || seenSuggestions.has(dedupeKey)) {
966
+ return false;
967
+ }
968
+ seenSuggestions.add(dedupeKey);
969
+ return true;
970
+ })
971
+ .map((replacementText, index) => ({
972
+ id: `${run.agentId}-${index}`,
973
+ agentId: run.agentId,
974
+ modelName: run.modelName,
975
+ text: replacementText,
976
+ }));
977
+ });
978
+ }, [modelRunValues]);
846
979
  const handleKeyDown = useCallback((e) => {
847
980
  if (e.key === "Escape") {
848
981
  e.preventDefault();
849
- if (state === "preview") {
850
- handleTryAgain();
851
- }
852
- else {
853
- handleClose();
854
- }
982
+ handleClose();
855
983
  }
856
- }, [state, handleTryAgain, handleClose]);
984
+ }, [handleClose]);
857
985
  const handleTextareaKeyDown = useCallback((e) => {
858
986
  if (e.key === "Enter" && !e.shiftKey) {
859
987
  e.preventDefault();
@@ -863,67 +991,16 @@ ${AI_TEXT_EDIT_RESPONSE_FORMAT_INSTRUCTION}`;
863
991
  }
864
992
  }
865
993
  }, [instruction, executeAiModification]);
866
- // Clamp the dialog position so it never renders outside the viewport.
867
- // This matters because `position` is based on selection coordinates which can be near the viewport edge.
868
- useLayoutEffect(() => {
869
- if (!position) {
870
- if (clampedPosition !== undefined)
871
- setClampedPosition(undefined);
872
- return;
873
- }
874
- const margin = 12;
875
- const vw = window.innerWidth || 0;
876
- const vh = window.innerHeight || 0;
877
- // Use ResizeObserver to track the actual size of the dialog as it changes
878
- const updatePosition = () => {
879
- const el = dialogRef.current;
880
- if (!el)
881
- return;
882
- const width = el.offsetWidth || 0;
883
- const height = el.offsetHeight || 0;
884
- if (!width || !height || !vw || !vh) {
885
- const next = { x: position.x, y: position.y };
886
- if (clampedPosition?.x !== next.x || clampedPosition?.y !== next.y)
887
- setClampedPosition(next);
888
- return;
889
- }
890
- const x = Math.min(Math.max(margin, position.x), Math.max(margin, vw - width - margin));
891
- const y = Math.min(Math.max(margin, position.y), Math.max(margin, vh - height - margin));
892
- if (clampedPosition?.x !== x || clampedPosition?.y !== y) {
893
- setClampedPosition({ x, y });
894
- }
895
- };
896
- const resizeObserver = new ResizeObserver(() => {
897
- updatePosition();
898
- });
899
- if (dialogRef.current) {
900
- resizeObserver.observe(dialogRef.current);
901
- }
902
- // Initial update
903
- updatePosition();
904
- return () => {
905
- resizeObserver.disconnect();
906
- };
907
- // Re-clamp when the content changes (height changes) or when the requested position changes.
908
- }, [
909
- position?.x,
910
- position?.y,
911
- state,
912
- result,
913
- selectedText,
914
- isLarge,
915
- modelRuns,
916
- hasMultipleResults,
917
- ]);
918
- return (_jsxs("div", { ref: dialogRef, className: cn("border-border-default agent-inline-dialog flex max-h-[80vh] flex-col overflow-hidden rounded-xl border bg-white/95 shadow-[0_10px_40px_color-mix(in_srgb,var(--color-neutral-grey-100)_10%,transparent)] backdrop-blur-sm 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
994
+ return (_jsxs("div", { ref: dialogRef, className: cn("border-border-default agent-inline-dialog flex max-h-[80vh] flex-col overflow-hidden rounded-2xl border bg-white/95 shadow-lg backdrop-blur-sm transition-all duration-300 ease-in-out [&_button]:rounded-[4px]",
995
+ // Popover grows while the custom prompt field is focused or results are shown.
996
+ promptFocused || state === "preview" ? "w-[390px]" : "w-[190px]", "animate-in fade-in-0 zoom-in-95 duration-200 ease-out", className), style: position
919
997
  ? {
920
998
  position: "fixed",
921
- left: clampedPosition.x,
922
- top: clampedPosition.y,
923
- zIndex: 95,
999
+ left: position.x,
1000
+ top: position.y,
1001
+ zIndex: 1100,
924
1002
  }
925
- : undefined, onKeyDown: handleKeyDown, children: [_jsxs("div", { className: "from-highlight-100/5 to-highlight-100/5 border-border-default flex flex-shrink-0 items-center gap-2.5 border-b bg-gradient-to-r px-4 py-3", children: [_jsx("div", { className: "bg-highlight-100 shadow-highlight-100 flex h-6 w-6 items-center justify-center rounded-lg shadow-sm", children: _jsx(Sparkles, { className: "h-3.5 w-3.5 text-white" }) }), _jsxs("div", { className: "flex flex-col", children: [_jsx("span", { className: "text-neutral-grey-100 text-sm leading-tight font-semibold", children: "AI Text Edit" }), conversationHistory.length > 0 && (_jsxs("span", { className: "text-neutral-grey-50 text-[10px] 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("hover:bg-neutral-grey-5 group rounded-lg p-1.5 transition-all duration-200", isLarge &&
926
- "bg-highlight-10 text-highlight-100 hover:bg-highlight-10"), title: isLarge ? "Make smaller" : "Make larger", children: _jsx(Maximize2, { className: cn("text-neutral-grey-50 group-hover:text-neutral-grey-50 h-4 w-4", isLarge && "text-highlight-100") }) }), _jsx(CloseButton, { onClick: handleClose, label: "Close" })] })] }), selectedText && (_jsxs("div", { className: "bg-neutral-grey-5/50 border-border-default flex-shrink-0 border-b px-4 py-3", children: [_jsxs("div", { className: "text-neutral-grey-50 mb-2 flex items-center gap-1.5 text-[10px] font-bold tracking-wider", children: [_jsx("div", { className: "bg-neutral-grey-10 h-1.5 w-1.5 rounded-full" }), "Selected Content"] }), _jsxs("div", { className: "relative max-h-48 overflow-y-auto whitespace-pre-wrap transition-all duration-300", children: [_jsx("div", { className: "bg-highlight-10 absolute top-0 bottom-0 left-0 w-0.5 rounded-full" }), _jsx("div", { className: "pl-3", children: renderTextWithContext(selectedText) })] })] })), _jsxs("div", { className: "min-h-0 flex-1 overflow-y-auto p-4", children: [state === "input" && (_jsxs("div", { className: "space-y-4", children: [_jsxs("div", { className: "space-y-2", children: [isAltPressed && (_jsxs("div", { className: "text-highlight-100 bg-highlight-10 animate-in fade-in flex items-center gap-2 rounded-lg px-2 py-1.5 text-xs duration-150", children: [_jsx("kbd", { className: "badge-pad-sm bg-highlight-10 rounded font-mono text-[10px] 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) => {
1003
+ : undefined, onKeyDown: handleKeyDown, children: [state === "preview" && (_jsxs("div", { className: "border-border-default flex flex-shrink-0 items-center gap-2.5 border-b px-3 py-3", children: [_jsx("button", { onClick: handleTryAgain, className: "hover:bg-neutral-grey-5 -ml-1.5 rounded-[4px] p-1.5 transition-colors", title: "Back", "aria-label": "Back", children: _jsx(ChevronLeft, { className: "text-neutral-grey-50 h-4 w-4" }) }), _jsx("span", { className: "text-neutral-grey-100 text-sm leading-tight font-semibold", children: "Choose a result" }), _jsx("div", { className: "ml-auto flex items-center gap-1", children: _jsx(CloseButton, { onClick: handleClose, label: "Close" }) })] })), _jsxs("div", { className: "min-h-0 flex-1 overflow-y-auto p-3", children: [state === "input" && (_jsxs("div", { className: "space-y-4", children: [_jsxs("div", { className: "space-y-2", children: [isAltPressed && (_jsxs("div", { className: "text-neutral-grey-100 bg-neutral-grey-5 animate-in fade-in flex items-center gap-2 rounded-xl px-2 py-1.5 text-xs duration-150", children: [_jsx("kbd", { className: "badge-pad-sm bg-neutral-grey-5 rounded font-mono text-[10px] 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-col", children: quickActions.map((action) => {
927
1004
  const hasSvgIcon = action.icon?.trim() &&
928
1005
  (action.icon.trim().startsWith("<svg") ||
929
1006
  action.icon.trim().startsWith("<?xml"));
@@ -935,69 +1012,44 @@ ${AI_TEXT_EDIT_RESPONSE_FORMAT_INSTRUCTION}`;
935
1012
  altSearchBuffer &&
936
1013
  labelLower.includes(altSearchBuffer) &&
937
1014
  !isMatch;
938
- return (_jsxs("button", { onClick: () => handleQuickAction(action), className: cn("flex items-center gap-1.5 rounded-lg px-2 py-1.5 text-xs font-medium transition-all duration-200", "border-border-default text-neutral-grey-50 border bg-white", "hover:border-highlight-100 hover:text-highlight-100 hover:bg-highlight-10", "shadow-sm hover:shadow-md active:scale-95", isMatch &&
939
- "border-highlight-100 bg-highlight-10 text-highlight-100 ring-highlight-100 ring-2", isPartialMatch &&
940
- "border-highlight-100 bg-highlight-10/50", isAltPressed &&
1015
+ return (_jsxs("button", { onClick: () => handleQuickAction(action), className: cn("flex w-full items-center gap-2.5 rounded-[4px] px-2 py-2 text-left text-xs transition-colors duration-150", "text-neutral-grey-100 hover:text-neutral-grey-100 hover:bg-neutral-grey-5", isMatch &&
1016
+ "bg-neutral-grey-5 text-neutral-grey-100 ring-neutral-grey-100 ring-2", isPartialMatch && "bg-neutral-grey-5/50", isAltPressed &&
941
1017
  !isMatch &&
942
1018
  !isPartialMatch &&
943
- "opacity-50"), children: [hasSvgIcon && (_jsx("div", { className: "flex h-3.5 w-3.5 shrink-0 items-center justify-center [&>svg]:h-full [&>svg]:w-full", dangerouslySetInnerHTML: {
1019
+ "opacity-50"), children: [hasSvgIcon && (_jsx("div", { className: "text-neutral-grey-50 flex h-4 w-4 shrink-0 items-center justify-start [&>svg]:h-full [&>svg]:w-full", dangerouslySetInnerHTML: {
944
1020
  __html: sanitizeSvg(action.icon.trim()),
945
1021
  } })), isAltPressed && altSearchBuffer ? (_jsxs("span", { children: [_jsx("span", { className: cn(isMatch &&
946
1022
  "font-bold underline underline-offset-2"), children: action.label.slice(0, altSearchBuffer.length) }), action.label.slice(altSearchBuffer.length)] })) : (action.label)] }, action.id));
947
- }) })] }), _jsxs("form", { onSubmit: (e) => {
948
- e.preventDefault();
1023
+ }) })] }), _jsx(InstructionComposer, { inputRef: inputRef, value: instruction, onChange: setInstruction, onSubmit: () => {
949
1024
  if (instruction.trim()) {
950
1025
  executeAiModification(instruction.trim());
951
1026
  setInstruction("");
952
1027
  }
953
- }, className: "group relative", children: [_jsx(Textarea, { ref: inputRef, value: instruction, onChange: (e) => setInstruction(e.target.value), onKeyDown: handleTextareaKeyDown, placeholder: conversationHistory.length > 0
954
- ? "How can I improve this further?"
955
- : "Describe the change you want...", className: cn("border-border-default w-full rounded-2xl border py-3 pr-14 pl-3 text-xs", "focus:border-highlight-100 focus:ring-highlight-100/10 focus:ring-4", "bg-neutral-grey-5/30 resize-none transition-all duration-200 outline-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("flex h-7 w-7 items-center justify-center rounded-lg p-0 transition-colors duration-200", "text-neutral-grey-50 hover:text-highlight-100 hover:bg-highlight-10", modelPopoverOpen &&
956
- "text-highlight-100 bg-highlight-10"), title: selectedModelSummary
957
- ? `Models: ${selectedModelSummary}`
958
- : "Select models", children: _jsx(Cpu, { className: "h-3.5 w-3.5" }) }) }), _jsxs(PopoverContent, { className: "w-56 p-1.5", align: "end", sideOffset: 8, children: [_jsxs("div", { className: "badge-pad flex items-center justify-between", children: [_jsx("span", { className: "text-neutral-grey-50 text-[10px] font-semibold tracking-wider", children: "Models" }), _jsxs("span", { className: "text-highlight-100 text-[10px] 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("flex w-full items-center gap-2 rounded-md px-2 py-1.5 text-left text-xs transition-colors", selectedModelIds.includes(model.id)
959
- ? "bg-highlight-10 text-highlight-100 font-medium"
960
- : "text-neutral-grey-50 hover:bg-neutral-grey-5"), children: [_jsx("span", { className: cn("flex h-3.5 w-3.5 items-center justify-center rounded border", selectedModelIds.includes(model.id)
961
- ? "border-highlight-100 bg-highlight-100 text-white"
962
- : "border-border-default bg-white text-transparent"), children: _jsx(Check, { className: "h-3 w-3" }) }), model.name] }, model.id))) })] })] })), _jsx("button", { type: "submit", disabled: !instruction.trim() || selectedModels.length === 0, className: cn("flex h-7 w-7 items-center justify-center rounded-lg p-0 transition-colors duration-200", instruction.trim() && selectedModels.length > 0
963
- ? "bg-highlight-100 hover:bg-highlight-100 text-white"
964
- : "bg-neutral-grey-5 text-neutral-grey-50 cursor-not-allowed"), title: "Send (Enter)", children: _jsx(SendHorizonal, { className: "h-3.5 w-3.5" }) })] })] }), conversationHistory.length > 0 && (_jsxs("div", { className: "flex items-center justify-between pt-1", children: [_jsxs("div", { className: "text-neutral-grey-50 flex items-center gap-1.5 text-[10px] font-medium", children: [_jsx(History, { className: "h-3 w-3" }), "Conversation active"] }), _jsxs("button", { onClick: handleStartOver, className: "text-highlight-100 hover:text-highlight-100 flex items-center gap-1 text-[10px] font-bold tracking-tight transition-colors", children: [_jsx(RotateCcw, { className: "h-3 w-3" }), "Clear History"] })] })), error && (_jsxs("div", { className: "text-feedback-red bg-feedback-red-light border-feedback-red animate-in fade-in slide-in-from-top-1 flex items-start gap-2 rounded-lg border px-3 py-2 text-xs duration-200", children: [_jsx(X, { className: "mt-0.5 h-3.5 w-3.5 shrink-0" }), _jsx("span", { children: error })] }))] })), state === "preview" && (_jsxs("div", { className: "animate-in fade-in slide-in-from-bottom-2 space-y-4 duration-300", children: [Object.keys(modelRuns).length > 0 && (_jsxs("div", { className: "space-y-2", children: [_jsxs("div", { className: "text-neutral-grey-50 flex items-center gap-1.5 text-[10px] font-bold tracking-wider", children: [_jsx("div", { className: "bg-highlight-100 h-1.5 w-1.5 rounded-full" }), Object.values(modelRuns).some((r) => r.status === "pending" || r.status === "streaming")
965
- ? "Responses (live)"
966
- : "Model responses"] }), _jsx("div", { className: "flex gap-3 overflow-x-auto pb-1", children: Object.values(modelRuns).map((run) => (_jsxs("div", { className: cn("flex min-w-[280px] flex-1 flex-col gap-2 rounded-xl border p-3", run.status === "done" &&
967
- "border-feedback-green bg-feedback-green-light/40", run.status === "error" &&
968
- "border-feedback-red bg-feedback-red-light/30", (run.status === "pending" ||
969
- run.status === "streaming") &&
970
- "border-highlight-100 bg-highlight-10/30"), children: [_jsxs("div", { className: "flex items-center justify-between gap-2", children: [_jsx("div", { className: "text-neutral-grey-100 truncate text-xs font-semibold", children: run.modelName }), _jsxs("div", { className: "flex shrink-0 items-center gap-2", children: [_jsx("button", { type: "button", onClick: () => handleOpenAgentInSidePanel(run.agentId), className: "text-neutral-grey-50 hover:text-highlight-100 hover:bg-highlight-10 rounded p-1 transition-colors", title: "Open agent in side panel", children: _jsx(Bug, { className: "h-3 w-3" }) }), (run.status === "pending" ||
971
- run.status === "streaming") && (_jsx("button", { type: "button", onClick: () => handleStopModelRun(run.agentId), className: "text-neutral-grey-50 hover:text-feedback-red hover:bg-feedback-red-light rounded-lg p-1.5 transition-colors", title: "Stop this model", children: _jsx(StopCircle, { className: "h-4 w-4" }) })), _jsxs(Badge, { variant: "outline", className: cn(run.status === "done" &&
972
- "border-feedback-green text-feedback-green", run.status === "error" &&
973
- "border-feedback-red text-feedback-red", (run.status === "pending" ||
974
- run.status === "streaming") &&
975
- "border-highlight-100 text-highlight-100"), children: [run.status === "pending" && "Queued", run.status === "streaming" && "Streaming…", run.status === "done" && "Ready", run.status === "error" && "Error"] })] })] }), _jsxs("div", { className: cn("min-h-[80px] overflow-y-auto rounded-lg border p-2 text-xs whitespace-pre-wrap", run.status === "done" &&
976
- "border-feedback-green bg-white/80", run.status === "error" &&
977
- "border-feedback-red text-feedback-red bg-white/80", (run.status === "pending" ||
978
- run.status === "streaming") &&
979
- "border-highlight-100 bg-white/60"), style: { maxHeight: isLarge ? "420px" : "200px" }, children: [run.status === "pending" && (_jsx("span", { className: "text-neutral-grey-50 italic", children: "Starting\u2026" })), run.status === "streaming" &&
1028
+ }, onKeyDown: handleTextareaKeyDown, placeholder: conversationHistory.length > 0
1029
+ ? "How can I improve this further?"
1030
+ : "Describe...", minHeightClass: "min-h-[92px]", submitTitle: "Send (Enter)", canSubmit: !!instruction.trim() && selectedModels.length > 0, models: availableModels, hasMultipleModels: hasMultipleModels, modelPopoverOpen: modelPopoverOpen, onModelPopoverOpenChange: setModelPopoverOpen, selectedModelIds: selectedModelIds, selectedModelsCount: selectedModels.length, selectedModelSummary: selectedModelSummary, onToggleModel: toggleModelSelection, onFocusChange: setPromptFocused }), error && (_jsxs("div", { className: "text-feedback-red bg-feedback-red-light border-feedback-red animate-in fade-in slide-in-from-top-1 flex items-start gap-2 rounded-xl border px-3 py-2 text-xs duration-200", children: [_jsx(X, { className: "mt-0.5 h-3.5 w-3.5 shrink-0" }), _jsx("span", { children: error })] }))] })), state === "preview" && (_jsxs("div", { className: "animate-in fade-in slide-in-from-bottom-2 space-y-4 duration-300", children: [modelRunValues.length > 0 &&
1031
+ (useCompactResultList ? (_jsxs("div", { className: "border-border-default overflow-hidden rounded-lg border bg-white", children: [compactSuggestions.length > 0 ? (compactSuggestions.map((suggestion) => (_jsxs("button", { type: "button", onClick: () => handleUseRunResult(suggestion.text), className: "hover:bg-neutral-grey-5 border-border-default flex h-8 w-full items-center gap-2 border-b px-3 text-left text-xs last:border-b-0", title: suggestion.text, children: [_jsx("span", { className: "text-neutral-grey-100 min-w-0 flex-1 truncate", children: suggestion.text }), selectedModels.length > 1 && (_jsx("span", { className: "text-neutral-grey-50 max-w-[96px] shrink-0 truncate text-[10px]", title: suggestion.modelName, children: suggestion.modelName }))] }, suggestion.id)))) : (_jsxs("div", { className: "text-neutral-grey-50 flex min-h-9 items-center gap-1.5 px-3 text-xs italic", children: [modelRunValues.some((run) => isActiveModelRunStatus(run.status)) && (_jsx(LoaderCircle, { className: "h-3.5 w-3.5 animate-spin" })), modelRunValues.some((run) => isActiveModelRunStatus(run.status))
1032
+ ? "Waiting for suggestions..."
1033
+ : "No suggestions returned."] })), compactSuggestions.length === 0 &&
1034
+ modelRunValues
1035
+ .filter((run) => run.status === "error")
1036
+ .map((run) => (_jsx("div", { className: "text-feedback-red border-border-default border-t px-3 py-2 text-xs", children: run.error || `${run.modelName} failed.` }, `${run.agentId}-error`)))] })) : (_jsx("div", { className: "flex flex-col gap-4", children: modelRunValues.map((run) => {
1037
+ const replacementTexts = run.replacementTexts ??
1038
+ (run.replacementText != null
1039
+ ? [run.replacementText]
1040
+ : []);
1041
+ return (_jsxs("div", { className: cn("border-border-default flex flex-col gap-4 rounded-lg border bg-white p-4", run.status === "error" && "border-feedback-red"), children: [_jsxs("div", { className: "text-neutral-grey-100 flex items-center gap-2 text-xs leading-none font-semibold", children: [_jsxs("div", { className: "flex min-w-0 items-center gap-2", children: [_jsx(Lightbulb, { className: "text-neutral-grey-100 h-5 w-5 shrink-0" }), _jsx("span", { children: "Suggestion" })] }), selectedModels.length > 1 && (_jsx(Badge, { asChild: true, variant: "secondary", size: "sm", className: "ml-auto max-w-[180px] cursor-default truncate", children: _jsx("button", { type: "button", onClick: (event) => handleModelBadgeClick(event, run.agentId), title: `${run.modelName} (Ctrl+click to open agent chat)`, children: run.modelName }) }))] }), _jsxs("div", { className: "max-h-[220px] min-h-[44px] overflow-y-auto", children: [run.status === "pending" && (_jsxs("span", { className: "text-neutral-grey-50 inline-flex items-center gap-1.5 text-xs italic", children: [_jsx(LoaderCircle, { className: "h-3 w-3 animate-spin" }), "Starting..."] })), run.status === "thinking" && (_jsxs("span", { className: "text-neutral-grey-50 inline-flex items-center gap-1.5 text-xs italic", children: [_jsx(LoaderCircle, { className: "h-3 w-3 animate-spin" }), "Thinking..."] })), run.status === "streaming" &&
980
1042
  (() => {
981
1043
  const preview = extractStreamingPreview(run.rawContent ?? "");
982
- return preview ? (renderTextWithContext(preview, false)) : (_jsx("span", { className: "text-neutral-grey-50 italic", children: "Waiting for response\u2026" }));
1044
+ return preview ? (_jsx("div", { className: "font-mono text-sm leading-7 whitespace-pre-wrap", children: renderTextWithContext(preview, false) })) : (_jsxs("span", { className: "text-neutral-grey-50 inline-flex items-center gap-1.5 text-xs italic", children: [_jsx(LoaderCircle, { className: "h-3 w-3 animate-spin" }), "Waiting for response..."] }));
983
1045
  })(), run.status === "done" &&
984
- run.replacementText != null &&
985
- renderTextWithContext(run.replacementText, true), run.status === "error" && (_jsx("div", { className: "text-feedback-red", children: run.error || "Something went wrong." }))] }), run.status === "done" && run.replacementText != null && (_jsxs(Button, { size: "sm", onClick: () => handleUseRunResult(run.replacementText), className: "bg-highlight-100 hover:bg-highlight-100 mt-2 w-full rounded-lg font-semibold text-white", children: [_jsx(Check, { className: "mr-1.5 h-4 w-4" }), "Use this"] }))] }, run.agentId))) })] })), _jsxs("form", { onSubmit: (e) => {
986
- e.preventDefault();
1046
+ replacementTexts.length > 0 && (_jsx("div", { className: "flex flex-col gap-4", children: replacementTexts.map((replacementText, index) => (_jsxs("div", { className: "border-border-default flex flex-col gap-3 border-b pb-4 last:border-b-0 last:pb-0", children: [replacementTexts.length > 1 && (_jsxs("div", { className: "text-neutral-grey-50 text-[11px] font-semibold", children: ["Suggestion ", index + 1] })), renderSuggestionPreview(replacementText), _jsxs(Button, { size: "sm", onClick: () => handleUseRunResult(replacementText), className: "bg-neutral-grey-10 hover:bg-neutral-grey-15 text-neutral-grey-100 self-start rounded-[4px] px-4 py-2 text-sm font-semibold shadow-none", children: [_jsx(Check, { className: "mr-1.5 h-4 w-4" }), "Apply"] })] }, `${run.agentId}-${index}`))) })), run.status === "error" && (_jsx("div", { className: "text-feedback-red text-sm", children: run.error || "Something went wrong." }))] })] }, run.agentId));
1047
+ }) }))), _jsx(InstructionComposer, { inputRef: inputRef, value: instruction, onChange: setInstruction, onSubmit: () => {
987
1048
  if (instruction.trim()) {
988
1049
  executeAiModification(instruction.trim());
989
1050
  setInstruction("");
990
1051
  }
991
- }, className: "group relative", 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("border-border-default min-h-[80px] w-full rounded-2xl border py-3 pr-14 pl-3 text-xs", "focus:border-highlight-100 focus:ring-highlight-100/10 focus:ring-4", "bg-neutral-grey-5/30 resize-none transition-all duration-200 outline-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("flex h-7 w-7 items-center justify-center rounded-lg p-0 transition-colors duration-200", "text-neutral-grey-50 hover:text-highlight-100 hover:bg-highlight-10", modelPopoverOpen &&
992
- "text-highlight-100 bg-highlight-10"), title: selectedModelSummary
993
- ? `Models: ${selectedModelSummary}`
994
- : "Select models", children: _jsx(Cpu, { className: "h-3.5 w-3.5" }) }) }), _jsxs(PopoverContent, { className: "w-56 p-1.5", align: "end", sideOffset: 8, children: [_jsxs("div", { className: "badge-pad flex items-center justify-between", children: [_jsx("span", { className: "text-2xs text-neutral-grey-50 font-semibold tracking-wider", children: "Models" }), _jsxs("span", { className: "text-highlight-100 text-[10px] 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("flex w-full items-center gap-2 rounded-md px-2 py-1.5 text-left text-xs transition-colors", selectedModelIds.includes(model.id)
995
- ? "bg-highlight-10 text-highlight-100 font-medium"
996
- : "text-neutral-grey-50 hover:bg-neutral-grey-5"), children: [_jsx("span", { className: cn("flex h-3.5 w-3.5 items-center justify-center rounded border", selectedModelIds.includes(model.id)
997
- ? "border-highlight-100 bg-highlight-100 text-white"
998
- : "border-border-default bg-white text-transparent"), children: _jsx(Check, { className: "h-3 w-3" }) }), model.name] }, model.id))) })] })] })), _jsx("button", { type: "submit", disabled: !instruction.trim() || selectedModels.length === 0, className: cn("flex h-7 w-7 items-center justify-center rounded-lg p-0 transition-colors duration-200", instruction.trim() && selectedModels.length > 0
999
- ? "bg-highlight-100 hover:bg-highlight-100 text-white"
1000
- : "bg-neutral-grey-5 text-neutral-grey-50 cursor-not-allowed"), title: "Refine (Enter)", children: _jsx(Wand2, { className: "h-3.5 w-3.5" }) })] })] }), _jsxs("div", { className: "flex gap-2.5 pt-1", children: [_jsxs(Button, { variant: "ghost", size: "sm", onClick: handleStartOver, className: "text-neutral-grey-50 hover:text-neutral-grey-100 hover:bg-neutral-grey-5 flex-1 rounded-xl font-medium", children: [_jsx(RotateCcw, { className: "mr-2 h-4 w-4" }), "Discard"] }), _jsxs(Button, { variant: "ghost", size: "sm", onClick: handleRetry, disabled: conversationHistory.length === 0, className: "text-highlight-100 hover:text-highlight-100 hover:bg-highlight-10 flex-1 rounded-xl font-medium disabled:pointer-events-none disabled:opacity-50", title: "Run the same request again", children: [_jsx(RotateCw, { className: "mr-2 h-4 w-4" }), "Retry"] })] })] }))] })] }));
1052
+ }, onKeyDown: handleTextareaKeyDown, placeholder: "Not quite right? Ask for a change...", minHeightClass: "min-h-[92px]", submitTitle: "Refine (Enter)", canSubmit: !!instruction.trim() && selectedModels.length > 0, models: availableModels, hasMultipleModels: hasMultipleModels, modelPopoverOpen: modelPopoverOpen, onModelPopoverOpenChange: setModelPopoverOpen, selectedModelIds: selectedModelIds, selectedModelsCount: selectedModels.length, selectedModelSummary: selectedModelSummary, onToggleModel: toggleModelSelection, onFocusChange: setPromptFocused })] }))] })] }));
1001
1053
  }
1002
1054
  export default InlineAiDialog;
1003
1055
  //# sourceMappingURL=InlineAiDialog.js.map