@parhelia/core 0.1.11004 → 0.1.11007

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 (1104) hide show
  1. package/dist/dist/agents-view/AgentCard.d.ts +12 -0
  2. package/dist/dist/agents-view/AgentCard.js +30 -0
  3. package/dist/dist/agents-view/AgentCard.js.map +1 -0
  4. package/dist/dist/agents-view/AgentsView.d.ts +5 -0
  5. package/dist/dist/agents-view/AgentsView.js +255 -0
  6. package/dist/dist/agents-view/AgentsView.js.map +1 -0
  7. package/dist/dist/agents-view/ProfileAgentsGroup.d.ts +17 -0
  8. package/dist/dist/agents-view/ProfileAgentsGroup.js +13 -0
  9. package/dist/dist/agents-view/ProfileAgentsGroup.js.map +1 -0
  10. package/dist/dist/client-components/api.d.ts +1 -0
  11. package/dist/dist/client-components/api.js +4 -0
  12. package/dist/dist/client-components/api.js.map +1 -0
  13. package/dist/dist/client-components/index.d.ts +17 -0
  14. package/dist/dist/client-components/index.js +18 -0
  15. package/dist/dist/client-components/index.js.map +1 -0
  16. package/dist/dist/components/ActionButton.d.ts +14 -0
  17. package/dist/dist/components/ActionButton.js +6 -0
  18. package/dist/dist/components/ActionButton.js.map +1 -0
  19. package/dist/dist/components/Error.d.ts +9 -0
  20. package/dist/dist/components/Error.js +24 -0
  21. package/dist/dist/components/Error.js.map +1 -0
  22. package/dist/dist/components/FilterInput.d.ts +22 -0
  23. package/dist/dist/components/FilterInput.js +29 -0
  24. package/dist/dist/components/FilterInput.js.map +1 -0
  25. package/dist/dist/components/index.d.ts +7 -0
  26. package/dist/dist/components/index.js +5 -0
  27. package/dist/dist/components/index.js.map +1 -0
  28. package/dist/dist/components/ui/CardConnector.d.ts +4 -0
  29. package/dist/dist/components/ui/CardConnector.js +6 -0
  30. package/dist/dist/components/ui/CardConnector.js.map +1 -0
  31. package/dist/dist/components/ui/LanguageSelector.d.ts +8 -0
  32. package/dist/dist/components/ui/LanguageSelector.js +53 -0
  33. package/dist/dist/components/ui/LanguageSelector.js.map +1 -0
  34. package/dist/dist/components/ui/PlaceholderInput.d.ts +41 -0
  35. package/dist/dist/components/ui/PlaceholderInput.js +160 -0
  36. package/dist/dist/components/ui/PlaceholderInput.js.map +1 -0
  37. package/dist/dist/components/ui/PlaceholderInputTypes.d.ts +41 -0
  38. package/dist/dist/components/ui/PlaceholderInputTypes.js +48 -0
  39. package/dist/dist/components/ui/PlaceholderInputTypes.js.map +1 -0
  40. package/dist/dist/components/ui/PlaceholderItemSelector.d.ts +7 -0
  41. package/dist/dist/components/ui/PlaceholderItemSelector.js +154 -0
  42. package/dist/dist/components/ui/PlaceholderItemSelector.js.map +1 -0
  43. package/dist/dist/components/ui/alert.d.ts +7 -0
  44. package/dist/dist/components/ui/alert.js +21 -0
  45. package/dist/dist/components/ui/alert.js.map +1 -0
  46. package/dist/dist/components/ui/badge.d.ts +9 -0
  47. package/dist/dist/components/ui/badge.js +23 -0
  48. package/dist/dist/components/ui/badge.js.map +1 -0
  49. package/dist/dist/components/ui/button.d.ts +10 -0
  50. package/dist/dist/components/ui/button.js +33 -0
  51. package/dist/dist/components/ui/button.js.map +1 -0
  52. package/dist/dist/components/ui/calendar.d.ts +7 -0
  53. package/dist/dist/components/ui/calendar.js +58 -0
  54. package/dist/dist/components/ui/calendar.js.map +1 -0
  55. package/dist/dist/components/ui/card.d.ts +19 -0
  56. package/dist/dist/components/ui/card.js +78 -0
  57. package/dist/dist/components/ui/card.js.map +1 -0
  58. package/dist/dist/components/ui/checkbox.d.ts +4 -0
  59. package/dist/dist/components/ui/checkbox.js +10 -0
  60. package/dist/dist/components/ui/checkbox.js.map +1 -0
  61. package/dist/dist/components/ui/command.d.ts +18 -0
  62. package/dist/dist/components/ui/command.js +35 -0
  63. package/dist/dist/components/ui/command.js.map +1 -0
  64. package/dist/dist/components/ui/context-menu.d.ts +53 -0
  65. package/dist/dist/components/ui/context-menu.js +290 -0
  66. package/dist/dist/components/ui/context-menu.js.map +1 -0
  67. package/dist/dist/components/ui/copy-button.d.ts +10 -0
  68. package/dist/dist/components/ui/copy-button.js +61 -0
  69. package/dist/dist/components/ui/copy-button.js.map +1 -0
  70. package/dist/dist/components/ui/dialog.d.ts +16 -0
  71. package/dist/dist/components/ui/dialog.js +37 -0
  72. package/dist/dist/components/ui/dialog.js.map +1 -0
  73. package/dist/dist/components/ui/dropdown-menu.d.ts +25 -0
  74. package/dist/dist/components/ui/dropdown-menu.js +52 -0
  75. package/dist/dist/components/ui/dropdown-menu.js.map +1 -0
  76. package/dist/dist/components/ui/input.d.ts +3 -0
  77. package/dist/dist/components/ui/input.js +9 -0
  78. package/dist/dist/components/ui/input.js.map +1 -0
  79. package/dist/dist/components/ui/label.d.ts +5 -0
  80. package/dist/dist/components/ui/label.js +9 -0
  81. package/dist/dist/components/ui/label.js.map +1 -0
  82. package/dist/dist/components/ui/menubar.d.ts +26 -0
  83. package/dist/dist/components/ui/menubar.js +55 -0
  84. package/dist/dist/components/ui/menubar.js.map +1 -0
  85. package/dist/dist/components/ui/paste-button.d.ts +14 -0
  86. package/dist/dist/components/ui/paste-button.js +114 -0
  87. package/dist/dist/components/ui/paste-button.js.map +1 -0
  88. package/dist/dist/components/ui/popover.d.ts +11 -0
  89. package/dist/dist/components/ui/popover.js +66 -0
  90. package/dist/dist/components/ui/popover.js.map +1 -0
  91. package/dist/dist/components/ui/progress.d.ts +7 -0
  92. package/dist/dist/components/ui/progress.js +9 -0
  93. package/dist/dist/components/ui/progress.js.map +1 -0
  94. package/dist/dist/components/ui/select.d.ts +18 -0
  95. package/dist/dist/components/ui/select.js +34 -0
  96. package/dist/dist/components/ui/select.js.map +1 -0
  97. package/dist/dist/components/ui/sonner.d.ts +3 -0
  98. package/dist/dist/components/ui/sonner.js +16 -0
  99. package/dist/dist/components/ui/sonner.js.map +1 -0
  100. package/dist/dist/components/ui/switch.d.ts +4 -0
  101. package/dist/dist/components/ui/switch.js +9 -0
  102. package/dist/dist/components/ui/switch.js.map +1 -0
  103. package/dist/dist/components/ui/tabs.d.ts +17 -0
  104. package/dist/dist/components/ui/tabs.js +27 -0
  105. package/dist/dist/components/ui/tabs.js.map +1 -0
  106. package/dist/dist/components/ui/textarea.d.ts +3 -0
  107. package/dist/dist/components/ui/textarea.js +11 -0
  108. package/dist/dist/components/ui/textarea.js.map +1 -0
  109. package/dist/dist/components/ui/tooltip.d.ts +9 -0
  110. package/dist/dist/components/ui/tooltip.js +18 -0
  111. package/dist/dist/components/ui/tooltip.js.map +1 -0
  112. package/dist/dist/components/ui/upload-button.d.ts +15 -0
  113. package/dist/dist/components/ui/upload-button.js +56 -0
  114. package/dist/dist/components/ui/upload-button.js.map +1 -0
  115. package/dist/dist/config/config.d.ts +24 -0
  116. package/dist/dist/config/config.js +1088 -0
  117. package/dist/dist/config/config.js.map +1 -0
  118. package/dist/dist/config/types.d.ts +244 -0
  119. package/dist/dist/config/types.js +2 -0
  120. package/dist/dist/config/types.js.map +1 -0
  121. package/dist/dist/editor/AspectRatioSelector.d.ts +13 -0
  122. package/dist/dist/editor/AspectRatioSelector.js +71 -0
  123. package/dist/dist/editor/AspectRatioSelector.js.map +1 -0
  124. package/dist/dist/editor/ComponentInfo.d.ts +4 -0
  125. package/dist/dist/editor/ComponentInfo.js +41 -0
  126. package/dist/dist/editor/ComponentInfo.js.map +1 -0
  127. package/dist/dist/editor/ConfirmationDialog.d.ts +19 -0
  128. package/dist/dist/editor/ConfirmationDialog.js +31 -0
  129. package/dist/dist/editor/ConfirmationDialog.js.map +1 -0
  130. package/dist/dist/editor/ContentTree.d.ts +39 -0
  131. package/dist/dist/editor/ContentTree.js +602 -0
  132. package/dist/dist/editor/ContentTree.js.map +1 -0
  133. package/dist/dist/editor/ContextMenu.d.ts +15 -0
  134. package/dist/dist/editor/ContextMenu.js +239 -0
  135. package/dist/dist/editor/ContextMenu.js.map +1 -0
  136. package/dist/dist/editor/Editor.d.ts +12 -0
  137. package/dist/dist/editor/Editor.js +116 -0
  138. package/dist/dist/editor/Editor.js.map +1 -0
  139. package/dist/dist/editor/EditorWarning.d.ts +5 -0
  140. package/dist/dist/editor/EditorWarning.js +12 -0
  141. package/dist/dist/editor/EditorWarning.js.map +1 -0
  142. package/dist/dist/editor/EditorWarnings.d.ts +9 -0
  143. package/dist/dist/editor/EditorWarnings.js +19 -0
  144. package/dist/dist/editor/EditorWarnings.js.map +1 -0
  145. package/dist/dist/editor/FieldActionsOverlay.d.ts +18 -0
  146. package/dist/dist/editor/FieldActionsOverlay.js +201 -0
  147. package/dist/dist/editor/FieldActionsOverlay.js.map +1 -0
  148. package/dist/dist/editor/FieldEditorPopup.d.ts +10 -0
  149. package/dist/dist/editor/FieldEditorPopup.js +23 -0
  150. package/dist/dist/editor/FieldEditorPopup.js.map +1 -0
  151. package/dist/dist/editor/FieldHistory.d.ts +7 -0
  152. package/dist/dist/editor/FieldHistory.js +45 -0
  153. package/dist/dist/editor/FieldHistory.js.map +1 -0
  154. package/dist/dist/editor/FieldList.d.ts +19 -0
  155. package/dist/dist/editor/FieldList.js +90 -0
  156. package/dist/dist/editor/FieldList.js.map +1 -0
  157. package/dist/dist/editor/FieldListField.d.ts +16 -0
  158. package/dist/dist/editor/FieldListField.js +286 -0
  159. package/dist/dist/editor/FieldListField.js.map +1 -0
  160. package/dist/dist/editor/FieldListFieldWithFallbacks.d.ts +11 -0
  161. package/dist/dist/editor/FieldListFieldWithFallbacks.js +120 -0
  162. package/dist/dist/editor/FieldListFieldWithFallbacks.js.map +1 -0
  163. package/dist/dist/editor/FloatingToolbar.d.ts +7 -0
  164. package/dist/dist/editor/FloatingToolbar.js +91 -0
  165. package/dist/dist/editor/FloatingToolbar.js.map +1 -0
  166. package/dist/dist/editor/ImageEditButton.d.ts +27 -0
  167. package/dist/dist/editor/ImageEditButton.js +22 -0
  168. package/dist/dist/editor/ImageEditButton.js.map +1 -0
  169. package/dist/dist/editor/ImageEditor.d.ts +5 -0
  170. package/dist/dist/editor/ImageEditor.js +76 -0
  171. package/dist/dist/editor/ImageEditor.js.map +1 -0
  172. package/dist/dist/editor/ItemInfo.d.ts +4 -0
  173. package/dist/dist/editor/ItemInfo.js +60 -0
  174. package/dist/dist/editor/ItemInfo.js.map +1 -0
  175. package/dist/dist/editor/LinkEditorDialog.d.ts +18 -0
  176. package/dist/dist/editor/LinkEditorDialog.js +101 -0
  177. package/dist/dist/editor/LinkEditorDialog.js.map +1 -0
  178. package/dist/dist/editor/MainLayout.d.ts +12 -0
  179. package/dist/dist/editor/MainLayout.js +124 -0
  180. package/dist/dist/editor/MainLayout.js.map +1 -0
  181. package/dist/dist/editor/MobileLayout.d.ts +2 -0
  182. package/dist/dist/editor/MobileLayout.js +34 -0
  183. package/dist/dist/editor/MobileLayout.js.map +1 -0
  184. package/dist/dist/editor/NewEditorClient.d.ts +5 -0
  185. package/dist/dist/editor/NewEditorClient.js +7 -0
  186. package/dist/dist/editor/NewEditorClient.js.map +1 -0
  187. package/dist/dist/editor/PictureCropper.d.ts +6 -0
  188. package/dist/dist/editor/PictureCropper.js +722 -0
  189. package/dist/dist/editor/PictureCropper.js.map +1 -0
  190. package/dist/dist/editor/PictureEditor.d.ts +9 -0
  191. package/dist/dist/editor/PictureEditor.js +180 -0
  192. package/dist/dist/editor/PictureEditor.js.map +1 -0
  193. package/dist/dist/editor/PictureEditorDialog.d.ts +8 -0
  194. package/dist/dist/editor/PictureEditorDialog.js +195 -0
  195. package/dist/dist/editor/PictureEditorDialog.js.map +1 -0
  196. package/dist/dist/editor/QuickItemSwitcher.d.ts +9 -0
  197. package/dist/dist/editor/QuickItemSwitcher.js +78 -0
  198. package/dist/dist/editor/QuickItemSwitcher.js.map +1 -0
  199. package/dist/dist/editor/ScrollingContentTree.d.ts +10 -0
  200. package/dist/dist/editor/ScrollingContentTree.js +48 -0
  201. package/dist/dist/editor/ScrollingContentTree.js.map +1 -0
  202. package/dist/dist/editor/SetupLoadingScreen.d.ts +5 -0
  203. package/dist/dist/editor/SetupLoadingScreen.js +11 -0
  204. package/dist/dist/editor/SetupLoadingScreen.js.map +1 -0
  205. package/dist/dist/editor/Titlebar.d.ts +1 -0
  206. package/dist/dist/editor/Titlebar.js +46 -0
  207. package/dist/dist/editor/Titlebar.js.map +1 -0
  208. package/dist/dist/editor/ai/AgentCostDisplay.d.ts +32 -0
  209. package/dist/dist/editor/ai/AgentCostDisplay.js +93 -0
  210. package/dist/dist/editor/ai/AgentCostDisplay.js.map +1 -0
  211. package/dist/dist/editor/ai/AgentDocumentList.d.ts +8 -0
  212. package/dist/dist/editor/ai/AgentDocumentList.js +132 -0
  213. package/dist/dist/editor/ai/AgentDocumentList.js.map +1 -0
  214. package/dist/dist/editor/ai/AgentHistory.d.ts +11 -0
  215. package/dist/dist/editor/ai/AgentHistory.js +12 -0
  216. package/dist/dist/editor/ai/AgentHistory.js.map +1 -0
  217. package/dist/dist/editor/ai/AgentProfilesOverview.d.ts +9 -0
  218. package/dist/dist/editor/ai/AgentProfilesOverview.js +16 -0
  219. package/dist/dist/editor/ai/AgentProfilesOverview.js.map +1 -0
  220. package/dist/dist/editor/ai/AgentStatusBadge.d.ts +26 -0
  221. package/dist/dist/editor/ai/AgentStatusBadge.js +126 -0
  222. package/dist/dist/editor/ai/AgentStatusBadge.js.map +1 -0
  223. package/dist/dist/editor/ai/AgentTerminal.d.ts +14 -0
  224. package/dist/dist/editor/ai/AgentTerminal.js +3012 -0
  225. package/dist/dist/editor/ai/AgentTerminal.js.map +1 -0
  226. package/dist/dist/editor/ai/Agents.d.ts +4 -0
  227. package/dist/dist/editor/ai/Agents.js +891 -0
  228. package/dist/dist/editor/ai/Agents.js.map +1 -0
  229. package/dist/dist/editor/ai/AiResponseMessage.d.ts +18 -0
  230. package/dist/dist/editor/ai/AiResponseMessage.js +684 -0
  231. package/dist/dist/editor/ai/AiResponseMessage.js.map +1 -0
  232. package/dist/dist/editor/ai/ContextInfoBar.d.ts +14 -0
  233. package/dist/dist/editor/ai/ContextInfoBar.js +432 -0
  234. package/dist/dist/editor/ai/ContextInfoBar.js.map +1 -0
  235. package/dist/dist/editor/ai/DancingDots.d.ts +1 -0
  236. package/dist/dist/editor/ai/DancingDots.js +6 -0
  237. package/dist/dist/editor/ai/DancingDots.js.map +1 -0
  238. package/dist/dist/editor/ai/MediaImage.d.ts +6 -0
  239. package/dist/dist/editor/ai/MediaImage.js +38 -0
  240. package/dist/dist/editor/ai/MediaImage.js.map +1 -0
  241. package/dist/dist/editor/ai/ToolCallDisplay.d.ts +45 -0
  242. package/dist/dist/editor/ai/ToolCallDisplay.js +292 -0
  243. package/dist/dist/editor/ai/ToolCallDisplay.js.map +1 -0
  244. package/dist/dist/editor/ai/aiPageModel.d.ts +24 -0
  245. package/dist/dist/editor/ai/aiPageModel.js +97 -0
  246. package/dist/dist/editor/ai/aiPageModel.js.map +1 -0
  247. package/dist/dist/editor/ai/editorAiContext.d.ts +10 -0
  248. package/dist/dist/editor/ai/editorAiContext.js +10 -0
  249. package/dist/dist/editor/ai/editorAiContext.js.map +1 -0
  250. package/dist/dist/editor/ai/types.d.ts +30 -0
  251. package/dist/dist/editor/ai/types.js +2 -0
  252. package/dist/dist/editor/ai/types.js.map +1 -0
  253. package/dist/dist/editor/ai/useAgentStatus.d.ts +14 -0
  254. package/dist/dist/editor/ai/useAgentStatus.js +203 -0
  255. package/dist/dist/editor/ai/useAgentStatus.js.map +1 -0
  256. package/dist/dist/editor/client/AboutDialog.d.ts +2 -0
  257. package/dist/dist/editor/client/AboutDialog.js +23 -0
  258. package/dist/dist/editor/client/AboutDialog.js.map +1 -0
  259. package/dist/dist/editor/client/EditorShell.d.ts +37 -0
  260. package/dist/dist/editor/client/EditorShell.js +2283 -0
  261. package/dist/dist/editor/client/EditorShell.js.map +1 -0
  262. package/dist/dist/editor/client/GenericDialog.d.ts +10 -0
  263. package/dist/dist/editor/client/GenericDialog.js +25 -0
  264. package/dist/dist/editor/client/GenericDialog.js.map +1 -0
  265. package/dist/dist/editor/client/editContext.d.ts +262 -0
  266. package/dist/dist/editor/client/editContext.js +29 -0
  267. package/dist/dist/editor/client/editContext.js.map +1 -0
  268. package/dist/dist/editor/client/fieldModificationStore.d.ts +25 -0
  269. package/dist/dist/editor/client/fieldModificationStore.js +184 -0
  270. package/dist/dist/editor/client/fieldModificationStore.js.map +1 -0
  271. package/dist/dist/editor/client/helpers.d.ts +12 -0
  272. package/dist/dist/editor/client/helpers.js +29 -0
  273. package/dist/dist/editor/client/helpers.js.map +1 -0
  274. package/dist/dist/editor/client/hooks/useEditorUrlSync.d.ts +18 -0
  275. package/dist/dist/editor/client/hooks/useEditorUrlSync.js +56 -0
  276. package/dist/dist/editor/client/hooks/useEditorUrlSync.js.map +1 -0
  277. package/dist/dist/editor/client/hooks/useEditorWebSocket.d.ts +11 -0
  278. package/dist/dist/editor/client/hooks/useEditorWebSocket.js +86 -0
  279. package/dist/dist/editor/client/hooks/useEditorWebSocket.js.map +1 -0
  280. package/dist/dist/editor/client/hooks/useGlobalEditorKeyDown.d.ts +1 -0
  281. package/dist/dist/editor/client/hooks/useGlobalEditorKeyDown.js +12 -0
  282. package/dist/dist/editor/client/hooks/useGlobalEditorKeyDown.js.map +1 -0
  283. package/dist/dist/editor/client/hooks/useMediaQuery.d.ts +1 -0
  284. package/dist/dist/editor/client/hooks/useMediaQuery.js +19 -0
  285. package/dist/dist/editor/client/hooks/useMediaQuery.js.map +1 -0
  286. package/dist/dist/editor/client/hooks/useMediaSelector.d.ts +12 -0
  287. package/dist/dist/editor/client/hooks/useMediaSelector.js +30 -0
  288. package/dist/dist/editor/client/hooks/useMediaSelector.js.map +1 -0
  289. package/dist/dist/editor/client/hooks/useQuota.d.ts +29 -0
  290. package/dist/dist/editor/client/hooks/useQuota.js +53 -0
  291. package/dist/dist/editor/client/hooks/useQuota.js.map +1 -0
  292. package/dist/dist/editor/client/hooks/useSocketMessageHandler.d.ts +35 -0
  293. package/dist/dist/editor/client/hooks/useSocketMessageHandler.js +241 -0
  294. package/dist/dist/editor/client/hooks/useSocketMessageHandler.js.map +1 -0
  295. package/dist/dist/editor/client/hooks/useWorkbox.d.ts +9 -0
  296. package/dist/dist/editor/client/hooks/useWorkbox.js +52 -0
  297. package/dist/dist/editor/client/hooks/useWorkbox.js.map +1 -0
  298. package/dist/dist/editor/client/itemsRepository.d.ts +38 -0
  299. package/dist/dist/editor/client/itemsRepository.js +482 -0
  300. package/dist/dist/editor/client/itemsRepository.js.map +1 -0
  301. package/dist/dist/editor/client/operations.d.ts +69 -0
  302. package/dist/dist/editor/client/operations.js +633 -0
  303. package/dist/dist/editor/client/operations.js.map +1 -0
  304. package/dist/dist/editor/client/pageModelBuilder.d.ts +6 -0
  305. package/dist/dist/editor/client/pageModelBuilder.js +171 -0
  306. package/dist/dist/editor/client/pageModelBuilder.js.map +1 -0
  307. package/dist/dist/editor/client/ui/EditorChrome.d.ts +12 -0
  308. package/dist/dist/editor/client/ui/EditorChrome.js +30 -0
  309. package/dist/dist/editor/client/ui/EditorChrome.js.map +1 -0
  310. package/dist/dist/editor/client/ui/FullscreenControls.d.ts +7 -0
  311. package/dist/dist/editor/client/ui/FullscreenControls.js +21 -0
  312. package/dist/dist/editor/client/ui/FullscreenControls.js.map +1 -0
  313. package/dist/dist/editor/commands/agentCommands.d.ts +9 -0
  314. package/dist/dist/editor/commands/agentCommands.js +30 -0
  315. package/dist/dist/editor/commands/agentCommands.js.map +1 -0
  316. package/dist/dist/editor/commands/commands.d.ts +19 -0
  317. package/dist/dist/editor/commands/commands.js +2 -0
  318. package/dist/dist/editor/commands/commands.js.map +1 -0
  319. package/dist/dist/editor/commands/componentCommands.d.ts +12 -0
  320. package/dist/dist/editor/commands/componentCommands.js +367 -0
  321. package/dist/dist/editor/commands/componentCommands.js.map +1 -0
  322. package/dist/dist/editor/commands/createVersionCommand.d.ts +4 -0
  323. package/dist/dist/editor/commands/createVersionCommand.js +24 -0
  324. package/dist/dist/editor/commands/createVersionCommand.js.map +1 -0
  325. package/dist/dist/editor/commands/deleteVersionCommand.d.ts +4 -0
  326. package/dist/dist/editor/commands/deleteVersionCommand.js +53 -0
  327. package/dist/dist/editor/commands/deleteVersionCommand.js.map +1 -0
  328. package/dist/dist/editor/commands/itemCommands.d.ts +29 -0
  329. package/dist/dist/editor/commands/itemCommands.js +448 -0
  330. package/dist/dist/editor/commands/itemCommands.js.map +1 -0
  331. package/dist/dist/editor/commands/localizeItem/LocalizeItemDialog.d.ts +8 -0
  332. package/dist/dist/editor/commands/localizeItem/LocalizeItemDialog.js +91 -0
  333. package/dist/dist/editor/commands/localizeItem/LocalizeItemDialog.js.map +1 -0
  334. package/dist/dist/editor/commands/undo.d.ts +15 -0
  335. package/dist/dist/editor/commands/undo.js +29 -0
  336. package/dist/dist/editor/commands/undo.js.map +1 -0
  337. package/dist/dist/editor/componentTreeHelper.d.ts +18 -0
  338. package/dist/dist/editor/componentTreeHelper.js +123 -0
  339. package/dist/dist/editor/componentTreeHelper.js.map +1 -0
  340. package/dist/dist/editor/context-menu/CopyMoveMenu.d.ts +7 -0
  341. package/dist/dist/editor/context-menu/CopyMoveMenu.js +58 -0
  342. package/dist/dist/editor/context-menu/CopyMoveMenu.js.map +1 -0
  343. package/dist/dist/editor/context-menu/InsertMenu.d.ts +9 -0
  344. package/dist/dist/editor/context-menu/InsertMenu.js +229 -0
  345. package/dist/dist/editor/context-menu/InsertMenu.js.map +1 -0
  346. package/dist/dist/editor/control-center/About.d.ts +1 -0
  347. package/dist/dist/editor/control-center/About.js +8 -0
  348. package/dist/dist/editor/control-center/About.js.map +1 -0
  349. package/dist/dist/editor/control-center/AllAgentsPanel.d.ts +5 -0
  350. package/dist/dist/editor/control-center/AllAgentsPanel.js +126 -0
  351. package/dist/dist/editor/control-center/AllAgentsPanel.js.map +1 -0
  352. package/dist/dist/editor/control-center/ControlCenterMenu.d.ts +1 -0
  353. package/dist/dist/editor/control-center/ControlCenterMenu.js +66 -0
  354. package/dist/dist/editor/control-center/ControlCenterMenu.js.map +1 -0
  355. package/dist/dist/editor/control-center/IndexOverview.d.ts +1 -0
  356. package/dist/dist/editor/control-center/IndexOverview.js +323 -0
  357. package/dist/dist/editor/control-center/IndexOverview.js.map +1 -0
  358. package/dist/dist/editor/control-center/Info.d.ts +1 -0
  359. package/dist/dist/editor/control-center/Info.js +10 -0
  360. package/dist/dist/editor/control-center/Info.js.map +1 -0
  361. package/dist/dist/editor/control-center/LatestFeedback.d.ts +1 -0
  362. package/dist/dist/editor/control-center/LatestFeedback.js +136 -0
  363. package/dist/dist/editor/control-center/LatestFeedback.js.map +1 -0
  364. package/dist/dist/editor/control-center/QuotaInfo.d.ts +1 -0
  365. package/dist/dist/editor/control-center/QuotaInfo.js +102 -0
  366. package/dist/dist/editor/control-center/QuotaInfo.js.map +1 -0
  367. package/dist/dist/editor/control-center/Setup.d.ts +1 -0
  368. package/dist/dist/editor/control-center/Setup.js +174 -0
  369. package/dist/dist/editor/control-center/Setup.js.map +1 -0
  370. package/dist/dist/editor/control-center/Status.d.ts +1 -0
  371. package/dist/dist/editor/control-center/Status.js +79 -0
  372. package/dist/dist/editor/control-center/Status.js.map +1 -0
  373. package/dist/dist/editor/control-center/WebSocketMessages.d.ts +1 -0
  374. package/dist/dist/editor/control-center/WebSocketMessages.js +71 -0
  375. package/dist/dist/editor/control-center/WebSocketMessages.js.map +1 -0
  376. package/dist/dist/editor/control-center/parhelia-setup/Overview.d.ts +1 -0
  377. package/dist/dist/editor/control-center/parhelia-setup/Overview.js +91 -0
  378. package/dist/dist/editor/control-center/parhelia-setup/Overview.js.map +1 -0
  379. package/dist/dist/editor/control-center/setup-steps/AiSetupStep/EmbeddingsModelSection.d.ts +2 -0
  380. package/dist/dist/editor/control-center/setup-steps/AiSetupStep/EmbeddingsModelSection.js +195 -0
  381. package/dist/dist/editor/control-center/setup-steps/AiSetupStep/EmbeddingsModelSection.js.map +1 -0
  382. package/dist/dist/editor/control-center/setup-steps/AiSetupStep/index.d.ts +2 -0
  383. package/dist/dist/editor/control-center/setup-steps/AiSetupStep/index.js +22 -0
  384. package/dist/dist/editor/control-center/setup-steps/AiSetupStep/index.js.map +1 -0
  385. package/dist/dist/editor/control-center/setup-steps/AiSetupStep/provider/ProviderSection.d.ts +1 -0
  386. package/dist/dist/editor/control-center/setup-steps/AiSetupStep/provider/ProviderSection.js +233 -0
  387. package/dist/dist/editor/control-center/setup-steps/AiSetupStep/provider/ProviderSection.js.map +1 -0
  388. package/dist/dist/editor/control-center/setup-steps/AiSetupStep/required-containers/RequiredContainersList.d.ts +15 -0
  389. package/dist/dist/editor/control-center/setup-steps/AiSetupStep/required-containers/RequiredContainersList.js +14 -0
  390. package/dist/dist/editor/control-center/setup-steps/AiSetupStep/required-containers/RequiredContainersList.js.map +1 -0
  391. package/dist/dist/editor/control-center/setup-steps/AiSetupStep/required-containers/RequiredContainersSection.d.ts +1 -0
  392. package/dist/dist/editor/control-center/setup-steps/AiSetupStep/required-containers/RequiredContainersSection.js +94 -0
  393. package/dist/dist/editor/control-center/setup-steps/AiSetupStep/required-containers/RequiredContainersSection.js.map +1 -0
  394. package/dist/dist/editor/control-center/setup-steps/AiSetupStep/tools/GenerateToolsSection.d.ts +1 -0
  395. package/dist/dist/editor/control-center/setup-steps/AiSetupStep/tools/GenerateToolsSection.js +367 -0
  396. package/dist/dist/editor/control-center/setup-steps/AiSetupStep/tools/GenerateToolsSection.js.map +1 -0
  397. package/dist/dist/editor/control-center/setup-steps/AiSetupStep/types.d.ts +1 -0
  398. package/dist/dist/editor/control-center/setup-steps/AiSetupStep/types.js +2 -0
  399. package/dist/dist/editor/control-center/setup-steps/AiSetupStep/types.js.map +1 -0
  400. package/dist/dist/editor/control-center/setup-steps/AiSetupStep/utils.d.ts +5 -0
  401. package/dist/dist/editor/control-center/setup-steps/AiSetupStep/utils.js +44 -0
  402. package/dist/dist/editor/control-center/setup-steps/AiSetupStep/utils.js.map +1 -0
  403. package/dist/dist/editor/control-center/setup-steps/DbSetupStep.d.ts +2 -0
  404. package/dist/dist/editor/control-center/setup-steps/DbSetupStep.js +46 -0
  405. package/dist/dist/editor/control-center/setup-steps/DbSetupStep.js.map +1 -0
  406. package/dist/dist/editor/control-center/setup-steps/IndexSetupStep.d.ts +2 -0
  407. package/dist/dist/editor/control-center/setup-steps/IndexSetupStep.js +36 -0
  408. package/dist/dist/editor/control-center/setup-steps/IndexSetupStep.js.map +1 -0
  409. package/dist/dist/editor/control-center/setup-steps/SettingsSetupStep.d.ts +2 -0
  410. package/dist/dist/editor/control-center/setup-steps/SettingsSetupStep.js +111 -0
  411. package/dist/dist/editor/control-center/setup-steps/SettingsSetupStep.js.map +1 -0
  412. package/dist/dist/editor/control-center/setup-steps/SetupOverview.d.ts +14 -0
  413. package/dist/dist/editor/control-center/setup-steps/SetupOverview.js +38 -0
  414. package/dist/dist/editor/control-center/setup-steps/SetupOverview.js.map +1 -0
  415. package/dist/dist/editor/editor-warnings/ItemLocked.d.ts +2 -0
  416. package/dist/dist/editor/editor-warnings/ItemLocked.js +38 -0
  417. package/dist/dist/editor/editor-warnings/ItemLocked.js.map +1 -0
  418. package/dist/dist/editor/editor-warnings/NoLanguageWriteAccess.d.ts +2 -0
  419. package/dist/dist/editor/editor-warnings/NoLanguageWriteAccess.js +14 -0
  420. package/dist/dist/editor/editor-warnings/NoLanguageWriteAccess.js.map +1 -0
  421. package/dist/dist/editor/editor-warnings/NoWorkflowWriteAccess.d.ts +2 -0
  422. package/dist/dist/editor/editor-warnings/NoWorkflowWriteAccess.js +14 -0
  423. package/dist/dist/editor/editor-warnings/NoWorkflowWriteAccess.js.map +1 -0
  424. package/dist/dist/editor/editor-warnings/NoWriteAccess.d.ts +2 -0
  425. package/dist/dist/editor/editor-warnings/NoWriteAccess.js +14 -0
  426. package/dist/dist/editor/editor-warnings/NoWriteAccess.js.map +1 -0
  427. package/dist/dist/editor/editor-warnings/ValidationErrors.d.ts +2 -0
  428. package/dist/dist/editor/editor-warnings/ValidationErrors.js +28 -0
  429. package/dist/dist/editor/editor-warnings/ValidationErrors.js.map +1 -0
  430. package/dist/dist/editor/field-types/AttachmentEditor.d.ts +9 -0
  431. package/dist/dist/editor/field-types/AttachmentEditor.js +68 -0
  432. package/dist/dist/editor/field-types/AttachmentEditor.js.map +1 -0
  433. package/dist/dist/editor/field-types/CheckboxEditor.d.ts +5 -0
  434. package/dist/dist/editor/field-types/CheckboxEditor.js +30 -0
  435. package/dist/dist/editor/field-types/CheckboxEditor.js.map +1 -0
  436. package/dist/dist/editor/field-types/DateFieldEditor.d.ts +5 -0
  437. package/dist/dist/editor/field-types/DateFieldEditor.js +93 -0
  438. package/dist/dist/editor/field-types/DateFieldEditor.js.map +1 -0
  439. package/dist/dist/editor/field-types/DateTimeFieldEditor.d.ts +5 -0
  440. package/dist/dist/editor/field-types/DateTimeFieldEditor.js +151 -0
  441. package/dist/dist/editor/field-types/DateTimeFieldEditor.js.map +1 -0
  442. package/dist/dist/editor/field-types/DropLinkEditor.d.ts +5 -0
  443. package/dist/dist/editor/field-types/DropLinkEditor.js +42 -0
  444. package/dist/dist/editor/field-types/DropLinkEditor.js.map +1 -0
  445. package/dist/dist/editor/field-types/DropListEditor.d.ts +5 -0
  446. package/dist/dist/editor/field-types/DropListEditor.js +46 -0
  447. package/dist/dist/editor/field-types/DropListEditor.js.map +1 -0
  448. package/dist/dist/editor/field-types/ImageFieldEditor.d.ts +5 -0
  449. package/dist/dist/editor/field-types/ImageFieldEditor.js +34 -0
  450. package/dist/dist/editor/field-types/ImageFieldEditor.js.map +1 -0
  451. package/dist/dist/editor/field-types/InternalLinkFieldEditor.d.ts +5 -0
  452. package/dist/dist/editor/field-types/InternalLinkFieldEditor.js +172 -0
  453. package/dist/dist/editor/field-types/InternalLinkFieldEditor.js.map +1 -0
  454. package/dist/dist/editor/field-types/LinkFieldEditor.d.ts +5 -0
  455. package/dist/dist/editor/field-types/LinkFieldEditor.js +62 -0
  456. package/dist/dist/editor/field-types/LinkFieldEditor.js.map +1 -0
  457. package/dist/dist/editor/field-types/MultiLineText.d.ts +7 -0
  458. package/dist/dist/editor/field-types/MultiLineText.js +48 -0
  459. package/dist/dist/editor/field-types/MultiLineText.js.map +1 -0
  460. package/dist/dist/editor/field-types/NameValueListEditor.d.ts +7 -0
  461. package/dist/dist/editor/field-types/NameValueListEditor.js +101 -0
  462. package/dist/dist/editor/field-types/NameValueListEditor.js.map +1 -0
  463. package/dist/dist/editor/field-types/PictureFieldEditor.d.ts +5 -0
  464. package/dist/dist/editor/field-types/PictureFieldEditor.js +58 -0
  465. package/dist/dist/editor/field-types/PictureFieldEditor.js.map +1 -0
  466. package/dist/dist/editor/field-types/RawEditor.d.ts +6 -0
  467. package/dist/dist/editor/field-types/RawEditor.js +31 -0
  468. package/dist/dist/editor/field-types/RawEditor.js.map +1 -0
  469. package/dist/dist/editor/field-types/ReactQuill.d.ts +125 -0
  470. package/dist/dist/editor/field-types/ReactQuill.js +385 -0
  471. package/dist/dist/editor/field-types/ReactQuill.js.map +1 -0
  472. package/dist/dist/editor/field-types/RichTextEditor.d.ts +7 -0
  473. package/dist/dist/editor/field-types/RichTextEditor.js +21 -0
  474. package/dist/dist/editor/field-types/RichTextEditor.js.map +1 -0
  475. package/dist/dist/editor/field-types/RichTextEditorComponent.d.ts +8 -0
  476. package/dist/dist/editor/field-types/RichTextEditorComponent.js +88 -0
  477. package/dist/dist/editor/field-types/RichTextEditorComponent.js.map +1 -0
  478. package/dist/dist/editor/field-types/SingleLineText.d.ts +7 -0
  479. package/dist/dist/editor/field-types/SingleLineText.js +113 -0
  480. package/dist/dist/editor/field-types/SingleLineText.js.map +1 -0
  481. package/dist/dist/editor/field-types/TreeListEditor.d.ts +5 -0
  482. package/dist/dist/editor/field-types/TreeListEditor.js +387 -0
  483. package/dist/dist/editor/field-types/TreeListEditor.js.map +1 -0
  484. package/dist/dist/editor/field-types/richtext/components/EditorDropdown.css +82 -0
  485. package/dist/dist/editor/field-types/richtext/components/EditorDropdown.d.ts +11 -0
  486. package/dist/dist/editor/field-types/richtext/components/EditorDropdown.js +83 -0
  487. package/dist/dist/editor/field-types/richtext/components/EditorDropdown.js.map +1 -0
  488. package/dist/dist/editor/field-types/richtext/components/ReactSlate.css +208 -0
  489. package/dist/dist/editor/field-types/richtext/components/ReactSlate.d.ts +5 -0
  490. package/dist/dist/editor/field-types/richtext/components/ReactSlate.js +607 -0
  491. package/dist/dist/editor/field-types/richtext/components/ReactSlate.js.map +1 -0
  492. package/dist/dist/editor/field-types/richtext/components/SimpleDropdown.d.ts +18 -0
  493. package/dist/dist/editor/field-types/richtext/components/SimpleDropdown.js +71 -0
  494. package/dist/dist/editor/field-types/richtext/components/SimpleDropdown.js.map +1 -0
  495. package/dist/dist/editor/field-types/richtext/components/SimpleRichTextEditor.css +325 -0
  496. package/dist/dist/editor/field-types/richtext/components/SimpleRichTextEditor.d.ts +5 -0
  497. package/dist/dist/editor/field-types/richtext/components/SimpleRichTextEditor.js +359 -0
  498. package/dist/dist/editor/field-types/richtext/components/SimpleRichTextEditor.js.map +1 -0
  499. package/dist/dist/editor/field-types/richtext/components/SimpleToolbar.d.ts +16 -0
  500. package/dist/dist/editor/field-types/richtext/components/SimpleToolbar.js +181 -0
  501. package/dist/dist/editor/field-types/richtext/components/SimpleToolbar.js.map +1 -0
  502. package/dist/dist/editor/field-types/richtext/components/SimpleToolbarButton.d.ts +9 -0
  503. package/dist/dist/editor/field-types/richtext/components/SimpleToolbarButton.js +14 -0
  504. package/dist/dist/editor/field-types/richtext/components/SimpleToolbarButton.js.map +1 -0
  505. package/dist/dist/editor/field-types/richtext/components/ToolbarButton.d.ts +3 -0
  506. package/dist/dist/editor/field-types/richtext/components/ToolbarButton.js +6 -0
  507. package/dist/dist/editor/field-types/richtext/components/ToolbarButton.js.map +1 -0
  508. package/dist/dist/editor/field-types/richtext/config/pluginFactory.d.ts +19 -0
  509. package/dist/dist/editor/field-types/richtext/config/pluginFactory.js +17 -0
  510. package/dist/dist/editor/field-types/richtext/config/pluginFactory.js.map +1 -0
  511. package/dist/dist/editor/field-types/richtext/contextMenuFactory.d.ts +4 -0
  512. package/dist/dist/editor/field-types/richtext/contextMenuFactory.js +201 -0
  513. package/dist/dist/editor/field-types/richtext/contextMenuFactory.js.map +1 -0
  514. package/dist/dist/editor/field-types/richtext/hooks/useProfileCache.d.ts +68 -0
  515. package/dist/dist/editor/field-types/richtext/hooks/useProfileCache.js +214 -0
  516. package/dist/dist/editor/field-types/richtext/hooks/useProfileCache.js.map +1 -0
  517. package/dist/dist/editor/field-types/richtext/hooks/useRichTextProfile.d.ts +25 -0
  518. package/dist/dist/editor/field-types/richtext/hooks/useRichTextProfile.js +64 -0
  519. package/dist/dist/editor/field-types/richtext/hooks/useRichTextProfile.js.map +1 -0
  520. package/dist/dist/editor/field-types/richtext/index.d.ts +6 -0
  521. package/dist/dist/editor/field-types/richtext/index.js +7 -0
  522. package/dist/dist/editor/field-types/richtext/index.js.map +1 -0
  523. package/dist/dist/editor/field-types/richtext/types.d.ts +288 -0
  524. package/dist/dist/editor/field-types/richtext/types.js +107 -0
  525. package/dist/dist/editor/field-types/richtext/types.js.map +1 -0
  526. package/dist/dist/editor/field-types/richtext/utils/conversion.d.ts +7 -0
  527. package/dist/dist/editor/field-types/richtext/utils/conversion.js +762 -0
  528. package/dist/dist/editor/field-types/richtext/utils/conversion.js.map +1 -0
  529. package/dist/dist/editor/field-types/richtext/utils/plugins.d.ts +170 -0
  530. package/dist/dist/editor/field-types/richtext/utils/plugins.js +490 -0
  531. package/dist/dist/editor/field-types/richtext/utils/plugins.js.map +1 -0
  532. package/dist/dist/editor/field-types/richtext/utils/profileMapper.d.ts +38 -0
  533. package/dist/dist/editor/field-types/richtext/utils/profileMapper.js +386 -0
  534. package/dist/dist/editor/field-types/richtext/utils/profileMapper.js.map +1 -0
  535. package/dist/dist/editor/field-types/richtext/utils/profileServiceCache.d.ts +37 -0
  536. package/dist/dist/editor/field-types/richtext/utils/profileServiceCache.js +119 -0
  537. package/dist/dist/editor/field-types/richtext/utils/profileServiceCache.js.map +1 -0
  538. package/dist/dist/editor/fieldTypes.d.ts +129 -0
  539. package/dist/dist/editor/fieldTypes.js +2 -0
  540. package/dist/dist/editor/fieldTypes.js.map +1 -0
  541. package/dist/dist/editor/hooks/useEditorSettings.d.ts +17 -0
  542. package/dist/dist/editor/hooks/useEditorSettings.js +61 -0
  543. package/dist/dist/editor/hooks/useEditorSettings.js.map +1 -0
  544. package/dist/dist/editor/hooks/useParheliaSettings.d.ts +17 -0
  545. package/dist/dist/editor/hooks/useParheliaSettings.js +61 -0
  546. package/dist/dist/editor/hooks/useParheliaSettings.js.map +1 -0
  547. package/dist/dist/editor/media-selector/AiImageSearch.d.ts +4 -0
  548. package/dist/dist/editor/media-selector/AiImageSearch.js +164 -0
  549. package/dist/dist/editor/media-selector/AiImageSearch.js.map +1 -0
  550. package/dist/dist/editor/media-selector/AiImageSearchPrompt.d.ts +3 -0
  551. package/dist/dist/editor/media-selector/AiImageSearchPrompt.js +57 -0
  552. package/dist/dist/editor/media-selector/AiImageSearchPrompt.js.map +1 -0
  553. package/dist/dist/editor/media-selector/MediaFolderBrowser.d.ts +5 -0
  554. package/dist/dist/editor/media-selector/MediaFolderBrowser.js +182 -0
  555. package/dist/dist/editor/media-selector/MediaFolderBrowser.js.map +1 -0
  556. package/dist/dist/editor/media-selector/MediaSelector.d.ts +9 -0
  557. package/dist/dist/editor/media-selector/MediaSelector.js +8 -0
  558. package/dist/dist/editor/media-selector/MediaSelector.js.map +1 -0
  559. package/dist/dist/editor/media-selector/Preview.d.ts +4 -0
  560. package/dist/dist/editor/media-selector/Preview.js +19 -0
  561. package/dist/dist/editor/media-selector/Preview.js.map +1 -0
  562. package/dist/dist/editor/media-selector/Thumbnails.d.ts +8 -0
  563. package/dist/dist/editor/media-selector/Thumbnails.js +10 -0
  564. package/dist/dist/editor/media-selector/Thumbnails.js.map +1 -0
  565. package/dist/dist/editor/media-selector/TreeSelector.d.ts +7 -0
  566. package/dist/dist/editor/media-selector/TreeSelector.js +183 -0
  567. package/dist/dist/editor/media-selector/TreeSelector.js.map +1 -0
  568. package/dist/dist/editor/media-selector/UploadZone.d.ts +4 -0
  569. package/dist/dist/editor/media-selector/UploadZone.js +81 -0
  570. package/dist/dist/editor/media-selector/UploadZone.js.map +1 -0
  571. package/dist/dist/editor/media-selector/index.d.ts +8 -0
  572. package/dist/dist/editor/media-selector/index.js +9 -0
  573. package/dist/dist/editor/media-selector/index.js.map +1 -0
  574. package/dist/dist/editor/menubar/ActiveUsers.d.ts +1 -0
  575. package/dist/dist/editor/menubar/ActiveUsers.js +120 -0
  576. package/dist/dist/editor/menubar/ActiveUsers.js.map +1 -0
  577. package/dist/dist/editor/menubar/ApproveAndPublish.d.ts +1 -0
  578. package/dist/dist/editor/menubar/ApproveAndPublish.js +13 -0
  579. package/dist/dist/editor/menubar/ApproveAndPublish.js.map +1 -0
  580. package/dist/dist/editor/menubar/FavoritesControls.d.ts +8 -0
  581. package/dist/dist/editor/menubar/FavoritesControls.js +217 -0
  582. package/dist/dist/editor/menubar/FavoritesControls.js.map +1 -0
  583. package/dist/dist/editor/menubar/GenericToolbar.d.ts +11 -0
  584. package/dist/dist/editor/menubar/GenericToolbar.js +10 -0
  585. package/dist/dist/editor/menubar/GenericToolbar.js.map +1 -0
  586. package/dist/dist/editor/menubar/ItemActionsMenu.d.ts +3 -0
  587. package/dist/dist/editor/menubar/ItemActionsMenu.js +23 -0
  588. package/dist/dist/editor/menubar/ItemActionsMenu.js.map +1 -0
  589. package/dist/dist/editor/menubar/ItemLanguageVersion.d.ts +1 -0
  590. package/dist/dist/editor/menubar/ItemLanguageVersion.js +54 -0
  591. package/dist/dist/editor/menubar/ItemLanguageVersion.js.map +1 -0
  592. package/dist/dist/editor/menubar/ItemToolbar.d.ts +1 -0
  593. package/dist/dist/editor/menubar/ItemToolbar.js +11 -0
  594. package/dist/dist/editor/menubar/ItemToolbar.js.map +1 -0
  595. package/dist/dist/editor/menubar/NavButtons.d.ts +1 -0
  596. package/dist/dist/editor/menubar/NavButtons.js +40 -0
  597. package/dist/dist/editor/menubar/NavButtons.js.map +1 -0
  598. package/dist/dist/editor/menubar/PageSelector.d.ts +4 -0
  599. package/dist/dist/editor/menubar/PageSelector.js +152 -0
  600. package/dist/dist/editor/menubar/PageSelector.js.map +1 -0
  601. package/dist/dist/editor/menubar/Separator.d.ts +3 -0
  602. package/dist/dist/editor/menubar/Separator.js +6 -0
  603. package/dist/dist/editor/menubar/Separator.js.map +1 -0
  604. package/dist/dist/editor/menubar/SiteInfo.d.ts +1 -0
  605. package/dist/dist/editor/menubar/SiteInfo.js +24 -0
  606. package/dist/dist/editor/menubar/SiteInfo.js.map +1 -0
  607. package/dist/dist/editor/menubar/ToolbarFactory.d.ts +2 -0
  608. package/dist/dist/editor/menubar/ToolbarFactory.js +55 -0
  609. package/dist/dist/editor/menubar/ToolbarFactory.js.map +1 -0
  610. package/dist/dist/editor/menubar/User.d.ts +4 -0
  611. package/dist/dist/editor/menubar/User.js +18 -0
  612. package/dist/dist/editor/menubar/User.js.map +1 -0
  613. package/dist/dist/editor/menubar/VersionSelector.d.ts +10 -0
  614. package/dist/dist/editor/menubar/VersionSelector.js +53 -0
  615. package/dist/dist/editor/menubar/VersionSelector.js.map +1 -0
  616. package/dist/dist/editor/menubar/WorkflowButton.d.ts +1 -0
  617. package/dist/dist/editor/menubar/WorkflowButton.js +93 -0
  618. package/dist/dist/editor/menubar/WorkflowButton.js.map +1 -0
  619. package/dist/dist/editor/menubar/toolbar-sections/CompareControls.d.ts +1 -0
  620. package/dist/dist/editor/menubar/toolbar-sections/CompareControls.js +11 -0
  621. package/dist/dist/editor/menubar/toolbar-sections/CompareControls.js.map +1 -0
  622. package/dist/dist/editor/menubar/toolbar-sections/EditControls.d.ts +7 -0
  623. package/dist/dist/editor/menubar/toolbar-sections/EditControls.js +15 -0
  624. package/dist/dist/editor/menubar/toolbar-sections/EditControls.js.map +1 -0
  625. package/dist/dist/editor/menubar/toolbar-sections/InsertControls.d.ts +1 -0
  626. package/dist/dist/editor/menubar/toolbar-sections/InsertControls.js +15 -0
  627. package/dist/dist/editor/menubar/toolbar-sections/InsertControls.js.map +1 -0
  628. package/dist/dist/editor/menubar/toolbar-sections/ReviewCommands.d.ts +1 -0
  629. package/dist/dist/editor/menubar/toolbar-sections/ReviewCommands.js +41 -0
  630. package/dist/dist/editor/menubar/toolbar-sections/ReviewCommands.js.map +1 -0
  631. package/dist/dist/editor/menubar/toolbar-sections/UtilityControls.d.ts +1 -0
  632. package/dist/dist/editor/menubar/toolbar-sections/UtilityControls.js +17 -0
  633. package/dist/dist/editor/menubar/toolbar-sections/UtilityControls.js.map +1 -0
  634. package/dist/dist/editor/menubar/toolbar-sections/ViewportControls.d.ts +1 -0
  635. package/dist/dist/editor/menubar/toolbar-sections/ViewportControls.js +21 -0
  636. package/dist/dist/editor/menubar/toolbar-sections/ViewportControls.js.map +1 -0
  637. package/dist/dist/editor/menubar/toolbar-sections/index.d.ts +6 -0
  638. package/dist/dist/editor/menubar/toolbar-sections/index.js +7 -0
  639. package/dist/dist/editor/menubar/toolbar-sections/index.js.map +1 -0
  640. package/dist/dist/editor/page-editor-chrome/CommentHighlighting.d.ts +6 -0
  641. package/dist/dist/editor/page-editor-chrome/CommentHighlighting.js +270 -0
  642. package/dist/dist/editor/page-editor-chrome/CommentHighlighting.js.map +1 -0
  643. package/dist/dist/editor/page-editor-chrome/CommentHighlightings.d.ts +4 -0
  644. package/dist/dist/editor/page-editor-chrome/CommentHighlightings.js +15 -0
  645. package/dist/dist/editor/page-editor-chrome/CommentHighlightings.js.map +1 -0
  646. package/dist/dist/editor/page-editor-chrome/FieldActionIndicator.d.ts +4 -0
  647. package/dist/dist/editor/page-editor-chrome/FieldActionIndicator.js +35 -0
  648. package/dist/dist/editor/page-editor-chrome/FieldActionIndicator.js.map +1 -0
  649. package/dist/dist/editor/page-editor-chrome/FieldActionIndicators.d.ts +1 -0
  650. package/dist/dist/editor/page-editor-chrome/FieldActionIndicators.js +13 -0
  651. package/dist/dist/editor/page-editor-chrome/FieldActionIndicators.js.map +1 -0
  652. package/dist/dist/editor/page-editor-chrome/FieldEditedIndicator.d.ts +8 -0
  653. package/dist/dist/editor/page-editor-chrome/FieldEditedIndicator.js +26 -0
  654. package/dist/dist/editor/page-editor-chrome/FieldEditedIndicator.js.map +1 -0
  655. package/dist/dist/editor/page-editor-chrome/FieldEditedIndicators.d.ts +6 -0
  656. package/dist/dist/editor/page-editor-chrome/FieldEditedIndicators.js +14 -0
  657. package/dist/dist/editor/page-editor-chrome/FieldEditedIndicators.js.map +1 -0
  658. package/dist/dist/editor/page-editor-chrome/FrameMenu.d.ts +7 -0
  659. package/dist/dist/editor/page-editor-chrome/FrameMenu.js +346 -0
  660. package/dist/dist/editor/page-editor-chrome/FrameMenu.js.map +1 -0
  661. package/dist/dist/editor/page-editor-chrome/FrameMenus.d.ts +5 -0
  662. package/dist/dist/editor/page-editor-chrome/FrameMenus.js +22 -0
  663. package/dist/dist/editor/page-editor-chrome/FrameMenus.js.map +1 -0
  664. package/dist/dist/editor/page-editor-chrome/InlineEditor.d.ts +5 -0
  665. package/dist/dist/editor/page-editor-chrome/InlineEditor.js +704 -0
  666. package/dist/dist/editor/page-editor-chrome/InlineEditor.js.map +1 -0
  667. package/dist/dist/editor/page-editor-chrome/LockedFieldIndicator.d.ts +1 -0
  668. package/dist/dist/editor/page-editor-chrome/LockedFieldIndicator.js +33 -0
  669. package/dist/dist/editor/page-editor-chrome/LockedFieldIndicator.js.map +1 -0
  670. package/dist/dist/editor/page-editor-chrome/NoLayout.d.ts +1 -0
  671. package/dist/dist/editor/page-editor-chrome/NoLayout.js +19 -0
  672. package/dist/dist/editor/page-editor-chrome/NoLayout.js.map +1 -0
  673. package/dist/dist/editor/page-editor-chrome/PageEditorChrome.d.ts +6 -0
  674. package/dist/dist/editor/page-editor-chrome/PageEditorChrome.js +64 -0
  675. package/dist/dist/editor/page-editor-chrome/PageEditorChrome.js.map +1 -0
  676. package/dist/dist/editor/page-editor-chrome/PictureEditorOverlay.d.ts +1 -0
  677. package/dist/dist/editor/page-editor-chrome/PictureEditorOverlay.js +190 -0
  678. package/dist/dist/editor/page-editor-chrome/PictureEditorOverlay.js.map +1 -0
  679. package/dist/dist/editor/page-editor-chrome/PlaceholderDropZone.d.ts +18 -0
  680. package/dist/dist/editor/page-editor-chrome/PlaceholderDropZone.js +122 -0
  681. package/dist/dist/editor/page-editor-chrome/PlaceholderDropZone.js.map +1 -0
  682. package/dist/dist/editor/page-editor-chrome/PlaceholderDropZones.d.ts +5 -0
  683. package/dist/dist/editor/page-editor-chrome/PlaceholderDropZones.js +289 -0
  684. package/dist/dist/editor/page-editor-chrome/PlaceholderDropZones.js.map +1 -0
  685. package/dist/dist/editor/page-editor-chrome/SuggestionHighlighting.d.ts +6 -0
  686. package/dist/dist/editor/page-editor-chrome/SuggestionHighlighting.js +224 -0
  687. package/dist/dist/editor/page-editor-chrome/SuggestionHighlighting.js.map +1 -0
  688. package/dist/dist/editor/page-editor-chrome/SuggestionHighlightings.d.ts +4 -0
  689. package/dist/dist/editor/page-editor-chrome/SuggestionHighlightings.js +16 -0
  690. package/dist/dist/editor/page-editor-chrome/SuggestionHighlightings.js.map +1 -0
  691. package/dist/dist/editor/page-editor-chrome/useInlineAICompletion.d.ts +7 -0
  692. package/dist/dist/editor/page-editor-chrome/useInlineAICompletion.js +699 -0
  693. package/dist/dist/editor/page-editor-chrome/useInlineAICompletion.js.map +1 -0
  694. package/dist/dist/editor/page-viewer/DeviceToolbar.d.ts +6 -0
  695. package/dist/dist/editor/page-viewer/DeviceToolbar.js +21 -0
  696. package/dist/dist/editor/page-viewer/DeviceToolbar.js.map +1 -0
  697. package/dist/dist/editor/page-viewer/EditorForm.d.ts +8 -0
  698. package/dist/dist/editor/page-viewer/EditorForm.js +264 -0
  699. package/dist/dist/editor/page-viewer/EditorForm.js.map +1 -0
  700. package/dist/dist/editor/page-viewer/EditorFormPopup.d.ts +11 -0
  701. package/dist/dist/editor/page-viewer/EditorFormPopup.js +41 -0
  702. package/dist/dist/editor/page-viewer/EditorFormPopup.js.map +1 -0
  703. package/dist/dist/editor/page-viewer/MiniMap.d.ts +9 -0
  704. package/dist/dist/editor/page-viewer/MiniMap.js +234 -0
  705. package/dist/dist/editor/page-viewer/MiniMap.js.map +1 -0
  706. package/dist/dist/editor/page-viewer/PageViewer.d.ts +10 -0
  707. package/dist/dist/editor/page-viewer/PageViewer.js +67 -0
  708. package/dist/dist/editor/page-viewer/PageViewer.js.map +1 -0
  709. package/dist/dist/editor/page-viewer/PageViewerFrame.d.ts +11 -0
  710. package/dist/dist/editor/page-viewer/PageViewerFrame.js +846 -0
  711. package/dist/dist/editor/page-viewer/PageViewerFrame.js.map +1 -0
  712. package/dist/dist/editor/page-viewer/pageModelSkeletonBuilder.d.ts +3 -0
  713. package/dist/dist/editor/page-viewer/pageModelSkeletonBuilder.js +349 -0
  714. package/dist/dist/editor/page-viewer/pageModelSkeletonBuilder.js.map +1 -0
  715. package/dist/dist/editor/page-viewer/pageViewContext.d.ts +40 -0
  716. package/dist/dist/editor/page-viewer/pageViewContext.js +155 -0
  717. package/dist/dist/editor/page-viewer/pageViewContext.js.map +1 -0
  718. package/dist/dist/editor/pageModel.d.ts +223 -0
  719. package/dist/dist/editor/pageModel.js +2 -0
  720. package/dist/dist/editor/pageModel.js.map +1 -0
  721. package/dist/dist/editor/picture-shared.d.ts +16 -0
  722. package/dist/dist/editor/picture-shared.js +25 -0
  723. package/dist/dist/editor/picture-shared.js.map +1 -0
  724. package/dist/dist/editor/reviews/Comment.d.ts +8 -0
  725. package/dist/dist/editor/reviews/Comment.js +162 -0
  726. package/dist/dist/editor/reviews/Comment.js.map +1 -0
  727. package/dist/dist/editor/reviews/CommentDisplayPopover.d.ts +9 -0
  728. package/dist/dist/editor/reviews/CommentDisplayPopover.js +104 -0
  729. package/dist/dist/editor/reviews/CommentDisplayPopover.js.map +1 -0
  730. package/dist/dist/editor/reviews/CommentEditor.d.ts +20 -0
  731. package/dist/dist/editor/reviews/CommentEditor.js +57 -0
  732. package/dist/dist/editor/reviews/CommentEditor.js.map +1 -0
  733. package/dist/dist/editor/reviews/CommentPopover.d.ts +22 -0
  734. package/dist/dist/editor/reviews/CommentPopover.js +145 -0
  735. package/dist/dist/editor/reviews/CommentPopover.js.map +1 -0
  736. package/dist/dist/editor/reviews/CommentView.d.ts +21 -0
  737. package/dist/dist/editor/reviews/CommentView.js +52 -0
  738. package/dist/dist/editor/reviews/CommentView.js.map +1 -0
  739. package/dist/dist/editor/reviews/Comments.d.ts +3 -0
  740. package/dist/dist/editor/reviews/Comments.js +118 -0
  741. package/dist/dist/editor/reviews/Comments.js.map +1 -0
  742. package/dist/dist/editor/reviews/CreateReviewDialog.d.ts +9 -0
  743. package/dist/dist/editor/reviews/CreateReviewDialog.js +454 -0
  744. package/dist/dist/editor/reviews/CreateReviewDialog.js.map +1 -0
  745. package/dist/dist/editor/reviews/DecisionsMatrix.d.ts +29 -0
  746. package/dist/dist/editor/reviews/DecisionsMatrix.js +739 -0
  747. package/dist/dist/editor/reviews/DecisionsMatrix.js.map +1 -0
  748. package/dist/dist/editor/reviews/DiffView.d.ts +17 -0
  749. package/dist/dist/editor/reviews/DiffView.js +57 -0
  750. package/dist/dist/editor/reviews/DiffView.js.map +1 -0
  751. package/dist/dist/editor/reviews/EditReviewSettingsDialog.d.ts +20 -0
  752. package/dist/dist/editor/reviews/EditReviewSettingsDialog.js +208 -0
  753. package/dist/dist/editor/reviews/EditReviewSettingsDialog.js.map +1 -0
  754. package/dist/dist/editor/reviews/ItemTreeSelector.d.ts +9 -0
  755. package/dist/dist/editor/reviews/ItemTreeSelector.js +43 -0
  756. package/dist/dist/editor/reviews/ItemTreeSelector.js.map +1 -0
  757. package/dist/dist/editor/reviews/MultiReviewManager.d.ts +1 -0
  758. package/dist/dist/editor/reviews/MultiReviewManager.js +50 -0
  759. package/dist/dist/editor/reviews/MultiReviewManager.js.map +1 -0
  760. package/dist/dist/editor/reviews/PagesPanel.d.ts +21 -0
  761. package/dist/dist/editor/reviews/PagesPanel.js +124 -0
  762. package/dist/dist/editor/reviews/PagesPanel.js.map +1 -0
  763. package/dist/dist/editor/reviews/PreconfiguredReviewerSelector.d.ts +9 -0
  764. package/dist/dist/editor/reviews/PreconfiguredReviewerSelector.js +55 -0
  765. package/dist/dist/editor/reviews/PreconfiguredReviewerSelector.js.map +1 -0
  766. package/dist/dist/editor/reviews/PreviewInfo.d.ts +1 -0
  767. package/dist/dist/editor/reviews/PreviewInfo.js +12 -0
  768. package/dist/dist/editor/reviews/PreviewInfo.js.map +1 -0
  769. package/dist/dist/editor/reviews/ReviewDetail.d.ts +8 -0
  770. package/dist/dist/editor/reviews/ReviewDetail.js +189 -0
  771. package/dist/dist/editor/reviews/ReviewDetail.js.map +1 -0
  772. package/dist/dist/editor/reviews/ReviewersPanel.d.ts +14 -0
  773. package/dist/dist/editor/reviews/ReviewersPanel.js +216 -0
  774. package/dist/dist/editor/reviews/ReviewersPanel.js.map +1 -0
  775. package/dist/dist/editor/reviews/Reviews.d.ts +1 -0
  776. package/dist/dist/editor/reviews/Reviews.js +6 -0
  777. package/dist/dist/editor/reviews/Reviews.js.map +1 -0
  778. package/dist/dist/editor/reviews/ReviewsList.d.ts +11 -0
  779. package/dist/dist/editor/reviews/ReviewsList.js +134 -0
  780. package/dist/dist/editor/reviews/ReviewsList.js.map +1 -0
  781. package/dist/dist/editor/reviews/SuggestedEdit.d.ts +4 -0
  782. package/dist/dist/editor/reviews/SuggestedEdit.js +200 -0
  783. package/dist/dist/editor/reviews/SuggestedEdit.js.map +1 -0
  784. package/dist/dist/editor/reviews/SuggestionDisplayPopover.d.ts +9 -0
  785. package/dist/dist/editor/reviews/SuggestionDisplayPopover.js +204 -0
  786. package/dist/dist/editor/reviews/SuggestionDisplayPopover.js.map +1 -0
  787. package/dist/dist/editor/reviews/commentAi.d.ts +7 -0
  788. package/dist/dist/editor/reviews/commentAi.js +100 -0
  789. package/dist/dist/editor/reviews/commentAi.js.map +1 -0
  790. package/dist/dist/editor/reviews/reviewCommands.d.ts +3 -0
  791. package/dist/dist/editor/reviews/reviewCommands.js +38 -0
  792. package/dist/dist/editor/reviews/reviewCommands.js.map +1 -0
  793. package/dist/dist/editor/reviews/useMultiReview.d.ts +42 -0
  794. package/dist/dist/editor/reviews/useMultiReview.js +377 -0
  795. package/dist/dist/editor/reviews/useMultiReview.js.map +1 -0
  796. package/dist/dist/editor/reviews/useReviews.d.ts +12 -0
  797. package/dist/dist/editor/reviews/useReviews.js +43 -0
  798. package/dist/dist/editor/reviews/useReviews.js.map +1 -0
  799. package/dist/dist/editor/services/agentService.d.ts +368 -0
  800. package/dist/dist/editor/services/agentService.js +721 -0
  801. package/dist/dist/editor/services/agentService.js.map +1 -0
  802. package/dist/dist/editor/services/aiService.d.ts +111 -0
  803. package/dist/dist/editor/services/aiService.js +294 -0
  804. package/dist/dist/editor/services/aiService.js.map +1 -0
  805. package/dist/dist/editor/services/componentDesignerService.d.ts +46 -0
  806. package/dist/dist/editor/services/componentDesignerService.js +72 -0
  807. package/dist/dist/editor/services/componentDesignerService.js.map +1 -0
  808. package/dist/dist/editor/services/contentService.d.ts +79 -0
  809. package/dist/dist/editor/services/contentService.js +127 -0
  810. package/dist/dist/editor/services/contentService.js.map +1 -0
  811. package/dist/dist/editor/services/contextService.d.ts +26 -0
  812. package/dist/dist/editor/services/contextService.js +103 -0
  813. package/dist/dist/editor/services/contextService.js.map +1 -0
  814. package/dist/dist/editor/services/editService.d.ts +66 -0
  815. package/dist/dist/editor/services/editService.js +325 -0
  816. package/dist/dist/editor/services/editService.js.map +1 -0
  817. package/dist/dist/editor/services/favouritesService.d.ts +47 -0
  818. package/dist/dist/editor/services/favouritesService.js +28 -0
  819. package/dist/dist/editor/services/favouritesService.js.map +1 -0
  820. package/dist/dist/editor/services/iconService.d.ts +8 -0
  821. package/dist/dist/editor/services/iconService.js +6 -0
  822. package/dist/dist/editor/services/iconService.js.map +1 -0
  823. package/dist/dist/editor/services/indexService.d.ts +13 -0
  824. package/dist/dist/editor/services/indexService.js +45 -0
  825. package/dist/dist/editor/services/indexService.js.map +1 -0
  826. package/dist/dist/editor/services/reviewsService.d.ts +53 -0
  827. package/dist/dist/editor/services/reviewsService.js +130 -0
  828. package/dist/dist/editor/services/reviewsService.js.map +1 -0
  829. package/dist/dist/editor/services/searchService.d.ts +17 -0
  830. package/dist/dist/editor/services/searchService.js +25 -0
  831. package/dist/dist/editor/services/searchService.js.map +1 -0
  832. package/dist/dist/editor/services/serviceHelper.d.ts +10 -0
  833. package/dist/dist/editor/services/serviceHelper.js +118 -0
  834. package/dist/dist/editor/services/serviceHelper.js.map +1 -0
  835. package/dist/dist/editor/services/setupService.d.ts +30 -0
  836. package/dist/dist/editor/services/setupService.js +17 -0
  837. package/dist/dist/editor/services/setupService.js.map +1 -0
  838. package/dist/dist/editor/services/suggestedEditsService.d.ts +18 -0
  839. package/dist/dist/editor/services/suggestedEditsService.js +44 -0
  840. package/dist/dist/editor/services/suggestedEditsService.js.map +1 -0
  841. package/dist/dist/editor/services/systemService.d.ts +4 -0
  842. package/dist/dist/editor/services/systemService.js +11 -0
  843. package/dist/dist/editor/services/systemService.js.map +1 -0
  844. package/dist/dist/editor/services-server/api.d.ts +19 -0
  845. package/dist/dist/editor/services-server/api.js +111 -0
  846. package/dist/dist/editor/services-server/api.js.map +1 -0
  847. package/dist/dist/editor/services-server/graphQL.d.ts +29 -0
  848. package/dist/dist/editor/services-server/graphQL.js +53 -0
  849. package/dist/dist/editor/services-server/graphQL.js.map +1 -0
  850. package/dist/dist/editor/sidebar/Completions.d.ts +1 -0
  851. package/dist/dist/editor/sidebar/Completions.js +55 -0
  852. package/dist/dist/editor/sidebar/Completions.js.map +1 -0
  853. package/dist/dist/editor/sidebar/ComponentPalette.d.ts +1 -0
  854. package/dist/dist/editor/sidebar/ComponentPalette.js +86 -0
  855. package/dist/dist/editor/sidebar/ComponentPalette.js.map +1 -0
  856. package/dist/dist/editor/sidebar/ComponentTree.d.ts +1 -0
  857. package/dist/dist/editor/sidebar/ComponentTree.js +691 -0
  858. package/dist/dist/editor/sidebar/ComponentTree.js.map +1 -0
  859. package/dist/dist/editor/sidebar/Debug.d.ts +1 -0
  860. package/dist/dist/editor/sidebar/Debug.js +71 -0
  861. package/dist/dist/editor/sidebar/Debug.js.map +1 -0
  862. package/dist/dist/editor/sidebar/DictionaryEditor.d.ts +1 -0
  863. package/dist/dist/editor/sidebar/DictionaryEditor.js +158 -0
  864. package/dist/dist/editor/sidebar/DictionaryEditor.js.map +1 -0
  865. package/dist/dist/editor/sidebar/Divider.d.ts +6 -0
  866. package/dist/dist/editor/sidebar/Divider.js +6 -0
  867. package/dist/dist/editor/sidebar/Divider.js.map +1 -0
  868. package/dist/dist/editor/sidebar/EditHistory.d.ts +1 -0
  869. package/dist/dist/editor/sidebar/EditHistory.js +80 -0
  870. package/dist/dist/editor/sidebar/EditHistory.js.map +1 -0
  871. package/dist/dist/editor/sidebar/GraphQL.d.ts +2 -0
  872. package/dist/dist/editor/sidebar/GraphQL.js +234 -0
  873. package/dist/dist/editor/sidebar/GraphQL.js.map +1 -0
  874. package/dist/dist/editor/sidebar/Insert.d.ts +1 -0
  875. package/dist/dist/editor/sidebar/Insert.js +22 -0
  876. package/dist/dist/editor/sidebar/Insert.js.map +1 -0
  877. package/dist/dist/editor/sidebar/LeftToolbar.d.ts +1 -0
  878. package/dist/dist/editor/sidebar/LeftToolbar.js +16 -0
  879. package/dist/dist/editor/sidebar/LeftToolbar.js.map +1 -0
  880. package/dist/dist/editor/sidebar/MainContentTree.d.ts +5 -0
  881. package/dist/dist/editor/sidebar/MainContentTree.js +70 -0
  882. package/dist/dist/editor/sidebar/MainContentTree.js.map +1 -0
  883. package/dist/dist/editor/sidebar/Performance.d.ts +1 -0
  884. package/dist/dist/editor/sidebar/Performance.js +32 -0
  885. package/dist/dist/editor/sidebar/Performance.js.map +1 -0
  886. package/dist/dist/editor/sidebar/SEOInfo.d.ts +1 -0
  887. package/dist/dist/editor/sidebar/SEOInfo.js +158 -0
  888. package/dist/dist/editor/sidebar/SEOInfo.js.map +1 -0
  889. package/dist/dist/editor/sidebar/Sessions.d.ts +1 -0
  890. package/dist/dist/editor/sidebar/Sessions.js +29 -0
  891. package/dist/dist/editor/sidebar/Sessions.js.map +1 -0
  892. package/dist/dist/editor/sidebar/Sidebar.d.ts +1 -0
  893. package/dist/dist/editor/sidebar/Sidebar.js +13 -0
  894. package/dist/dist/editor/sidebar/Sidebar.js.map +1 -0
  895. package/dist/dist/editor/sidebar/SidebarView.d.ts +13 -0
  896. package/dist/dist/editor/sidebar/SidebarView.js +53 -0
  897. package/dist/dist/editor/sidebar/SidebarView.js.map +1 -0
  898. package/dist/dist/editor/sidebar/Validation.d.ts +1 -0
  899. package/dist/dist/editor/sidebar/Validation.js +51 -0
  900. package/dist/dist/editor/sidebar/Validation.js.map +1 -0
  901. package/dist/dist/editor/sidebar/ViewSelector.d.ts +4 -0
  902. package/dist/dist/editor/sidebar/ViewSelector.js +191 -0
  903. package/dist/dist/editor/sidebar/ViewSelector.js.map +1 -0
  904. package/dist/dist/editor/sidebar/Workbox.d.ts +1 -0
  905. package/dist/dist/editor/sidebar/Workbox.js +79 -0
  906. package/dist/dist/editor/sidebar/Workbox.js.map +1 -0
  907. package/dist/dist/editor/ui/CenteredMessage.d.ts +3 -0
  908. package/dist/dist/editor/ui/CenteredMessage.js +5 -0
  909. package/dist/dist/editor/ui/CenteredMessage.js.map +1 -0
  910. package/dist/dist/editor/ui/CopyMoveTargetSelectorDialog.d.ts +10 -0
  911. package/dist/dist/editor/ui/CopyMoveTargetSelectorDialog.js +38 -0
  912. package/dist/dist/editor/ui/CopyMoveTargetSelectorDialog.js.map +1 -0
  913. package/dist/dist/editor/ui/DialogButtons.d.ts +4 -0
  914. package/dist/dist/editor/ui/DialogButtons.js +6 -0
  915. package/dist/dist/editor/ui/DialogButtons.js.map +1 -0
  916. package/dist/dist/editor/ui/DragPreview.d.ts +14 -0
  917. package/dist/dist/editor/ui/DragPreview.js +33 -0
  918. package/dist/dist/editor/ui/DragPreview.js.map +1 -0
  919. package/dist/dist/editor/ui/IconSelectorDialog.d.ts +5 -0
  920. package/dist/dist/editor/ui/IconSelectorDialog.js +239 -0
  921. package/dist/dist/editor/ui/IconSelectorDialog.js.map +1 -0
  922. package/dist/dist/editor/ui/Icons.d.ts +74 -0
  923. package/dist/dist/editor/ui/Icons.js +106 -0
  924. package/dist/dist/editor/ui/Icons.js.map +1 -0
  925. package/dist/dist/editor/ui/ItemList.d.ts +16 -0
  926. package/dist/dist/editor/ui/ItemList.js +19 -0
  927. package/dist/dist/editor/ui/ItemList.js.map +1 -0
  928. package/dist/dist/editor/ui/ItemNameDialogNew.d.ts +10 -0
  929. package/dist/dist/editor/ui/ItemNameDialogNew.js +82 -0
  930. package/dist/dist/editor/ui/ItemNameDialogNew.js.map +1 -0
  931. package/dist/dist/editor/ui/ItemSearch.d.ts +25 -0
  932. package/dist/dist/editor/ui/ItemSearch.js +92 -0
  933. package/dist/dist/editor/ui/ItemSearch.js.map +1 -0
  934. package/dist/dist/editor/ui/PerfectTree.d.ts +78 -0
  935. package/dist/dist/editor/ui/PerfectTree.js +860 -0
  936. package/dist/dist/editor/ui/PerfectTree.js.map +1 -0
  937. package/dist/dist/editor/ui/Section.d.ts +4 -0
  938. package/dist/dist/editor/ui/Section.js +12 -0
  939. package/dist/dist/editor/ui/Section.js.map +1 -0
  940. package/dist/dist/editor/ui/SimpleIconButton.d.ts +14 -0
  941. package/dist/dist/editor/ui/SimpleIconButton.js +15 -0
  942. package/dist/dist/editor/ui/SimpleIconButton.js.map +1 -0
  943. package/dist/dist/editor/ui/SimpleMenu.d.ts +6 -0
  944. package/dist/dist/editor/ui/SimpleMenu.js +7 -0
  945. package/dist/dist/editor/ui/SimpleMenu.js.map +1 -0
  946. package/dist/dist/editor/ui/SimpleTable.d.ts +14 -0
  947. package/dist/dist/editor/ui/SimpleTable.js +9 -0
  948. package/dist/dist/editor/ui/SimpleTable.js.map +1 -0
  949. package/dist/dist/editor/ui/SimpleTabs.d.ts +16 -0
  950. package/dist/dist/editor/ui/SimpleTabs.js +20 -0
  951. package/dist/dist/editor/ui/SimpleTabs.js.map +1 -0
  952. package/dist/dist/editor/ui/SimpleToolbar.d.ts +3 -0
  953. package/dist/dist/editor/ui/SimpleToolbar.js +5 -0
  954. package/dist/dist/editor/ui/SimpleToolbar.js.map +1 -0
  955. package/dist/dist/editor/ui/Spinner.d.ts +4 -0
  956. package/dist/dist/editor/ui/Spinner.js +18 -0
  957. package/dist/dist/editor/ui/Spinner.js.map +1 -0
  958. package/dist/dist/editor/ui/Splitter.d.ts +22 -0
  959. package/dist/dist/editor/ui/Splitter.js +443 -0
  960. package/dist/dist/editor/ui/Splitter.js.map +1 -0
  961. package/dist/dist/editor/ui/TemplateSelectorDialog.d.ts +8 -0
  962. package/dist/dist/editor/ui/TemplateSelectorDialog.js +138 -0
  963. package/dist/dist/editor/ui/TemplateSelectorDialog.js.map +1 -0
  964. package/dist/dist/editor/ui/Toolbar.d.ts +3 -0
  965. package/dist/dist/editor/ui/Toolbar.js +5 -0
  966. package/dist/dist/editor/ui/Toolbar.js.map +1 -0
  967. package/dist/dist/editor/utils/id-helper.d.ts +1 -0
  968. package/dist/dist/editor/utils/id-helper.js +5 -0
  969. package/dist/dist/editor/utils/id-helper.js.map +1 -0
  970. package/dist/dist/editor/utils/insertOptions.d.ts +3 -0
  971. package/dist/dist/editor/utils/insertOptions.js +43 -0
  972. package/dist/dist/editor/utils/insertOptions.js.map +1 -0
  973. package/dist/dist/editor/utils/itemConverters.d.ts +3 -0
  974. package/dist/dist/editor/utils/itemConverters.js +53 -0
  975. package/dist/dist/editor/utils/itemConverters.js.map +1 -0
  976. package/dist/dist/editor/utils/itemutils.d.ts +3 -0
  977. package/dist/dist/editor/utils/itemutils.js +24 -0
  978. package/dist/dist/editor/utils/itemutils.js.map +1 -0
  979. package/dist/dist/editor/utils/jsonCleaner.d.ts +8 -0
  980. package/dist/dist/editor/utils/jsonCleaner.js +76 -0
  981. package/dist/dist/editor/utils/jsonCleaner.js.map +1 -0
  982. package/dist/dist/editor/utils/keyboardNavigation.d.ts +34 -0
  983. package/dist/dist/editor/utils/keyboardNavigation.js +237 -0
  984. package/dist/dist/editor/utils/keyboardNavigation.js.map +1 -0
  985. package/dist/dist/editor/utils/urlUtils.d.ts +9 -0
  986. package/dist/dist/editor/utils/urlUtils.js +25 -0
  987. package/dist/dist/editor/utils/urlUtils.js.map +1 -0
  988. package/dist/dist/editor/utils/useMemoDebug.d.ts +1 -0
  989. package/dist/dist/editor/utils/useMemoDebug.js +18 -0
  990. package/dist/dist/editor/utils/useMemoDebug.js.map +1 -0
  991. package/dist/dist/editor/utils.d.ts +65 -0
  992. package/dist/dist/editor/utils.js +488 -0
  993. package/dist/dist/editor/utils.js.map +1 -0
  994. package/dist/dist/editor/views/CompareView.d.ts +1 -0
  995. package/dist/dist/editor/views/CompareView.js +148 -0
  996. package/dist/dist/editor/views/CompareView.js.map +1 -0
  997. package/dist/dist/editor/views/EditView.d.ts +1 -0
  998. package/dist/dist/editor/views/EditView.js +15 -0
  999. package/dist/dist/editor/views/EditView.js.map +1 -0
  1000. package/dist/dist/editor/views/ItemEditor.d.ts +7 -0
  1001. package/dist/dist/editor/views/ItemEditor.js +29 -0
  1002. package/dist/dist/editor/views/ItemEditor.js.map +1 -0
  1003. package/dist/dist/editor/views/MediaFolderEditView.d.ts +4 -0
  1004. package/dist/dist/editor/views/MediaFolderEditView.js +40 -0
  1005. package/dist/dist/editor/views/MediaFolderEditView.js.map +1 -0
  1006. package/dist/dist/editor/views/ParheliaView.d.ts +5 -0
  1007. package/dist/dist/editor/views/ParheliaView.js +163 -0
  1008. package/dist/dist/editor/views/ParheliaView.js.map +1 -0
  1009. package/dist/dist/editor/views/SingleEditView.d.ts +9 -0
  1010. package/dist/dist/editor/views/SingleEditView.js +33 -0
  1011. package/dist/dist/editor/views/SingleEditView.js.map +1 -0
  1012. package/dist/dist/images/bg-shape-black.webp +0 -0
  1013. package/dist/dist/images/wizard-bg.png +0 -0
  1014. package/dist/dist/images/wizard-tour.png +0 -0
  1015. package/dist/dist/images/wizard.png +0 -0
  1016. package/dist/dist/index.d.ts +67 -0
  1017. package/dist/dist/index.js +57 -0
  1018. package/dist/dist/index.js.map +1 -0
  1019. package/dist/dist/lib/safelist.d.ts +1 -0
  1020. package/dist/dist/lib/safelist.js +5 -0
  1021. package/dist/dist/lib/safelist.js.map +1 -0
  1022. package/dist/dist/lib/utils.d.ts +2 -0
  1023. package/dist/dist/lib/utils.js +6 -0
  1024. package/dist/dist/lib/utils.js.map +1 -0
  1025. package/dist/dist/revision.d.ts +2 -0
  1026. package/dist/dist/revision.js +3 -0
  1027. package/dist/dist/revision.js.map +1 -0
  1028. package/dist/dist/setup/SetupWizardPage.d.ts +5 -0
  1029. package/dist/dist/setup/SetupWizardPage.js +8 -0
  1030. package/dist/dist/setup/SetupWizardPage.js.map +1 -0
  1031. package/dist/dist/setup/services/setupWizardService.d.ts +89 -0
  1032. package/dist/dist/setup/services/setupWizardService.js +92 -0
  1033. package/dist/dist/setup/services/setupWizardService.js.map +1 -0
  1034. package/dist/dist/setup/utils/modelPricing.d.ts +7 -0
  1035. package/dist/dist/setup/utils/modelPricing.js +106 -0
  1036. package/dist/dist/setup/utils/modelPricing.js.map +1 -0
  1037. package/dist/dist/setup/wizard/SetupWizard.d.ts +27 -0
  1038. package/dist/dist/setup/wizard/SetupWizard.js +92 -0
  1039. package/dist/dist/setup/wizard/SetupWizard.js.map +1 -0
  1040. package/dist/dist/setup/wizard/index.d.ts +6 -0
  1041. package/dist/dist/setup/wizard/index.js +6 -0
  1042. package/dist/dist/setup/wizard/index.js.map +1 -0
  1043. package/dist/dist/setup/wizard/steps/AgentsStep.d.ts +2 -0
  1044. package/dist/dist/setup/wizard/steps/AgentsStep.js +117 -0
  1045. package/dist/dist/setup/wizard/steps/AgentsStep.js.map +1 -0
  1046. package/dist/dist/setup/wizard/steps/EndpointsStep.d.ts +2 -0
  1047. package/dist/dist/setup/wizard/steps/EndpointsStep.js +94 -0
  1048. package/dist/dist/setup/wizard/steps/EndpointsStep.js.map +1 -0
  1049. package/dist/dist/setup/wizard/steps/ModelsStep.d.ts +2 -0
  1050. package/dist/dist/setup/wizard/steps/ModelsStep.js +287 -0
  1051. package/dist/dist/setup/wizard/steps/ModelsStep.js.map +1 -0
  1052. package/dist/dist/setup/wizard/steps/SearchStep.d.ts +2 -0
  1053. package/dist/dist/setup/wizard/steps/SearchStep.js +95 -0
  1054. package/dist/dist/setup/wizard/steps/SearchStep.js.map +1 -0
  1055. package/dist/dist/splash-screen/ModernSplashScreen.d.ts +8 -0
  1056. package/dist/dist/splash-screen/ModernSplashScreen.js +36 -0
  1057. package/dist/dist/splash-screen/ModernSplashScreen.js.map +1 -0
  1058. package/dist/dist/splash-screen/NewPage.d.ts +3 -0
  1059. package/dist/dist/splash-screen/NewPage.js +145 -0
  1060. package/dist/dist/splash-screen/NewPage.js.map +1 -0
  1061. package/dist/dist/splash-screen/OpenPage.d.ts +1 -0
  1062. package/dist/dist/splash-screen/OpenPage.js +56 -0
  1063. package/dist/dist/splash-screen/OpenPage.js.map +1 -0
  1064. package/dist/dist/splash-screen/ParheliaAssistantChat.d.ts +8 -0
  1065. package/dist/dist/splash-screen/ParheliaAssistantChat.js +169 -0
  1066. package/dist/dist/splash-screen/ParheliaAssistantChat.js.map +1 -0
  1067. package/dist/dist/splash-screen/ParheliaLogo.d.ts +5 -0
  1068. package/dist/dist/splash-screen/ParheliaLogo.js +71 -0
  1069. package/dist/dist/splash-screen/ParheliaLogo.js.map +1 -0
  1070. package/dist/dist/splash-screen/RecentAgents.d.ts +7 -0
  1071. package/dist/dist/splash-screen/RecentAgents.js +76 -0
  1072. package/dist/dist/splash-screen/RecentAgents.js.map +1 -0
  1073. package/dist/dist/splash-screen/RecentPages.d.ts +1 -0
  1074. package/dist/dist/splash-screen/RecentPages.js +59 -0
  1075. package/dist/dist/splash-screen/RecentPages.js.map +1 -0
  1076. package/dist/dist/splash-screen/SectionHeadline.d.ts +4 -0
  1077. package/dist/dist/splash-screen/SectionHeadline.js +7 -0
  1078. package/dist/dist/splash-screen/SectionHeadline.js.map +1 -0
  1079. package/dist/dist/styles.css +6035 -0
  1080. package/dist/dist/tour/Tour.d.ts +3 -0
  1081. package/dist/dist/tour/Tour.js +426 -0
  1082. package/dist/dist/tour/Tour.js.map +1 -0
  1083. package/dist/dist/tour/default-tour.d.ts +9 -0
  1084. package/dist/dist/tour/default-tour.js +302 -0
  1085. package/dist/dist/tour/default-tour.js.map +1 -0
  1086. package/dist/dist/tour/preview-tour.d.ts +2 -0
  1087. package/dist/dist/tour/preview-tour.js +93 -0
  1088. package/dist/dist/tour/preview-tour.js.map +1 -0
  1089. package/dist/dist/types.d.ts +490 -0
  1090. package/dist/dist/types.js +2 -0
  1091. package/dist/dist/types.js.map +1 -0
  1092. package/dist/editor/control-center/parhelia-setup/Overview.d.ts +1 -0
  1093. package/dist/editor/control-center/parhelia-setup/Overview.js +91 -0
  1094. package/dist/editor/control-center/parhelia-setup/Overview.js.map +1 -0
  1095. package/dist/editor/hooks/useEditorSettings.d.ts +17 -0
  1096. package/dist/editor/hooks/useEditorSettings.js +61 -0
  1097. package/dist/editor/hooks/useEditorSettings.js.map +1 -0
  1098. package/dist/editor/page-viewer/EditorFormPopup.d.ts +11 -0
  1099. package/dist/editor/page-viewer/EditorFormPopup.js +41 -0
  1100. package/dist/editor/page-viewer/EditorFormPopup.js.map +1 -0
  1101. package/dist/revision.d.ts +2 -2
  1102. package/dist/revision.js +2 -2
  1103. package/dist/revision.js.map +1 -1
  1104. package/package.json +1 -1
@@ -0,0 +1,3012 @@
1
+ import { jsx as _jsx, jsxs as _jsxs, Fragment as _Fragment } from "react/jsx-runtime";
2
+ import React, { useEffect, useState, useRef, useCallback, useLayoutEffect, ViewTransition, } from "react";
3
+ import { Send, AlertCircle, Loader2, User, Wand2, Square, Mic, MicOff, ChevronDown, ChevronUp, ListTodo, ExternalLink, } from "lucide-react";
4
+ import { DancingDots } from "./DancingDots";
5
+ import { getAgent, startAgent, updateAgentSettings, updateAgentCostLimit, updateAgentContext, cancelAgent, canonicalizeAgentMetadata, getPendingPrompts, } from "../services/agentService";
6
+ import { useEditContext, useFieldsEditContext } from "../client/editContext";
7
+ import { Textarea } from "../../components/ui/textarea";
8
+ import { Button } from "../../components/ui/button";
9
+ import { PlaceholderInput } from "../../components/ui/PlaceholderInput";
10
+ import { AiResponseMessage } from "./AiResponseMessage";
11
+ import { AgentCostDisplay } from "./AgentCostDisplay";
12
+ import { ContextInfoBar } from "./ContextInfoBar";
13
+ import { AgentDocumentList } from "./AgentDocumentList";
14
+ import { getComponentById } from "../componentTreeHelper";
15
+ import { Popover, PopoverContent, PopoverTrigger, } from "../../components/ui/popover";
16
+ import { SecretAgentIcon } from "../ui/Icons";
17
+ import { formatTime } from "../utils";
18
+ import { Tooltip, TooltipTrigger, TooltipContent, } from "../../components/ui/tooltip";
19
+ // Simple user message component
20
+ const UserMessage = ({ message }) => {
21
+ // Parse source agent name from content if it starts with "[From ...]:"
22
+ // Backend formats messages from other agents as "[From {sourceAgentName}]: {content}"
23
+ const content = message.content || "";
24
+ const fromPattern = /^\[From ([^\]]+)\]:\s*(.*)$/s;
25
+ const match = content.match(fromPattern);
26
+ let sourceAgentName;
27
+ let displayContent = content;
28
+ if (match && match[1]) {
29
+ const extractedName = match[1];
30
+ // If it says "From User", treat it as a regular user message
31
+ if (extractedName.toLowerCase() === "user") {
32
+ sourceAgentName = undefined;
33
+ displayContent = content; // Keep original content
34
+ }
35
+ else {
36
+ sourceAgentName = extractedName;
37
+ displayContent = match[2] || ""; // Remove the "[From ...]:" prefix from content
38
+ }
39
+ }
40
+ else {
41
+ // Fallback: check for source agent name in message metadata or properties
42
+ sourceAgentName =
43
+ message.sourceAgentName ||
44
+ message.metadata?.sourceAgentName ||
45
+ message.sourceAgent?.name;
46
+ }
47
+ const displayName = sourceAgentName ? `[From ${sourceAgentName}]` : "You";
48
+ return (_jsxs("div", { className: "flex gap-3 p-4", children: [_jsx("div", { className: "flex-shrink-0", children: _jsx(User, { className: "h-6 w-6 text-blue-600", strokeWidth: 1 }) }), _jsxs("div", { className: "min-w-0 flex-1 select-text", children: [_jsxs("div", { className: "mb-1 flex items-center gap-2", children: [_jsx("span", { className: "text-xs font-medium text-gray-900", children: displayName }), message.createdDate && (_jsx("span", { className: "text-xs text-gray-400", "data-testid": "user-message-timestamp", "data-timestamp": message.createdDate, children: formatTime(new Date(message.createdDate)) }))] }), _jsx("div", { className: "prose prose-sm max-w-none text-xs text-gray-700 select-text", children: displayContent })] })] }));
49
+ };
50
+ // Helper to extract todos from potentially incomplete JSON during streaming
51
+ const extractPartialTodos = (jsonText) => {
52
+ // First try to parse complete JSON
53
+ try {
54
+ const parsed = JSON.parse(jsonText);
55
+ return Array.isArray(parsed) ? parsed : parsed?.items || [];
56
+ }
57
+ catch (e) {
58
+ // If JSON is incomplete, try to extract whatever todo items we can find
59
+ const items = [];
60
+ // Look for individual todo objects in the partial JSON
61
+ // Match patterns like: { "text": "...", "done": false, "note": "..." }
62
+ // Handle various field orderings (text can be anywhere in the object)
63
+ const textPattern = /"text"\s*:\s*"([^"]+)"/g;
64
+ const textMatches = [];
65
+ let textMatch;
66
+ while ((textMatch = textPattern.exec(jsonText)) !== null) {
67
+ if (textMatch[1]) {
68
+ textMatches.push({
69
+ text: textMatch[1],
70
+ startIdx: textMatch.index,
71
+ });
72
+ }
73
+ }
74
+ // For each text field found, try to find the enclosing object
75
+ for (const { text, startIdx } of textMatches) {
76
+ // Find the opening brace before this text field
77
+ let openBrace = -1;
78
+ for (let i = startIdx - 1; i >= 0; i--) {
79
+ if (jsonText[i] === "{") {
80
+ openBrace = i;
81
+ break;
82
+ }
83
+ if (jsonText[i] === "}")
84
+ break; // Hit another object's end
85
+ }
86
+ if (openBrace === -1)
87
+ continue;
88
+ // Find the closing brace after this text field
89
+ let closeBrace = -1;
90
+ let depth = 0;
91
+ for (let i = openBrace; i < jsonText.length; i++) {
92
+ if (jsonText[i] === "{")
93
+ depth++;
94
+ if (jsonText[i] === "}") {
95
+ depth--;
96
+ if (depth === 0) {
97
+ closeBrace = i;
98
+ break;
99
+ }
100
+ }
101
+ }
102
+ // Extract the object and try to parse it
103
+ const objStr = closeBrace !== -1
104
+ ? jsonText.substring(openBrace, closeBrace + 1)
105
+ : jsonText.substring(openBrace) + "}"; // Try to close incomplete object
106
+ try {
107
+ const obj = JSON.parse(objStr);
108
+ if (obj.text) {
109
+ items.push({
110
+ text: obj.text,
111
+ done: obj.done === true,
112
+ note: obj.note || undefined,
113
+ });
114
+ }
115
+ }
116
+ catch (e) {
117
+ // Skip malformed objects
118
+ }
119
+ }
120
+ // Also try to extract from partial objects at the end
121
+ // Look for the last opening brace and try to parse up to where we have valid content
122
+ const lines = jsonText.split("\n");
123
+ for (let i = lines.length - 1; i >= 0; i--) {
124
+ const partialJson = lines.slice(0, i + 1).join("\n");
125
+ // Try to close any open braces/brackets
126
+ let testJson = partialJson;
127
+ const openBraces = (testJson.match(/\{/g) || []).length;
128
+ const closeBraces = (testJson.match(/\}/g) || []).length;
129
+ const openBrackets = (testJson.match(/\[/g) || []).length;
130
+ const closeBrackets = (testJson.match(/\]/g) || []).length;
131
+ // Add missing closing characters
132
+ testJson += "]".repeat(openBrackets - closeBrackets);
133
+ testJson += "}".repeat(openBraces - closeBraces);
134
+ try {
135
+ const parsed = JSON.parse(testJson);
136
+ const partialItems = Array.isArray(parsed)
137
+ ? parsed
138
+ : parsed?.items || [];
139
+ if (partialItems.length > items.length) {
140
+ return partialItems;
141
+ }
142
+ }
143
+ catch (e) {
144
+ continue;
145
+ }
146
+ }
147
+ return items;
148
+ }
149
+ };
150
+ const extractTodosFromMessages = (messages) => {
151
+ const todos = [];
152
+ const fencedTodoToken = "```todo_list";
153
+ const plainTodoToken = "todo_list";
154
+ for (const message of messages) {
155
+ if (message.role !== "assistant" || !message.content)
156
+ continue;
157
+ const content = message.content;
158
+ let cursor = 0;
159
+ while (cursor < content.length) {
160
+ const nextFenced = content.indexOf(fencedTodoToken, cursor);
161
+ const nextPlain = content.indexOf(plainTodoToken, cursor);
162
+ let todoStart = -1;
163
+ let isFenced = false;
164
+ if (nextFenced !== -1 && (nextPlain === -1 || nextFenced < nextPlain)) {
165
+ todoStart = nextFenced;
166
+ isFenced = true;
167
+ }
168
+ else if (nextPlain !== -1) {
169
+ // Check if it's at line start
170
+ const before = nextPlain > 0 ? content[nextPlain - 1] : "\n";
171
+ if (before === "\n" || before === "\r" || nextPlain === 0) {
172
+ todoStart = nextPlain;
173
+ isFenced = false;
174
+ }
175
+ }
176
+ if (todoStart === -1)
177
+ break;
178
+ try {
179
+ let jsonText = "";
180
+ let isComplete = true;
181
+ if (isFenced) {
182
+ const afterToken = todoStart + fencedTodoToken.length;
183
+ const closePos = content.indexOf("```", afterToken);
184
+ if (closePos === -1) {
185
+ // Incomplete fenced block - extract what we have so far
186
+ jsonText = content.slice(afterToken).trim();
187
+ isComplete = false;
188
+ cursor = content.length; // Process till end
189
+ }
190
+ else {
191
+ jsonText = content.slice(afterToken, closePos).trim();
192
+ cursor = closePos + 3;
193
+ }
194
+ }
195
+ else {
196
+ const afterToken = todoStart + plainTodoToken.length;
197
+ const braceStart = content.indexOf("{", afterToken);
198
+ if (braceStart === -1)
199
+ break;
200
+ let depth = 0;
201
+ let braceEnd = -1;
202
+ for (let i = braceStart; i < content.length; i++) {
203
+ if (content[i] === "{")
204
+ depth++;
205
+ if (content[i] === "}") {
206
+ depth--;
207
+ if (depth === 0) {
208
+ braceEnd = i;
209
+ break;
210
+ }
211
+ }
212
+ }
213
+ if (braceEnd === -1) {
214
+ // Incomplete JSON - extract what we have
215
+ jsonText = content.slice(braceStart).trim();
216
+ isComplete = false;
217
+ cursor = content.length;
218
+ }
219
+ else {
220
+ jsonText = content.slice(braceStart, braceEnd + 1).trim();
221
+ cursor = braceEnd + 1;
222
+ }
223
+ }
224
+ // Use the partial extraction helper for incomplete JSON
225
+ const todoItems = isComplete
226
+ ? (() => {
227
+ try {
228
+ const parsed = JSON.parse(jsonText);
229
+ return Array.isArray(parsed) ? parsed : parsed?.items || [];
230
+ }
231
+ catch (e) {
232
+ return [];
233
+ }
234
+ })()
235
+ : extractPartialTodos(jsonText);
236
+ const title = (() => {
237
+ try {
238
+ const parsed = JSON.parse(jsonText);
239
+ return Array.isArray(parsed) ? undefined : parsed?.title;
240
+ }
241
+ catch (e) {
242
+ return undefined;
243
+ }
244
+ })();
245
+ todoItems.forEach((item) => {
246
+ if (!item)
247
+ return;
248
+ const text = item.text ||
249
+ item.content ||
250
+ item.label ||
251
+ String(item.task || item.title || "");
252
+ if (!text)
253
+ return;
254
+ todos.push({
255
+ id: item.id,
256
+ text,
257
+ done: !!(item.done ??
258
+ item.completed ??
259
+ item.checked ??
260
+ item.status === "completed"),
261
+ note: item.note || item.description,
262
+ messageId: message.id,
263
+ sourceTitle: title,
264
+ });
265
+ });
266
+ }
267
+ catch (e) {
268
+ cursor++;
269
+ continue;
270
+ }
271
+ }
272
+ }
273
+ return todos;
274
+ };
275
+ // TodoListPanel component
276
+ const TodoListPanel = ({ messages, agentMetadata, }) => {
277
+ const [isExpanded, setIsExpanded] = useState(true);
278
+ // First try to get todos from agent metadata (real-time updates)
279
+ const metadataTodos = (() => {
280
+ try {
281
+ const todoList = agentMetadata?.additionalData?.todoList;
282
+ if (todoList?.items && Array.isArray(todoList.items)) {
283
+ return todoList.items
284
+ .map((item, idx) => ({
285
+ id: item.id || `metadata-${idx}`,
286
+ text: item.text || item.label || String(item.task || item.title || ""),
287
+ done: !!(item.done ?? item.completed ?? item.checked),
288
+ note: item.note || item.description,
289
+ messageId: undefined,
290
+ sourceTitle: todoList.title,
291
+ }))
292
+ .filter((item) => item.text);
293
+ }
294
+ }
295
+ catch (e) {
296
+ console.error("📋 Error extracting todos from metadata:", e);
297
+ }
298
+ return null;
299
+ })();
300
+ // If we have metadata todos, use them; otherwise extract from messages
301
+ const todos = metadataTodos && metadataTodos.length > 0
302
+ ? metadataTodos
303
+ : extractTodosFromMessages(messages);
304
+ // Check if there's an active streaming message with incomplete todo content
305
+ const isUpdating = messages.some((msg) => {
306
+ if (msg.role !== "assistant" || msg.isCompleted)
307
+ return false;
308
+ const content = msg.content || "";
309
+ // Check for incomplete fenced todo blocks
310
+ const fencedStart = content.indexOf("```todo_list");
311
+ if (fencedStart !== -1) {
312
+ const afterStart = fencedStart + "```todo_list".length;
313
+ const closePos = content.indexOf("```", afterStart);
314
+ if (closePos === -1) {
315
+ // Incomplete fenced block
316
+ return true;
317
+ }
318
+ }
319
+ // Check for incomplete plain todo blocks
320
+ const plainStart = content.indexOf("todo_list");
321
+ if (plainStart !== -1 && plainStart !== fencedStart) {
322
+ const before = plainStart > 0 ? content[plainStart - 1] : "\n";
323
+ if (before === "\n" || before === "\r" || plainStart === 0) {
324
+ const braceStart = content.indexOf("{", plainStart);
325
+ if (braceStart !== -1) {
326
+ let depth = 0;
327
+ let braceEnd = -1;
328
+ for (let i = braceStart; i < content.length; i++) {
329
+ if (content[i] === "{")
330
+ depth++;
331
+ if (content[i] === "}") {
332
+ depth--;
333
+ if (depth === 0) {
334
+ braceEnd = i;
335
+ break;
336
+ }
337
+ }
338
+ }
339
+ if (braceEnd === -1) {
340
+ // Incomplete plain block
341
+ return true;
342
+ }
343
+ }
344
+ }
345
+ }
346
+ return false;
347
+ });
348
+ if (todos.length === 0 && !isUpdating)
349
+ return null;
350
+ const completedCount = todos.filter((t) => t.done).length;
351
+ const totalCount = todos.length;
352
+ return (_jsxs("div", { className: "border-t border-gray-200 bg-gray-50", children: [_jsxs("button", { onClick: () => setIsExpanded(!isExpanded), className: "flex w-full cursor-pointer items-center justify-between px-4 py-2 text-left transition-colors hover:bg-gray-100", children: [_jsxs("div", { className: "flex items-center gap-2", children: [_jsx(ListTodo, { className: "h-4 w-4 text-gray-500", strokeWidth: 1 }), _jsx("span", { className: "text-xs font-medium text-gray-700", children: "Todo List" }), isUpdating ? (_jsxs("span", { className: "flex items-center gap-1 text-xs text-blue-600", children: [_jsx(Loader2, { className: "h-3 w-3 animate-spin", strokeWidth: 1 }), "Updating..."] })) : (_jsxs("span", { className: "text-xs text-gray-500", children: [completedCount, "/", totalCount, " completed"] }))] }), isExpanded ? (_jsx(ChevronUp, { className: "h-4 w-4 text-gray-500", strokeWidth: 1 })) : (_jsx(ChevronDown, { className: "h-4 w-4 text-gray-500", strokeWidth: 1 }))] }), isExpanded && (_jsxs("div", { className: "max-h-64 overflow-y-auto px-4 pb-3", children: [todos.length > 0 && (_jsx("div", { className: "space-y-1.5", children: todos.map((todo, idx) => (_jsxs("div", { className: "flex items-start gap-2 rounded bg-white p-2 text-xs", children: [_jsx("div", { className: "flex-shrink-0 pt-0.5", children: todo.done ? (_jsx("div", { className: "flex h-4 w-4 items-center justify-center rounded border-2 border-green-500 bg-green-500", children: _jsx("svg", { className: "h-3 w-3 text-white", fill: "none", strokeWidth: 2, stroke: "currentColor", viewBox: "0 0 24 24", children: _jsx("path", { strokeLinecap: "round", strokeLinejoin: "round", d: "M5 13l4 4L19 7" }) }) })) : (_jsx("div", { className: "h-4 w-4 rounded border-2 border-gray-300" })) }), _jsxs("div", { className: "min-w-0 flex-1", children: [_jsx("div", { className: `${todo.done
353
+ ? "text-gray-500 line-through"
354
+ : "text-gray-900"}`, children: todo.text }), todo.note && (_jsx("div", { className: "mt-0.5 text-xs text-gray-500", children: todo.note }))] })] }, todo.id || `${todo.messageId}-${idx}`))) })), isUpdating && (_jsxs("div", { className: `flex items-center gap-2 rounded px-3 py-2 text-xs ${todos.length > 0
355
+ ? "mt-2 bg-blue-50 text-blue-700"
356
+ : "justify-center bg-white text-gray-500"}`, children: [_jsx(Loader2, { className: "h-3 w-3 animate-spin", strokeWidth: 1 }), _jsx("span", { children: todos.length > 0
357
+ ? "Updating todo list..."
358
+ : "Loading todo list..." })] }))] }))] }));
359
+ };
360
+ const groupConsecutiveMessages = (agentMessages) => {
361
+ // Work directly with the messages array - streaming messages are identified by their properties
362
+ const allMessages = agentMessages;
363
+ const groups = [];
364
+ let currentAssistantGroup = [];
365
+ for (const message of allMessages) {
366
+ if (message.role === "user") {
367
+ // Finish any current assistant group
368
+ if (currentAssistantGroup.length > 0) {
369
+ groups.push({
370
+ type: "assistant-group",
371
+ messages: currentAssistantGroup,
372
+ });
373
+ currentAssistantGroup = [];
374
+ }
375
+ // Add user message
376
+ groups.push({ type: "user", messages: [message] });
377
+ }
378
+ else if (message.role === "assistant") {
379
+ // Add to current assistant group
380
+ currentAssistantGroup.push(message);
381
+ }
382
+ // Skip tool messages as they're handled within assistant messages
383
+ }
384
+ // Add any remaining assistant group
385
+ if (currentAssistantGroup.length > 0) {
386
+ groups.push({ type: "assistant-group", messages: currentAssistantGroup });
387
+ }
388
+ return groups;
389
+ };
390
+ // Merge messages from DB and local state with ID-based deduplication
391
+ const mergeMessagesById = (dbMessages, localMessages) => {
392
+ const messageMap = new Map();
393
+ // Normalize ID key (lowercase) to avoid duplicates caused by casing differences
394
+ const keyOf = (id) => (id ? id.toLowerCase() : "");
395
+ // First, add all DB messages (source of truth for completed messages)
396
+ dbMessages.forEach((msg) => {
397
+ if (msg.id)
398
+ messageMap.set(keyOf(msg.id), msg);
399
+ });
400
+ // Then merge local messages (preserve streaming state, prefer longer content)
401
+ localMessages.forEach((localMsg) => {
402
+ if (!localMsg.id)
403
+ return;
404
+ const key = keyOf(localMsg.id);
405
+ const existingMsg = messageMap.get(key);
406
+ if (!existingMsg) {
407
+ // New message only in local state (e.g., streaming)
408
+ messageMap.set(key, localMsg);
409
+ }
410
+ else if (!localMsg.isCompleted && localMsg.messageType === "streaming") {
411
+ // Keep streaming version if more recent/longer
412
+ if (localMsg.content.length > existingMsg.content.length) {
413
+ messageMap.set(key, localMsg);
414
+ }
415
+ }
416
+ // Otherwise, keep the DB version (completed messages from DB are authoritative)
417
+ });
418
+ // Sort by messageIndex or createdDate to maintain order
419
+ // Ignore messageIndex if it's -1 (unassigned/streaming)
420
+ return Array.from(messageMap.values()).sort((a, b) => {
421
+ const aIndex = a.messageIndex === -1 ? Infinity : a.messageIndex;
422
+ const bIndex = b.messageIndex === -1 ? Infinity : b.messageIndex;
423
+ if (aIndex !== bIndex) {
424
+ return aIndex - bIndex;
425
+ }
426
+ return (new Date(a.createdDate || 0).getTime() -
427
+ new Date(b.createdDate || 0).getTime());
428
+ });
429
+ };
430
+ // Calculate total token usage and cost data from agent messages
431
+ const calculateTotalTokens = (messages) => {
432
+ const totals = messages.reduce((acc, message) => {
433
+ return {
434
+ input: acc.input + (message.inputTokens || 0),
435
+ output: acc.output + (message.outputTokens || 0),
436
+ cached: acc.cached + (message.cachedInputTokens || 0),
437
+ cacheWrite: acc.cacheWrite,
438
+ inputCost: acc.inputCost + (message.inputTokenCost || 0),
439
+ outputCost: acc.outputCost + (message.outputTokenCost || 0),
440
+ cachedCost: acc.cachedCost + (message.cachedInputTokenCost || 0),
441
+ cacheWriteCost: acc.cacheWriteCost,
442
+ totalCost: acc.totalCost + (message.totalCost || 0),
443
+ };
444
+ }, {
445
+ input: 0,
446
+ output: 0,
447
+ cached: 0,
448
+ cacheWrite: 0,
449
+ inputCost: 0,
450
+ outputCost: 0,
451
+ cachedCost: 0,
452
+ cacheWriteCost: 0,
453
+ totalCost: 0,
454
+ });
455
+ return totals;
456
+ };
457
+ // Convert agent messages to AI terminal format for a response group
458
+ const convertAgentMessagesToAiFormat = (agentMessages) => {
459
+ return agentMessages.map((agentMessage) => {
460
+ const message = {
461
+ id: agentMessage.id,
462
+ content: agentMessage.content,
463
+ formattedContent: agentMessage.content
464
+ ?.replace(/^######\s+(.+)$/gm, "<h6>$1</h6>")
465
+ ?.replace(/^#####\s+(.+)$/gm, "<h5>$1</h5>")
466
+ ?.replace(/^####\s+(.+)$/gm, "<h4>$1</h4>")
467
+ ?.replace(/^###\s+(.+)$/gm, "<h3>$1</h3>")
468
+ ?.replace(/^##\s+(.+)$/gm, "<h2>$1</h2>")
469
+ ?.replace(/^#\s+(.+)$/gm, "<h1>$1</h1>")
470
+ ?.replace(/\*\*(.*?)\*\*/g, "<strong>$1</strong>")
471
+ ?.replace(/\n/g, "<br/>"),
472
+ name: agentMessage.name,
473
+ role: agentMessage.role,
474
+ createdDate: agentMessage.createdDate,
475
+ tool_calls: agentMessage.toolCalls
476
+ ? agentMessage.toolCalls.map((toolCall) => ({
477
+ id: toolCall.toolCallId,
478
+ displayName: toolCall.functionName,
479
+ function: {
480
+ name: toolCall.functionName,
481
+ arguments: toolCall.functionArguments,
482
+ result: toolCall.functionResult,
483
+ error: toolCall.functionError,
484
+ },
485
+ // Pass through approval info if present on the tool call
486
+ requiresApproval: toolCall.requiresApproval,
487
+ }))
488
+ : [],
489
+ };
490
+ if (agentMessage.toolCallId) {
491
+ message.tool_call_id = agentMessage.toolCallId;
492
+ }
493
+ return message;
494
+ });
495
+ };
496
+ // interface AgentTerminalProps {
497
+ // agentStub: Agent;
498
+ // }
499
+ export function AgentTerminal({ agentStub, initialMetadata, profiles, isActive = true, compact = false, hideContext = false, hideBottomControls = false, hideGreeting = false, className, initialPrompt, }) {
500
+ const editContext = useEditContext();
501
+ const fieldsContext = useFieldsEditContext();
502
+ const [agent, setAgent] = useState(undefined);
503
+ const [messages, setMessages] = useState([]);
504
+ const [prompt, setPrompt] = useState("");
505
+ const [inputPlaceholder, setInputPlaceholder] = useState("Type your message... (Enter to send, Shift+Enter or Ctrl+Enter for new line)");
506
+ const [isLoading, setIsLoading] = useState(false);
507
+ const [isConnecting, setIsConnecting] = useState(false);
508
+ const [isSubmitting, setIsSubmitting] = useState(false);
509
+ const [activePlaceholderInput, setActivePlaceholderInput] = useState(null);
510
+ const [agentMetadata, setAgentMetadata] = useState(null);
511
+ // Generate a stable clientSessionId per component instance for stream deduplication
512
+ const clientSessionIdRef = useRef(null);
513
+ if (!clientSessionIdRef.current) {
514
+ clientSessionIdRef.current = crypto.randomUUID();
515
+ }
516
+ // Voice input state
517
+ const [isVoiceSupported, setIsVoiceSupported] = useState(false);
518
+ const [isListening, setIsListening] = useState(false);
519
+ const recognitionRef = useRef(null);
520
+ const prevPlaceholderRef = useRef(null);
521
+ const [isWaitingForResponse, setIsWaitingForResponse] = useState(false);
522
+ const isWaitingRef = useRef(false);
523
+ useEffect(() => {
524
+ isWaitingRef.current = isWaitingForResponse;
525
+ }, [isWaitingForResponse]);
526
+ // Dots visibility controlled by 1s idle timer since last incremental update
527
+ const [showDots, setShowDots] = useState(false);
528
+ const dotsTimeoutRef = useRef(null);
529
+ const hasActiveStreaming = useCallback(() => {
530
+ const current = messagesRef.current || [];
531
+ return current.some((m) => !m.isCompleted && m.messageType === "streaming");
532
+ }, []);
533
+ const hasPendingApprovals = useCallback(() => {
534
+ const current = messagesRef.current || [];
535
+ return current.some((m) => (m.toolCalls || []).some((tc) => {
536
+ const hasApprovalMetadata = !!tc.requiresApproval && tc.isCompleted === false;
537
+ const hasPendingSuffix = (tc.functionName || "").includes("(pending approval)");
538
+ return hasApprovalMetadata || hasPendingSuffix;
539
+ }));
540
+ }, []);
541
+ const resetDotsTimer = useCallback(() => {
542
+ if (dotsTimeoutRef.current) {
543
+ clearTimeout(dotsTimeoutRef.current);
544
+ dotsTimeoutRef.current = null;
545
+ }
546
+ const waiting = isWaitingRef.current;
547
+ const streaming = hasActiveStreaming();
548
+ const pendingApprovals = hasPendingApprovals();
549
+ // Check if agent is waiting for approval
550
+ const currentAgent = agentRef.current;
551
+ const isWaitingForApproval = currentAgent?.status === "waitingForApproval" ||
552
+ currentAgent?.status === 2;
553
+ // Don't show dots if there are pending approvals (waiting for user action)
554
+ // or if the agent status is waitingForApproval
555
+ if (!waiting && !streaming) {
556
+ setShowDots(false);
557
+ return;
558
+ }
559
+ if (pendingApprovals || isWaitingForApproval) {
560
+ setShowDots(false);
561
+ return;
562
+ }
563
+ // Show dots immediately when waiting or streaming
564
+ setShowDots(true);
565
+ dotsTimeoutRef.current = setTimeout(() => {
566
+ // Re-check conditions after a brief delay to avoid flicker
567
+ const stillWaiting = isWaitingRef.current;
568
+ const stillStreaming = hasActiveStreaming();
569
+ const stillPendingApprovals = hasPendingApprovals();
570
+ const stillCurrentAgent = agentRef.current;
571
+ const stillWaitingForApproval = stillCurrentAgent?.status === "waitingForApproval" ||
572
+ stillCurrentAgent?.status === 2;
573
+ setShowDots((stillWaiting || stillStreaming) &&
574
+ !stillPendingApprovals &&
575
+ !stillWaitingForApproval);
576
+ }, 100);
577
+ }, [hasActiveStreaming, hasPendingApprovals]);
578
+ const [resolvedPageName, setResolvedPageName] = useState(undefined);
579
+ const [resolvedComponentName, setResolvedComponentName] = useState(undefined);
580
+ const [resolvedFieldName, setResolvedFieldName] = useState(undefined);
581
+ const [isContextCollapsed, setIsContextCollapsed] = useState(true);
582
+ const [isContextDragOver, setIsContextDragOver] = useState(false);
583
+ const [promptHistory, setPromptHistory] = useState(() => {
584
+ if (typeof window !== "undefined") {
585
+ return JSON.parse(localStorage.getItem("editor.agent.promptHistory") || "[]");
586
+ }
587
+ return [];
588
+ });
589
+ const [currentHistoryIndex, setCurrentHistoryIndex] = useState(-1);
590
+ const [showPredefined, setShowPredefined] = useState(false);
591
+ const [activeProfile, setActiveProfile] = useState(undefined);
592
+ const [selectedModelId, setSelectedModelId] = useState(undefined);
593
+ const [mode, setMode] = useState("supervised");
594
+ const [queuedPrompts, setQueuedPrompts] = useState([]);
595
+ // Remove deprecated cost limit fields from metadata to avoid confusion with agent/profile settings
596
+ const sanitizeAgentMetadata = useCallback((meta) => {
597
+ try {
598
+ if (!meta)
599
+ return meta;
600
+ const clean = { ...meta };
601
+ delete clean.costLimit;
602
+ delete clean.CostLimit;
603
+ delete clean.initialCostLimit;
604
+ delete clean.InitialCostLimit;
605
+ if (clean.additionalData && typeof clean.additionalData === "object") {
606
+ const ad = { ...clean.additionalData };
607
+ delete ad.costLimit;
608
+ delete ad.CostLimit;
609
+ delete ad.initialCostLimit;
610
+ delete ad.InitialCostLimit;
611
+ clean.additionalData = ad;
612
+ }
613
+ return clean;
614
+ }
615
+ catch {
616
+ return meta;
617
+ }
618
+ }, []);
619
+ // Read deterministic flags from query string once
620
+ let deterministicFlags;
621
+ try {
622
+ const params = new URLSearchParams(window.location.search);
623
+ const detParam = params.get("deterministic");
624
+ const deterministic = detParam === "true" ||
625
+ (detParam === null ? params.has("deterministic") : false);
626
+ const seedStr = params.get("seed");
627
+ const seed = seedStr ? Number(seedStr) : undefined;
628
+ deterministicFlags = {
629
+ deterministic,
630
+ seed: Number.isFinite(seed) ? seed : undefined,
631
+ };
632
+ }
633
+ catch {
634
+ deterministicFlags = {
635
+ deterministic: false,
636
+ seed: undefined,
637
+ };
638
+ }
639
+ useEffect(() => {
640
+ localStorage.setItem("editor.agent.promptHistory", JSON.stringify(promptHistory));
641
+ }, [promptHistory]);
642
+ // Clear idle timer on unmount
643
+ useEffect(() => {
644
+ return () => {
645
+ if (dotsTimeoutRef.current) {
646
+ clearTimeout(dotsTimeoutRef.current);
647
+ dotsTimeoutRef.current = null;
648
+ }
649
+ };
650
+ }, []);
651
+ // Whenever waiting state changes, restart idle timer logic
652
+ useEffect(() => {
653
+ resetDotsTimer();
654
+ }, [isWaitingForResponse, resetDotsTimer]);
655
+ useEffect(() => {
656
+ // Keep messagesRef synchronized with messages state
657
+ messagesRef.current = messages;
658
+ }, [messages]);
659
+ const [error, setError] = useState(null);
660
+ const [costLimitExceeded, setCostLimitExceeded] = useState(null);
661
+ // Live running totals from backend status updates (tokenUsage)
662
+ const [liveTotals, setLiveTotals] = useState(null);
663
+ // Flag to track when we should create a new message
664
+ const shouldCreateNewMessage = useRef(false);
665
+ // Keep a ref to the current messages for immediate access
666
+ const messagesRef = useRef([]);
667
+ const abortControllerRef = useRef(null);
668
+ const messagesEndRef = useRef(null);
669
+ const textareaRef = useRef(null);
670
+ const messagesContainerRef = useRef(null);
671
+ const [shouldAutoScroll, setShouldAutoScroll] = useState(true);
672
+ // WebSocket subscription state for agent streaming
673
+ const seenMessageIdsRef = useRef(new Set());
674
+ const lastSeqRef = useRef(0);
675
+ const subscribedAgentIdRef = useRef(null);
676
+ // Cache mode/model changes made while the agent is still "new" (not yet persisted)
677
+ const pendingSettingsRef = useRef(null);
678
+ // Auto-scroll to bottom when new messages arrive
679
+ const scrollToBottom = useCallback(() => {
680
+ const container = messagesContainerRef.current;
681
+ if (!container)
682
+ return;
683
+ // Jump precisely to the bottom to avoid ending slightly above due to smooth scrolling animations
684
+ container.scrollTop = container.scrollHeight;
685
+ }, []);
686
+ // Detect speech recognition support (client-only)
687
+ useEffect(() => {
688
+ try {
689
+ if (typeof window === "undefined")
690
+ return;
691
+ const SR = window.SpeechRecognition ||
692
+ window.webkitSpeechRecognition;
693
+ setIsVoiceSupported(!!SR);
694
+ }
695
+ catch {
696
+ setIsVoiceSupported(false);
697
+ }
698
+ }, []);
699
+ // Auto-focus terminal input on mount
700
+ useEffect(() => {
701
+ if (textareaRef.current) {
702
+ textareaRef.current.focus();
703
+ }
704
+ }, []);
705
+ // Start voice recognition
706
+ const startVoice = useCallback(() => {
707
+ try {
708
+ if (isListening)
709
+ return;
710
+ if (typeof window === "undefined")
711
+ return;
712
+ const SR = window.SpeechRecognition ||
713
+ window.webkitSpeechRecognition;
714
+ if (!SR) {
715
+ return;
716
+ }
717
+ const r = new SR();
718
+ r.lang = editContext?.currentItemDescriptor?.language || "en-US";
719
+ r.continuous = true;
720
+ r.interimResults = true;
721
+ r.onstart = () => {
722
+ setIsListening(true);
723
+ prevPlaceholderRef.current = inputPlaceholder;
724
+ setInputPlaceholder("Listening...");
725
+ };
726
+ r.onresult = (event) => {
727
+ let finalText = "";
728
+ let interimText = "";
729
+ for (let i = event.resultIndex; i < event.results.length; i++) {
730
+ const res = event.results[i];
731
+ if (res.isFinal)
732
+ finalText += res[0]?.transcript || "";
733
+ else
734
+ interimText += res[0]?.transcript || "";
735
+ }
736
+ if (interimText) {
737
+ setInputPlaceholder(`Listening... ${interimText.trim()}`);
738
+ }
739
+ else {
740
+ setInputPlaceholder("Listening...");
741
+ }
742
+ if (finalText && finalText.trim()) {
743
+ setPrompt((prev) => {
744
+ const prefix = prev && !prev.endsWith(" ") ? prev + " " : prev;
745
+ return (prefix || "") + finalText.trim() + " ";
746
+ });
747
+ if (textareaRef.current) {
748
+ try {
749
+ const v = textareaRef.current.value || "";
750
+ textareaRef.current.selectionStart = v.length;
751
+ textareaRef.current.selectionEnd = v.length;
752
+ }
753
+ catch { }
754
+ }
755
+ }
756
+ };
757
+ r.onerror = (e) => {
758
+ console.warn("Speech recognition error", e);
759
+ };
760
+ r.onend = () => {
761
+ setIsListening(false);
762
+ if (prevPlaceholderRef.current !== null) {
763
+ setInputPlaceholder(prevPlaceholderRef.current);
764
+ prevPlaceholderRef.current = null;
765
+ }
766
+ recognitionRef.current = null;
767
+ };
768
+ recognitionRef.current = r;
769
+ r.start();
770
+ }
771
+ catch (e) {
772
+ console.error("Failed to start voice input", e);
773
+ }
774
+ }, [
775
+ editContext?.currentItemDescriptor?.language,
776
+ inputPlaceholder,
777
+ isListening,
778
+ ]);
779
+ const stopVoice = useCallback(() => {
780
+ try {
781
+ const r = recognitionRef.current;
782
+ if (r)
783
+ r.stop();
784
+ }
785
+ catch { }
786
+ }, []);
787
+ const toggleVoice = useCallback(() => {
788
+ if (isListening)
789
+ stopVoice();
790
+ else
791
+ startVoice();
792
+ }, [isListening, startVoice, stopVoice]);
793
+ // Cleanup any active recognition on unmount
794
+ useEffect(() => {
795
+ return () => {
796
+ try {
797
+ const r = recognitionRef.current;
798
+ if (r) {
799
+ r.onresult = null;
800
+ r.onerror = null;
801
+ r.onend = null;
802
+ r.stop();
803
+ }
804
+ }
805
+ catch { }
806
+ recognitionRef.current = null;
807
+ };
808
+ }, []);
809
+ // Check if user is at the bottom of the scroll container
810
+ const isAtBottom = useCallback(() => {
811
+ const container = messagesContainerRef.current;
812
+ if (!container)
813
+ return true;
814
+ const threshold = 100; // pixels from bottom to consider "at bottom"
815
+ return (container.scrollHeight - container.scrollTop - container.clientHeight <
816
+ threshold);
817
+ }, []);
818
+ // Handle scroll events to detect manual scrolling
819
+ const handleScroll = useCallback(() => {
820
+ const atBottom = isAtBottom();
821
+ if (atBottom !== shouldAutoScroll) {
822
+ setShouldAutoScroll(atBottom);
823
+ }
824
+ }, [isAtBottom, shouldAutoScroll]);
825
+ // Shared stream message handlers with messageId support
826
+ const createNewStreamMessage = useCallback((messageId, agentData) => {
827
+ const currentAgent = agentData || agent;
828
+ if (!currentAgent) {
829
+ console.error("❌ createNewStreamMessage: No agent available", {
830
+ messageId,
831
+ agentData: !!agentData,
832
+ agent: !!agent,
833
+ });
834
+ throw new Error("No agent available");
835
+ }
836
+ // Reduced: avoid verbose logging during streaming
837
+ return {
838
+ id: messageId,
839
+ agentId: currentAgent.id,
840
+ messageIndex: -1,
841
+ role: "assistant",
842
+ content: "",
843
+ name: "agent",
844
+ messageType: "streaming",
845
+ isCompleted: false,
846
+ model: currentAgent.model || "",
847
+ tokensUsed: 0,
848
+ inputTokens: 0,
849
+ outputTokens: 0,
850
+ cachedInputTokens: 0,
851
+ inputTokenCost: 0,
852
+ outputTokenCost: 0,
853
+ cachedInputTokenCost: 0,
854
+ totalCost: 0,
855
+ currency: currentAgent.currency || "USD",
856
+ createdDate: new Date().toISOString(),
857
+ toolCalls: [],
858
+ };
859
+ }, [agent]);
860
+ const handleContentChunk = useCallback((message, agentData) => {
861
+ // Get messageId from data, or generate one from agent ID (for backward compatibility)
862
+ // If no messageId is provided, we'll use the last assistant message or create a new one
863
+ let messageId = message.data?.messageId;
864
+ if (!messageId && agentData?.id) {
865
+ // For backward compatibility: if no messageId, find or create the current streaming message
866
+ // This handles cases where the backend doesn't send messageId
867
+ const currentMessages = messagesRef.current;
868
+ const lastStreamingMessage = [...currentMessages]
869
+ .reverse()
870
+ .find((m) => m.role === "assistant" && !m.isCompleted);
871
+ if (lastStreamingMessage) {
872
+ messageId = lastStreamingMessage.id;
873
+ }
874
+ else {
875
+ // If the agent isn't currently running (e.g., we switched tabs after the run
876
+ // completed), skip creating a new streaming message to avoid duplicates.
877
+ const currentAgentStatus = (agentData || agent)?.status;
878
+ const isAgentRunning = currentAgentStatus === "running" || currentAgentStatus === 1;
879
+ if (!isAgentRunning) {
880
+ return;
881
+ }
882
+ // Create a new message ID based on timestamp when the agent is still running
883
+ messageId = crypto.randomUUID();
884
+ }
885
+ }
886
+ if (!messageId) {
887
+ console.error("Unable to determine messageId for content chunk!");
888
+ return;
889
+ }
890
+ // Clear waiting state when first content chunk arrives
891
+ setIsWaitingForResponse(false);
892
+ isWaitingRef.current = false;
893
+ // Any content chunk is an incremental update -> reset idle timer
894
+ resetDotsTimer();
895
+ // Extract cost/token data from message.cost (new structure)
896
+ const cost = message.cost;
897
+ if (cost &&
898
+ (cost.total !== undefined || cost.tokens?.total !== undefined)) {
899
+ const nextTotals = {
900
+ input: Number(cost.tokens?.input) || 0,
901
+ output: Number(cost.tokens?.output) || 0,
902
+ cached: Number(cost.tokens?.cached) || 0,
903
+ cacheWrite: Number(cost.tokens?.cacheWrite) || 0,
904
+ inputCost: Number(cost.input) || 0,
905
+ outputCost: Number(cost.output) || 0,
906
+ cachedCost: Number(cost.cached) || 0,
907
+ cacheWriteCost: Number(cost.cacheWrite) || 0,
908
+ totalCost: Number(cost.total) || 0,
909
+ currency: "USD",
910
+ };
911
+ const anyNonZero = (nextTotals.totalCost || 0) > 0 ||
912
+ (nextTotals.input || 0) > 0 ||
913
+ (nextTotals.output || 0) > 0 ||
914
+ (nextTotals.cached || 0) > 0 ||
915
+ (nextTotals.cacheWrite || 0) > 0;
916
+ if (anyNonZero) {
917
+ setLiveTotals(nextTotals);
918
+ }
919
+ // Check cost limit if available
920
+ if (cost.limit &&
921
+ cost.total &&
922
+ Number(cost.total) > Number(cost.limit)) {
923
+ setCostLimitExceeded({
924
+ totalCost: Number(cost.total),
925
+ costLimit: Number(cost.limit),
926
+ initialCostLimit: Number(cost.limit),
927
+ });
928
+ setIsWaitingForResponse(false);
929
+ shouldCreateNewMessage.current = false;
930
+ }
931
+ }
932
+ // Always call setMessages and handle all logic in the callback with latest messages
933
+ setMessages((prev) => {
934
+ // Find existing message by messageId in the latest messages
935
+ const existingMessageIndex = prev.findIndex((msg) => msg.id === messageId);
936
+ if (existingMessageIndex === -1) {
937
+ // Message doesn't exist - create new streaming message
938
+ const newStreamMessage = createNewStreamMessage(messageId, agentData);
939
+ // Set the content for the new message
940
+ const updatedNewMessage = { ...newStreamMessage };
941
+ if (!message.data.isIncremental) {
942
+ updatedNewMessage.content = message.data?.deltaContent || "";
943
+ }
944
+ else {
945
+ updatedNewMessage.content = message.data?.deltaContent || "";
946
+ }
947
+ const updated = [...prev, updatedNewMessage];
948
+ messagesRef.current = updated;
949
+ return updated;
950
+ }
951
+ else {
952
+ // Message exists - update it
953
+ const existingMessage = prev[existingMessageIndex];
954
+ if (!existingMessage)
955
+ return prev;
956
+ // Check if existing content is already longer than what we're trying to stream
957
+ const currentContentLength = existingMessage.content?.length || 0;
958
+ const totalContentLength = message.data?.totalContentLength || 0;
959
+ if (currentContentLength >= totalContentLength &&
960
+ totalContentLength > 0) {
961
+ return prev;
962
+ }
963
+ const updatedMessage = { ...existingMessage };
964
+ if (!message.data.isIncremental) {
965
+ updatedMessage.content = message.data?.deltaContent || "";
966
+ }
967
+ else {
968
+ updatedMessage.content =
969
+ existingMessage.content + (message.data?.deltaContent || "");
970
+ }
971
+ const updated = prev.map((msg, index) => index === existingMessageIndex ? updatedMessage : msg);
972
+ messagesRef.current = updated;
973
+ return updated;
974
+ }
975
+ });
976
+ }, [createNewStreamMessage, agent]);
977
+ const handleToolCall = useCallback((message, agentData) => {
978
+ const toolCallId = message.data?.toolCallId || message.data?.id || crypto.randomUUID();
979
+ // Prefer provided messageId, otherwise fall back to the last streaming assistant message
980
+ let toolCallMessageId = message.data?.messageId;
981
+ if (!toolCallMessageId) {
982
+ const current = messagesRef.current;
983
+ const lastStreaming = [...current]
984
+ .reverse()
985
+ .find((m) => m.role === "assistant" && !m.isCompleted);
986
+ if (lastStreaming?.id) {
987
+ toolCallMessageId = lastStreaming.id;
988
+ }
989
+ }
990
+ // Find or create the target message for this tool call
991
+ if (toolCallMessageId) {
992
+ const currentMessages = messagesRef.current;
993
+ const existingMessageIndex = currentMessages.findIndex((msg) => msg.id === toolCallMessageId);
994
+ if (existingMessageIndex === -1) {
995
+ // Double-check with current ref to prevent race conditions
996
+ const currentMessages = messagesRef.current;
997
+ const existsInRef = currentMessages.find((msg) => msg.id === toolCallMessageId);
998
+ if (!existsInRef) {
999
+ // Create new message for this tool call
1000
+ const newStreamMessage = createNewStreamMessage(toolCallMessageId, agentData);
1001
+ setMessages((prev) => {
1002
+ // Final check before adding to prevent duplicates
1003
+ const finalCheck = prev.find((msg) => msg.id === toolCallMessageId);
1004
+ if (finalCheck) {
1005
+ return prev;
1006
+ }
1007
+ const updated = [...prev, newStreamMessage];
1008
+ messagesRef.current = updated;
1009
+ return updated;
1010
+ });
1011
+ }
1012
+ }
1013
+ }
1014
+ // Add tool call to the message in the array
1015
+ if (toolCallMessageId && message.data && toolCallId) {
1016
+ const functionName = message.data.functionName ||
1017
+ message.data.name ||
1018
+ message.data.function?.name ||
1019
+ "unknown";
1020
+ const toolCall = {
1021
+ id: toolCallId,
1022
+ messageId: toolCallMessageId,
1023
+ dbMessageId: message.data.messageId, // Database message ID for approval/rejection
1024
+ toolCallId: toolCallId,
1025
+ functionName: functionName,
1026
+ functionArguments: message.data.functionArguments ||
1027
+ message.data.arguments ||
1028
+ JSON.stringify(message.data.function?.arguments || {}),
1029
+ functionResult: message.data.functionResult || message.data.result || "",
1030
+ functionError: message.data.functionError || message.data.error || "",
1031
+ isCompleted: false,
1032
+ responseTimeMs: message.data.responseTimeMs,
1033
+ createdDate: new Date().toISOString(),
1034
+ requiresApproval: message.data?.requiresApproval,
1035
+ };
1036
+ // Check for duplicates using the current messages ref
1037
+ const currentMessages = messagesRef.current;
1038
+ const targetMessage = currentMessages.find((msg) => msg.id === toolCallMessageId);
1039
+ if (targetMessage) {
1040
+ const existingToolCalls = targetMessage.toolCalls || [];
1041
+ const existingToolCallIndex = existingToolCalls.findIndex((tc) => tc.toolCallId === toolCallId);
1042
+ if (existingToolCallIndex !== -1) {
1043
+ return; // Skip adding duplicate
1044
+ }
1045
+ }
1046
+ setMessages((prev) => {
1047
+ const updated = prev.map((msg) => {
1048
+ if (msg.id !== toolCallMessageId)
1049
+ return msg;
1050
+ const existingToolCalls = msg.toolCalls || [];
1051
+ return { ...msg, toolCalls: [...existingToolCalls, toolCall] };
1052
+ });
1053
+ messagesRef.current = updated;
1054
+ return updated;
1055
+ });
1056
+ // Tool call activity counts as activity; keep dots hidden for 1s
1057
+ resetDotsTimer();
1058
+ }
1059
+ }, [createNewStreamMessage]);
1060
+ const handleToolResult = useCallback((message, agentData) => {
1061
+ const resultToolCallId = message.data?.toolCallId || message.data?.id || crypto.randomUUID();
1062
+ // Prefer provided messageId, otherwise fall back to the last streaming assistant message
1063
+ let resultMessageId = message.data?.messageId;
1064
+ if (!resultMessageId) {
1065
+ const current = messagesRef.current;
1066
+ const lastStreaming = [...current]
1067
+ .reverse()
1068
+ .find((m) => m.role === "assistant" && !m.isCompleted);
1069
+ if (lastStreaming?.id) {
1070
+ resultMessageId = lastStreaming.id;
1071
+ }
1072
+ }
1073
+ // Extract cost/token data from tool result if present
1074
+ const cost = message.cost;
1075
+ if (cost &&
1076
+ (cost.total !== undefined || cost.tokens?.total !== undefined)) {
1077
+ const nextTotals = {
1078
+ input: Number(cost.tokens?.input) || 0,
1079
+ output: Number(cost.tokens?.output) || 0,
1080
+ cached: Number(cost.tokens?.cached) || 0,
1081
+ cacheWrite: Number(cost.tokens?.cacheWrite) || 0,
1082
+ inputCost: Number(cost.input) || 0,
1083
+ outputCost: Number(cost.output) || 0,
1084
+ cachedCost: Number(cost.cached) || 0,
1085
+ cacheWriteCost: Number(cost.cacheWrite) || 0,
1086
+ totalCost: Number(cost.total) || 0,
1087
+ currency: "USD",
1088
+ };
1089
+ const anyNonZero = (nextTotals.totalCost || 0) > 0 ||
1090
+ (nextTotals.input || 0) > 0 ||
1091
+ (nextTotals.output || 0) > 0 ||
1092
+ (nextTotals.cached || 0) > 0 ||
1093
+ (nextTotals.cacheWrite || 0) > 0;
1094
+ if (anyNonZero) {
1095
+ setLiveTotals(nextTotals);
1096
+ }
1097
+ }
1098
+ else {
1099
+ // Fallback: legacy aggregated totals included in the tool result data
1100
+ const data = message.data;
1101
+ if (data &&
1102
+ (data.totalCost !== undefined || data.totalTokens !== undefined)) {
1103
+ const nextTotals = {
1104
+ input: Number(data.totalInputTokens) || 0,
1105
+ output: Number(data.totalOutputTokens) || 0,
1106
+ cached: Number(data.totalCachedTokens) || 0,
1107
+ cacheWrite: Number(data.totalCacheWriteTokens) || 0,
1108
+ inputCost: Number(data.totalInputTokenCost) || 0,
1109
+ outputCost: Number(data.totalOutputTokenCost) || 0,
1110
+ cachedCost: Number(data.totalCachedTokenCost) || 0,
1111
+ cacheWriteCost: Number(data.totalCacheWriteTokenCost) || 0,
1112
+ totalCost: Number(data.totalCost) || 0,
1113
+ currency: data.currency || "USD",
1114
+ };
1115
+ const anyNonZero = (nextTotals.totalCost || 0) > 0 ||
1116
+ (nextTotals.input || 0) > 0 ||
1117
+ (nextTotals.output || 0) > 0 ||
1118
+ (nextTotals.cached || 0) > 0 ||
1119
+ (nextTotals.cacheWrite || 0) > 0;
1120
+ if (anyNonZero) {
1121
+ setLiveTotals(nextTotals);
1122
+ }
1123
+ }
1124
+ }
1125
+ // Update tool result directly in the messages array
1126
+ if (!resultMessageId) {
1127
+ return;
1128
+ }
1129
+ // Update the message with tool result
1130
+ setMessages((prev) => {
1131
+ const updated = prev.map((msg) => {
1132
+ if (msg.id !== resultMessageId)
1133
+ return msg;
1134
+ const updatedMessage = { ...msg };
1135
+ if (!updatedMessage.toolCalls) {
1136
+ updatedMessage.toolCalls = [];
1137
+ }
1138
+ // Find and update the tool call with the result
1139
+ const toolCallIndex = updatedMessage.toolCalls.findIndex((tc) => tc.toolCallId === resultToolCallId);
1140
+ if (toolCallIndex >= 0) {
1141
+ const existingToolCall = updatedMessage.toolCalls[toolCallIndex];
1142
+ if (existingToolCall && message.data) {
1143
+ const updatedToolCalls = [...updatedMessage.toolCalls];
1144
+ const toolCall = {
1145
+ id: existingToolCall.id,
1146
+ messageId: existingToolCall.messageId,
1147
+ toolCallId: existingToolCall.toolCallId,
1148
+ functionName: existingToolCall.functionName,
1149
+ functionArguments: existingToolCall.functionArguments,
1150
+ functionResult: message.data.functionResult || message.data.result || "",
1151
+ functionError: message.data.functionError || message.data.error || "",
1152
+ isCompleted: true,
1153
+ responseTimeMs: message.data.responseTimeMs,
1154
+ createdDate: existingToolCall.createdDate,
1155
+ };
1156
+ updatedToolCalls[toolCallIndex] = toolCall;
1157
+ updatedMessage.toolCalls = updatedToolCalls;
1158
+ }
1159
+ // Check if all tool calls in message are completed
1160
+ const allToolCallsCompleted = updatedMessage.toolCalls.every((tc) => tc.isCompleted);
1161
+ if (allToolCallsCompleted) {
1162
+ shouldCreateNewMessage.current = true;
1163
+ }
1164
+ }
1165
+ else if (message.data && resultToolCallId && resultMessageId) {
1166
+ // Create new tool call if it doesn't exist
1167
+ const functionName = message.data.functionName ||
1168
+ message.data.name ||
1169
+ message.data.function?.name ||
1170
+ "unknown";
1171
+ const toolCall = {
1172
+ id: resultToolCallId,
1173
+ messageId: resultMessageId,
1174
+ toolCallId: resultToolCallId,
1175
+ functionName: functionName,
1176
+ functionArguments: message.data.functionArguments ||
1177
+ message.data.arguments ||
1178
+ JSON.stringify(message.data.function?.arguments || {}),
1179
+ functionResult: message.data.functionResult || message.data.result || "",
1180
+ functionError: message.data.functionError || message.data.error || "",
1181
+ isCompleted: true,
1182
+ responseTimeMs: message.data.responseTimeMs,
1183
+ createdDate: new Date().toISOString(),
1184
+ };
1185
+ updatedMessage.toolCalls = [...updatedMessage.toolCalls, toolCall];
1186
+ }
1187
+ // Updated tool calls count
1188
+ return updatedMessage;
1189
+ });
1190
+ messagesRef.current = updated;
1191
+ return updated;
1192
+ });
1193
+ // Tool result activity; reset idle timer
1194
+ resetDotsTimer();
1195
+ }, [resetDotsTimer]);
1196
+ // Listen for local approval resolution to update UI
1197
+ useEffect(() => {
1198
+ const onApprovalResolved = (ev) => {
1199
+ try {
1200
+ const detail = ev?.detail || {};
1201
+ const messageId = detail.messageId;
1202
+ const toolCallId = detail.toolCallId;
1203
+ const approved = !!detail.approved;
1204
+ if (!messageId || !toolCallId)
1205
+ return;
1206
+ // Update local state to reflect approval status
1207
+ setMessages((prev) => {
1208
+ const updated = prev.map((m) => {
1209
+ if (m.id !== messageId)
1210
+ return m;
1211
+ const updatedToolCalls = (m.toolCalls || []).map((tc) => {
1212
+ if (tc.toolCallId !== toolCallId)
1213
+ return tc;
1214
+ const base = (tc.functionName || "")
1215
+ .replace(" (pending approval)", "")
1216
+ .replace(" (approved)", "")
1217
+ .replace(" (rejected)", "");
1218
+ return {
1219
+ ...tc,
1220
+ functionName: base + (approved ? " (approved)" : " (rejected)"),
1221
+ // Mark tool call as completed when rejected or approved
1222
+ isCompleted: true,
1223
+ // Set error if rejected
1224
+ ...(approved ? {} : { functionError: "REJECTED" }),
1225
+ };
1226
+ });
1227
+ // Check if all tool calls are completed
1228
+ const allToolCallsCompleted = updatedToolCalls.length > 0 &&
1229
+ updatedToolCalls.every((tc) => tc.isCompleted);
1230
+ // If all tool calls are completed and message was streaming, mark it as completed
1231
+ const shouldMarkMessageCompleted = allToolCallsCompleted &&
1232
+ !m.isCompleted &&
1233
+ m.messageType === "streaming";
1234
+ return {
1235
+ ...m,
1236
+ toolCalls: updatedToolCalls,
1237
+ // Mark message as completed if all tool calls are done
1238
+ ...(shouldMarkMessageCompleted
1239
+ ? { isCompleted: true, messageType: "completed" }
1240
+ : {}),
1241
+ };
1242
+ });
1243
+ messagesRef.current = updated;
1244
+ return updated;
1245
+ });
1246
+ }
1247
+ catch (err) {
1248
+ console.error("❌ Error handling approval resolution:", err);
1249
+ }
1250
+ };
1251
+ window.addEventListener("agent:toolApprovalResolved", onApprovalResolved);
1252
+ return () => window.removeEventListener("agent:toolApprovalResolved", onApprovalResolved);
1253
+ }, []);
1254
+ // Load agent data and messages
1255
+ const loadAgent = useCallback(async () => {
1256
+ try {
1257
+ // Even if agentStub.status is "new", try to load from backend first
1258
+ // The agent might have been persisted after sending a prompt
1259
+ // Only treat as "new" if backend returns 404
1260
+ const hasExistingMessages = messagesRef.current.length > 0;
1261
+ if (agentStub.status === "new" && !hasExistingMessages) {
1262
+ // Only initialize as new if we have no messages yet (initial mount)
1263
+ // Derive initial profile from provided metadata if present
1264
+ const initialProfileIdFromMeta = (() => {
1265
+ try {
1266
+ return initialMetadata?.additionalData?.profileId;
1267
+ }
1268
+ catch {
1269
+ return undefined;
1270
+ }
1271
+ })();
1272
+ const initialProfileNameFromMeta = (() => {
1273
+ try {
1274
+ return (initialMetadata?.additionalData?.profileName ||
1275
+ initialMetadata?.profile ||
1276
+ undefined);
1277
+ }
1278
+ catch {
1279
+ return undefined;
1280
+ }
1281
+ })();
1282
+ setAgent({
1283
+ ...agentStub,
1284
+ messages: [],
1285
+ status: "new",
1286
+ updatedDate: new Date().toISOString(),
1287
+ createdDate: new Date().toISOString(),
1288
+ id: agentStub.id,
1289
+ name: agentStub.name,
1290
+ model: "",
1291
+ currency: "USD",
1292
+ profileId: initialProfileIdFromMeta || "",
1293
+ profileName: initialProfileNameFromMeta || "",
1294
+ totalTokensUsed: 0,
1295
+ totalInputTokens: 0,
1296
+ totalOutputTokens: 0,
1297
+ totalCachedInputTokens: 0,
1298
+ totalInputTokenCost: 0,
1299
+ totalOutputTokenCost: 0,
1300
+ totalCachedInputTokenCost: 0,
1301
+ totalCost: 0,
1302
+ messageCount: 0,
1303
+ });
1304
+ setMessages([]);
1305
+ setError(null);
1306
+ setIsLoading(false);
1307
+ // Initialize local context for a brand-new agent (not yet persisted)
1308
+ // Optionally seed with current page/selection/focused field based on profile setting
1309
+ const item = editContext?.currentItemDescriptor;
1310
+ const profileForSeeding = (() => {
1311
+ try {
1312
+ if (initialProfileIdFromMeta) {
1313
+ const byId = (profiles || []).find((p) => p.id === initialProfileIdFromMeta);
1314
+ if (byId)
1315
+ return byId;
1316
+ }
1317
+ if (initialProfileNameFromMeta) {
1318
+ const byName = (profiles || []).find((p) => p.name === initialProfileNameFromMeta);
1319
+ if (byName)
1320
+ return byName;
1321
+ }
1322
+ return (profiles || [])[0];
1323
+ }
1324
+ catch {
1325
+ return undefined;
1326
+ }
1327
+ })();
1328
+ const shouldSeedContext = (() => {
1329
+ try {
1330
+ // Check for new editorContextMode first
1331
+ const mode = profileForSeeding?.editorContextMode;
1332
+ if (mode !== undefined) {
1333
+ return mode === "onCreate" || mode === "live";
1334
+ }
1335
+ // Backward compatibility: check old includeEditorContextOnCreate boolean
1336
+ if (profileForSeeding?.includeEditorContextOnCreate !== undefined) {
1337
+ return !!profileForSeeding.includeEditorContextOnCreate;
1338
+ }
1339
+ // Default to true when unspecified
1340
+ return true;
1341
+ }
1342
+ catch {
1343
+ return true;
1344
+ }
1345
+ })();
1346
+ // Create context with top-level properties (what ContextInfoBar expects)
1347
+ const localCtx = item && shouldSeedContext
1348
+ ? {
1349
+ items: [
1350
+ {
1351
+ id: item.id,
1352
+ language: item.language,
1353
+ version: item.version,
1354
+ name: editContext?.contentEditorItem?.name,
1355
+ },
1356
+ ],
1357
+ components: editContext?.selection?.length && item
1358
+ ? editContext.selection.map((componentId) => ({
1359
+ componentId,
1360
+ pageItem: {
1361
+ id: item.id,
1362
+ language: item.language,
1363
+ version: item.version,
1364
+ name: editContext?.contentEditorItem?.name,
1365
+ },
1366
+ }))
1367
+ : undefined,
1368
+ field: fieldsContext?.focusedField?.fieldId &&
1369
+ fieldsContext.focusedField?.item?.id
1370
+ ? {
1371
+ fieldId: fieldsContext.focusedField.fieldId,
1372
+ fieldName: fieldsContext.focusedField
1373
+ .fieldName,
1374
+ item: {
1375
+ id: fieldsContext.focusedField.item.id,
1376
+ language: fieldsContext.focusedField.item.language ||
1377
+ editContext?.currentItemDescriptor?.language ||
1378
+ "en",
1379
+ version: fieldsContext.focusedField.item.version ??
1380
+ editContext?.currentItemDescriptor?.version ??
1381
+ 0,
1382
+ name: editContext?.contentEditorItem?.name,
1383
+ },
1384
+ }
1385
+ : undefined,
1386
+ }
1387
+ : null;
1388
+ let nextMetadata = null;
1389
+ if (initialMetadata) {
1390
+ // Merge initial metadata with local context (using top-level structure)
1391
+ const base = { ...initialMetadata };
1392
+ if (localCtx) {
1393
+ // Merge items (avoid duplicates)
1394
+ if (localCtx.items && localCtx.items.length) {
1395
+ const targetPages = Array.isArray(base.items)
1396
+ ? [...base.items]
1397
+ : [];
1398
+ const existingKeys = new Set(targetPages.map((p) => `${p.id}-${p.language || ""}-${p.version || ""}`));
1399
+ const additions = localCtx.items.filter((p) => !existingKeys.has(`${p.id}-${p.language || ""}-${p.version || ""}`));
1400
+ if (additions.length)
1401
+ base.items = [...targetPages, ...additions];
1402
+ }
1403
+ // Merge components (avoid duplicates)
1404
+ if (localCtx.components && localCtx.components.length) {
1405
+ const currentComponents = Array.isArray(base.components)
1406
+ ? base.components
1407
+ : [];
1408
+ const existingIds = new Set(currentComponents.map((c) => c.componentId));
1409
+ const additions = localCtx.components.filter((c) => !!c?.componentId && !existingIds.has(c.componentId));
1410
+ if (additions.length)
1411
+ base.components = [...currentComponents, ...additions];
1412
+ }
1413
+ // Set field if missing
1414
+ if (!base.field && localCtx.field) {
1415
+ base.field = localCtx.field;
1416
+ }
1417
+ }
1418
+ nextMetadata = base;
1419
+ }
1420
+ else {
1421
+ nextMetadata = localCtx;
1422
+ }
1423
+ if (nextMetadata) {
1424
+ setAgentMetadata(sanitizeAgentMetadata(nextMetadata));
1425
+ // If an initial prompt is provided via metadata, seed the input once
1426
+ try {
1427
+ const maybePrompt = nextMetadata?.additionalData
1428
+ ?.initialPrompt;
1429
+ if (typeof maybePrompt === "string" && maybePrompt.trim()) {
1430
+ setPrompt(maybePrompt);
1431
+ }
1432
+ }
1433
+ catch { }
1434
+ }
1435
+ // Only return early if we have no existing messages
1436
+ // If we have messages, continue to load from backend to merge them
1437
+ if (!hasExistingMessages) {
1438
+ return;
1439
+ }
1440
+ }
1441
+ setIsLoading(true);
1442
+ setError(null);
1443
+ const agentData = await getAgent(agentStub.id);
1444
+ setAgent(agentData);
1445
+ // Merge database messages with any existing local messages using ID-based deduplication
1446
+ // This prevents both missing messages and duplicates
1447
+ // Use messagesRef.current instead of prevMessages to ensure we have the latest messages
1448
+ const dbMessages = agentData.messages || [];
1449
+ // Track all DB message IDs as "seen" to prevent WebSocket duplicates
1450
+ dbMessages.forEach((msg) => {
1451
+ if (msg.id) {
1452
+ seenMessageIdsRef.current.add(msg.id.toLowerCase());
1453
+ }
1454
+ });
1455
+ // Keep local streaming only if the agent is still running; otherwise discard locals
1456
+ const isRunning = agentData.status === "running" || agentData.status === 1;
1457
+ // Filter local messages to only include streaming/incomplete messages that aren't in DB
1458
+ // This prevents duplicates when reloading - DB messages are source of truth for completed messages
1459
+ const localStreaming = isRunning
1460
+ ? messagesRef.current.filter((localMsg) => {
1461
+ if (!localMsg.id)
1462
+ return false;
1463
+ // Keep streaming messages that aren't completed
1464
+ if (!localMsg.isCompleted && localMsg.messageType === "streaming") {
1465
+ // Check if this message exists in DB
1466
+ const existsInDb = dbMessages.some((dbMsg) => dbMsg.id &&
1467
+ dbMsg.id.toLowerCase() === localMsg.id.toLowerCase());
1468
+ // Keep if it doesn't exist in DB (truly local streaming)
1469
+ return !existsInDb;
1470
+ }
1471
+ // Don't keep completed messages from local state - DB is source of truth
1472
+ return false;
1473
+ })
1474
+ : [];
1475
+ const merged = mergeMessagesById(dbMessages, localStreaming);
1476
+ messagesRef.current = merged;
1477
+ setMessages(merged);
1478
+ // Normalize waiting/connecting/dots state based on freshly loaded status
1479
+ const runningNow = agentData.status === "running" || agentData.status === 1;
1480
+ const hasStreamingNow = merged.some((m) => !m.isCompleted && m.messageType === "streaming");
1481
+ if (runningNow || hasStreamingNow) {
1482
+ setIsWaitingForResponse(true);
1483
+ isWaitingRef.current = true;
1484
+ }
1485
+ else {
1486
+ setIsWaitingForResponse(false);
1487
+ isWaitingRef.current = false;
1488
+ setIsConnecting(false);
1489
+ }
1490
+ resetDotsTimer();
1491
+ // Check if cost limit was exceeded (detect from existing messages)
1492
+ try {
1493
+ const costLimitMessage = (agentData.messages || []).find((msg) => msg.role === "assistant" &&
1494
+ msg.content &&
1495
+ msg.content.startsWith("⚠️") &&
1496
+ msg.content.includes("Cost limit"));
1497
+ if (costLimitMessage &&
1498
+ costLimitMessage.content &&
1499
+ agentData.costLimit) {
1500
+ // Extract cost from the message if possible
1501
+ const match = costLimitMessage.content.match(/Current cost: \$([0-9.]+)/);
1502
+ const totalCost = match && match[1] ? parseFloat(match[1]) : agentData.totalCost || 0;
1503
+ setCostLimitExceeded({
1504
+ totalCost: totalCost,
1505
+ costLimit: agentData.costLimit,
1506
+ initialCostLimit: agentData.costLimit,
1507
+ });
1508
+ }
1509
+ else if (agentData.costLimit &&
1510
+ agentData.totalCost &&
1511
+ agentData.totalCost > agentData.costLimit) {
1512
+ setCostLimitExceeded({
1513
+ totalCost: agentData.totalCost,
1514
+ costLimit: agentData.costLimit,
1515
+ initialCostLimit: agentData.costLimit,
1516
+ });
1517
+ }
1518
+ }
1519
+ catch (e) {
1520
+ console.error("Failed to check cost limit on load:", e);
1521
+ }
1522
+ // Parse metadata from DB if present (do not seed for existing agents)
1523
+ const parsedMeta = (() => {
1524
+ try {
1525
+ const contextJson = agentData.agentContext;
1526
+ if (!contextJson)
1527
+ return null;
1528
+ const parsedContext = JSON.parse(contextJson);
1529
+ // Context is stored as flat structure with top-level properties
1530
+ if (parsedContext && typeof parsedContext === "object") {
1531
+ return parsedContext;
1532
+ }
1533
+ return null;
1534
+ }
1535
+ catch {
1536
+ return null;
1537
+ }
1538
+ })();
1539
+ // For existing agents, use database metadata or none
1540
+ setAgentMetadata(sanitizeAgentMetadata(parsedMeta));
1541
+ }
1542
+ catch (err) {
1543
+ console.error("❌ Failed to load agent:", err);
1544
+ // For new agents that don't exist yet, this is expected
1545
+ if (err?.message?.includes("404") ||
1546
+ err?.message?.includes("not found")) {
1547
+ // Agent does not exist, treat as new
1548
+ // But preserve existing messages if we have them (from WebSocket updates)
1549
+ const hasExistingMessages = messagesRef.current.length > 0;
1550
+ setAgent(undefined);
1551
+ if (!hasExistingMessages) {
1552
+ setMessages([]);
1553
+ }
1554
+ setError(null);
1555
+ }
1556
+ else {
1557
+ console.error("❌ Load error:", err.message);
1558
+ setError("Failed to load agent data");
1559
+ }
1560
+ }
1561
+ finally {
1562
+ setIsLoading(false);
1563
+ }
1564
+ }, [agentStub.id]);
1565
+ // Initial load
1566
+ useEffect(() => {
1567
+ loadAgent();
1568
+ }, [loadAgent]);
1569
+ // Reload agent when tab becomes active to get latest messages
1570
+ const previousIsActiveRef = useRef(isActive);
1571
+ useEffect(() => {
1572
+ const wasInactive = !previousIsActiveRef.current;
1573
+ const isNowActive = isActive;
1574
+ previousIsActiveRef.current = isActive;
1575
+ if (wasInactive && isNowActive && agent) {
1576
+ loadAgent();
1577
+ }
1578
+ }, [isActive, agent?.id, loadAgent]);
1579
+ // Watch for cost limit exceeded based on agent status or cost values
1580
+ useEffect(() => {
1581
+ if (!agent) {
1582
+ setCostLimitExceeded(null);
1583
+ return;
1584
+ }
1585
+ // Check if cost limit exceeded based on status or cost values
1586
+ const statusIndicatesLimit = agent.status === "costLimitReached" || agent.status === 7;
1587
+ const costExceedsLimit = agent.costLimit && agent.totalCost && agent.totalCost > agent.costLimit;
1588
+ if (statusIndicatesLimit || costExceedsLimit) {
1589
+ // Only set if not already set to avoid unnecessary re-renders
1590
+ setCostLimitExceeded((prev) => {
1591
+ const totalCost = agent.totalCost || 0;
1592
+ const costLimit = agent.costLimit || 0;
1593
+ // Check if values actually changed
1594
+ if (prev?.totalCost === totalCost && prev?.costLimit === costLimit) {
1595
+ return prev;
1596
+ }
1597
+ return {
1598
+ totalCost,
1599
+ costLimit,
1600
+ initialCostLimit: costLimit,
1601
+ };
1602
+ });
1603
+ }
1604
+ else {
1605
+ // Clear cost limit exceeded if status changed back
1606
+ setCostLimitExceeded((prev) => (prev ? null : prev));
1607
+ }
1608
+ }, [agent?.status, agent?.totalCost, agent?.costLimit]);
1609
+ // WebSocket message handler for agent streaming
1610
+ const handleAgentWebSocketMessage = useCallback((message) => {
1611
+ if (!agent)
1612
+ return;
1613
+ const messageType = message.type;
1614
+ // Handle agent:name:updated (payload structure is different)
1615
+ if (messageType === "agent:name:updated") {
1616
+ const { agentId: updatedAgentId, agentName } = message.payload;
1617
+ if (updatedAgentId === agent.id && agentName) {
1618
+ setAgent((prev) => (prev ? { ...prev, name: agentName } : prev));
1619
+ }
1620
+ return;
1621
+ }
1622
+ // For other agent messages, check if this is for our agent
1623
+ const agentId = message.payload?.agentId;
1624
+ if (agentId !== agent.id)
1625
+ return;
1626
+ // Handle agent:run:start
1627
+ if (messageType === "agent:run:start") {
1628
+ // Reset run-scoped deduplication so new run seq values (starting at 1)
1629
+ // are not discarded due to previous run's lastSeqRef
1630
+ lastSeqRef.current = 0;
1631
+ // Prep streaming UI state for the new run
1632
+ setIsConnecting(true);
1633
+ setIsWaitingForResponse(true);
1634
+ isWaitingRef.current = true;
1635
+ shouldCreateNewMessage.current = false;
1636
+ resetDotsTimer();
1637
+ return;
1638
+ }
1639
+ // Handle agent:user:message
1640
+ if (messageType === "agent:user:message") {
1641
+ const { messageId, content, timestamp, sourceAgentName, sourceAgent } = message.payload;
1642
+ // Track in seenMessageIds for deduplication
1643
+ const normalizedId = messageId.toLowerCase();
1644
+ if (seenMessageIdsRef.current.has(normalizedId)) {
1645
+ return;
1646
+ }
1647
+ seenMessageIdsRef.current.add(normalizedId);
1648
+ // Add user message to the messages list
1649
+ setMessages((prev) => {
1650
+ // Double-check if message already exists (deduplication)
1651
+ if (prev.some((m) => m.id && m.id.toLowerCase() === normalizedId)) {
1652
+ return prev;
1653
+ }
1654
+ const userMessage = {
1655
+ id: messageId,
1656
+ agentId: agent.id,
1657
+ messageIndex: prev.length,
1658
+ role: "user",
1659
+ content: content,
1660
+ name: "user",
1661
+ messageType: "user",
1662
+ isCompleted: true,
1663
+ model: "",
1664
+ tokensUsed: 0,
1665
+ inputTokens: 0,
1666
+ outputTokens: 0,
1667
+ cachedInputTokens: 0,
1668
+ inputTokenCost: 0,
1669
+ outputTokenCost: 0,
1670
+ cachedInputTokenCost: 0,
1671
+ totalCost: 0,
1672
+ currency: "USD",
1673
+ createdDate: timestamp || new Date().toISOString(),
1674
+ toolCalls: [],
1675
+ // Store source agent information for display
1676
+ ...(sourceAgentName || sourceAgent?.name
1677
+ ? {
1678
+ sourceAgentName: sourceAgentName || sourceAgent?.name,
1679
+ }
1680
+ : {}),
1681
+ };
1682
+ const updated = [...prev, userMessage];
1683
+ messagesRef.current = updated;
1684
+ return updated;
1685
+ });
1686
+ return;
1687
+ }
1688
+ // Handle agent:prompt:queued
1689
+ if (messageType === "agent:prompt:queued") {
1690
+ const { queueEntry } = message.payload;
1691
+ if (queueEntry) {
1692
+ // Add the new prompt to the queued prompts list
1693
+ setQueuedPrompts((prev) => {
1694
+ // Check if prompt already exists (deduplication)
1695
+ if (prev.some((p) => p.id === queueEntry.id)) {
1696
+ return prev;
1697
+ }
1698
+ return [...prev, queueEntry];
1699
+ });
1700
+ }
1701
+ return;
1702
+ }
1703
+ // Handle agent:prompt:processed
1704
+ if (messageType === "agent:prompt:processed") {
1705
+ const { promptId } = message.payload;
1706
+ if (promptId) {
1707
+ // Remove the processed prompt from the queued prompts list
1708
+ setQueuedPrompts((prev) => prev.filter((p) => p.id !== promptId));
1709
+ }
1710
+ return;
1711
+ }
1712
+ // Handle agent:run:delta (content, tools, etc.)
1713
+ if (messageType === "agent:run:delta") {
1714
+ // Allow deltas if the agent is running OR if we already have an active streaming message
1715
+ // OR if the server provided a messageId for targeted updates.
1716
+ // This avoids dropping early deltas that may arrive before the 'running' status update.
1717
+ const isRunning = agent.status === "running" || agent.status === 1;
1718
+ const hasStreaming = messagesRef.current.some((m) => !m.isCompleted && m.messageType === "streaming");
1719
+ const hasMessageId = !!message?.payload?.data?.messageId ||
1720
+ !!message?.payload?.data?.MessageId;
1721
+ if (!isRunning && !hasStreaming && !hasMessageId) {
1722
+ return; // ignore only if we cannot safely target an existing streaming message
1723
+ }
1724
+ const { seq, type, data, cost } = message.payload;
1725
+ // Deduplicate by sequence
1726
+ if (seq && seq <= lastSeqRef.current) {
1727
+ return; // Already processed
1728
+ }
1729
+ if (seq) {
1730
+ lastSeqRef.current = seq;
1731
+ }
1732
+ // Route based on delta type
1733
+ const agentStreamMessage = {
1734
+ type,
1735
+ data,
1736
+ cost,
1737
+ timestamp: new Date().toISOString(),
1738
+ };
1739
+ if (type === "ContentChunk" || type === "contentChunk") {
1740
+ handleContentChunk(agentStreamMessage, agent);
1741
+ }
1742
+ else if (type === "ToolCall" || type === "toolCall") {
1743
+ handleToolCall(agentStreamMessage, agent);
1744
+ }
1745
+ else if (type === "ToolResult" || type === "toolResult") {
1746
+ handleToolResult(agentStreamMessage, agent);
1747
+ }
1748
+ return;
1749
+ }
1750
+ // Unified: agent:run:status (state only)
1751
+ if (messageType === "agent:run:status") {
1752
+ const { seq, data: statusData } = message.payload;
1753
+ // Deduplicate by sequence
1754
+ if (seq && seq <= lastSeqRef.current) {
1755
+ return;
1756
+ }
1757
+ if (seq) {
1758
+ lastSeqRef.current = seq;
1759
+ }
1760
+ // Route based on statusData.state
1761
+ try {
1762
+ // Normalize various status shapes and handle Cancelled uniformly
1763
+ const normalizedStatus = statusData?.state ||
1764
+ statusData?.Status ||
1765
+ statusData?.status;
1766
+ if (normalizedStatus === "Cancelled" ||
1767
+ normalizedStatus === "canceled") {
1768
+ // Stop indicators and mark any in-progress streaming messages as completed
1769
+ setIsWaitingForResponse(false);
1770
+ isWaitingRef.current = false;
1771
+ setIsConnecting(false);
1772
+ setMessages((prev) => {
1773
+ const updated = prev.map((msg) => !msg.isCompleted && msg.messageType === "streaming"
1774
+ ? {
1775
+ ...msg,
1776
+ isCompleted: true,
1777
+ messageType: "completed",
1778
+ }
1779
+ : msg);
1780
+ messagesRef.current = updated;
1781
+ return updated;
1782
+ });
1783
+ resetDotsTimer();
1784
+ return;
1785
+ }
1786
+ if (statusData?.state === "streamOpen") {
1787
+ setIsConnecting(false);
1788
+ return;
1789
+ }
1790
+ if (statusData?.state === "tokenUsage") {
1791
+ const totals = statusData?.totals;
1792
+ if (totals) {
1793
+ const totalCost = Number(totals.totalCost) || 0;
1794
+ const statusCostLimit = (() => {
1795
+ try {
1796
+ const v = statusData?.costLimit;
1797
+ const n = v != null ? Number(v) : undefined;
1798
+ return Number.isFinite(n) && n > 0
1799
+ ? n
1800
+ : undefined;
1801
+ }
1802
+ catch {
1803
+ return undefined;
1804
+ }
1805
+ })();
1806
+ const nextTotals = {
1807
+ input: Number(totals.totalInputTokens) || 0,
1808
+ output: Number(totals.totalOutputTokens) || 0,
1809
+ cached: Number(totals.totalCachedInputTokens) || 0,
1810
+ cacheWrite: Number(totals.totalCacheWriteTokens) || 0,
1811
+ inputCost: Number(totals.totalInputTokenCost) || 0,
1812
+ outputCost: Number(totals.totalOutputTokenCost) || 0,
1813
+ cachedCost: Number(totals.totalCachedInputTokenCost) || 0,
1814
+ cacheWriteCost: Number(totals.totalCacheWriteTokenCost) || 0,
1815
+ totalCost: totalCost,
1816
+ currency: totals.currency,
1817
+ };
1818
+ const anyNonZero = (nextTotals.totalCost || 0) > 0 ||
1819
+ (nextTotals.input || 0) > 0 ||
1820
+ (nextTotals.output || 0) > 0 ||
1821
+ (nextTotals.cached || 0) > 0 ||
1822
+ (nextTotals.cacheWrite || 0) > 0;
1823
+ if (anyNonZero) {
1824
+ setLiveTotals(nextTotals);
1825
+ }
1826
+ // If server provides costLimit along with totals, persist it locally
1827
+ if (statusCostLimit) {
1828
+ setAgent((prev) => prev &&
1829
+ (!prev.costLimit || prev.costLimit !== statusCostLimit)
1830
+ ? { ...prev, costLimit: statusCostLimit }
1831
+ : prev);
1832
+ }
1833
+ if (agent?.costLimit && totalCost > agent.costLimit) {
1834
+ setCostLimitExceeded({
1835
+ totalCost: totalCost,
1836
+ costLimit: agent.costLimit,
1837
+ initialCostLimit: agent.costLimit,
1838
+ });
1839
+ setIsWaitingForResponse(false);
1840
+ shouldCreateNewMessage.current = false;
1841
+ }
1842
+ setMessages((prev) => [...prev]);
1843
+ }
1844
+ return;
1845
+ }
1846
+ if (statusData?.state === "ToolApprovalsRequired") {
1847
+ const msgId = statusData.messageId;
1848
+ const ids = statusData.toolCallIds || [];
1849
+ if (msgId && Array.isArray(ids) && ids.length > 0) {
1850
+ setMessages((prev) => {
1851
+ const updated = prev.map((m) => {
1852
+ if (m.id !== msgId)
1853
+ return m;
1854
+ const existingToolCalls = m.toolCalls || [];
1855
+ const updatedToolCalls = existingToolCalls.map((tc) => {
1856
+ if (!ids.includes(tc.toolCallId))
1857
+ return tc;
1858
+ const fn = tc.functionName || "";
1859
+ return {
1860
+ ...tc,
1861
+ functionName: fn.includes("(pending approval)")
1862
+ ? fn
1863
+ : fn + " (pending approval)",
1864
+ };
1865
+ });
1866
+ return { ...m, toolCalls: updatedToolCalls };
1867
+ });
1868
+ messagesRef.current = updated;
1869
+ return updated;
1870
+ });
1871
+ }
1872
+ setIsConnecting(false);
1873
+ setIsWaitingForResponse(false);
1874
+ return;
1875
+ }
1876
+ if (statusData?.state === "CostLimitReached") {
1877
+ const totalCost = Number(statusData.totalCost) || 0;
1878
+ const costLimit = Number(statusData.costLimit) || agent?.costLimit || 0;
1879
+ setCostLimitExceeded({
1880
+ totalCost: totalCost,
1881
+ costLimit: costLimit,
1882
+ initialCostLimit: costLimit,
1883
+ });
1884
+ setIsWaitingForResponse(false);
1885
+ setIsConnecting(false);
1886
+ return;
1887
+ }
1888
+ if (statusData?.state === "contextWindow") {
1889
+ window.__agentContextWindowStatus = {
1890
+ model: statusData.model,
1891
+ normalizedModel: statusData.normalizedModel,
1892
+ contextWindowTokens: statusData.contextWindowTokens,
1893
+ maxCompletionTokens: statusData.maxCompletionTokens,
1894
+ estimatedInputTokens: statusData.estimatedInputTokens,
1895
+ messageCount: statusData.messageCount,
1896
+ contextUsedPercent: statusData.contextUsedPercent,
1897
+ };
1898
+ setMessages((prev) => [...prev]);
1899
+ return;
1900
+ }
1901
+ if (statusData?.state === "contextChanged") {
1902
+ const nextContext = statusData.context || {};
1903
+ setAgentMetadata((prev) => {
1904
+ const current = (prev || {});
1905
+ const currentWithoutContext = { ...current };
1906
+ delete currentWithoutContext.context;
1907
+ const next = {
1908
+ ...currentWithoutContext,
1909
+ additionalData: {
1910
+ ...(current.additionalData || {}),
1911
+ context: nextContext,
1912
+ },
1913
+ };
1914
+ return next;
1915
+ });
1916
+ return;
1917
+ }
1918
+ }
1919
+ catch (err) {
1920
+ console.error("[AgentTerminal] Error handling status update:", err);
1921
+ }
1922
+ return;
1923
+ }
1924
+ // Lifecycle: agent:run:complete
1925
+ if (messageType === "agent:run:complete") {
1926
+ // Reset deduplication for the next run
1927
+ lastSeqRef.current = 0;
1928
+ // Mark the last assistant message as completed
1929
+ setMessages((prev) => {
1930
+ const updated = prev.map((msg) => msg.role === "assistant" && !msg.isCompleted
1931
+ ? {
1932
+ ...msg,
1933
+ isCompleted: true,
1934
+ messageType: "completed",
1935
+ }
1936
+ : msg);
1937
+ messagesRef.current = updated;
1938
+ return updated;
1939
+ });
1940
+ setIsWaitingForResponse(false);
1941
+ isWaitingRef.current = false;
1942
+ setIsConnecting(false);
1943
+ shouldCreateNewMessage.current = false;
1944
+ resetDotsTimer();
1945
+ return;
1946
+ }
1947
+ // Lifecycle: agent:run:error
1948
+ if (messageType === "agent:run:error") {
1949
+ const errorMsg = message.payload?.error || "Unknown error";
1950
+ // Reset deduplication for the next run after an error
1951
+ lastSeqRef.current = 0;
1952
+ setError(errorMsg);
1953
+ setIsWaitingForResponse(false);
1954
+ isWaitingRef.current = false;
1955
+ setIsConnecting(false);
1956
+ resetDotsTimer();
1957
+ return;
1958
+ }
1959
+ }, [
1960
+ agent,
1961
+ handleContentChunk,
1962
+ handleToolCall,
1963
+ handleToolResult,
1964
+ resetDotsTimer,
1965
+ ]);
1966
+ // Keep refs for latest agent and resetDotsTimer to avoid adding them to effect deps
1967
+ const agentRef = useRef(agent);
1968
+ const resetDotsTimerRef = useRef(resetDotsTimer);
1969
+ const handleAgentWebSocketMessageRef = useRef(handleAgentWebSocketMessage);
1970
+ useEffect(() => {
1971
+ agentRef.current = agent;
1972
+ }, [agent]);
1973
+ useEffect(() => {
1974
+ resetDotsTimerRef.current = resetDotsTimer;
1975
+ }, [resetDotsTimer]);
1976
+ useEffect(() => {
1977
+ handleAgentWebSocketMessageRef.current = handleAgentWebSocketMessage;
1978
+ }, [handleAgentWebSocketMessage]);
1979
+ // Subscribe to agent WebSocket messages when active
1980
+ useEffect(() => {
1981
+ const addListener = editContext?.addSocketMessageListener;
1982
+ if (!isActive || !addListener) {
1983
+ // Unsubscribe if we were previously subscribed
1984
+ if (subscribedAgentIdRef.current) {
1985
+ const socket = globalThis.editorSocket;
1986
+ if (socket && socket.readyState === WebSocket.OPEN) {
1987
+ socket.send(JSON.stringify({
1988
+ type: "agent:unsubscribe",
1989
+ agentId: subscribedAgentIdRef.current,
1990
+ }));
1991
+ }
1992
+ subscribedAgentIdRef.current = null;
1993
+ }
1994
+ return;
1995
+ }
1996
+ // Send subscription message to server
1997
+ const socket = globalThis.editorSocket;
1998
+ if (socket && socket.readyState === WebSocket.OPEN) {
1999
+ socket.send(JSON.stringify({
2000
+ type: "agent:subscribe",
2001
+ agentId: agentStub.id,
2002
+ }));
2003
+ }
2004
+ // Use the addSocketMessageListener helper from editContext
2005
+ // Wrap the handler in a stable function that uses the ref
2006
+ const stableHandler = (message) => {
2007
+ handleAgentWebSocketMessageRef.current(message);
2008
+ };
2009
+ const unsubscribe = addListener(stableHandler);
2010
+ subscribedAgentIdRef.current = agentStub.id;
2011
+ // Reset deduplication state when switching agents
2012
+ seenMessageIdsRef.current.clear();
2013
+ lastSeqRef.current = 0;
2014
+ // Set up streaming state based on agent status (uses latest values via refs)
2015
+ const currentAgent = agentRef.current;
2016
+ if (currentAgent) {
2017
+ const isRunning = currentAgent.status === "running" || currentAgent.status === 1;
2018
+ const isWaitingForApproval = currentAgent.status === "waitingForApproval" ||
2019
+ currentAgent.status === 2;
2020
+ if (isRunning) {
2021
+ setIsWaitingForResponse(true);
2022
+ isWaitingRef.current = true;
2023
+ shouldCreateNewMessage.current = false;
2024
+ resetDotsTimerRef.current();
2025
+ }
2026
+ else if (isWaitingForApproval) {
2027
+ setIsWaitingForResponse(false);
2028
+ isWaitingRef.current = false;
2029
+ resetDotsTimerRef.current();
2030
+ }
2031
+ else {
2032
+ setIsWaitingForResponse(false);
2033
+ isWaitingRef.current = false;
2034
+ resetDotsTimerRef.current();
2035
+ }
2036
+ }
2037
+ return () => {
2038
+ // Send unsubscribe message to server
2039
+ const socket = globalThis.editorSocket;
2040
+ if (socket &&
2041
+ socket.readyState === WebSocket.OPEN &&
2042
+ subscribedAgentIdRef.current) {
2043
+ socket.send(JSON.stringify({
2044
+ type: "agent:unsubscribe",
2045
+ agentId: subscribedAgentIdRef.current,
2046
+ }));
2047
+ }
2048
+ unsubscribe();
2049
+ subscribedAgentIdRef.current = null;
2050
+ };
2051
+ }, [isActive, agentStub.id, editContext?.addSocketMessageListener]);
2052
+ // Focus prompt when requested globally (from AI command)
2053
+ useEffect(() => {
2054
+ const focusHandler = () => {
2055
+ try {
2056
+ if (textareaRef.current) {
2057
+ textareaRef.current.focus();
2058
+ // Move caret to end
2059
+ const value = textareaRef.current.value || "";
2060
+ textareaRef.current.selectionStart = value.length;
2061
+ textareaRef.current.selectionEnd = value.length;
2062
+ }
2063
+ }
2064
+ catch { }
2065
+ };
2066
+ window.addEventListener("editor:focusAgentPrompt", focusHandler);
2067
+ return () => window.removeEventListener("editor:focusAgentPrompt", focusHandler);
2068
+ }, []);
2069
+ // Profiles are provided by parent component (Agents). No local loading here.
2070
+ // Select active profile based on agent.profileId or agentStub.profileId
2071
+ useEffect(() => {
2072
+ if (!profiles || profiles.length === 0)
2073
+ return;
2074
+ // For new agents, use agentStub.profileId; for loaded agents, use agent.profileId
2075
+ const profileIdToUse = agent?.profileId || agentStub.profileId;
2076
+ // Use case-insensitive comparison for GUID matching (backend may return different casing)
2077
+ const normalizedProfileId = profileIdToUse?.toLowerCase();
2078
+ const candidate = normalizedProfileId
2079
+ ? (profiles.find((p) => p.id?.toLowerCase() === normalizedProfileId) ??
2080
+ profiles[0])
2081
+ : profiles[0];
2082
+ if (candidate && (!activeProfile || activeProfile.id !== candidate.id)) {
2083
+ setActiveProfile(candidate);
2084
+ }
2085
+ }, [profiles, agent?.profileId, agentStub.profileId]);
2086
+ // Fetch initial queued prompts on mount, then rely on WebSocket updates
2087
+ useEffect(() => {
2088
+ if (!agent?.id) {
2089
+ setQueuedPrompts([]);
2090
+ return;
2091
+ }
2092
+ // Fetch once on mount, then rely on WebSocket updates
2093
+ const fetchInitialPrompts = async () => {
2094
+ try {
2095
+ const prompts = await getPendingPrompts(agent.id);
2096
+ setQueuedPrompts(prompts);
2097
+ }
2098
+ catch (error) {
2099
+ console.error("Failed to fetch initial queued prompts:", error);
2100
+ }
2101
+ };
2102
+ fetchInitialPrompts();
2103
+ }, [agent?.id]);
2104
+ // Update selected model when the active profile or agent model changes
2105
+ useEffect(() => {
2106
+ if (!activeProfile)
2107
+ return;
2108
+ const agentModelName = agent?.model; // persisted as model NAME on server
2109
+ const models = activeProfile.models || [];
2110
+ let nextModelId = undefined;
2111
+ if (agentModelName) {
2112
+ const match = models.find((m) => (m.name || "").toLowerCase() === agentModelName.toLowerCase());
2113
+ if (match)
2114
+ nextModelId = match.id;
2115
+ }
2116
+ if (!nextModelId) {
2117
+ nextModelId = activeProfile.defaultModelId || models[0]?.id;
2118
+ }
2119
+ setSelectedModelId(nextModelId || undefined);
2120
+ }, [activeProfile?.id, agent?.model]);
2121
+ // Cleanup stream connection when component unmounts or agent changes
2122
+ useEffect(() => {
2123
+ return () => {
2124
+ if (abortControllerRef.current) {
2125
+ abortControllerRef.current.abort();
2126
+ }
2127
+ };
2128
+ }, [agent?.id]);
2129
+ // Initialize mode from metadata; fall back to agent.Mode from server
2130
+ useEffect(() => {
2131
+ try {
2132
+ const metaMode = agentMetadata?.mode;
2133
+ if (metaMode === "autonomous" ||
2134
+ metaMode === "read-only" ||
2135
+ metaMode === "supervised") {
2136
+ setMode(metaMode);
2137
+ return;
2138
+ }
2139
+ }
2140
+ catch { }
2141
+ try {
2142
+ const serverMode = agent?.mode;
2143
+ if (serverMode === "autonomous" ||
2144
+ serverMode === "read-only" ||
2145
+ serverMode === "supervised") {
2146
+ setMode(serverMode);
2147
+ }
2148
+ }
2149
+ catch { }
2150
+ }, [agentMetadata, agent?.mode]);
2151
+ // Auto-scroll when messages change (only if user hasn't manually scrolled up)
2152
+ useLayoutEffect(() => {
2153
+ if (shouldAutoScroll) {
2154
+ scrollToBottom();
2155
+ }
2156
+ }, [messages, scrollToBottom, shouldAutoScroll]);
2157
+ // Persist any pending settings (mode/model) once an agent exists server-side
2158
+ const persistPendingSettingsIfNeeded = useCallback(async () => {
2159
+ try {
2160
+ if (!agent?.id)
2161
+ return;
2162
+ const pending = pendingSettingsRef.current;
2163
+ if (!pending)
2164
+ return;
2165
+ const payload = {};
2166
+ if (pending.modelName)
2167
+ payload.model = pending.modelName;
2168
+ if (pending.mode)
2169
+ payload.mode = pending.mode;
2170
+ if (Object.keys(payload).length === 0)
2171
+ return;
2172
+ await updateAgentSettings(agent.id, payload);
2173
+ pendingSettingsRef.current = null;
2174
+ }
2175
+ catch (e) {
2176
+ console.error("Failed to persist pending settings", e);
2177
+ }
2178
+ }, [agent?.id]);
2179
+ const handleSubmit = async () => {
2180
+ if (isSubmitting || !editContext)
2181
+ return;
2182
+ try {
2183
+ setIsSubmitting(true);
2184
+ setError(null);
2185
+ // For new agents, use agentStub.id; for existing agents, use agent.id
2186
+ const agentId = agent?.id || agentStub.id;
2187
+ if (!agentId)
2188
+ return;
2189
+ // Optional context factory: invoke if configured and available, otherwise continue
2190
+ const factoryName = agentMetadata?.additionalData
2191
+ ?.contextFactory;
2192
+ if (factoryName) {
2193
+ const factory = editContext.getContextFactory?.(factoryName);
2194
+ if (factory) {
2195
+ try {
2196
+ await Promise.resolve(factory());
2197
+ }
2198
+ catch (e) {
2199
+ console.warn(`Context factory '${factoryName}' failed: ${e?.message || String(e)}`);
2200
+ }
2201
+ }
2202
+ else {
2203
+ console.warn(`Context factory not found: ${factoryName}. Proceeding without it.`);
2204
+ }
2205
+ }
2206
+ // NOTE: User message is no longer added optimistically here
2207
+ // It will be added when we receive the agent:user:message broadcast from the server
2208
+ // This ensures all tabs (including the sending tab) have the same messageId from the database
2209
+ const request = {
2210
+ agentId: agentId,
2211
+ message: prompt.trim(),
2212
+ sessionId: editContext.sessionId,
2213
+ profileId: activeProfile?.id || profiles[0]?.id || "",
2214
+ profile: activeProfile?.name || profiles[0]?.name || "",
2215
+ model: selectedModelId,
2216
+ mode: mode,
2217
+ context: canonicalizeAgentMetadata(agentMetadata), // Canonicalize to ensure complete field structure
2218
+ deterministic: deterministicFlags.deterministic,
2219
+ seed: deterministicFlags.seed,
2220
+ };
2221
+ // Starting agent
2222
+ // Re-enable auto-scroll when user submits a new message
2223
+ setShouldAutoScroll(true);
2224
+ // No need to create a temporary message - the stream will create messages as needed
2225
+ const response = await startAgent(request);
2226
+ // Check if prompt was queued (agent was already running)
2227
+ const wasQueued = response.message?.toLowerCase().includes("queued") ||
2228
+ response.status === "Queued";
2229
+ if (wasQueued) {
2230
+ // Prompt was queued - show a brief notification but don't set waiting state
2231
+ // The prompt will be processed when the agent becomes idle
2232
+ console.log("Prompt queued for processing");
2233
+ // Don't set isWaitingForResponse since the agent is already running
2234
+ setIsWaitingForResponse(false);
2235
+ isWaitingRef.current = false;
2236
+ }
2237
+ else {
2238
+ // Normal submission - set waiting state to show dancing dots immediately
2239
+ setIsWaitingForResponse(true);
2240
+ // Update the ref immediately so resetDotsTimer sees the new state
2241
+ isWaitingRef.current = true;
2242
+ // Start idle timer; dots appear only if no chunks for >1s
2243
+ resetDotsTimer();
2244
+ }
2245
+ // If user changed mode/model while the agent was new, persist them now
2246
+ await persistPendingSettingsIfNeeded();
2247
+ // Save prompt to history
2248
+ if (prompt.trim()) {
2249
+ setPromptHistory((prev) => [
2250
+ prompt.trim(),
2251
+ ...prev.filter((p) => p !== prompt.trim()).slice(0, 9),
2252
+ ]);
2253
+ setCurrentHistoryIndex(-1);
2254
+ }
2255
+ setPrompt("");
2256
+ // WebSocket connection is already active via subscription - no need for SSE
2257
+ }
2258
+ catch (err) {
2259
+ console.error("Failed to submit prompt:", err);
2260
+ setError("Failed to submit prompt");
2261
+ setIsWaitingForResponse(false);
2262
+ // Remove the optimistically added user message on error
2263
+ setMessages((prev) => prev.slice(0, -1));
2264
+ }
2265
+ finally {
2266
+ setIsSubmitting(false);
2267
+ }
2268
+ };
2269
+ const handleKeyPress = (e) => {
2270
+ // Submit only on plain Enter (no Ctrl/Meta/Shift/Alt)
2271
+ if (e.key === "Enter" &&
2272
+ !e.ctrlKey &&
2273
+ !e.metaKey &&
2274
+ !e.shiftKey &&
2275
+ !e.altKey) {
2276
+ e.preventDefault();
2277
+ handleSubmit();
2278
+ }
2279
+ if (e.key === "ArrowUp") {
2280
+ // Only navigate history if prompt is empty or we're already navigating history
2281
+ const canNavigateHistory = prompt.trim().length === 0 || currentHistoryIndex !== -1;
2282
+ if (canNavigateHistory) {
2283
+ e.preventDefault();
2284
+ if (promptHistory.length > 0) {
2285
+ const newIndex = currentHistoryIndex < promptHistory.length - 1
2286
+ ? currentHistoryIndex + 1
2287
+ : currentHistoryIndex;
2288
+ setCurrentHistoryIndex(newIndex);
2289
+ const historicalPrompt = promptHistory[newIndex];
2290
+ if (textareaRef.current && historicalPrompt) {
2291
+ setPrompt(historicalPrompt);
2292
+ setTimeout(() => {
2293
+ if (textareaRef.current) {
2294
+ textareaRef.current.selectionStart = historicalPrompt.length;
2295
+ textareaRef.current.selectionEnd = historicalPrompt.length;
2296
+ }
2297
+ }, 0);
2298
+ }
2299
+ }
2300
+ }
2301
+ }
2302
+ if (e.key === "ArrowDown" && currentHistoryIndex >= 0) {
2303
+ e.preventDefault();
2304
+ const newIndex = currentHistoryIndex - 1;
2305
+ setCurrentHistoryIndex(newIndex);
2306
+ const historicalPrompt = newIndex >= 0 ? promptHistory[newIndex] || "" : "";
2307
+ setPrompt(historicalPrompt);
2308
+ if (textareaRef.current) {
2309
+ setTimeout(() => {
2310
+ if (textareaRef.current) {
2311
+ textareaRef.current.selectionStart = historicalPrompt.length;
2312
+ textareaRef.current.selectionEnd = historicalPrompt.length;
2313
+ }
2314
+ }, 0);
2315
+ }
2316
+ }
2317
+ };
2318
+ // Send a message programmatically (used by quick-action buttons)
2319
+ const sendQuickMessage = async (text) => {
2320
+ if (!text.trim() || isSubmitting || !editContext)
2321
+ return;
2322
+ try {
2323
+ setIsSubmitting(true);
2324
+ setError(null);
2325
+ const agentId = agent?.id;
2326
+ if (!agentId)
2327
+ return;
2328
+ // Optional context factory: invoke if configured and available, otherwise continue
2329
+ const factoryName = agentMetadata?.additionalData
2330
+ ?.contextFactory;
2331
+ if (factoryName) {
2332
+ const factory = editContext.getContextFactory?.(factoryName);
2333
+ if (factory) {
2334
+ try {
2335
+ await Promise.resolve(factory());
2336
+ }
2337
+ catch (e) {
2338
+ console.warn(`Context factory '${factoryName}' failed: ${e?.message || String(e)}`);
2339
+ }
2340
+ }
2341
+ else {
2342
+ console.warn(`Context factory not found: ${factoryName}. Proceeding without it.`);
2343
+ }
2344
+ }
2345
+ // NOTE: User message is no longer added optimistically here
2346
+ // It will be added when we receive the agent:user:message broadcast from the server
2347
+ // This ensures all tabs (including the sending tab) have the same messageId from the database
2348
+ const request = {
2349
+ agentId: agent.id,
2350
+ message: text.trim(),
2351
+ sessionId: editContext.sessionId,
2352
+ profileId: activeProfile?.id || profiles[0]?.id || "",
2353
+ profile: activeProfile?.name || profiles[0]?.name || "",
2354
+ model: selectedModelId,
2355
+ mode: mode,
2356
+ context: canonicalizeAgentMetadata(agentMetadata), // Canonicalize to ensure complete field structure
2357
+ deterministic: deterministicFlags.deterministic,
2358
+ seed: deterministicFlags.seed,
2359
+ };
2360
+ setIsWaitingForResponse(true);
2361
+ // Update the ref immediately so resetDotsTimer sees the new state
2362
+ isWaitingRef.current = true;
2363
+ resetDotsTimer();
2364
+ setShouldAutoScroll(true);
2365
+ await startAgent(request);
2366
+ // If user changed mode/model while the agent was new, persist them now
2367
+ await persistPendingSettingsIfNeeded();
2368
+ // WebSocket connection is already active via subscription - no need for SSE
2369
+ }
2370
+ catch (err) {
2371
+ console.error("Failed to submit quick message:", err);
2372
+ setError("Failed to submit prompt");
2373
+ setIsWaitingForResponse(false);
2374
+ setMessages((prev) => prev.slice(0, -1));
2375
+ }
2376
+ finally {
2377
+ setIsSubmitting(false);
2378
+ }
2379
+ };
2380
+ // Auto-send initial prompt if provided and agent has no messages yet
2381
+ const initialPromptSentRef = useRef(false);
2382
+ useEffect(() => {
2383
+ if (initialPrompt !== undefined &&
2384
+ !isLoading &&
2385
+ !initialPromptSentRef.current &&
2386
+ messages.length === 0 &&
2387
+ agentStub.id &&
2388
+ editContext &&
2389
+ activeProfile && // MUST have activeProfile set, not just profiles.length
2390
+ profiles.length > 0) {
2391
+ initialPromptSentRef.current = true;
2392
+ // Delay slightly to ensure all state is ready
2393
+ setTimeout(() => {
2394
+ setPrompt(initialPrompt);
2395
+ // Trigger submit programmatically
2396
+ handleSubmit();
2397
+ }, 200);
2398
+ }
2399
+ }, [
2400
+ initialPrompt,
2401
+ isLoading,
2402
+ messages.length,
2403
+ agentStub.id,
2404
+ editContext,
2405
+ activeProfile,
2406
+ profiles.length,
2407
+ handleSubmit,
2408
+ ]);
2409
+ // Resolve display names when metadata or editor state changes
2410
+ useEffect(() => {
2411
+ const metaCtx = agentMetadata;
2412
+ if (!metaCtx) {
2413
+ setResolvedPageName(undefined);
2414
+ setResolvedComponentName(undefined);
2415
+ setResolvedFieldName(undefined);
2416
+ return;
2417
+ }
2418
+ // Page names (for now, just resolve the first page)
2419
+ if (metaCtx.items?.length) {
2420
+ const firstPage = metaCtx.items[0];
2421
+ if (firstPage) {
2422
+ let name = firstPage.name;
2423
+ if (!name &&
2424
+ editContext?.contentEditorItem?.descriptor.id === firstPage.id &&
2425
+ editContext?.contentEditorItem?.name) {
2426
+ name = editContext.contentEditorItem.name;
2427
+ }
2428
+ else if (!name) {
2429
+ name = undefined;
2430
+ }
2431
+ setResolvedPageName(name);
2432
+ }
2433
+ else {
2434
+ setResolvedPageName(undefined);
2435
+ }
2436
+ }
2437
+ else
2438
+ setResolvedPageName(undefined);
2439
+ // Component names (for now, just resolve the first component)
2440
+ if (metaCtx.components?.length && editContext?.page) {
2441
+ const firstComponent = metaCtx.components[0];
2442
+ if (firstComponent?.componentId) {
2443
+ try {
2444
+ const comp = getComponentById(firstComponent.componentId, editContext.page);
2445
+ setResolvedComponentName(comp?.name);
2446
+ }
2447
+ catch {
2448
+ setResolvedComponentName(undefined);
2449
+ }
2450
+ }
2451
+ else {
2452
+ setResolvedComponentName(undefined);
2453
+ }
2454
+ }
2455
+ else
2456
+ setResolvedComponentName(undefined);
2457
+ // Field name (async)
2458
+ (async () => {
2459
+ if (metaCtx.field && editContext?.itemsRepository) {
2460
+ try {
2461
+ // Use the item descriptor from field context if available, otherwise fallback to current item
2462
+ const itemDescriptor = metaCtx.field.item || {
2463
+ id: editContext.currentItemDescriptor?.id || "",
2464
+ language: editContext.currentItemDescriptor?.language || "en",
2465
+ version: editContext.currentItemDescriptor?.version || 0,
2466
+ };
2467
+ const field = await editContext.itemsRepository.getField({
2468
+ item: itemDescriptor,
2469
+ fieldId: metaCtx.field.fieldId,
2470
+ });
2471
+ setResolvedFieldName(field?.name || metaCtx.field.fieldName);
2472
+ }
2473
+ catch {
2474
+ setResolvedFieldName(metaCtx.field.fieldName);
2475
+ }
2476
+ }
2477
+ else
2478
+ setResolvedFieldName(undefined);
2479
+ })();
2480
+ }, [
2481
+ agentMetadata,
2482
+ editContext?.page,
2483
+ editContext?.contentEditorItem,
2484
+ editContext?.currentItemDescriptor,
2485
+ editContext?.itemsRepository,
2486
+ ]);
2487
+ // Helper function to build current context from editor state
2488
+ const buildCurrentContext = useCallback(() => {
2489
+ if (!editContext?.currentItemDescriptor)
2490
+ return null;
2491
+ const item = editContext.currentItemDescriptor;
2492
+ return {
2493
+ items: [
2494
+ {
2495
+ id: item.id,
2496
+ language: item.language,
2497
+ version: item.version,
2498
+ name: editContext?.contentEditorItem?.name,
2499
+ },
2500
+ ],
2501
+ components: editContext?.selection?.length && item
2502
+ ? editContext.selection.map((componentId) => ({
2503
+ componentId,
2504
+ pageItem: {
2505
+ id: item.id,
2506
+ language: item.language,
2507
+ version: item.version,
2508
+ name: editContext?.contentEditorItem?.name,
2509
+ },
2510
+ }))
2511
+ : undefined,
2512
+ field: fieldsContext?.focusedField?.fieldId &&
2513
+ fieldsContext.focusedField?.item?.id
2514
+ ? {
2515
+ fieldId: fieldsContext.focusedField.fieldId,
2516
+ fieldName: fieldsContext.focusedField.fieldName,
2517
+ item: {
2518
+ id: fieldsContext.focusedField.item.id,
2519
+ language: fieldsContext.focusedField.item.language ||
2520
+ editContext?.currentItemDescriptor?.language ||
2521
+ "en",
2522
+ version: fieldsContext.focusedField.item.version ??
2523
+ editContext?.currentItemDescriptor?.version ??
2524
+ 0,
2525
+ name: editContext?.contentEditorItem?.name,
2526
+ },
2527
+ }
2528
+ : undefined,
2529
+ };
2530
+ }, [
2531
+ editContext?.currentItemDescriptor,
2532
+ editContext?.selection,
2533
+ editContext?.contentEditorItem?.name,
2534
+ fieldsContext?.focusedField,
2535
+ ]);
2536
+ // Live context updates: watch for changes and update agent context when in "live" mode
2537
+ const previousContextRef = useRef("");
2538
+ useEffect(() => {
2539
+ // Get profile from activeProfile or find it in profiles array
2540
+ const normalizedAgentProfileId = agent?.profileId?.toLowerCase();
2541
+ const profile = activeProfile ||
2542
+ profiles.find((p) => p.id?.toLowerCase() === normalizedAgentProfileId);
2543
+ if (!profile)
2544
+ return;
2545
+ const mode = profile.editorContextMode;
2546
+ // Only live mode should auto-update; legacy boolean is treated as "onCreate"
2547
+ const isLiveMode = mode === "live";
2548
+ if (!isLiveMode) {
2549
+ return;
2550
+ }
2551
+ // Extract key values for change detection (inside effect to ensure fresh values)
2552
+ const currentItemKey = editContext?.currentItemDescriptor
2553
+ ? `${editContext.currentItemDescriptor.id}-${editContext.currentItemDescriptor.language}-${editContext.currentItemDescriptor.version}`
2554
+ : "";
2555
+ const selectionKey = editContext?.selection?.join(",") || "";
2556
+ const focusedFieldKey = fieldsContext?.focusedField?.fieldId || "";
2557
+ // Create a key for the current context state
2558
+ const contextKey = `${currentItemKey}|${selectionKey}|${focusedFieldKey}`;
2559
+ // Skip if context hasn't actually changed
2560
+ if (contextKey === previousContextRef.current) {
2561
+ return;
2562
+ }
2563
+ // Update the previous context key immediately so we only process each change once
2564
+ previousContextRef.current = contextKey;
2565
+ // Apply the update immediately (no debounce) to avoid missing field changes
2566
+ (async () => {
2567
+ try {
2568
+ const currentCtx = buildCurrentContext();
2569
+ if (!currentCtx) {
2570
+ return;
2571
+ }
2572
+ // Merge with existing metadata to preserve other context (like comments)
2573
+ const existingMeta = agentMetadata || {};
2574
+ const merged = {
2575
+ ...existingMeta,
2576
+ items: currentCtx.items ? [...currentCtx.items] : undefined,
2577
+ components: currentCtx.components
2578
+ ? [...currentCtx.components]
2579
+ : undefined,
2580
+ field: currentCtx.field ? { ...currentCtx.field } : undefined,
2581
+ };
2582
+ // Remove undefined properties to ensure clean state
2583
+ if (!merged.items || merged.items.length === 0) {
2584
+ delete merged.items;
2585
+ }
2586
+ if (!merged.components || merged.components.length === 0) {
2587
+ delete merged.components;
2588
+ }
2589
+ if (!merged.field) {
2590
+ delete merged.field;
2591
+ }
2592
+ // Always update local metadata so UI reflects context even before agent is saved
2593
+ // Create a fresh object to ensure React detects the change
2594
+ const sanitized = sanitizeAgentMetadata(merged);
2595
+ setAgentMetadata(sanitized ? { ...sanitized } : null);
2596
+ // If the agent exists server-side, persist context as well
2597
+ if (agent?.id && agent.status !== "new") {
2598
+ await updateAgentContext(agent.id, merged);
2599
+ }
2600
+ }
2601
+ catch (err) {
2602
+ console.error("[Live Context] Failed to update context:", err);
2603
+ }
2604
+ })();
2605
+ }, [
2606
+ agent?.id,
2607
+ agent?.status,
2608
+ agent?.profileId,
2609
+ activeProfile?.editorContextMode,
2610
+ profiles,
2611
+ editContext?.currentItemDescriptor?.id,
2612
+ editContext?.currentItemDescriptor?.language,
2613
+ editContext?.currentItemDescriptor?.version,
2614
+ editContext?.selection,
2615
+ fieldsContext?.focusedField?.fieldId,
2616
+ buildCurrentContext,
2617
+ ]);
2618
+ // Stop current execution/stream safely
2619
+ const handleStop = useCallback(async () => {
2620
+ try {
2621
+ setIsWaitingForResponse(false);
2622
+ isWaitingRef.current = false;
2623
+ // Request backend to stop the current execution (does NOT close the agent)
2624
+ if (agentStub?.id) {
2625
+ try {
2626
+ await cancelAgent(agentStub.id);
2627
+ }
2628
+ catch (err) {
2629
+ console.error("Failed to cancel agent on backend:", err);
2630
+ // Continue with UI cleanup even if backend call fails
2631
+ }
2632
+ }
2633
+ // Disconnect from the stream
2634
+ if (abortControllerRef.current) {
2635
+ abortControllerRef.current.abort();
2636
+ abortControllerRef.current = null;
2637
+ }
2638
+ setIsConnecting(false);
2639
+ setIsSubmitting(false);
2640
+ // Mark any in-progress streaming messages as completed in UI
2641
+ setMessages((prev) => {
2642
+ const updated = prev.map((msg) => !msg.isCompleted && msg.messageType === "streaming"
2643
+ ? { ...msg, isCompleted: true, messageType: "completed" }
2644
+ : msg);
2645
+ messagesRef.current = updated;
2646
+ return updated;
2647
+ });
2648
+ // Update indicator state
2649
+ resetDotsTimer();
2650
+ }
2651
+ catch (e) {
2652
+ console.error("Failed to stop agent execution", e);
2653
+ }
2654
+ }, [resetDotsTimer]);
2655
+ // Determine effective cost limit from agent, profile, or metadata so the cost display
2656
+ // is visible immediately even before any messages or server-side persistence.
2657
+ let effectiveCostLimit;
2658
+ try {
2659
+ const candidates = [
2660
+ agent?.costLimit,
2661
+ activeProfile?.costLimit,
2662
+ ];
2663
+ for (const c of candidates) {
2664
+ const n = c != null ? Number(c) : 0;
2665
+ if (Number.isFinite(n) && n > 0) {
2666
+ effectiveCostLimit = n;
2667
+ break;
2668
+ }
2669
+ }
2670
+ }
2671
+ catch { }
2672
+ if (effectiveCostLimit === undefined) {
2673
+ effectiveCostLimit = undefined;
2674
+ }
2675
+ // Calculate total token usage for cost display
2676
+ const totalTokens = calculateTotalTokens(messages);
2677
+ // Determine if the agent is actively executing (submitting, connecting, waiting, or streaming)
2678
+ const isExecuting = isSubmitting ||
2679
+ isConnecting ||
2680
+ isWaitingForResponse ||
2681
+ hasActiveStreaming();
2682
+ // Move useMemo hook before early return to comply with Rules of Hooks
2683
+ const isLiveEditorContextMode = React.useMemo(() => {
2684
+ try {
2685
+ const normalizedAgentProfileId = agent?.profileId?.toLowerCase();
2686
+ const profile = activeProfile ||
2687
+ profiles.find((p) => p.id?.toLowerCase() === normalizedAgentProfileId);
2688
+ const mode = profile?.editorContextMode;
2689
+ return mode === "live";
2690
+ }
2691
+ catch {
2692
+ return false;
2693
+ }
2694
+ }, [activeProfile, profiles, agent?.profileId]);
2695
+ if (isLoading) {
2696
+ return (_jsx("div", { className: "flex h-full items-center justify-center", children: _jsxs("div", { className: "flex items-center gap-2 text-xs text-gray-500", children: [_jsx(Loader2, { className: "h-4 w-4 animate-spin", strokeWidth: 1 }), "Loading agent..."] }) }));
2697
+ }
2698
+ const renderContextInfoBar = () => (_jsx(ContextInfoBar, { agent: agent, agentMetadata: agentMetadata, setAgentMetadata: setAgentMetadata, setAgent: setAgent, resolvedPageName: resolvedPageName, resolvedComponentName: resolvedComponentName, resolvedFieldName: resolvedFieldName, isLiveEditorContextMode: isLiveEditorContextMode, activeProfile: activeProfile }));
2699
+ const renderCostLimitBanner = () => {
2700
+ if (!costLimitExceeded)
2701
+ return null;
2702
+ const { totalCost, costLimit, initialCostLimit } = costLimitExceeded;
2703
+ return (_jsxs("div", { className: "m-3 rounded border border-amber-300 bg-amber-50 p-3 text-xs text-amber-900", children: [_jsxs("div", { className: "mb-2 flex items-center gap-2", children: [_jsx(AlertCircle, { className: "h-4 w-4 text-amber-500", strokeWidth: 1 }), _jsxs("span", { children: ["Cost limit exceeded. Spent $", totalCost.toFixed(2), " / $", costLimit.toFixed(2), "."] })] }), _jsx("div", { className: "flex gap-2", children: _jsx("button", { className: "rounded border border-amber-300 bg-white px-2 py-1 hover:bg-amber-100", onClick: async () => {
2704
+ if (!agent?.id)
2705
+ return;
2706
+ try {
2707
+ // Extend cost limit - backend will automatically resume the agent
2708
+ const result = await updateAgentCostLimit(agent.id, "extend");
2709
+ // Update the agent's cost limit in local state
2710
+ if (result.success && result.costLimit !== undefined) {
2711
+ setAgent((prev) => prev ? { ...prev, costLimit: result.costLimit } : prev);
2712
+ }
2713
+ // Clear the banner and set waiting state
2714
+ // Agent will resume automatically via backend's ResumeAgentAsync
2715
+ setCostLimitExceeded(null);
2716
+ setIsWaitingForResponse(true);
2717
+ isWaitingRef.current = true;
2718
+ setShouldAutoScroll(true);
2719
+ }
2720
+ catch (e) {
2721
+ console.error("Failed to extend cost limit:", e);
2722
+ setError(e instanceof Error
2723
+ ? e.message
2724
+ : "Failed to extend cost limit");
2725
+ }
2726
+ }, children: "Extend limit and continue" }) })] }));
2727
+ };
2728
+ const renderErrorBanner = () => {
2729
+ const currentAgent = agent || agentStub;
2730
+ const isErrorStatus = currentAgent?.status === "error" || currentAgent?.status === 4;
2731
+ const errorMessage = currentAgent?.statusMessage;
2732
+ if (!isErrorStatus || !errorMessage)
2733
+ return null;
2734
+ return (_jsx("div", { className: "m-3 rounded border border-red-300 bg-red-50 p-3 text-xs text-red-900", children: _jsxs("div", { className: "flex items-start gap-2", children: [_jsx(AlertCircle, { className: "mt-0.5 h-4 w-4 flex-shrink-0 text-red-500", strokeWidth: 1 }), _jsxs("div", { className: "flex-1", children: [_jsx("div", { className: "mb-1 font-semibold", children: "Agent Error" }), _jsx("div", { className: "text-red-800", children: errorMessage })] })] }) }));
2735
+ };
2736
+ return (_jsxs("div", { className: `flex h-full flex-col ${className || ""}`, children: [_jsxs("div", { ref: messagesContainerRef, className: "flex-1 overflow-y-auto", onScroll: handleScroll, children: [error && (_jsx("div", { className: "m-4 rounded-lg border-l-4 border-red-500 bg-red-50 p-3 select-text", children: _jsxs("div", { className: "flex items-start", children: [_jsx(AlertCircle, { className: "mt-0.5 h-5 w-5 text-red-400", strokeWidth: 1 }), _jsxs("div", { className: "ml-3", children: [_jsx("p", { className: "text-sm font-medium text-red-800", children: "Error" }), _jsx("p", { className: "mt-1 text-sm text-red-700", children: error })] })] }) })), messages.length === 0 && !error && !hideGreeting && (_jsx("div", { className: "flex h-full items-center justify-center p-8", children: _jsx("div", { className: "max-w-prose text-center", children: !activeProfile ? (_jsx(Loader2, { className: "mx-auto h-8 w-8 animate-spin text-gray-400" })) : (_jsxs(_Fragment, { children: [activeProfile.svgIcon ? (_jsx("div", { className: "mx-auto mb-4 flex h-24 w-24 items-center justify-center text-gray-400 [&>svg]:h-full [&>svg]:w-full", dangerouslySetInnerHTML: {
2737
+ __html: activeProfile.svgIcon,
2738
+ } })) : (_jsx(SecretAgentIcon, { size: 96, strokeWidth: 1, className: "mx-auto mb-4 text-gray-400" })), activeProfile.greetingMessage ? (_jsx(ViewTransition, { children: _jsx("div", { className: "prose prose-sm mx-auto text-center", dangerouslySetInnerHTML: {
2739
+ __html: activeProfile.greetingMessage,
2740
+ } }) })) : (_jsxs(_Fragment, { children: [_jsx("h3", { className: "mb-2 text-lg font-medium text-gray-900", children: "Start a conversation" }), _jsx("p", { className: "mb-4 text-sm text-gray-500", children: "Send a message to begin working with your AI agent." }), _jsx("div", { className: "text-xs text-gray-400", children: "Your agent can help with content editing, research, and automation tasks." })] }))] })) }) })), renderErrorBanner(), _jsx("div", { className: "space-y-0 divide-y divide-gray-100 select-text", children: groupConsecutiveMessages(messages).map((group, groupIndex) => {
2741
+ if (group.type === "user" && group.messages[0]) {
2742
+ // Render user message
2743
+ return (_jsx(UserMessage, { message: group.messages[0] }, groupIndex));
2744
+ }
2745
+ else {
2746
+ // Render bundled assistant messages
2747
+ // Check if this group contains any streaming message
2748
+ const hasStreamingMessage = group.messages.some((msg) => !msg.isCompleted && msg.messageType === "streaming");
2749
+ // Filter out cost limit error messages (they're shown in the banner instead)
2750
+ const filteredMessages = group.messages.filter((msg) => {
2751
+ const content = msg.content || "";
2752
+ // Skip messages that are cost limit errors (shown in banner instead)
2753
+ return (!content.startsWith("⚠️") || !content.includes("Cost limit"));
2754
+ });
2755
+ // If all messages were filtered out, don't render this group
2756
+ if (filteredMessages.length === 0) {
2757
+ return null;
2758
+ }
2759
+ const convertedMessages = convertAgentMessagesToAiFormat(filteredMessages);
2760
+ return (_jsx(AiResponseMessage, { messages: convertedMessages, finished: !isSubmitting && !isConnecting, editOperations: [], error: error || undefined, profileSvgIcon: activeProfile?.svgIcon, agentId: agent?.id || agentStub.id, agentName: activeProfile?.name, onQuickAction: (action) => {
2761
+ const text = (action.prompt ||
2762
+ action.value ||
2763
+ action.label ||
2764
+ "").trim();
2765
+ if (!text)
2766
+ return;
2767
+ // Check if text contains placeholders ({placeholder} or <placeholder>)
2768
+ const hasPlaceholders = /\{([^}]+)\}|<([^>]+)>/.test(text);
2769
+ if (hasPlaceholders) {
2770
+ // Show placeholder input
2771
+ setActivePlaceholderInput({
2772
+ text,
2773
+ behavior: action.behavior,
2774
+ });
2775
+ return;
2776
+ }
2777
+ if (action.behavior === "compose") {
2778
+ setPrompt(text);
2779
+ setInputPlaceholder(action.placeholder ||
2780
+ "Review and edit, then press Enter to send");
2781
+ if (textareaRef.current) {
2782
+ try {
2783
+ textareaRef.current.focus();
2784
+ const v = textareaRef.current.value || "";
2785
+ textareaRef.current.selectionStart = v.length;
2786
+ textareaRef.current.selectionEnd = v.length;
2787
+ }
2788
+ catch { }
2789
+ }
2790
+ return;
2791
+ }
2792
+ // Stop any current execution before sending the next message
2793
+ if (isExecuting) {
2794
+ try {
2795
+ handleStop();
2796
+ }
2797
+ catch { }
2798
+ }
2799
+ sendQuickMessage(text);
2800
+ } }, groupIndex));
2801
+ }
2802
+ }) }), messages.length > 0 && (_jsx("div", { className: showDots ? "visible" : "invisible", children: _jsx(DancingDots, {}) })), renderCostLimitBanner(), _jsx("div", { ref: messagesEndRef })] }), !hideContext && renderContextInfoBar(), !hideContext && agent?.id && activeProfile && (_jsx(AgentDocumentList, { agentId: agent.id, maxFileSizeMB: activeProfile.maxDocumentSizeMB ?? 10, enabled: activeProfile.enableDocumentUpload ?? false, profileId: activeProfile.id }, `${agent.id}-${agent.updatedDate || ""}-${activeProfile.id}`)), !hideContext && (_jsx(TodoListPanel, { messages: messages, agentMetadata: agentMetadata })), queuedPrompts.length > 0 && (_jsx("div", { className: "border-t border-gray-200 bg-amber-50/50", children: _jsxs("div", { className: "px-4 pt-3 pb-2", children: [_jsxs("div", { className: "mb-2 flex items-center gap-2", children: [_jsx("div", { className: "h-2 w-2 animate-pulse rounded-full bg-amber-500" }), _jsxs("span", { className: "text-xs font-semibold text-amber-900", children: ["Queued Messages (", queuedPrompts.length, ")"] })] }), _jsx("div", { className: "space-y-2", children: queuedPrompts.map((qp) => (_jsx("div", { className: "rounded-md border border-amber-200 bg-white p-2.5 text-xs", children: _jsx("div", { className: "flex items-start justify-between gap-2", children: _jsxs("div", { className: "min-w-0 flex-1", children: [_jsx("div", { className: "mb-1 flex items-center gap-1.5", children: qp.sourceAgentName ? (_jsxs(_Fragment, { children: [_jsxs("span", { className: "font-medium text-gray-700", children: ["From ", qp.sourceAgentName] }), qp.priority > 5 && (_jsx("span", { className: "rounded bg-red-100 px-1.5 py-0.5 text-[10px] font-medium text-red-700", children: "High Priority" }))] })) : (_jsx("span", { className: "font-medium text-gray-700", children: "From User" })) }), _jsx("div", { className: "break-words whitespace-pre-wrap text-gray-600", children: qp.prompt }), qp.createdDate && (_jsx("div", { className: "mt-1.5 text-[10px] text-gray-400", children: formatTime(new Date(qp.createdDate)) }))] }) }) }, qp.id))) })] }) })), _jsxs("div", { className: "border-t border-gray-200 p-4", children: [activePlaceholderInput ? (
2803
+ // Placeholder Input (from quick actions)
2804
+ _jsx(PlaceholderInput, { text: activePlaceholderInput.text, showButtons: false, onComplete: (filledText) => {
2805
+ setActivePlaceholderInput(null);
2806
+ if (activePlaceholderInput.behavior === "compose") {
2807
+ setPrompt(filledText);
2808
+ setInputPlaceholder("Review and edit, then press Enter to send");
2809
+ if (textareaRef.current) {
2810
+ try {
2811
+ textareaRef.current.focus();
2812
+ const v = textareaRef.current.value || "";
2813
+ textareaRef.current.selectionStart = v.length;
2814
+ textareaRef.current.selectionEnd = v.length;
2815
+ }
2816
+ catch { }
2817
+ }
2818
+ }
2819
+ else {
2820
+ // Submit behavior or default
2821
+ if (isExecuting) {
2822
+ try {
2823
+ handleStop();
2824
+ }
2825
+ catch { }
2826
+ }
2827
+ sendQuickMessage(filledText);
2828
+ }
2829
+ }, onCancel: () => {
2830
+ setActivePlaceholderInput(null);
2831
+ } })) : prompt && /\{([^}]+)\}|<([^>]+)>/.test(prompt) ? (
2832
+ // Template mode: show PlaceholderInput when prompt contains placeholders
2833
+ _jsx(PlaceholderInput, { text: prompt, showButtons: false, onComplete: (filledText) => {
2834
+ setPrompt(filledText);
2835
+ // Auto-submit after filling placeholders
2836
+ if (filledText.trim()) {
2837
+ if (isExecuting) {
2838
+ try {
2839
+ handleStop();
2840
+ }
2841
+ catch { }
2842
+ }
2843
+ sendQuickMessage(filledText);
2844
+ }
2845
+ }, onCancel: () => {
2846
+ setPrompt("");
2847
+ setInputPlaceholder("Type your message... (Enter to send, Shift+Enter or Ctrl+Enter for new line)");
2848
+ } })) : (_jsx("div", { className: "flex items-stretch gap-2", children: _jsx(Textarea, { ref: textareaRef, value: prompt, onChange: (e) => {
2849
+ setPrompt(e.target.value);
2850
+ // Reset history index when user starts typing
2851
+ if (currentHistoryIndex !== -1) {
2852
+ setCurrentHistoryIndex(-1);
2853
+ }
2854
+ }, onKeyDown: handleKeyPress, placeholder: inputPlaceholder, className: "h-[80px] flex-1 resize-none overflow-y-auto text-xs", "data-testid": "agent-terminal-prompt", disabled: isSubmitting }) })), !hideBottomControls && (_jsxs(_Fragment, { children: [_jsxs("div", { className: "flex items-stretch justify-between gap-2", children: [_jsxs("div", { className: "mt-2 flex flex-wrap items-center justify-start gap-2", children: [_jsxs(Tooltip, { delayDuration: 400, children: [_jsx(TooltipTrigger, { asChild: true, children: _jsxs("select", { className: `h-5 rounded border px-1.5 text-[10px] ${mode === "read-only"
2855
+ ? "border-green-300 bg-green-50 text-green-700"
2856
+ : mode === "supervised"
2857
+ ? "border-amber-300 bg-amber-50 text-amber-700"
2858
+ : "border-red-300 bg-red-50 text-red-700"}`, value: mode, onChange: async (e) => {
2859
+ const nextMode = e.target.value || "supervised";
2860
+ // Optimistic UI update
2861
+ setMode(nextMode);
2862
+ const current = agentMetadata || {};
2863
+ const nextMeta = {
2864
+ ...current,
2865
+ mode: nextMode,
2866
+ };
2867
+ try {
2868
+ if (!agent?.id || agent.status === "new") {
2869
+ setAgentMetadata(nextMeta);
2870
+ // Cache until first start when agent is persisted
2871
+ pendingSettingsRef.current = {
2872
+ ...(pendingSettingsRef.current || {}),
2873
+ mode: nextMode,
2874
+ };
2875
+ return;
2876
+ }
2877
+ await updateAgentSettings(agent.id, {
2878
+ mode: nextMode,
2879
+ });
2880
+ setAgentMetadata(nextMeta);
2881
+ setAgent((prev) => prev
2882
+ ? { ...prev, metadata: JSON.stringify(nextMeta) }
2883
+ : prev);
2884
+ }
2885
+ catch (e2) {
2886
+ console.error("Failed to persist mode change", e2);
2887
+ }
2888
+ }, title: "Mode", "aria-label": "Mode", "data-testid": "agent-mode-select", children: [_jsx("option", { value: "supervised", children: "Supervised" }), _jsx("option", { value: "autonomous", children: "Autonomous" }), _jsx("option", { value: "read-only", children: "Read-Only" })] }) }), _jsx(TooltipContent, { side: "top", sideOffset: 6, children: _jsxs("div", { className: "max-w-[320px] space-y-1", children: [_jsxs("div", { children: [_jsx("span", { className: "font-semibold text-green-500", children: "Read-Only" }), ": Limited tool access as configured by the profile (Ask Mode Tools)."] }), _jsxs("div", { children: [_jsx("span", { className: "font-semibold text-amber-500", children: "Supervised" }), ": Full tool access, but writes are limited to pages/items in the current context. Creating new items or updating existing items outside the current context requires explicit approval."] }), _jsxs("div", { children: [_jsx("span", { className: "font-semibold text-red-500", children: "Autonomous" }), ": Full tool access; can write across the site/project only limited by user permissions."] })] }) })] }), profiles?.length > 0 && (_jsx("select", { className: "h-5 rounded border px-1.5 text-[10px] text-gray-500", value: activeProfile?.id || "", onChange: async (e) => {
2889
+ const nextProfile = profiles.find((x) => x.id === e.target.value);
2890
+ if (!nextProfile)
2891
+ return;
2892
+ setActiveProfile(nextProfile);
2893
+ try {
2894
+ if (agent?.id && agent.status !== "new") {
2895
+ await updateAgentSettings(agent.id, {
2896
+ profileId: nextProfile.id,
2897
+ profileName: nextProfile.name,
2898
+ });
2899
+ }
2900
+ else {
2901
+ // cache until first start
2902
+ pendingSettingsRef.current = {
2903
+ ...(pendingSettingsRef.current || {}),
2904
+ // we cache profile by updating local metadata
2905
+ };
2906
+ setAgentMetadata((current) => {
2907
+ const next = { ...(current || {}) };
2908
+ next.profile = nextProfile.name;
2909
+ next.additionalData = {
2910
+ ...(next.additionalData || {}),
2911
+ profileId: nextProfile.id,
2912
+ profileName: nextProfile.name,
2913
+ };
2914
+ return next;
2915
+ });
2916
+ }
2917
+ // reflect in local agent stub so tabs and titles can use it if needed
2918
+ setAgent((prev) => prev
2919
+ ? {
2920
+ ...prev,
2921
+ metadata: JSON.stringify({
2922
+ ...(agentMetadata || {}),
2923
+ profile: nextProfile.name,
2924
+ additionalData: {
2925
+ ...(agentMetadata
2926
+ ?.additionalData || {}),
2927
+ profileId: nextProfile.id,
2928
+ profileName: nextProfile.name,
2929
+ },
2930
+ }),
2931
+ }
2932
+ : prev);
2933
+ }
2934
+ catch (err) {
2935
+ console.error("Failed to persist agent profile", err);
2936
+ }
2937
+ }, title: "Profile", "aria-label": "Profile", "data-testid": "agent-profile-select", children: profiles.map((p) => (_jsx("option", { value: p.id, children: p.name }, p.id))) })), activeProfile?.models?.length ? (_jsx("select", { className: "h-5 rounded border px-1.5 text-[10px] text-gray-500", value: selectedModelId || "", onChange: async (e) => {
2938
+ const nextId = e.target.value;
2939
+ setSelectedModelId(nextId);
2940
+ const modelName = activeProfile?.models?.find((m) => m.id === nextId)
2941
+ ?.name || "";
2942
+ // Update local agent state immediately for UX and to reflect in streaming stub
2943
+ setAgent((prev) => prev ? { ...prev, model: modelName } : prev);
2944
+ // Persist only for existing agents; otherwise cache until first start
2945
+ try {
2946
+ if (agent?.id && agent.status !== "new") {
2947
+ await updateAgentSettings(agent.id, {
2948
+ model: modelName,
2949
+ });
2950
+ }
2951
+ else {
2952
+ pendingSettingsRef.current = {
2953
+ ...(pendingSettingsRef.current || {}),
2954
+ modelName,
2955
+ };
2956
+ }
2957
+ }
2958
+ catch (err) {
2959
+ console.error("Failed to persist agent model", err);
2960
+ }
2961
+ }, title: "Model", "aria-label": "Model", "data-testid": "agent-model-select", children: activeProfile.models.map((m) => (_jsx("option", { value: m.id, children: m.name }, m.id))) })) : null, activeProfile?.prompts?.length ? (_jsxs(Popover, { open: showPredefined, onOpenChange: setShowPredefined, children: [_jsx(PopoverTrigger, { asChild: true, children: _jsx("button", { className: "rounded p-1 hover:bg-gray-100", onClick: () => { }, title: "Predefined prompts", "aria-label": "Predefined prompts", children: _jsx(Wand2, { className: "h-3 w-3", strokeWidth: 1 }) }) }), _jsx(PopoverContent, { className: "w-64 p-0", align: "start", children: _jsx("div", { className: "max-h-56 overflow-y-auto p-2", children: activeProfile.prompts.map((p, index) => (_jsx("div", { className: "cursor-pointer rounded p-1.5 text-xs text-gray-700 hover:bg-gray-100", onClick: () => {
2962
+ setPrompt(p.prompt);
2963
+ setShowPredefined(false);
2964
+ if (textareaRef.current)
2965
+ textareaRef.current.focus();
2966
+ }, children: p.title }, index))) }) })] })) : null] }), _jsxs("div", { className: "flex items-center gap-1 self-end", children: [isVoiceSupported ? (_jsx(Button, { onClick: toggleVoice, size: "sm", className: "h-5.5 w-5.5 cursor-pointer rounded-full", title: isListening ? "Stop voice input" : "Start voice input", "aria-label": isListening ? "Stop voice input" : "Start voice input", "aria-pressed": isListening, children: isListening ? (_jsx(MicOff, { className: "size-3", strokeWidth: 1 })) : (_jsx(Mic, { className: "size-3", strokeWidth: 1 })) })) : null, _jsx(Button, { onClick: isExecuting ? handleStop : handleSubmit, disabled: !isExecuting && !prompt.trim(), size: "sm", className: "h-5.5 w-5.5 cursor-pointer rounded-full", title: isExecuting ? "Stop" : "Send", "aria-label": isExecuting ? "Stop" : "Send", "data-testid": "agent-send-stop-button", "data-executing": isExecuting ? "true" : "false", children: isExecuting ? (_jsx(Square, { className: "size-3", strokeWidth: 1 })) : (_jsx(Send, { className: "size-3", strokeWidth: 1 })) })] })] }), _jsxs("div", { className: "mt-1 flex items-center gap-2 text-[10px] text-gray-500", children: [_jsx(AgentCostDisplay, { totalTokens: liveTotals
2967
+ ? {
2968
+ input: liveTotals.input,
2969
+ output: liveTotals.output,
2970
+ cached: liveTotals.cached,
2971
+ cacheWrite: liveTotals.cacheWrite ?? 0,
2972
+ inputCost: liveTotals.inputCost,
2973
+ outputCost: liveTotals.outputCost,
2974
+ cachedCost: liveTotals.cachedCost,
2975
+ cacheWriteCost: liveTotals.cacheWriteCost ?? 0,
2976
+ totalCost: liveTotals.totalCost,
2977
+ }
2978
+ : totalTokens, costLimit: effectiveCostLimit }), (() => {
2979
+ try {
2980
+ const s = window.__agentContextWindowStatus;
2981
+ if (!s || !s.contextWindowTokens)
2982
+ return null;
2983
+ const pct = typeof s.contextUsedPercent === "number"
2984
+ ? `${s.contextUsedPercent.toFixed(1)}%`
2985
+ : undefined;
2986
+ // Helper function to format tokens as "k"
2987
+ const formatTokens = (tokens) => {
2988
+ if (tokens >= 1000) {
2989
+ return `${(tokens / 1000).toFixed(1)}k`;
2990
+ }
2991
+ return tokens.toString();
2992
+ };
2993
+ if (!pct)
2994
+ return null;
2995
+ return (_jsxs(Tooltip, { children: [_jsx(TooltipTrigger, { asChild: true, children: _jsxs("div", { className: "cursor-help rounded border border-gray-200 bg-gray-50 px-2 py-0.5", children: ["Context: ", pct] }) }), _jsx(TooltipContent, { side: "top", sideOffset: 6, children: _jsxs("div", { className: "max-w-[320px] space-y-1 text-xs", children: [_jsxs("div", { children: [_jsx("span", { className: "font-semibold", children: "Model:" }), " ", s.model, s.normalizedModel && ` (${s.normalizedModel})`] }), _jsxs("div", { children: [_jsx("span", { className: "font-semibold", children: "Context window:" }), " ", formatTokens(s.estimatedInputTokens || 0), " /", " ", formatTokens(s.contextWindowTokens), " tokens"] }), typeof s.maxCompletionTokens === "number" && (_jsxs("div", { children: [_jsx("span", { className: "font-semibold", children: "Max completion:" }), " ", formatTokens(s.maxCompletionTokens), " tokens"] })), _jsxs("div", { children: [_jsx("span", { className: "font-semibold", children: "Used:" }), " ", pct] })] }) })] }));
2996
+ }
2997
+ catch {
2998
+ return null;
2999
+ }
3000
+ })(), activeProfile && (_jsxs(Tooltip, { children: [_jsx(TooltipTrigger, { asChild: true, children: _jsxs("button", { type: "button", className: "flex items-center gap-1 text-gray-400 hover:text-gray-600", onClick: async () => {
3001
+ if (!editContext || !activeProfile?.id)
3002
+ return;
3003
+ // Load the profile item using editContext
3004
+ const lang = editContext?.currentItemDescriptor?.language || "en";
3005
+ await editContext.loadItem({
3006
+ id: activeProfile.id,
3007
+ language: lang,
3008
+ version: 0,
3009
+ });
3010
+ }, children: [_jsx("span", { className: "max-w-[100px] truncate", children: activeProfile.name }), _jsx(ExternalLink, { className: "h-2.5 w-2.5 shrink-0", strokeWidth: 1.5 })] }) }), _jsx(TooltipContent, { side: "top", sideOffset: 6, children: "Open profile settings" })] }))] })] }))] })] }));
3011
+ }
3012
+ //# sourceMappingURL=AgentTerminal.js.map