@parhelia/core 0.1.12911 → 0.1.12917

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 (333) hide show
  1. package/dist/agents-view/AgentGalleryCard.js +1 -1
  2. package/dist/agents-view/AgentGalleryCard.js.map +1 -1
  3. package/dist/agents-view/AgentGalleryView.d.ts +1 -1
  4. package/dist/agents-view/AgentGalleryView.js +3 -2
  5. package/dist/agents-view/AgentGalleryView.js.map +1 -1
  6. package/dist/agents-view/AgentsView.js +1 -1
  7. package/dist/agents-view/AgentsView.js.map +1 -1
  8. package/dist/agents-view/AgentsWorkspaceView.js +15 -2
  9. package/dist/agents-view/AgentsWorkspaceView.js.map +1 -1
  10. package/dist/components/MarkdownViewerPopover.d.ts +73 -0
  11. package/dist/components/MarkdownViewerPopover.js +109 -0
  12. package/dist/components/MarkdownViewerPopover.js.map +1 -0
  13. package/dist/components/PageHeader.d.ts +11 -2
  14. package/dist/components/PageHeader.js +8 -3
  15. package/dist/components/PageHeader.js.map +1 -1
  16. package/dist/components/SearchInput.js +1 -1
  17. package/dist/components/ui/UserPicker.d.ts +5 -1
  18. package/dist/components/ui/UserPicker.js +17 -3
  19. package/dist/components/ui/UserPicker.js.map +1 -1
  20. package/dist/components/ui/button.js +1 -1
  21. package/dist/components/ui/button.js.map +1 -1
  22. package/dist/components/ui/command.js +1 -1
  23. package/dist/components/ui/delete-button.d.ts +1 -1
  24. package/dist/components/ui/delete-button.js +2 -2
  25. package/dist/components/ui/delete-button.js.map +1 -1
  26. package/dist/components/ui/dropdown-menu.js +3 -3
  27. package/dist/components/ui/input.js +1 -1
  28. package/dist/components/ui/input.js.map +1 -1
  29. package/dist/components/ui/label.js +1 -1
  30. package/dist/components/ui/select.d.ts +2 -0
  31. package/dist/components/ui/select.js +8 -6
  32. package/dist/components/ui/select.js.map +1 -1
  33. package/dist/components/ui/textarea.js +1 -3
  34. package/dist/components/ui/textarea.js.map +1 -1
  35. package/dist/config/config.js +22 -2
  36. package/dist/config/config.js.map +1 -1
  37. package/dist/config/types/workspace.d.ts +6 -2
  38. package/dist/editor/ConfirmationDialog.d.ts +3 -0
  39. package/dist/editor/ConfirmationDialog.js +5 -1
  40. package/dist/editor/ConfirmationDialog.js.map +1 -1
  41. package/dist/editor/ContentTree.d.ts +9 -2
  42. package/dist/editor/ContentTree.js +16 -4
  43. package/dist/editor/ContentTree.js.map +1 -1
  44. package/dist/editor/ContextMenu.js +6 -2
  45. package/dist/editor/ContextMenu.js.map +1 -1
  46. package/dist/editor/EditorWarning.js +1 -1
  47. package/dist/editor/EditorWarning.js.map +1 -1
  48. package/dist/editor/FieldHistory.js +8 -5
  49. package/dist/editor/FieldHistory.js.map +1 -1
  50. package/dist/editor/FieldListField.js +4 -3
  51. package/dist/editor/FieldListField.js.map +1 -1
  52. package/dist/editor/GlobalMenuBar.js +5 -2
  53. package/dist/editor/GlobalMenuBar.js.map +1 -1
  54. package/dist/editor/MobileLayout.js +4 -1
  55. package/dist/editor/MobileLayout.js.map +1 -1
  56. package/dist/editor/ScrollingContentTree.d.ts +2 -1
  57. package/dist/editor/ScrollingContentTree.js +2 -2
  58. package/dist/editor/ScrollingContentTree.js.map +1 -1
  59. package/dist/editor/Titlebar.d.ts +2 -1
  60. package/dist/editor/Titlebar.js +4 -9
  61. package/dist/editor/Titlebar.js.map +1 -1
  62. package/dist/editor/WorkspaceTitleSwitcher.d.ts +2 -1
  63. package/dist/editor/WorkspaceTitleSwitcher.js +4 -3
  64. package/dist/editor/WorkspaceTitleSwitcher.js.map +1 -1
  65. package/dist/editor/ai/AgentProfileSelector.js +3 -3
  66. package/dist/editor/ai/AgentProfileSelector.js.map +1 -1
  67. package/dist/editor/ai/Agents.js +15 -4
  68. package/dist/editor/ai/Agents.js.map +1 -1
  69. package/dist/editor/ai/ContentInspectorPopover.js +2 -1
  70. package/dist/editor/ai/ContentInspectorPopover.js.map +1 -1
  71. package/dist/editor/ai/InlineAiTrigger.js +5 -1
  72. package/dist/editor/ai/InlineAiTrigger.js.map +1 -1
  73. package/dist/editor/ai/agentActivitySummary.js +17 -9
  74. package/dist/editor/ai/agentActivitySummary.js.map +1 -1
  75. package/dist/editor/ai/dialogs/capturePageScreenshot.d.ts +18 -1
  76. package/dist/editor/ai/dialogs/capturePageScreenshot.js +60 -13
  77. package/dist/editor/ai/dialogs/capturePageScreenshot.js.map +1 -1
  78. package/dist/editor/ai/terminal/components/AgentDocumentList.js +6 -3
  79. package/dist/editor/ai/terminal/components/AgentDocumentList.js.map +1 -1
  80. package/dist/editor/ai/terminal/components/AgentFullPromptControls.d.ts +2 -1
  81. package/dist/editor/ai/terminal/components/AgentFullPromptControls.js +9 -6
  82. package/dist/editor/ai/terminal/components/AgentFullPromptControls.js.map +1 -1
  83. package/dist/editor/ai/terminal/components/AgentModeSelector.js +8 -7
  84. package/dist/editor/ai/terminal/components/AgentModeSelector.js.map +1 -1
  85. package/dist/editor/ai/terminal/components/AgentPromptTrayPopovers.js +4 -1
  86. package/dist/editor/ai/terminal/components/AgentPromptTrayPopovers.js.map +1 -1
  87. package/dist/editor/ai/terminal/components/AgentSummaryPromptActions.d.ts +2 -1
  88. package/dist/editor/ai/terminal/components/AgentSummaryPromptActions.js +7 -2
  89. package/dist/editor/ai/terminal/components/AgentSummaryPromptActions.js.map +1 -1
  90. package/dist/editor/ai/terminal/components/AgentTerminalSummaryLayout.d.ts +2 -1
  91. package/dist/editor/ai/terminal/components/AgentTerminalSummaryLayout.js +2 -2
  92. package/dist/editor/ai/terminal/components/AgentTerminalSummaryLayout.js.map +1 -1
  93. package/dist/editor/ai/terminal/components/ContextInfoBar.js +35 -8
  94. package/dist/editor/ai/terminal/components/ContextInfoBar.js.map +1 -1
  95. package/dist/editor/ai/terminal/components/EditOperationsPanel.js +3 -3
  96. package/dist/editor/ai/terminal/components/EditOperationsPanel.js.map +1 -1
  97. package/dist/editor/ai/terminal/components/UserMessage.js +4 -4
  98. package/dist/editor/ai/terminal/components/UserMessage.js.map +1 -1
  99. package/dist/editor/ai/terminal/projectTemplateContext.d.ts +11 -0
  100. package/dist/editor/ai/terminal/projectTemplateContext.js +64 -0
  101. package/dist/editor/ai/terminal/projectTemplateContext.js.map +1 -0
  102. package/dist/editor/ai/terminal/useAgentLoadPipeline.js +1 -0
  103. package/dist/editor/ai/terminal/useAgentLoadPipeline.js.map +1 -1
  104. package/dist/editor/ai/terminal/useAgentLoader.d.ts +1 -0
  105. package/dist/editor/ai/terminal/useAgentLoader.js +14 -2
  106. package/dist/editor/ai/terminal/useAgentLoader.js.map +1 -1
  107. package/dist/editor/ai/terminal/useAgentSettingsData.js +1 -0
  108. package/dist/editor/ai/terminal/useAgentSettingsData.js.map +1 -1
  109. package/dist/editor/ai/terminal/useAgentSubmitHandlers.d.ts +1 -0
  110. package/dist/editor/ai/terminal/useAgentSubmitHandlers.js +19 -1
  111. package/dist/editor/ai/terminal/useAgentSubmitHandlers.js.map +1 -1
  112. package/dist/editor/ai/terminal/useAgentTerminalController.js +4 -1
  113. package/dist/editor/ai/terminal/useAgentTerminalController.js.map +1 -1
  114. package/dist/editor/ai/useInlineAiPosition.d.ts +2 -1
  115. package/dist/editor/ai/useInlineAiPosition.js +10 -3
  116. package/dist/editor/ai/useInlineAiPosition.js.map +1 -1
  117. package/dist/editor/bridge/protocol.d.ts +35 -1
  118. package/dist/editor/bridge/protocol.js +4 -1
  119. package/dist/editor/bridge/protocol.js.map +1 -1
  120. package/dist/editor/client/EditorShell.js +47 -33
  121. package/dist/editor/client/EditorShell.js.map +1 -1
  122. package/dist/editor/client/editContext.d.ts +3 -4
  123. package/dist/editor/client/errorToast.d.ts +12 -0
  124. package/dist/editor/client/errorToast.js +67 -0
  125. package/dist/editor/client/errorToast.js.map +1 -0
  126. package/dist/editor/client/helpers.d.ts +2 -4
  127. package/dist/editor/client/helpers.js +3 -2
  128. package/dist/editor/client/helpers.js.map +1 -1
  129. package/dist/editor/client/hooks/useSocketMessageHandler.js +5 -3
  130. package/dist/editor/client/hooks/useSocketMessageHandler.js.map +1 -1
  131. package/dist/editor/client/operations.d.ts +2 -4
  132. package/dist/editor/client/operations.js +11 -2
  133. package/dist/editor/client/operations.js.map +1 -1
  134. package/dist/editor/client/pageModelBuilder.d.ts +1 -0
  135. package/dist/editor/client/pageModelBuilder.js +9 -2
  136. package/dist/editor/client/pageModelBuilder.js.map +1 -1
  137. package/dist/editor/client/ui/FullscreenControls.d.ts +0 -1
  138. package/dist/editor/client/ui/FullscreenControls.js +4 -17
  139. package/dist/editor/client/ui/FullscreenControls.js.map +1 -1
  140. package/dist/editor/commands/componentCommands.d.ts +1 -0
  141. package/dist/editor/commands/componentCommands.js +139 -2
  142. package/dist/editor/commands/componentCommands.js.map +1 -1
  143. package/dist/editor/content-tree/TreeSettingsMenu.js +1 -1
  144. package/dist/editor/content-tree/TreeSettingsMenu.js.map +1 -1
  145. package/dist/editor/field-types/DateFieldEditor.js +1 -1
  146. package/dist/editor/field-types/DateFieldEditor.js.map +1 -1
  147. package/dist/editor/field-types/DateTimeFieldEditor.js +1 -1
  148. package/dist/editor/field-types/DateTimeFieldEditor.js.map +1 -1
  149. package/dist/editor/field-types/useTextCompletion.js +12 -43
  150. package/dist/editor/field-types/useTextCompletion.js.map +1 -1
  151. package/dist/editor/fieldTypeConfiguration.d.ts +2 -0
  152. package/dist/editor/fieldTypeConfiguration.js +7 -0
  153. package/dist/editor/fieldTypeConfiguration.js.map +1 -0
  154. package/dist/editor/menubar/PageSelector.js +8 -1
  155. package/dist/editor/menubar/PageSelector.js.map +1 -1
  156. package/dist/editor/menubar/toolbar-sections/DeviceSwitchToolbar.d.ts +7 -1
  157. package/dist/editor/menubar/toolbar-sections/DeviceSwitchToolbar.js +22 -14
  158. package/dist/editor/menubar/toolbar-sections/DeviceSwitchToolbar.js.map +1 -1
  159. package/dist/editor/page-editor-chrome/BridgeInlineFormatOverlay.js +7 -1
  160. package/dist/editor/page-editor-chrome/BridgeInlineFormatOverlay.js.map +1 -1
  161. package/dist/editor/page-editor-chrome/DragInsertionOverlay.js +53 -19
  162. package/dist/editor/page-editor-chrome/DragInsertionOverlay.js.map +1 -1
  163. package/dist/editor/page-editor-chrome/FrameMenu.js +11 -3
  164. package/dist/editor/page-editor-chrome/FrameMenu.js.map +1 -1
  165. package/dist/editor/page-editor-chrome/InsertComponentMenu.js +1 -1
  166. package/dist/editor/page-editor-chrome/InsertComponentMenu.js.map +1 -1
  167. package/dist/editor/page-editor-chrome/PlaceholderDropZone.js +4 -3
  168. package/dist/editor/page-editor-chrome/PlaceholderDropZone.js.map +1 -1
  169. package/dist/editor/page-editor-chrome/bridgeInlineFormatToolbarLayout.d.ts +2 -1
  170. package/dist/editor/page-editor-chrome/bridgeInlineFormatToolbarLayout.js +2 -0
  171. package/dist/editor/page-editor-chrome/bridgeInlineFormatToolbarLayout.js.map +1 -1
  172. package/dist/editor/page-editor-chrome/insertTargetLabel.d.ts +1 -0
  173. package/dist/editor/page-editor-chrome/insertTargetLabel.js +14 -1
  174. package/dist/editor/page-editor-chrome/insertTargetLabel.js.map +1 -1
  175. package/dist/editor/page-editor-chrome/overlay/placeholderZones.js +13 -3
  176. package/dist/editor/page-editor-chrome/overlay/placeholderZones.js.map +1 -1
  177. package/dist/editor/page-editor-chrome/useComponentDragHandle.js +11 -5
  178. package/dist/editor/page-editor-chrome/useComponentDragHandle.js.map +1 -1
  179. package/dist/editor/page-viewer/PageViewer.js +5 -4
  180. package/dist/editor/page-viewer/PageViewer.js.map +1 -1
  181. package/dist/editor/page-viewer/PageViewerFrame.js +342 -5
  182. package/dist/editor/page-viewer/PageViewerFrame.js.map +1 -1
  183. package/dist/editor/page-viewer/RenderingParametersSection.js +1 -1
  184. package/dist/editor/page-viewer/RenderingParametersSection.js.map +1 -1
  185. package/dist/editor/page-viewer/bridgeFieldPatch.d.ts +3 -1
  186. package/dist/editor/page-viewer/bridgeFieldPatch.js +26 -2
  187. package/dist/editor/page-viewer/bridgeFieldPatch.js.map +1 -1
  188. package/dist/editor/page-viewer/pageViewContext.d.ts +4 -1
  189. package/dist/editor/page-viewer/pageViewContext.js +4 -1
  190. package/dist/editor/page-viewer/pageViewContext.js.map +1 -1
  191. package/dist/editor/page-viewer/parentBridgeInjection.d.ts +23 -0
  192. package/dist/editor/page-viewer/parentBridgeInjection.js +251 -0
  193. package/dist/editor/page-viewer/parentBridgeInjection.js.map +1 -0
  194. package/dist/editor/page-viewer/renderUrl.js +4 -2
  195. package/dist/editor/page-viewer/renderUrl.js.map +1 -1
  196. package/dist/editor/pageModel.d.ts +1 -0
  197. package/dist/editor/reviews/DecisionsMatrix.js +1 -1
  198. package/dist/editor/reviews/DecisionsMatrix.js.map +1 -1
  199. package/dist/editor/reviews/MultiReviewManager.js +3 -22
  200. package/dist/editor/reviews/MultiReviewManager.js.map +1 -1
  201. package/dist/editor/reviews/openCommentsFeedback.js +2 -0
  202. package/dist/editor/reviews/openCommentsFeedback.js.map +1 -1
  203. package/dist/editor/services/agentService.js +6 -2
  204. package/dist/editor/services/agentService.js.map +1 -1
  205. package/dist/editor/services/editService.d.ts +15 -0
  206. package/dist/editor/services/editService.js +3 -0
  207. package/dist/editor/services/editService.js.map +1 -1
  208. package/dist/editor/services/textCompletionService.d.ts +14 -0
  209. package/dist/editor/services/textCompletionService.js +45 -0
  210. package/dist/editor/services/textCompletionService.js.map +1 -0
  211. package/dist/editor/settings/About.js +40 -263
  212. package/dist/editor/settings/About.js.map +1 -1
  213. package/dist/editor/settings/SettingsBreadcrumb.js +8 -1
  214. package/dist/editor/settings/SettingsBreadcrumb.js.map +1 -1
  215. package/dist/editor/settings/SettingsHeaderActionsContext.d.ts +4 -0
  216. package/dist/editor/settings/SettingsHeaderActionsContext.js.map +1 -1
  217. package/dist/editor/settings/SettingsTitlebar.d.ts +1 -0
  218. package/dist/editor/settings/SettingsTitlebar.js +18 -0
  219. package/dist/editor/settings/SettingsTitlebar.js.map +1 -0
  220. package/dist/editor/settings/SettingsView.js +64 -18
  221. package/dist/editor/settings/SettingsView.js.map +1 -1
  222. package/dist/editor/settings/panels/AgentToolsPanel.js +3 -7
  223. package/dist/editor/settings/panels/AgentToolsPanel.js.map +1 -1
  224. package/dist/editor/settings/panels/AgentsPanel.js +2 -3
  225. package/dist/editor/settings/panels/AgentsPanel.js.map +1 -1
  226. package/dist/editor/settings/panels/ClusterInstancesPanel.js +2 -3
  227. package/dist/editor/settings/panels/ClusterInstancesPanel.js.map +1 -1
  228. package/dist/editor/settings/panels/FieldTypeSerializersPanel.js +2 -4
  229. package/dist/editor/settings/panels/FieldTypeSerializersPanel.js.map +1 -1
  230. package/dist/editor/settings/panels/JavaScriptToolsPanel.js +2 -3
  231. package/dist/editor/settings/panels/JavaScriptToolsPanel.js.map +1 -1
  232. package/dist/editor/settings/panels/McpToolsPanel.js +3 -4
  233. package/dist/editor/settings/panels/McpToolsPanel.js.map +1 -1
  234. package/dist/editor/settings/panels/ModelsPanel.js +4 -3
  235. package/dist/editor/settings/panels/ModelsPanel.js.map +1 -1
  236. package/dist/editor/settings/panels/ProjectTemplateAgentPanel.d.ts +8 -1
  237. package/dist/editor/settings/panels/ProjectTemplateAgentPanel.js +75 -9
  238. package/dist/editor/settings/panels/ProjectTemplateAgentPanel.js.map +1 -1
  239. package/dist/editor/settings/panels/ProjectTemplateSelectorList.js +1 -1
  240. package/dist/editor/settings/panels/ProjectTemplateSelectorList.js.map +1 -1
  241. package/dist/editor/settings/panels/ProjectTemplatesPanel.js +516 -52
  242. package/dist/editor/settings/panels/ProjectTemplatesPanel.js.map +1 -1
  243. package/dist/editor/settings/panels/ProvidersPanel.js +1 -1
  244. package/dist/editor/settings/panels/ProvidersPanel.js.map +1 -1
  245. package/dist/editor/settings/settingsNavigationStore.d.ts +12 -0
  246. package/dist/editor/settings/settingsNavigationStore.js +32 -0
  247. package/dist/editor/settings/settingsNavigationStore.js.map +1 -0
  248. package/dist/editor/setup-wizard/steps/LicenseActivationStep.d.ts +3 -1
  249. package/dist/editor/setup-wizard/steps/LicenseActivationStep.js +9 -5
  250. package/dist/editor/setup-wizard/steps/LicenseActivationStep.js.map +1 -1
  251. package/dist/editor/setup-wizard/steps/LicenseEmailStep.d.ts +2 -1
  252. package/dist/editor/setup-wizard/steps/LicenseEmailStep.js +6 -3
  253. package/dist/editor/setup-wizard/steps/LicenseEmailStep.js.map +1 -1
  254. package/dist/editor/setup-wizard/steps/ProviderStep.js +6 -2
  255. package/dist/editor/setup-wizard/steps/ProviderStep.js.map +1 -1
  256. package/dist/editor/sidebar/ComponentPalette.js +10 -4
  257. package/dist/editor/sidebar/ComponentPalette.js.map +1 -1
  258. package/dist/editor/sidebar/ComponentTree.js +12 -12
  259. package/dist/editor/sidebar/ComponentTree.js.map +1 -1
  260. package/dist/editor/sidebar/ContentTreePanel.js +1 -1
  261. package/dist/editor/sidebar/ContentTreePanel.js.map +1 -1
  262. package/dist/editor/sidebar/SidebarPanel.js +1 -1
  263. package/dist/editor/sidebar/SidebarPanel.js.map +1 -1
  264. package/dist/editor/sidebar/WorkspaceRailMobile.d.ts +0 -1
  265. package/dist/editor/sidebar/WorkspaceRailMobile.js +4 -16
  266. package/dist/editor/sidebar/WorkspaceRailMobile.js.map +1 -1
  267. package/dist/editor/ui/ComponentThumbnailDialog.d.ts +14 -0
  268. package/dist/editor/ui/ComponentThumbnailDialog.js +75 -0
  269. package/dist/editor/ui/ComponentThumbnailDialog.js.map +1 -0
  270. package/dist/editor/ui/ItemCollectionEditor.d.ts +6 -2
  271. package/dist/editor/ui/ItemCollectionEditor.js +163 -84
  272. package/dist/editor/ui/ItemCollectionEditor.js.map +1 -1
  273. package/dist/editor/ui/PerfectTree.d.ts +5 -1
  274. package/dist/editor/ui/PerfectTree.js +10 -6
  275. package/dist/editor/ui/PerfectTree.js.map +1 -1
  276. package/dist/editor/ui/PublishRestrictionsDialog.js +77 -9
  277. package/dist/editor/ui/PublishRestrictionsDialog.js.map +1 -1
  278. package/dist/editor/ui/SimpleIconButton.js +1 -1
  279. package/dist/editor/ui/Splitter.d.ts +3 -0
  280. package/dist/editor/ui/Splitter.js +30 -16
  281. package/dist/editor/ui/Splitter.js.map +1 -1
  282. package/dist/editor/ui/TreeListSelector.d.ts +6 -2
  283. package/dist/editor/ui/TreeListSelector.js +2 -2
  284. package/dist/editor/ui/TreeListSelector.js.map +1 -1
  285. package/dist/editor/utils/itemutils.js +2 -0
  286. package/dist/editor/utils/itemutils.js.map +1 -1
  287. package/dist/editor/views/ItemEditorPane.js +1 -1
  288. package/dist/editor/views/ItemEditorPane.js.map +1 -1
  289. package/dist/index.d.ts +9 -2
  290. package/dist/index.js +6 -2
  291. package/dist/index.js.map +1 -1
  292. package/dist/revision.d.ts +2 -2
  293. package/dist/revision.js +2 -2
  294. package/dist/task-board/TaskBoardWorkspace.js +73 -5
  295. package/dist/task-board/TaskBoardWorkspace.js.map +1 -1
  296. package/dist/task-board/components/CreateProjectDialog.d.ts +0 -1
  297. package/dist/task-board/components/CreateProjectDialog.js +1 -4
  298. package/dist/task-board/components/CreateProjectDialog.js.map +1 -1
  299. package/dist/task-board/components/GoalDialog.d.ts +9 -0
  300. package/dist/task-board/components/GoalDialog.js +149 -0
  301. package/dist/task-board/components/GoalDialog.js.map +1 -0
  302. package/dist/task-board/components/ProjectDashboard.d.ts +10 -0
  303. package/dist/task-board/components/ProjectDashboard.js +5 -4
  304. package/dist/task-board/components/ProjectDashboard.js.map +1 -1
  305. package/dist/task-board/components/ProjectGoalsPanel.d.ts +16 -0
  306. package/dist/task-board/components/ProjectGoalsPanel.js +310 -0
  307. package/dist/task-board/components/ProjectGoalsPanel.js.map +1 -0
  308. package/dist/task-board/components/ProjectPropertiesPanel.js +6 -4
  309. package/dist/task-board/components/ProjectPropertiesPanel.js.map +1 -1
  310. package/dist/task-board/components/TaskAssigneeBadge.d.ts +1 -1
  311. package/dist/task-board/components/TaskAssigneeBadge.js +1 -1
  312. package/dist/task-board/components/TaskAssigneeBadge.js.map +1 -1
  313. package/dist/task-board/components/TaskAssigneePicker.js +1 -1
  314. package/dist/task-board/components/TaskAssigneePicker.js.map +1 -1
  315. package/dist/task-board/components/TaskAttachmentDropZone.d.ts +1 -0
  316. package/dist/task-board/components/TaskAttachmentDropZone.js +5 -3
  317. package/dist/task-board/components/TaskAttachmentDropZone.js.map +1 -1
  318. package/dist/task-board/components/TaskAttachmentsSection.js +8 -1
  319. package/dist/task-board/components/TaskAttachmentsSection.js.map +1 -1
  320. package/dist/task-board/components/TaskRow.js +1 -1
  321. package/dist/task-board/components/TaskRow.js.map +1 -1
  322. package/dist/task-board/components/WizardCommunicationCenter.js +1 -10
  323. package/dist/task-board/components/WizardCommunicationCenter.js.map +1 -1
  324. package/dist/task-board/services/goalService.d.ts +65 -0
  325. package/dist/task-board/services/goalService.js +37 -0
  326. package/dist/task-board/services/goalService.js.map +1 -0
  327. package/dist/task-board/types.d.ts +68 -3
  328. package/dist/task-board/views/DependencyGraphView.js +121 -31
  329. package/dist/task-board/views/DependencyGraphView.js.map +1 -1
  330. package/package.json +2 -2
  331. package/dist/editor/sidebar/MobileWorkspacePopover.d.ts +0 -16
  332. package/dist/editor/sidebar/MobileWorkspacePopover.js +0 -35
  333. package/dist/editor/sidebar/MobileWorkspacePopover.js.map +0 -1
@@ -1,10 +1,10 @@
1
1
  import { jsx as _jsx, jsxs as _jsxs, Fragment as _Fragment } from "react/jsx-runtime";
2
- import { ChevronLeft, CopyPlus, CornerDownRight, GitBranch, LayoutTemplate, Link2, Plus, RefreshCw, Settings2, Shield, X, } from "lucide-react";
2
+ import { ChevronLeft, CopyPlus, CornerDownRight, GitBranch, LayoutTemplate, Link2, PanelRightOpen, Plus, RefreshCw, Settings2, Shield, Trash2, X, } from "lucide-react";
3
3
  import { useCallback, useEffect, useMemo, useRef, useState, Suspense, lazy, } from "react";
4
4
  import { toast } from "sonner";
5
5
  import { Badge } from "../../../components/ui/badge";
6
6
  import { Button } from "../../../components/ui/button";
7
- import { SettingsCard as Card } from "../SettingsCard";
7
+ import { CloseButton } from "../../../components/ui/close-button";
8
8
  import { DeleteIcon } from "../../../components/ui/delete-icon";
9
9
  import { Dialog, DialogContent, DialogFooter, } from "../../../components/ui/dialog";
10
10
  import { Input } from "../../../components/ui/input";
@@ -22,7 +22,7 @@ const DependencyGraphView = lazy(() => import("../../../task-board/views/Depende
22
22
  })));
23
23
  import { useEditContext } from "../../client/editContext";
24
24
  import { useSearchParams } from "../../client/navigation";
25
- import { updateAgentContext } from "../../services/agentService";
25
+ import { updateAgentContext, } from "../../services/agentService";
26
26
  import { getAiProfilesErrorMessage, loadAiProfiles, } from "../../services/aiService";
27
27
  import { localStorageService } from "../../services/localStorageService";
28
28
  import { ItemNameDialog, } from "../../ui/ItemNameDialogNew";
@@ -94,6 +94,9 @@ function normalizeTaskTemplate(task) {
94
94
  const rawAssigneeId = task.assigneeId?.trim() || null;
95
95
  const rawAgentProfileId = task.agentProfileId?.trim() || null;
96
96
  const rawParentTaskId = task.parentTaskId?.trim() || null;
97
+ const dependencyIds = Array.from(new Set((task.dependencyIds ?? [])
98
+ .map((dependencyId) => dependencyId?.trim())
99
+ .filter((dependencyId) => !!dependencyId)));
97
100
  const disabled = task.disabled === true;
98
101
  const taskType = String(task.taskType ?? "").toLowerCase() === "decisionpoint"
99
102
  ? "DecisionPoint"
@@ -115,6 +118,7 @@ function normalizeTaskTemplate(task) {
115
118
  assigneeId: canonicalAgentId,
116
119
  agentProfileId: canonicalAgentId,
117
120
  parentTaskId: rawParentTaskId,
121
+ dependencyIds,
118
122
  };
119
123
  }
120
124
  if (assigneeType === "user" || assigneeType === "Role") {
@@ -127,6 +131,7 @@ function normalizeTaskTemplate(task) {
127
131
  assigneeId: rawAssigneeId,
128
132
  agentProfileId: null,
129
133
  parentTaskId: rawParentTaskId,
134
+ dependencyIds,
130
135
  };
131
136
  }
132
137
  return {
@@ -138,6 +143,7 @@ function normalizeTaskTemplate(task) {
138
143
  assigneeId: rawAssigneeId,
139
144
  agentProfileId: null,
140
145
  parentTaskId: rawParentTaskId,
146
+ dependencyIds,
141
147
  };
142
148
  }
143
149
  function normalizeGraphOrientation(orientation) {
@@ -147,7 +153,6 @@ function normalizeProjectTemplate(template) {
147
153
  return {
148
154
  ...template,
149
155
  hideFromCreateDialog: template.hideFromCreateDialog === true,
150
- openInWizardMode: template.openInWizardMode === true,
151
156
  graphLayout: template.graphLayout
152
157
  ? {
153
158
  ...template.graphLayout,
@@ -155,6 +160,10 @@ function normalizeProjectTemplate(template) {
155
160
  }
156
161
  : null,
157
162
  taskTemplates: (template.taskTemplates ?? []).map(normalizeTaskTemplate),
163
+ goalTemplates: (template.goalTemplates ?? []).map((goal) => ({
164
+ ...goal,
165
+ disabled: goal.disabled === true,
166
+ })),
158
167
  };
159
168
  }
160
169
  function createEmptyTemplate() {
@@ -164,11 +173,11 @@ function createEmptyTemplate() {
164
173
  description: "",
165
174
  disabled: false,
166
175
  hideFromCreateDialog: false,
167
- openInWizardMode: false,
168
176
  isSystem: false,
169
177
  defaultCostLimit: null,
170
178
  graphLayout: null,
171
179
  taskTemplates: [],
180
+ goalTemplates: [],
172
181
  };
173
182
  }
174
183
  function createEmptyTaskTemplate(taskCount, title) {
@@ -188,6 +197,17 @@ function createEmptyTaskTemplate(taskCount, title) {
188
197
  dependencyIds: [],
189
198
  };
190
199
  }
200
+ function createEmptyGoalDefinition(goalCount, title) {
201
+ return {
202
+ id: crypto.randomUUID(),
203
+ title: title?.trim() || `Goal ${goalCount + 1}`,
204
+ description: "",
205
+ disabled: false,
206
+ sortOrder: goalCount * 100,
207
+ defaultScopeJson: null,
208
+ dataShape: null,
209
+ };
210
+ }
191
211
  function sortTemplates(templates) {
192
212
  return [...templates].sort((left, right) => left.name.localeCompare(right.name, undefined, { sensitivity: "base" }));
193
213
  }
@@ -195,10 +215,9 @@ function buildUpsertTemplateRequest(template) {
195
215
  return {
196
216
  projectTemplateId: template.id,
197
217
  name: template.name.trim(),
198
- description: template.description?.trim() || null,
218
+ description: template.description || null,
199
219
  disabled: template.disabled === true,
200
220
  hideFromCreateDialog: template.hideFromCreateDialog === true,
201
- openInWizardMode: template.openInWizardMode === true,
202
221
  defaultCostLimit: template.defaultCostLimit == null ||
203
222
  Number.isNaN(template.defaultCostLimit)
204
223
  ? null
@@ -216,7 +235,7 @@ function buildUpsertTemplateRequest(template) {
216
235
  return {
217
236
  ...normalizedTask,
218
237
  title: normalizedTask.title.trim(),
219
- description: normalizedTask.description?.trim() || null,
238
+ description: normalizedTask.description || null,
220
239
  disabled: normalizedTask.disabled === true,
221
240
  taskType: normalizedTask.taskType ?? "Task",
222
241
  decisionMode: normalizedTask.taskType === "DecisionPoint"
@@ -231,10 +250,35 @@ function buildUpsertTemplateRequest(template) {
231
250
  dependencyIds: Array.from(new Set(normalizedTask.dependencyIds || [])),
232
251
  };
233
252
  }),
253
+ goalTemplates: (template.goalTemplates ?? []).map((goal, index) => ({
254
+ id: goal.id,
255
+ title: goal.title.trim(),
256
+ description: goal.description || null,
257
+ disabled: goal.disabled === true,
258
+ sortOrder: goal.sortOrder || index * 100,
259
+ defaultScopeJson: goal.defaultScopeJson?.trim() || null,
260
+ dataShape: goal.dataShape?.trim() || null,
261
+ })),
234
262
  };
235
263
  }
236
264
  function mergeTemplateResponseWithRequest(serverTemplate, request) {
237
265
  const requestedTaskById = new Map((request.taskTemplates ?? []).map((task) => [task.id, task]));
266
+ const requestedGoalById = new Map((request.goalTemplates ?? []).map((goal) => [goal.id, goal]));
267
+ // Server re-reads goals after BeginEdit/EndEdit; if a just-written goal is
268
+ // briefly missing from the response, keep it from the request so the next
269
+ // autosave does not delete it.
270
+ const serverGoals = serverTemplate.goalTemplates ?? [];
271
+ const serverGoalIds = new Set(serverGoals.map((goal) => goal.id));
272
+ const mergedGoalTemplates = [
273
+ ...serverGoals.map((goal) => {
274
+ const requested = requestedGoalById.get(goal.id);
275
+ return {
276
+ ...goal,
277
+ description: requested?.description ?? goal.description,
278
+ };
279
+ }),
280
+ ...(request.goalTemplates ?? []).filter((goal) => !serverGoalIds.has(goal.id)),
281
+ ];
238
282
  const mergedGraphLayout = request.graphLayout === undefined
239
283
  ? serverTemplate.graphLayout
240
284
  : request.graphLayout === null
@@ -247,7 +291,9 @@ function mergeTemplateResponseWithRequest(serverTemplate, request) {
247
291
  };
248
292
  return normalizeProjectTemplate({
249
293
  ...serverTemplate,
294
+ description: request.description ?? serverTemplate.description,
250
295
  graphLayout: mergedGraphLayout,
296
+ goalTemplates: mergedGoalTemplates,
251
297
  taskTemplates: (serverTemplate.taskTemplates ?? []).map((task) => {
252
298
  const requested = requestedTaskById.get(task.id);
253
299
  // Sitecore item-cache reads after BeginEdit/EndEdit can briefly omit
@@ -258,6 +304,7 @@ function mergeTemplateResponseWithRequest(serverTemplate, request) {
258
304
  const requestedDeps = requested?.dependencyIds ?? [];
259
305
  return {
260
306
  ...task,
307
+ description: requested?.description ?? task.description,
261
308
  parentTaskId: task.parentTaskId ?? requested?.parentTaskId ?? null,
262
309
  dependencyIds: serverDeps.length === 0 && requestedDeps.length > 0
263
310
  ? Array.from(new Set(requestedDeps))
@@ -266,6 +313,61 @@ function mergeTemplateResponseWithRequest(serverTemplate, request) {
266
313
  }),
267
314
  });
268
315
  }
316
+ function getActiveDescriptionDraftField(selectedTaskId, selectedGoalId) {
317
+ if (typeof document === "undefined") {
318
+ return null;
319
+ }
320
+ const activeElement = document.activeElement;
321
+ if (!(activeElement instanceof HTMLElement)) {
322
+ return null;
323
+ }
324
+ switch (activeElement.dataset.testid) {
325
+ case "project-template-description-input":
326
+ return { kind: "template" };
327
+ case "project-template-task-description-input":
328
+ return { kind: "task", id: selectedTaskId };
329
+ case "project-template-goal-description-input":
330
+ return { kind: "goal", id: selectedGoalId };
331
+ default:
332
+ return null;
333
+ }
334
+ }
335
+ function preserveActiveDescriptionDraft(template, draft, activeField) {
336
+ if (!draft || template.id !== draft.id || !activeField) {
337
+ return template;
338
+ }
339
+ if (activeField.kind === "template") {
340
+ return {
341
+ ...template,
342
+ description: draft.description,
343
+ };
344
+ }
345
+ if (activeField.kind === "task" && activeField.id) {
346
+ const draftTask = draft.taskTemplates.find((task) => task.id === activeField.id);
347
+ if (!draftTask) {
348
+ return template;
349
+ }
350
+ return {
351
+ ...template,
352
+ taskTemplates: template.taskTemplates.map((task) => task.id === activeField.id
353
+ ? { ...task, description: draftTask.description }
354
+ : task),
355
+ };
356
+ }
357
+ if (activeField.kind === "goal" && activeField.id) {
358
+ const draftGoal = (draft.goalTemplates ?? []).find((goal) => goal.id === activeField.id);
359
+ if (!draftGoal) {
360
+ return template;
361
+ }
362
+ return {
363
+ ...template,
364
+ goalTemplates: (template.goalTemplates ?? []).map((goal) => goal.id === activeField.id
365
+ ? { ...goal, description: draftGoal.description }
366
+ : goal),
367
+ };
368
+ }
369
+ return template;
370
+ }
269
371
  function isValidGuid(value) {
270
372
  return (!!value &&
271
373
  /^[0-9a-f]{8}-[0-9a-f]{4}-[1-5][0-9a-f]{3}-[89ab][0-9a-f]{3}-[0-9a-f]{12}$/i.test(value));
@@ -362,12 +464,28 @@ function canAddTemplateDependency(template, taskId, dependencyId) {
362
464
  }
363
465
  return task.parentTaskId !== dependencyId;
364
466
  }
365
- function buildProjectTemplateAgentContext(template, selectedTaskTemplateId) {
467
+ function buildProjectTemplateAgentContext(template, selectedTaskTemplateId, selectedGoalTemplateId = null) {
366
468
  const dependencyCount = template.taskTemplates.reduce((count, task) => count + (task.dependencyIds?.length ?? 0), 0);
367
469
  const agentAssignedTaskCount = template.taskTemplates.filter((task) => task.agentProfileId || (task.assigneeType === "Agent" && task.assigneeId)).length;
368
470
  const selectedTask = selectedTaskTemplateId
369
471
  ? (template.taskTemplates.find((task) => task.id === selectedTaskTemplateId) ?? null)
370
472
  : null;
473
+ const goalDefinitions = [...(template.goalTemplates ?? [])]
474
+ .sort((a, b) => (a.sortOrder ?? 0) - (b.sortOrder ?? 0))
475
+ .map((goal) => ({
476
+ id: goal.id,
477
+ title: goal.title?.trim() || "Untitled goal",
478
+ description: goal.description?.trim() || null,
479
+ disabled: goal.disabled === true,
480
+ sortOrder: goal.sortOrder ?? 0,
481
+ defaultScopeJson: goal.defaultScopeJson?.trim() || null,
482
+ dataShape: goal.dataShape?.trim() || null,
483
+ }));
484
+ const selectedGoal = selectedGoalTemplateId
485
+ ? (goalDefinitions.find((goal) => goal.id === selectedGoalTemplateId) ??
486
+ null)
487
+ : null;
488
+ const enabledGoalCount = goalDefinitions.filter((goal) => goal.disabled !== true).length;
371
489
  return {
372
490
  activeWorkspace: "settings",
373
491
  additionalData: {
@@ -383,10 +501,22 @@ function buildProjectTemplateAgentContext(template, selectedTaskTemplateId) {
383
501
  selectedTaskTemplate: selectedTask
384
502
  ? normalizeTaskTemplate(selectedTask)
385
503
  : null,
504
+ selectedGoalTemplateId: selectedGoal ? selectedGoal.id : null,
505
+ selectedGoalTemplateTitle: selectedGoal?.title ?? null,
506
+ selectedGoalTemplate: selectedGoal,
507
+ projectTemplateGoalDefinitions: goalDefinitions,
508
+ projectTemplateGoalSummary: {
509
+ goalCount: goalDefinitions.length,
510
+ enabledGoalCount,
511
+ disabledGoalCount: goalDefinitions.length - enabledGoalCount,
512
+ },
386
513
  projectTemplateSummary: {
387
514
  taskCount: template.taskTemplates.length,
388
515
  dependencyCount,
389
516
  agentAssignedTaskCount,
517
+ goalCount: goalDefinitions.length,
518
+ enabledGoalCount,
519
+ disabledGoalCount: goalDefinitions.length - enabledGoalCount,
390
520
  defaultCostLimit: template.defaultCostLimit ?? null,
391
521
  disabled: template.disabled === true,
392
522
  },
@@ -415,6 +545,10 @@ export function ProjectTemplatesPanel() {
415
545
  const [newTaskTitle, setNewTaskTitle] = useState("");
416
546
  const [newTaskDependencySourceId, setNewTaskDependencySourceId] = useState(null);
417
547
  const [creatingTask, setCreatingTask] = useState(false);
548
+ const [selectedGoalId, setSelectedGoalId] = useState(null);
549
+ const [isCreateGoalDialogOpen, setIsCreateGoalDialogOpen] = useState(false);
550
+ const [newGoalTitle, setNewGoalTitle] = useState("");
551
+ const [creatingGoal, setCreatingGoal] = useState(false);
418
552
  const [isAddChildTaskDialogOpen, setIsAddChildTaskDialogOpen] = useState(false);
419
553
  const [newChildTaskTitle, setNewChildTaskTitle] = useState("");
420
554
  const [creatingChildTask, setCreatingChildTask] = useState(false);
@@ -430,6 +564,12 @@ export function ProjectTemplatesPanel() {
430
564
  const [editingAgentProfile, setEditingAgentProfile] = useState(null);
431
565
  const [isTaskEditorMaximized, setIsTaskEditorMaximized] = useState(false);
432
566
  const [taskEditorOverlayBounds, setTaskEditorOverlayBounds] = useState(null);
567
+ const [settingsMainContentBounds, setSettingsMainContentBounds] = useState(null);
568
+ const [agentPanelBounds, setAgentPanelBounds] = useState(null);
569
+ const [isAgentPanelCollapsed, setIsAgentPanelCollapsed] = useState(() => {
570
+ const stored = localStorageService.getItem(PROJECT_TEMPLATE_SPLITTER_STORAGE_KEY);
571
+ return stored?.lastCollapsed ?? true;
572
+ });
433
573
  const [forceCollapseAgentPanelKey, setForceCollapseAgentPanelKey] = useState(0);
434
574
  const [forceExpandAgentPanelKey, setForceExpandAgentPanelKey] = useState(0);
435
575
  const settingsMainContentRef = useRequiredSettingsMainContentRef();
@@ -442,6 +582,7 @@ export function ProjectTemplatesPanel() {
442
582
  const draftTemplateRef = useRef(null);
443
583
  const selectedTemplateIdRef = useRef(selectedTemplateId);
444
584
  const selectedTaskIdRef = useRef(selectedTaskId);
585
+ const selectedGoalIdRef = useRef(selectedGoalId);
445
586
  const selectedDependencyIdRef = useRef(selectedDependencyId);
446
587
  const isDirtyRef = useRef(isDirty);
447
588
  const savingRef = useRef(saving);
@@ -456,6 +597,7 @@ export function ProjectTemplatesPanel() {
456
597
  };
457
598
  const restoreAgentPanelAfterMaximize = () => {
458
599
  if (agentPanelWasExpandedBeforeMaximizeRef.current === true) {
600
+ setIsAgentPanelCollapsed(false);
459
601
  setForceExpandAgentPanelKey((value) => value + 1);
460
602
  }
461
603
  agentPanelWasExpandedBeforeMaximizeRef.current = null;
@@ -478,11 +620,114 @@ export function ProjectTemplatesPanel() {
478
620
  const agentPanelCollapsed = wasAgentPanelCollapsed();
479
621
  agentPanelWasExpandedBeforeMaximizeRef.current = !agentPanelCollapsed;
480
622
  if (!agentPanelCollapsed) {
623
+ setIsAgentPanelCollapsed(true);
481
624
  setForceCollapseAgentPanelKey((value) => value + 1);
482
625
  }
483
626
  setTaskEditorOverlayBounds(nextBounds);
484
627
  setIsTaskEditorMaximized(true);
485
628
  };
629
+ useEffect(() => {
630
+ const settingsMainContent = settingsMainContentRef.current;
631
+ const updateBounds = () => {
632
+ const nextBounds = measureOverlayBounds(settingsMainContentRef.current);
633
+ if (nextBounds) {
634
+ setSettingsMainContentBounds(nextBounds);
635
+ }
636
+ };
637
+ updateBounds();
638
+ if (typeof window === "undefined") {
639
+ return;
640
+ }
641
+ let frameId = null;
642
+ const scheduleUpdate = () => {
643
+ if (frameId != null) {
644
+ window.cancelAnimationFrame(frameId);
645
+ }
646
+ frameId = window.requestAnimationFrame(() => {
647
+ frameId = null;
648
+ updateBounds();
649
+ });
650
+ };
651
+ const resizeObserver = typeof ResizeObserver !== "undefined" && settingsMainContent
652
+ ? new ResizeObserver(scheduleUpdate)
653
+ : null;
654
+ if (resizeObserver && settingsMainContent) {
655
+ resizeObserver.observe(settingsMainContent);
656
+ }
657
+ window.addEventListener("resize", scheduleUpdate);
658
+ window.addEventListener("scroll", scheduleUpdate, true);
659
+ return () => {
660
+ if (frameId != null) {
661
+ window.cancelAnimationFrame(frameId);
662
+ }
663
+ resizeObserver?.disconnect();
664
+ window.removeEventListener("resize", scheduleUpdate);
665
+ window.removeEventListener("scroll", scheduleUpdate, true);
666
+ };
667
+ }, [settingsMainContentRef]);
668
+ useEffect(() => {
669
+ if (isMobile) {
670
+ setAgentPanelBounds(null);
671
+ return;
672
+ }
673
+ const updateBounds = () => {
674
+ const element = document.querySelector('[data-testid="splitter-panel-project-template-agent"]');
675
+ const nextBounds = measureOverlayBounds(element);
676
+ setAgentPanelBounds((currentBounds) => {
677
+ if (!nextBounds) {
678
+ return currentBounds === null ? currentBounds : null;
679
+ }
680
+ if (currentBounds &&
681
+ Math.abs(currentBounds.top - nextBounds.top) < 0.5 &&
682
+ Math.abs(currentBounds.left - nextBounds.left) < 0.5 &&
683
+ Math.abs(currentBounds.width - nextBounds.width) < 0.5 &&
684
+ Math.abs(currentBounds.height - nextBounds.height) < 0.5) {
685
+ return currentBounds;
686
+ }
687
+ return nextBounds;
688
+ });
689
+ };
690
+ updateBounds();
691
+ if (typeof window === "undefined") {
692
+ return;
693
+ }
694
+ let frameId = null;
695
+ const scheduleUpdate = () => {
696
+ if (frameId != null) {
697
+ window.cancelAnimationFrame(frameId);
698
+ }
699
+ frameId = window.requestAnimationFrame(() => {
700
+ frameId = null;
701
+ updateBounds();
702
+ });
703
+ };
704
+ const settingsMainContent = settingsMainContentRef.current;
705
+ const agentPanelElement = document.querySelector('[data-testid="splitter-panel-project-template-agent"]');
706
+ const resizeObserver = typeof ResizeObserver !== "undefined" && settingsMainContent
707
+ ? new ResizeObserver(scheduleUpdate)
708
+ : null;
709
+ if (resizeObserver && settingsMainContent) {
710
+ resizeObserver.observe(settingsMainContent);
711
+ }
712
+ if (resizeObserver && agentPanelElement) {
713
+ resizeObserver.observe(agentPanelElement);
714
+ }
715
+ window.addEventListener("resize", scheduleUpdate);
716
+ window.addEventListener("scroll", scheduleUpdate, true);
717
+ return () => {
718
+ if (frameId != null) {
719
+ window.cancelAnimationFrame(frameId);
720
+ }
721
+ resizeObserver?.disconnect();
722
+ window.removeEventListener("resize", scheduleUpdate);
723
+ window.removeEventListener("scroll", scheduleUpdate, true);
724
+ };
725
+ }, [
726
+ isAgentPanelCollapsed,
727
+ isMobile,
728
+ selectedTemplateId,
729
+ settingsMainContentRef,
730
+ ]);
486
731
  useEffect(() => {
487
732
  if (!isTaskEditorMaximized) {
488
733
  setTaskEditorOverlayBounds(null);
@@ -623,8 +868,14 @@ export function ProjectTemplatesPanel() {
623
868
  setMobileView("detail");
624
869
  return;
625
870
  }
871
+ setIsAgentPanelCollapsed(true);
626
872
  setForceCollapseAgentPanelKey((value) => value + 1);
627
873
  }, [isMobile]);
874
+ const handleShowTemplateAssistant = useCallback(() => {
875
+ setEditingAgentProfile(null);
876
+ setIsAgentPanelCollapsed(false);
877
+ setForceExpandAgentPanelKey((value) => value + 1);
878
+ }, []);
628
879
  useEffect(() => {
629
880
  if (!isMobile) {
630
881
  setMobileView("detail");
@@ -643,7 +894,8 @@ export function ProjectTemplatesPanel() {
643
894
  if (result.type !== "success") {
644
895
  throw new Error(result.summary || "Failed to load project templates");
645
896
  }
646
- const loadedTemplates = result.data ?? [];
897
+ const activeDescriptionDraftField = getActiveDescriptionDraftField(selectedTaskIdRef.current, selectedGoalIdRef.current);
898
+ const loadedTemplates = (result.data ?? []).map((template) => preserveActiveDescriptionDraft(template, draftTemplateRef.current, activeDescriptionDraftField));
647
899
  setTemplates(loadedTemplates);
648
900
  setState("success");
649
901
  const preferredTemplateExists = !!preferredTemplateId &&
@@ -713,6 +965,9 @@ export function ProjectTemplatesPanel() {
713
965
  }, [aiProfiles]);
714
966
  const selectedTask = useMemo(() => draftTemplate?.taskTemplates.find((task) => task.id === selectedTaskId) ??
715
967
  null, [draftTemplate, selectedTaskId]);
968
+ const templateAgentInitialMetadata = useMemo(() => draftTemplate
969
+ ? buildProjectTemplateAgentContext(draftTemplate, selectedTaskId, selectedGoalId)
970
+ : undefined, [draftTemplate, selectedGoalId, selectedTaskId]);
716
971
  const dependencyTasks = useMemo(() => {
717
972
  if (!draftTemplate || !selectedTask)
718
973
  return [];
@@ -782,9 +1037,9 @@ export function ProjectTemplatesPanel() {
782
1037
  setMobileView("detail");
783
1038
  }
784
1039
  }, [isMobile]);
785
- const syncProjectTemplateAgentContext = useCallback(async (agentId, template, selectedTaskTemplateId) => {
1040
+ const syncProjectTemplateAgentContext = useCallback(async (agentId, template, selectedTaskTemplateId, selectedGoalTemplateId) => {
786
1041
  try {
787
- await updateAgentContext(agentId, buildProjectTemplateAgentContext(template, selectedTaskTemplateId));
1042
+ await updateAgentContext(agentId, buildProjectTemplateAgentContext(template, selectedTaskTemplateId, selectedGoalTemplateId));
788
1043
  }
789
1044
  catch (error) {
790
1045
  setTemplateAgentError(error instanceof Error
@@ -837,8 +1092,9 @@ export function ProjectTemplatesPanel() {
837
1092
  const currentTemplate = draftTemplateRef.current;
838
1093
  if (!currentTemplate || currentTemplate.id !== selectedTemplateId)
839
1094
  return;
840
- void syncProjectTemplateAgentContext(templateAgentId, currentTemplate, selectedTaskId);
1095
+ void syncProjectTemplateAgentContext(templateAgentId, currentTemplate, selectedTaskId, selectedGoalId);
841
1096
  }, [
1097
+ selectedGoalId,
842
1098
  selectedTaskId,
843
1099
  templateAgentId,
844
1100
  templateAgentLoading,
@@ -869,6 +1125,14 @@ export function ProjectTemplatesPanel() {
869
1125
  taskTemplates: currentTemplate.taskTemplates.map((task) => task.id === selectedTaskId ? updater({ ...task }) : task),
870
1126
  }));
871
1127
  }, [applyDraftChange, selectedTaskId]);
1128
+ const updateSelectedGoal = useCallback((updater) => {
1129
+ if (!selectedGoalId)
1130
+ return;
1131
+ applyDraftChange((currentTemplate) => ({
1132
+ ...currentTemplate,
1133
+ goalTemplates: (currentTemplate.goalTemplates ?? []).map((goal) => goal.id === selectedGoalId ? updater({ ...goal }) : goal),
1134
+ }));
1135
+ }, [applyDraftChange, selectedGoalId]);
872
1136
  const handleDuplicateAssignedAgentProfile = useCallback(async () => {
873
1137
  if (!editContext || !selectedAgentProfileId)
874
1138
  return;
@@ -1000,7 +1264,10 @@ export function ProjectTemplatesPanel() {
1000
1264
  }
1001
1265
  if (templateAgentId && savedTemplate.id === selectedTemplateId) {
1002
1266
  const nextSelectedTaskId = getSelectedTaskIdForTemplate(savedTemplate, selectedTaskIdRef.current);
1003
- void syncProjectTemplateAgentContext(templateAgentId, savedTemplate, nextSelectedTaskId);
1267
+ const nextSelectedGoalId = savedTemplate.goalTemplates?.some((goal) => goal.id === selectedGoalId) === true
1268
+ ? selectedGoalId
1269
+ : null;
1270
+ void syncProjectTemplateAgentContext(templateAgentId, savedTemplate, nextSelectedTaskId, nextSelectedGoalId);
1004
1271
  }
1005
1272
  return true;
1006
1273
  }
@@ -1009,7 +1276,12 @@ export function ProjectTemplatesPanel() {
1009
1276
  setSaving(false);
1010
1277
  }
1011
1278
  }
1012
- }, [selectedTemplateId, syncProjectTemplateAgentContext, templateAgentId]);
1279
+ }, [
1280
+ selectedGoalId,
1281
+ selectedTemplateId,
1282
+ syncProjectTemplateAgentContext,
1283
+ templateAgentId,
1284
+ ]);
1013
1285
  const applyDraftChangeAndPersist = useCallback((updater) => {
1014
1286
  let nextTemplate = null;
1015
1287
  let nextSignature = null;
@@ -1134,6 +1406,9 @@ export function ProjectTemplatesPanel() {
1134
1406
  useEffect(() => {
1135
1407
  selectedTaskIdRef.current = selectedTaskId;
1136
1408
  }, [selectedTaskId]);
1409
+ useEffect(() => {
1410
+ selectedGoalIdRef.current = selectedGoalId;
1411
+ }, [selectedGoalId]);
1137
1412
  useEffect(() => {
1138
1413
  selectedDependencyIdRef.current = selectedDependencyId;
1139
1414
  }, [selectedDependencyId]);
@@ -1244,6 +1519,7 @@ export function ProjectTemplatesPanel() {
1244
1519
  setSelectedTemplateId(nextTemplate.id);
1245
1520
  setDraftTemplate(cloneTemplate(nextTemplate));
1246
1521
  setSelectedTaskId(null);
1522
+ setSelectedGoalId(null);
1247
1523
  setIsDirty(true);
1248
1524
  setSaveError(null);
1249
1525
  lastPersistedSignatureRef.current = null;
@@ -1349,7 +1625,7 @@ export function ProjectTemplatesPanel() {
1349
1625
  setTemplateAgentId(result.data.agentId);
1350
1626
  const currentTemplate = draftTemplateRef.current;
1351
1627
  if (currentTemplate?.id === selectedTemplateId) {
1352
- await syncProjectTemplateAgentContext(result.data.agentId, currentTemplate, selectedTaskIdRef.current);
1628
+ await syncProjectTemplateAgentContext(result.data.agentId, currentTemplate, selectedTaskIdRef.current, selectedGoalId);
1353
1629
  }
1354
1630
  }
1355
1631
  catch (error) {
@@ -1362,7 +1638,12 @@ export function ProjectTemplatesPanel() {
1362
1638
  finally {
1363
1639
  setTemplateAgentResetting(false);
1364
1640
  }
1365
- }, [flushPendingSave, selectedTemplateId, syncProjectTemplateAgentContext]);
1641
+ }, [
1642
+ flushPendingSave,
1643
+ selectedGoalId,
1644
+ selectedTemplateId,
1645
+ syncProjectTemplateAgentContext,
1646
+ ]);
1366
1647
  const handleOpenCreateTaskDialog = useCallback(async () => {
1367
1648
  if (!draftTemplate)
1368
1649
  return;
@@ -1450,6 +1731,56 @@ export function ProjectTemplatesPanel() {
1450
1731
  setCreatingTask(false);
1451
1732
  }
1452
1733
  }, [draftTemplate, newTaskDependencySourceId, newTaskTitle, persistTemplate]);
1734
+ const handleConfirmCreateGoal = useCallback(async () => {
1735
+ if (!draftTemplate)
1736
+ return;
1737
+ const trimmedTitle = newGoalTitle.trim();
1738
+ if (!trimmedTitle) {
1739
+ toast.error("Goal title is required");
1740
+ return;
1741
+ }
1742
+ if (!draftTemplate.name.trim()) {
1743
+ const message = "Project template name is required before it can be saved";
1744
+ setSaveError(message);
1745
+ toast.error(message);
1746
+ return;
1747
+ }
1748
+ if (autosaveTimeoutRef.current !== null) {
1749
+ window.clearTimeout(autosaveTimeoutRef.current);
1750
+ autosaveTimeoutRef.current = null;
1751
+ }
1752
+ const nextGoal = createEmptyGoalDefinition((draftTemplate.goalTemplates ?? []).length, trimmedTitle);
1753
+ const nextTemplate = cloneTemplate(draftTemplate);
1754
+ nextTemplate.goalTemplates = [
1755
+ ...(nextTemplate.goalTemplates ?? []),
1756
+ nextGoal,
1757
+ ];
1758
+ const request = buildUpsertTemplateRequest(nextTemplate);
1759
+ const signature = JSON.stringify(request);
1760
+ latestDraftSignatureRef.current = signature;
1761
+ setDraftTemplate(cloneTemplate(nextTemplate));
1762
+ setTemplates((existingTemplates) => sortTemplates([
1763
+ ...existingTemplates.filter((template) => template.id !== nextTemplate.id),
1764
+ cloneTemplate(nextTemplate),
1765
+ ]));
1766
+ setSelectedGoalId(nextGoal.id);
1767
+ setIsDirty(true);
1768
+ setSaveError(null);
1769
+ setCreatingGoal(true);
1770
+ try {
1771
+ const saved = await persistTemplate(request, signature, {
1772
+ showErrorToast: true,
1773
+ });
1774
+ if (saved) {
1775
+ setIsCreateGoalDialogOpen(false);
1776
+ setNewGoalTitle("");
1777
+ toast.success("Goal definition created");
1778
+ }
1779
+ }
1780
+ finally {
1781
+ setCreatingGoal(false);
1782
+ }
1783
+ }, [draftTemplate, newGoalTitle, persistTemplate]);
1453
1784
  const handleOpenAddChildTaskDialog = useCallback(async () => {
1454
1785
  if (!draftTemplate || !selectedTaskId)
1455
1786
  return;
@@ -1486,7 +1817,7 @@ export function ProjectTemplatesPanel() {
1486
1817
  ...existingTemplates.filter((template) => template.id !== nextTemplate.id),
1487
1818
  cloneTemplate(nextTemplate),
1488
1819
  ]));
1489
- // Keep the parent task selected so the new child appears in "Child tasks" immediately.
1820
+ // Keep the parent task selected so the new subtask appears immediately.
1490
1821
  setIsDirty(true);
1491
1822
  setSaveError(null);
1492
1823
  setCreatingChildTask(true);
@@ -1497,7 +1828,7 @@ export function ProjectTemplatesPanel() {
1497
1828
  if (saved) {
1498
1829
  setIsAddChildTaskDialogOpen(false);
1499
1830
  setNewChildTaskTitle("");
1500
- toast.success("Child task template created");
1831
+ toast.success("Subtask template created");
1501
1832
  }
1502
1833
  }
1503
1834
  finally {
@@ -1532,6 +1863,12 @@ export function ProjectTemplatesPanel() {
1532
1863
  setSelectedDependencyId(null);
1533
1864
  setSelectedTaskId(taskId);
1534
1865
  }, []);
1866
+ const handleCloseTaskDetailsPane = useCallback(() => {
1867
+ selectedTaskIdRef.current = null;
1868
+ selectedDependencyIdRef.current = null;
1869
+ setSelectedTaskId(null);
1870
+ setSelectedDependencyId(null);
1871
+ }, []);
1535
1872
  const handleSelectDependencyFromGraph = useCallback((taskId, dependencyId) => {
1536
1873
  selectedDependencyIdRef.current = dependencyId;
1537
1874
  setSelectedTaskId(taskId);
@@ -1662,6 +1999,43 @@ export function ProjectTemplatesPanel() {
1662
1999
  }
1663
2000
  runDelete();
1664
2001
  }, [applyDraftChange, editContext]);
2002
+ const removeGoalDefinitionById = useCallback((goalId) => {
2003
+ const template = draftTemplateRef.current;
2004
+ const goals = template?.goalTemplates ?? [];
2005
+ if (!goals.some((goal) => goal.id === goalId))
2006
+ return;
2007
+ const goalTitle = goals.find((goal) => goal.id === goalId)?.title ?? "Untitled goal";
2008
+ const runDelete = () => {
2009
+ const current = draftTemplateRef.current;
2010
+ const currentGoals = current?.goalTemplates ?? [];
2011
+ if (!currentGoals.some((goal) => goal.id === goalId))
2012
+ return;
2013
+ const remainingGoals = currentGoals.filter((goal) => goal.id !== goalId);
2014
+ applyDraftChange((currentTemplate) => ({
2015
+ ...currentTemplate,
2016
+ goalTemplates: (currentTemplate.goalTemplates ?? []).filter((goal) => goal.id !== goalId),
2017
+ }));
2018
+ setSelectedGoalId((prev) => {
2019
+ if (prev === goalId) {
2020
+ return remainingGoals[0]?.id ?? null;
2021
+ }
2022
+ return remainingGoals.some((goal) => goal.id === prev)
2023
+ ? prev
2024
+ : (remainingGoals[0]?.id ?? null);
2025
+ });
2026
+ };
2027
+ if (editContext?.confirm) {
2028
+ editContext.confirm({
2029
+ header: "Remove goal definition",
2030
+ message: `Are you sure you want to remove "${goalTitle}"?`,
2031
+ acceptLabel: "Remove",
2032
+ showCancel: true,
2033
+ accept: runDelete,
2034
+ });
2035
+ return;
2036
+ }
2037
+ runDelete();
2038
+ }, [applyDraftChange, editContext]);
1665
2039
  const handleDeleteSelectedTask = useCallback(() => {
1666
2040
  if (!selectedTaskId)
1667
2041
  return;
@@ -1713,30 +2087,41 @@ export function ProjectTemplatesPanel() {
1713
2087
  const breadcrumbTaskCount = draftTemplate?.taskTemplates.length ?? 0;
1714
2088
  const breadcrumbItems = useMemo(() => breadcrumbDraftName
1715
2089
  ? [
1716
- {
1717
- title: "Workflow Project Templates",
1718
- subtitle: "Create project templates",
1719
- onClick: () => {
1720
- void handleNavigateToOverview();
1721
- },
1722
- },
1723
2090
  {
1724
2091
  title: breadcrumbDraftName,
1725
2092
  subtitle: `${breadcrumbTaskCount} task templates`,
2093
+ backLink: {
2094
+ label: "Back to project templates overview",
2095
+ onClick: () => {
2096
+ void handleNavigateToOverview();
2097
+ },
2098
+ },
1726
2099
  },
1727
2100
  ]
1728
2101
  : null, [breadcrumbDraftName, breadcrumbTaskCount, handleNavigateToOverview]);
1729
2102
  const desktopHeaderActions = useMemo(() => {
1730
2103
  if (isMobile)
1731
2104
  return null;
2105
+ const showCreate = !draftTemplate;
1732
2106
  const showDelete = draftTemplate && !draftTemplate.isSystem;
1733
- return (_jsxs("div", { className: "flex items-center gap-2", children: [headerStatusBadge, _jsxs(Button, { size: "sm", onClick: () => void handleCreateTemplate(), "data-testid": "project-template-create-button", children: [_jsx(Plus, { className: "h-4 w-4", strokeWidth: 1.5 }), "Create template"] }), showDelete ? (_jsxs(Button, { variant: "outline", size: "sm", onClick: () => handleDeleteTemplate(), disabled: deleting, "data-testid": "project-template-delete-button", children: [_jsx(DeleteIcon, { size: "lg" }), deleting ? "Deleting..." : "Delete"] })) : null] }));
2107
+ const agentPanelHeaderOffset = draftTemplate &&
2108
+ !isTaskEditorMaximized &&
2109
+ !isAgentPanelCollapsed &&
2110
+ agentPanelBounds
2111
+ ? Math.round(agentPanelBounds.width + 8)
2112
+ : 0;
2113
+ return (_jsxs("div", { className: "mt-2 flex items-center gap-2", style: agentPanelHeaderOffset > 0
2114
+ ? { marginRight: agentPanelHeaderOffset }
2115
+ : undefined, children: [headerStatusBadge, showCreate ? (_jsxs(Button, { size: "sm", onClick: () => void handleCreateTemplate(), "data-testid": "project-template-create-button", children: [_jsx(Plus, { className: "h-4 w-4", strokeWidth: 1.5 }), "Create template"] })) : null, showDelete ? (_jsxs(Button, { variant: "outline", size: "sm", onClick: () => handleDeleteTemplate(), disabled: deleting, "data-testid": "project-template-delete-button", children: [_jsx(DeleteIcon, { size: "lg" }), deleting ? "Deleting..." : "Delete"] })) : null] }));
1734
2116
  }, [
2117
+ agentPanelBounds,
1735
2118
  deleting,
1736
2119
  draftTemplate,
1737
2120
  handleCreateTemplate,
1738
2121
  handleDeleteTemplate,
1739
2122
  headerStatusBadge,
2123
+ isAgentPanelCollapsed,
2124
+ isTaskEditorMaximized,
1740
2125
  isMobile,
1741
2126
  ]);
1742
2127
  useEffect(() => {
@@ -1774,7 +2159,7 @@ export function ProjectTemplatesPanel() {
1774
2159
  }));
1775
2160
  return nextLayout;
1776
2161
  } }) }) }));
1777
- const taskPane = (_jsx("div", { className: "flex h-full min-h-0 flex-col overflow-hidden", "data-testid": "project-template-task-detail-pane", children: !selectedTask ? (_jsx("div", { className: "min-h-0 flex-1 overflow-y-auto p-4", children: _jsx("div", { className: "border-border-default bg-neutral-grey-5 text-neutral-grey-50 rounded-lg border border-dashed p-6 text-center text-xs", children: "Select a task node to edit its details." }) })) : (_jsxs(_Fragment, { children: [_jsx("div", { className: "border-border-default shrink-0 border-b bg-white px-4 pt-4 pb-3", children: _jsxs("div", { className: "flex items-center justify-between gap-3", children: [_jsxs("div", { children: [_jsxs("div", { className: "flex items-center gap-2", children: [_jsx("div", { className: "text-neutral-grey-100 text-xs font-medium", "data-testid": "project-template-selected-task-title", children: selectedTask.title || "Untitled Task" }), selectedTask.taskType === "DecisionPoint" ? (_jsx(Badge, { variant: "outline", className: "border-highlight-100 bg-highlight-10 text-2xs text-highlight-100", children: "Decision Point" })) : null, selectedTask.disabled ? (_jsx(Badge, { variant: "outline", className: "text-2xs", children: "Disabled" })) : null] }), _jsx("div", { className: "text-neutral-grey-50 text-xs", children: "Configure task details, assignment, and dependencies." })] }), _jsxs(Button, { variant: "outline", size: "sm", onClick: handleDeleteSelectedTask, "data-testid": "project-template-remove-task-button", children: [_jsx(DeleteIcon, { size: "lg" }), "Remove Task"] })] }) }), _jsx("div", { className: "min-h-0 flex-1 overflow-y-auto px-4 pt-3 pb-4", children: _jsxs("div", { className: "space-y-4", children: [_jsxs("div", { className: "grid gap-4 md:grid-cols-2", children: [_jsxs("div", { className: "grid gap-1.5 md:col-span-2", children: [_jsx(Label, { className: "text-xs", htmlFor: "project-template-task-title-input", children: "Task title" }), _jsx(Input, { id: "project-template-task-title-input", value: selectedTask.title, onChange: (event) => updateSelectedTask((currentTask) => ({
2162
+ const taskPane = (_jsx("div", { className: "flex h-full min-h-0 flex-col overflow-hidden", "data-testid": "project-template-task-detail-pane", children: !selectedTask ? (_jsx("div", { className: "min-h-0 flex-1 overflow-y-auto p-4", children: _jsx("div", { className: "border-border-default bg-neutral-grey-5 text-neutral-grey-50 rounded-lg border border-dashed p-6 text-center text-xs", children: "Select a task node to edit its details." }) })) : (_jsxs(_Fragment, { children: [_jsx("div", { className: "border-border-default shrink-0 border-b bg-white px-4 pt-4 pb-3", children: _jsxs("div", { className: "flex items-start justify-between gap-3", children: [_jsxs("div", { children: [_jsxs("div", { className: "flex items-center gap-2", children: [_jsx("div", { className: "text-neutral-grey-100 text-xs font-medium", "data-testid": "project-template-selected-task-title", children: selectedTask.title || "Untitled Task" }), selectedTask.taskType === "DecisionPoint" ? (_jsx(Badge, { variant: "outline", className: "border-highlight-100 bg-highlight-10 text-2xs text-highlight-100", children: "Decision Point" })) : null, selectedTask.disabled ? (_jsx(Badge, { variant: "outline", className: "text-2xs", children: "Disabled" })) : null] }), _jsx("div", { className: "text-neutral-grey-50 text-xs", children: "Configure task details, assignment, and dependencies." })] }), _jsxs("div", { className: "flex shrink-0 items-center gap-2", children: [_jsxs(Button, { variant: "outline", size: "sm", onClick: handleDeleteSelectedTask, "data-testid": "project-template-remove-task-button", children: [_jsx(DeleteIcon, { size: "lg" }), "Remove Task"] }), _jsx(CloseButton, { onClick: handleCloseTaskDetailsPane, label: "Close task details", "data-testid": "project-template-close-task-details-button" })] })] }) }), _jsx("div", { className: "min-h-0 flex-1 overflow-y-auto px-4 pt-3 pb-4", children: _jsxs("div", { className: "space-y-4", children: [_jsxs("div", { className: "grid gap-4 md:grid-cols-2", children: [_jsxs("div", { className: "grid gap-1.5 md:col-span-2", children: [_jsx(Label, { className: "text-xs", htmlFor: "project-template-task-title-input", children: "Task title" }), _jsx(Input, { id: "project-template-task-title-input", value: selectedTask.title, onChange: (event) => updateSelectedTask((currentTask) => ({
1778
2163
  ...currentTask,
1779
2164
  title: event.target.value,
1780
2165
  })), placeholder: "Task title", className: "text-xs md:text-xs", "data-testid": "project-template-task-title-input" })] }), _jsxs("div", { className: "grid gap-1.5 md:col-span-2", children: [_jsx(Label, { className: "text-xs", children: "Description" }), _jsx(Textarea, { className: "text-xs", value: selectedTask.description ?? "", onChange: (event) => updateSelectedTask((currentTask) => ({
@@ -1803,7 +2188,7 @@ export function ProjectTemplatesPanel() {
1803
2188
  agentProfileId: next?.assigneeType === "Agent"
1804
2189
  ? next.assigneeId
1805
2190
  : null,
1806
- })), placeholder: "Assign user or agent", buttonClassName: "h-[27px] w-full justify-between rounded-md bg-neutral-grey-5 text-xs", buttonTestId: "project-template-task-assignee-picker" }) }), selectedTask.assigneeType === "Agent" ? (_jsxs(Button, { type: "button", size: "sm", variant: "outline", className: "h-[27px] shrink-0 gap-1 px-2 text-xs", onClick: () => void handleEditAssignedAgentProfile(), disabled: !selectedAgentProfileId, "data-testid": "project-template-task-edit-agent-profile-button", children: [_jsx(Settings2, { className: "h-3.5 w-3.5", strokeWidth: 1.5 }), "Edit Profile"] })) : null] }), profilesError ? (_jsx("div", { className: "text-feedback-orange text-xs", children: profilesError })) : null] })] }), _jsxs("div", { className: "space-y-3", children: [_jsxs("div", { className: "border-border-default bg-neutral-grey-5 rounded-lg border p-3", "data-testid": "project-template-dependencies-section", children: [_jsxs("div", { className: "mb-2 flex items-center justify-between gap-2", children: [_jsxs("div", { className: "text-neutral-grey-100 flex items-center gap-2 text-xs font-medium", children: [_jsx(Shield, { className: "text-neutral-grey-50 h-4 w-4", strokeWidth: 1.5 }), "Dependencies"] }), _jsxs(Popover, { open: dependencyPickerOpen, onOpenChange: setDependencyPickerOpen, children: [_jsx(PopoverTrigger, { asChild: true, children: _jsx(Button, { type: "button", size: "sm", variant: "outline", className: "h-7 gap-1 px-2", disabled: dependencyAddCandidates.length === 0, "aria-label": "Add dependency", "data-testid": "project-template-add-dependency-button", children: _jsx(Plus, { className: "h-3.5 w-3.5", strokeWidth: 1.5 }) }) }), _jsxs(PopoverContent, { align: "end", className: "w-72 p-0", sideOffset: 6, "data-testid": "project-template-dependency-popover", children: [_jsx("div", { className: "border-border-default text-neutral-grey-100 border-b px-3 py-2 text-xs font-medium", children: "Depends on" }), _jsx("div", { className: "max-h-56 overflow-y-auto p-1", children: dependencyAddCandidates.length === 0 ? (_jsx("div", { className: "text-neutral-grey-50 px-2 py-3 text-center text-xs", children: "All other tasks are already linked." })) : (dependencyAddCandidates.map((task) => (_jsxs("button", { type: "button", className: "hover:bg-neutral-grey-5 flex w-full items-center gap-2 rounded-md px-2 py-2 text-left text-xs", onClick: () => handleAddDependency(task.id), "data-testid": `project-template-dependency-option-${task.id}`, children: [_jsx(Link2, { className: "text-neutral-grey-50 h-3.5 w-3.5 shrink-0", strokeWidth: 1.5 }), _jsx("span", { className: "text-neutral-grey-100 min-w-0 truncate font-medium", children: task.title || "Untitled Task" })] }, task.id)))) })] })] })] }), _jsx("p", { className: "text-neutral-grey-50 mb-2 text-[11px] leading-snug", children: "This task must wait for these tasks to finish first." }), dependencyTasks.length === 0 ? (_jsx("div", { className: "text-neutral-grey-50 text-xs", children: draftTemplate.taskTemplates.filter((t) => t.id !== selectedTask.id).length === 0
2191
+ })), placeholder: "Assign user or agent", buttonClassName: "h-8 min-h-0 w-full justify-between rounded-md bg-white text-xs", buttonTestId: "project-template-task-assignee-picker" }) }), selectedTask.assigneeType === "Agent" ? (_jsxs(Button, { type: "button", size: "sm", variant: "outline", className: "h-8 shrink-0 gap-1 px-2 text-xs", onClick: () => void handleEditAssignedAgentProfile(), disabled: !selectedAgentProfileId, "data-testid": "project-template-task-edit-agent-profile-button", children: [_jsx(Settings2, { className: "h-3.5 w-3.5", strokeWidth: 1.5 }), "Edit Profile"] })) : null] }), profilesError ? (_jsx("div", { className: "text-feedback-orange text-xs", children: profilesError })) : null] })] }), _jsxs("div", { className: "space-y-3", children: [_jsxs("div", { className: "border-border-default bg-neutral-grey-5 rounded-lg border p-3", "data-testid": "project-template-dependencies-section", children: [_jsxs("div", { className: "mb-2 flex items-center justify-between gap-2", children: [_jsxs("div", { className: "text-neutral-grey-100 flex items-center gap-2 text-xs font-medium", children: [_jsx(Shield, { className: "text-neutral-grey-50 h-4 w-4", strokeWidth: 1.5 }), "Dependencies"] }), _jsxs(Popover, { open: dependencyPickerOpen, onOpenChange: setDependencyPickerOpen, children: [_jsx(PopoverTrigger, { asChild: true, children: _jsx(Button, { type: "button", size: "sm", variant: "outline", className: "h-7 gap-1 px-2", disabled: dependencyAddCandidates.length === 0, "aria-label": "Add dependency", "data-testid": "project-template-add-dependency-button", children: _jsx(Plus, { className: "h-3.5 w-3.5", strokeWidth: 1.5 }) }) }), _jsxs(PopoverContent, { align: "end", className: "w-72 p-0", sideOffset: 6, "data-testid": "project-template-dependency-popover", children: [_jsx("div", { className: "border-border-default text-neutral-grey-100 border-b px-3 py-2 text-xs font-medium", children: "Depends on" }), _jsx("div", { className: "max-h-56 overflow-y-auto p-1", children: dependencyAddCandidates.length === 0 ? (_jsx("div", { className: "text-neutral-grey-50 px-2 py-3 text-center text-xs", children: "All other tasks are already linked." })) : (dependencyAddCandidates.map((task) => (_jsxs("button", { type: "button", className: "hover:bg-neutral-grey-5 flex w-full items-center gap-2 rounded-md px-2 py-2 text-left text-xs", onClick: () => handleAddDependency(task.id), "data-testid": `project-template-dependency-option-${task.id}`, children: [_jsx(Link2, { className: "text-neutral-grey-50 h-3.5 w-3.5 shrink-0", strokeWidth: 1.5 }), _jsx("span", { className: "text-neutral-grey-100 min-w-0 truncate font-medium", children: task.title || "Untitled Task" })] }, task.id)))) })] })] })] }), _jsx("p", { className: "text-neutral-grey-50 mb-2 text-[11px] leading-snug", children: "This task must wait for these tasks to finish first." }), dependencyTasks.length === 0 ? (_jsx("div", { className: "text-neutral-grey-50 text-xs", children: draftTemplate.taskTemplates.filter((t) => t.id !== selectedTask.id).length === 0
1807
2192
  ? "Add more task templates to create dependencies."
1808
2193
  : "No dependencies yet. Use + to add one." })) : (_jsx("ul", { className: "space-y-1.5", children: dependencyTasks.map((task) => (_jsxs("li", { tabIndex: 0, className: cn("flex items-center justify-between gap-2 rounded-md border bg-white px-3 py-2 text-xs transition-colors outline-none", selectedDependencyId === task.id
1809
2194
  ? "border-feedback-orange bg-feedback-orange-light ring-feedback-orange ring-1"
@@ -1819,23 +2204,28 @@ export function ProjectTemplatesPanel() {
1819
2204
  event.preventDefault();
1820
2205
  event.stopPropagation();
1821
2206
  handleRemoveDependency(task.id);
1822
- }, "data-testid": `project-template-dependency-row-${task.id}`, children: [_jsx("span", { className: "text-neutral-grey-100 min-w-0 truncate font-medium", children: task.title || "Untitled Task" }), _jsx("button", { type: "button", className: "text-neutral-grey-50 hover:bg-neutral-grey-5 hover:text-neutral-grey-100 shrink-0 rounded p-0.5", "aria-label": `Remove dependency on ${task.title}`, onClick: () => handleRemoveDependency(task.id), "data-testid": `project-template-remove-dependency-${task.id}`, children: _jsx(X, { className: "h-4 w-4", strokeWidth: 1.5 }) })] }, task.id))) }))] }), _jsxs("div", { className: "border-border-default bg-neutral-grey-5 rounded-lg border p-3", "data-testid": "project-template-child-tasks-section", children: [_jsxs("div", { className: "mb-2 flex items-center justify-between gap-2", children: [_jsxs("div", { className: "text-neutral-grey-100 flex items-center gap-2 text-xs font-medium", children: [_jsx(CornerDownRight, { className: "text-neutral-grey-50 h-4 w-4", strokeWidth: 1.5 }), "Child tasks"] }), _jsx(Button, { type: "button", size: "sm", variant: "outline", className: "h-7 gap-1 px-2", onClick: () => void handleOpenAddChildTaskDialog(), disabled: creatingChildTask, "aria-label": "Add child task", "data-testid": "project-template-add-child-task-button", children: _jsx(Plus, { className: "h-3.5 w-3.5", strokeWidth: 1.5 }) })] }), _jsx("p", { className: "text-neutral-grey-50 mb-2 text-[11px] leading-snug", children: "Tasks that run after this one (they depend on this task)." }), childTaskTemplates.length === 0 ? (_jsx("div", { className: "text-neutral-grey-50 text-xs", children: "No child tasks yet. Use + to add one." })) : (_jsx("ul", { className: "space-y-1.5", children: childTaskTemplates.map((task) => (_jsxs("li", { className: "border-border-default flex items-center justify-between gap-2 rounded-md border bg-white px-3 py-2 text-xs", "data-testid": `project-template-child-task-row-${task.id}`, children: [_jsx("span", { className: "text-neutral-grey-100 min-w-0 truncate font-medium", children: task.title || "Untitled Task" }), _jsx("button", { type: "button", className: "text-neutral-grey-50 hover:bg-neutral-grey-5 hover:text-neutral-grey-100 shrink-0 rounded p-0.5", "aria-label": `Unlink child task ${task.title}`, onClick: () => handleUnlinkChildTask(task.id), "data-testid": `project-template-unlink-child-task-${task.id}`, children: _jsx(X, { className: "h-4 w-4", strokeWidth: 1.5 }) })] }, task.id))) }))] })] })] }) })] })) }));
2207
+ }, "data-testid": `project-template-dependency-row-${task.id}`, children: [_jsx("span", { className: "text-neutral-grey-100 min-w-0 truncate font-medium", children: task.title || "Untitled Task" }), _jsx("button", { type: "button", className: "text-neutral-grey-50 hover:bg-neutral-grey-5 hover:text-neutral-grey-100 shrink-0 rounded p-0.5", "aria-label": `Remove dependency on ${task.title}`, onClick: () => handleRemoveDependency(task.id), "data-testid": `project-template-remove-dependency-${task.id}`, children: _jsx(X, { className: "h-4 w-4", strokeWidth: 1.5 }) })] }, task.id))) }))] }), _jsxs("div", { className: "border-border-default bg-neutral-grey-5 rounded-lg border p-3", "data-testid": "project-template-child-tasks-section", children: [_jsxs("div", { className: "mb-2 flex items-center justify-between gap-2", children: [_jsxs("div", { className: "text-neutral-grey-100 flex items-center gap-2 text-xs font-medium", children: [_jsx(CornerDownRight, { className: "text-neutral-grey-50 h-4 w-4", strokeWidth: 1.5 }), "Subtasks"] }), _jsx(Button, { type: "button", size: "sm", variant: "outline", className: "h-7 gap-1 px-2", onClick: () => void handleOpenAddChildTaskDialog(), disabled: creatingChildTask, "aria-label": "Add subtask", "data-testid": "project-template-add-child-task-button", children: _jsx(Plus, { className: "h-3.5 w-3.5", strokeWidth: 1.5 }) })] }), _jsx("p", { className: "text-neutral-grey-50 mb-2 text-[11px] leading-snug", children: "Subtasks must be completed before this task is done." }), childTaskTemplates.length === 0 ? (_jsx("div", { className: "text-neutral-grey-50 text-xs", children: "No subtasks yet. Use + to add one." })) : (_jsx("ul", { className: "space-y-1.5", children: childTaskTemplates.map((task) => (_jsxs("li", { className: "border-border-default flex items-center justify-between gap-2 rounded-md border bg-white px-3 py-2 text-xs", "data-testid": `project-template-child-task-row-${task.id}`, children: [_jsx("span", { className: "text-neutral-grey-100 min-w-0 truncate font-medium", children: task.title || "Untitled Task" }), _jsx("button", { type: "button", className: "text-neutral-grey-50 hover:bg-neutral-grey-5 hover:text-neutral-grey-100 shrink-0 rounded p-0.5", "aria-label": `Unlink subtask ${task.title}`, onClick: () => handleUnlinkChildTask(task.id), "data-testid": `project-template-unlink-child-task-${task.id}`, children: _jsx(X, { className: "h-4 w-4", strokeWidth: 1.5 }) })] }, task.id))) }))] })] })] }) })] })) }));
1823
2208
  if (isMobile) {
1824
2209
  return (_jsxs("div", { className: "border-border-default flex shrink-0 flex-col border-b", children: [_jsx("div", { className: "border-border-default h-[300px] shrink-0 overflow-hidden border-b", children: graphView }), taskPane] }));
1825
2210
  }
1826
- return (_jsx("div", { className: "border-border-default min-h-[360px] flex-1 overflow-hidden border-b", children: _jsx(Splitter, { direction: "vertical", localStorageKey: "settings-project-template-graph-task-splitter-v1", className: "h-full", panels: [
2211
+ return (_jsx("div", { className: "border-border-default min-h-[360px] flex-1 overflow-hidden border-b", children: _jsx(Splitter, { direction: "horizontal", localStorageKey: "settings-project-template-graph-task-splitter-v2", className: "h-full", panels: [
1827
2212
  {
1828
2213
  name: "project-template-graph",
1829
- defaultSize: 400,
1830
- className: "min-h-0",
1831
- content: graphView,
1832
- },
1833
- {
1834
- name: "project-template-task-details",
1835
2214
  defaultSize: "auto",
1836
2215
  className: "min-h-0",
1837
- content: taskPane,
2216
+ content: graphView,
1838
2217
  },
2218
+ ...(selectedTask
2219
+ ? [
2220
+ {
2221
+ name: "project-template-task-details",
2222
+ defaultSize: 560,
2223
+ minSize: 360,
2224
+ className: "min-h-0",
2225
+ content: taskPane,
2226
+ },
2227
+ ]
2228
+ : []),
1839
2229
  ] }) }));
1840
2230
  };
1841
2231
  const detailContent = (_jsxs("div", { className: "bg-neutral-grey-5/40 flex h-full flex-col", "data-testid": "project-template-detail-pane", children: [isMobile && draftTemplate && !draftTemplate.isSystem ? (_jsxs("div", { className: "border-border-default flex min-w-0 items-center gap-3 border-b bg-white px-5 py-2", "data-testid": "project-template-detail-pane-header", children: [_jsx("div", { className: "min-w-0 flex-1", children: templateSelector }), _jsx("div", { className: "flex shrink-0 items-center gap-1.5 self-center", children: _jsx(Button, { variant: "outline", size: "icon", className: "h-9 w-9 shrink-0", onClick: () => handleDeleteTemplate(), disabled: deleting, "aria-label": deleting ? "Deleting template" : "Delete template", title: deleting ? "Deleting…" : "Delete template", "data-testid": "project-template-delete-button", children: deleting ? (_jsx(RefreshCw, { className: "h-4 w-4 animate-spin", strokeWidth: 1.5 })) : (_jsx(DeleteIcon, { size: "lg" })) }) })] })) : null, draftTemplate ? ((() => {
@@ -1852,6 +2242,12 @@ export function ProjectTemplatesPanel() {
1852
2242
  content: null,
1853
2243
  testId: "project-template-tab-task-editor",
1854
2244
  },
2245
+ {
2246
+ id: "project-template-tab-goals",
2247
+ label: "Goals",
2248
+ content: null,
2249
+ testId: "project-template-tab-goals",
2250
+ },
1855
2251
  ];
1856
2252
  const basicSettingsContent = (_jsxs("div", { className: "grid gap-4 overflow-y-auto p-4 md:grid-cols-2", "data-testid": "project-template-basic-settings-panel", children: [_jsxs("div", { className: "grid gap-1.5 md:col-span-2", children: [_jsx(Label, { className: "text-xs", htmlFor: "project-template-name-input", children: "Template name" }), _jsx(Input, { id: "project-template-name-input", value: draftTemplate.name, onChange: (event) => applyDraftChange((currentTemplate) => ({
1857
2253
  ...currentTemplate,
@@ -1870,20 +2266,81 @@ export function ProjectTemplatesPanel() {
1870
2266
  })), className: "data-[state=checked]:bg-feedback-orange data-[state=checked]:shadow-inner", "aria-label": "Disable this project template", "data-testid": "project-template-disabled-switch" })] }), _jsxs("div", { className: "flex items-center justify-between gap-4 md:col-span-2", children: [_jsxs("div", { className: "min-w-0", children: [_jsx("div", { className: "text-neutral-grey-100 text-xs font-medium", children: "Hide from create dialog" }), _jsx("div", { className: "text-neutral-grey-50 mt-0.5 text-xs", children: "Keeps the template active, but removes it from the create project dialog." })] }), _jsx(Switch, { checked: draftTemplate.hideFromCreateDialog === true, onCheckedChange: (checked) => applyDraftChange((currentTemplate) => ({
1871
2267
  ...currentTemplate,
1872
2268
  hideFromCreateDialog: checked,
1873
- })), "aria-label": "Hide this project template from the create dialog", "data-testid": "project-template-hide-from-create-dialog-switch" })] }), _jsxs("div", { className: "flex items-center justify-between gap-4 md:col-span-2", children: [_jsxs("div", { className: "min-w-0", children: [_jsx("div", { className: "text-neutral-grey-100 text-xs font-medium", children: "Open in wizard mode" }), _jsx("div", { className: "text-neutral-grey-50 mt-0.5 text-xs", children: "New projects created from this template start in taskboard wizard mode." })] }), _jsx(Switch, { checked: draftTemplate.openInWizardMode === true, onCheckedChange: (checked) => applyDraftChange((currentTemplate) => ({
1874
- ...currentTemplate,
1875
- openInWizardMode: checked,
1876
- })), "aria-label": "Open new projects from this template in wizard mode", "data-testid": "project-template-open-in-wizard-mode-switch" })] })] }));
2269
+ })), "aria-label": "Hide this project template from the create dialog", "data-testid": "project-template-hide-from-create-dialog-switch" })] })] }));
1877
2270
  const taskEditorContent = (_jsx("div", { className: "flex h-full min-h-0 flex-1 flex-col overflow-hidden", children: renderTemplateTaskEditorMain() }));
1878
- return (_jsxs("div", { className: cn("flex min-h-0 flex-1 flex-col overflow-y-auto overscroll-y-contain md:overflow-hidden", isTaskEditorMaximized ? "overflow-hidden p-0" : "p-5"), children: [_jsx("div", { className: "flex shrink-0 flex-col gap-5 md:max-h-[50vh] md:min-h-0 md:overflow-y-auto md:overscroll-y-contain", children: saveError && (_jsx("div", { className: "border-feedback-red bg-feedback-red-light text-feedback-red rounded border px-4 py-3 text-xs", children: saveError })) }), _jsxs("section", { className: cn("border-border-default flex min-h-0 flex-1 flex-col rounded-lg border bg-white md:overflow-hidden", isTaskEditorMaximized &&
1879
- "overflow-hidden rounded-none shadow-xl"), "data-testid": "project-template-task-editor-shell", children: [_jsxs("div", { className: "border-border-default flex shrink-0 items-center justify-between gap-3 border-b px-4 py-3", children: [_jsx("div", { className: "min-w-0 flex-1", children: _jsx(SimpleTabs, { tabs: detailTabs, activeTab: activeDetailTab === "basic" ? 0 : 1, setActiveTab: (index) => setActiveDetailTab(index === 0 ? "basic" : "tasks"), hideContent: true, className: "w-full justify-start gap-6" }) }), _jsxs(Button, { size: "sm", variant: "outline", onClick: () => void handleOpenCreateTaskDialog(), disabled: creatingTask, "data-testid": "project-template-add-task-button", className: activeDetailTab === "tasks"
1880
- ? ""
1881
- : "pointer-events-none invisible", "aria-hidden": activeDetailTab !== "tasks", tabIndex: activeDetailTab === "tasks" ? undefined : -1, children: [_jsx(Plus, { className: "h-4 w-4", strokeWidth: 1.5 }), "Add Task"] })] }), _jsx("div", { className: "flex min-h-0 flex-1 flex-col overflow-hidden", children: activeDetailTab === "basic"
2271
+ const goalDefinitions = draftTemplate.goalTemplates ?? [];
2272
+ const selectedGoal = goalDefinitions.find((goal) => goal.id === selectedGoalId) ?? null;
2273
+ const goalsContent = (_jsx("div", { className: "flex h-full min-h-0 flex-1 flex-col gap-3 overflow-y-auto p-4", "data-testid": "project-template-goals-section", children: goalDefinitions.length === 0 ? (_jsx("div", { className: "border-border-default text-neutral-grey-50 rounded-md border border-dashed p-6 text-center text-xs", children: "No goal definitions yet. Use \u201CAdd Goal\u201D to create one \u2014 projects created from this template can pick from these goals." })) : (_jsxs("div", { className: "grid gap-3 md:grid-cols-[220px_1fr]", children: [_jsx("div", { className: "flex flex-col gap-1", children: [...goalDefinitions]
2274
+ .sort((a, b) => (a.sortOrder ?? 0) - (b.sortOrder ?? 0))
2275
+ .map((goal) => (_jsxs("div", { "data-testid": `project-template-goal-row-${goal.id}`, className: cn("flex items-center justify-between gap-2 rounded-md px-3 py-2 text-xs", goal.id === selectedGoalId
2276
+ ? "bg-neutral-grey-5"
2277
+ : "hover:bg-neutral-grey-5 bg-transparent"), children: [_jsxs("button", { type: "button", className: "min-w-0 flex-1 truncate text-left", onClick: () => setSelectedGoalId(goal.id), children: [goal.title || "Untitled goal", goal.disabled ? " (disabled)" : ""] }), _jsx("button", { type: "button", "aria-label": `Remove ${goal.title || "goal"}`, "data-testid": `project-template-remove-goal-${goal.id}`, className: "text-neutral-grey-50 hover:text-feedback-red shrink-0", onClick: () => removeGoalDefinitionById(goal.id), children: _jsx(Trash2, { className: "h-3.5 w-3.5", strokeWidth: 1.5 }) })] }, goal.id))) }), selectedGoal ? (_jsxs("div", { className: "border-border-default flex flex-col gap-3 rounded-md border bg-white p-4", children: [_jsxs("div", { className: "grid gap-1.5", children: [_jsx(Label, { className: "text-xs", htmlFor: "project-template-goal-title-input", children: "Title" }), _jsx(Input, { id: "project-template-goal-title-input", "data-testid": "project-template-goal-title-input", className: "text-xs md:text-xs", value: selectedGoal.title, onChange: (event) => updateSelectedGoal((goal) => ({
2278
+ ...goal,
2279
+ title: event.target.value,
2280
+ })), placeholder: "Goal title" })] }), _jsxs("div", { className: "grid gap-1.5", children: [_jsx(Label, { className: "text-xs", htmlFor: "project-template-goal-description-input", children: "Description" }), _jsx(Textarea, { id: "project-template-goal-description-input", "data-testid": "project-template-goal-description-input", className: "text-xs", rows: 3, value: selectedGoal.description ?? "", onChange: (event) => updateSelectedGoal((goal) => ({
2281
+ ...goal,
2282
+ description: event.target.value,
2283
+ })), placeholder: "What this goal covers" })] }), _jsxs("div", { className: "grid gap-1.5", children: [_jsx(Label, { className: "text-xs", htmlFor: "project-template-goal-sort-order-input", children: "Sort order" }), _jsx(Input, { id: "project-template-goal-sort-order-input", type: "number", className: "text-xs md:text-xs", value: selectedGoal.sortOrder ?? 0, onChange: (event) => updateSelectedGoal((goal) => ({
2284
+ ...goal,
2285
+ sortOrder: event.target.value.trim() === ""
2286
+ ? 0
2287
+ : Number(event.target.value),
2288
+ })) })] }), _jsxs("div", { className: "grid gap-1.5", children: [_jsx(Label, { className: "text-xs", htmlFor: "project-template-goal-default-scope-input", children: "Default scope (JSON, optional)" }), _jsx(Textarea, { id: "project-template-goal-default-scope-input", className: "font-mono text-xs", rows: 2, value: selectedGoal.defaultScopeJson ?? "", onChange: (event) => updateSelectedGoal((goal) => ({
2289
+ ...goal,
2290
+ defaultScopeJson: event.target.value,
2291
+ })), placeholder: '{"rootItemId":"...","pagesOnly":true}' })] }), _jsxs("div", { className: "grid gap-1.5", children: [_jsx(Label, { className: "text-xs", htmlFor: "project-template-goal-data-shape-input", children: "Data shape hint (optional)" }), _jsx(Input, { id: "project-template-goal-data-shape-input", className: "text-xs md:text-xs", value: selectedGoal.dataShape ?? "", onChange: (event) => updateSelectedGoal((goal) => ({
2292
+ ...goal,
2293
+ dataShape: event.target.value,
2294
+ })), placeholder: "e.g. { recommendations: string[] }" })] }), _jsxs("div", { className: "flex items-center justify-between gap-4", children: [_jsxs("div", { className: "min-w-0", children: [_jsx("div", { className: "text-neutral-grey-100 text-xs font-medium", children: "Disabled" }), _jsx("div", { className: "text-neutral-grey-50 mt-0.5 text-xs", children: "Keeps the definition but hides it from the runtime goal catalog." })] }), _jsx(Switch, { checked: selectedGoal.disabled === true, onCheckedChange: (checked) => updateSelectedGoal((goal) => ({
2295
+ ...goal,
2296
+ disabled: checked,
2297
+ })), "aria-label": "Disable this goal definition", "data-testid": "project-template-goal-disabled-switch" })] })] })) : (_jsx("div", { className: "border-border-default text-neutral-grey-50 flex items-center justify-center rounded-md border border-dashed p-6 text-center text-xs", children: "Select a goal to edit its details." }))] })) }));
2298
+ const detailAction = activeDetailTab === "tasks" ? (_jsxs(Button, { size: "sm", variant: "outline", onClick: () => void handleOpenCreateTaskDialog(), disabled: creatingTask, "data-testid": "project-template-add-task-button", children: [_jsx(Plus, { className: "h-4 w-4", strokeWidth: 1.5 }), "Add Task"] })) : activeDetailTab === "goals" ? (_jsxs(Button, { size: "sm", variant: "outline", onClick: () => {
2299
+ setNewGoalTitle("");
2300
+ setIsCreateGoalDialogOpen(true);
2301
+ }, disabled: creatingGoal, "data-testid": "project-template-add-goal-button", children: [_jsx(Plus, { className: "h-4 w-4", strokeWidth: 1.5 }), "Add Goal"] })) : null;
2302
+ return (_jsxs("div", { className: cn("flex min-h-0 flex-1 flex-col overflow-y-auto overscroll-y-contain md:overflow-hidden", isTaskEditorMaximized && "overflow-hidden"), children: [saveError ? (_jsx("div", { className: "flex shrink-0 flex-col pb-3 md:max-h-[50vh] md:min-h-0 md:overflow-y-auto md:overscroll-y-contain", children: _jsx("div", { className: "border-feedback-red bg-feedback-red-light text-feedback-red rounded border px-4 py-3 text-xs", children: saveError }) })) : null, _jsxs("section", { className: cn("border-border-default flex min-h-0 flex-1 flex-col rounded-lg border bg-white md:overflow-hidden", isTaskEditorMaximized &&
2303
+ "overflow-hidden rounded-none shadow-xl"), "data-testid": "project-template-task-editor-shell", children: [_jsxs("div", { className: "border-border-default flex h-[53px] shrink-0 items-center justify-between gap-3 border-b px-4 pt-3", children: [_jsx("div", { className: "min-w-0 flex-1", children: _jsx(SimpleTabs, { tabs: detailTabs, activeTab: activeDetailTab === "basic"
2304
+ ? 0
2305
+ : activeDetailTab === "tasks"
2306
+ ? 1
2307
+ : 2, setActiveTab: (index) => setActiveDetailTab(index === 0
2308
+ ? "basic"
2309
+ : index === 1
2310
+ ? "tasks"
2311
+ : "goals"), hideContent: true, className: "w-full translate-y-0.5 justify-start gap-6" }) }), detailAction ? (_jsx("div", { className: "mb-2 flex shrink-0 items-center", children: detailAction })) : null] }), _jsx("div", { className: "flex min-h-0 flex-1 flex-col overflow-hidden", children: activeDetailTab === "basic"
1882
2312
  ? basicSettingsContent
1883
- : taskEditorContent })] })] }));
2313
+ : activeDetailTab === "tasks"
2314
+ ? taskEditorContent
2315
+ : goalsContent })] })] }));
1884
2316
  })()) : (_jsx("div", { className: "flex min-h-0 flex-1 items-center justify-center p-5", children: _jsxs("div", { className: "border-border-default max-w-sm rounded-lg border border-dashed bg-white p-8 text-center", children: [_jsx(GitBranch, { className: "text-neutral-grey-50 mx-auto mb-3 h-10 w-10", strokeWidth: 1.2 }), _jsx("h3", { className: "text-neutral-grey-100 text-xs font-medium", children: "Select a project template" }), _jsx("p", { className: "text-neutral-grey-50 mt-1 text-xs", children: "Choose a template from the dropdown or create a new one to start editing." })] }) }))] }));
1885
- const overviewContent = (_jsx("div", { className: "flex h-full min-h-0 flex-col px-10 pt-0 pb-10", "data-testid": "project-template-overview", children: _jsx(Card, { icon: _jsx(GitBranch, { strokeWidth: 1, className: "h-5 w-5" }), title: "Workflow project templates", description: "Select a template to edit its defaults and task graph.", noPadding: true, className: "flex min-h-0 flex-1 flex-col overflow-hidden", children: _jsx("div", { className: "border-border-default flex min-h-0 flex-1 flex-col border-t", children: _jsx(ProjectTemplateSelectorList, { rootTestId: "project-template-overview-list", templates: templates, selectedTemplateId: selectedTemplateId, error: error, deleting: deleting, loading: state === "loading", onSelectTemplate: handleSelectTemplate, onDeleteTemplate: handleDeleteTemplate }) }) }) }));
1886
- const agentPanelContent = (_jsx(ProjectTemplateAgentPanel, { templateName: draftTemplate?.name ?? null, agentId: templateAgentId, loading: templateAgentLoading, resetting: templateAgentResetting, error: templateAgentError, onStartOver: () => void handleResetTemplateAgent(), onClose: handleHideTemplateAssistant, headerStart: isMobile ? (_jsx(Button, { type: "button", variant: "ghost", size: "sm", className: "gap-1 px-2", onClick: handleMobileBackFromAgent, "data-testid": "project-template-mobile-back-from-agent", children: _jsx(ChevronLeft, { className: "h-5 w-5", strokeWidth: 1.5 }) })) : undefined }));
2317
+ const overviewContent = (_jsx("div", { className: "flex h-full min-h-0 flex-col px-10 pt-0 pb-10", "data-testid": "project-template-overview", children: _jsx("div", { className: "flex min-h-0 flex-1 flex-col overflow-hidden rounded-lg bg-white", children: _jsx(ProjectTemplateSelectorList, { rootTestId: "project-template-overview-list", templates: templates, selectedTemplateId: selectedTemplateId, error: error, deleting: deleting, loading: state === "loading", onSelectTemplate: handleSelectTemplate, onDeleteTemplate: handleDeleteTemplate }) }) }));
2318
+ const agentFullHeightBounds = useMemo(() => !isMobile && !isTaskEditorMaximized && settingsMainContentBounds
2319
+ ? {
2320
+ top: settingsMainContentBounds.top,
2321
+ right: settingsMainContentBounds.left + settingsMainContentBounds.width,
2322
+ height: settingsMainContentBounds.height,
2323
+ }
2324
+ : undefined, [isMobile, isTaskEditorMaximized, settingsMainContentBounds]);
2325
+ const assistantTopToggleStyle = useMemo(() => !isMobile &&
2326
+ !isTaskEditorMaximized &&
2327
+ isAgentPanelCollapsed &&
2328
+ settingsMainContentBounds
2329
+ ? {
2330
+ position: "fixed",
2331
+ top: settingsMainContentBounds.top + 8,
2332
+ left: settingsMainContentBounds.left +
2333
+ settingsMainContentBounds.width -
2334
+ 88,
2335
+ zIndex: 45,
2336
+ }
2337
+ : undefined, [
2338
+ isAgentPanelCollapsed,
2339
+ isMobile,
2340
+ isTaskEditorMaximized,
2341
+ settingsMainContentBounds,
2342
+ ]);
2343
+ const agentPanelContent = (_jsx(ProjectTemplateAgentPanel, { templateName: draftTemplate?.name ?? null, agentId: templateAgentId, loading: templateAgentLoading, resetting: templateAgentResetting, error: templateAgentError, initialMetadata: templateAgentInitialMetadata, fullHeightBounds: agentFullHeightBounds, onStartOver: () => void handleResetTemplateAgent(), onClose: handleHideTemplateAssistant, headerStart: isMobile ? (_jsx(Button, { type: "button", variant: "ghost", size: "sm", className: "gap-1 px-2", onClick: handleMobileBackFromAgent, "data-testid": "project-template-mobile-back-from-agent", children: _jsx(ChevronLeft, { className: "h-5 w-5", strokeWidth: 1.5 }) })) : undefined }));
1887
2344
  const rightPanelContent = editingAgentProfile ? (_jsx(AgentProfileEditorPanel, { agent: editingAgentProfile, onClose: handleCloseEditingAgentProfile, actions: _jsxs(Button, { type: "button", variant: "outline", size: "sm", onClick: () => void handleDuplicateAssignedAgentProfile(), disabled: !selectedAgentProfileId ||
1888
2345
  !editContext ||
1889
2346
  duplicatingAgentProfile ||
@@ -1900,7 +2357,7 @@ export function ProjectTemplatesPanel() {
1900
2357
  name: "project-template-agent",
1901
2358
  defaultSize: 460,
1902
2359
  content: rightPanelContent,
1903
- className: "overflow-hidden",
2360
+ className: "overflow-hidden bg-white",
1904
2361
  collapsible: true,
1905
2362
  hidden: isMobile && mobileView !== "agent",
1906
2363
  },
@@ -1911,7 +2368,9 @@ export function ProjectTemplatesPanel() {
1911
2368
  if (!draftTemplate) {
1912
2369
  return overviewContent;
1913
2370
  }
1914
- return (_jsxs(_Fragment, { children: [_jsx("div", { className: cn("h-full", !isTaskEditorMaximized && "px-10 pt-0 pb-10"), children: _jsx("div", { className: cn("h-full", isTaskEditorMaximized && "fixed overflow-hidden bg-white shadow-xl"), style: projectTemplateEditorStyle, "data-testid": "project-template-editor", onKeyDownCapture: handleProjectTemplateEditorKeyDownCapture, children: _jsx(Splitter, { panels: panels, localStorageKey: PROJECT_TEMPLATE_SPLITTER_STORAGE_KEY, direction: "horizontal", className: "h-full", forceCollapseLastPanelKey: forceCollapseLastPanelKey, forceExpandLastPanelKey: forceExpandLastPanelKey }) }) }), _jsx(Dialog, { open: isCreateTaskDialogOpen, onOpenChange: (open) => {
2371
+ return (_jsxs(_Fragment, { children: [assistantTopToggleStyle ? (_jsx(Button, { type: "button", variant: "outline", size: "icon", className: "h-8 w-8 rounded-md bg-white shadow-sm hover:bg-white", style: assistantTopToggleStyle, onClick: handleShowTemplateAssistant, "aria-label": "Show template assistant", title: "Show template assistant", "data-testid": "project-template-assistant-expand-button", children: _jsx(PanelRightOpen, { className: "h-5 w-5", strokeWidth: 1 }) })) : null, _jsx("div", { className: cn("h-full", !isTaskEditorMaximized && "px-10 pt-0 pb-5"), children: _jsx("div", { className: cn("h-full", isTaskEditorMaximized && "fixed overflow-hidden bg-white shadow-xl"), style: projectTemplateEditorStyle, "data-testid": "project-template-editor", onKeyDownCapture: handleProjectTemplateEditorKeyDownCapture, children: _jsx(Splitter, { panels: panels, localStorageKey: PROJECT_TEMPLATE_SPLITTER_STORAGE_KEY, direction: "horizontal", className: "h-full !overflow-visible", expandLabel: _jsx(PanelRightOpen, { className: "h-5 w-5", strokeWidth: 1 }), expandButtonLabel: "Show template assistant", expandButtonTestId: isTaskEditorMaximized
2372
+ ? "project-template-assistant-expand-button"
2373
+ : undefined, expandButtonClassName: cn("border-border-default absolute right-4 z-50 h-8 w-8 rounded-md bg-white p-0 text-neutral-grey-100 shadow-sm backdrop-blur-sm hover:bg-white hover:text-neutral-grey-100 md:p-0", isTaskEditorMaximized ? "top-4" : "hidden"), forceCollapseLastPanelKey: forceCollapseLastPanelKey, forceExpandLastPanelKey: forceExpandLastPanelKey, onLastPanelCollapsedChange: setIsAgentPanelCollapsed }) }) }), _jsx(Dialog, { open: isCreateTaskDialogOpen, onOpenChange: (open) => {
1915
2374
  setIsCreateTaskDialogOpen(open);
1916
2375
  if (!open) {
1917
2376
  setNewTaskDependencySourceId(null);
@@ -1929,7 +2388,12 @@ export function ProjectTemplatesPanel() {
1929
2388
  ? "Creating..."
1930
2389
  : newTaskDependencySourceId
1931
2390
  ? "Create Dependent Task"
1932
- : "Create Task" })] })] }) }), _jsx(Dialog, { open: isAddChildTaskDialogOpen, onOpenChange: setIsAddChildTaskDialogOpen, children: _jsxs(DialogContent, { className: "max-w-md", "data-testid": "project-template-create-child-task-dialog", children: [_jsx(StyledDialogTitle, { icon: _jsx(Plus, { strokeWidth: 1.5 }), title: "Add Child Task", subtitle: "Creates a new task that depends on the current task." }), _jsxs("div", { className: "grid gap-2 p-6", children: [_jsx(Label, { className: "text-xs", htmlFor: "project-template-new-child-task-title", children: "Task title" }), _jsx(Input, { id: "project-template-new-child-task-title", value: newChildTaskTitle, onChange: (event) => setNewChildTaskTitle(event.target.value), placeholder: "e.g. Review content", className: "text-xs md:text-xs", autoFocus: true, onKeyDown: (event) => {
2391
+ : "Create Task" })] })] }) }), _jsx(Dialog, { open: isCreateGoalDialogOpen, onOpenChange: setIsCreateGoalDialogOpen, children: _jsxs(DialogContent, { className: "max-w-md", "data-testid": "project-template-create-goal-dialog", children: [_jsx(StyledDialogTitle, { icon: _jsx(Plus, { strokeWidth: 1.5 }), title: "Add Goal Definition", subtitle: "Create the goal and save it immediately." }), _jsxs("div", { className: "grid gap-2 p-6", children: [_jsx(Label, { className: "text-xs", htmlFor: "project-template-new-goal-title", children: "Goal title" }), _jsx(Input, { id: "project-template-new-goal-title", value: newGoalTitle, onChange: (event) => setNewGoalTitle(event.target.value), placeholder: "e.g. Review all pages", className: "text-xs md:text-xs", autoFocus: true, onKeyDown: (event) => {
2392
+ if (event.key === "Enter" && !event.shiftKey) {
2393
+ event.preventDefault();
2394
+ void handleConfirmCreateGoal();
2395
+ }
2396
+ } })] }), _jsxs(DialogFooter, { className: "px-6 pt-0 pb-6", children: [_jsx(Button, { variant: "outline", onClick: () => setIsCreateGoalDialogOpen(false), disabled: creatingGoal, "data-testid": "project-template-create-goal-cancel-button", children: "Cancel" }), _jsx(Button, { onClick: () => void handleConfirmCreateGoal(), disabled: creatingGoal || !newGoalTitle.trim(), "data-testid": "project-template-create-goal-submit-button", children: creatingGoal ? "Creating..." : "Create Goal" })] })] }) }), _jsx(Dialog, { open: isAddChildTaskDialogOpen, onOpenChange: setIsAddChildTaskDialogOpen, children: _jsxs(DialogContent, { className: "max-w-md", "data-testid": "project-template-create-child-task-dialog", children: [_jsx(StyledDialogTitle, { icon: _jsx(Plus, { strokeWidth: 1.5 }), title: "Add Child Task", subtitle: "Creates a new task that depends on the current task." }), _jsxs("div", { className: "grid gap-2 p-6", children: [_jsx(Label, { className: "text-xs", htmlFor: "project-template-new-child-task-title", children: "Task title" }), _jsx(Input, { id: "project-template-new-child-task-title", value: newChildTaskTitle, onChange: (event) => setNewChildTaskTitle(event.target.value), placeholder: "e.g. Review content", className: "text-xs md:text-xs", autoFocus: true, onKeyDown: (event) => {
1933
2397
  if (event.key === "Enter" && !event.shiftKey) {
1934
2398
  event.preventDefault();
1935
2399
  void handleConfirmCreateChildTask();