@parhelia/core 0.1.12556 → 0.1.12560

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