@parhelia/core 0.1.12570 → 0.1.12585

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 (591) hide show
  1. package/dist/agents-view/AgentCard.d.ts +6 -4
  2. package/dist/agents-view/AgentCard.js +143 -24
  3. package/dist/agents-view/AgentCard.js.map +1 -1
  4. package/dist/agents-view/AgentsInbox.d.ts +1 -1
  5. package/dist/agents-view/AgentsInbox.js +7 -92
  6. package/dist/agents-view/AgentsInbox.js.map +1 -1
  7. package/dist/agents-view/AgentsTitlebar.js +3 -2
  8. package/dist/agents-view/AgentsTitlebar.js.map +1 -1
  9. package/dist/agents-view/AgentsView.d.ts +6 -7
  10. package/dist/agents-view/AgentsView.js +191 -99
  11. package/dist/agents-view/AgentsView.js.map +1 -1
  12. package/dist/agents-view/AgentsWorkspaceView.d.ts +2 -6
  13. package/dist/agents-view/AgentsWorkspaceView.js +266 -113
  14. package/dist/agents-view/AgentsWorkspaceView.js.map +1 -1
  15. package/dist/agents-view/ProfileAgentsGroup.d.ts +2 -1
  16. package/dist/agents-view/ProfileAgentsGroup.js +4 -3
  17. package/dist/agents-view/ProfileAgentsGroup.js.map +1 -1
  18. package/dist/components/ActionButton.d.ts +1 -1
  19. package/dist/components/ActionButton.js.map +1 -1
  20. package/dist/components/FilterInput.d.ts +1 -1
  21. package/dist/components/FilterInput.js +1 -1
  22. package/dist/components/FilterInput.js.map +1 -1
  23. package/dist/components/ui/LanguageSelector.js +2 -4
  24. package/dist/components/ui/LanguageSelector.js.map +1 -1
  25. package/dist/components/ui/PlaceholderInput.js +3 -3
  26. package/dist/components/ui/PlaceholderInput.js.map +1 -1
  27. package/dist/components/ui/PlaceholderInputTypes.js +1 -1
  28. package/dist/components/ui/PlaceholderInputTypes.js.map +1 -1
  29. package/dist/components/ui/alert-dialog.d.ts +1 -1
  30. package/dist/components/ui/alert-dialog.js +6 -10
  31. package/dist/components/ui/alert-dialog.js.map +1 -1
  32. package/dist/components/ui/button.d.ts +4 -4
  33. package/dist/components/ui/button.js +4 -1
  34. package/dist/components/ui/button.js.map +1 -1
  35. package/dist/components/ui/context-menu.d.ts +1 -1
  36. package/dist/components/ui/context-menu.js +12 -4
  37. package/dist/components/ui/context-menu.js.map +1 -1
  38. package/dist/components/ui/copy-button.d.ts +2 -1
  39. package/dist/components/ui/copy-button.js +2 -2
  40. package/dist/components/ui/copy-button.js.map +1 -1
  41. package/dist/components/ui/dialog.d.ts +1 -1
  42. package/dist/components/ui/dialog.js +21 -126
  43. package/dist/components/ui/dialog.js.map +1 -1
  44. package/dist/components/ui/input.d.ts +1 -1
  45. package/dist/components/ui/input.js +5 -3
  46. package/dist/components/ui/input.js.map +1 -1
  47. package/dist/components/ui/paste-button.d.ts +2 -1
  48. package/dist/components/ui/paste-button.js +2 -2
  49. package/dist/components/ui/paste-button.js.map +1 -1
  50. package/dist/components/ui/popover.js +1 -9
  51. package/dist/components/ui/popover.js.map +1 -1
  52. package/dist/components/ui/select.js +1 -1
  53. package/dist/components/ui/select.js.map +1 -1
  54. package/dist/components/ui/styled-dialog-title.js +1 -1
  55. package/dist/components/ui/styled-dialog-title.js.map +1 -1
  56. package/dist/components/ui/tabs.d.ts +1 -1
  57. package/dist/components/ui/tabs.js +4 -11
  58. package/dist/components/ui/tabs.js.map +1 -1
  59. package/dist/config/config.d.ts +4 -2
  60. package/dist/config/config.js +250 -70
  61. package/dist/config/config.js.map +1 -1
  62. package/dist/config/types/workspace.d.ts +6 -0
  63. package/dist/config/types.d.ts +63 -12
  64. package/dist/config/types.js.map +1 -1
  65. package/dist/editor/ConfirmationDialog.js +20 -4
  66. package/dist/editor/ConfirmationDialog.js.map +1 -1
  67. package/dist/editor/ContentTree.d.ts +2 -1
  68. package/dist/editor/ContentTree.js +93 -32
  69. package/dist/editor/ContentTree.js.map +1 -1
  70. package/dist/editor/Editor.js +87 -22
  71. package/dist/editor/Editor.js.map +1 -1
  72. package/dist/editor/FieldHistory.js +84 -36
  73. package/dist/editor/FieldHistory.js.map +1 -1
  74. package/dist/editor/FieldListField.js +21 -9
  75. package/dist/editor/FieldListField.js.map +1 -1
  76. package/dist/editor/FieldListFieldWithFallbacks.js +23 -2
  77. package/dist/editor/FieldListFieldWithFallbacks.js.map +1 -1
  78. package/dist/editor/GlobalMenuBar.js +29 -2
  79. package/dist/editor/GlobalMenuBar.js.map +1 -1
  80. package/dist/editor/ImageEditor.js +5 -2
  81. package/dist/editor/ImageEditor.js.map +1 -1
  82. package/dist/editor/ItemInfo.js +36 -1
  83. package/dist/editor/ItemInfo.js.map +1 -1
  84. package/dist/editor/LinkEditorDialog.js +3 -0
  85. package/dist/editor/LinkEditorDialog.js.map +1 -1
  86. package/dist/editor/MainLayout.d.ts +0 -2
  87. package/dist/editor/MainLayout.js +65 -8
  88. package/dist/editor/MainLayout.js.map +1 -1
  89. package/dist/editor/MigrationsView.js +29 -5
  90. package/dist/editor/MigrationsView.js.map +1 -1
  91. package/dist/editor/MobileLayout.js +37 -12
  92. package/dist/editor/MobileLayout.js.map +1 -1
  93. package/dist/editor/PictureCropper.js +54 -45
  94. package/dist/editor/PictureCropper.js.map +1 -1
  95. package/dist/editor/PictureEditor.js +17 -15
  96. package/dist/editor/PictureEditor.js.map +1 -1
  97. package/dist/editor/QuickItemSwitcher.js +37 -63
  98. package/dist/editor/QuickItemSwitcher.js.map +1 -1
  99. package/dist/editor/SetupWizard.js +52 -12
  100. package/dist/editor/SetupWizard.js.map +1 -1
  101. package/dist/editor/Titlebar.js +7 -2
  102. package/dist/editor/Titlebar.js.map +1 -1
  103. package/dist/editor/ai/AgentCostDisplay.d.ts +1 -0
  104. package/dist/editor/ai/AgentCostDisplay.js +1 -1
  105. package/dist/editor/ai/AgentCostDisplay.js.map +1 -1
  106. package/dist/editor/ai/AgentDocumentList.js +32 -14
  107. package/dist/editor/ai/AgentDocumentList.js.map +1 -1
  108. package/dist/editor/ai/AgentGreeting.js +6 -5
  109. package/dist/editor/ai/AgentGreeting.js.map +1 -1
  110. package/dist/editor/ai/AgentProfileSelector.js +2 -1
  111. package/dist/editor/ai/AgentProfileSelector.js.map +1 -1
  112. package/dist/editor/ai/AgentStatusBadge.d.ts +0 -5
  113. package/dist/editor/ai/AgentStatusBadge.js +67 -65
  114. package/dist/editor/ai/AgentStatusBadge.js.map +1 -1
  115. package/dist/editor/ai/AgentTerminal.d.ts +14 -2
  116. package/dist/editor/ai/AgentTerminal.js +2515 -579
  117. package/dist/editor/ai/AgentTerminal.js.map +1 -1
  118. package/dist/editor/ai/AgentTerminalStatusBar.d.ts +9 -4
  119. package/dist/editor/ai/AgentTerminalStatusBar.js +481 -56
  120. package/dist/editor/ai/AgentTerminalStatusBar.js.map +1 -1
  121. package/dist/editor/ai/Agents.js +161 -113
  122. package/dist/editor/ai/Agents.js.map +1 -1
  123. package/dist/editor/ai/AiResponseMessage.d.ts +10 -1
  124. package/dist/editor/ai/AiResponseMessage.js +267 -26
  125. package/dist/editor/ai/AiResponseMessage.js.map +1 -1
  126. package/dist/editor/ai/ContextInfoBar.d.ts +2 -3
  127. package/dist/editor/ai/ContextInfoBar.js +64 -7
  128. package/dist/editor/ai/ContextInfoBar.js.map +1 -1
  129. package/dist/editor/ai/EditOperationsPanel.d.ts +3 -2
  130. package/dist/editor/ai/EditOperationsPanel.js +21 -78
  131. package/dist/editor/ai/EditOperationsPanel.js.map +1 -1
  132. package/dist/editor/ai/GuidanceOverlay.js +17 -11
  133. package/dist/editor/ai/GuidanceOverlay.js.map +1 -1
  134. package/dist/editor/ai/InlineAiDialog.d.ts +1 -1
  135. package/dist/editor/ai/InlineAiDialog.js +514 -192
  136. package/dist/editor/ai/InlineAiDialog.js.map +1 -1
  137. package/dist/editor/ai/InlineAiTrigger.js +115 -12
  138. package/dist/editor/ai/InlineAiTrigger.js.map +1 -1
  139. package/dist/editor/ai/MediaImage.js +40 -8
  140. package/dist/editor/ai/MediaImage.js.map +1 -1
  141. package/dist/editor/ai/SpawnedAgentsPanel.js +10 -12
  142. package/dist/editor/ai/SpawnedAgentsPanel.js.map +1 -1
  143. package/dist/editor/ai/ToolCallDisplay.d.ts +22 -2
  144. package/dist/editor/ai/ToolCallDisplay.js +614 -202
  145. package/dist/editor/ai/ToolCallDisplay.js.map +1 -1
  146. package/dist/editor/ai/dialogs/AgentDialogHandler.d.ts +1 -8
  147. package/dist/editor/ai/dialogs/AgentDialogHandler.js +379 -42
  148. package/dist/editor/ai/dialogs/AgentDialogHandler.js.map +1 -1
  149. package/dist/editor/ai/dialogs/QuestionnaireInline.d.ts +5 -1
  150. package/dist/editor/ai/dialogs/QuestionnaireInline.js +628 -60
  151. package/dist/editor/ai/dialogs/QuestionnaireInline.js.map +1 -1
  152. package/dist/editor/ai/dialogs/agentDialogTypes.d.ts +117 -0
  153. package/dist/editor/ai/dialogs/agentDialogTypes.js +2 -0
  154. package/dist/editor/ai/dialogs/agentDialogTypes.js.map +1 -1
  155. package/dist/editor/ai/types.d.ts +3 -1
  156. package/dist/editor/ai/useAgentStatus.d.ts +2 -1
  157. package/dist/editor/ai/useAgentStatus.js +90 -100
  158. package/dist/editor/ai/useAgentStatus.js.map +1 -1
  159. package/dist/editor/ai/useInlineAiPosition.js +45 -5
  160. package/dist/editor/ai/useInlineAiPosition.js.map +1 -1
  161. package/dist/editor/client/AboutDialog.js +4 -2
  162. package/dist/editor/client/AboutDialog.js.map +1 -1
  163. package/dist/editor/client/EditorShell.d.ts +4 -1
  164. package/dist/editor/client/EditorShell.js +853 -258
  165. package/dist/editor/client/EditorShell.js.map +1 -1
  166. package/dist/editor/client/editContext.d.ts +33 -19
  167. package/dist/editor/client/editContext.js.map +1 -1
  168. package/dist/editor/client/helpers.js +6 -0
  169. package/dist/editor/client/helpers.js.map +1 -1
  170. package/dist/editor/client/hooks/useEditorUrlSync.js +1 -2
  171. package/dist/editor/client/hooks/useEditorUrlSync.js.map +1 -1
  172. package/dist/editor/client/hooks/useEditorWebSocket.d.ts +10 -0
  173. package/dist/editor/client/hooks/useEditorWebSocket.js +209 -14
  174. package/dist/editor/client/hooks/useEditorWebSocket.js.map +1 -1
  175. package/dist/editor/client/hooks/useQuota.d.ts +8 -0
  176. package/dist/editor/client/hooks/useQuota.js.map +1 -1
  177. package/dist/editor/client/hooks/useSocketMessageHandler.js +73 -15
  178. package/dist/editor/client/hooks/useSocketMessageHandler.js.map +1 -1
  179. package/dist/editor/client/itemsRepository.js +10 -6
  180. package/dist/editor/client/itemsRepository.js.map +1 -1
  181. package/dist/editor/client/operations.d.ts +6 -3
  182. package/dist/editor/client/operations.js +208 -30
  183. package/dist/editor/client/operations.js.map +1 -1
  184. package/dist/editor/client/pageModelBuilder.js +4 -31
  185. package/dist/editor/client/pageModelBuilder.js.map +1 -1
  186. package/dist/editor/client/ui/DevModeIndicator.js +2 -2
  187. package/dist/editor/client/ui/DevModeIndicator.js.map +1 -1
  188. package/dist/editor/client/ui/EditorChrome.d.ts +0 -6
  189. package/dist/editor/client/ui/EditorChrome.js +55 -72
  190. package/dist/editor/client/ui/EditorChrome.js.map +1 -1
  191. package/dist/editor/client/ui/FullscreenControls.js +5 -3
  192. package/dist/editor/client/ui/FullscreenControls.js.map +1 -1
  193. package/dist/editor/commands/commands.d.ts +11 -1
  194. package/dist/editor/commands/commands.js +12 -1
  195. package/dist/editor/commands/commands.js.map +1 -1
  196. package/dist/editor/commands/componentCommands.js +109 -55
  197. package/dist/editor/commands/componentCommands.js.map +1 -1
  198. package/dist/editor/commands/customCommandConverter.d.ts +8 -1
  199. package/dist/editor/commands/customCommandConverter.js +35 -5
  200. package/dist/editor/commands/customCommandConverter.js.map +1 -1
  201. package/dist/editor/commands/handlers/agentHandler.js +2 -1
  202. package/dist/editor/commands/handlers/agentHandler.js.map +1 -1
  203. package/dist/editor/commands/itemCommands.d.ts +3 -0
  204. package/dist/editor/commands/itemCommands.js +93 -10
  205. package/dist/editor/commands/itemCommands.js.map +1 -1
  206. package/dist/editor/commands/undo.d.ts +9 -15
  207. package/dist/editor/commands/undo.js +24 -0
  208. package/dist/editor/commands/undo.js.map +1 -1
  209. package/dist/editor/context-menu/InsertMenu.js +83 -39
  210. package/dist/editor/context-menu/InsertMenu.js.map +1 -1
  211. package/dist/editor/field-types/MultiLineText.js +1 -1
  212. package/dist/editor/field-types/MultiLineText.js.map +1 -1
  213. package/dist/editor/field-types/RawEditor.js +1 -1
  214. package/dist/editor/field-types/RichTextEditor.js +13 -5
  215. package/dist/editor/field-types/RichTextEditor.js.map +1 -1
  216. package/dist/editor/field-types/RichTextEditorComponent.js +37 -3
  217. package/dist/editor/field-types/RichTextEditorComponent.js.map +1 -1
  218. package/dist/editor/field-types/SingleLineText.js +1 -1
  219. package/dist/editor/field-types/TreeListEditor.js +3 -2
  220. package/dist/editor/field-types/TreeListEditor.js.map +1 -1
  221. package/dist/editor/field-types/richtext/components/ReactSlate.css +23 -5
  222. package/dist/editor/field-types/richtext/components/ReactSlate.d.ts +2 -0
  223. package/dist/editor/field-types/richtext/components/ReactSlate.js +28 -4
  224. package/dist/editor/field-types/richtext/components/ReactSlate.js.map +1 -1
  225. package/dist/editor/field-types/richtext/components/ToolbarButton.js +4 -2
  226. package/dist/editor/field-types/richtext/components/ToolbarButton.js.map +1 -1
  227. package/dist/editor/field-types/richtext/contextMenuFactory.d.ts +13 -0
  228. package/dist/editor/field-types/richtext/contextMenuFactory.js +181 -24
  229. package/dist/editor/field-types/richtext/contextMenuFactory.js.map +1 -1
  230. package/dist/editor/field-types/richtext/types.d.ts +2 -0
  231. package/dist/editor/field-types/richtext/types.js.map +1 -1
  232. package/dist/editor/field-types/richtext/utils/plugins.js +4 -0
  233. package/dist/editor/field-types/richtext/utils/plugins.js.map +1 -1
  234. package/dist/editor/field-types/textContextMenuFactory.js +3 -2
  235. package/dist/editor/field-types/textContextMenuFactory.js.map +1 -1
  236. package/dist/editor/media-selector/AiImageSearchPrompt.js +4 -2
  237. package/dist/editor/media-selector/AiImageSearchPrompt.js.map +1 -1
  238. package/dist/editor/media-selector/MediaFolderBrowser.js +1 -1
  239. package/dist/editor/media-selector/MediaFolderBrowser.js.map +1 -1
  240. package/dist/editor/media-selector/MediaSelector.js +7 -1
  241. package/dist/editor/media-selector/MediaSelector.js.map +1 -1
  242. package/dist/editor/media-selector/TreeSelector.js +40 -35
  243. package/dist/editor/media-selector/TreeSelector.js.map +1 -1
  244. package/dist/editor/menubar/ActiveUsers.js +1 -1
  245. package/dist/editor/menubar/ActiveUsers.js.map +1 -1
  246. package/dist/editor/menubar/GenericToolbar.js +4 -2
  247. package/dist/editor/menubar/GenericToolbar.js.map +1 -1
  248. package/dist/editor/menubar/ItemLanguageVersion.js +2 -2
  249. package/dist/editor/menubar/ItemLanguageVersion.js.map +1 -1
  250. package/dist/editor/menubar/PageSelector.js +26 -147
  251. package/dist/editor/menubar/PageSelector.js.map +1 -1
  252. package/dist/editor/menubar/Separator.js +1 -1
  253. package/dist/editor/menubar/VersionSelector.js +2 -4
  254. package/dist/editor/menubar/VersionSelector.js.map +1 -1
  255. package/dist/editor/menubar/WorkflowButton.js +39 -12
  256. package/dist/editor/menubar/WorkflowButton.js.map +1 -1
  257. package/dist/editor/menubar/toolbar-sections/CustomCommandsToolbar.js +16 -38
  258. package/dist/editor/menubar/toolbar-sections/CustomCommandsToolbar.js.map +1 -1
  259. package/dist/editor/menubar/toolbar-sections/EditControls.js +3 -3
  260. package/dist/editor/menubar/toolbar-sections/EditControls.js.map +1 -1
  261. package/dist/editor/menubar/toolbar-sections/HelpButton.js +1 -0
  262. package/dist/editor/menubar/toolbar-sections/HelpButton.js.map +1 -1
  263. package/dist/editor/menubar/toolbar-sections/ManualBrowser.d.ts +6 -10
  264. package/dist/editor/menubar/toolbar-sections/ManualBrowser.js +597 -220
  265. package/dist/editor/menubar/toolbar-sections/ManualBrowser.js.map +1 -1
  266. package/dist/editor/menubar/toolbar-sections/UtilityControls.js +13 -2
  267. package/dist/editor/menubar/toolbar-sections/UtilityControls.js.map +1 -1
  268. package/dist/editor/page-editor-chrome/CommentHighlighting.js +42 -1
  269. package/dist/editor/page-editor-chrome/CommentHighlighting.js.map +1 -1
  270. package/dist/editor/page-editor-chrome/FrameMenu.js +1 -1
  271. package/dist/editor/page-editor-chrome/FrameMenu.js.map +1 -1
  272. package/dist/editor/page-editor-chrome/InlineEditor.js +97 -48
  273. package/dist/editor/page-editor-chrome/InlineEditor.js.map +1 -1
  274. package/dist/editor/page-editor-chrome/PlaceholderDropZone.js +38 -17
  275. package/dist/editor/page-editor-chrome/PlaceholderDropZone.js.map +1 -1
  276. package/dist/editor/page-editor-chrome/PlaceholderDropZones.js +17 -11
  277. package/dist/editor/page-editor-chrome/PlaceholderDropZones.js.map +1 -1
  278. package/dist/editor/page-editor-chrome/useInlineAICompletion.js +301 -301
  279. package/dist/editor/page-editor-chrome/useInlineAICompletion.js.map +1 -1
  280. package/dist/editor/page-viewer/DeviceToolbar.js +1 -1
  281. package/dist/editor/page-viewer/DeviceToolbar.js.map +1 -1
  282. package/dist/editor/page-viewer/EditorForm.js +69 -11
  283. package/dist/editor/page-viewer/EditorForm.js.map +1 -1
  284. package/dist/editor/page-viewer/MiniMap.d.ts +2 -4
  285. package/dist/editor/page-viewer/MiniMap.js +91 -28
  286. package/dist/editor/page-viewer/MiniMap.js.map +1 -1
  287. package/dist/editor/page-viewer/PageViewer.d.ts +3 -1
  288. package/dist/editor/page-viewer/PageViewer.js +92 -19
  289. package/dist/editor/page-viewer/PageViewer.js.map +1 -1
  290. package/dist/editor/page-viewer/PageViewerFrame.d.ts +2 -1
  291. package/dist/editor/page-viewer/PageViewerFrame.js +348 -115
  292. package/dist/editor/page-viewer/PageViewerFrame.js.map +1 -1
  293. package/dist/editor/page-viewer/pageModelSkeletonBuilder.js +114 -49
  294. package/dist/editor/page-viewer/pageModelSkeletonBuilder.js.map +1 -1
  295. package/dist/editor/page-viewer/pageViewContext.d.ts +1 -0
  296. package/dist/editor/page-viewer/pageViewContext.js +51 -14
  297. package/dist/editor/page-viewer/pageViewContext.js.map +1 -1
  298. package/dist/editor/pageModel.d.ts +14 -1
  299. package/dist/editor/reviews/Comment.d.ts +2 -1
  300. package/dist/editor/reviews/Comment.js +92 -15
  301. package/dist/editor/reviews/Comment.js.map +1 -1
  302. package/dist/editor/reviews/CommentDisplayPopover.js +70 -5
  303. package/dist/editor/reviews/CommentDisplayPopover.js.map +1 -1
  304. package/dist/editor/reviews/CommentView.d.ts +3 -1
  305. package/dist/editor/reviews/CommentView.js +26 -6
  306. package/dist/editor/reviews/CommentView.js.map +1 -1
  307. package/dist/editor/reviews/Comments.js +140 -75
  308. package/dist/editor/reviews/Comments.js.map +1 -1
  309. package/dist/editor/reviews/CreateReviewDialog.js +281 -177
  310. package/dist/editor/reviews/CreateReviewDialog.js.map +1 -1
  311. package/dist/editor/reviews/DecisionsMatrix.js +96 -25
  312. package/dist/editor/reviews/DecisionsMatrix.js.map +1 -1
  313. package/dist/editor/reviews/DiffView.js +7 -14
  314. package/dist/editor/reviews/DiffView.js.map +1 -1
  315. package/dist/editor/reviews/EditReviewSettingsDialog.js +6 -4
  316. package/dist/editor/reviews/EditReviewSettingsDialog.js.map +1 -1
  317. package/dist/editor/reviews/MultiReviewManager.js +25 -3
  318. package/dist/editor/reviews/MultiReviewManager.js.map +1 -1
  319. package/dist/editor/reviews/PagesPanel.js +31 -15
  320. package/dist/editor/reviews/PagesPanel.js.map +1 -1
  321. package/dist/editor/reviews/PreviewInfo.js +1 -4
  322. package/dist/editor/reviews/PreviewInfo.js.map +1 -1
  323. package/dist/editor/reviews/ReviewCard.js +13 -7
  324. package/dist/editor/reviews/ReviewCard.js.map +1 -1
  325. package/dist/editor/reviews/ReviewDetail.js +3 -2
  326. package/dist/editor/reviews/ReviewDetail.js.map +1 -1
  327. package/dist/editor/reviews/ReviewsList.js +7 -3
  328. package/dist/editor/reviews/ReviewsList.js.map +1 -1
  329. package/dist/editor/reviews/SuggestedEdit.js +34 -3
  330. package/dist/editor/reviews/SuggestedEdit.js.map +1 -1
  331. package/dist/editor/reviews/SuggestionDisplayPopover.js +31 -5
  332. package/dist/editor/reviews/SuggestionDisplayPopover.js.map +1 -1
  333. package/dist/editor/reviews/commentAi.js +25 -6
  334. package/dist/editor/reviews/commentAi.js.map +1 -1
  335. package/dist/editor/reviews/reviewCommands.js +4 -1
  336. package/dist/editor/reviews/reviewCommands.js.map +1 -1
  337. package/dist/editor/reviews/useMultiReview.js +2 -2
  338. package/dist/editor/reviews/useMultiReview.js.map +1 -1
  339. package/dist/editor/reviews/useReviews.d.ts +4 -3
  340. package/dist/editor/reviews/useReviews.js +21 -32
  341. package/dist/editor/reviews/useReviews.js.map +1 -1
  342. package/dist/editor/services/agentService.d.ts +240 -5
  343. package/dist/editor/services/agentService.js +299 -39
  344. package/dist/editor/services/agentService.js.map +1 -1
  345. package/dist/editor/services/aiService.d.ts +57 -1
  346. package/dist/editor/services/aiService.js +79 -6
  347. package/dist/editor/services/aiService.js.map +1 -1
  348. package/dist/editor/services/contentService.d.ts +6 -3
  349. package/dist/editor/services/contentService.js +13 -12
  350. package/dist/editor/services/contentService.js.map +1 -1
  351. package/dist/editor/services/editService.d.ts +52 -1
  352. package/dist/editor/services/editService.js +94 -2
  353. package/dist/editor/services/editService.js.map +1 -1
  354. package/dist/editor/services/indexService.js +1 -1
  355. package/dist/editor/services/indexService.js.map +1 -1
  356. package/dist/editor/services/reviewsService.d.ts +3 -6
  357. package/dist/editor/services/reviewsService.js +2 -11
  358. package/dist/editor/services/reviewsService.js.map +1 -1
  359. package/dist/editor/services/serviceHelper.d.ts +2 -1
  360. package/dist/editor/services/serviceHelper.js +112 -20
  361. package/dist/editor/services/serviceHelper.js.map +1 -1
  362. package/dist/editor/services/systemService.d.ts +2 -1
  363. package/dist/editor/services/systemService.js +3 -0
  364. package/dist/editor/services/systemService.js.map +1 -1
  365. package/dist/editor/services-server/api.d.ts +1 -2
  366. package/dist/editor/services-server/api.js +11 -6
  367. package/dist/editor/services-server/api.js.map +1 -1
  368. package/dist/editor/settings/About.js +317 -3
  369. package/dist/editor/settings/About.js.map +1 -1
  370. package/dist/editor/settings/IndexOverview.js +3 -1
  371. package/dist/editor/settings/IndexOverview.js.map +1 -1
  372. package/dist/editor/settings/QuotaInfo.js +210 -4
  373. package/dist/editor/settings/QuotaInfo.js.map +1 -1
  374. package/dist/editor/settings/SettingsView.js +25 -23
  375. package/dist/editor/settings/SettingsView.js.map +1 -1
  376. package/dist/editor/settings/Status.js +7 -6
  377. package/dist/editor/settings/Status.js.map +1 -1
  378. package/dist/editor/settings/index/CollectionWarningsDisplay.d.ts +10 -0
  379. package/dist/editor/settings/index/CollectionWarningsDisplay.js +16 -0
  380. package/dist/editor/settings/index/CollectionWarningsDisplay.js.map +1 -0
  381. package/dist/editor/settings/index/useIndexStatus.js +23 -22
  382. package/dist/editor/settings/index/useIndexStatus.js.map +1 -1
  383. package/dist/editor/settings/panels/AgentsPanel.d.ts +0 -4
  384. package/dist/editor/settings/panels/AgentsPanel.js +95 -121
  385. package/dist/editor/settings/panels/AgentsPanel.js.map +1 -1
  386. package/dist/editor/settings/panels/ModelConfigPanel.js +1 -1
  387. package/dist/editor/settings/panels/ModelConfigPanel.js.map +1 -1
  388. package/dist/editor/settings/panels/ModelsPanel.js +324 -108
  389. package/dist/editor/settings/panels/ModelsPanel.js.map +1 -1
  390. package/dist/editor/settings/panels/ProvidersPanel.d.ts +1 -1
  391. package/dist/editor/settings/panels/ProvidersPanel.js +86 -59
  392. package/dist/editor/settings/panels/ProvidersPanel.js.map +1 -1
  393. package/dist/editor/settings/panels/SearchConfigPanel.js +67 -6
  394. package/dist/editor/settings/panels/SearchConfigPanel.js.map +1 -1
  395. package/dist/editor/settings/panels/StatusPanel.js +7 -2
  396. package/dist/editor/settings/panels/StatusPanel.js.map +1 -1
  397. package/dist/editor/settings/panels/index.d.ts +3 -2
  398. package/dist/editor/settings/panels/index.js +3 -2
  399. package/dist/editor/settings/panels/index.js.map +1 -1
  400. package/dist/editor/settings/status/coreStatusChecks.js +124 -19
  401. package/dist/editor/settings/status/coreStatusChecks.js.map +1 -1
  402. package/dist/editor/settings/status/useStartupChecks.d.ts +3 -1
  403. package/dist/editor/settings/status/useStartupChecks.js +9 -5
  404. package/dist/editor/settings/status/useStartupChecks.js.map +1 -1
  405. package/dist/editor/setup-wizard/steps/CompleteStep.d.ts +2 -1
  406. package/dist/editor/setup-wizard/steps/CompleteStep.js +2 -1
  407. package/dist/editor/setup-wizard/steps/CompleteStep.js.map +1 -1
  408. package/dist/editor/sidebar/ComponentPalette.js +2 -1
  409. package/dist/editor/sidebar/ComponentPalette.js.map +1 -1
  410. package/dist/editor/sidebar/ComponentTree.d.ts +8 -1
  411. package/dist/editor/sidebar/ComponentTree.js +216 -69
  412. package/dist/editor/sidebar/ComponentTree.js.map +1 -1
  413. package/dist/editor/sidebar/EditHistory.js +22 -46
  414. package/dist/editor/sidebar/EditHistory.js.map +1 -1
  415. package/dist/editor/sidebar/Favorites.js +4 -8
  416. package/dist/editor/sidebar/Favorites.js.map +1 -1
  417. package/dist/editor/sidebar/MainContentTree.js +4 -3
  418. package/dist/editor/sidebar/MainContentTree.js.map +1 -1
  419. package/dist/editor/sidebar/OperationItem.js +21 -7
  420. package/dist/editor/sidebar/OperationItem.js.map +1 -1
  421. package/dist/editor/sidebar/SidebarPanel.d.ts +3 -1
  422. package/dist/editor/sidebar/SidebarPanel.js +44 -12
  423. package/dist/editor/sidebar/SidebarPanel.js.map +1 -1
  424. package/dist/editor/sidebar/SidebarStack.d.ts +2 -1
  425. package/dist/editor/sidebar/SidebarStack.js +4 -3
  426. package/dist/editor/sidebar/SidebarStack.js.map +1 -1
  427. package/dist/editor/sidebar/Validation.js +24 -12
  428. package/dist/editor/sidebar/Validation.js.map +1 -1
  429. package/dist/editor/sidebar/Workbox.js +53 -3
  430. package/dist/editor/sidebar/Workbox.js.map +1 -1
  431. package/dist/editor/sidebar/WorkspaceRail.d.ts +0 -1
  432. package/dist/editor/sidebar/WorkspaceRail.js +56 -167
  433. package/dist/editor/sidebar/WorkspaceRail.js.map +1 -1
  434. package/dist/editor/template-wizard/TemplateStructureInlineEditor.js +3 -2
  435. package/dist/editor/template-wizard/TemplateStructureInlineEditor.js.map +1 -1
  436. package/dist/editor/tree-indicators/GutterColumns.d.ts +3 -1
  437. package/dist/editor/tree-indicators/GutterColumns.js +26 -5
  438. package/dist/editor/tree-indicators/GutterColumns.js.map +1 -1
  439. package/dist/editor/tree-indicators/GutterContext.d.ts +4 -0
  440. package/dist/editor/tree-indicators/GutterContext.js +23 -0
  441. package/dist/editor/tree-indicators/GutterContext.js.map +1 -1
  442. package/dist/editor/tree-indicators/index.d.ts +0 -1
  443. package/dist/editor/tree-indicators/index.js +0 -1
  444. package/dist/editor/tree-indicators/index.js.map +1 -1
  445. package/dist/editor/tree-indicators/types.d.ts +12 -1
  446. package/dist/editor/ui/CopyMoveTargetSelectorDialog.js +1 -1
  447. package/dist/editor/ui/CopyMoveTargetSelectorDialog.js.map +1 -1
  448. package/dist/editor/ui/Icons.js +1 -1
  449. package/dist/editor/ui/Icons.js.map +1 -1
  450. package/dist/editor/ui/ItemNameDialogNew.d.ts +2 -0
  451. package/dist/editor/ui/ItemNameDialogNew.js +33 -17
  452. package/dist/editor/ui/ItemNameDialogNew.js.map +1 -1
  453. package/dist/editor/ui/ItemSearch.js +7 -11
  454. package/dist/editor/ui/ItemSearch.js.map +1 -1
  455. package/dist/editor/ui/SimpleIconButton.js +1 -1
  456. package/dist/editor/ui/SimpleIconButton.js.map +1 -1
  457. package/dist/editor/ui/SimpleTabs.d.ts +1 -0
  458. package/dist/editor/ui/SimpleTabs.js +45 -25
  459. package/dist/editor/ui/SimpleTabs.js.map +1 -1
  460. package/dist/editor/ui/Splitter.d.ts +1 -0
  461. package/dist/editor/ui/Splitter.js +102 -86
  462. package/dist/editor/ui/Splitter.js.map +1 -1
  463. package/dist/editor/ui/TemplateSelectorDialog.js +4 -4
  464. package/dist/editor/ui/TemplateSelectorDialog.js.map +1 -1
  465. package/dist/editor/ui/TreeListSelector.d.ts +6 -1
  466. package/dist/editor/ui/TreeListSelector.js +2 -2
  467. package/dist/editor/ui/TreeListSelector.js.map +1 -1
  468. package/dist/editor/utils/keyboardNavigation.d.ts +6 -20
  469. package/dist/editor/utils/keyboardNavigation.js +48 -140
  470. package/dist/editor/utils/keyboardNavigation.js.map +1 -1
  471. package/dist/editor/utils.js +19 -9
  472. package/dist/editor/utils.js.map +1 -1
  473. package/dist/editor/views/CompareView.d.ts +3 -1
  474. package/dist/editor/views/CompareView.js +7 -5
  475. package/dist/editor/views/CompareView.js.map +1 -1
  476. package/dist/editor/views/EditView.js +1 -1
  477. package/dist/editor/views/EditView.js.map +1 -1
  478. package/dist/editor/views/EditorSlot.js +27 -34
  479. package/dist/editor/views/EditorSlot.js.map +1 -1
  480. package/dist/editor/views/ItemEditor.js +7 -3
  481. package/dist/editor/views/ItemEditor.js.map +1 -1
  482. package/dist/editor/views/MediaFolderEditView.js +1 -1
  483. package/dist/editor/views/MediaFolderEditView.js.map +1 -1
  484. package/dist/editor/views/ParheliaView.js +5 -6
  485. package/dist/editor/views/ParheliaView.js.map +1 -1
  486. package/dist/editor/views/SingleEditView.d.ts +2 -1
  487. package/dist/editor/views/SingleEditView.js +10 -8
  488. package/dist/editor/views/SingleEditView.js.map +1 -1
  489. package/dist/editor/views/editorSlotContext.js +35 -6
  490. package/dist/editor/views/editorSlotContext.js.map +1 -1
  491. package/dist/index.d.ts +16 -2
  492. package/dist/index.js +11 -0
  493. package/dist/index.js.map +1 -1
  494. package/dist/revision.d.ts +2 -2
  495. package/dist/revision.js +2 -2
  496. package/dist/setup/services/setupWizardService.d.ts +48 -14
  497. package/dist/setup/services/setupWizardService.js +52 -17
  498. package/dist/setup/services/setupWizardService.js.map +1 -1
  499. package/dist/setup/wizard/steps/AddModelDialog.js +12 -3
  500. package/dist/setup/wizard/steps/AddModelDialog.js.map +1 -1
  501. package/dist/setup/wizard/steps/ImportModelDialog.js +46 -22
  502. package/dist/setup/wizard/steps/ImportModelDialog.js.map +1 -1
  503. package/dist/splash-screen/ModernSplashScreen.js +112 -32
  504. package/dist/splash-screen/ModernSplashScreen.js.map +1 -1
  505. package/dist/splash-screen/NewPage.js +33 -50
  506. package/dist/splash-screen/NewPage.js.map +1 -1
  507. package/dist/splash-screen/OpenPage.js +2 -6
  508. package/dist/splash-screen/OpenPage.js.map +1 -1
  509. package/dist/splash-screen/ParheliaAssistantChat.js +12 -29
  510. package/dist/splash-screen/ParheliaAssistantChat.js.map +1 -1
  511. package/dist/splash-screen/ParheliaLogo.js +87 -37
  512. package/dist/splash-screen/ParheliaLogo.js.map +1 -1
  513. package/dist/splash-screen/RecentPages.js +3 -3
  514. package/dist/splash-screen/RecentPages.js.map +1 -1
  515. package/dist/tour/Tour.d.ts +2 -1
  516. package/dist/tour/Tour.js +256 -75
  517. package/dist/tour/Tour.js.map +1 -1
  518. package/dist/tour/default-tour.js +222 -96
  519. package/dist/tour/default-tour.js.map +1 -1
  520. package/dist/types.d.ts +70 -29
  521. package/package.json +19 -15
  522. package/styles.css +39 -10
  523. package/dist/editor/ComponentInfo.d.ts +0 -4
  524. package/dist/editor/ComponentInfo.js +0 -41
  525. package/dist/editor/ComponentInfo.js.map +0 -1
  526. package/dist/editor/ai/HelpTerminal.d.ts +0 -5
  527. package/dist/editor/ai/HelpTerminal.js +0 -166
  528. package/dist/editor/ai/HelpTerminal.js.map +0 -1
  529. package/dist/editor/field-types/ReactQuill.d.ts +0 -125
  530. package/dist/editor/field-types/ReactQuill.js +0 -385
  531. package/dist/editor/field-types/ReactQuill.js.map +0 -1
  532. package/dist/editor/services-server/graphQL.d.ts +0 -29
  533. package/dist/editor/services-server/graphQL.js +0 -53
  534. package/dist/editor/services-server/graphQL.js.map +0 -1
  535. package/dist/editor/settings/AllAgentsPanel.d.ts +0 -5
  536. package/dist/editor/settings/AllAgentsPanel.js +0 -139
  537. package/dist/editor/settings/AllAgentsPanel.js.map +0 -1
  538. package/dist/editor/settings/LatestFeedback.d.ts +0 -1
  539. package/dist/editor/settings/LatestFeedback.js +0 -136
  540. package/dist/editor/settings/LatestFeedback.js.map +0 -1
  541. package/dist/editor/settings/Setup.d.ts +0 -1
  542. package/dist/editor/settings/Setup.js +0 -211
  543. package/dist/editor/settings/Setup.js.map +0 -1
  544. package/dist/editor/settings/panels/DatabasePanel.d.ts +0 -6
  545. package/dist/editor/settings/panels/DatabasePanel.js +0 -50
  546. package/dist/editor/settings/panels/DatabasePanel.js.map +0 -1
  547. package/dist/editor/settings/setup-steps/AiSetupStep/EmbeddingsModelSection.d.ts +0 -2
  548. package/dist/editor/settings/setup-steps/AiSetupStep/EmbeddingsModelSection.js +0 -195
  549. package/dist/editor/settings/setup-steps/AiSetupStep/EmbeddingsModelSection.js.map +0 -1
  550. package/dist/editor/settings/setup-steps/AiSetupStep/index.d.ts +0 -2
  551. package/dist/editor/settings/setup-steps/AiSetupStep/index.js +0 -21
  552. package/dist/editor/settings/setup-steps/AiSetupStep/index.js.map +0 -1
  553. package/dist/editor/settings/setup-steps/AiSetupStep/provider/ProviderSection.d.ts +0 -1
  554. package/dist/editor/settings/setup-steps/AiSetupStep/provider/ProviderSection.js +0 -233
  555. package/dist/editor/settings/setup-steps/AiSetupStep/provider/ProviderSection.js.map +0 -1
  556. package/dist/editor/settings/setup-steps/AiSetupStep/required-containers/RequiredContainersList.d.ts +0 -15
  557. package/dist/editor/settings/setup-steps/AiSetupStep/required-containers/RequiredContainersList.js +0 -14
  558. package/dist/editor/settings/setup-steps/AiSetupStep/required-containers/RequiredContainersList.js.map +0 -1
  559. package/dist/editor/settings/setup-steps/AiSetupStep/required-containers/RequiredContainersSection.d.ts +0 -1
  560. package/dist/editor/settings/setup-steps/AiSetupStep/required-containers/RequiredContainersSection.js +0 -94
  561. package/dist/editor/settings/setup-steps/AiSetupStep/required-containers/RequiredContainersSection.js.map +0 -1
  562. package/dist/editor/settings/setup-steps/AiSetupStep/types.d.ts +0 -1
  563. package/dist/editor/settings/setup-steps/AiSetupStep/types.js +0 -2
  564. package/dist/editor/settings/setup-steps/AiSetupStep/types.js.map +0 -1
  565. package/dist/editor/settings/setup-steps/AiSetupStep/utils.d.ts +0 -5
  566. package/dist/editor/settings/setup-steps/AiSetupStep/utils.js +0 -44
  567. package/dist/editor/settings/setup-steps/AiSetupStep/utils.js.map +0 -1
  568. package/dist/editor/settings/setup-steps/IndexSetupStep.d.ts +0 -2
  569. package/dist/editor/settings/setup-steps/IndexSetupStep.js +0 -36
  570. package/dist/editor/settings/setup-steps/IndexSetupStep.js.map +0 -1
  571. package/dist/editor/settings/setup-steps/SettingsSetupStep.d.ts +0 -2
  572. package/dist/editor/settings/setup-steps/SettingsSetupStep.js +0 -111
  573. package/dist/editor/settings/setup-steps/SettingsSetupStep.js.map +0 -1
  574. package/dist/editor/settings/setup-steps/SetupOverview.d.ts +0 -14
  575. package/dist/editor/settings/setup-steps/SetupOverview.js +0 -38
  576. package/dist/editor/settings/setup-steps/SetupOverview.js.map +0 -1
  577. package/dist/editor/sidebar/Debug.d.ts +0 -1
  578. package/dist/editor/sidebar/Debug.js +0 -70
  579. package/dist/editor/sidebar/Debug.js.map +0 -1
  580. package/dist/editor/sidebar/GraphQL.d.ts +0 -2
  581. package/dist/editor/sidebar/GraphQL.js +0 -234
  582. package/dist/editor/sidebar/GraphQL.js.map +0 -1
  583. package/dist/editor/sidebar/LeftToolbar.d.ts +0 -1
  584. package/dist/editor/sidebar/LeftToolbar.js +0 -12
  585. package/dist/editor/sidebar/LeftToolbar.js.map +0 -1
  586. package/dist/editor/sidebar/NavigationSidebar.d.ts +0 -4
  587. package/dist/editor/sidebar/NavigationSidebar.js +0 -254
  588. package/dist/editor/sidebar/NavigationSidebar.js.map +0 -1
  589. package/dist/editor/tree-indicators/GutterSelector.d.ts +0 -5
  590. package/dist/editor/tree-indicators/GutterSelector.js +0 -91
  591. package/dist/editor/tree-indicators/GutterSelector.js.map +0 -1
@@ -1,62 +1,189 @@
1
- import { jsx as _jsx, jsxs as _jsxs } from "react/jsx-runtime";
2
- import { useState, useEffect, useMemo } from "react";
1
+ import { jsx as _jsx, jsxs as _jsxs, Fragment as _Fragment } from "react/jsx-runtime";
2
+ import { useState, useEffect, useMemo, useCallback } from "react";
3
3
  import { Button } from "../../../components/ui/button";
4
+ import { Input } from "../../../components/ui/input";
5
+ import { Select } from "../../../components/ui/select";
6
+ import { Dialog, DialogContent, DialogDescription, DialogFooter, DialogHeader, DialogTitle, } from "../../../components/ui/dialog";
4
7
  import { setupWizardService, } from "../../../setup/services/setupWizardService";
5
- import { CheckCircle, AlertCircle, RefreshCw, Upload, Plus, ArrowRight, Settings, Cloud, Trash2, } from "lucide-react";
8
+ import { AlertCircle, RefreshCw, Upload, Plus, ArrowRight, Brain, Image, Settings, Cloud, Trash2, Copy, } from "lucide-react";
9
+ import { useSearchParams } from "../../client/navigation";
6
10
  import { AddModelDialog } from "../../../setup/wizard/steps/AddModelDialog";
7
11
  import { ImportModelDialog } from "../../../setup/wizard/steps/ImportModelDialog";
8
12
  import { Splitter } from "../../ui/Splitter";
9
- import { ItemConfigPanel } from "./ItemConfigPanel";
13
+ import { ModelConfigPanel } from "./ModelConfigPanel";
10
14
  import { useEditContext } from "../../client/editContext";
11
15
  import { FilterInput } from "../../../components/FilterInput";
16
+ const SELECTED_MODEL_QUERY_PARAM = "modelId";
17
+ /**
18
+ * True when a numeric price is present (including 0). Used for display and
19
+ * "missing pricing" detection.
20
+ */
21
+ const hasDefinedPricingValue = (value) => value !== undefined && value !== null;
22
+ const hasUsableImagePricing = (model) => hasDefinedPricingValue(model.pricing?.inputTextTokenCostPerMillion) ||
23
+ hasDefinedPricingValue(model.pricing?.inputImageTokenCostPerMillion) ||
24
+ hasDefinedPricingValue(model.pricing?.outputImageTokenCostPerMillion);
25
+ /**
26
+ * True when the model row has nothing to show on the pricing line (no usable
27
+ * token/image figures). This is the same condition used to decide whether to
28
+ * show the warning — avoids blank rows when field-level "missing" logic drifts.
29
+ */
30
+ const isPricingLineEmpty = (model) => !hasVisiblePricingSummary(model);
31
+ const getPricingWarningMessage = (model) => {
32
+ const template = model.templateType || "Ai Chat Model";
33
+ if (template === "Ai Image Model") {
34
+ return "Pricing information is missing. Configure at least one image pricing field.";
35
+ }
36
+ if (template === "Ai Embeddings Model") {
37
+ return "Pricing information is missing. Set Input Cost Per Million Tokens.";
38
+ }
39
+ const missingFields = [];
40
+ if (!hasDefinedPricingValue(model.pricing?.inputCostPerMillionTokens)) {
41
+ missingFields.push("Input Cost Per Million Tokens");
42
+ }
43
+ if (!hasDefinedPricingValue(model.pricing?.outputCostPerMillionTokens)) {
44
+ missingFields.push("Output Cost Per Million Tokens");
45
+ }
46
+ if (missingFields.length === 0) {
47
+ return "Pricing information is missing.";
48
+ }
49
+ return `Pricing information is missing. Set ${missingFields.join(" and ")}.`;
50
+ };
51
+ const hasVisiblePricingSummary = (model) => {
52
+ if (!model.pricing) {
53
+ return false;
54
+ }
55
+ if (model.templateType === "Ai Image Model") {
56
+ return hasUsableImagePricing(model);
57
+ }
58
+ return (hasDefinedPricingValue(model.pricing.inputCostPerMillionTokens) ||
59
+ hasDefinedPricingValue(model.pricing.outputCostPerMillionTokens) ||
60
+ hasDefinedPricingValue(model.pricing.cachedInputCostPerMillionTokens));
61
+ };
62
+ /** Sitecore item name for lists and dialogs; falls back to API model id / key. */
63
+ function getModelListLabel(model) {
64
+ return model.itemName?.trim() || model.name || model.key || "";
65
+ }
66
+ function normalizeModelId(id) {
67
+ return (id || "").replace(/[{}]/g, "").toLowerCase();
68
+ }
69
+ function getModelTypeLabel(templateType) {
70
+ switch (templateType) {
71
+ case "Ai Chat Model":
72
+ return "Chat";
73
+ case "Ai Embeddings Model":
74
+ return "Embeddings";
75
+ case "Ai Image Model":
76
+ return "Image";
77
+ default:
78
+ return templateType;
79
+ }
80
+ }
12
81
  /**
13
82
  * Settings panel for AI Models configuration.
14
83
  * Install and configure AI models for chat and other tasks.
15
84
  */
16
85
  export function ModelsPanel() {
17
86
  const editContext = useEditContext();
87
+ const searchParams = useSearchParams();
18
88
  const [state, setState] = useState("loading");
19
89
  const [installedModels, setInstalledModels] = useState([]);
20
90
  const [providers, setProviders] = useState([]);
91
+ const [settingsExists, setSettingsExists] = useState(false);
92
+ const [defaultChatModelId, setDefaultChatModelId] = useState("");
93
+ const [defaultImageModelId, setDefaultImageModelId] = useState("");
94
+ const [savingDefaults, setSavingDefaults] = useState(false);
21
95
  const [error, setError] = useState(null);
22
96
  const [updating, setUpdating] = useState(null);
23
97
  // Dialog states
24
98
  const [showAddDialog, setShowAddDialog] = useState(false);
25
99
  const [showImportDialog, setShowImportDialog] = useState(false);
26
- // Sidebar editor state
100
+ // URL-synced model selection
101
+ const [urlSelectedModelId, setUrlSelectedModelId] = useState(searchParams.get(SELECTED_MODEL_QUERY_PARAM) ||
102
+ (typeof window !== "undefined"
103
+ ? new URLSearchParams(window.location.search).get(SELECTED_MODEL_QUERY_PARAM)
104
+ : null));
27
105
  const [selectedModel, setSelectedModel] = useState(null);
28
106
  // Bulk pricing update state
29
107
  const [updatingAllPricing, setUpdatingAllPricing] = useState(false);
30
- const [updatingModelPricing, setUpdatingModelPricing] = useState(null);
31
108
  // Delete state
32
109
  const [deleting, setDeleting] = useState(null);
110
+ // Duplicate state
111
+ const [duplicatingId, setDuplicatingId] = useState(null);
112
+ const [duplicateDialogModel, setDuplicateDialogModel] = useState(null);
113
+ const [duplicateItemName, setDuplicateItemName] = useState("");
33
114
  // Provider types (discovered from backend)
34
115
  const [providerTypes, setProviderTypes] = useState([]);
35
116
  // Filter state
36
117
  const [filterText, setFilterText] = useState("");
118
+ useEffect(() => {
119
+ const key = searchParams.get(SELECTED_MODEL_QUERY_PARAM) ||
120
+ (typeof window !== "undefined"
121
+ ? new URLSearchParams(window.location.search).get(SELECTED_MODEL_QUERY_PARAM)
122
+ : null);
123
+ setUrlSelectedModelId(key);
124
+ }, [searchParams]);
125
+ useEffect(() => {
126
+ if (typeof window === "undefined")
127
+ return;
128
+ const handlePopState = () => {
129
+ setUrlSelectedModelId(new URLSearchParams(window.location.search).get(SELECTED_MODEL_QUERY_PARAM));
130
+ };
131
+ window.addEventListener("popstate", handlePopState);
132
+ return () => window.removeEventListener("popstate", handlePopState);
133
+ }, []);
134
+ useEffect(() => {
135
+ if (!urlSelectedModelId) {
136
+ if (selectedModel)
137
+ setSelectedModel(null);
138
+ return;
139
+ }
140
+ const match = installedModels.find((m) => m.id === urlSelectedModelId);
141
+ if (match && match !== selectedModel) {
142
+ setSelectedModel(match);
143
+ }
144
+ }, [installedModels, urlSelectedModelId, selectedModel]);
145
+ const updateSelectedModelUrl = useCallback((modelId) => {
146
+ editContext?.updateUrl({
147
+ [SELECTED_MODEL_QUERY_PARAM]: modelId || undefined,
148
+ });
149
+ setUrlSelectedModelId(modelId || null);
150
+ }, [editContext]);
37
151
  const handleOpenConfig = (model) => {
38
152
  setSelectedModel(model);
153
+ updateSelectedModelUrl(model.id);
39
154
  };
40
155
  const handleCloseConfig = () => {
41
156
  setSelectedModel(null);
157
+ updateSelectedModelUrl(null);
42
158
  };
43
159
  const loadData = async () => {
44
160
  try {
45
161
  setState("loading");
46
162
  setError(null);
47
- const [installed, providersData, providerTypesData] = await Promise.all([
163
+ const [installed, providersData, providerTypesData, defaultModels, hasSettings,] = await Promise.all([
48
164
  setupWizardService.getInstalledModels(),
49
165
  setupWizardService.getProviders(),
50
166
  setupWizardService.getProviderTypes(),
167
+ setupWizardService.getDefaultModels(),
168
+ setupWizardService.getSettingsExists(),
51
169
  ]);
52
170
  setInstalledModels(installed);
53
171
  setProviders(providersData);
54
172
  setProviderTypes(providerTypesData);
173
+ setSettingsExists(hasSettings);
174
+ const resolvedChatModel = installed.find((model) => normalizeModelId(model.id) ===
175
+ normalizeModelId(defaultModels.chatModelId));
176
+ const resolvedImageModel = installed.find((model) => normalizeModelId(model.id) ===
177
+ normalizeModelId(defaultModels.imageModelId));
178
+ setDefaultChatModelId(resolvedChatModel?.id || defaultModels.chatModelId || "");
179
+ setDefaultImageModelId(resolvedImageModel?.id || defaultModels.imageModelId || "");
55
180
  setState("success");
181
+ return installed;
56
182
  }
57
183
  catch (e) {
58
184
  setState("error");
59
185
  setError(e?.message || "Failed to load models");
186
+ return undefined;
60
187
  }
61
188
  };
62
189
  // Get providers that support model import (any provider with a registered provider type)
@@ -120,88 +247,131 @@ export function ModelsPanel() {
120
247
  setUpdatingAllPricing(false);
121
248
  }
122
249
  };
123
- // Update pricing for a single model
124
- const handleUpdateSingleModelPricing = async (model) => {
125
- if (!model.providerId || !model.name) {
126
- setError("Model provider or name is missing");
250
+ const handleUpdate = async (model) => {
251
+ if (!model.id || !model.key)
127
252
  return;
128
- }
129
253
  try {
130
- setUpdatingModelPricing(model.id);
254
+ setUpdating(model.id);
131
255
  setError(null);
132
- const result = await setupWizardService.upsertProviderModels({
133
- providerId: model.providerId,
134
- selectedModelIds: [model.name],
135
- mode: "updatePricing",
256
+ await setupWizardService.updateModel({
257
+ modelId: model.id,
258
+ sourceModelKey: model.key,
136
259
  });
137
260
  await loadData();
138
- if (result.errors.length > 0) {
139
- setError(`Errors: ${result.errors.join(", ")}`);
140
- }
141
261
  }
142
262
  catch (e) {
143
- setError(e?.message || "Failed to update pricing");
263
+ setError(e?.message || "Failed to update model");
144
264
  }
145
265
  finally {
146
- setUpdatingModelPricing(null);
266
+ setUpdating(null);
147
267
  }
148
268
  };
149
- const handleUpdate = async (model) => {
150
- if (!model.id || !model.key)
269
+ const handleDefaultModelsChange = async (nextChatModelId, nextImageModelId) => {
270
+ if (!settingsExists) {
271
+ setError("Parhelia settings item not found");
151
272
  return;
273
+ }
274
+ const previousChatModelId = defaultChatModelId;
275
+ const previousImageModelId = defaultImageModelId;
276
+ setDefaultChatModelId(nextChatModelId);
277
+ setDefaultImageModelId(nextImageModelId);
152
278
  try {
153
- setUpdating(model.id);
279
+ setSavingDefaults(true);
154
280
  setError(null);
155
- await setupWizardService.updateModel({
156
- modelId: model.id,
157
- sourceModelKey: model.key,
281
+ await setupWizardService.setDefaultModels({
282
+ chatModelId: nextChatModelId,
283
+ imageModelId: nextImageModelId,
158
284
  });
159
- await loadData();
160
285
  }
161
286
  catch (e) {
162
- setError(e?.message || "Failed to update model");
287
+ setDefaultChatModelId(previousChatModelId);
288
+ setDefaultImageModelId(previousImageModelId);
289
+ setError(e?.message || "Failed to save default models");
163
290
  }
164
291
  finally {
165
- setUpdating(null);
292
+ setSavingDefaults(false);
166
293
  }
167
294
  };
168
- const handleDelete = (model) => {
295
+ const handleDelete = async (model) => {
169
296
  if (!editContext || !model.id)
170
297
  return;
171
- editContext.confirm({
172
- header: "Delete Model",
173
- message: `Are you sure you want to delete "${model.name || model.key}"?`,
174
- acceptLabel: "Delete",
175
- showCancel: true,
176
- accept: async () => {
177
- try {
178
- setDeleting(model.id);
179
- setError(null);
180
- // If this model is currently selected, close the config panel
181
- if (selectedModel?.id === model.id) {
182
- setSelectedModel(null);
183
- }
184
- // Delete the model item
185
- await editContext.operations.deleteItems([
186
- {
187
- id: model.id,
188
- language: editContext.item?.language ??
189
- editContext.currentItemDescriptor?.language ??
190
- "en",
191
- version: 0,
192
- },
193
- ]);
194
- // Reload the models list
195
- await loadData();
196
- }
197
- catch (e) {
198
- setError(e?.message || "Failed to delete model");
298
+ try {
299
+ setDeleting(model.id);
300
+ setError(null);
301
+ const deleted = await editContext.operations.deleteItems([
302
+ {
303
+ id: model.id,
304
+ language: editContext.item?.language ??
305
+ editContext.currentItemDescriptor?.language ??
306
+ "en",
307
+ version: 0,
308
+ },
309
+ ]);
310
+ if (deleted) {
311
+ if (selectedModel?.id === model.id) {
312
+ setSelectedModel(null);
313
+ updateSelectedModelUrl(null);
199
314
  }
200
- finally {
201
- setDeleting(null);
315
+ await loadData();
316
+ }
317
+ }
318
+ catch (e) {
319
+ setError(e?.message || "Failed to delete model");
320
+ }
321
+ finally {
322
+ setDeleting(null);
323
+ }
324
+ };
325
+ const openDuplicateDialog = (model) => {
326
+ const segment = model.itemName?.trim() ||
327
+ (model.key.includes("/") && model.key.split("/").length > 0
328
+ ? model.key.split("/").pop()
329
+ : model.name || model.key);
330
+ setDuplicateItemName(`Copy of ${segment}`);
331
+ setDuplicateDialogModel(model);
332
+ };
333
+ const handleConfirmDuplicate = async () => {
334
+ if (!editContext || !duplicateDialogModel?.id) {
335
+ return;
336
+ }
337
+ const parentId = duplicateDialogModel.parentId;
338
+ if (!parentId) {
339
+ return;
340
+ }
341
+ const name = duplicateItemName.trim();
342
+ if (!name) {
343
+ setError("Enter a name for the duplicate item");
344
+ return;
345
+ }
346
+ const model = duplicateDialogModel;
347
+ const lang = editContext.item?.language ??
348
+ editContext.currentItemDescriptor?.language ??
349
+ "en";
350
+ try {
351
+ setDuplicatingId(model.id);
352
+ setError(null);
353
+ const created = await editContext.operations.duplicateItem({ id: model.id, language: lang, version: 0 }, { id: parentId, language: lang, version: 0 }, name);
354
+ if (!created) {
355
+ setDuplicatingId(null);
356
+ return;
357
+ }
358
+ setDuplicateDialogModel(null);
359
+ const list = await loadData();
360
+ if (list) {
361
+ const createdId = String(created.id).replace(/[{}]/g, "").toLowerCase();
362
+ const next = list.find((m) => m.id.replace(/[{}]/g, "").toLowerCase() === createdId);
363
+ if (next) {
364
+ setSelectedModel(next);
365
+ updateSelectedModelUrl(next.id);
202
366
  }
203
- },
204
- });
367
+ }
368
+ }
369
+ catch (e) {
370
+ setError(e?.message || "Failed to duplicate model");
371
+ }
372
+ finally {
373
+ setDuplicatingId(null);
374
+ }
205
375
  };
206
376
  useEffect(() => {
207
377
  loadData();
@@ -211,25 +381,50 @@ export function ModelsPanel() {
211
381
  window.location.hash = "#providers";
212
382
  }
213
383
  };
214
- // Check if model uses an importable provider (OpenRouter or Novita)
215
- const isImportableModel = (model) => {
216
- if (!model.providerId)
217
- return false;
218
- return importableProviders.some((p) => p.id === model.providerId);
219
- };
220
- // Helper to get model type display label
221
- const getModelTypeLabel = (templateType) => {
222
- switch (templateType) {
223
- case "Ai Chat Model":
224
- return "Chat";
225
- case "Ai Embeddings Model":
226
- return "Embeddings";
227
- case "Ai Image Model":
228
- return "Image";
229
- default:
230
- return templateType;
384
+ const chatModels = useMemo(() => installedModels
385
+ .filter((model) => model.templateType === "Ai Chat Model")
386
+ .sort((a, b) => getModelListLabel(a).localeCompare(getModelListLabel(b))), [installedModels]);
387
+ const imageModels = useMemo(() => installedModels
388
+ .filter((model) => model.templateType === "Ai Image Model")
389
+ .sort((a, b) => getModelListLabel(a).localeCompare(getModelListLabel(b))), [installedModels]);
390
+ const chatDefaultConfiguredModel = useMemo(() => chatModels.find((model) => normalizeModelId(model.id) === normalizeModelId(defaultChatModelId)), [chatModels, defaultChatModelId]);
391
+ const imageDefaultConfiguredModel = useMemo(() => imageModels.find((model) => normalizeModelId(model.id) === normalizeModelId(defaultImageModelId)), [imageModels, defaultImageModelId]);
392
+ const chatModelOptions = useMemo(() => {
393
+ const options = [
394
+ { value: "", label: "Not set" },
395
+ ...chatModels.map((model) => ({
396
+ value: model.id,
397
+ label: getModelListLabel(model),
398
+ description: model.providerName || undefined,
399
+ })),
400
+ ];
401
+ if (defaultChatModelId && !chatDefaultConfiguredModel) {
402
+ options.push({
403
+ value: defaultChatModelId,
404
+ label: "Configured model not found",
405
+ description: defaultChatModelId,
406
+ });
231
407
  }
232
- };
408
+ return options;
409
+ }, [chatModels, defaultChatModelId, chatDefaultConfiguredModel]);
410
+ const imageModelOptions = useMemo(() => {
411
+ const options = [
412
+ { value: "", label: "Not set" },
413
+ ...imageModels.map((model) => ({
414
+ value: model.id,
415
+ label: getModelListLabel(model),
416
+ description: model.providerName || undefined,
417
+ })),
418
+ ];
419
+ if (defaultImageModelId && !imageDefaultConfiguredModel) {
420
+ options.push({
421
+ value: defaultImageModelId,
422
+ label: "Configured model not found",
423
+ description: defaultImageModelId,
424
+ });
425
+ }
426
+ return options;
427
+ }, [imageModels, defaultImageModelId, imageDefaultConfiguredModel]);
233
428
  // Filter models based on filter text
234
429
  const filteredModels = useMemo(() => {
235
430
  if (!filterText.trim()) {
@@ -237,18 +432,20 @@ export function ModelsPanel() {
237
432
  }
238
433
  const searchTerm = filterText.toLowerCase().trim();
239
434
  return installedModels.filter((model) => {
435
+ const listLabel = getModelListLabel(model).toLowerCase();
240
436
  const modelName = (model.name || model.key || "").toLowerCase();
241
437
  const providerName = (model.providerName || "").toLowerCase();
242
438
  const templateType = (model.templateType || "").toLowerCase();
243
439
  const modelTypeLabel = getModelTypeLabel(model.templateType || "Ai Chat Model").toLowerCase();
244
- return (modelName.includes(searchTerm) ||
440
+ return (listLabel.includes(searchTerm) ||
441
+ modelName.includes(searchTerm) ||
245
442
  providerName.includes(searchTerm) ||
246
443
  templateType.includes(searchTerm) ||
247
444
  modelTypeLabel.includes(searchTerm));
248
445
  });
249
- }, [installedModels, filterText, getModelTypeLabel]);
446
+ }, [installedModels, filterText]);
250
447
  // Group models by provider for display
251
- const groupModelsByProvider = (models) => {
448
+ const groupModelsByProvider = useCallback((models) => {
252
449
  const groups = {};
253
450
  models.forEach((model) => {
254
451
  const providerId = model.providerId || "unknown";
@@ -265,42 +462,59 @@ export function ModelsPanel() {
265
462
  const typeOrder = (a.templateType || "").localeCompare(b.templateType || "");
266
463
  if (typeOrder !== 0)
267
464
  return typeOrder;
268
- return (a.name || a.key || "").localeCompare(b.name || b.key || "");
465
+ return getModelListLabel(a).localeCompare(getModelListLabel(b));
269
466
  });
270
467
  });
271
468
  return groups;
272
- };
273
- const modelsByProvider = useMemo(() => groupModelsByProvider(filteredModels), [filteredModels, providers]);
274
- const statusIcon = (currentState) => {
275
- if (currentState === "success")
276
- return _jsx(CheckCircle, { className: "h-4 w-4 text-green-600", strokeWidth: 1 });
277
- if (currentState === "error")
278
- return _jsx(AlertCircle, { className: "h-4 w-4 text-red-600", strokeWidth: 1 });
279
- return (_jsx(RefreshCw, { className: "h-4 w-4 animate-spin text-amber-600", strokeWidth: 1 }));
280
- };
469
+ }, [providers]);
470
+ const modelsByProvider = useMemo(() => groupModelsByProvider(filteredModels), [filteredModels, groupModelsByProvider]);
471
+ const modelsMissingPricing = useMemo(() => {
472
+ return installedModels.filter((model) => isPricingLineEmpty(model));
473
+ }, [installedModels]);
281
474
  // Build the models list content
282
- const modelsListContent = (_jsx("div", { className: "flex h-full flex-col p-4", children: _jsx("div", { className: "mx-auto flex w-full flex-1 flex-col overflow-hidden", children: _jsxs("div", { className: "flex h-full flex-col overflow-hidden", children: [_jsxs("div", { className: "shrink-0 space-y-4 pb-4", children: [_jsxs("div", { className: "flex items-center justify-between", children: [_jsxs("div", { className: "flex items-center gap-2", children: [statusIcon(state), _jsxs("span", { className: "text-sm text-gray-700", children: [installedModels.length, " model", installedModels.length !== 1 ? "s" : "", " installed"] })] }), importableInstalledModels.length > 0 && (_jsxs(Button, { size: "sm", variant: "outline", onClick: handleUpdateAllPricing, disabled: updatingAllPricing, title: "Update pricing for all models from their provider APIs", children: [updatingAllPricing ? (_jsx(RefreshCw, { className: "mr-1 h-4 w-4 animate-spin" })) : (_jsx(RefreshCw, { className: "mr-1 h-4 w-4" })), "Update All Pricing"] }))] }), state !== "loading" && providers.length === 0 && (_jsx("div", { className: "rounded border border-yellow-200 bg-yellow-50 p-4", children: _jsxs("div", { className: "flex items-start gap-3", children: [_jsx(AlertCircle, { className: "mt-0.5 h-5 w-5 shrink-0 text-yellow-600" }), _jsxs("div", { className: "flex-1", children: [_jsx("p", { className: "mb-1 text-sm font-medium text-yellow-800", children: "No providers configured" }), _jsx("p", { className: "mb-3 text-xs text-yellow-700", children: "You need to configure at least one provider before you can add models." }), _jsxs(Button, { size: "sm", variant: "outline", onClick: handleNavigateToProviders, className: "text-xs", children: ["Go to Providers", _jsx(ArrowRight, { className: "ml-1 h-3 w-3" })] })] })] }) })), providers.length > 0 && (_jsxs("div", { className: "flex gap-2", children: [importableProviders.length > 0 && (_jsxs(Button, { size: "sm", variant: "outline", onClick: () => {
283
- setShowImportDialog(true);
284
- setError(null);
285
- }, children: [_jsx(Cloud, { strokeWidth: 1, className: "mr-1 h-4 w-4" }), "Import from Provider"] })), _jsxs(Button, { size: "sm", variant: "outline", onClick: () => {
286
- setShowAddDialog(true);
287
- setError(null);
288
- }, children: [_jsx(Plus, { strokeWidth: 1, className: "mr-1 h-4 w-4" }), "Add Manually"] })] })), error && (_jsx("div", { className: "rounded border border-red-200 bg-red-50 p-2 text-xs whitespace-pre-wrap text-red-700", children: error })), _jsx(FilterInput, { value: filterText, onChange: setFilterText, placeholder: "Filter models by name, provider, or type...", className: "w-full" })] }), _jsx("div", { className: "min-h-0 flex-1 overflow-y-auto", children: filterText && filteredModels.length === 0 ? (_jsxs("div", { className: "flex items-center justify-center py-8 text-sm text-gray-500", children: ["No models found matching \"", filterText, "\""] })) : (_jsx("div", { className: "space-y-4", children: Object.entries(modelsByProvider).map(([providerId, { providerName, models }]) => {
475
+ const modelsListContent = (_jsx("div", { className: "flex h-full flex-col p-4", children: _jsx("div", { className: "mx-auto flex w-full flex-1 flex-col overflow-hidden", children: _jsxs("div", { className: "flex h-full flex-col overflow-hidden", children: [_jsxs("div", { className: "mt-1 shrink-0", children: [_jsxs("div", { className: "mb-2 rounded-t-lg bg-white p-4", children: [_jsxs("div", { className: "flex flex-wrap items-start justify-between gap-3", children: [_jsxs("div", { children: [_jsx("h2", { className: "text-sm font-semibold text-gray-900", children: "Default models" }), _jsx("p", { className: "mt-1 text-xs text-gray-500", children: "Choose the shared defaults used when a chat or image model is not configured elsewhere." })] }), savingDefaults && (_jsxs("div", { className: "flex items-center gap-2 text-xs text-gray-500", children: [_jsx(RefreshCw, { className: "h-3.5 w-3.5 animate-spin" }), "Saving..."] }))] }), _jsxs("div", { className: "mt-4 grid gap-4 md:grid-cols-2", children: [_jsxs("div", { className: "space-y-2", children: [_jsxs("label", { className: "flex items-center gap-2 text-sm font-medium text-gray-700", children: [_jsx(Brain, { className: "h-4 w-4 text-purple-600", strokeWidth: 1.5 }), "Default chat model"] }), _jsx(Select, { value: defaultChatModelId, onValueChange: (value) => void handleDefaultModelsChange(value, defaultImageModelId), options: chatModelOptions, placeholder: "Select a chat model", disabled: savingDefaults || !settingsExists, searchable: true, searchPlaceholder: "Search chat models..." }), _jsx("p", { className: "text-xs text-gray-500", children: "Used by features that fall back to the settings-level chat model." })] }), _jsxs("div", { className: "space-y-2", children: [_jsxs("label", { className: "flex items-center gap-2 text-sm font-medium text-gray-700", children: [_jsx(Image, { className: "h-4 w-4 text-green-600", strokeWidth: 1.5 }), "Default image model"] }), _jsx(Select, { value: defaultImageModelId, onValueChange: (value) => void handleDefaultModelsChange(defaultChatModelId, value), options: imageModelOptions, placeholder: "Select an image model", disabled: savingDefaults || !settingsExists, searchable: true, searchPlaceholder: "Search image models..." }), _jsx("p", { className: "text-xs text-gray-500", children: "Used by image generation and editing features that rely on the shared default." })] })] }), !settingsExists && (_jsx("div", { className: "mt-4 rounded border border-yellow-200 bg-yellow-50 p-3 text-xs text-yellow-800", children: "Create the Parhelia settings item before saving default models." }))] }), _jsx("div", { className: "rounded-t-lg bg-white p-4", children: _jsxs("div", { className: "flex flex-wrap items-start justify-between gap-3", children: [_jsxs("div", { children: [_jsxs("h2", { className: "text-sm font-semibold text-gray-900", children: ["Installed models (", installedModels.length, ")"] }), _jsx("p", { className: "mt-1 text-xs text-gray-500", children: "Browse, filter, and configure the models available in Parhelia." }), modelsMissingPricing.length > 0 && (_jsxs("div", { className: "mt-3 rounded border border-yellow-200 bg-yellow-50 p-3 text-xs text-yellow-800", children: [modelsMissingPricing.length, " installed model", modelsMissingPricing.length !== 1
476
+ ? "s have"
477
+ : " has", " ", "missing or incomplete pricing information. A warning is shown on each affected model below."] }))] }), _jsx("div", { className: "flex flex-wrap items-center gap-3", children: importableInstalledModels.length > 0 && (_jsxs(Button, { size: "sm", variant: "outline", onClick: handleUpdateAllPricing, disabled: updatingAllPricing, title: "Update pricing for all models from their provider APIs", children: [updatingAllPricing ? (_jsx(RefreshCw, { className: "mr-1 h-4 w-4 animate-spin" })) : (_jsx(RefreshCw, { className: "mr-1 h-4 w-4" })), "Update All Pricing"] })) })] }) }), _jsxs("div", { className: "bg-white px-4", children: [state !== "loading" && providers.length === 0 && (_jsx("div", { className: "rounded border border-yellow-200 bg-yellow-50 p-4", children: _jsxs("div", { className: "flex items-start gap-3", children: [_jsx(AlertCircle, { className: "mt-0.5 h-5 w-5 shrink-0 text-yellow-600" }), _jsxs("div", { className: "flex-1", children: [_jsx("p", { className: "mb-1 text-sm font-medium text-yellow-800", children: "No providers configured" }), _jsx("p", { className: "mb-3 text-xs text-yellow-700", children: "You need to configure at least one provider before you can add models." }), _jsxs(Button, { size: "sm", variant: "outline", onClick: handleNavigateToProviders, className: "text-xs", children: ["Go to Providers", _jsx(ArrowRight, { className: "ml-1 h-3 w-3" })] })] })] }) })), providers.length > 0 && (_jsxs("div", { className: "mb-4 flex gap-2", children: [importableProviders.length > 0 && (_jsxs(Button, { size: "sm", variant: "outline", onClick: () => {
478
+ setShowImportDialog(true);
479
+ setError(null);
480
+ }, children: [_jsx(Cloud, { strokeWidth: 1, className: "mr-1 h-4 w-4" }), "Import from Provider"] })), _jsxs(Button, { size: "sm", variant: "outline", onClick: () => {
481
+ setShowAddDialog(true);
482
+ setError(null);
483
+ }, children: [_jsx(Plus, { strokeWidth: 1, className: "mr-1 h-4 w-4" }), "Add Manually"] })] })), error && (_jsx("div", { className: "rounded border border-red-200 bg-red-50 p-2 text-xs whitespace-pre-wrap text-red-700", children: error })), _jsx(FilterInput, { value: filterText, onChange: setFilterText, placeholder: "Filter models by name, provider, or type...", className: "mb-4 w-full" })] })] }), _jsx("div", { className: "min-h-0 flex-1 overflow-y-auto rounded-b-lg bg-white px-4 pb-4", children: filterText && filteredModels.length === 0 ? (_jsxs("div", { className: "flex items-center justify-center py-8 text-sm text-gray-500", children: ["No models found matching ", `"${filterText}"`] })) : (_jsx("div", { className: "space-y-4", children: Object.entries(modelsByProvider).map(([providerId, { providerName, models }]) => {
289
484
  if (models.length === 0)
290
485
  return null;
291
486
  return (_jsxs("div", { className: "space-y-2", children: [_jsxs("label", { className: "block text-sm font-medium text-gray-700", children: [providerName, _jsxs("span", { className: "ml-2 text-xs font-normal text-gray-500", children: ["(", models.length, " model", models.length !== 1 ? "s" : "", ")"] })] }), _jsx("div", { className: "space-y-2", children: models.map((model) => {
292
487
  const status = model.status;
293
488
  const isSelected = selectedModel?.id === model.id;
489
+ const showPricingLine = hasVisiblePricingSummary(model);
294
490
  return (_jsxs("div", { className: `flex flex-wrap items-center gap-2 rounded border p-3 text-sm transition-shadow hover:shadow-sm ${isSelected
295
491
  ? "border-blue-400 bg-blue-50"
296
- : "border-gray-200 bg-white"}`, children: [_jsxs("div", { className: "min-w-0 flex-1", children: [_jsxs("div", { className: "flex flex-wrap items-center gap-2", children: [_jsx("span", { className: "truncate font-medium", children: model.name || model.key }), _jsx("span", { className: "shrink-0 rounded bg-gray-100 px-1.5 py-0.5 text-xs text-gray-600", children: getModelTypeLabel(model.templateType || "Ai Chat Model") }), status === "Outdated" && (_jsx("span", { className: "shrink-0 rounded bg-amber-100 px-1.5 py-0.5 text-xs text-amber-700", children: "Update available" }))] }), model.pricing && (_jsxs("div", { className: "mt-1 text-xs text-gray-500", children: ["Input: $", model.pricing.inputCostPerMillionTokens?.toFixed(2) || "0.00", "/M, Output: $", model.pricing.outputCostPerMillionTokens?.toFixed(2) || "0.00", "/M", model.pricing
297
- .cachedInputCostPerMillionTokens && (_jsxs("span", { className: "ml-2", children: ["Cached: $", model.pricing.cachedInputCostPerMillionTokens.toFixed(2), "/M"] }))] })), (model.maxContextWindowTokens ||
492
+ : "border-gray-200 bg-white"}`, children: [_jsxs("div", { className: "min-w-0 flex-1", children: [_jsxs("div", { className: "flex flex-wrap items-center gap-2", children: [_jsx("span", { className: "truncate font-medium", children: getModelListLabel(model) }), _jsx("span", { className: "shrink-0 rounded bg-gray-100 px-1.5 py-0.5 text-xs text-gray-600", children: getModelTypeLabel(model.templateType || "Ai Chat Model") }), normalizeModelId(model.id) ===
493
+ normalizeModelId(defaultChatModelId) && (_jsx("span", { className: "shrink-0 rounded bg-purple-100 px-1.5 py-0.5 text-xs text-purple-700", children: "Default chat" })), normalizeModelId(model.id) ===
494
+ normalizeModelId(defaultImageModelId) && (_jsx("span", { className: "shrink-0 rounded bg-green-100 px-1.5 py-0.5 text-xs text-green-700", children: "Default image" })), status === "Outdated" && (_jsx("span", { className: "shrink-0 rounded bg-amber-100 px-1.5 py-0.5 text-xs text-amber-700", children: "Update available" })), !showPricingLine && (_jsx("span", { className: "shrink-0 rounded bg-yellow-100 px-1.5 py-0.5 text-xs text-yellow-800", children: "Pricing missing" }))] }), showPricingLine && model.pricing ? (_jsx("div", { className: "mt-1 text-xs text-gray-500", children: model.templateType ===
495
+ "Ai Image Model" &&
496
+ hasUsableImagePricing(model) ? (_jsxs(_Fragment, { children: [hasDefinedPricingValue(model.pricing.inputTextTokenCostPerMillion) && (_jsxs("span", { children: ["Input Text: $", model.pricing.inputTextTokenCostPerMillion.toFixed(2), "/M"] })), hasDefinedPricingValue(model.pricing.inputImageTokenCostPerMillion) && (_jsxs("span", { className: "ml-2", children: ["Input Image: $", model.pricing.inputImageTokenCostPerMillion.toFixed(2), "/M"] })), hasDefinedPricingValue(model.pricing.outputImageTokenCostPerMillion) && (_jsxs("span", { className: "ml-2", children: ["Output Image: $", model.pricing.outputImageTokenCostPerMillion.toFixed(2), "/M"] }))] })) : (_jsxs(_Fragment, { children: [hasDefinedPricingValue(model.pricing
497
+ .inputCostPerMillionTokens) && (_jsxs("span", { children: ["Input: $", model.pricing.inputCostPerMillionTokens.toFixed(2), "/M"] })), hasDefinedPricingValue(model.pricing
498
+ .outputCostPerMillionTokens) && (_jsxs("span", { className: "ml-2", children: ["Output: $", model.pricing.outputCostPerMillionTokens.toFixed(2), "/M"] })), hasDefinedPricingValue(model.pricing
499
+ .cachedInputCostPerMillionTokens) && (_jsxs("span", { className: "ml-2", children: ["Cached: $", model.pricing.cachedInputCostPerMillionTokens.toFixed(2), "/M"] }))] })) })) : (_jsxs("div", { className: "mt-1 flex items-start gap-2 rounded border border-yellow-200 bg-yellow-50 px-2 py-1.5 text-xs text-yellow-800", children: [_jsx(AlertCircle, { className: "mt-0.5 h-3.5 w-3.5 shrink-0" }), _jsx("span", { children: getPricingWarningMessage(model) })] })), (model.maxContextWindowTokens ||
298
500
  model.maxResponseTokens) && (_jsxs("div", { className: "mt-1 text-xs text-gray-500", children: [model.maxContextWindowTokens && (_jsxs("span", { children: ["Context:", " ", model.maxContextWindowTokens.toLocaleString(), " ", "tokens"] })), model.maxContextWindowTokens &&
299
501
  model.maxResponseTokens &&
300
- " • ", model.maxResponseTokens && (_jsxs("span", { children: ["Max Response:", " ", model.maxResponseTokens.toLocaleString(), " ", "tokens"] }))] }))] }), _jsxs("div", { className: "flex shrink-0 items-center gap-1", children: [status === "Outdated" && (_jsxs(Button, { size: "sm", variant: "outline", onClick: () => handleUpdate(model), disabled: updating === model.id, title: "Update model", children: [updating === model.id ? (_jsx(RefreshCw, { strokeWidth: 1, className: "h-3 w-3 animate-spin" })) : (_jsx(Upload, { strokeWidth: 1, className: "h-3 w-3" })), _jsx("span", { className: "ml-1 hidden sm:inline", children: "Update" })] })), isImportableModel(model) && (_jsx(Button, { size: "sm", variant: "ghost", onClick: () => handleUpdateSingleModelPricing(model), disabled: updatingModelPricing === model.id ||
301
- updatingAllPricing, title: "Update pricing from provider API", children: updatingModelPricing === model.id ? (_jsx(RefreshCw, { strokeWidth: 1, className: "h-3 w-3 animate-spin" })) : (_jsx(RefreshCw, { strokeWidth: 1, className: "h-3 w-3" })) })), _jsxs(Button, { size: "sm", variant: isSelected ? "default" : "ghost", onClick: () => handleOpenConfig(model), title: "Configure model", children: [_jsx(Settings, { className: "h-4 w-4", strokeWidth: 1.5 }), _jsx("span", { className: "ml-1 hidden sm:inline", children: "Configure" })] }), _jsx(Button, { size: "sm", variant: "ghost", onClick: () => handleDelete(model), disabled: deleting === model.id, title: "Delete model", className: "text-red-600 hover:bg-red-50 hover:text-red-700", children: deleting === model.id ? (_jsx(RefreshCw, { strokeWidth: 1, className: "h-3 w-3 animate-spin" })) : (_jsx(Trash2, { strokeWidth: 1, className: "h-3 w-3" })) })] })] }, model.id));
502
+ " • ", model.maxResponseTokens && (_jsxs("span", { children: ["Max Response:", " ", model.maxResponseTokens.toLocaleString(), " ", "tokens"] }))] }))] }), _jsxs("div", { className: "flex shrink-0 items-center gap-1", children: [status === "Outdated" && (_jsxs(Button, { size: "sm", variant: "outline", onClick: () => handleUpdate(model), disabled: updating === model.id, title: "Update model", children: [updating === model.id ? (_jsx(RefreshCw, { strokeWidth: 1, className: "h-3 w-3 animate-spin" })) : (_jsx(Upload, { strokeWidth: 1, className: "h-3 w-3" })), _jsx("span", { className: "ml-1 hidden sm:inline", children: "Update" })] })), _jsxs(Button, { size: "sm", variant: isSelected ? "default" : "ghost", onClick: () => handleOpenConfig(model), title: "Configure model", children: [_jsx(Settings, { className: "h-4 w-4", strokeWidth: 1.5 }), _jsx("span", { className: "ml-1 hidden sm:inline", children: "Configure" })] }), _jsxs(Button, { size: "sm", variant: "ghost", onClick: () => openDuplicateDialog(model), disabled: !editContext ||
503
+ !model.parentId ||
504
+ duplicatingId === model.id, title: "Duplicate model", children: [duplicatingId === model.id ? (_jsx(RefreshCw, { strokeWidth: 1, className: "h-3 w-3 animate-spin" })) : (_jsx(Copy, { strokeWidth: 1, className: "h-3 w-3" })), _jsx("span", { className: "ml-1 hidden sm:inline", children: "Duplicate" })] }), _jsx(Button, { size: "sm", variant: "ghost", onClick: () => handleDelete(model), disabled: deleting === model.id, title: "Delete model", className: "text-red-600 hover:bg-red-50 hover:text-red-700", children: deleting === model.id ? (_jsx(RefreshCw, { strokeWidth: 1, className: "h-3 w-3 animate-spin" })) : (_jsx(Trash2, { strokeWidth: 1, className: "h-3 w-3" })) })] })] }, model.id));
302
505
  }) })] }, providerId));
303
- }) })) }), _jsx(AddModelDialog, { open: showAddDialog, onOpenChange: setShowAddDialog, onSuccess: loadData, providers: providers, installedModels: installedModels }), _jsx(ImportModelDialog, { open: showImportDialog, onOpenChange: setShowImportDialog, onSuccess: loadData, importableProviders: importableProviders, providerTypes: providerTypes })] }) }) }));
506
+ }) })) }), _jsx(AddModelDialog, { open: showAddDialog, onOpenChange: setShowAddDialog, onSuccess: loadData, providers: providers, installedModels: installedModels }), _jsx(ImportModelDialog, { open: showImportDialog, onOpenChange: setShowImportDialog, onSuccess: loadData, importableProviders: importableProviders, providerTypes: providerTypes }), _jsx(Dialog, { open: duplicateDialogModel !== null, onOpenChange: (open) => {
507
+ if (!open)
508
+ setDuplicateDialogModel(null);
509
+ }, children: _jsxs(DialogContent, { className: "max-w-md", children: [_jsxs(DialogHeader, { className: "pr-14", children: [_jsx(DialogTitle, { children: "Duplicate model" }), _jsx(DialogDescription, { children: "New Sitecore item name. Field values (including model name and reasoning) are copied; adjust them in Configure after duplicating." })] }), _jsxs("div", { className: "space-y-2 px-8 pb-6", children: [_jsx("label", { htmlFor: "duplicate-model-item-name", className: "block text-sm font-medium text-gray-700", children: "Item name" }), _jsx(Input, { id: "duplicate-model-item-name", value: duplicateItemName, onChange: (e) => setDuplicateItemName(e.target.value), onKeyDown: (e) => {
510
+ if (e.key === "Enter") {
511
+ e.preventDefault();
512
+ void handleConfirmDuplicate();
513
+ }
514
+ }, autoFocus: true })] }), _jsxs(DialogFooter, { className: "border-t border-gray-100 pt-4", children: [_jsx(Button, { type: "button", variant: "outline", className: "min-h-9 min-w-22", onClick: () => setDuplicateDialogModel(null), children: "Cancel" }), _jsx(Button, { type: "button", className: "min-h-9 min-w-22", onClick: () => void handleConfirmDuplicate(), disabled: !duplicateItemName.trim() ||
515
+ (duplicateDialogModel != null &&
516
+ duplicatingId === duplicateDialogModel.id), children: duplicateDialogModel != null &&
517
+ duplicatingId === duplicateDialogModel.id ? (_jsxs(_Fragment, { children: [_jsx(RefreshCw, { className: "mr-1 h-4 w-4 animate-spin" }), "Duplicating\u2026"] })) : ("Duplicate") })] })] }) })] }) }) }));
304
518
  // Build splitter panels - only show config panel when a model is selected
305
519
  const panels = selectedModel?.id
306
520
  ? [
@@ -313,7 +527,9 @@ export function ModelsPanel() {
313
527
  {
314
528
  name: "model-config",
315
529
  defaultSize: 400,
316
- content: (_jsx(ItemConfigPanel, { itemId: selectedModel.id, title: `Configure: ${selectedModel.name || selectedModel.key || "Model"}`, onClose: handleCloseConfig }, selectedModel.id)),
530
+ content: (_jsx(ModelConfigPanel, { itemId: selectedModel.id, title: `Configure: ${getModelListLabel(selectedModel) || "Model"}`, onClose: handleCloseConfig, onModelRenamed: async () => {
531
+ await loadData();
532
+ } }, selectedModel.id)),
317
533
  className: "overflow-hidden",
318
534
  },
319
535
  ]