@stigmer/react 3.11.0 → 3.12.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 (559) hide show
  1. package/activity/useRecentActivity.d.ts +3 -2
  2. package/activity/useRecentActivity.d.ts.map +1 -1
  3. package/activity/useRecentActivity.js +3 -2
  4. package/activity/useRecentActivity.js.map +1 -1
  5. package/agent/AgentDetailView.d.ts +2 -12
  6. package/agent/AgentDetailView.d.ts.map +1 -1
  7. package/agent/AgentDetailView.js +10 -42
  8. package/agent/AgentDetailView.js.map +1 -1
  9. package/agent/internal/agentToInput.d.ts.map +1 -1
  10. package/agent/internal/agentToInput.js +0 -8
  11. package/agent/internal/agentToInput.js.map +1 -1
  12. package/agent-instance/AgentInstanceList.d.ts.map +1 -1
  13. package/agent-instance/AgentInstanceList.js +2 -1
  14. package/agent-instance/AgentInstanceList.js.map +1 -1
  15. package/api-key/ApiKeyListPanel.d.ts.map +1 -1
  16. package/api-key/ApiKeyListPanel.js +2 -1
  17. package/api-key/ApiKeyListPanel.js.map +1 -1
  18. package/attachment/AttachmentChipList.d.ts.map +1 -1
  19. package/attachment/AttachmentChipList.js +9 -8
  20. package/attachment/AttachmentChipList.js.map +1 -1
  21. package/attachment/AttachmentImageLightbox.d.ts.map +1 -1
  22. package/attachment/AttachmentImageLightbox.js +1 -1
  23. package/attachment/AttachmentImageLightbox.js.map +1 -1
  24. package/channel/AgentChannelsPanel.d.ts.map +1 -1
  25. package/channel/AgentChannelsPanel.js +2 -1
  26. package/channel/AgentChannelsPanel.js.map +1 -1
  27. package/channel/ChannelConversationsDialog.d.ts.map +1 -1
  28. package/channel/ChannelConversationsDialog.js +2 -1
  29. package/channel/ChannelConversationsDialog.js.map +1 -1
  30. package/channel/ChannelTemplatesDialog.d.ts.map +1 -1
  31. package/channel/ChannelTemplatesDialog.js +2 -1
  32. package/channel/ChannelTemplatesDialog.js.map +1 -1
  33. package/channel-app/internal.d.ts.map +1 -1
  34. package/channel-app/internal.js +2 -1
  35. package/channel-app/internal.js.map +1 -1
  36. package/composer/ComposerToolbar.d.ts.map +1 -1
  37. package/composer/ComposerToolbar.js +10 -7
  38. package/composer/ComposerToolbar.js.map +1 -1
  39. package/composer/ConfigureMenu.d.ts.map +1 -1
  40. package/composer/ConfigureMenu.js +2 -1
  41. package/composer/ConfigureMenu.js.map +1 -1
  42. package/composer/ContextChip.d.ts.map +1 -1
  43. package/composer/ContextChip.js +2 -1
  44. package/composer/ContextChip.js.map +1 -1
  45. package/composer/ContextPopover.d.ts.map +1 -1
  46. package/composer/ContextPopover.js +2 -1
  47. package/composer/ContextPopover.js.map +1 -1
  48. package/composer/SessionComposer.d.ts +13 -0
  49. package/composer/SessionComposer.d.ts.map +1 -1
  50. package/composer/SessionComposer.js +12 -2
  51. package/composer/SessionComposer.js.map +1 -1
  52. package/conversation/ConversationMediaAttachment.d.ts.map +1 -1
  53. package/conversation/ConversationMediaAttachment.js +2 -1
  54. package/conversation/ConversationMediaAttachment.js.map +1 -1
  55. package/conversation/ConversationTimelineView.d.ts.map +1 -1
  56. package/conversation/ConversationTimelineView.js +14 -4
  57. package/conversation/ConversationTimelineView.js.map +1 -1
  58. package/conversation/conversationPresentation.d.ts +28 -0
  59. package/conversation/conversationPresentation.d.ts.map +1 -1
  60. package/conversation/conversationPresentation.js +38 -1
  61. package/conversation/conversationPresentation.js.map +1 -1
  62. package/cursor-accounts/MemberCoverageTable.d.ts.map +1 -1
  63. package/cursor-accounts/MemberCoverageTable.js +6 -5
  64. package/cursor-accounts/MemberCoverageTable.js.map +1 -1
  65. package/dashboard/DashboardKPICards.d.ts.map +1 -1
  66. package/dashboard/DashboardKPICards.js +3 -1
  67. package/dashboard/DashboardKPICards.js.map +1 -1
  68. package/dependency-graph/DependencyTreeNode.d.ts.map +1 -1
  69. package/dependency-graph/DependencyTreeNode.js +1 -7
  70. package/dependency-graph/DependencyTreeNode.js.map +1 -1
  71. package/dependency-graph/types.d.ts +8 -20
  72. package/dependency-graph/types.d.ts.map +1 -1
  73. package/dependency-graph/useDependencyGraph.d.ts.map +1 -1
  74. package/dependency-graph/useDependencyGraph.js +2 -20
  75. package/dependency-graph/useDependencyGraph.js.map +1 -1
  76. package/environment/EnvironmentVariableEditor.d.ts.map +1 -1
  77. package/environment/EnvironmentVariableEditor.js +2 -1
  78. package/environment/EnvironmentVariableEditor.js.map +1 -1
  79. package/execution/ApprovalCard.d.ts.map +1 -1
  80. package/execution/ApprovalCard.js +1 -1
  81. package/execution/ApprovalCard.js.map +1 -1
  82. package/execution/ArtifactRowView.d.ts.map +1 -1
  83. package/execution/ArtifactRowView.js +2 -1
  84. package/execution/ArtifactRowView.js.map +1 -1
  85. package/execution/FilePathLink.d.ts +4 -4
  86. package/execution/FilePathLink.d.ts.map +1 -1
  87. package/execution/FilePathLink.js +4 -4
  88. package/execution/FilePathLink.js.map +1 -1
  89. package/execution/McpToolDetail.d.ts.map +1 -1
  90. package/execution/McpToolDetail.js +2 -1
  91. package/execution/McpToolDetail.js.map +1 -1
  92. package/execution/MessageAttachments.d.ts.map +1 -1
  93. package/execution/MessageAttachments.js +10 -8
  94. package/execution/MessageAttachments.js.map +1 -1
  95. package/execution/MessageEntry.d.ts.map +1 -1
  96. package/execution/MessageEntry.js +2 -1
  97. package/execution/MessageEntry.js.map +1 -1
  98. package/execution/PlanArtifactCard.d.ts.map +1 -1
  99. package/execution/PlanArtifactCard.js +7 -4
  100. package/execution/PlanArtifactCard.js.map +1 -1
  101. package/execution/ToolCallDetail.d.ts.map +1 -1
  102. package/execution/ToolCallDetail.js +1 -1
  103. package/execution/ToolCallDetail.js.map +1 -1
  104. package/execution/ToolCallItem.d.ts.map +1 -1
  105. package/execution/ToolCallItem.js +5 -1
  106. package/execution/ToolCallItem.js.map +1 -1
  107. package/execution/WriteBackCard.d.ts.map +1 -1
  108. package/execution/WriteBackCard.js +6 -4
  109. package/execution/WriteBackCard.js.map +1 -1
  110. package/execution/artifact-row-item.d.ts +1 -1
  111. package/execution/artifact-row-item.d.ts.map +1 -1
  112. package/file-reference/FileReferenceChipList.d.ts.map +1 -1
  113. package/file-reference/FileReferenceChipList.js +6 -1
  114. package/file-reference/FileReferenceChipList.js.map +1 -1
  115. package/iam-policy/OrgMembersPanel.d.ts.map +1 -1
  116. package/iam-policy/OrgMembersPanel.js +6 -5
  117. package/iam-policy/OrgMembersPanel.js.map +1 -1
  118. package/iam-policy/ProviderBadge.d.ts.map +1 -1
  119. package/iam-policy/ProviderBadge.js +3 -2
  120. package/iam-policy/ProviderBadge.js.map +1 -1
  121. package/iam-policy/RoleSelector.d.ts.map +1 -1
  122. package/iam-policy/RoleSelector.js +1 -1
  123. package/iam-policy/RoleSelector.js.map +1 -1
  124. package/identity-provider/IdentityProviderListPanel.d.ts.map +1 -1
  125. package/identity-provider/IdentityProviderListPanel.js +2 -1
  126. package/identity-provider/IdentityProviderListPanel.js.map +1 -1
  127. package/index.d.ts +0 -2
  128. package/index.d.ts.map +1 -1
  129. package/index.js +0 -6
  130. package/index.js.map +1 -1
  131. package/internal/truncated-text.d.ts +17 -0
  132. package/internal/truncated-text.d.ts.map +1 -0
  133. package/internal/truncated-text.js +27 -0
  134. package/internal/truncated-text.js.map +1 -0
  135. package/invitation/InvitationManager.d.ts.map +1 -1
  136. package/invitation/InvitationManager.js +4 -3
  137. package/invitation/InvitationManager.js.map +1 -1
  138. package/library/ScopeToggle.d.ts.map +1 -1
  139. package/library/ScopeToggle.js +10 -2
  140. package/library/ScopeToggle.js.map +1 -1
  141. package/library/VisibilitySelector.d.ts.map +1 -1
  142. package/library/VisibilitySelector.js +2 -1
  143. package/library/VisibilitySelector.js.map +1 -1
  144. package/library/useExportResource.d.ts +3 -4
  145. package/library/useExportResource.d.ts.map +1 -1
  146. package/library/useExportResource.js +1 -1
  147. package/library/useExportResource.js.map +1 -1
  148. package/manifest/EditResourceYamlDialog.d.ts.map +1 -1
  149. package/manifest/EditResourceYamlDialog.js.map +1 -1
  150. package/mcp-server/McpServerConfigPanel.d.ts +30 -1
  151. package/mcp-server/McpServerConfigPanel.d.ts.map +1 -1
  152. package/mcp-server/McpServerConfigPanel.js +18 -8
  153. package/mcp-server/McpServerConfigPanel.js.map +1 -1
  154. package/mcp-server/McpServerConnectDialog.d.ts +12 -1
  155. package/mcp-server/McpServerConnectDialog.d.ts.map +1 -1
  156. package/mcp-server/McpServerConnectDialog.js +8 -7
  157. package/mcp-server/McpServerConnectDialog.js.map +1 -1
  158. package/mcp-server/McpServerDetailView.d.ts.map +1 -1
  159. package/mcp-server/McpServerDetailView.js +4 -4
  160. package/mcp-server/McpServerDetailView.js.map +1 -1
  161. package/mcp-server/McpServerPicker.d.ts.map +1 -1
  162. package/mcp-server/McpServerPicker.js +86 -5
  163. package/mcp-server/McpServerPicker.js.map +1 -1
  164. package/mcp-server/McpToolSelector.d.ts.map +1 -1
  165. package/mcp-server/McpToolSelector.js +2 -1
  166. package/mcp-server/McpToolSelector.js.map +1 -1
  167. package/mcp-server/VendorApprovalBlockedNotice.d.ts +77 -0
  168. package/mcp-server/VendorApprovalBlockedNotice.d.ts.map +1 -0
  169. package/mcp-server/VendorApprovalBlockedNotice.js +62 -0
  170. package/mcp-server/VendorApprovalBlockedNotice.js.map +1 -0
  171. package/mcp-server/mcpServerSetupReducer.d.ts +18 -0
  172. package/mcp-server/mcpServerSetupReducer.d.ts.map +1 -1
  173. package/mcp-server/mcpServerSetupReducer.js +6 -0
  174. package/mcp-server/mcpServerSetupReducer.js.map +1 -1
  175. package/mcp-server/useMcpServerSetup.d.ts.map +1 -1
  176. package/mcp-server/useMcpServerSetup.js +7 -0
  177. package/mcp-server/useMcpServerSetup.js.map +1 -1
  178. package/oauth-app/OAuthAppListPanel.d.ts.map +1 -1
  179. package/oauth-app/OAuthAppListPanel.js +2 -1
  180. package/oauth-app/OAuthAppListPanel.js.map +1 -1
  181. package/package.json +4 -4
  182. package/platform-client/PlatformClientListPanel.d.ts.map +1 -1
  183. package/platform-client/PlatformClientListPanel.js +3 -2
  184. package/platform-client/PlatformClientListPanel.js.map +1 -1
  185. package/pricing-governance/BaselineEditor.d.ts.map +1 -1
  186. package/pricing-governance/BaselineEditor.js +7 -1
  187. package/pricing-governance/BaselineEditor.js.map +1 -1
  188. package/pricing-governance/ModelCatalogPanel.d.ts.map +1 -1
  189. package/pricing-governance/ModelCatalogPanel.js +2 -1
  190. package/pricing-governance/ModelCatalogPanel.js.map +1 -1
  191. package/pricing-governance/PricingGovernanceConsole.d.ts.map +1 -1
  192. package/pricing-governance/PricingGovernanceConsole.js +2 -1
  193. package/pricing-governance/PricingGovernanceConsole.js.map +1 -1
  194. package/pricing-governance/PricingGovernancePanel.d.ts.map +1 -1
  195. package/pricing-governance/PricingGovernancePanel.js +2 -1
  196. package/pricing-governance/PricingGovernancePanel.js.map +1 -1
  197. package/resource-workbench/components/StatusBadge.d.ts.map +1 -1
  198. package/resource-workbench/components/StatusBadge.js +2 -1
  199. package/resource-workbench/components/StatusBadge.js.map +1 -1
  200. package/schedule/CadenceField.d.ts.map +1 -1
  201. package/schedule/CadenceField.js +15 -8
  202. package/schedule/CadenceField.js.map +1 -1
  203. package/schedule/ScheduleRunsTable.d.ts.map +1 -1
  204. package/schedule/ScheduleRunsTable.js +3 -2
  205. package/schedule/ScheduleRunsTable.js.map +1 -1
  206. package/session/PlanEditor.d.ts.map +1 -1
  207. package/session/PlanEditor.js +3 -5
  208. package/session/PlanEditor.js.map +1 -1
  209. package/sharing/AgentShareList.d.ts.map +1 -1
  210. package/sharing/AgentShareList.js +3 -1
  211. package/sharing/AgentShareList.js.map +1 -1
  212. package/sharing/ShareAgentDialog.d.ts.map +1 -1
  213. package/sharing/ShareAgentDialog.js +2 -1
  214. package/sharing/ShareAgentDialog.js.map +1 -1
  215. package/skill/SkillDetailView.d.ts.map +1 -1
  216. package/skill/SkillDetailView.js +3 -2
  217. package/skill/SkillDetailView.js.map +1 -1
  218. package/src/__tests__/helpers/open-menu.ts +88 -0
  219. package/src/__tests__/portal-container.test.tsx +3 -3
  220. package/src/activity/useRecentActivity.ts +3 -2
  221. package/src/agent/AgentDetailView.tsx +6 -130
  222. package/src/agent/internal/__tests__/agentToInput.test.ts +2 -11
  223. package/src/agent/internal/agentToInput.ts +0 -11
  224. package/src/agent-instance/AgentInstanceList.tsx +5 -6
  225. package/src/agent-instance/__tests__/AgentInstanceList.test.tsx +5 -4
  226. package/src/api-key/ApiKeyListPanel.tsx +11 -3
  227. package/src/attachment/AttachmentChipList.tsx +74 -65
  228. package/src/attachment/AttachmentImageLightbox.tsx +5 -4
  229. package/src/attachment/__tests__/AttachmentChipList.test.tsx +4 -3
  230. package/src/channel/AgentChannelsPanel.tsx +5 -6
  231. package/src/channel/ChannelConversationsDialog.tsx +5 -3
  232. package/src/channel/ChannelTemplatesDialog.tsx +5 -6
  233. package/src/channel/__tests__/AgentChannelsPanel.test.tsx +14 -9
  234. package/src/channel-app/internal.tsx +5 -6
  235. package/src/composer/ComposerToolbar.tsx +122 -90
  236. package/src/composer/ConfigureMenu.tsx +33 -24
  237. package/src/composer/ContextChip.tsx +2 -3
  238. package/src/composer/ContextPopover.tsx +27 -18
  239. package/src/composer/SessionComposer.tsx +41 -9
  240. package/src/composer/__tests__/SessionComposer-agentSetupError.test.tsx +124 -0
  241. package/src/composer/__tests__/SessionComposer-lockAgent.test.tsx +4 -9
  242. package/src/conversation/ConversationMediaAttachment.tsx +2 -2
  243. package/src/conversation/ConversationTimelineView.tsx +19 -2
  244. package/src/conversation/__tests__/ConversationTimelineView.test.tsx +106 -3
  245. package/src/conversation/conversationPresentation.ts +52 -1
  246. package/src/cursor-accounts/MemberCoverageTable.tsx +15 -13
  247. package/src/cursor-accounts/__tests__/CursorAccountsConsole.test.tsx +4 -4
  248. package/src/dashboard/DashboardKPICards.tsx +2 -1
  249. package/src/dependency-graph/DependencyTreeNode.tsx +1 -7
  250. package/src/dependency-graph/__tests__/useDependencyGraph.test.ts +18 -34
  251. package/src/dependency-graph/types.ts +8 -20
  252. package/src/dependency-graph/useDependencyGraph.ts +2 -22
  253. package/src/environment/EnvironmentVariableEditor.tsx +17 -6
  254. package/src/execution/ApprovalCard.tsx +1 -3
  255. package/src/execution/ArtifactRowView.tsx +68 -48
  256. package/src/execution/FilePathLink.tsx +43 -27
  257. package/src/execution/McpToolDetail.tsx +6 -2
  258. package/src/execution/MessageAttachments.tsx +57 -41
  259. package/src/execution/MessageEntry.tsx +22 -15
  260. package/src/execution/PlanArtifactCard.tsx +25 -18
  261. package/src/execution/ToolCallDetail.tsx +1 -4
  262. package/src/execution/ToolCallItem.tsx +18 -7
  263. package/src/execution/WriteBackCard.tsx +38 -29
  264. package/src/execution/__tests__/ArtifactRow.test.tsx +6 -2
  265. package/src/execution/__tests__/ArtifactRowView.test.tsx +5 -2
  266. package/src/execution/__tests__/FilePathLink.test.tsx +10 -6
  267. package/src/execution/__tests__/FileReviewCard.test.tsx +2 -1
  268. package/src/execution/__tests__/MessageEntry-attachments.test.tsx +3 -2
  269. package/src/execution/__tests__/MessageThread.test.tsx +6 -1
  270. package/src/execution/__tests__/artifact-row-tooltips.layout.test.tsx +115 -0
  271. package/src/execution/artifact-row-item.ts +1 -1
  272. package/src/file-reference/FileReferenceChipList.tsx +29 -17
  273. package/src/file-reference/__tests__/FileReferenceChipList.test.tsx +5 -2
  274. package/src/iam-policy/OrgMembersPanel.tsx +26 -19
  275. package/src/iam-policy/ProviderBadge.tsx +17 -10
  276. package/src/iam-policy/RoleSelector.tsx +0 -1
  277. package/src/identity-provider/IdentityProviderListPanel.tsx +11 -3
  278. package/src/index.ts +0 -82
  279. package/src/internal/__tests__/truncated-text.layout.test.tsx +68 -0
  280. package/src/internal/__tests__/truncated-text.test.tsx +33 -0
  281. package/src/internal/truncated-text.tsx +81 -0
  282. package/src/invitation/InvitationManager.tsx +18 -5
  283. package/src/library/ScopeToggle.tsx +14 -2
  284. package/src/library/VisibilitySelector.tsx +21 -14
  285. package/src/library/useExportResource.ts +3 -4
  286. package/src/manifest/EditResourceYamlDialog.tsx +1 -2
  287. package/src/manifest/__tests__/ApplyManifestDialog.test.tsx +2 -2
  288. package/src/manifest/__tests__/EditResourceYamlDialog.test.tsx +9 -9
  289. package/src/mcp-server/McpServerConfigPanel.tsx +79 -37
  290. package/src/mcp-server/McpServerConnectDialog.tsx +41 -5
  291. package/src/mcp-server/McpServerDetailView.tsx +23 -39
  292. package/src/mcp-server/McpServerPicker.tsx +99 -7
  293. package/src/mcp-server/McpToolSelector.tsx +12 -7
  294. package/src/mcp-server/VendorApprovalBlockedNotice.tsx +221 -0
  295. package/src/mcp-server/__tests__/McpServerPicker.test.tsx +504 -0
  296. package/src/mcp-server/__tests__/VendorApprovalBlocked.surfaces.test.tsx +321 -0
  297. package/src/mcp-server/__tests__/VendorApprovalBlockedNotice.test.tsx +154 -0
  298. package/src/mcp-server/mcpServerSetupReducer.ts +24 -0
  299. package/src/mcp-server/useMcpServerSetup.ts +9 -0
  300. package/src/oauth-app/OAuthAppListPanel.tsx +11 -3
  301. package/src/platform-client/PlatformClientListPanel.tsx +35 -18
  302. package/src/pricing-governance/BaselineEditor.tsx +20 -0
  303. package/src/pricing-governance/ModelCatalogPanel.tsx +9 -5
  304. package/src/pricing-governance/PricingGovernanceConsole.tsx +9 -5
  305. package/src/pricing-governance/PricingGovernancePanel.tsx +13 -4
  306. package/src/pricing-governance/__tests__/ModelCatalogPanel.test.tsx +37 -0
  307. package/src/resource-workbench/components/StatusBadge.tsx +7 -3
  308. package/src/schedule/CadenceField.tsx +38 -27
  309. package/src/schedule/ScheduleRunsTable.tsx +23 -11
  310. package/src/schedule/__tests__/cadence-tooltips.layout.test.tsx +86 -0
  311. package/src/session/PlanEditor.tsx +9 -8
  312. package/src/sharing/AgentShareList.tsx +28 -22
  313. package/src/sharing/ShareAgentDialog.tsx +5 -6
  314. package/src/sharing/__tests__/AgentShareList.test.tsx +4 -4
  315. package/src/skill/SkillDetailView.tsx +23 -12
  316. package/src/version-history/VersionTimelineEntry.tsx +21 -12
  317. package/src/workflow/CanvasTransitionEdge.tsx +23 -16
  318. package/src/workflow/ExecutionActiveTaskIndicator.tsx +74 -59
  319. package/src/workflow/TaskPickerPopover.tsx +0 -1
  320. package/src/workflow/WorkflowCanvasEditor.tsx +95 -64
  321. package/src/workflow/WorkflowNode.tsx +13 -6
  322. package/src/workflow/WorkflowTaskApprovalSummary.tsx +18 -11
  323. package/src/workflow/WorkflowTaskList.tsx +2 -2
  324. package/src/workflow/WorkflowVersionBadge.tsx +33 -18
  325. package/src/workflow/WorkflowVersionTimeline.tsx +7 -6
  326. package/src/workflow/__tests__/WorkflowTaskApprovalSummary.test.tsx +3 -1
  327. package/src/workflow/__tests__/structured-data-viewer.test.tsx +5 -2
  328. package/src/workflow/execution-comparison/ExecutionComparisonView.tsx +5 -3
  329. package/src/workflow/execution-comparison/TaskComparisonTable.tsx +12 -5
  330. package/src/workflow/execution-history/ExecutionHistoryTable.tsx +24 -15
  331. package/src/workflow/inspector/InspectorHeader.tsx +20 -11
  332. package/src/workflow/inspector/NestedTaskList.tsx +18 -11
  333. package/src/workflow/inspector/WorkflowSummaryPanel.tsx +5 -3
  334. package/src/workflow/inspector/tabs/BranchesTab.tsx +61 -31
  335. package/src/workflow/instance/WorkflowInstanceList.tsx +5 -6
  336. package/src/workflow/instance/__tests__/WorkflowInstanceList.test.tsx +5 -4
  337. package/src/workflow/node-shell/DiffBadge.tsx +18 -11
  338. package/src/workflow/node-shell/ExecutionBadge.tsx +73 -46
  339. package/src/workflow/node-shell/NodeActions.tsx +128 -94
  340. package/src/workflow/task-detail/StructuredDataViewer.tsx +4 -2
  341. package/src/workspace/EditorTabs.tsx +102 -85
  342. package/src/workspace/ExplorerTree.tsx +47 -30
  343. package/src/workspace/FileViewer.tsx +11 -3
  344. package/src/workspace/PanelChip.tsx +32 -23
  345. package/src/workspace/WorkspaceEditor.tsx +21 -9
  346. package/src/workspace/WorkspaceSummary.tsx +21 -12
  347. package/src/workspace/WorkspaceSurface.tsx +86 -61
  348. package/src/workspace/__tests__/EditorTabs.test.tsx +5 -2
  349. package/src/workspace/__tests__/WorkspaceSurface.test.tsx +5 -2
  350. package/styles.css +1 -1
  351. package/version-history/VersionTimelineEntry.d.ts.map +1 -1
  352. package/version-history/VersionTimelineEntry.js +2 -1
  353. package/version-history/VersionTimelineEntry.js.map +1 -1
  354. package/workflow/CanvasTransitionEdge.d.ts +1 -1
  355. package/workflow/CanvasTransitionEdge.d.ts.map +1 -1
  356. package/workflow/CanvasTransitionEdge.js +3 -2
  357. package/workflow/CanvasTransitionEdge.js.map +1 -1
  358. package/workflow/ExecutionActiveTaskIndicator.d.ts.map +1 -1
  359. package/workflow/ExecutionActiveTaskIndicator.js +12 -11
  360. package/workflow/ExecutionActiveTaskIndicator.js.map +1 -1
  361. package/workflow/TaskPickerPopover.js +1 -1
  362. package/workflow/TaskPickerPopover.js.map +1 -1
  363. package/workflow/WorkflowCanvasEditor.d.ts.map +1 -1
  364. package/workflow/WorkflowCanvasEditor.js +9 -2
  365. package/workflow/WorkflowCanvasEditor.js.map +1 -1
  366. package/workflow/WorkflowNode.d.ts.map +1 -1
  367. package/workflow/WorkflowNode.js +2 -1
  368. package/workflow/WorkflowNode.js.map +1 -1
  369. package/workflow/WorkflowTaskApprovalSummary.d.ts.map +1 -1
  370. package/workflow/WorkflowTaskApprovalSummary.js +6 -4
  371. package/workflow/WorkflowTaskApprovalSummary.js.map +1 -1
  372. package/workflow/WorkflowTaskList.js +2 -2
  373. package/workflow/WorkflowTaskList.js.map +1 -1
  374. package/workflow/WorkflowVersionBadge.d.ts.map +1 -1
  375. package/workflow/WorkflowVersionBadge.js +2 -1
  376. package/workflow/WorkflowVersionBadge.js.map +1 -1
  377. package/workflow/WorkflowVersionTimeline.d.ts.map +1 -1
  378. package/workflow/WorkflowVersionTimeline.js +2 -1
  379. package/workflow/WorkflowVersionTimeline.js.map +1 -1
  380. package/workflow/execution-comparison/ExecutionComparisonView.d.ts.map +1 -1
  381. package/workflow/execution-comparison/ExecutionComparisonView.js +2 -1
  382. package/workflow/execution-comparison/ExecutionComparisonView.js.map +1 -1
  383. package/workflow/execution-comparison/TaskComparisonTable.d.ts.map +1 -1
  384. package/workflow/execution-comparison/TaskComparisonTable.js +2 -1
  385. package/workflow/execution-comparison/TaskComparisonTable.js.map +1 -1
  386. package/workflow/execution-history/ExecutionHistoryTable.d.ts.map +1 -1
  387. package/workflow/execution-history/ExecutionHistoryTable.js +6 -4
  388. package/workflow/execution-history/ExecutionHistoryTable.js.map +1 -1
  389. package/workflow/inspector/InspectorHeader.d.ts.map +1 -1
  390. package/workflow/inspector/InspectorHeader.js +4 -2
  391. package/workflow/inspector/InspectorHeader.js.map +1 -1
  392. package/workflow/inspector/NestedTaskList.d.ts.map +1 -1
  393. package/workflow/inspector/NestedTaskList.js +2 -1
  394. package/workflow/inspector/NestedTaskList.js.map +1 -1
  395. package/workflow/inspector/WorkflowSummaryPanel.d.ts.map +1 -1
  396. package/workflow/inspector/WorkflowSummaryPanel.js +2 -1
  397. package/workflow/inspector/WorkflowSummaryPanel.js.map +1 -1
  398. package/workflow/inspector/tabs/BranchesTab.d.ts.map +1 -1
  399. package/workflow/inspector/tabs/BranchesTab.js +5 -2
  400. package/workflow/inspector/tabs/BranchesTab.js.map +1 -1
  401. package/workflow/instance/WorkflowInstanceList.d.ts.map +1 -1
  402. package/workflow/instance/WorkflowInstanceList.js +2 -1
  403. package/workflow/instance/WorkflowInstanceList.js.map +1 -1
  404. package/workflow/node-shell/DiffBadge.d.ts.map +1 -1
  405. package/workflow/node-shell/DiffBadge.js +3 -2
  406. package/workflow/node-shell/DiffBadge.js.map +1 -1
  407. package/workflow/node-shell/ExecutionBadge.d.ts.map +1 -1
  408. package/workflow/node-shell/ExecutionBadge.js +5 -4
  409. package/workflow/node-shell/ExecutionBadge.js.map +1 -1
  410. package/workflow/node-shell/NodeActions.d.ts.map +1 -1
  411. package/workflow/node-shell/NodeActions.js +12 -11
  412. package/workflow/node-shell/NodeActions.js.map +1 -1
  413. package/workflow/task-detail/StructuredDataViewer.d.ts.map +1 -1
  414. package/workflow/task-detail/StructuredDataViewer.js +5 -1
  415. package/workflow/task-detail/StructuredDataViewer.js.map +1 -1
  416. package/workspace/EditorTabs.d.ts.map +1 -1
  417. package/workspace/EditorTabs.js +38 -37
  418. package/workspace/EditorTabs.js.map +1 -1
  419. package/workspace/ExplorerTree.d.ts.map +1 -1
  420. package/workspace/ExplorerTree.js +2 -1
  421. package/workspace/ExplorerTree.js.map +1 -1
  422. package/workspace/FileViewer.d.ts.map +1 -1
  423. package/workspace/FileViewer.js +2 -1
  424. package/workspace/FileViewer.js.map +1 -1
  425. package/workspace/PanelChip.d.ts.map +1 -1
  426. package/workspace/PanelChip.js +2 -1
  427. package/workspace/PanelChip.js.map +1 -1
  428. package/workspace/WorkspaceEditor.d.ts.map +1 -1
  429. package/workspace/WorkspaceEditor.js +2 -1
  430. package/workspace/WorkspaceEditor.js.map +1 -1
  431. package/workspace/WorkspaceSummary.d.ts.map +1 -1
  432. package/workspace/WorkspaceSummary.js +7 -2
  433. package/workspace/WorkspaceSummary.js.map +1 -1
  434. package/workspace/WorkspaceSurface.d.ts.map +1 -1
  435. package/workspace/WorkspaceSurface.js +12 -11
  436. package/workspace/WorkspaceSurface.js.map +1 -1
  437. package/datastore/CollectionRecordsBrowser.d.ts +0 -34
  438. package/datastore/CollectionRecordsBrowser.d.ts.map +0 -1
  439. package/datastore/CollectionRecordsBrowser.js +0 -223
  440. package/datastore/CollectionRecordsBrowser.js.map +0 -1
  441. package/datastore/CollectionSchemaView.d.ts +0 -29
  442. package/datastore/CollectionSchemaView.d.ts.map +0 -1
  443. package/datastore/CollectionSchemaView.js +0 -93
  444. package/datastore/CollectionSchemaView.js.map +0 -1
  445. package/datastore/DatastoreDetailView.d.ts +0 -44
  446. package/datastore/DatastoreDetailView.d.ts.map +0 -1
  447. package/datastore/DatastoreDetailView.js +0 -76
  448. package/datastore/DatastoreDetailView.js.map +0 -1
  449. package/datastore/DatastoreSyncReport.d.ts +0 -19
  450. package/datastore/DatastoreSyncReport.d.ts.map +0 -1
  451. package/datastore/DatastoreSyncReport.js +0 -45
  452. package/datastore/DatastoreSyncReport.js.map +0 -1
  453. package/datastore/DeleteDatastoreDialog.d.ts +0 -35
  454. package/datastore/DeleteDatastoreDialog.d.ts.map +0 -1
  455. package/datastore/DeleteDatastoreDialog.js +0 -90
  456. package/datastore/DeleteDatastoreDialog.js.map +0 -1
  457. package/datastore/FieldValueControl.d.ts +0 -55
  458. package/datastore/FieldValueControl.d.ts.map +0 -1
  459. package/datastore/FieldValueControl.js +0 -138
  460. package/datastore/FieldValueControl.js.map +0 -1
  461. package/datastore/RecordFilterBuilder.d.ts +0 -37
  462. package/datastore/RecordFilterBuilder.d.ts.map +0 -1
  463. package/datastore/RecordFilterBuilder.js +0 -122
  464. package/datastore/RecordFilterBuilder.js.map +0 -1
  465. package/datastore/RecordFormPanel.d.ts +0 -45
  466. package/datastore/RecordFormPanel.d.ts.map +0 -1
  467. package/datastore/RecordFormPanel.js +0 -215
  468. package/datastore/RecordFormPanel.js.map +0 -1
  469. package/datastore/index.d.ts +0 -43
  470. package/datastore/index.d.ts.map +0 -1
  471. package/datastore/index.js +0 -22
  472. package/datastore/index.js.map +0 -1
  473. package/datastore/recordFilter.d.ts +0 -62
  474. package/datastore/recordFilter.d.ts.map +0 -1
  475. package/datastore/recordFilter.js +0 -104
  476. package/datastore/recordFilter.js.map +0 -1
  477. package/datastore/recordValues.d.ts +0 -85
  478. package/datastore/recordValues.d.ts.map +0 -1
  479. package/datastore/recordValues.js +0 -282
  480. package/datastore/recordValues.js.map +0 -1
  481. package/datastore/useDatastore.d.ts +0 -39
  482. package/datastore/useDatastore.d.ts.map +0 -1
  483. package/datastore/useDatastore.js +0 -44
  484. package/datastore/useDatastore.js.map +0 -1
  485. package/datastore/useDatastoreCount.d.ts +0 -50
  486. package/datastore/useDatastoreCount.d.ts.map +0 -1
  487. package/datastore/useDatastoreCount.js +0 -27
  488. package/datastore/useDatastoreCount.js.map +0 -1
  489. package/datastore/useDatastoreDescription.d.ts +0 -54
  490. package/datastore/useDatastoreDescription.d.ts.map +0 -1
  491. package/datastore/useDatastoreDescription.js +0 -50
  492. package/datastore/useDatastoreDescription.js.map +0 -1
  493. package/datastore/useDatastoreList.d.ts +0 -57
  494. package/datastore/useDatastoreList.d.ts.map +0 -1
  495. package/datastore/useDatastoreList.js +0 -29
  496. package/datastore/useDatastoreList.js.map +0 -1
  497. package/datastore/useDatastoreSearch.d.ts +0 -19
  498. package/datastore/useDatastoreSearch.d.ts.map +0 -1
  499. package/datastore/useDatastoreSearch.js +0 -22
  500. package/datastore/useDatastoreSearch.js.map +0 -1
  501. package/datastore/useDeleteDatastore.d.ts +0 -53
  502. package/datastore/useDeleteDatastore.d.ts.map +0 -1
  503. package/datastore/useDeleteDatastore.js +0 -40
  504. package/datastore/useDeleteDatastore.js.map +0 -1
  505. package/datastore/useDeleteRecord.d.ts +0 -34
  506. package/datastore/useDeleteRecord.d.ts.map +0 -1
  507. package/datastore/useDeleteRecord.js +0 -43
  508. package/datastore/useDeleteRecord.js.map +0 -1
  509. package/datastore/useInsertRecord.d.ts +0 -50
  510. package/datastore/useInsertRecord.d.ts.map +0 -1
  511. package/datastore/useInsertRecord.js +0 -55
  512. package/datastore/useInsertRecord.js.map +0 -1
  513. package/datastore/useRecordCollection.d.ts +0 -104
  514. package/datastore/useRecordCollection.d.ts.map +0 -1
  515. package/datastore/useRecordCollection.js +0 -136
  516. package/datastore/useRecordCollection.js.map +0 -1
  517. package/datastore/useRecordList.d.ts +0 -66
  518. package/datastore/useRecordList.d.ts.map +0 -1
  519. package/datastore/useRecordList.js +0 -58
  520. package/datastore/useRecordList.js.map +0 -1
  521. package/datastore/useUpdateRecord.d.ts +0 -52
  522. package/datastore/useUpdateRecord.d.ts.map +0 -1
  523. package/datastore/useUpdateRecord.js +0 -55
  524. package/datastore/useUpdateRecord.js.map +0 -1
  525. package/src/agent/__tests__/AgentDetailView.datastores.test.tsx +0 -166
  526. package/src/datastore/CollectionRecordsBrowser.tsx +0 -570
  527. package/src/datastore/CollectionSchemaView.tsx +0 -247
  528. package/src/datastore/DatastoreDetailView.tsx +0 -201
  529. package/src/datastore/DatastoreSyncReport.tsx +0 -105
  530. package/src/datastore/DeleteDatastoreDialog.tsx +0 -202
  531. package/src/datastore/FieldValueControl.tsx +0 -289
  532. package/src/datastore/RecordFilterBuilder.tsx +0 -422
  533. package/src/datastore/RecordFormPanel.tsx +0 -432
  534. package/src/datastore/__tests__/CollectionRecordsBrowser.test.tsx +0 -245
  535. package/src/datastore/__tests__/DeleteDatastoreDialog.test.tsx +0 -133
  536. package/src/datastore/__tests__/FieldValueControl.test.tsx +0 -160
  537. package/src/datastore/__tests__/RecordFilterBuilder.test.tsx +0 -155
  538. package/src/datastore/__tests__/RecordFormPanel.test.tsx +0 -227
  539. package/src/datastore/__tests__/recordFilter.test.ts +0 -169
  540. package/src/datastore/__tests__/recordMutations.test.tsx +0 -195
  541. package/src/datastore/__tests__/recordValues.test.ts +0 -359
  542. package/src/datastore/__tests__/schemaAndSyncViews.test.tsx +0 -142
  543. package/src/datastore/__tests__/useDatastoreDescription.test.tsx +0 -143
  544. package/src/datastore/__tests__/useRecordCollection.test.tsx +0 -250
  545. package/src/datastore/__tests__/useRecordList.test.tsx +0 -85
  546. package/src/datastore/index.ts +0 -111
  547. package/src/datastore/recordFilter.ts +0 -154
  548. package/src/datastore/recordValues.ts +0 -327
  549. package/src/datastore/useDatastore.ts +0 -67
  550. package/src/datastore/useDatastoreCount.ts +0 -69
  551. package/src/datastore/useDatastoreDescription.ts +0 -90
  552. package/src/datastore/useDatastoreList.ts +0 -79
  553. package/src/datastore/useDatastoreSearch.ts +0 -39
  554. package/src/datastore/useDeleteDatastore.ts +0 -87
  555. package/src/datastore/useDeleteRecord.ts +0 -77
  556. package/src/datastore/useInsertRecord.ts +0 -92
  557. package/src/datastore/useRecordCollection.ts +0 -256
  558. package/src/datastore/useRecordList.ts +0 -131
  559. package/src/datastore/useUpdateRecord.ts +0 -95
@@ -0,0 +1,504 @@
1
+ import { describe, it, expect, vi, beforeAll, afterEach } from "vitest";
2
+ import {
3
+ render,
4
+ screen,
5
+ cleanup,
6
+ fireEvent,
7
+ waitFor,
8
+ } from "@testing-library/react";
9
+ import { useEffect, useRef, type ReactNode } from "react";
10
+ import { create } from "@bufbuild/protobuf";
11
+ import { createRouterTransport, ConnectError, Code } from "@connectrpc/connect";
12
+ import { Stigmer } from "@stigmer/sdk";
13
+ import type { ResourceRef } from "@stigmer/sdk";
14
+ import { McpServerQueryController } from "@stigmer/protos/ai/stigmer/agentic/mcpserver/v1/query_pb";
15
+ import { McpServerCommandController } from "@stigmer/protos/ai/stigmer/agentic/mcpserver/v1/command_pb";
16
+ import {
17
+ OAuthConnectionHealth,
18
+ GetOAuthGrantStatusOutputSchema,
19
+ InitiateOAuthConnectOutputSchema,
20
+ CompleteOAuthConnectOutputSchema,
21
+ } from "@stigmer/protos/ai/stigmer/agentic/mcpserver/v1/io_pb";
22
+ import {
23
+ McpServerSpecSchema,
24
+ McpServerAuthSchema,
25
+ HttpServerConfigSchema,
26
+ } from "@stigmer/protos/ai/stigmer/agentic/mcpserver/v1/spec_pb";
27
+ import {
28
+ McpServerStatusSchema,
29
+ DiscoveredCapabilitiesSchema,
30
+ DiscoveredToolSchema,
31
+ } from "@stigmer/protos/ai/stigmer/agentic/mcpserver/v1/status_pb";
32
+ import { EnvVarDeclarationSchema } from "@stigmer/protos/ai/stigmer/agentic/environment/v1/spec_pb";
33
+ import { ApiResourceKind } from "@stigmer/protos/ai/stigmer/commons/apiresource/apiresourcekind/api_resource_kind_pb";
34
+ import type { McpServer } from "@stigmer/protos/ai/stigmer/agentic/mcpserver/v1/api_pb";
35
+ import { samples } from "../../test/samples";
36
+ import { StigmerContext } from "../../context";
37
+ import { McpServerPicker } from "../McpServerPicker";
38
+ import { useMcpServerSetup } from "../useMcpServerSetup";
39
+ import * as oauthPopup from "../../internal/oauthPopup.js";
40
+
41
+ // The popup machinery is window-dependent (window.open, postMessage,
42
+ // BroadcastChannel); these tests drive the RPC chain, so replace it with
43
+ // a deterministic callback handshake. The `openOAuthPopup` call count is
44
+ // the load-bearing assertion of this suite: a discovery-leg retry must
45
+ // NEVER reopen the popup (stigmer/stigmer#418).
46
+ vi.mock("../../internal/oauthPopup.js", () => ({
47
+ openOAuthPopup: vi.fn(() => ({ location: { href: "" }, closed: false })),
48
+ popupBlockedError: vi.fn(
49
+ () => new Error("Popup was blocked by the browser."),
50
+ ),
51
+ waitForOAuthCallback: vi.fn(async () => ({
52
+ code: "auth-code",
53
+ state: "state-1",
54
+ })),
55
+ closeOAuthPopup: vi.fn(),
56
+ OAUTH_CALLBACK_MESSAGE_TYPE: "stigmer:oauth:callback",
57
+ OAUTH_BROADCAST_CHANNEL: "stigmer:oauth:broadcast",
58
+ }));
59
+
60
+ const openOAuthPopupMock = vi.mocked(oauthPopup.openOAuthPopup);
61
+
62
+ beforeAll(() => {
63
+ // happy-dom lacks ResizeObserver, which the scroll-shadow machinery
64
+ // observes.
65
+ if (!("ResizeObserver" in globalThis)) {
66
+ (globalThis as unknown as { ResizeObserver: unknown }).ResizeObserver =
67
+ class {
68
+ observe() {}
69
+ unobserve() {}
70
+ disconnect() {}
71
+ };
72
+ }
73
+ });
74
+
75
+ afterEach(() => {
76
+ cleanup();
77
+ vi.clearAllMocks();
78
+ });
79
+
80
+ const ORG = "acme";
81
+ const SLUG = "order-management-api";
82
+ const SERVER_NAME = "Order Management API";
83
+
84
+ function serverRef(slug = SLUG): ResourceRef {
85
+ return { org: ORG, slug, kind: ApiResourceKind.mcp_server };
86
+ }
87
+
88
+ /**
89
+ * An OAuth-only server before any discovery: one declared env var that is
90
+ * also the OAuth target, no discovered capabilities.
91
+ */
92
+ function buildOAuthServer(o?: { name?: string; slug?: string; id?: string }): McpServer {
93
+ const server = samples.mcpServer({
94
+ name: o?.name ?? SERVER_NAME,
95
+ org: ORG,
96
+ slug: o?.slug ?? SLUG,
97
+ id: o?.id ?? "mcp-00000000-0000-0000-0000-00000000041a",
98
+ });
99
+ server.spec = create(McpServerSpecSchema, {
100
+ description: "REST API for order lookup and return processing.",
101
+ serverType: {
102
+ case: "http",
103
+ value: create(HttpServerConfigSchema, { url: "https://api.acme.com/mcp" }),
104
+ },
105
+ env: {
106
+ API_TOKEN: create(EnvVarDeclarationSchema, {
107
+ isSecret: true,
108
+ description: "OAuth access token",
109
+ }),
110
+ },
111
+ auth: create(McpServerAuthSchema, {
112
+ targetEnvVar: "API_TOKEN",
113
+ oauthOnly: true,
114
+ }),
115
+ });
116
+ return server;
117
+ }
118
+
119
+ /** The same server after a successful discovery: three tools. */
120
+ function buildDiscoveredServer(): McpServer {
121
+ const server = buildOAuthServer();
122
+ server.status = create(McpServerStatusSchema, {
123
+ discoveredCapabilities: create(DiscoveredCapabilitiesSchema, {
124
+ tools: [
125
+ create(DiscoveredToolSchema, { name: "get_order" }),
126
+ create(DiscoveredToolSchema, { name: "list_orders" }),
127
+ create(DiscoveredToolSchema, { name: "process_return" }),
128
+ ],
129
+ }),
130
+ });
131
+ return server;
132
+ }
133
+
134
+ function grantStatusOutput(
135
+ connected: boolean,
136
+ health: OAuthConnectionHealth,
137
+ ) {
138
+ return create(GetOAuthGrantStatusOutputSchema, {
139
+ connected,
140
+ connectionHealth: health,
141
+ targetEnvVar: connected ? "API_TOKEN" : "",
142
+ authMethod: connected ? "mcp_oauth" : "",
143
+ });
144
+ }
145
+
146
+ /**
147
+ * Composes the picker with a real `useMcpServerSetup`, wired exactly the
148
+ * way `SessionComposer` wires it. The given refs are added once on mount.
149
+ */
150
+ function PickerHarness({ refs }: { readonly refs: readonly ResourceRef[] }) {
151
+ const setup = useMcpServerSetup(ORG);
152
+ const addedRef = useRef(false);
153
+ const { addServer } = setup;
154
+ useEffect(() => {
155
+ if (addedRef.current) return;
156
+ addedRef.current = true;
157
+ for (const ref of refs) void addServer(ref);
158
+ }, [refs, addServer]);
159
+
160
+ return (
161
+ <McpServerPicker
162
+ org={ORG}
163
+ setup={{
164
+ entries: setup.entries,
165
+ onServerAdded: (ref) => void setup.addServer(ref),
166
+ onServerRemoved: setup.removeServer,
167
+ onSubmitEnvVars: (ref, values, opts) =>
168
+ void setup.submitEnvVars(ref, values, opts),
169
+ onEnabledToolsChange: setup.setEnabledTools,
170
+ }}
171
+ />
172
+ );
173
+ }
174
+
175
+ /**
176
+ * Mounts the harness against a real Connect router transport. RPCs a test
177
+ * does not register fall through to Connect's `unimplemented`, which the
178
+ * SDK hooks degrade from (search list and personal-environment lookups
179
+ * are irrelevant here and stay unregistered).
180
+ */
181
+ function renderPicker(
182
+ register: Parameters<typeof createRouterTransport>[0],
183
+ refs: readonly ResourceRef[] = [serverRef()],
184
+ ) {
185
+ const client = new Stigmer({
186
+ baseUrl: "/",
187
+ getAccessToken: () => "test-token",
188
+ customTransport: createRouterTransport(register),
189
+ });
190
+ return render(
191
+ <StigmerContext.Provider value={client}>
192
+ <PickerHarness refs={refs} />
193
+ </StigmerContext.Provider>,
194
+ );
195
+ }
196
+
197
+ async function drillIntoConfigure(buttonName: RegExp) {
198
+ const configure = await screen.findByRole("button", { name: buttonName });
199
+ fireEvent.click(configure);
200
+ }
201
+
202
+ describe("McpServerPicker — discovery-leg failure (in-flow arm)", () => {
203
+ function registerFailingDiscovery() {
204
+ // Mutable fixture state: the grant flips to connected at token
205
+ // exchange (the two-act persistence contract), and discovery starts
206
+ // failing, then succeeds once `discoveryFails` is cleared.
207
+ const state = {
208
+ server: buildOAuthServer(),
209
+ grantConnected: false,
210
+ discoveryFails: true,
211
+ };
212
+ const connectSpy = vi.fn(() => {
213
+ if (state.discoveryFails) {
214
+ throw new ConnectError("discovery workflow failed", Code.Internal);
215
+ }
216
+ state.server = buildDiscoveredServer();
217
+ return state.server;
218
+ });
219
+
220
+ const register: Parameters<typeof createRouterTransport>[0] = (
221
+ router,
222
+ ) => {
223
+ router.service(McpServerQueryController, {
224
+ getByReference: () => state.server,
225
+ getOAuthGrantStatus: () =>
226
+ grantStatusOutput(
227
+ state.grantConnected,
228
+ state.grantConnected
229
+ ? OAuthConnectionHealth.OAUTH_CONNECTION_HEALTH_HEALTHY
230
+ : OAuthConnectionHealth.OAUTH_CONNECTION_HEALTH_NO_GRANT,
231
+ ),
232
+ });
233
+ router.service(McpServerCommandController, {
234
+ initiateOAuthConnect: () =>
235
+ create(InitiateOAuthConnectOutputSchema, {
236
+ authorizationUrl: "https://vendor.example/authorize",
237
+ state: "state-1",
238
+ }),
239
+ completeOAuthConnect: () => {
240
+ state.grantConnected = true;
241
+ return create(CompleteOAuthConnectOutputSchema, { connected: true });
242
+ },
243
+ connect: connectSpy,
244
+ });
245
+ };
246
+
247
+ return { state, connectSpy, register };
248
+ }
249
+
250
+ async function signInAndFailDiscovery() {
251
+ await drillIntoConfigure(new RegExp(`Configure ${SLUG}`));
252
+ fireEvent.click(
253
+ await screen.findByRole("button", {
254
+ name: `Sign in with ${SERVER_NAME}`,
255
+ }),
256
+ );
257
+ // Honest copy: the sign-in succeeded, only the discovery leg broke.
258
+ await screen.findByText(
259
+ /Signed in successfully, but tool discovery failed/,
260
+ );
261
+ }
262
+
263
+ it("renders the honest copy, stranded status, and a Discover tools action", async () => {
264
+ const { register } = registerFailingDiscovery();
265
+ renderPicker(register);
266
+
267
+ await signInAndFailDiscovery();
268
+
269
+ expect(
270
+ screen.getByText("Signed in — tools not discovered yet"),
271
+ ).toBeTruthy();
272
+ expect(
273
+ screen.getByRole("button", { name: "Discover tools" }),
274
+ ).toBeTruthy();
275
+ expect(
276
+ screen.queryByRole("button", { name: `Sign in with ${SERVER_NAME}` }),
277
+ ).toBeNull();
278
+ });
279
+
280
+ it("retries with a bare connect and never reopens the popup", async () => {
281
+ const { state, connectSpy, register } = registerFailingDiscovery();
282
+ renderPicker(register);
283
+
284
+ await signInAndFailDiscovery();
285
+ expect(openOAuthPopupMock).toHaveBeenCalledTimes(1);
286
+ expect(connectSpy).toHaveBeenCalledTimes(1);
287
+
288
+ state.discoveryFails = false;
289
+ fireEvent.click(screen.getByRole("button", { name: "Discover tools" }));
290
+
291
+ // Discovery succeeded → the entry re-resolves ready with real tools;
292
+ // the stranded state and its affordance retire themselves.
293
+ await waitFor(() =>
294
+ expect(
295
+ screen.queryByText("Signed in — tools not discovered yet"),
296
+ ).toBeNull(),
297
+ );
298
+ await screen.findByText("process_return");
299
+ expect(
300
+ screen.queryByRole("button", { name: "Discover tools" }),
301
+ ).toBeNull();
302
+ expect(connectSpy).toHaveBeenCalledTimes(2);
303
+ expect(openOAuthPopupMock).toHaveBeenCalledTimes(1);
304
+ });
305
+
306
+ it("keeps a failing bare retry honest and popup-free", async () => {
307
+ const { connectSpy, register } = registerFailingDiscovery();
308
+ renderPicker(register);
309
+
310
+ await signInAndFailDiscovery();
311
+ fireEvent.click(screen.getByRole("button", { name: "Discover tools" }));
312
+
313
+ await waitFor(() => expect(connectSpy).toHaveBeenCalledTimes(2));
314
+ // Still stranded, still honest, still no second popup.
315
+ await screen.findByText(
316
+ /Signed in successfully, but tool discovery failed/,
317
+ );
318
+ expect(
319
+ screen.getByRole("button", { name: "Discover tools" }),
320
+ ).toBeTruthy();
321
+ expect(openOAuthPopupMock).toHaveBeenCalledTimes(1);
322
+ });
323
+
324
+ it("routes a non-discovery failure back through the OAuth popup", async () => {
325
+ renderPicker((router) => {
326
+ router.service(McpServerQueryController, {
327
+ getByReference: () => buildOAuthServer(),
328
+ getOAuthGrantStatus: () =>
329
+ grantStatusOutput(
330
+ false,
331
+ OAuthConnectionHealth.OAUTH_CONNECTION_HEALTH_NO_GRANT,
332
+ ),
333
+ });
334
+ router.service(McpServerCommandController, {
335
+ initiateOAuthConnect: () =>
336
+ create(InitiateOAuthConnectOutputSchema, {
337
+ authorizationUrl: "https://vendor.example/authorize",
338
+ state: "state-1",
339
+ }),
340
+ completeOAuthConnect: () => {
341
+ throw new ConnectError("token exchange failed", Code.Unavailable);
342
+ },
343
+ });
344
+ });
345
+
346
+ await drillIntoConfigure(new RegExp(`Configure ${SLUG}`));
347
+ const signIn = await screen.findByRole("button", {
348
+ name: `Sign in with ${SERVER_NAME}`,
349
+ });
350
+
351
+ fireEvent.click(signIn);
352
+ await screen.findByText(/token exchange failed/);
353
+ // Sign-in itself failed — no "signed in successfully" framing, and the
354
+ // action remains a full OAuth relaunch.
355
+ expect(
356
+ screen.queryByText(/Signed in successfully/),
357
+ ).toBeNull();
358
+ fireEvent.click(
359
+ screen.getByRole("button", { name: `Sign in with ${SERVER_NAME}` }),
360
+ );
361
+ await waitFor(() => expect(openOAuthPopupMock).toHaveBeenCalledTimes(2));
362
+ });
363
+ });
364
+
365
+ describe("McpServerPicker — stranded server truth (reopen/re-add arm)", () => {
366
+ it("offers Discover tools for a usable grant with zero discovered tools", async () => {
367
+ let server = buildOAuthServer();
368
+ const connectSpy = vi.fn(() => {
369
+ server = buildDiscoveredServer();
370
+ return server;
371
+ });
372
+
373
+ renderPicker((router) => {
374
+ router.service(McpServerQueryController, {
375
+ getByReference: () => server,
376
+ getOAuthGrantStatus: () =>
377
+ grantStatusOutput(
378
+ true,
379
+ OAuthConnectionHealth.OAUTH_CONNECTION_HEALTH_HEALTHY,
380
+ ),
381
+ });
382
+ router.service(McpServerCommandController, { connect: connectSpy });
383
+ });
384
+
385
+ // Grant exists → the entry resolves ready, but with nothing discovered.
386
+ await drillIntoConfigure(new RegExp(`Configure ${SLUG}`));
387
+
388
+ await screen.findByText("Signed in — tools not discovered yet");
389
+ fireEvent.click(
390
+ await screen.findByRole("button", { name: "Discover tools" }),
391
+ );
392
+
393
+ await waitFor(() =>
394
+ expect(
395
+ screen.queryByText("Signed in — tools not discovered yet"),
396
+ ).toBeNull(),
397
+ );
398
+ await screen.findByText("process_return");
399
+ expect(connectSpy).toHaveBeenCalledTimes(1);
400
+ expect(openOAuthPopupMock).not.toHaveBeenCalled();
401
+ });
402
+
403
+ it("offers re-auth, not discovery, for an expired grant", async () => {
404
+ renderPicker((router) => {
405
+ router.service(McpServerQueryController, {
406
+ getByReference: () => buildOAuthServer(),
407
+ getOAuthGrantStatus: () =>
408
+ grantStatusOutput(
409
+ true,
410
+ OAuthConnectionHealth.OAUTH_CONNECTION_HEALTH_TOKEN_EXPIRED,
411
+ ),
412
+ });
413
+ });
414
+
415
+ await drillIntoConfigure(new RegExp(`Configure ${SLUG}`));
416
+
417
+ await screen.findByRole("button", { name: "Sign in to reconnect" });
418
+ expect(screen.queryByRole("button", { name: "Discover tools" })).toBeNull();
419
+
420
+ fireEvent.click(
421
+ screen.getByRole("button", { name: "Sign in to reconnect" }),
422
+ );
423
+ await waitFor(() => expect(openOAuthPopupMock).toHaveBeenCalledTimes(1));
424
+ });
425
+ });
426
+
427
+ describe("McpServerPicker — cross-server scoping", () => {
428
+ it("keeps server A's discovery failure out of server B's configure view", async () => {
429
+ const SLUG_B = "billing-api";
430
+ const NAME_B = "Billing API";
431
+ const serverA = buildOAuthServer();
432
+ const serverB = buildOAuthServer({
433
+ name: NAME_B,
434
+ slug: SLUG_B,
435
+ id: "mcp-00000000-0000-0000-0000-00000000041b",
436
+ });
437
+ let grantConnectedA = false;
438
+ const connectSpy = vi.fn(() => {
439
+ throw new ConnectError("discovery workflow failed", Code.Internal);
440
+ });
441
+
442
+ renderPicker(
443
+ (router) => {
444
+ router.service(McpServerQueryController, {
445
+ getByReference: (input) =>
446
+ input.slug === SLUG_B ? serverB : serverA,
447
+ getOAuthGrantStatus: (input) =>
448
+ grantStatusOutput(
449
+ input.resourceId === serverA.metadata!.id && grantConnectedA,
450
+ input.resourceId === serverA.metadata!.id && grantConnectedA
451
+ ? OAuthConnectionHealth.OAUTH_CONNECTION_HEALTH_HEALTHY
452
+ : OAuthConnectionHealth.OAUTH_CONNECTION_HEALTH_NO_GRANT,
453
+ ),
454
+ });
455
+ router.service(McpServerCommandController, {
456
+ initiateOAuthConnect: () =>
457
+ create(InitiateOAuthConnectOutputSchema, {
458
+ authorizationUrl: "https://vendor.example/authorize",
459
+ state: "state-1",
460
+ }),
461
+ completeOAuthConnect: () => {
462
+ grantConnectedA = true;
463
+ return create(CompleteOAuthConnectOutputSchema, {
464
+ connected: true,
465
+ });
466
+ },
467
+ connect: connectSpy,
468
+ });
469
+ },
470
+ [serverRef(), serverRef(SLUG_B)],
471
+ );
472
+
473
+ // Server A: sign in, discovery fails.
474
+ await drillIntoConfigure(new RegExp(`Configure ${SLUG}$`));
475
+ fireEvent.click(
476
+ await screen.findByRole("button", {
477
+ name: `Sign in with ${SERVER_NAME}`,
478
+ }),
479
+ );
480
+ await screen.findByText(
481
+ /Signed in successfully, but tool discovery failed/,
482
+ );
483
+ expect(openOAuthPopupMock).toHaveBeenCalledTimes(1);
484
+
485
+ // Back to the list, drill into server B.
486
+ fireEvent.click(
487
+ screen.getByRole("button", { name: "Back to MCP server list" }),
488
+ );
489
+ await drillIntoConfigure(new RegExp(`Configure ${SLUG_B}`));
490
+
491
+ // B must not inherit A's failure: no honest-copy banner, no stranded
492
+ // affordance — a fresh sign-in action.
493
+ await screen.findByRole("button", { name: `Sign in with ${NAME_B}` });
494
+ expect(screen.queryByText(/Signed in successfully/)).toBeNull();
495
+ expect(screen.queryByRole("button", { name: "Discover tools" })).toBeNull();
496
+
497
+ // And B's sign-in goes through the popup — proving it did not take
498
+ // A's bare-discovery retry branch.
499
+ fireEvent.click(
500
+ screen.getByRole("button", { name: `Sign in with ${NAME_B}` }),
501
+ );
502
+ await waitFor(() => expect(openOAuthPopupMock).toHaveBeenCalledTimes(2));
503
+ });
504
+ });