@codingame/monaco-vscode-workbench-service-override 37.6.1 → 38.0.0

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 (323) hide show
  1. package/common.js +2 -0
  2. package/index.js +9 -10
  3. package/package.json +10 -10
  4. package/session.js +45 -42
  5. package/vscode/src/vs/platform/agentHost/common/sessionComparisonPrompts.d.ts +1 -0
  6. package/vscode/src/vs/platform/agentHost/common/sessionComparisonPrompts.js +12 -0
  7. package/vscode/src/vs/sessions/browser/{singlePaneWorkbench.d.ts → desktopWorkbench.d.ts} +6 -5
  8. package/vscode/src/vs/sessions/browser/{singlePaneWorkbench.js → desktopWorkbench.js} +23 -25
  9. package/vscode/src/vs/sessions/browser/dockedAuxiliaryBarController.d.ts +5 -2
  10. package/vscode/src/vs/sessions/browser/dockedAuxiliaryBarController.js +41 -3
  11. package/vscode/src/vs/sessions/browser/layoutActions.js +25 -41
  12. package/vscode/src/vs/sessions/browser/mobileWorkbench.d.ts +4 -0
  13. package/vscode/src/vs/sessions/browser/mobileWorkbench.js +10 -0
  14. package/vscode/src/vs/sessions/browser/parts/chatCompositeBar.d.ts +10 -5
  15. package/vscode/src/vs/sessions/browser/parts/chatCompositeBar.js +138 -34
  16. package/vscode/src/vs/sessions/browser/parts/chatGroupDropTarget.d.ts +2 -0
  17. package/vscode/src/vs/sessions/browser/parts/chatGroupDropTarget.js +13 -5
  18. package/vscode/src/vs/sessions/browser/parts/chatGroupView.d.ts +27 -5
  19. package/vscode/src/vs/sessions/browser/parts/chatGroupView.js +129 -28
  20. package/vscode/src/vs/sessions/browser/parts/chatGroupsView.d.ts +22 -7
  21. package/vscode/src/vs/sessions/browser/parts/chatGroupsView.js +260 -21
  22. package/vscode/src/vs/sessions/browser/parts/chatHeader.d.ts +25 -0
  23. package/vscode/src/vs/sessions/browser/parts/chatHeader.js +42 -0
  24. package/vscode/src/vs/sessions/browser/parts/customViewGridPart.js +9 -1
  25. package/vscode/src/vs/sessions/browser/parts/customViewNode.js +1 -1
  26. package/vscode/src/vs/sessions/browser/parts/{singlePaneAuxiliaryBarPart.d.ts → desktopAuxiliaryBarPart.d.ts} +4 -4
  27. package/vscode/src/vs/sessions/browser/parts/desktopAuxiliaryBarPart.js +26 -0
  28. package/vscode/src/vs/sessions/browser/parts/{singlePaneEditorPart.d.ts → desktopEditorPart.d.ts} +8 -6
  29. package/vscode/src/vs/sessions/browser/parts/{singlePaneEditorPart.js → desktopEditorPart.js} +25 -5
  30. package/vscode/src/vs/sessions/browser/parts/editorPart.js +16 -4
  31. package/vscode/src/vs/sessions/browser/parts/editorParts.d.ts +1 -1
  32. package/vscode/src/vs/sessions/browser/parts/editorParts.js +7 -6
  33. package/vscode/src/vs/sessions/browser/parts/gridGap.d.ts +14 -0
  34. package/vscode/src/vs/sessions/browser/parts/gridGap.js +69 -0
  35. package/vscode/src/vs/sessions/browser/parts/media/chatCompositeBar.css +132 -4
  36. package/vscode/src/vs/sessions/browser/parts/media/chatGroupsView.css +10 -0
  37. package/vscode/src/vs/sessions/browser/parts/media/editorPart.css +46 -2
  38. package/vscode/src/vs/sessions/browser/parts/media/sessionReadOnlyBanner.css +3 -3
  39. package/vscode/src/vs/sessions/browser/parts/media/sessionView.css +45 -48
  40. package/vscode/src/vs/sessions/browser/parts/media/sessionsPart.css +15 -0
  41. package/vscode/src/vs/sessions/browser/parts/menubar.contribution.js +8 -8
  42. package/vscode/src/vs/sessions/browser/parts/mobile/mobileSessionsPart.js +1 -1
  43. package/vscode/src/vs/sessions/browser/parts/remoteHostUnavailableEmptyState.d.ts +9 -1
  44. package/vscode/src/vs/sessions/browser/parts/remoteHostUnavailableEmptyState.js +21 -3
  45. package/vscode/src/vs/sessions/browser/parts/sessionBarStyles.js +1 -1
  46. package/vscode/src/vs/sessions/browser/parts/sessionDropTarget.d.ts +4 -3
  47. package/vscode/src/vs/sessions/browser/parts/sessionDropTarget.js +29 -15
  48. package/vscode/src/vs/sessions/browser/parts/sessionGridLayout.d.ts +67 -0
  49. package/vscode/src/vs/sessions/browser/parts/sessionGridLayout.js +598 -0
  50. package/vscode/src/vs/sessions/browser/parts/sessionHeader.d.ts +11 -84
  51. package/vscode/src/vs/sessions/browser/parts/sessionHeader.js +37 -317
  52. package/vscode/src/vs/sessions/browser/parts/sessionHeaderBar.d.ts +103 -0
  53. package/vscode/src/vs/sessions/browser/parts/sessionHeaderBar.js +391 -0
  54. package/vscode/src/vs/sessions/browser/parts/sessionReadOnlyBanner.d.ts +6 -4
  55. package/vscode/src/vs/sessions/browser/parts/sessionReadOnlyBanner.js +58 -28
  56. package/vscode/src/vs/sessions/browser/parts/sessionRemoteConnection.d.ts +4 -0
  57. package/vscode/src/vs/sessions/browser/parts/sessionRemoteConnection.js +66 -23
  58. package/vscode/src/vs/sessions/browser/parts/sessionView.d.ts +24 -5
  59. package/vscode/src/vs/sessions/browser/parts/sessionView.js +143 -33
  60. package/vscode/src/vs/sessions/browser/parts/sessionsPart.d.ts +25 -19
  61. package/vscode/src/vs/sessions/browser/parts/sessionsPart.js +157 -58
  62. package/vscode/src/vs/sessions/browser/parts/sessionsParts.d.ts +12 -3
  63. package/vscode/src/vs/sessions/browser/parts/sessionsParts.js +17 -2
  64. package/vscode/src/vs/sessions/browser/sessionWorkspace.d.ts +6 -3
  65. package/vscode/src/vs/sessions/browser/sessionWorkspace.js +2 -2
  66. package/vscode/src/vs/sessions/browser/sessionsSetUpService.js +66 -20
  67. package/vscode/src/vs/sessions/browser/sessionsSignInDialog.d.ts +1 -0
  68. package/vscode/src/vs/sessions/browser/sessionsSignInDialog.js +5 -4
  69. package/vscode/src/vs/sessions/browser/workbenchFactory.d.ts +12 -0
  70. package/vscode/src/vs/sessions/browser/workbenchFactory.js +17 -0
  71. package/vscode/src/vs/sessions/contrib/accountMenu/browser/account.contribution.d.ts +85 -1
  72. package/vscode/src/vs/sessions/contrib/accountMenu/browser/account.contribution.js +118 -100
  73. package/vscode/src/vs/sessions/contrib/accountMenu/browser/chatPetAchievementBadges.d.ts +3 -2
  74. package/vscode/src/vs/sessions/contrib/accountMenu/browser/chatPetAchievementBadges.js +39 -34
  75. package/vscode/src/vs/sessions/contrib/accountMenu/browser/media/accountTitleBarWidget.css +6 -0
  76. package/vscode/src/vs/sessions/contrib/agentFeedback/browser/nullAgentFeedbackService.contribution.d.ts +3 -0
  77. package/vscode/src/vs/sessions/contrib/agentFeedback/browser/nullAgentFeedbackService.contribution.js +6 -0
  78. package/vscode/src/vs/sessions/contrib/aiCustomizationTreeView/browser/aiCustomizationTreeView.contribution.js +18 -18
  79. package/vscode/src/vs/sessions/contrib/aiCustomizationTreeView/browser/aiCustomizationTreeViewViews.js +12 -12
  80. package/vscode/src/vs/sessions/contrib/applyCommitsToParentRepo/browser/applyChangesToParentRepo.js +7 -7
  81. package/vscode/src/vs/sessions/contrib/aquarium/browser/aquarium.contribution.js +12 -12
  82. package/vscode/src/vs/sessions/contrib/aquarium/browser/aquariumOverlay.js +10 -10
  83. package/vscode/src/vs/sessions/contrib/automations/browser/automationDialog.d.ts +78 -8
  84. package/vscode/src/vs/sessions/contrib/automations/browser/automationDialog.js +1166 -202
  85. package/vscode/src/vs/sessions/contrib/automations/browser/automationDialogService.d.ts +11 -1
  86. package/vscode/src/vs/sessions/contrib/automations/browser/automationDialogService.js +190 -69
  87. package/vscode/src/vs/sessions/contrib/automations/browser/automationRunner.d.ts +11 -9
  88. package/vscode/src/vs/sessions/contrib/automations/browser/automationRunner.js +122 -233
  89. package/vscode/src/vs/sessions/contrib/automations/browser/automationTelemetry.d.ts +22 -0
  90. package/vscode/src/vs/sessions/contrib/automations/browser/automationTelemetry.js +62 -0
  91. package/vscode/src/vs/sessions/contrib/automations/browser/automationTools.d.ts +7 -2
  92. package/vscode/src/vs/sessions/contrib/automations/browser/automationTools.js +172 -84
  93. package/vscode/src/vs/sessions/contrib/automations/browser/automations.contribution.js +17 -7
  94. package/vscode/src/vs/sessions/contrib/automations/browser/media/automationDialog.css +242 -60
  95. package/vscode/src/vs/sessions/contrib/automations/browser/providerAutomationService.d.ts +24 -36
  96. package/vscode/src/vs/sessions/contrib/automations/browser/providerAutomationService.js +104 -420
  97. package/vscode/src/vs/sessions/contrib/changes/browser/changes.contribution.js +15 -14
  98. package/vscode/src/vs/sessions/contrib/changes/browser/changesActions.d.ts +13 -3
  99. package/vscode/src/vs/sessions/contrib/changes/browser/changesActions.js +66 -43
  100. package/vscode/src/vs/sessions/contrib/changes/browser/changesMultiDiffSourceResolver.js +2 -7
  101. package/vscode/src/vs/sessions/contrib/changes/browser/changesViewActions.js +54 -59
  102. package/vscode/src/vs/sessions/contrib/changes/browser/changesetReviewActions.js +7 -7
  103. package/vscode/src/vs/sessions/contrib/changes/browser/media/changesActions.css +6 -0
  104. package/vscode/src/vs/sessions/contrib/changes/browser/sessionSyncChanges.js +25 -21
  105. package/vscode/src/vs/sessions/contrib/changes/browser/sessionsChangesAccessibilityHelp.js +21 -27
  106. package/vscode/src/vs/sessions/contrib/chat/browser/sessionChatInputToolbarDebug.js +17 -17
  107. package/vscode/src/vs/sessions/contrib/chat/browser/sessionTaskRunner.d.ts +5 -5
  108. package/vscode/src/vs/sessions/contrib/chat/browser/sessionTaskRunner.js +2 -2
  109. package/vscode/src/vs/sessions/contrib/chatDebug/browser/chatDebug.contribution.js +2 -2
  110. package/vscode/src/vs/sessions/contrib/codeReview/browser/codeReview.contributions.js +9 -16
  111. package/vscode/src/vs/sessions/contrib/customViewTest/browser/customViewTest.contribution.js +7 -7
  112. package/vscode/src/vs/sessions/contrib/editor/browser/addTabActions.js +10 -10
  113. package/vscode/src/vs/sessions/contrib/editor/browser/editor.contribution.d.ts +13 -1
  114. package/vscode/src/vs/sessions/contrib/editor/browser/editor.contribution.js +104 -117
  115. package/vscode/src/vs/sessions/contrib/editor/browser/emptyFileEditor.contribution.js +8 -7
  116. package/vscode/src/vs/sessions/contrib/editor/browser/emptyFileEditor.js +5 -5
  117. package/vscode/src/vs/sessions/contrib/editor/browser/emptyFileEditorInput.js +1 -1
  118. package/vscode/src/vs/sessions/contrib/editor/browser/media/editorBreadcrumbs.css +0 -1
  119. package/vscode/src/vs/sessions/contrib/editor/browser/media/editorHeader.css +1 -1
  120. package/vscode/src/vs/sessions/contrib/files/browser/files.contribution.d.ts +7 -0
  121. package/vscode/src/vs/sessions/contrib/files/browser/files.contribution.js +77 -13
  122. package/vscode/src/vs/sessions/contrib/files/browser/filesView.d.ts +2 -1
  123. package/vscode/src/vs/sessions/contrib/files/browser/filesView.js +14 -4
  124. package/vscode/src/vs/sessions/contrib/layout/browser/baseSessionLayoutController.d.ts +45 -10
  125. package/vscode/src/vs/sessions/contrib/layout/browser/baseSessionLayoutController.js +527 -77
  126. package/vscode/src/vs/sessions/contrib/layout/browser/chatLayoutOwnerKeys.d.ts +18 -0
  127. package/vscode/src/vs/sessions/contrib/layout/browser/chatLayoutOwnerKeys.js +95 -0
  128. package/vscode/src/vs/sessions/contrib/layout/browser/{singlePane/singlePaneDetailPanelCoordinator.d.ts → desktop/desktopDetailPanelCoordinator.d.ts} +5 -4
  129. package/vscode/src/vs/sessions/contrib/layout/browser/{singlePane/singlePaneDetailPanelCoordinator.js → desktop/desktopDetailPanelCoordinator.js} +10 -7
  130. package/vscode/src/vs/sessions/contrib/layout/browser/{singlePane/singlePaneDockedTabsCoordinator.d.ts → desktop/desktopDockedTabsCoordinator.d.ts} +15 -12
  131. package/vscode/src/vs/sessions/contrib/layout/browser/{singlePane/singlePaneDockedTabsCoordinator.js → desktop/desktopDockedTabsCoordinator.js} +91 -44
  132. package/vscode/src/vs/sessions/contrib/layout/browser/{singlePane/singlePaneDraftSessionStrategy.d.ts → desktop/desktopDraftSessionStrategy.d.ts} +10 -5
  133. package/vscode/src/vs/sessions/contrib/layout/browser/{singlePane/singlePaneDraftSessionStrategy.js → desktop/desktopDraftSessionStrategy.js} +95 -22
  134. package/vscode/src/vs/sessions/contrib/layout/browser/{singlePane/singlePaneExistingSessionStrategy.d.ts → desktop/desktopExistingSessionStrategy.d.ts} +13 -11
  135. package/vscode/src/vs/sessions/contrib/layout/browser/{singlePane/singlePaneExistingSessionStrategy.js → desktop/desktopExistingSessionStrategy.js} +137 -57
  136. package/vscode/src/vs/sessions/contrib/layout/browser/{singlePane/singlePaneLayoutStrategy.d.ts → desktop/desktopLayoutStrategy.d.ts} +22 -13
  137. package/vscode/src/vs/sessions/contrib/layout/browser/{singlePane/singlePaneLayoutStrategy.js → desktop/desktopLayoutStrategy.js} +2 -2
  138. package/vscode/src/vs/sessions/contrib/layout/browser/desktop/desktopOwnerCompositionStore.d.ts +22 -0
  139. package/vscode/src/vs/sessions/contrib/layout/browser/desktop/desktopOwnerCompositionStore.js +136 -0
  140. package/vscode/src/vs/sessions/contrib/layout/browser/{singlePane/singlePaneSharedHelpers.d.ts → desktop/desktopSharedHelpers.d.ts} +9 -2
  141. package/vscode/src/vs/sessions/contrib/layout/browser/desktop/desktopSharedHelpers.js +56 -0
  142. package/vscode/src/vs/sessions/contrib/layout/browser/{singlePane/singlePaneVisibilityProfileStore.d.ts → desktop/desktopVisibilityProfileStore.d.ts} +3 -2
  143. package/vscode/src/vs/sessions/contrib/layout/browser/{singlePane/singlePaneVisibilityProfileStore.js → desktop/desktopVisibilityProfileStore.js} +10 -9
  144. package/vscode/src/vs/sessions/contrib/layout/browser/desktopLayoutController.d.ts +71 -0
  145. package/vscode/src/vs/sessions/contrib/layout/browser/desktopLayoutController.js +201 -0
  146. package/vscode/src/vs/sessions/contrib/layout/browser/sessions.layout.contribution.d.ts +8 -1
  147. package/vscode/src/vs/sessions/contrib/layout/browser/sessions.layout.contribution.js +35 -35
  148. package/vscode/src/vs/sessions/contrib/layout/common/sessionEditorWorkingSet.d.ts +39 -0
  149. package/vscode/src/vs/sessions/contrib/layout/common/sessionEditorWorkingSet.js +73 -0
  150. package/vscode/src/vs/sessions/contrib/onboardingTours/browser/newSessionTourContribution.d.ts +42 -1
  151. package/vscode/src/vs/sessions/contrib/onboardingTours/browser/newSessionTourContribution.js +14 -10
  152. package/vscode/src/vs/sessions/contrib/onboardingTours/browser/newSessionViewTourContribution.js +3 -4
  153. package/vscode/src/vs/sessions/contrib/onboardingTours/browser/newSessionViewTourTrigger.d.ts +2 -2
  154. package/vscode/src/vs/sessions/contrib/onboardingTours/browser/newSessionViewTourTrigger.js +13 -9
  155. package/vscode/src/vs/sessions/contrib/onboardingTours/browser/newSessionViewV2TourContribution.js +20 -5
  156. package/vscode/src/vs/sessions/contrib/onboardingTours/browser/newSessionViewV2TourVariation.d.ts +8 -0
  157. package/vscode/src/vs/sessions/contrib/onboardingTours/browser/newSessionViewV2TourVariation.js +19 -0
  158. package/vscode/src/vs/sessions/contrib/onboardingTours/browser/newSessionViewV3Prompt.js +21 -20
  159. package/vscode/src/vs/sessions/contrib/onboardingTours/browser/tours/newSessionTour.js +10 -5
  160. package/vscode/src/vs/sessions/contrib/onboardingTours/browser/tours/newSessionViewTour.js +12 -8
  161. package/vscode/src/vs/sessions/contrib/onboardingTours/browser/tours/newSessionViewTourShared.d.ts +3 -1
  162. package/vscode/src/vs/sessions/contrib/onboardingTours/browser/tours/newSessionViewTourShared.js +12 -7
  163. package/vscode/src/vs/sessions/contrib/onboardingTours/browser/tours/newSessionViewV2Tour.d.ts +9 -1
  164. package/vscode/src/vs/sessions/contrib/onboardingTours/browser/tours/newSessionViewV2Tour.js +46 -19
  165. package/vscode/src/vs/sessions/contrib/onboardingTours/browser/tours/newSessionViewV3Tour.js +2 -0
  166. package/vscode/src/vs/sessions/contrib/policyBlocked/browser/media/sessionsPolicyBlocked.css +33 -0
  167. package/vscode/src/vs/sessions/contrib/policyBlocked/browser/policyBlocked.contribution.d.ts +4 -2
  168. package/vscode/src/vs/sessions/contrib/policyBlocked/browser/policyBlocked.contribution.js +29 -8
  169. package/vscode/src/vs/sessions/contrib/policyBlocked/browser/sessionsPolicyBlocked.d.ts +15 -2
  170. package/vscode/src/vs/sessions/contrib/policyBlocked/browser/sessionsPolicyBlocked.js +169 -32
  171. package/vscode/src/vs/sessions/contrib/providers/agentHost/browser/agentHostForkActions.js +30 -8
  172. package/vscode/src/vs/sessions/contrib/providers/agentHost/browser/agentHostSessionBranchActions.js +8 -34
  173. package/vscode/src/vs/sessions/contrib/providers/agentHost/browser/agentMergeActions.js +63 -49
  174. package/vscode/src/vs/sessions/contrib/providers/agentHost/browser/exportDebugLogsAction.js +1 -1
  175. package/vscode/src/vs/sessions/contrib/providers/agentHost/browser/mobile/mobileChatInputConfigPicker.js +31 -17
  176. package/vscode/src/vs/sessions/contrib/providers/remoteAgentHost/browser/connectionDiagnostics.contribution.d.ts +32 -0
  177. package/vscode/src/vs/sessions/contrib/providers/remoteAgentHost/browser/connectionDiagnostics.contribution.js +250 -0
  178. package/vscode/src/vs/sessions/contrib/providers/remoteAgentHost/browser/connectionDiagnosticsLogs.d.ts +6 -0
  179. package/vscode/src/vs/sessions/contrib/providers/remoteAgentHost/browser/connectionDiagnosticsLogs.js +52 -0
  180. package/vscode/src/vs/sessions/contrib/providers/remoteAgentHost/browser/connectionDiagnosticsReport.d.ts +51 -0
  181. package/vscode/src/vs/sessions/contrib/providers/remoteAgentHost/browser/connectionDiagnosticsReport.js +439 -0
  182. package/vscode/src/vs/sessions/contrib/providers/remoteAgentHost/browser/connectionDiagnosticsService.d.ts +45 -0
  183. package/vscode/src/vs/sessions/contrib/providers/remoteAgentHost/browser/connectionDiagnosticsService.js +595 -0
  184. package/vscode/src/vs/sessions/contrib/providers/remoteAgentHost/browser/devContainerAgentHostService.d.ts +20 -3
  185. package/vscode/src/vs/sessions/contrib/providers/remoteAgentHost/browser/devContainerAgentHostService.js +360 -46
  186. package/vscode/src/vs/sessions/contrib/providers/remoteAgentHost/browser/devContainerSource.d.ts +9 -0
  187. package/vscode/src/vs/sessions/contrib/providers/remoteAgentHost/browser/devContainerSource.js +59 -0
  188. package/vscode/src/vs/sessions/contrib/providers/remoteAgentHost/browser/media/connectionDiagnostics.css +201 -0
  189. package/vscode/src/vs/sessions/contrib/remoteSessions/browser/getRemoteSessionTool.d.ts +10 -0
  190. package/vscode/src/vs/sessions/contrib/remoteSessions/browser/getRemoteSessionTool.js +70 -0
  191. package/vscode/src/vs/sessions/contrib/remoteSessions/browser/remoteSessionChatService.d.ts +20 -0
  192. package/vscode/src/vs/sessions/contrib/remoteSessions/browser/remoteSessionChatService.js +104 -0
  193. package/vscode/src/vs/sessions/contrib/remoteSessions/browser/remoteSessionInspector.d.ts +15 -0
  194. package/vscode/src/vs/sessions/contrib/remoteSessions/browser/remoteSessionInspector.js +152 -0
  195. package/vscode/src/vs/sessions/contrib/remoteSessions/browser/remoteSessionMessageRouter.d.ts +49 -0
  196. package/vscode/src/vs/sessions/contrib/remoteSessions/browser/remoteSessionMessageRouter.js +340 -0
  197. package/vscode/src/vs/sessions/contrib/remoteSessions/browser/remoteSessionService.d.ts +41 -0
  198. package/vscode/src/vs/sessions/contrib/remoteSessions/browser/remoteSessionService.js +400 -0
  199. package/vscode/src/vs/sessions/contrib/remoteSessions/browser/remoteSessionSource.d.ts +28 -0
  200. package/vscode/src/vs/sessions/contrib/remoteSessions/browser/remoteSessionSource.js +178 -0
  201. package/vscode/src/vs/sessions/contrib/remoteSessions/browser/remoteSessionTools.d.ts +17 -0
  202. package/vscode/src/vs/sessions/contrib/remoteSessions/browser/remoteSessionTools.js +206 -0
  203. package/vscode/src/vs/sessions/contrib/remoteSessions/browser/remoteSessions.contribution.d.ts +1 -0
  204. package/vscode/src/vs/sessions/contrib/remoteSessions/browser/remoteSessions.contribution.js +58 -0
  205. package/vscode/src/vs/sessions/contrib/remoteSessions/browser/sendRemoteMessageTool.d.ts +10 -0
  206. package/vscode/src/vs/sessions/contrib/remoteSessions/browser/sendRemoteMessageTool.js +90 -0
  207. package/vscode/src/vs/sessions/contrib/remoteSessions/common/remoteSessionInspection.d.ts +38 -0
  208. package/vscode/src/vs/sessions/contrib/remoteSessions/common/remoteSessionInspection.js +58 -0
  209. package/vscode/src/vs/sessions/contrib/search/browser/search.contribution.js +4 -5
  210. package/vscode/src/vs/sessions/contrib/search/browser/searchEditorEmptyState.contribution.js +1 -1
  211. package/vscode/src/vs/sessions/contrib/sessionComparison/browser/sessionComparison.contribution.d.ts +1 -0
  212. package/vscode/src/vs/sessions/contrib/sessionComparison/browser/sessionComparison.contribution.js +33 -0
  213. package/vscode/src/vs/sessions/contrib/sessionComparison/browser/sessionComparisonGridController.d.ts +30 -0
  214. package/vscode/src/vs/sessions/contrib/sessionComparison/browser/sessionComparisonGridController.js +190 -0
  215. package/vscode/src/vs/sessions/contrib/sessionComparison/browser/sessionComparisonTool.d.ts +31 -0
  216. package/vscode/src/vs/sessions/contrib/sessionComparison/browser/sessionComparisonTool.js +559 -0
  217. package/vscode/src/vs/sessions/contrib/sessionComparison/browser/sessionComparisonViewService.d.ts +12 -0
  218. package/vscode/src/vs/sessions/contrib/sessionComparison/browser/sessionComparisonViewService.js +38 -0
  219. package/vscode/src/vs/sessions/contrib/sessions/browser/blockedSessionsIndicatorModel.d.ts +13 -4
  220. package/vscode/src/vs/sessions/contrib/sessions/browser/blockedSessionsIndicatorModel.js +155 -22
  221. package/vscode/src/vs/sessions/contrib/sessions/browser/blockedSessionsList.js +9 -5
  222. package/vscode/src/vs/sessions/contrib/sessions/browser/media/automationsCards.css +90 -25
  223. package/vscode/src/vs/sessions/contrib/sessions/browser/media/sessionsTitleBarWidget.css +21 -4
  224. package/vscode/src/vs/sessions/contrib/sessions/browser/sessionDetailsAction.d.ts +2 -1
  225. package/vscode/src/vs/sessions/contrib/sessions/browser/sessionDetailsAction.js +11 -7
  226. package/vscode/src/vs/sessions/contrib/sessions/browser/sessions.contribution.d.ts +116 -1
  227. package/vscode/src/vs/sessions/contrib/sessions/browser/sessions.contribution.js +126 -30
  228. package/vscode/src/vs/sessions/contrib/sessions/browser/sessionsAccountTelemetry.d.ts +26 -0
  229. package/vscode/src/vs/sessions/contrib/sessions/browser/sessionsAccountTelemetry.js +160 -0
  230. package/vscode/src/vs/sessions/contrib/sessions/browser/sessionsActions.d.ts +14 -6
  231. package/vscode/src/vs/sessions/contrib/sessions/browser/sessionsActions.js +555 -151
  232. package/vscode/src/vs/sessions/contrib/sessions/browser/sessionsLifecycleTracker.d.ts +192 -0
  233. package/vscode/src/vs/sessions/contrib/sessions/browser/sessionsLifecycleTracker.js +510 -0
  234. package/vscode/src/vs/sessions/contrib/sessions/browser/sessionsTelemetry.contribution.d.ts +6 -7
  235. package/vscode/src/vs/sessions/contrib/sessions/browser/sessionsTelemetry.contribution.js +64 -57
  236. package/vscode/src/vs/sessions/contrib/sessions/browser/sessionsTitleBarWidget.d.ts +5 -3
  237. package/vscode/src/vs/sessions/contrib/sessions/browser/sessionsTitleBarWidget.js +83 -51
  238. package/vscode/src/vs/sessions/contrib/sessions/browser/sessionsWindowNotifier.d.ts +5 -1
  239. package/vscode/src/vs/sessions/contrib/sessions/browser/sessionsWindowNotifier.js +33 -12
  240. package/vscode/src/vs/sessions/contrib/sessions/browser/views/automationCataloguePresentation.d.ts +3 -0
  241. package/vscode/src/vs/sessions/contrib/sessions/browser/views/automationCataloguePresentation.js +53 -0
  242. package/vscode/src/vs/sessions/contrib/sessions/browser/views/automationTemplates.js +10 -10
  243. package/vscode/src/vs/sessions/contrib/sessions/browser/views/automationsAccessibility.d.ts +2 -2
  244. package/vscode/src/vs/sessions/contrib/sessions/browser/views/automationsAccessibility.js +103 -55
  245. package/vscode/src/vs/sessions/contrib/sessions/browser/views/automationsView.d.ts +7 -1
  246. package/vscode/src/vs/sessions/contrib/sessions/browser/views/automationsView.js +679 -325
  247. package/vscode/src/vs/sessions/contrib/sessions/browser/views/sessionsViewActions.d.ts +27 -1
  248. package/vscode/src/vs/sessions/contrib/sessions/browser/views/sessionsViewActions.js +508 -163
  249. package/vscode/src/vs/sessions/contrib/terminal/browser/agentHostSessionTaskRunner.d.ts +20 -2
  250. package/vscode/src/vs/sessions/contrib/terminal/browser/agentHostSessionTaskRunner.js +100 -17
  251. package/vscode/src/vs/sessions/contrib/terminal/browser/sessionsTerminalContribution.d.ts +5 -1
  252. package/vscode/src/vs/sessions/contrib/terminal/browser/sessionsTerminalContribution.js +108 -30
  253. package/vscode/src/vs/sessions/contrib/workspace/browser/workspaceFolderManagement.d.ts +5 -3
  254. package/vscode/src/vs/sessions/contrib/workspace/browser/workspaceFolderManagement.js +47 -35
  255. package/vscode/src/vs/sessions/services/agentHostFilter/browser/agentHostFilterService.d.ts +9 -4
  256. package/vscode/src/vs/sessions/services/agentHostFilter/browser/agentHostFilterService.js +75 -25
  257. package/vscode/src/vs/sessions/services/customView/browser/customViewService.d.ts +11 -4
  258. package/vscode/src/vs/sessions/services/customView/browser/customViewService.js +17 -9
  259. package/vscode/src/vs/sessions/services/sessions/browser/closedItemHistory.d.ts +5 -0
  260. package/vscode/src/vs/sessions/services/sessions/browser/closedItemHistory.js +20 -2
  261. package/vscode/src/vs/sessions/services/sessions/browser/sessionComparisonService.d.ts +75 -0
  262. package/vscode/src/vs/sessions/services/sessions/browser/sessionComparisonService.js +1135 -0
  263. package/vscode/src/vs/sessions/services/sessions/browser/sessionGridState.d.ts +17 -0
  264. package/vscode/src/vs/sessions/services/sessions/browser/sessionGridState.js +99 -0
  265. package/vscode/src/vs/sessions/services/sessions/browser/sessionGroupsService.d.ts +4 -0
  266. package/vscode/src/vs/sessions/services/sessions/browser/sessionGroupsService.js +88 -23
  267. package/vscode/src/vs/sessions/services/sessions/browser/sessionNavigation.d.ts +19 -26
  268. package/vscode/src/vs/sessions/services/sessions/browser/sessionNavigation.js +115 -74
  269. package/vscode/src/vs/sessions/services/sessions/browser/sessionsListModelService.js +1 -1
  270. package/vscode/src/vs/sessions/services/sessions/browser/sessionsManagementService.d.ts +22 -7
  271. package/vscode/src/vs/sessions/services/sessions/browser/sessionsManagementService.js +278 -60
  272. package/vscode/src/vs/sessions/services/sessions/browser/sessionsRecencyHistory.d.ts +17 -20
  273. package/vscode/src/vs/sessions/services/sessions/browser/sessionsRecencyHistory.js +33 -22
  274. package/vscode/src/vs/sessions/services/sessions/browser/sessionsService.d.ts +28 -8
  275. package/vscode/src/vs/sessions/services/sessions/browser/sessionsService.js +673 -160
  276. package/vscode/src/vs/sessions/services/sessions/browser/visibleSessions.d.ts +13 -4
  277. package/vscode/src/vs/sessions/services/sessions/browser/visibleSessions.js +105 -15
  278. package/vscode/src/vs/sessions/services/sessions/common/sessionContextKeys.js +53 -34
  279. package/vscode/src/vs/sessions/services/workspaceFolderLabel/browser/workspaceFolderLabelService.js +1 -1
  280. package/vscode/src/vs/workbench/browser/layout.js +1 -1
  281. package/vscode/src/vs/workbench/browser/workbench.d.ts +0 -2
  282. package/vscode/src/vs/workbench/browser/workbench.js +23 -20
  283. package/vscode/src/vs/workbench/contrib/chat/common/automations/schedule.d.ts +6 -0
  284. package/vscode/src/vs/workbench/contrib/chat/common/automations/schedule.js +41 -0
  285. package/vscode/src/vs/workbench/contrib/chat/common/chatUsage.d.ts +15 -0
  286. package/vscode/src/vs/workbench/contrib/chat/common/chatUsage.js +56 -0
  287. package/vscode/src/vs/platform/agentHost/common/meta/agentCheckoutOperationMeta.d.ts +0 -18
  288. package/vscode/src/vs/platform/agentHost/common/meta/agentCheckoutOperationMeta.js +0 -27
  289. package/vscode/src/vs/sessions/browser/parts/singlePaneAuxiliaryBarPart.js +0 -36
  290. package/vscode/src/vs/sessions/contrib/automations/browser/automationLeaderElection.d.ts +0 -37
  291. package/vscode/src/vs/sessions/contrib/automations/browser/automationLeaderElection.js +0 -126
  292. package/vscode/src/vs/sessions/contrib/automations/browser/automationScheduler.d.ts +0 -59
  293. package/vscode/src/vs/sessions/contrib/automations/browser/automationScheduler.js +0 -232
  294. package/vscode/src/vs/sessions/contrib/automations/browser/automationStorageService.d.ts +0 -13
  295. package/vscode/src/vs/sessions/contrib/automations/browser/automationStorageService.js +0 -22
  296. package/vscode/src/vs/sessions/contrib/blockedSessions/browser/blockedSessions.d.ts +0 -45
  297. package/vscode/src/vs/sessions/contrib/blockedSessions/browser/blockedSessions.js +0 -110
  298. package/vscode/src/vs/sessions/contrib/layout/browser/desktopSessionLayoutController.d.ts +0 -112
  299. package/vscode/src/vs/sessions/contrib/layout/browser/desktopSessionLayoutController.js +0 -444
  300. package/vscode/src/vs/sessions/contrib/layout/browser/singlePane/singlePaneSharedHelpers.js +0 -43
  301. package/vscode/src/vs/sessions/contrib/layout/browser/singlePaneLayoutController.d.ts +0 -55
  302. package/vscode/src/vs/sessions/contrib/layout/browser/singlePaneLayoutController.js +0 -91
  303. package/vscode/src/vs/sessions/contrib/providers/agentHost/browser/agentHostClaudePermissionModePicker.d.ts +0 -26
  304. package/vscode/src/vs/sessions/contrib/providers/agentHost/browser/agentHostClaudePermissionModePicker.js +0 -98
  305. package/vscode/src/vs/sessions/contrib/providers/agentHost/browser/agentHostCodexApprovalsPicker.d.ts +0 -33
  306. package/vscode/src/vs/sessions/contrib/providers/agentHost/browser/agentHostCodexApprovalsPicker.js +0 -98
  307. package/vscode/src/vs/sessions/contrib/providers/agentHost/browser/agentHostModeIcon.d.ts +0 -2
  308. package/vscode/src/vs/sessions/contrib/providers/agentHost/browser/agentHostModeIcon.js +0 -13
  309. package/vscode/src/vs/sessions/contrib/providers/agentHost/browser/agentHostModePicker.d.ts +0 -122
  310. package/vscode/src/vs/sessions/contrib/providers/agentHost/browser/agentHostModePicker.js +0 -464
  311. package/vscode/src/vs/sessions/contrib/providers/agentHost/browser/agentHostPermissionPickerActionItem.d.ts +0 -35
  312. package/vscode/src/vs/sessions/contrib/providers/agentHost/browser/agentHostPermissionPickerActionItem.js +0 -90
  313. package/vscode/src/vs/sessions/contrib/providers/agentHost/browser/agentHostPermissionPickerDelegate.d.ts +0 -84
  314. package/vscode/src/vs/sessions/contrib/providers/agentHost/browser/agentHostPermissionPickerDelegate.js +0 -328
  315. package/vscode/src/vs/sessions/contrib/providers/agentHost/browser/agentHostSessionConfigPicker.d.ts +0 -174
  316. package/vscode/src/vs/sessions/contrib/providers/agentHost/browser/agentHostSessionConfigPicker.js +0 -1390
  317. package/vscode/src/vs/sessions/contrib/providers/agentHost/browser/media/agentHostSessionConfigPicker.css +0 -44
  318. package/vscode/src/vs/sessions/contrib/providers/agentHost/browser/mobile/mobileAgentHostModePicker.d.ts +0 -30
  319. package/vscode/src/vs/sessions/contrib/providers/agentHost/browser/mobile/mobileAgentHostModePicker.js +0 -78
  320. package/vscode/src/vs/sessions/contrib/providers/agentHost/browser/mobile/mobileChatPhoneInputTarget.d.ts +0 -11
  321. package/vscode/src/vs/sessions/contrib/providers/agentHost/browser/mobile/mobileChatPhoneInputTarget.js +0 -26
  322. package/vscode/src/vs/sessions/contrib/providers/remoteAgentHost/browser/remoteAgentHostConnectionCustomization.d.ts +0 -27
  323. package/vscode/src/vs/sessions/contrib/providers/remoteAgentHost/browser/remoteAgentHostConnectionCustomization.js +0 -26
@@ -1,19 +1,23 @@
1
1
 
2
2
  import { __decorate, __param } from '@codingame/monaco-vscode-api/external/tslib/tslib.es6';
3
- import { $ as $$1, isEditableElement, addDisposableListener, EventType, clearNode, append, getWindow, hide, DisposableResizeObserver, addStandardDisposableListener, show } from '@codingame/monaco-vscode-api/vscode/vs/base/browser/dom';
3
+ import { $ as $$1, isEditableElement, addDisposableListener, EventType, clearNode, append, hide, getWindow, DisposableResizeObserver, show, reset } from '@codingame/monaco-vscode-api/vscode/vs/base/browser/dom';
4
4
  import { raceCancellationError, raceTimeout } from '@codingame/monaco-vscode-api/vscode/vs/base/common/async';
5
5
  import { BaseActionViewItem } from '@codingame/monaco-vscode-api/vscode/vs/base/browser/ui/actionbar/actionViewItems';
6
6
  import { renderIcon } from '@codingame/monaco-vscode-api/vscode/vs/base/browser/ui/iconLabel/iconLabels';
7
+ import { Button, unthemedButtonStyles } from '@codingame/monaco-vscode-api/vscode/vs/base/browser/ui/button/button';
8
+ import { Checkbox } from '@codingame/monaco-vscode-api/vscode/vs/base/browser/ui/toggle/toggle';
7
9
  import { InputBox } from '@codingame/monaco-vscode-api/vscode/vs/base/browser/ui/inputbox/inputBox';
10
+ import '@codingame/monaco-vscode-api/vscode/vs/base/browser/ui/contextview/contextview';
8
11
  import { SelectBox } from '@codingame/monaco-vscode-api/vscode/vs/base/browser/ui/selectBox/selectBox';
9
- import { Checkbox } from '@codingame/monaco-vscode-api/vscode/vs/base/browser/ui/toggle/toggle';
10
- import { CancellationToken, CancellationTokenSource } from '@codingame/monaco-vscode-api/vscode/vs/base/common/cancellation';
12
+ import { CancellationToken, CancellationTokenSource, cancelOnDispose } from '@codingame/monaco-vscode-api/vscode/vs/base/common/cancellation';
11
13
  import { Codicon } from '@codingame/monaco-vscode-api/vscode/vs/base/common/codicons';
12
14
  import { Emitter, Event } from '@codingame/monaco-vscode-api/vscode/vs/base/common/event';
15
+ import { onUnexpectedError, isCancellationError, getErrorMessage } from '@codingame/monaco-vscode-api/vscode/vs/base/common/errors';
13
16
  import { KeyCode } from '@codingame/monaco-vscode-api/vscode/vs/base/common/keyCodes';
14
17
  import { DisposableStore, Disposable, MutableDisposable, toDisposable } from '@codingame/monaco-vscode-api/vscode/vs/base/common/lifecycle';
15
18
  import '@codingame/monaco-vscode-api/vscode/vs/base/common/observableInternal/index';
16
- import { isEqual } from '@codingame/monaco-vscode-api/vscode/vs/base/common/resources';
19
+ import { isEqual, getComparisonKey } from '@codingame/monaco-vscode-api/vscode/vs/base/common/resources';
20
+ import { isStringArray } from '@codingame/monaco-vscode-api/vscode/vs/base/common/types';
17
21
  import { ICodeEditorService } from '@codingame/monaco-vscode-api/vscode/vs/editor/browser/services/codeEditorService.service';
18
22
  import { EditorOptions } from '@codingame/monaco-vscode-api/vscode/vs/editor/common/config/editorOptions';
19
23
  import { EditorContextKeys } from '@codingame/monaco-vscode-api/vscode/vs/editor/common/editorContextKeys';
@@ -30,26 +34,28 @@ import { ServiceCollection } from '@codingame/monaco-vscode-api/vscode/vs/platfo
30
34
  import { KeybindingsRegistry, KeybindingWeight } from '@codingame/monaco-vscode-api/vscode/vs/platform/keybinding/common/keybindingsRegistry';
31
35
  import { ILogService } from '@codingame/monaco-vscode-api/vscode/vs/platform/log/common/log.service';
32
36
  import { MenuWorkbenchToolBar, HiddenItemStrategy } from '@codingame/monaco-vscode-api/vscode/vs/platform/actions/browser/toolbar';
33
- import { defaultInputBoxStyles, defaultSelectBoxStyles, defaultCheckboxStyles } from '@codingame/monaco-vscode-api/vscode/vs/platform/theme/browser/defaultStyles';
37
+ import { getInputBoxStyle, defaultSelectBoxStyles, defaultButtonStyles, defaultCheckboxStyles } from '@codingame/monaco-vscode-api/vscode/vs/platform/theme/browser/defaultStyles';
34
38
  import { hasNativeContextMenu } from '@codingame/monaco-vscode-api/vscode/vs/platform/window/common/window';
35
39
  import { WorkspacePicker } from '@codingame/monaco-vscode-api/vscode/vs/sessions/contrib/chat/browser/sessionWorkspacePicker';
36
- import { BranchPicker } from '@codingame/monaco-vscode-api/vscode/vs/sessions/contrib/chat/browser/branchPicker';
40
+ import { BranchPicker, NEW_WORKTREE_LABEL } from '@codingame/monaco-vscode-api/vscode/vs/sessions/contrib/chat/browser/branchPicker';
37
41
  import { MobileSessionTypePicker } from '@codingame/monaco-vscode-api/vscode/vs/sessions/contrib/chat/browser/mobile/mobileSessionTypePicker';
38
42
  import { isMobilePickerSheetTarget } from '@codingame/monaco-vscode-api/vscode/vs/sessions/browser/parts/mobile/mobilePickerSheet';
39
- import { SESSION_WORKSPACE_GROUP_LOCAL } from '@codingame/monaco-vscode-api/vscode/vs/sessions/services/sessions/common/session';
43
+ import { GITHUB_REMOTE_FILE_SCHEME, SESSION_WORKSPACE_GROUP_LOCAL } from '@codingame/monaco-vscode-api/vscode/vs/sessions/services/sessions/common/session';
40
44
  import { IGitService } from '@codingame/monaco-vscode-api/vscode/vs/workbench/contrib/git/common/gitService.service';
41
- import { DAYS_OF_WEEK } from '@codingame/monaco-vscode-api/vscode/vs/workbench/contrib/chat/common/automations/schedule';
45
+ import { DAYS_OF_WEEK, automationScheduleToUTC } from '../../../../workbench/contrib/chat/common/automations/schedule.js';
42
46
  import { ChatContextKeys } from '@codingame/monaco-vscode-api/vscode/vs/workbench/contrib/chat/common/actions/chatContextKeys';
43
47
  import { ChatAgentLocation } from '@codingame/monaco-vscode-api/vscode/vs/workbench/contrib/chat/common/constants';
48
+ import { SessionType } from '@codingame/monaco-vscode-api/vscode/vs/workbench/contrib/chat/common/chatSessionsService';
44
49
  import { ChatInputPart } from '@codingame/monaco-vscode-api/vscode/vs/workbench/contrib/chat/browser/widget/input/chatInputPart';
45
50
  import { ChatInputPickerResponsiveLayout } from '@codingame/monaco-vscode-api/vscode/vs/workbench/contrib/chat/browser/widget/input/chatInputPickerResponsiveLayout';
51
+ import { settingsTextInputBorder, settingsTextInputForeground, settingsTextInputBackground } from '@codingame/monaco-vscode-api/vscode/vs/workbench/contrib/preferences/common/settingsEditorColorRegistry';
46
52
  import { normalizeAutomationBranchNames, AutomationIsolationModel } from '../common/isolationGroupModel.js';
47
53
  import { ISessionsManagementService } from '@codingame/monaco-vscode-api/vscode/vs/sessions/services/sessions/common/sessionsManagement.service';
48
54
  import { shouldUseMobileWorkspacePickerSheet, showMobileWorkspacePickerSheet } from '@codingame/monaco-vscode-api/vscode/vs/sessions/contrib/chat/browser/mobile/mobileWorkspacePickerSheet';
49
55
  import { AutomationInputCompletions } from './automationInputCompletions.js';
50
56
  import { NewChatModelPickerService } from '@codingame/monaco-vscode-api/vscode/vs/sessions/contrib/chat/browser/newChatModelPicker';
51
57
  import { INewChatModelPickerService } from '@codingame/monaco-vscode-api/vscode/vs/sessions/contrib/chat/browser/newChatModelPicker.service';
52
- import { createNewSessionConfigToolbar, createNewSessionControlToolbar } from '@codingame/monaco-vscode-api/vscode/vs/sessions/contrib/chat/browser/newSessionConfigToolbars';
58
+ import { createNewSessionControlToolbar } from '@codingame/monaco-vscode-api/vscode/vs/sessions/contrib/chat/browser/newSessionConfigToolbars';
53
59
  import { SessionModelSelection } from '@codingame/monaco-vscode-api/vscode/vs/sessions/contrib/chat/browser/sessionModelSelection';
54
60
  import { ISessionModelSelection } from '@codingame/monaco-vscode-api/vscode/vs/sessions/contrib/chat/browser/sessionModelSelection.service';
55
61
  import { SessionContext } from '@codingame/monaco-vscode-api/vscode/vs/sessions/services/sessions/browser/sessionContext';
@@ -59,24 +65,35 @@ import { setActiveSessionContextKeys } from '../../../services/sessions/common/s
59
65
  import { SessionUsesCombinedConfigPickerContext } from '@codingame/monaco-vscode-api/vscode/vs/sessions/common/contextkeys';
60
66
  import { Menus } from '@codingame/monaco-vscode-api/vscode/vs/sessions/browser/menus';
61
67
  import { derived } from '@codingame/monaco-vscode-api/vscode/vs/base/common/observableInternal/observables/derived';
62
- import { constObservable } from '@codingame/monaco-vscode-api/vscode/vs/base/common/observableInternal/observables/constObservable';
63
- import { autorun } from '@codingame/monaco-vscode-api/vscode/vs/base/common/observableInternal/reactions/autorun';
68
+ import { AnchorPosition } from '@codingame/monaco-vscode-api/vscode/vs/base/common/layout';
64
69
  import { observableValue, disposableObservableValue } from '@codingame/monaco-vscode-api/vscode/vs/base/common/observableInternal/observables/observableValue';
65
70
  import { observableSignalFromEvent } from '@codingame/monaco-vscode-api/vscode/vs/base/common/observableInternal/observables/observableSignalFromEvent';
71
+ import { constObservable } from '@codingame/monaco-vscode-api/vscode/vs/base/common/observableInternal/observables/constObservable';
72
+ import { autorun } from '@codingame/monaco-vscode-api/vscode/vs/base/common/observableInternal/reactions/autorun';
73
+ import { transaction } from '@codingame/monaco-vscode-api/vscode/vs/base/common/observableInternal/transaction';
74
+ import { waitForState } from '@codingame/monaco-vscode-api/vscode/vs/base/common/observableInternal/utils/utilsCancellation';
66
75
 
67
76
  const $ = $$1;
77
+ const automationNameInputBoxStyles = getInputBoxStyle({
78
+ inputBackground: settingsTextInputBackground,
79
+ inputForeground: settingsTextInputForeground,
80
+ inputBorder: settingsTextInputBorder
81
+ });
68
82
  const INTERVALS = [{
69
83
  value: "manual",
70
- label: ( localize(3297, "Manual"))
84
+ label: ( localize(3670, "Manual"))
71
85
  }, {
72
86
  value: "hourly",
73
- label: ( localize(3298, "Hourly"))
87
+ label: ( localize(3671, "Hourly"))
74
88
  }, {
75
89
  value: "daily",
76
- label: ( localize(3299, "Daily"))
90
+ label: ( localize(3672, "Daily"))
91
+ }, {
92
+ value: "weekdays",
93
+ label: ( localize(3673, "Weekdays"))
77
94
  }, {
78
95
  value: "weekly",
79
- label: ( localize(3300, "Weekly"))
96
+ label: ( localize(3674, "Weekly"))
80
97
  }];
81
98
  function isAutomationDialogPopupTarget(relatedTarget) {
82
99
  return isMobilePickerSheetTarget(relatedTarget) || !!relatedTarget.closest(
@@ -102,7 +119,7 @@ async function canSelectAutomationWorkspace(
102
119
  return !!(await workspaceTrustRequestService.requestResourcesTrust({
103
120
  uri: folderUri,
104
121
  message: ( localize(
105
- 3301,
122
+ 3675,
106
123
  "An agent session will be able to read files, run commands, and make changes in this folder."
107
124
  ))
108
125
  }));
@@ -184,6 +201,20 @@ function registerAutomationDialogKeyboardNavigation(
184
201
  dispose: () => store.dispose()
185
202
  };
186
203
  }
204
+ function getAutomationDialogProviders(automationService, existing) {
205
+ return derived(reader => {
206
+ if (existing === undefined) {
207
+ return automationService.availableProviders.read(reader).map(provider => provider.id);
208
+ }
209
+ automationService.automations.read(reader);
210
+ automationService.catalogueState.read(reader);
211
+ const providerId = existing.target.providerId;
212
+ if (providerId === undefined || !automationService.canUpdateAutomation(existing.id)) {
213
+ return [];
214
+ }
215
+ return [providerId];
216
+ });
217
+ }
187
218
  const AUTOMATION_CONFIGURATION_CAPTURE_TIMEOUT_MS = 5_000;
188
219
  const AUTOMATION_CONFIGURATION_RETARGET_CAPTURE_TIMEOUT_MS = 1_000;
189
220
  class AutomationSessionDraftSynchronizer extends Disposable {
@@ -471,9 +502,6 @@ function getAutomationToolbarResponsiveItems(toolbar, options = {}) {
471
502
  isCompact: () => element.classList.contains("compact-picker"),
472
503
  setCompact: compact => {
473
504
  element.classList.toggle("compact-picker", compact);
474
- if (action.id === "sessions.modelPicker") {
475
- options.compactModelPicker?.set(compact, undefined);
476
- }
477
505
  }
478
506
  });
479
507
  }
@@ -511,6 +539,7 @@ let AutomationIsolationGroupActionViewItem = class AutomationIsolationGroupActio
511
539
  this.branchLoadState = "noFolder";
512
540
  this.branches = [];
513
541
  this.worktreeCapabilityResolved = false;
542
+ this.visibleFromInput = true;
514
543
  this.branchPicker = this._register(instantiationService.createInstance(BranchPicker, {
515
544
  user: "automationBranchPicker",
516
545
  slotClassName: "automation-form-branch-picker-slot",
@@ -528,8 +557,8 @@ let AutomationIsolationGroupActionViewItem = class AutomationIsolationGroupActio
528
557
  void this.reloadRepository(this.isolationModel.folderUri);
529
558
  },
530
559
  isolation: {
531
- label: ( localize(3302, "New Worktree")),
532
- ariaLabel: ( localize(3303, "Worktree isolation")),
560
+ label: NEW_WORKTREE_LABEL,
561
+ ariaLabel: ( localize(3676, "Worktree isolation")),
533
562
  onToggle: checked => {
534
563
  this.isolationModel.selectIsolationMode(checked ? "worktree" : "workspace");
535
564
  this.renderBranchControl();
@@ -543,10 +572,12 @@ let AutomationIsolationGroupActionViewItem = class AutomationIsolationGroupActio
543
572
  this.cancelBranchRequest();
544
573
  clearNode(container);
545
574
  container.style.marginLeft = "auto";
575
+ this.container = container;
546
576
  const visible = this.visible;
547
577
  if (visible) {
548
578
  this.renderDisposables.add(autorun(reader => {
549
- setAutomationControlVisible(container, visible.read(reader));
579
+ this.visibleFromInput = visible.read(reader);
580
+ this.updateVisibility();
550
581
  }));
551
582
  }
552
583
  const isolationGroup = append(container, $("span.automation-form-isolation-group"));
@@ -573,6 +604,14 @@ let AutomationIsolationGroupActionViewItem = class AutomationIsolationGroupActio
573
604
  showPicker(anchor) {
574
605
  this.branchPicker.showPicker(anchor);
575
606
  }
607
+ updateVisibility() {
608
+ if (this.container) {
609
+ setAutomationControlVisible(
610
+ this.container,
611
+ this.visibleFromInput && this.branchLoadState !== "noRepository"
612
+ );
613
+ }
614
+ }
576
615
  refreshTargetCapability() {
577
616
  const folderUri = this.isolationModel.folderUri;
578
617
  const sessionTypeId = this.state.sessionTypeId;
@@ -631,29 +670,30 @@ let AutomationIsolationGroupActionViewItem = class AutomationIsolationGroupActio
631
670
  disabledReason: worktreeUnavailableReason
632
671
  }
633
672
  });
673
+ this.updateVisibility();
634
674
  this.revalidate();
635
675
  }
636
676
  getBranchPresentation() {
637
677
  const displayBranch = this.isolationModel.displayBranch;
638
678
  if (!this.isolationModel.folderUri) {
639
679
  return {
640
- label: ( localize(3304, "—")),
641
- reason: ( localize(3305, "Select a folder to determine its Git branch.")),
680
+ label: ( localize(3677, "—")),
681
+ reason: ( localize(3678, "Select a folder to determine its Git branch.")),
642
682
  missing: true
643
683
  };
644
684
  }
645
685
  if (!this.worktreeCapabilityResolved) {
646
686
  return {
647
- label: displayBranch ?? ( localize(3304, "—")),
648
- reason: ( localize(3306, "Session capabilities are loading.")),
687
+ label: displayBranch ?? ( localize(3677, "—")),
688
+ reason: ( localize(3679, "Session capabilities are loading.")),
649
689
  missing: !displayBranch
650
690
  };
651
691
  }
652
692
  if (!this.isolationModel.supportsWorktreeConfiguration) {
653
693
  return {
654
- label: displayBranch ?? ( localize(3304, "—")),
694
+ label: displayBranch ?? ( localize(3677, "—")),
655
695
  reason: ( localize(
656
- 3307,
696
+ 3680,
657
697
  "The selected session type does not support Worktree branch configuration."
658
698
  )),
659
699
  missing: !displayBranch
@@ -661,15 +701,15 @@ let AutomationIsolationGroupActionViewItem = class AutomationIsolationGroupActio
661
701
  }
662
702
  if (this.branchLoadState === "error") {
663
703
  return {
664
- label: displayBranch ?? ( localize(3308, "Unable to load branches")),
665
- reason: ( localize(3309, "Open the branch picker to retry loading local branches.")),
704
+ label: displayBranch ?? ( localize(3681, "Unable to load branches")),
705
+ reason: ( localize(3682, "Open the branch picker to retry loading local branches.")),
666
706
  missing: !displayBranch
667
707
  };
668
708
  }
669
709
  if (this.isolationModel.isolationMode !== "worktree") {
670
710
  return {
671
- label: displayBranch ?? this.detachedCommit ?? ( localize(3304, "—")),
672
- reason: ( localize(3310, "Select Worktree to choose a branch.")),
711
+ label: displayBranch ?? this.detachedCommit ?? ( localize(3677, "—")),
712
+ reason: ( localize(3683, "Select Worktree to choose a branch.")),
673
713
  missing: !displayBranch && !this.detachedCommit
674
714
  };
675
715
  }
@@ -677,32 +717,32 @@ let AutomationIsolationGroupActionViewItem = class AutomationIsolationGroupActio
677
717
  case "loadingRepository":
678
718
  case "loadingBranches":
679
719
  return {
680
- label: displayBranch ?? ( localize(3311, "Loading branches…")),
681
- reason: ( localize(3312, "Local branches are loading.")),
720
+ label: displayBranch ?? ( localize(3684, "Loading branches…")),
721
+ reason: ( localize(3685, "Local branches are loading.")),
682
722
  missing: !displayBranch
683
723
  };
684
724
  case "noRepository":
685
725
  return {
686
- label: displayBranch ?? ( localize(3313, "no git repo")),
687
- reason: ( localize(3314, "No Git repository was found for the selected folder.")),
726
+ label: displayBranch ?? ( localize(3686, "no git repo")),
727
+ reason: ( localize(3687, "No Git repository was found for the selected folder.")),
688
728
  missing: !displayBranch
689
729
  };
690
730
  case "empty":
691
731
  return {
692
- label: displayBranch ?? ( localize(3315, "No local branches")),
693
- reason: ( localize(3316, "No local branches were found in this repository.")),
732
+ label: displayBranch ?? ( localize(3688, "No local branches")),
733
+ reason: ( localize(3689, "No local branches were found in this repository.")),
694
734
  missing: !displayBranch
695
735
  };
696
736
  case "ready":
697
737
  return {
698
- label: displayBranch ?? ( localize(3317, "Select branch")),
699
- reason: ( localize(3318, "Choose the local branch to use as the Worktree base.")),
738
+ label: displayBranch ?? ( localize(3690, "Select branch")),
739
+ reason: ( localize(3691, "Choose the local branch to use as the Worktree base.")),
700
740
  missing: !displayBranch
701
741
  };
702
742
  case "noFolder":
703
743
  return {
704
- label: ( localize(3304, "—")),
705
- reason: ( localize(3305, "Select a folder to determine its Git branch.")),
744
+ label: ( localize(3677, "—")),
745
+ reason: ( localize(3678, "Select a folder to determine its Git branch.")),
706
746
  missing: true
707
747
  };
708
748
  }
@@ -715,13 +755,13 @@ let AutomationIsolationGroupActionViewItem = class AutomationIsolationGroupActio
715
755
  }
716
756
  getWorktreeUnavailableReason() {
717
757
  if (!this.isolationModel.folderUri) {
718
- return localize(3319, "Select a folder to use Worktree isolation.");
758
+ return localize(3692, "Select a folder to use Worktree isolation.");
719
759
  }
720
760
  if (!this.worktreeCapabilityResolved) {
721
- return localize(3306, "Session capabilities are loading.");
761
+ return localize(3679, "Session capabilities are loading.");
722
762
  }
723
763
  if (!this.isolationModel.supportsWorktreeConfiguration) {
724
- return localize(3320, "Not supported by the selected session type");
764
+ return localize(3693, "Not supported by the selected session type");
725
765
  }
726
766
  if (this.isolationModel.selectedBranch) {
727
767
  return undefined;
@@ -729,17 +769,17 @@ let AutomationIsolationGroupActionViewItem = class AutomationIsolationGroupActio
729
769
  switch (this.branchLoadState) {
730
770
  case "loadingRepository":
731
771
  case "loadingBranches":
732
- return localize(3312, "Local branches are loading.");
772
+ return localize(3685, "Local branches are loading.");
733
773
  case "noRepository":
734
- return localize(3314, "No Git repository was found for the selected folder.");
774
+ return localize(3687, "No Git repository was found for the selected folder.");
735
775
  case "error":
736
- return localize(3309, "Open the branch picker to retry loading local branches.");
776
+ return localize(3682, "Open the branch picker to retry loading local branches.");
737
777
  case "empty":
738
- return localize(3316, "No local branches were found in this repository.");
778
+ return localize(3689, "No local branches were found in this repository.");
739
779
  case "ready":
740
- return this.branches.length > 0 ? undefined : ( localize(3316, "No local branches were found in this repository."));
780
+ return this.branches.length > 0 ? undefined : ( localize(3689, "No local branches were found in this repository."));
741
781
  case "noFolder":
742
- return localize(3319, "Select a folder to use Worktree isolation.");
782
+ return localize(3692, "Select a folder to use Worktree isolation.");
743
783
  }
744
784
  }
745
785
  cancelBranchRequest() {
@@ -783,6 +823,9 @@ let AutomationIsolationGroupActionViewItem = class AutomationIsolationGroupActio
783
823
  }
784
824
  if (!repo) {
785
825
  this.branchLoadState = "noRepository";
826
+ if (this.isolationModel.isolationMode === "worktree") {
827
+ this.isolationModel.selectIsolationMode("workspace");
828
+ }
786
829
  this.renderBranchControl();
787
830
  return;
788
831
  }
@@ -794,7 +837,7 @@ let AutomationIsolationGroupActionViewItem = class AutomationIsolationGroupActio
794
837
  this.detachedCommit = undefined;
795
838
  this.isolationModel.setHeadBranch(head.name);
796
839
  } else if (head?.commit) {
797
- this.detachedCommit = ( localize(3321, "({0})", head.commit.slice(0, 7)));
840
+ this.detachedCommit = ( localize(3694, "({0})", head.commit.slice(0, 7)));
798
841
  this.isolationModel.setHeadBranch(undefined);
799
842
  } else {
800
843
  this.detachedCommit = undefined;
@@ -846,7 +889,7 @@ registerAction2(class OpenAutomationsHarnessChipAction extends Action2 {
846
889
  constructor() {
847
890
  super({
848
891
  id: AUTOMATIONS_HARNESS_CHIP_ACTION_ID,
849
- title: ( localize2(3322, "Automations Harness Chip")),
892
+ title: ( localize2(3695, "Automations Harness Chip")),
850
893
  f1: false,
851
894
  precondition: ChatContextKeys.enabled,
852
895
  menu: [{
@@ -863,7 +906,7 @@ registerAction2(class OpenAutomationsWorkspacePickerAction extends Action2 {
863
906
  constructor() {
864
907
  super({
865
908
  id: AUTOMATIONS_WORKSPACE_PICKER_ACTION_ID,
866
- title: ( localize2(3323, "Automations Workspace Picker")),
909
+ title: ( localize2(3696, "Automations Workspace Picker")),
867
910
  f1: false,
868
911
  precondition: ChatContextKeys.enabled,
869
912
  menu: [{
@@ -880,7 +923,7 @@ registerAction2(class OpenAutomationsIsolationGroupAction extends Action2 {
880
923
  constructor() {
881
924
  super({
882
925
  id: AUTOMATIONS_ISOLATION_GROUP_ACTION_ID,
883
- title: ( localize2(3324, "Automations Isolation Group")),
926
+ title: ( localize2(3697, "Automations Isolation Group")),
884
927
  f1: false,
885
928
  precondition: ChatContextKeys.enabled,
886
929
  menu: [{
@@ -909,27 +952,45 @@ function renderForm(
909
952
  workspaceTrustRequestService,
910
953
  initialPrompt,
911
954
  initialTarget,
912
- initialSessionConfiguration
955
+ initialSessionConfiguration,
956
+ allowedProviders,
957
+ getProviderConfiguration = () => undefined,
958
+ isEdit = false,
959
+ customizations,
960
+ notifyError = onUnexpectedError,
961
+ quickInputService
913
962
  ) {
963
+ let reloadCustomizations = () => {};
964
+ const validateForm = revalidate;
965
+ revalidate = () => {
966
+ reloadCustomizations();
967
+ validateForm();
968
+ };
914
969
  const formContent = append(form, $(".automation-form-content"));
915
970
  const nameRow = append(formContent, $(".automation-form-row"));
916
- append(nameRow, $("span.automation-form-label", undefined, ( localize(3325, "Name"))));
971
+ append(nameRow, $("span.automation-form-label", undefined, ( localize(3698, "Name"))));
917
972
  const nameInputContainer = append(nameRow, $(".automation-form-input-host"));
918
973
  const nameInput = disposables.add(( new InputBox(nameInputContainer, contextViewService, {
919
- inputBoxStyles: defaultInputBoxStyles,
920
- placeholder: ( localize(3326, "e.g. Morning standup notes")),
921
- ariaLabel: ( localize(3325, "Name"))
974
+ inputBoxStyles: automationNameInputBoxStyles,
975
+ placeholder: ( localize(3699, "e.g. Morning standup notes")),
976
+ ariaLabel: ( localize(3698, "Name"))
922
977
  })));
923
978
  nameInput.value = state.name;
924
979
  disposables.add(nameInput.onDidChange(value => {
925
980
  state.name = value;
926
981
  revalidate();
927
982
  }));
983
+ const sessionSection = append(formContent, $(".automation-session-section"));
928
984
  const scheduleRow = append(formContent, $(".automation-form-row.automation-form-schedule-row"));
929
- const useCustomDrawn = !hasNativeContextMenu(configurationService);
985
+ const scheduleSelectOptions = {
986
+ useCustomDrawn: !hasNativeContextMenu(configurationService),
987
+ anchorPosition: AnchorPosition.ABOVE,
988
+ maxVisibleOptions: 6
989
+ };
930
990
  const intervalGroup = append(scheduleRow, $(".automation-form-schedule-group"));
931
- append(intervalGroup, $("span.automation-form-label", undefined, ( localize(3327, "Schedule"))));
932
- const intervalOptions = INTERVALS.map(item => ({
991
+ append(intervalGroup, $("span.automation-form-label", undefined, ( localize(3700, "Schedule"))));
992
+ let intervals = INTERVALS;
993
+ const intervalOptions = intervals.map(item => ({
933
994
  text: item.label
934
995
  }));
935
996
  const intervalIndex = Math.max(0, INTERVALS.findIndex(item => item.value === state.interval));
@@ -939,8 +1000,8 @@ function renderForm(
939
1000
  contextViewService,
940
1001
  defaultSelectBoxStyles,
941
1002
  {
942
- ariaLabel: ( localize(3327, "Schedule")),
943
- useCustomDrawn
1003
+ ...scheduleSelectOptions,
1004
+ ariaLabel: ( localize(3700, "Schedule"))
944
1005
  }
945
1006
  )));
946
1007
  const intervalSelectContainer = append(intervalGroup, $(".automation-form-schedule-select-container"));
@@ -949,16 +1010,14 @@ function renderForm(
949
1010
  scheduleRow,
950
1011
  $(".automation-form-schedule-group.automation-form-time-group")
951
1012
  );
952
- append(timeGroup, $("span.automation-form-label", undefined, ( localize(3328, "Time"))));
953
- const timeOptions = buildTimeOptions();
954
- const initialTimeIndex = nearestTimeOptionIndex(state.hour, state.minute);
955
- state.hour = timeOptions[initialTimeIndex].hour;
956
- state.minute = timeOptions[initialTimeIndex].minute;
1013
+ const timeLabel = append(timeGroup, $("span.automation-form-label", undefined, ( localize(3701, "Time"))));
1014
+ const timeOptions = buildTimeOptions(state.hour, state.minute);
1015
+ const initialTimeIndex = timeOptions.findIndex(option => option.hour === state.hour && option.minute === state.minute);
957
1016
  const timeSelect = disposables.add(( new SelectBox(timeOptions.map(opt => ({
958
1017
  text: opt.label
959
1018
  })), initialTimeIndex, contextViewService, defaultSelectBoxStyles, {
960
- ariaLabel: ( localize(3328, "Time")),
961
- useCustomDrawn
1019
+ ...scheduleSelectOptions,
1020
+ ariaLabel: ( localize(3701, "Time"))
962
1021
  })));
963
1022
  const timeSelectContainer = append(timeGroup, $(
964
1023
  ".automation-form-schedule-select-container.automation-form-time-select-container"
@@ -968,12 +1027,13 @@ function renderForm(
968
1027
  const opt = timeOptions[e.index];
969
1028
  state.hour = opt.hour;
970
1029
  state.minute = opt.minute;
1030
+ revalidate();
971
1031
  }));
972
1032
  const dayGroup = append(
973
1033
  scheduleRow,
974
1034
  $(".automation-form-schedule-group.automation-form-day-group")
975
1035
  );
976
- append(dayGroup, $("span.automation-form-label", undefined, ( localize(3329, "Day of week"))));
1036
+ append(dayGroup, $("span.automation-form-label", undefined, ( localize(3702, "Day of week"))));
977
1037
  const dayOptions = DAYS_OF_WEEK.map(d => ({
978
1038
  text: d
979
1039
  }));
@@ -983,34 +1043,92 @@ function renderForm(
983
1043
  contextViewService,
984
1044
  defaultSelectBoxStyles,
985
1045
  {
986
- ariaLabel: ( localize(3329, "Day of week")),
987
- useCustomDrawn
1046
+ ...scheduleSelectOptions,
1047
+ ariaLabel: ( localize(3702, "Day of week"))
988
1048
  }
989
1049
  )));
990
1050
  const daySelectContainer = append(dayGroup, $(".automation-form-schedule-select-container"));
991
1051
  daySelect.render(daySelectContainer);
992
1052
  disposables.add(daySelect.onDidSelect(e => {
993
1053
  state.day = e.index;
1054
+ revalidate();
1055
+ }));
1056
+ const scheduleError = append(formContent, $("span.automation-target-error", {
1057
+ role: "status",
1058
+ "aria-live": "polite"
994
1059
  }));
1060
+ hide(scheduleError);
995
1061
  const applyIntervalVisibility = () => {
996
- const showTime = state.interval === "daily" || state.interval === "weekly";
1062
+ const showTime = state.interval === "daily" || state.interval === "weekdays" || state.interval === "weekly";
997
1063
  const showDay = state.interval === "weekly";
998
1064
  timeGroup.style.display = showTime ? "" : "none";
999
1065
  dayGroup.style.display = showDay ? "" : "none";
1000
1066
  };
1067
+ const updateIntervalOptions = cloud => {
1068
+ intervals = INTERVALS.filter(item => !cloud || item.value !== "weekdays");
1069
+ const unsupportedInterval = !( intervals.some(item => item.value === state.interval));
1070
+ if (unsupportedInterval) {
1071
+ intervals = [{
1072
+ value: state.interval,
1073
+ label: ( localize(3703, "Choose a schedule"))
1074
+ }, ...intervals];
1075
+ }
1076
+ intervalSelect.setOptions(intervals.map(item => ({
1077
+ text: item.label,
1078
+ isDisabled: unsupportedInterval && item.value === state.interval
1079
+ })), Math.max(0, intervals.findIndex(item => item.value === state.interval)));
1080
+ applyIntervalVisibility();
1081
+ };
1001
1082
  applyIntervalVisibility();
1002
1083
  disposables.add(intervalSelect.onDidSelect(e => {
1003
- state.interval = INTERVALS[e.index].value;
1004
- applyIntervalVisibility();
1084
+ state.interval = intervals[e.index].value;
1085
+ updateIntervalOptions(getProviderConfiguration(state.providerId) !== undefined);
1086
+ revalidate();
1005
1087
  }));
1088
+ const initialProviderConfiguration = getProviderConfiguration(state.providerId);
1089
+ const selectedProvider = observableValue(form, state.providerId);
1090
+ const cloudProvider = derived(
1091
+ reader => allowedProviders.read(reader).find(id => getProviderConfiguration(id) !== undefined) ?? (isEdit ? undefined : sessionsManagementService.getAllProviderSessionTypes().find(
1092
+ type => getProviderConfiguration(type.providerId)?.sessionTypes.includes(type.sessionType.id)
1093
+ )?.providerId)
1094
+ );
1095
+ const availableCloudConfiguration = derived(reader => getProviderConfiguration(cloudProvider.read(reader)));
1096
+ const cloudConfiguration = derived(reader => {
1097
+ allowedProviders.read(reader);
1098
+ return getProviderConfiguration(selectedProvider.read(reader));
1099
+ });
1100
+ const runInCloud = derived(reader => cloudConfiguration.read(reader) !== undefined);
1101
+ const sessionConfigurationErrorMessage = observableValue(form, undefined);
1102
+ let switchingTarget = false;
1103
+ let localTarget = {
1104
+ ...state
1105
+ };
1006
1106
  const isolationModel = ( new AutomationIsolationModel(state));
1007
1107
  const workspaceControlsVisible = derived(
1008
- reader => !isolationModel.isQuickChatObs.read(reader) && isolationModel.folderUriObs.read(reader) !== undefined
1108
+ reader => !runInCloud.read(reader) && !isolationModel.isQuickChatObs.read(reader) && isolationModel.folderUriObs.read(reader)?.scheme !== GITHUB_REMOTE_FILE_SCHEME && isolationModel.folderUriObs.read(reader) !== undefined
1009
1109
  );
1110
+ const sessionTypesChanged = observableSignalFromEvent(form, sessionsManagementService.onDidChangeSessionTypes);
1111
+ const sessionTypes = derived(reader => {
1112
+ sessionTypesChanged.read(reader);
1113
+ const folder = isolationModel.folderUriObs.read(reader);
1114
+ const quickChat = isolationModel.isQuickChatObs.read(reader);
1115
+ return quickChat ? sessionsManagementService.getQuickChatSessionTypes() : folder ? sessionsManagementService.getSessionTypesForFolder(folder) : [];
1116
+ });
1117
+ const pickerProviders = derived(reader => {
1118
+ const folder = isolationModel.folderUriObs.read(reader);
1119
+ const allowed = allowedProviders.read(reader);
1120
+ const cloud = cloudProvider.read(reader);
1121
+ return [...allowed, ...(cloud && !allowed.includes(cloud) ? [cloud] : [])].filter(
1122
+ id => isEdit || !getProviderConfiguration(id)?.getWorkspaceTarget(folder).read(reader).isPublicRepository
1123
+ );
1124
+ });
1010
1125
  const sessionTypePicker = disposables.add(
1011
1126
  instantiationService.createInstance(MobileSessionTypePicker, constObservable(undefined), {
1012
1127
  persistSelection: false,
1013
- telemetrySource: "AutomationSessionTypePicker"
1128
+ preserveUnavailableSelection: true,
1129
+ telemetrySource: "AutomationSessionTypePicker",
1130
+ allowedProviders: pickerProviders,
1131
+ prepareSessionTypeSelection: () => workspacePicker.onWillSelectWorkspace()
1014
1132
  })
1015
1133
  );
1016
1134
  sessionTypePicker.setQuickChatSource(isolationModel.isQuickChatObs);
@@ -1028,9 +1146,51 @@ function renderForm(
1028
1146
  onDidChangeActiveSessionProvider: onDidChangeSessionType.event
1029
1147
  };
1030
1148
  const syncStateFromPicker = () => {
1031
- const pick = sessionTypePicker.selectedPick;
1149
+ if (switchingTarget) {
1150
+ return;
1151
+ }
1152
+ let pick = sessionTypePicker.selectedPick;
1153
+ if (!isEdit && pick && getProviderConfiguration(pick.providerId)?.getWorkspaceTarget(state.folderUri).get().isPublicRepository) {
1154
+ const localTypes = sessionTypes.get().filter(
1155
+ type => pickerProviders.get().includes(type.providerId) && !getProviderConfiguration(type.providerId)
1156
+ );
1157
+ const fallback = localTypes.find(type => type.sessionType.id === SessionType.CopilotCLI) ?? localTypes.find(
1158
+ type => type.providerId === localTarget.providerId && type.sessionType.id === localTarget.sessionTypeId
1159
+ ) ?? localTypes[0];
1160
+ if (fallback) {
1161
+ sessionTypePicker.setFolderSource(isolationModel.folderUriObs, {
1162
+ initialPick: {
1163
+ providerId: fallback.providerId,
1164
+ sessionTypeId: fallback.sessionType.id
1165
+ }
1166
+ });
1167
+ pick = sessionTypePicker.selectedPick;
1168
+ }
1169
+ }
1032
1170
  state.providerId = pick?.providerId;
1033
1171
  state.sessionTypeId = pick?.sessionTypeId;
1172
+ const wasCloud = selectedProvider.get() !== undefined && getProviderConfiguration(selectedProvider.get()) !== undefined;
1173
+ selectedProvider.set(state.providerId, undefined);
1174
+ const configuration = cloudConfiguration.get();
1175
+ const target = configuration?.getWorkspaceTarget(state.folderUri).get();
1176
+ state.resolvedFolderUri = target?.workspace;
1177
+ state.targetPending = target?.pending ? {
1178
+ message: target.disabledReason ?? ( localize(3704, "Checking target availability..."))
1179
+ } : undefined;
1180
+ state.targetDisabledReason = target?.pending ? undefined : target?.disabledReason;
1181
+ state.timeZone = configuration?.timeZone;
1182
+ if (runInCloud.get()) {
1183
+ state.isolationMode = undefined;
1184
+ state.branch = undefined;
1185
+ if (configuration && isEdit && initialTarget?.kind === "workspace" && target?.workspace && !isEqual(initialTarget.folderUri, target.workspace)) {
1186
+ state.targetDisabledReason = configuration.targetChangeDisabledReason;
1187
+ }
1188
+ } else if (wasCloud && isEqual(state.folderUri, localTarget.folderUri)) {
1189
+ state.isolationMode = localTarget.isolationMode;
1190
+ if (localTarget.branch) {
1191
+ isolationModel.selectBranch(localTarget.branch);
1192
+ }
1193
+ }
1034
1194
  onDidChangeSessionTarget.fire();
1035
1195
  };
1036
1196
  disposables.add(autorun(reader => {
@@ -1043,7 +1203,9 @@ function renderForm(
1043
1203
  const workspacePicker = disposables.add(instantiationService.createInstance(MobileAutomationsWorkspacePicker, {
1044
1204
  restoreFromSessions: false,
1045
1205
  canRestoreWorkspace: () => false,
1046
- canSelectWorkspace: (folderUri, preferredProviderId) => canSelectAutomationWorkspace(
1206
+ canSelectWorkspace: (folderUri, preferredProviderId) => folderUri.scheme === GITHUB_REMOTE_FILE_SCHEME ? Promise.resolve(
1207
+ availableCloudConfiguration.get()?.getWorkspaceTarget(folderUri).get().workspace !== undefined
1208
+ ) : canSelectAutomationWorkspace(
1047
1209
  folderUri,
1048
1210
  preferredProviderId,
1049
1211
  sessionsManagementService,
@@ -1052,6 +1214,14 @@ function renderForm(
1052
1214
  }));
1053
1215
  workspacePicker.setTargetModel(isolationModel);
1054
1216
  workspacePicker.setLayoutService(layoutService);
1217
+ workspacePicker.setCloudConfiguration(availableCloudConfiguration);
1218
+ if (isEdit && initialProviderConfiguration) {
1219
+ workspacePicker.setDisabledReason(initialProviderConfiguration.targetChangeDisabledReason);
1220
+ }
1221
+ workspacePicker.onSelectionError = error => {
1222
+ logService.error("[AutomationDialog] Workspace selection failed.", error);
1223
+ notifyError(error);
1224
+ };
1055
1225
  const automationSessionDraftSynchronizer = disposables.add(( new AutomationSessionDraftSynchronizer(
1056
1226
  sessionsManagementService,
1057
1227
  (folderUri, preferredProviderId) => canSelectAutomationWorkspace(
@@ -1082,10 +1252,13 @@ function renderForm(
1082
1252
  return initialSessionConfiguration;
1083
1253
  };
1084
1254
  const updateAutomationSessionTarget = () => {
1085
- const folderUri = isolationModel.folderUriObs.get();
1255
+ if (switchingTarget) {
1256
+ return;
1257
+ }
1258
+ const folderUri = runInCloud.get() ? state.resolvedFolderUri : isolationModel.folderUriObs.get();
1086
1259
  const pick = sessionTypePicker.selectedPick;
1087
1260
  const isQuickChat = isolationModel.isQuickChatObs.get();
1088
- if (!pick || (isQuickChat && !pick.providerId) || (!isQuickChat && !folderUri)) {
1261
+ if (!pick || state.targetDisabledReason || state.targetPending || pick.providerId === undefined || !allowedProviders.get().includes(pick.providerId) || (!isQuickChat && !folderUri)) {
1089
1262
  automationSessionDraftSynchronizer.update(undefined);
1090
1263
  return;
1091
1264
  }
@@ -1114,38 +1287,144 @@ function renderForm(
1114
1287
  updateAutomationSessionTarget();
1115
1288
  revalidate();
1116
1289
  }));
1117
- disposables.add(
1118
- sessionsManagementService.onDidChangeSessionTypes(() => updateAutomationSessionTarget())
1119
- );
1290
+ disposables.add(sessionsManagementService.onDidChangeSessionTypes(() => {
1291
+ updateAutomationSessionTarget();
1292
+ revalidate();
1293
+ }));
1294
+ disposables.add(autorun(reader => {
1295
+ allowedProviders.read(reader);
1296
+ pickerProviders.read(reader);
1297
+ sessionTypes.read(reader);
1298
+ cloudConfiguration.read(reader)?.getWorkspaceTarget(isolationModel.folderUriObs.read(reader)).read(reader);
1299
+ syncStateFromPicker();
1300
+ updateAutomationSessionTarget();
1301
+ revalidate();
1302
+ }));
1120
1303
  if (state.folderUri) {
1121
1304
  workspacePicker.setSelectedWorkspace(state.folderUri, {
1122
1305
  fireEvent: false,
1123
1306
  persist: false
1124
1307
  });
1125
1308
  }
1126
- disposables.add(workspacePicker.onDidSelectWorkspace(uri => {
1127
- if (isolationModel.setWorkspace(uri)) {
1128
- updateAutomationSessionTarget();
1129
- revalidate();
1309
+ const targetSwitchCancellation = cancelOnDispose(disposables);
1310
+ workspacePicker.onWillSelectWorkspace = async () => {
1311
+ if (switchingTarget) {
1312
+ return false;
1130
1313
  }
1131
- }));
1132
- disposables.add(autorun(reader => {
1133
- isolationModel.isQuickChatObs.read(reader);
1314
+ if (!runInCloud.get()) {
1315
+ localTarget = {
1316
+ ...state,
1317
+ branch: isolationModel.persistedBranch
1318
+ };
1319
+ }
1320
+ switchingTarget = true;
1321
+ formContent.toggleAttribute("inert", true);
1322
+ formContent.setAttribute("aria-busy", "true");
1323
+ state.targetDisabledReason = undefined;
1324
+ state.targetPending = {
1325
+ message: ( localize(3705, "Saving the current session configuration..."))
1326
+ };
1327
+ revalidate();
1328
+ try {
1329
+ const capture = await automationSessionDraftSynchronizer.getSessionConfiguration(targetSwitchCancellation);
1330
+ if (capture.kind === "failed") {
1331
+ throw capture.error;
1332
+ }
1333
+ return !disposables.isDisposed;
1334
+ } catch (error) {
1335
+ if (!isCancellationError(error) && !disposables.isDisposed) {
1336
+ logService.error(
1337
+ "[AutomationDialog] Failed to capture the outgoing session configuration.",
1338
+ error
1339
+ );
1340
+ sessionConfigurationErrorMessage.set(getErrorMessage(error), undefined);
1341
+ }
1342
+ return false;
1343
+ } finally {
1344
+ switchingTarget = false;
1345
+ if (!disposables.isDisposed) {
1346
+ formContent.toggleAttribute("inert", false);
1347
+ formContent.setAttribute("aria-busy", "false");
1348
+ syncStateFromPicker();
1349
+ updateAutomationSessionTarget();
1350
+ revalidate();
1351
+ }
1352
+ }
1353
+ };
1354
+ const applyWorkspaceTarget = uri => {
1355
+ if (switchingTarget) {
1356
+ return;
1357
+ }
1358
+ switchingTarget = true;
1359
+ transaction(() => {
1360
+ const wasCloud = runInCloud.get();
1361
+ const currentPick = sessionTypePicker.selectedPick;
1362
+ isolationModel.setQuickChat(!uri, uri);
1363
+ const types = sessionTypes.get().filter(type => pickerProviders.get().includes(type.providerId));
1364
+ const preferred = workspacePicker.isSelectingRepository ? types.find(
1365
+ type => getProviderConfiguration(type.providerId)?.sessionTypes.includes(type.sessionType.id)
1366
+ ) : types.find(
1367
+ type => type.providerId === currentPick?.providerId && type.sessionType.id === currentPick.sessionTypeId
1368
+ ) ?? types.find(
1369
+ type => type.providerId === localTarget.providerId && type.sessionType.id === localTarget.sessionTypeId
1370
+ );
1371
+ const first = preferred ?? types[0];
1372
+ const pick = first ? {
1373
+ providerId: first.providerId,
1374
+ sessionTypeId: first.sessionType.id
1375
+ } : undefined;
1376
+ sessionTypePicker.setFolderSource(isolationModel.folderUriObs, {
1377
+ initialPick: pick
1378
+ });
1379
+ state.providerId = pick?.providerId;
1380
+ state.sessionTypeId = pick?.sessionTypeId;
1381
+ selectedProvider.set(state.providerId, undefined);
1382
+ if (!runInCloud.get() && wasCloud && isEqual(uri, localTarget.folderUri)) {
1383
+ state.isolationMode = localTarget.isolationMode;
1384
+ if (localTarget.branch) {
1385
+ isolationModel.selectBranch(localTarget.branch);
1386
+ }
1387
+ }
1388
+ });
1389
+ switchingTarget = false;
1390
+ syncStateFromPicker();
1134
1391
  updateAutomationSessionTarget();
1135
1392
  revalidate();
1393
+ };
1394
+ disposables.add(workspacePicker.onDidSelectWorkspace(applyWorkspaceTarget));
1395
+ disposables.add(autorun(reader => {
1396
+ if (isolationModel.isQuickChatObs.read(reader)) {
1397
+ applyWorkspaceTarget(undefined);
1398
+ }
1136
1399
  }));
1137
- const sessionSection = append(formContent, $(".automation-session-section"));
1138
1400
  const targetRow = append(sessionSection, $(".automation-form-row.automation-target-row"));
1139
- const targetLabel = append(targetRow, $("span.automation-form-label", {
1140
- id: "automation-target-label"
1141
- }, ( localize(3330, "Target"))));
1142
1401
  const targetContainer = append(targetRow, $(".automation-target-toolbar", {
1143
1402
  role: "group",
1144
- "aria-labelledby": targetLabel.id
1403
+ "aria-label": ( localize(3706, "Target"))
1145
1404
  }));
1405
+ const targetError = append(targetRow, $("span.automation-target-error", {
1406
+ id: "automation-target-error",
1407
+ role: "status",
1408
+ "aria-live": "polite",
1409
+ "aria-atomic": "true"
1410
+ }));
1411
+ hide(targetError);
1412
+ const targetProgress = append(targetRow, $("span.automation-target-progress", {
1413
+ id: "automation-target-progress",
1414
+ role: "status",
1415
+ "aria-live": "polite",
1416
+ "aria-atomic": "true"
1417
+ }));
1418
+ hide(targetProgress);
1419
+ if (isEdit && initialProviderConfiguration) {
1420
+ append(targetRow, $(
1421
+ "span.automation-form-hint",
1422
+ undefined,
1423
+ initialProviderConfiguration.targetChangeDisabledReason
1424
+ ));
1425
+ }
1146
1426
  const promptSection = append(sessionSection, $(".automation-prompt-section"));
1147
1427
  const promptRow = append(promptSection, $(".automation-form-row"));
1148
- append(promptRow, $("span.automation-form-label", undefined, ( localize(3331, "Prompt"))));
1149
1428
  const promptHost = append(promptRow, $(".automation-form-prompt-host.interactive-session"));
1150
1429
  const editorOverflowWidgetsDomNode = layoutService.getContainer(getWindow(promptHost)).appendChild($(".chat-editor-overflow.automation-dialog-editor-overflow.monaco-editor"));
1151
1430
  disposables.add(toDisposable(() => editorOverflowWidgetsDomNode.remove()));
@@ -1171,7 +1450,6 @@ function renderForm(
1171
1450
  [ISessionModelSelection, sessionModelSelection]
1172
1451
  ))));
1173
1452
  const usesCombinedConfigPicker = SessionUsesCombinedConfigPickerContext.bindTo(scopedContextKeyService);
1174
- const sessionTypesChanged = observableSignalFromEvent(form, sessionsManagementService.onDidChangeSessionTypes);
1175
1453
  disposables.add(autorun(reader => {
1176
1454
  sessionTypesChanged.read(reader);
1177
1455
  const session = activeAutomationSession.read(reader);
@@ -1185,7 +1463,7 @@ function renderForm(
1185
1463
  targetContainer,
1186
1464
  Menus.AutomationsDialogTargetToolbar,
1187
1465
  {
1188
- ariaLabel: ( localize(3332, "Automation target options")),
1466
+ ariaLabel: ( localize(3707, "Automation target options")),
1189
1467
  telemetrySource: "automations.dialog",
1190
1468
  hiddenItemStrategy: HiddenItemStrategy.NoHide,
1191
1469
  responsiveBehavior: {
@@ -1280,42 +1558,19 @@ function renderForm(
1280
1558
  ));
1281
1559
  chatInput.render(promptHost, initialPrompt, stubWidget);
1282
1560
  chatInput.inputEditor.updateOptions({
1283
- placeholder: ( localize(3333, "Describe what you want to automate"))
1561
+ placeholder: ( localize(3708, "Describe what you want to automate"))
1284
1562
  });
1285
1563
  disposables.add(
1286
1564
  scopedInstantiationService.createInstance(AutomationInputCompletions, chatInput.inputEditor)
1287
1565
  );
1288
- const sessionConfigurationRow = append(promptSection, $(".automation-form-row"));
1289
- const sessionConfigurationLabel = append(sessionConfigurationRow, $("span.automation-form-label", {
1290
- id: "automation-session-configuration-label"
1291
- }, ( localize(3334, "Session configuration"))));
1292
- const sessionConfiguration = append(sessionConfigurationRow, $(".automation-session-configuration", {
1293
- role: "group",
1294
- "aria-labelledby": sessionConfigurationLabel.id
1295
- }));
1296
- const sessionConfigContainer = append(
1297
- sessionConfiguration,
1298
- $(".automation-session-config.sessions-chat-config-toolbar")
1299
- );
1300
- const compactModelPicker = observableValue(sessionConfigContainer, false);
1301
- const sessionConfigToolbar = disposables.add(createNewSessionConfigToolbar(
1302
- sessionConfigContainer,
1303
- scopedInstantiationService,
1304
- compactModelPicker,
1305
- ( localize(3335, "Session configuration options"))
1306
- ));
1566
+ const sessionConfigContainer = chatInput.inputToolbarElement;
1567
+ sessionConfigContainer.classList.add("automation-session-config", "sessions-chat-config-toolbar");
1568
+ chatInput.setInputToolbarAriaLabel(( localize(3709, "Session configuration options")));
1569
+ const sessionConfiguration = append(promptSection, $(".automation-session-configuration"));
1307
1570
  const sessionControlsContainer = append(sessionConfiguration, $(".automation-session-controls"));
1308
1571
  const sessionControlsToolbar = disposables.add(
1309
- createNewSessionControlToolbar(sessionControlsContainer, scopedInstantiationService, ( localize(3336, "Session controls")))
1572
+ createNewSessionControlToolbar(sessionControlsContainer, scopedInstantiationService, ( localize(3710, "Session controls")))
1310
1573
  );
1311
- const sessionConfigLayout = disposables.add(( new ChatInputPickerResponsiveLayout("AutomationDialog.sessionConfig", sessionConfigContainer, {
1312
- getItems: () => getAutomationToolbarResponsiveItems(sessionConfigToolbar, {
1313
- compactModelPicker
1314
- }),
1315
- hasOverflow: () => sessionConfigToolbar.hasOverflow(),
1316
- relayout: () => sessionConfigToolbar.relayout()
1317
- })));
1318
- sessionConfigLayout.layout();
1319
1574
  const sessionControlsLayout = disposables.add(( new ChatInputPickerResponsiveLayout("AutomationDialog.sessionControls", sessionControlsContainer, {
1320
1575
  getItems: () => getAutomationToolbarResponsiveItems(sessionControlsToolbar),
1321
1576
  hasOverflow: () => sessionControlsToolbar.hasOverflow(),
@@ -1329,24 +1584,24 @@ function renderForm(
1329
1584
  "aria-atomic": "true"
1330
1585
  })
1331
1586
  );
1332
- const sessionConfigurationError = append(sessionConfiguration, $("span.automation-session-configuration-error", {
1333
- role: "alert",
1334
- tabindex: "-1"
1335
- }));
1336
- hide(sessionConfigurationError);
1337
1587
  disposables.add(autorun(reader => {
1338
1588
  const hasTarget = isolationModel.isQuickChatObs.read(reader) || isolationModel.folderUriObs.read(reader) !== undefined;
1339
- setAutomationControlVisible(sessionConfigurationRow, hasTarget);
1589
+ const cloud = runInCloud.read(reader);
1590
+ setAutomationControlVisible(sessionConfigContainer, hasTarget);
1591
+ setAutomationControlVisible(sessionControlsContainer, hasTarget && !cloud);
1340
1592
  const availability = automationSessionDraftSynchronizer.availability.read(reader);
1341
1593
  const pending = availability === "pending";
1342
1594
  const controlsUnavailable = availability !== "available";
1343
- sessionConfiguration.classList.toggle("controls-unavailable", controlsUnavailable);
1595
+ setAutomationControlVisible(sessionConfiguration, hasTarget && (!cloud || controlsUnavailable));
1344
1596
  for (const container of [sessionConfigContainer, sessionControlsContainer]) {
1597
+ container.classList.toggle("controls-unavailable", controlsUnavailable);
1345
1598
  container.toggleAttribute("inert", controlsUnavailable);
1346
- container.setAttribute("aria-hidden", String(controlsUnavailable));
1599
+ container.setAttribute("aria-hidden", String(
1600
+ !hasTarget || controlsUnavailable || cloud && container === sessionControlsContainer
1601
+ ));
1347
1602
  container.setAttribute("aria-busy", String(pending));
1348
1603
  }
1349
- sessionConfigurationUnavailable.textContent = pending ? ( localize(3337, "Loading session configuration…")) : hasTarget && controlsUnavailable ? ( localize(3338, "Session configuration unavailable")) : "";
1604
+ sessionConfigurationUnavailable.textContent = pending ? ( localize(3711, "Loading session configuration…")) : hasTarget && controlsUnavailable ? ( localize(3712, "Session configuration unavailable")) : "";
1350
1605
  }));
1351
1606
  disposables.add(chatInput.inputEditor.onDidChangeModelContent(() => {
1352
1607
  revalidate();
@@ -1374,61 +1629,302 @@ function renderForm(
1374
1629
  }, getWindow(promptHost))
1375
1630
  );
1376
1631
  disposables.add(resizeObserver.observe(promptHost));
1377
- const enabledRow = append(formContent, $(".automation-form-row.automation-form-checkbox-row"));
1378
- const enabledLabelText = ( localize(3339, "Enabled (the scheduler runs this automation when due)"));
1379
- const enabledCheckbox = disposables.add(( new Checkbox(enabledLabelText, state.enabled, defaultCheckboxStyles)));
1380
- append(enabledRow, enabledCheckbox.domNode);
1381
- const enabledLabel = append(
1382
- enabledRow,
1383
- $("span.automation-form-checkbox-label", undefined, enabledLabelText)
1384
- );
1385
- const setEnabled = value => {
1386
- if (enabledCheckbox.checked !== value) {
1387
- enabledCheckbox.checked = value;
1388
- }
1389
- state.enabled = value;
1632
+ const providerDetails = append(promptSection, $(".automation-provider-details.automation-form-row", {
1633
+ role: "group",
1634
+ "aria-labelledby": "automation-tools-label"
1635
+ }));
1636
+ append(providerDetails, $("span.automation-form-label", {
1637
+ id: "automation-tools-label"
1638
+ }, ( localize(3713, "Tools"))));
1639
+ append(providerDetails, $("p", {
1640
+ id: "automation-tools-description"
1641
+ }, ( localize(
1642
+ 3714,
1643
+ "Select which tools the agent can use. Built-in tools are always available."
1644
+ ))));
1645
+ const toolsContainer = append(providerDetails, $(".automation-provider-tools"));
1646
+ const toolsButton = disposables.add(( new Button(toolsContainer, {
1647
+ ...defaultButtonStyles,
1648
+ secondary: true
1649
+ })));
1650
+ toolsButton.label = ( localize(3715, "Configure allowed tools"));
1651
+ toolsButton.element.setAttribute("aria-haspopup", "dialog");
1652
+ toolsButton.element.setAttribute("aria-describedby", "automation-tools-description");
1653
+ const toolsNotReported = append(toolsContainer, $("p", undefined, ( localize(
1654
+ 3716,
1655
+ "GitHub did not report the saved tool selection. Unchanged permissions will be preserved. Select tools to replace it explicitly."
1656
+ ))));
1657
+ const toolsStatus = append(providerDetails, $(".automation-provider-tools-status", {
1658
+ role: "status",
1659
+ "aria-live": "polite"
1660
+ }));
1661
+ const toolsStatusText = append(toolsStatus, $("span"));
1662
+ const toolsRetry = disposables.add(( new Button(toolsStatus, {
1663
+ ...defaultButtonStyles,
1664
+ secondary: true
1665
+ })));
1666
+ toolsRetry.label = ( localize(3717, "Retry"));
1667
+ const toolsPicker = disposables.add(( new MutableDisposable()));
1668
+ let selectedTools;
1669
+ let selectAllCatalogTools = false;
1670
+ let toolsInitialized = false;
1671
+ let toolCatalog = {
1672
+ kind: "loading"
1390
1673
  };
1391
- disposables.add(enabledCheckbox.onChange(() => {
1392
- state.enabled = enabledCheckbox.checked;
1674
+ const catalogToolIds = catalog => catalog.kind === "ready" ? [...( new Set(catalog.groups.flatMap(group => group.tools.map(tool => tool.id))))] : [];
1675
+ const updateToolsControls = () => {
1676
+ const ready = toolCatalog.kind === "ready";
1677
+ if (ready && selectAllCatalogTools) {
1678
+ selectedTools = catalogToolIds(toolCatalog);
1679
+ selectAllCatalogTools = false;
1680
+ }
1681
+ toolsButton.enabled = ready && !!quickInputService;
1682
+ const ids = ( new Set([...catalogToolIds(toolCatalog), ...(selectedTools ?? [])]));
1683
+ if (ready && selectedTools) {
1684
+ toolsButton.element.setAttribute("aria-description", ( localize(3718, "{0} of {1} tools selected", selectedTools.length, ids.size)));
1685
+ } else {
1686
+ toolsButton.element.removeAttribute("aria-description");
1687
+ }
1688
+ setAutomationControlVisible(toolsNotReported, selectedTools === undefined && !selectAllCatalogTools);
1689
+ toolsStatusText.textContent = toolCatalog.kind === "loading" ? ( localize(3719, "Loading available tools...")) : toolCatalog.kind === "error" ? toolCatalog.message : "";
1690
+ setAutomationControlVisible(toolsStatus, !ready);
1691
+ setAutomationControlVisible(toolsRetry.element, toolCatalog.kind === "error");
1692
+ };
1693
+ disposables.add(toolsRetry.onDidClick(() => cloudConfiguration.get()?.loadTools()));
1694
+ disposables.add(toolsButton.onDidClick(() => {
1695
+ if (!quickInputService || toolCatalog.kind !== "ready") {
1696
+ return;
1697
+ }
1698
+ const store = ( new DisposableStore());
1699
+ let disposing = false;
1700
+ store.add(toDisposable(() => disposing = true));
1701
+ toolsPicker.value = store;
1702
+ const shown = ( new Set());
1703
+ const toItem = tool => {
1704
+ shown.add(tool.id);
1705
+ return {
1706
+ id: tool.id,
1707
+ label: tool.label,
1708
+ description: tool.description,
1709
+ checked: selectedTools?.includes(tool.id) === true
1710
+ };
1711
+ };
1712
+ const items = [];
1713
+ for (const group of toolCatalog.groups) {
1714
+ const children = group.tools.filter(tool => !( shown.has(tool.id))).map(toItem);
1715
+ if (children.length) {
1716
+ items.push({
1717
+ label: group.label,
1718
+ children
1719
+ });
1720
+ }
1721
+ }
1722
+ const unknown = (selectedTools ?? []).filter(id => !( shown.has(id)));
1723
+ if (unknown.length) {
1724
+ items.push({
1725
+ label: ( localize(3720, "Other Saved Tools")),
1726
+ children: unknown.map(id => toItem({
1727
+ id,
1728
+ label: id
1729
+ }))
1730
+ });
1731
+ }
1732
+ const picker = store.add(quickInputService.createQuickTree());
1733
+ picker.title = ( localize(3721, "Allowed Tools"));
1734
+ picker.placeholder = ( localize(3722, "Search tools"));
1735
+ picker.matchOnDescription = true;
1736
+ picker.sortByLabel = false;
1737
+ picker.setItemTree(items);
1738
+ store.add(picker.onDidAccept(() => {
1739
+ selectedTools = picker.checkedLeafItems.flatMap(item => item.id ? [item.id] : []);
1740
+ updateToolsControls();
1741
+ picker.hide();
1742
+ }));
1743
+ store.add(picker.onDidHide(() => {
1744
+ if (disposing) {
1745
+ return;
1746
+ }
1747
+ toolsPicker.clear();
1748
+ toolsButton.focus();
1749
+ }));
1750
+ picker.show();
1393
1751
  }));
1394
- disposables.add(addStandardDisposableListener(enabledLabel, "click", () => {
1395
- setEnabled(!enabledCheckbox.checked);
1752
+ disposables.add(autorun(reader => {
1753
+ const configuration = cloudConfiguration.read(reader);
1754
+ toolsPicker.clear();
1755
+ updateIntervalOptions(configuration !== undefined);
1756
+ setAutomationControlVisible(providerDetails, configuration !== undefined);
1757
+ timeLabel.textContent = configuration?.timeZone === "UTC" ? ( localize(3723, "Time (Local)")) : ( localize(3701, "Time"));
1758
+ timeSelect.setAriaLabel(timeLabel.textContent);
1759
+ if (!configuration) {
1760
+ return;
1761
+ }
1762
+ if (!toolsInitialized) {
1763
+ const stored = initialProviderConfiguration ? initialSessionConfiguration?.sessionTemplate?.config?.tools : undefined;
1764
+ selectedTools = isStringArray(stored) ? [...stored] : undefined;
1765
+ selectAllCatalogTools = selectedTools === undefined && !(isEdit && initialProviderConfiguration);
1766
+ toolsInitialized = true;
1767
+ }
1768
+ }));
1769
+ disposables.add(autorun(reader => {
1770
+ const configuration = cloudConfiguration.read(reader);
1771
+ toolCatalog = configuration?.tools.read(reader) ?? {
1772
+ kind: "loading"
1773
+ };
1774
+ if (toolCatalog.kind === "loading") {
1775
+ configuration?.loadTools();
1776
+ }
1777
+ updateToolsControls();
1778
+ }));
1779
+ const resolveSelectedTools = async (configuration, token) => {
1780
+ if (!selectAllCatalogTools) {
1781
+ return selectedTools;
1782
+ }
1783
+ configuration.loadTools();
1784
+ const cts = ( new CancellationTokenSource(token));
1785
+ let catalog;
1786
+ try {
1787
+ catalog = await waitForState(
1788
+ configuration.tools,
1789
+ catalog => catalog.kind !== "loading",
1790
+ undefined,
1791
+ cts.token
1792
+ );
1793
+ } finally {
1794
+ cts.dispose(true);
1795
+ }
1796
+ if (catalog.kind === "error") {
1797
+ throw ( new Error(catalog.message));
1798
+ }
1799
+ updateToolsControls();
1800
+ return selectedTools;
1801
+ };
1802
+ const customizationSelection = customizations ? disposables.add(( new AutomationCustomizationSelection(
1803
+ formContent,
1804
+ customizations.service,
1805
+ customizations.hoverService,
1806
+ logService,
1807
+ customizations.existingId
1808
+ ))) : undefined;
1809
+ reloadCustomizations = () => customizationSelection?.updateTarget(
1810
+ state.providerId && state.sessionTypeId && allowedProviders.get().includes(state.providerId) ? createAutomationTarget(state, isolationModel.persistedBranch) : undefined
1811
+ );
1812
+ disposables.add(onDidChangeSessionTarget.event(reloadCustomizations));
1813
+ disposables.add(autorun(reader => {
1814
+ isolationModel.isQuickChatObs.read(reader);
1815
+ isolationModel.folderUriObs.read(reader);
1816
+ allowedProviders.read(reader);
1817
+ reloadCustomizations();
1396
1818
  }));
1397
1819
  const saveStatus = append(form, $("span.automation-form-save-status", {
1398
1820
  role: "status",
1399
1821
  "aria-atomic": "true"
1400
1822
  }));
1823
+ const saveIcon = append(saveStatus, renderIcon(Codicon.loading));
1824
+ saveIcon.classList.add("codicon-modifier-spin");
1825
+ saveIcon.setAttribute("aria-hidden", "true");
1826
+ const saveStatusText = append(saveStatus, $("span"));
1401
1827
  hide(saveStatus);
1828
+ const saveError = append(form, $(".automation-form-save-error", {
1829
+ role: "alert",
1830
+ tabindex: "-1"
1831
+ }));
1832
+ append(saveError, renderIcon(Codicon.error)).setAttribute("aria-hidden", "true");
1833
+ const saveErrorText = append(saveError, $("span"));
1834
+ hide(saveError);
1835
+ disposables.add(autorun(reader => {
1836
+ const message = sessionConfigurationErrorMessage.read(reader);
1837
+ setAutomationControlVisible(saveError, !!message);
1838
+ saveErrorText.textContent = message ?? "";
1839
+ }));
1402
1840
  return {
1403
1841
  getPrompt: () => chatInput.inputEditor.getValue(),
1404
- getSessionConfiguration: token => automationSessionDraftSynchronizer.getSessionConfiguration(token),
1842
+ getSessionConfiguration: async token => {
1843
+ const captured = await automationSessionDraftSynchronizer.getSessionConfiguration(token);
1844
+ const configuration = cloudConfiguration.get();
1845
+ if (captured.kind === "failed" || !configuration) {
1846
+ return captured;
1847
+ }
1848
+ let tools;
1849
+ try {
1850
+ tools = await resolveSelectedTools(configuration, token);
1851
+ } catch (error) {
1852
+ return {
1853
+ kind: "failed",
1854
+ error
1855
+ };
1856
+ }
1857
+ if (tools === undefined) {
1858
+ return captured;
1859
+ }
1860
+ return {
1861
+ kind: "captured",
1862
+ configuration: {
1863
+ ...captured.configuration,
1864
+ sessionTemplate: {
1865
+ ...captured.configuration?.sessionTemplate,
1866
+ config: {
1867
+ ...captured.configuration?.sessionTemplate?.config,
1868
+ tools
1869
+ }
1870
+ }
1871
+ }
1872
+ };
1873
+ },
1405
1874
  getBranch: () => isolationModel.persistedBranch,
1875
+ providerDescription: derived(reader => cloudConfiguration.read(reader)?.description),
1876
+ showScheduleValidationError: message => {
1877
+ scheduleError.textContent = message ?? "";
1878
+ setAutomationControlVisible(scheduleError, message !== undefined);
1879
+ },
1880
+ getCustomizationIds: () => customizationSelection?.getSelectedIds(),
1881
+ waitForCustomizationChoices: async token => customizationSelection?.waitForChoices(token),
1882
+ showTargetValidationError: message => {
1883
+ const text = message ?? "";
1884
+ const pending = state.targetPending;
1885
+ setAutomationControlVisible(targetProgress, !!pending && message === undefined);
1886
+ const progressText = pending?.message ?? "";
1887
+ if (targetProgress.textContent !== progressText) {
1888
+ targetProgress.textContent = progressText;
1889
+ }
1890
+ targetContainer.setAttribute("aria-busy", String(!!pending));
1891
+ if (message !== undefined) {
1892
+ show(targetError);
1893
+ targetContainer.setAttribute("aria-describedby", targetError.id);
1894
+ targetContainer.setAttribute("aria-invalid", "true");
1895
+ } else {
1896
+ hide(targetError);
1897
+ if (pending) {
1898
+ targetContainer.setAttribute("aria-describedby", targetProgress.id);
1899
+ } else {
1900
+ targetContainer.removeAttribute("aria-describedby");
1901
+ }
1902
+ targetContainer.removeAttribute("aria-invalid");
1903
+ }
1904
+ if (targetError.textContent !== text) {
1905
+ targetError.textContent = text;
1906
+ }
1907
+ },
1406
1908
  waitForAutomationSessionSync: token => {
1407
1909
  updateAutomationSessionTarget();
1408
1910
  return automationSessionDraftSynchronizer.waitForSync(token);
1409
1911
  },
1410
- setSaving: saving => {
1912
+ setSaving: (saving, committing) => {
1411
1913
  formContent.toggleAttribute("inert", saving);
1412
1914
  formContent.setAttribute("aria-busy", String(saving));
1413
1915
  form.classList.toggle("saving", saving);
1414
1916
  if (saving) {
1415
1917
  show(saveStatus);
1416
- saveStatus.textContent = ( localize(3340, "Saving automation…"));
1918
+ saveStatusText.textContent = committing && customizationSelection?.getSelectedIds()?.length ? ( localize(3724, "Syncing customizations…")) : ( localize(3725, "Saving automation…"));
1417
1919
  } else {
1418
1920
  hide(saveStatus);
1419
- saveStatus.textContent = "";
1921
+ saveStatusText.textContent = "";
1420
1922
  }
1421
1923
  },
1422
- showSessionConfigurationError: message => {
1423
- if (message) {
1424
- show(sessionConfigurationError);
1425
- sessionConfigurationError.textContent = message;
1426
- } else {
1427
- hide(sessionConfigurationError);
1428
- sessionConfigurationError.textContent = "";
1429
- }
1924
+ showSaveError: message => {
1925
+ sessionConfigurationErrorMessage.set(message, undefined);
1430
1926
  },
1431
- focusSessionConfigurationError: () => sessionConfigurationError.focus(),
1927
+ focusSaveError: () => saveError.focus(),
1432
1928
  getFocusableElements: () => {
1433
1929
  return Array.from(
1434
1930
  form.querySelectorAll("input, select, textarea, button, a[href], [tabindex]")
@@ -1452,10 +1948,229 @@ function renderForm(
1452
1948
  }
1453
1949
  };
1454
1950
  }
1455
- function buildTimeOptions() {
1951
+ class AutomationCustomizationSelection extends Disposable {
1952
+ constructor(container, service, hoverService, logService, existingId) {
1953
+ super();
1954
+ this.service = service;
1955
+ this.hoverService = hoverService;
1956
+ this.logService = logService;
1957
+ this.existingId = existingId;
1958
+ this.rows = this._register(( new DisposableStore()));
1959
+ this.request = this._register(( new MutableDisposable()));
1960
+ this.toggles = ( new Map());
1961
+ this.loading = Promise.resolve();
1962
+ this.expanded = false;
1963
+ this._register(toDisposable(() => this.request.value?.cancel()));
1964
+ this.section = append(container, $(".automation-advanced"));
1965
+ this.disclosure = this._register(( new Button(this.section, {
1966
+ ...unthemedButtonStyles,
1967
+ secondary: true
1968
+ })));
1969
+ this.disclosure.element.classList.add("automation-advanced-disclosure", "automation-form-label");
1970
+ this.chevron = append(this.disclosure.element, $("span.automation-advanced-chevron", {
1971
+ "aria-hidden": "true"
1972
+ }));
1973
+ append(this.chevron, renderIcon(Codicon.chevronRight));
1974
+ append(this.disclosure.element, $("span", undefined, ( localize(3726, "Advanced"))));
1975
+ this.summary = append(this.disclosure.element, $("span.automation-advanced-summary"));
1976
+ this.content = append(this.section, $(".automation-customizations", {
1977
+ id: "automation-customizations"
1978
+ }));
1979
+ this.disclosure.element.setAttribute("aria-controls", this.content.id);
1980
+ this.disclosure.element.setAttribute("aria-expanded", "false");
1981
+ hide(this.section, this.content);
1982
+ this._register(this.disclosure.onDidClick(() => {
1983
+ this.expanded = !this.expanded;
1984
+ this.disclosure.element.setAttribute("aria-expanded", String(this.expanded));
1985
+ reset(
1986
+ this.chevron,
1987
+ renderIcon(this.expanded ? Codicon.chevronDown : Codicon.chevronRight)
1988
+ );
1989
+ this.content.hidden = !this.expanded;
1990
+ this.content.style.display = this.expanded ? "" : "none";
1991
+ this.summary.hidden = this.expanded;
1992
+ }));
1993
+ }
1994
+ getSelectedIds() {
1995
+ return this.choices?.filter(choice => this.toggles.get(choice.id) ?? choice.selected).map(choice => choice.id);
1996
+ }
1997
+ async waitForChoices(token) {
1998
+ await raceCancellationError(this.loading, token);
1999
+ }
2000
+ updateTarget(target) {
2001
+ const key = target ? JSON.stringify({
2002
+ kind: target.kind,
2003
+ providerId: target.providerId,
2004
+ sessionTypeId: target.sessionTypeId,
2005
+ folder: target.kind === "workspace" ? getComparisonKey(target.folderUri) : undefined,
2006
+ isolation: target.kind === "workspace" ? target.isolation : undefined
2007
+ }) : undefined;
2008
+ if (key === this.targetKey) {
2009
+ return;
2010
+ }
2011
+ this.targetKey = key;
2012
+ this.request.value?.cancel();
2013
+ this.request.clear();
2014
+ this.choices = undefined;
2015
+ this.rows.clear();
2016
+ clearNode(this.content);
2017
+ if (!target || !target.providerId || !target.sessionTypeId || !this.service.getCustomizationChoices) {
2018
+ hide(this.section);
2019
+ return;
2020
+ }
2021
+ show(this.section);
2022
+ this.summary.textContent = ( localize(3727, "Loading…"));
2023
+ const loading = append(this.content, $(".automation-customizations-message", {
2024
+ role: "status"
2025
+ }));
2026
+ const icon = append(loading, renderIcon(Codicon.loading));
2027
+ icon.classList.add("codicon-modifier-spin");
2028
+ icon.setAttribute("aria-hidden", "true");
2029
+ append(loading, $("span", undefined, ( localize(3728, "Loading customizations…"))));
2030
+ const request = ( new CancellationTokenSource());
2031
+ this.request.value = request;
2032
+ this.loading = this.load(target, request);
2033
+ }
2034
+ async load(target, request) {
2035
+ try {
2036
+ const choices = await this.service.getCustomizationChoices?.(target, this.existingId, request.token);
2037
+ if (request.token.isCancellationRequested || this._store.isDisposed) {
2038
+ return;
2039
+ }
2040
+ this.choices = choices;
2041
+ if (choices === undefined) {
2042
+ hide(this.section);
2043
+ return;
2044
+ }
2045
+ this.renderChoices(choices);
2046
+ } catch (error) {
2047
+ if (!request.token.isCancellationRequested && !this._store.isDisposed) {
2048
+ this.logService.error("[AutomationDialog] Failed to load customization choices.", error);
2049
+ hide(this.section);
2050
+ }
2051
+ }
2052
+ }
2053
+ updateSummary() {
2054
+ const outdated = this.choices?.filter(choice => choice.outdated).length ?? 0;
2055
+ this.summary.textContent = outdated ? ( localize(
2056
+ 3729,
2057
+ "{0} of {1} customizations · {2} outdated",
2058
+ this.getSelectedIds()?.length ?? 0,
2059
+ this.choices?.length ?? 0,
2060
+ outdated
2061
+ )) : ( localize(
2062
+ 3730,
2063
+ "{0} of {1} customizations",
2064
+ this.getSelectedIds()?.length ?? 0,
2065
+ this.choices?.length ?? 0
2066
+ ));
2067
+ }
2068
+ renderChoices(choices) {
2069
+ clearNode(this.content);
2070
+ append(this.content, $("span.automation-form-label", undefined, ( localize(3731, "Customizations"))));
2071
+ append(
2072
+ this.content,
2073
+ $("p.automation-customizations-description", undefined, ( localize(
2074
+ 3732,
2075
+ "Choose which plugins and customizations runs of this automation can use."
2076
+ )))
2077
+ );
2078
+ if (!choices.length) {
2079
+ append(
2080
+ this.content,
2081
+ $("p.automation-customizations-description", undefined, ( localize(3733, "No customizations are available for this target.")))
2082
+ );
2083
+ }
2084
+ for (const [index, choice] of choices.entries()) {
2085
+ const row = append(this.content, $(".automation-customization-row"));
2086
+ const checkbox = this.rows.add(( new Checkbox(
2087
+ choice.label,
2088
+ this.toggles.get(choice.id) ?? choice.selected,
2089
+ defaultCheckboxStyles
2090
+ )));
2091
+ row.appendChild(checkbox.domNode);
2092
+ const text = append(row, $(".automation-customization-text"));
2093
+ const label = append(text, $("span.automation-customization-label", {
2094
+ id: `automation-customization-${index}`
2095
+ }, choice.label));
2096
+ checkbox.domNode.setAttribute("aria-labelledby", label.id);
2097
+ this.rows.add(this.hoverService.setupDelayedHover(label, {
2098
+ content: choice.label
2099
+ }));
2100
+ if (choice.description) {
2101
+ const description = append(text, $("span.automation-customization-description", {
2102
+ id: `automation-customization-description-${index}`
2103
+ }, choice.description));
2104
+ checkbox.domNode.setAttribute("aria-describedby", description.id);
2105
+ this.rows.add(this.hoverService.setupDelayedHover(description, {
2106
+ content: choice.description
2107
+ }));
2108
+ }
2109
+ if (choice.outdated) {
2110
+ const outdated = append(row, $("span.automation-customization-outdated", {
2111
+ id: `automation-customization-outdated-${index}`
2112
+ }, ( localize(3734, "Outdated"))));
2113
+ checkbox.domNode.setAttribute(
2114
+ "aria-describedby",
2115
+ choice.description ? `automation-customization-description-${index} ${outdated.id}` : outdated.id
2116
+ );
2117
+ }
2118
+ this.rows.add(checkbox.onChange(() => {
2119
+ this.toggles.set(choice.id, checkbox.checked);
2120
+ this.updateSummary();
2121
+ }));
2122
+ this.rows.add(addDisposableListener(text, EventType.CLICK, () => {
2123
+ checkbox.checked = !checkbox.checked;
2124
+ this.toggles.set(choice.id, checkbox.checked);
2125
+ this.updateSummary();
2126
+ checkbox.focus();
2127
+ }));
2128
+ }
2129
+ if (( choices.some(choice => choice.outdated))) {
2130
+ const hint = append(this.content, $(".automation-customizations-message"));
2131
+ append(hint, renderIcon(Codicon.info)).setAttribute("aria-hidden", "true");
2132
+ append(hint, $("span", undefined, ( localize(
2133
+ 3735,
2134
+ "Outdated customizations will be updated when the automation is saved."
2135
+ ))));
2136
+ }
2137
+ this.updateSummary();
2138
+ }
2139
+ }
2140
+ function createAutomationTarget(state, branch) {
2141
+ if (state.isQuickChat) {
2142
+ return state.providerId && state.sessionTypeId ? {
2143
+ kind: "quickChat",
2144
+ providerId: state.providerId,
2145
+ sessionTypeId: state.sessionTypeId
2146
+ } : undefined;
2147
+ }
2148
+ if (!state.folderUri) {
2149
+ return undefined;
2150
+ }
2151
+ const isolation = state.isolationMode === "worktree" ? (branch ? {
2152
+ kind: "worktree",
2153
+ branch
2154
+ } : undefined) : state.isolationMode === "workspace" ? {
2155
+ kind: "folder"
2156
+ } : {
2157
+ kind: "default"
2158
+ };
2159
+ return isolation ? {
2160
+ kind: "workspace",
2161
+ folderUri: state.resolvedFolderUri ?? state.folderUri,
2162
+ providerId: state.providerId,
2163
+ sessionTypeId: state.sessionTypeId,
2164
+ isolation
2165
+ } : undefined;
2166
+ }
2167
+ function buildTimeOptions(initialHour, initialMinute) {
1456
2168
  const options = [];
1457
2169
  for (let hour = 0; hour < 24; hour++) {
1458
- for (let minute = 0; minute < 60; minute += 15) {
2170
+ for (let minute = 0; minute < 60; minute++) {
2171
+ if (minute % 15 !== 0 && (hour !== initialHour || minute !== initialMinute)) {
2172
+ continue;
2173
+ }
1459
2174
  const period = hour < 12 ? "AM" : "PM";
1460
2175
  const hour12 = hour === 0 ? 12 : (hour > 12 ? hour - 12 : hour);
1461
2176
  const minuteText = ( minute.toString()).padStart(2, "0");
@@ -1468,22 +2183,67 @@ function buildTimeOptions() {
1468
2183
  }
1469
2184
  return options;
1470
2185
  }
1471
- function nearestTimeOptionIndex(hour, minute) {
1472
- const safeHour = Math.max(0, Math.min(23, hour | 0));
1473
- const safeMinute = Math.max(0, Math.min(59, minute | 0));
1474
- const slot = Math.round(safeMinute / 15) % 4;
1475
- const carriedHour = safeMinute >= 53 && slot === 0 ? (safeHour + 1) % 24 : safeHour;
1476
- return carriedHour * 4 + slot;
1477
- }
1478
- function updateSaveButtonState(saveButton, state, validation, form, getPrompt, getBranch) {
1479
- validation.nameError = state.name.trim() === "" ? ( localize(3341, "Name is required.")) : undefined;
1480
- validation.promptError = getPrompt().trim() === "" ? ( localize(3342, "Prompt is required.")) : undefined;
1481
- validation.folderError = !state.folderUri && !state.isQuickChat ? ( localize(3343, "Workspace folder is required.")) : undefined;
1482
- validation.sessionTypeError = !state.sessionTypeId || (state.isQuickChat && !state.providerId) ? ( localize(3344, "Session type is required.")) : undefined;
1483
- validation.branchError = !state.isQuickChat && state.isolationMode === "worktree" && !getBranch() ? ( localize(3345, "A branch is required for Worktree isolation.")) : undefined;
1484
- const valid = !validation.nameError && !validation.promptError && !validation.folderError && !validation.sessionTypeError && !validation.branchError;
2186
+ function updateSaveButtonState(
2187
+ saveButton,
2188
+ state,
2189
+ validation,
2190
+ form,
2191
+ getPrompt,
2192
+ getBranch,
2193
+ sessionsManagementService,
2194
+ providerAvailable = true,
2195
+ originalProviderId,
2196
+ requireName = true
2197
+ ) {
2198
+ validation.nameError = requireName && state.name.trim() === "" ? ( localize(3736, "Name is required.")) : undefined;
2199
+ validation.promptError = getPrompt().trim() === "" ? ( localize(3737, "Prompt is required.")) : undefined;
2200
+ validation.folderError = !state.folderUri && !state.isQuickChat ? ( localize(3738, "Workspace folder is required.")) : undefined;
2201
+ if (originalProviderId !== undefined && state.providerId !== originalProviderId) {
2202
+ validation.sessionTypeError = ( localize(
2203
+ 3739,
2204
+ "To use another Agent Host, duplicate this automation. The original keeps its schedule until you disable it."
2205
+ ));
2206
+ } else if (state.targetPending) {
2207
+ validation.sessionTypeError = undefined;
2208
+ } else if (state.targetDisabledReason !== undefined) {
2209
+ validation.sessionTypeError = state.targetDisabledReason;
2210
+ } else if (!providerAvailable) {
2211
+ validation.sessionTypeError = ( localize(3740, "Choose an available Agent Host that supports automations."));
2212
+ } else if (!state.sessionTypeId || !state.providerId) {
2213
+ validation.sessionTypeError = ( localize(3741, "Session type is required."));
2214
+ } else {
2215
+ const target = {
2216
+ providerId: state.providerId,
2217
+ sessionTypeId: state.sessionTypeId
2218
+ };
2219
+ if (state.isQuickChat && !sessionsManagementService.isQuickChatTargetAvailable(target)) {
2220
+ validation.sessionTypeError = ( localize(
2221
+ 3742,
2222
+ "The selected Agent Host and session type cannot run without a workspace. Choose a workspace or another session type."
2223
+ ));
2224
+ } else if (!state.isQuickChat && state.folderUri !== undefined && !sessionsManagementService.isNewSessionTargetAvailable(state.resolvedFolderUri ?? state.folderUri, target)) {
2225
+ validation.sessionTypeError = ( localize(
2226
+ 3743,
2227
+ "The selected Agent Host and session type cannot use this workspace. Choose another workspace or session type."
2228
+ ));
2229
+ } else {
2230
+ validation.sessionTypeError = undefined;
2231
+ }
2232
+ }
2233
+ validation.branchError = !state.isQuickChat && state.isolationMode === "worktree" && !getBranch() ? ( localize(3744, "A branch is required for Worktree isolation.")) : undefined;
2234
+ const utcSchedule = state.timeZone === "UTC" ? automationScheduleToUTC({
2235
+ interval: state.interval,
2236
+ scheduleHour: state.hour,
2237
+ scheduleMinute: state.minute,
2238
+ scheduleDay: state.day
2239
+ }, state.timezoneOffset) : undefined;
2240
+ validation.scheduleError = !( INTERVALS.some(item => item.value === state.interval)) ? ( localize(3745, "Choose a supported schedule.")) : utcSchedule && state.interval === "weekdays" ? ( localize(
2241
+ 3746,
2242
+ "Weekdays is only available for local automations. Choose a supported schedule for Cloud."
2243
+ )) : utcSchedule && (state.interval === "daily" || state.interval === "weekly") && utcSchedule.scheduleMinute % 15 !== 0 ? ( localize(3747, "Choose a time that corresponds to minute 00, 15, 30, or 45 in UTC.")) : undefined;
2244
+ const valid = !validation.nameError && !validation.promptError && !validation.folderError && !validation.sessionTypeError && !validation.branchError && !validation.scheduleError;
1485
2245
  if (saveButton) {
1486
- saveButton.enabled = valid;
2246
+ saveButton.enabled = valid && !state.targetPending;
1487
2247
  }
1488
2248
  form.classList.toggle("automation-form-invalid", !valid);
1489
2249
  }
@@ -1491,6 +2251,63 @@ class AutomationsWorkspacePicker extends WorkspacePicker {
1491
2251
  constructor() {
1492
2252
  super(...arguments);
1493
2253
  this.targetModelWatch = this._register(( new MutableDisposable()));
2254
+ this.eligibilityWatch = this._register(( new MutableDisposable()));
2255
+ this.cloudConfiguration = constObservable(undefined);
2256
+ this.repositorySelection = this._register(( new MutableDisposable()));
2257
+ this.selectionGeneration = 0;
2258
+ this.selectingRepository = false;
2259
+ this.onSelectionError = onUnexpectedError;
2260
+ this.onWillSelectWorkspace = async () => true;
2261
+ }
2262
+ get isSelectingRepository() {
2263
+ return this.selectingRepository;
2264
+ }
2265
+ setDisabledReason(reason) {
2266
+ this.disabledReason = reason;
2267
+ if (reason !== undefined) {
2268
+ this.selectionGeneration++;
2269
+ this.repositorySelection.clear();
2270
+ }
2271
+ this._updateTriggerLabel();
2272
+ }
2273
+ setCloudConfiguration(configuration) {
2274
+ this.cloudConfiguration = configuration;
2275
+ this.eligibilityWatch.value = autorun(reader => {
2276
+ const value = configuration.read(reader);
2277
+ for (const item of super._buildItems()) {
2278
+ if (item.item?.folderUri?.scheme === GITHUB_REMOTE_FILE_SCHEME) {
2279
+ value?.getWorkspaceTarget(item.item.folderUri).read(reader);
2280
+ }
2281
+ }
2282
+ if (this.actionWidgetService.isVisible && this._triggerElement?.getAttribute("aria-expanded") === "true") {
2283
+ this.actionWidgetService.updateItems(this._buildItems(), undefined, {
2284
+ preserveHover: true,
2285
+ preserveScrollPosition: true
2286
+ });
2287
+ }
2288
+ });
2289
+ }
2290
+ showPicker(force = false, anchor) {
2291
+ if (this.disabledReason !== undefined) {
2292
+ return;
2293
+ }
2294
+ this.setCloudConfiguration(this.cloudConfiguration);
2295
+ super.showPicker(force, anchor);
2296
+ }
2297
+ async waitForWorkspaceTargets(token) {
2298
+ const configuration = this.cloudConfiguration.get();
2299
+ if (!configuration) {
2300
+ return true;
2301
+ }
2302
+ await Promise.all(super._buildItems().flatMap(
2303
+ item => item.item?.folderUri?.scheme === GITHUB_REMOTE_FILE_SCHEME ? [waitForState(
2304
+ configuration.getWorkspaceTarget(item.item.folderUri),
2305
+ target => !target.pending,
2306
+ undefined,
2307
+ token
2308
+ )] : []
2309
+ ));
2310
+ return !token.isCancellationRequested && configuration === this.cloudConfiguration.get();
1494
2311
  }
1495
2312
  setTargetModel(model) {
1496
2313
  this.targetModel = model;
@@ -1506,11 +2323,47 @@ class AutomationsWorkspacePicker extends WorkspacePicker {
1506
2323
  return false;
1507
2324
  }
1508
2325
  _buildItems() {
1509
- const items = super._buildItems();
2326
+ const configuration = this.cloudConfiguration.get();
2327
+ const items = super._buildItems().map(item => {
2328
+ if (item.item?.folderUri?.scheme !== GITHUB_REMOTE_FILE_SCHEME) {
2329
+ return item;
2330
+ }
2331
+ const reason = configuration ? configuration.getWorkspaceTarget(item.item.folderUri).get().disabledReason : ( localize(3748, "Cloud automations are unavailable."));
2332
+ return {
2333
+ ...item,
2334
+ submenuActions: undefined,
2335
+ group: {
2336
+ title: "",
2337
+ icon: Codicon.repo
2338
+ },
2339
+ ...(reason === undefined ? {} : {
2340
+ disabled: true,
2341
+ description: reason,
2342
+ ariaDescription: reason,
2343
+ tooltip: reason,
2344
+ hover: {
2345
+ content: reason
2346
+ }
2347
+ })
2348
+ };
2349
+ });
2350
+ if (configuration) {
2351
+ items.unshift({
2352
+ kind: ActionListItemKind.Action,
2353
+ label: ( localize(3749, "Work in GitHub")),
2354
+ group: {
2355
+ title: "",
2356
+ icon: Codicon.github
2357
+ },
2358
+ item: {
2359
+ id: "automation.workInGitHub"
2360
+ }
2361
+ });
2362
+ }
1510
2363
  const noWorkspace = {
1511
2364
  kind: ActionListItemKind.Action,
1512
- label: ( localize(3346, "No workspace")),
1513
- description: ( localize(3347, "Run without a backing workspace")),
2365
+ label: this._getNoWorkspaceLabel(),
2366
+ description: ( localize(3750, "Run without a backing workspace")),
1514
2367
  group: {
1515
2368
  title: "",
1516
2369
  icon: Codicon.commentDiscussion
@@ -1526,45 +2379,156 @@ class AutomationsWorkspacePicker extends WorkspacePicker {
1526
2379
  }, ...items] : [noWorkspace];
1527
2380
  }
1528
2381
  async _dispatchPickerItem(item) {
1529
- const applied = await super._dispatchPickerItem(item);
1530
- const selectedFolder = this.selectedFolderUri;
1531
- if (applied && selectedFolder && (item.folderUri || item.browseActionIndex !== undefined)) {
1532
- this.targetModel?.setQuickChat(false, selectedFolder);
2382
+ if (this.disabledReason !== undefined) {
2383
+ return false;
2384
+ }
2385
+ const generation = ++this.selectionGeneration;
2386
+ this.repositorySelection.clear();
2387
+ const resources = ( new DisposableStore());
2388
+ this.repositorySelection.value = resources;
2389
+ const token = cancelOnDispose(resources);
2390
+ try {
2391
+ const configuration = this.cloudConfiguration.get();
2392
+ if (item.id === "automation.workInGitHub") {
2393
+ if (!configuration) {
2394
+ throw ( new Error(( localize(3748, "Cloud automations are unavailable."))));
2395
+ }
2396
+ const folderUri = await configuration.pickWorkspace(token);
2397
+ if (!folderUri || token.isCancellationRequested || generation !== this.selectionGeneration) {
2398
+ return false;
2399
+ }
2400
+ item = {
2401
+ folderUri
2402
+ };
2403
+ }
2404
+ if (item.folderUri?.scheme === GITHUB_REMOTE_FILE_SCHEME) {
2405
+ if (!configuration) {
2406
+ throw ( new Error(( localize(3748, "Cloud automations are unavailable."))));
2407
+ }
2408
+ const target = await waitForState(
2409
+ configuration.getWorkspaceTarget(item.folderUri),
2410
+ target => !target.pending,
2411
+ undefined,
2412
+ token
2413
+ );
2414
+ if (!target.workspace || target.disabledReason) {
2415
+ throw ( new Error(target.disabledReason ?? ( localize(3751, "The repository must be private."))));
2416
+ }
2417
+ if (configuration !== this.cloudConfiguration.get()) {
2418
+ return false;
2419
+ }
2420
+ }
2421
+ if (!(await this.onWillSelectWorkspace()) || token.isCancellationRequested || generation !== this.selectionGeneration) {
2422
+ return false;
2423
+ }
2424
+ this.selectingRepository = item.folderUri?.scheme === GITHUB_REMOTE_FILE_SCHEME;
2425
+ if (this.selectingRepository && item.folderUri) {
2426
+ const repositoryUri = item.folderUri;
2427
+ const workspace = this.sessionsProvidersService.getProviders().map(provider => provider.resolveWorkspace(repositoryUri)).find(workspace => workspace !== undefined);
2428
+ const related = workspace && this._findRelatedLocalWorkspace(workspace);
2429
+ if (related && this.offersCloud(related.workspace.folders[0].root, configuration)) {
2430
+ item = {
2431
+ folderUri: related.workspace.folders[0].root,
2432
+ providerId: related.providerId
2433
+ };
2434
+ }
2435
+ }
2436
+ const applied = await super._dispatchPickerItem(item);
2437
+ const selectedFolder = this.selectedFolderUri;
2438
+ if (applied && selectedFolder && (item.folderUri || item.browseActionIndex !== undefined)) {
2439
+ this.targetModel?.setQuickChat(false, selectedFolder);
2440
+ }
2441
+ return applied;
2442
+ } catch (error) {
2443
+ if (!isCancellationError(error) && !token.isCancellationRequested) {
2444
+ this.onSelectionError(error instanceof Error ? error : ( new Error(getErrorMessage(error))));
2445
+ }
2446
+ return false;
2447
+ } finally {
2448
+ if (this.repositorySelection.value === resources) {
2449
+ this.selectingRepository = false;
2450
+ this.repositorySelection.clear();
2451
+ }
1533
2452
  }
1534
- return applied;
1535
2453
  }
1536
2454
  _isSelectedFolder(folderUri) {
1537
2455
  return !this.targetModel?.isQuickChat && super._isSelectedFolder(folderUri);
1538
2456
  }
2457
+ offersCloud(folderUri, configuration) {
2458
+ return !!configuration && ( this.sessionsProvidersService.getProviders().some(provider => provider.resolveWorkspace(folderUri) && ( provider.getSessionTypes(folderUri).some(type => configuration.sessionTypes.includes(type.id)))));
2459
+ }
1539
2460
  _renderTriggerLabel(trigger) {
1540
2461
  clearNode(trigger);
1541
2462
  const workspace = this.selectedResolved?.workspace;
1542
2463
  const noWorkspace = this.targetModel?.isQuickChat === true;
1543
- const label = noWorkspace ? ( localize(3346, "No workspace")) : workspace?.label ?? ( localize(3348, "Select workspace"));
2464
+ const label = noWorkspace ? this._getNoWorkspaceLabel() : workspace?.label ?? ( localize(3752, "Select workspace"));
1544
2465
  const icon = noWorkspace ? Codicon.commentDiscussion : workspace?.icon ?? Codicon.project;
1545
- trigger.setAttribute("aria-label", workspace || noWorkspace ? ( localize(3349, "Automation target, {0}", label)) : ( localize(3350, "Pick a workspace for this automation")));
2466
+ trigger.setAttribute("aria-label", workspace || noWorkspace ? ( localize(3753, "Automation target, {0}", label)) : ( localize(3754, "Pick a workspace for this automation")));
2467
+ const disabled = this.disabledReason !== undefined;
2468
+ trigger.setAttribute("aria-disabled", String(disabled));
2469
+ trigger.tabIndex = disabled ? -1 : 0;
2470
+ trigger.parentElement?.classList.toggle("disabled", disabled);
2471
+ if (disabled) {
2472
+ trigger.removeAttribute("aria-haspopup");
2473
+ trigger.setAttribute("aria-expanded", "false");
2474
+ trigger.setAttribute("aria-label", ( localize(3755, "Automation target, {0}. {1}", label, this.disabledReason)));
2475
+ } else {
2476
+ trigger.setAttribute("aria-haspopup", "listbox");
2477
+ }
1546
2478
  const renderedIcon = append(trigger, renderIcon(icon));
1547
2479
  renderedIcon.setAttribute("aria-hidden", "true");
1548
2480
  append(trigger, $("span.sessions-chat-dropdown-label", undefined, label));
1549
- const chevron = append(trigger, renderIcon(Codicon.chevronDownCompact));
1550
- chevron.classList.add("sessions-chat-dropdown-chevron");
1551
- chevron.setAttribute("aria-hidden", "true");
2481
+ if (!disabled) {
2482
+ const chevron = append(trigger, renderIcon(Codicon.chevronDownCompact));
2483
+ chevron.classList.add("sessions-chat-dropdown-chevron");
2484
+ chevron.setAttribute("aria-hidden", "true");
2485
+ }
1552
2486
  }
1553
2487
  _getAllBrowseActions() {
1554
2488
  return super._getAllBrowseActions().filter(a => a.group === SESSION_WORKSPACE_GROUP_LOCAL);
1555
2489
  }
1556
2490
  }
1557
2491
  class MobileAutomationsWorkspacePicker extends AutomationsWorkspacePicker {
2492
+ constructor() {
2493
+ super(...arguments);
2494
+ this.pendingPicker = this._register(( new MutableDisposable()));
2495
+ }
1558
2496
  setLayoutService(layoutService) {
1559
2497
  this.layoutService = layoutService;
1560
2498
  }
1561
2499
  showPicker(force = false, anchor) {
2500
+ if (this.disabledReason !== undefined) {
2501
+ return;
2502
+ }
1562
2503
  const triggerElement = anchor ?? this._triggerElement;
1563
2504
  if (!triggerElement || !this.layoutService || !shouldUseMobileWorkspacePickerSheet(this.layoutService)) {
1564
2505
  super.showPicker(force, anchor);
1565
2506
  return;
1566
2507
  }
1567
- void showMobileWorkspacePickerSheet(this.layoutService, triggerElement, this._buildItems(), item => {
2508
+ this.pendingPicker.clear();
2509
+ const pending = ( new DisposableStore());
2510
+ this.pendingPicker.value = pending;
2511
+ const cancellation = cancelOnDispose(pending);
2512
+ pending.add(toDisposable(() => {
2513
+ triggerElement.removeAttribute("aria-busy");
2514
+ }));
2515
+ triggerElement.setAttribute("aria-busy", "true");
2516
+ void this.showReadyMobilePicker(triggerElement, this.layoutService, cancellation).catch(error => {
2517
+ if (!isCancellationError(error)) {
2518
+ this.onSelectionError(error instanceof Error ? error : ( new Error(getErrorMessage(error))));
2519
+ }
2520
+ }).finally(() => {
2521
+ if (this.pendingPicker.value === pending) {
2522
+ this.pendingPicker.clear();
2523
+ }
2524
+ });
2525
+ }
2526
+ async showReadyMobilePicker(trigger, layoutService, token) {
2527
+ if (!(await this.waitForWorkspaceTargets(token)) || !trigger.isConnected || this.disabledReason !== undefined) {
2528
+ return;
2529
+ }
2530
+ trigger.removeAttribute("aria-busy");
2531
+ await showMobileWorkspacePickerSheet(layoutService, trigger, this._buildItems(), item => {
1568
2532
  void this._dispatchPickerItem(item);
1569
2533
  }, this._getAllBrowseActions());
1570
2534
  }
@@ -1586,4 +2550,4 @@ KeybindingsRegistry.registerCommandAndKeybindingRule({
1586
2550
  }
1587
2551
  });
1588
2552
 
1589
- export { AutomationIsolationGroupActionViewItem, AutomationSessionDraftSynchronizer, AutomationsWorkspacePicker, MobileAutomationsWorkspacePicker, canSelectAutomationWorkspace, isAutomationDialogPopupTarget, registerAutomationDialogKeyboardNavigation, renderForm, shouldPassThroughAutomationDialogCommand, updateSaveButtonState };
2553
+ export { AutomationCustomizationSelection, AutomationIsolationGroupActionViewItem, AutomationSessionDraftSynchronizer, AutomationsWorkspacePicker, MobileAutomationsWorkspacePicker, canSelectAutomationWorkspace, createAutomationTarget, getAutomationDialogProviders, isAutomationDialogPopupTarget, registerAutomationDialogKeyboardNavigation, renderForm, shouldPassThroughAutomationDialogCommand, updateSaveButtonState };