@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,321 @@
1
+ import { describe, it, expect, vi, beforeAll, afterEach } from "vitest";
2
+ import { render, screen, cleanup, fireEvent } from "@testing-library/react";
3
+ import type { ReactNode } from "react";
4
+ import { create } from "@bufbuild/protobuf";
5
+ import { createRouterTransport } from "@connectrpc/connect";
6
+ import { Stigmer } from "@stigmer/sdk";
7
+ import { McpServerQueryController } from "@stigmer/protos/ai/stigmer/agentic/mcpserver/v1/query_pb";
8
+ import { GetOAuthGrantStatusOutputSchema } from "@stigmer/protos/ai/stigmer/agentic/mcpserver/v1/io_pb";
9
+ import {
10
+ McpServerSpecSchema,
11
+ McpServerAuthSchema,
12
+ HttpServerConfigSchema,
13
+ } from "@stigmer/protos/ai/stigmer/agentic/mcpserver/v1/spec_pb";
14
+ import {
15
+ McpServerStatusSchema,
16
+ OAuthStatusSchema,
17
+ OAuthAppSource,
18
+ ValidationState,
19
+ } from "@stigmer/protos/ai/stigmer/agentic/mcpserver/v1/status_pb";
20
+ import { VendorApprovalStatus } from "@stigmer/protos/ai/stigmer/iam/oauthapp/v1/spec_pb";
21
+ import { ApiResourceKind } from "@stigmer/protos/ai/stigmer/commons/apiresource/apiresourcekind/api_resource_kind_pb";
22
+ import type { McpServer } from "@stigmer/protos/ai/stigmer/agentic/mcpserver/v1/api_pb";
23
+ import { samples } from "../../test/samples";
24
+ import { StigmerContext } from "../../context";
25
+ import { McpServerConnectDialog } from "../McpServerConnectDialog";
26
+ import { McpServerDetailView } from "../McpServerDetailView";
27
+ import { McpServerConfigPanel } from "../McpServerConfigPanel";
28
+ import type { UseMcpServerReturn } from "../useMcpServer";
29
+
30
+ /**
31
+ * Pins the oauth_only + vendor-approval-blocked combination across the three
32
+ * connect surfaces (stigmer/stigmer#412). Before the shared notice, this
33
+ * state was a silent dead end in the connect dialog (disabled button, no
34
+ * reason, no way forward) and two surfaces recommended manual token entry on
35
+ * servers whose endpoint rejects static tokens.
36
+ */
37
+
38
+ // happy-dom does not implement the native dialog show/close methods.
39
+ beforeAll(() => {
40
+ HTMLDialogElement.prototype.showModal = function showModal() {
41
+ this.open = true;
42
+ };
43
+ HTMLDialogElement.prototype.close = function close() {
44
+ this.open = false;
45
+ };
46
+ });
47
+
48
+ afterEach(cleanup);
49
+
50
+ const ORG = "acme";
51
+ const SLUG = "vendor-crm";
52
+ const DOCS_URL = "https://vendor.example.com/oauth-docs";
53
+
54
+ /**
55
+ * An oauth_only vendor-OAuth server whose platform OAuth app is blocked.
56
+ * `withAppRef` controls the BYOA arm: with a ref and a platform-sourced
57
+ * effective app, `canBringOwnApp` is true.
58
+ */
59
+ function buildBlockedOAuthOnlyServer(options: {
60
+ status: VendorApprovalStatus;
61
+ withAppRef: boolean;
62
+ }): McpServer {
63
+ const server = samples.mcpServer({ name: "Vendor CRM", org: ORG, slug: SLUG });
64
+ server.spec = create(McpServerSpecSchema, {
65
+ description: "CRM tools over the vendor's hosted MCP endpoint.",
66
+ serverType: {
67
+ case: "http",
68
+ value: create(HttpServerConfigSchema, { url: "https://mcp.vendor.example.com" }),
69
+ },
70
+ auth: create(McpServerAuthSchema, {
71
+ targetEnvVar: "VENDOR_ACCESS_TOKEN",
72
+ oauthOnly: true,
73
+ ...(options.withAppRef
74
+ ? {
75
+ oauthAppRef: {
76
+ org: "stigmer",
77
+ kind: ApiResourceKind.oauth_app,
78
+ slug: "vendor-oauth",
79
+ },
80
+ }
81
+ : {}),
82
+ }),
83
+ });
84
+ server.status = create(McpServerStatusSchema, {
85
+ validationState: ValidationState.valid,
86
+ oauthStatus: create(OAuthStatusSchema, {
87
+ vendorApprovalStatus: options.status,
88
+ vendorApprovalDocsUrl: DOCS_URL,
89
+ effectiveOauthSource: OAuthAppSource.OAUTH_APP_SOURCE_PLATFORM,
90
+ }),
91
+ });
92
+ return server;
93
+ }
94
+
95
+ function noGrant() {
96
+ return create(GetOAuthGrantStatusOutputSchema, { connected: false });
97
+ }
98
+
99
+ function renderWithTransport(
100
+ ui: ReactNode,
101
+ register: Parameters<typeof createRouterTransport>[0] = () => {},
102
+ ) {
103
+ const client = new Stigmer({
104
+ baseUrl: "/",
105
+ getAccessToken: () => "test-token",
106
+ customTransport: createRouterTransport(register),
107
+ });
108
+ return render(
109
+ <StigmerContext.Provider value={client}>{ui}</StigmerContext.Provider>,
110
+ );
111
+ }
112
+
113
+ // ---------------------------------------------------------------------------
114
+ // Surface 1: McpServerConnectDialog — the surface that was a silent dead end
115
+ // ---------------------------------------------------------------------------
116
+
117
+ describe("McpServerConnectDialog — oauth_only + vendor-blocked", () => {
118
+ function renderDialog(server: McpServer, onOpenDetails?: () => void) {
119
+ return renderWithTransport(
120
+ <McpServerConnectDialog
121
+ org={ORG}
122
+ slug={SLUG}
123
+ open
124
+ onClose={() => {}}
125
+ onOpenDetails={onOpenDetails}
126
+ />,
127
+ (router) => {
128
+ router.service(McpServerQueryController, {
129
+ getByReference: () => server,
130
+ getOAuthGrantStatus: noGrant,
131
+ });
132
+ },
133
+ );
134
+ }
135
+
136
+ it("explains the blocked state instead of showing only a disabled button", async () => {
137
+ renderDialog(
138
+ buildBlockedOAuthOnlyServer({
139
+ status: VendorApprovalStatus.PENDING,
140
+ withAppRef: true,
141
+ }),
142
+ );
143
+
144
+ const signIn = await screen.findByRole("button", {
145
+ name: "Sign in with OAuth",
146
+ });
147
+ expect((signIn as HTMLButtonElement).disabled).toBe(true);
148
+ // The reason is always visible — this was the oss#412 dead end.
149
+ expect(screen.getByText(/is awaiting vendor approval/)).toBeTruthy();
150
+ });
151
+
152
+ it("never offers manual entry on an oauth_only server", async () => {
153
+ renderDialog(
154
+ buildBlockedOAuthOnlyServer({
155
+ status: VendorApprovalStatus.PENDING,
156
+ withAppRef: true,
157
+ }),
158
+ );
159
+
160
+ await screen.findByRole("button", { name: "Sign in with OAuth" });
161
+ // OAuthRequiredNotice legitimately says tokens are *rejected*; what must
162
+ // never appear is a recommendation to enter one.
163
+ expect(screen.queryByText(/enter (a|your) token manually/i)).toBeNull();
164
+ expect(
165
+ screen.queryByRole("button", { name: "Enter token manually" }),
166
+ ).toBeNull();
167
+ });
168
+
169
+ it("routes the BYOA escape hatch to onOpenDetails", async () => {
170
+ const onOpenDetails = vi.fn();
171
+ renderDialog(
172
+ buildBlockedOAuthOnlyServer({
173
+ status: VendorApprovalStatus.PENDING,
174
+ withAppRef: true,
175
+ }),
176
+ onOpenDetails,
177
+ );
178
+
179
+ fireEvent.click(
180
+ await screen.findByRole("button", { name: "Use your own OAuth app" }),
181
+ );
182
+ expect(onOpenDetails).toHaveBeenCalledTimes(1);
183
+ });
184
+
185
+ it("is honest about rejection and falls back to the docs link without BYOA", async () => {
186
+ renderDialog(
187
+ buildBlockedOAuthOnlyServer({
188
+ status: VendorApprovalStatus.REJECTED,
189
+ withAppRef: false,
190
+ }),
191
+ );
192
+
193
+ expect(
194
+ await screen.findByText(/was not approved by the vendor/),
195
+ ).toBeTruthy();
196
+ expect(screen.queryByText(/awaiting vendor approval/)).toBeNull();
197
+ const docs = screen.getByRole("link", {
198
+ name: /Learn how to bring your own token/,
199
+ });
200
+ expect(docs.getAttribute("href")).toBe(DOCS_URL);
201
+ });
202
+ });
203
+
204
+ // ---------------------------------------------------------------------------
205
+ // Surface 2: McpServerDetailView — the banner that recommended a dead path
206
+ // ---------------------------------------------------------------------------
207
+
208
+ describe("McpServerDetailView — oauth_only + vendor-blocked", () => {
209
+ function loadedState(server: McpServer): UseMcpServerReturn {
210
+ return {
211
+ mcpServer: server,
212
+ isLoading: false,
213
+ isRefetching: false,
214
+ error: null,
215
+ refetch: vi.fn(),
216
+ };
217
+ }
218
+
219
+ it("offers BYOA without recommending manual entry, and keeps the tour's CTA marker", async () => {
220
+ renderWithTransport(
221
+ <McpServerDetailView
222
+ org={ORG}
223
+ slug={SLUG}
224
+ mcpServerState={loadedState(
225
+ buildBlockedOAuthOnlyServer({
226
+ status: VendorApprovalStatus.PENDING,
227
+ withAppRef: true,
228
+ }),
229
+ )}
230
+ />,
231
+ (router) => {
232
+ router.service(McpServerQueryController, {
233
+ getOAuthGrantStatus: noGrant,
234
+ });
235
+ },
236
+ );
237
+
238
+ expect(
239
+ await screen.findByText(
240
+ "The platform's OAuth app is awaiting vendor approval. You can use your own OAuth app.",
241
+ ),
242
+ ).toBeTruthy();
243
+ // OAuthRequiredNotice legitimately says tokens are *rejected*; what must
244
+ // never appear is a recommendation to enter one.
245
+ expect(screen.queryByText(/enter (a|your) token manually/i)).toBeNull();
246
+ expect(
247
+ screen.queryByRole("button", { name: "Enter token manually" }),
248
+ ).toBeNull();
249
+
250
+ const cta = screen.getByRole("button", { name: "Use your own OAuth app" });
251
+ // The byoa-setup docs tour targets this marker; it must survive the
252
+ // extraction into the shared notice.
253
+ expect(cta.getAttribute("data-cursor-target")).toBe("byoa-cta-button");
254
+ });
255
+ });
256
+
257
+ // ---------------------------------------------------------------------------
258
+ // Surface 3: McpServerConfigPanel — the session-setup inline sign-in
259
+ // ---------------------------------------------------------------------------
260
+
261
+ describe("McpServerConfigPanel — oauth_only + vendor-blocked", () => {
262
+ function renderPanel(
263
+ oauthSignInOverrides: Record<string, unknown> = {},
264
+ panelOverrides: Record<string, unknown> = {},
265
+ ) {
266
+ const server = buildBlockedOAuthOnlyServer({
267
+ status: VendorApprovalStatus.PENDING,
268
+ withAppRef: true,
269
+ });
270
+ return renderWithTransport(
271
+ <McpServerConfigPanel
272
+ mcpServer={server}
273
+ oauthSignIn={{
274
+ onSignIn: () => {},
275
+ phase: "idle",
276
+ isConnected: false,
277
+ error: null,
278
+ onClearError: () => {},
279
+ isVendorApprovalPending: true,
280
+ isVendorApprovalBlocked: true,
281
+ vendorApprovalDocsUrl: DOCS_URL,
282
+ ...oauthSignInOverrides,
283
+ }}
284
+ discoveredTools={[]}
285
+ toolApprovals={[]}
286
+ enabledTools={[]}
287
+ onEnabledToolsChange={() => {}}
288
+ onBack={() => {}}
289
+ error={null}
290
+ {...panelOverrides}
291
+ />,
292
+ );
293
+ }
294
+
295
+ it("never claims manual entry when the affordance is not wired (oauth_only)", () => {
296
+ renderPanel();
297
+ expect(screen.getByText(/is awaiting vendor approval/)).toBeTruthy();
298
+ expect(screen.queryByText(/manually/)).toBeNull();
299
+ });
300
+
301
+ it("explicit manualEntrySupported=false wins even if a switch handler leaks through", () => {
302
+ renderPanel(
303
+ { manualEntrySupported: false },
304
+ { onSwitchToManual: () => {} },
305
+ );
306
+ expect(screen.getByText(/is awaiting vendor approval/)).toBeTruthy();
307
+ expect(
308
+ screen.getByText(/OAuth sign-in is temporarily unavailable for this server/),
309
+ ).toBeTruthy();
310
+ expect(
311
+ screen.queryByText(/You can use your own OAuth app or enter a token manually/),
312
+ ).toBeNull();
313
+ });
314
+
315
+ it("mentions manual entry when the panel actually offers it (legacy fallback)", () => {
316
+ renderPanel({}, { onSwitchToManual: () => {} });
317
+ expect(
318
+ screen.getByText(/You can still connect by entering your own token manually/),
319
+ ).toBeTruthy();
320
+ });
321
+ });
@@ -0,0 +1,154 @@
1
+ import { describe, it, expect, vi, afterEach } from "vitest";
2
+ import { render, screen, cleanup, fireEvent } from "@testing-library/react";
3
+ import { VendorApprovalBlockedNotice } from "../VendorApprovalBlockedNotice";
4
+
5
+ afterEach(cleanup);
6
+
7
+ /**
8
+ * The copy contract for the vendor-approval-blocked state lives here.
9
+ *
10
+ * The invariant under test (stigmer/stigmer#412): the notice must never
11
+ * recommend a path that does not exist. "Enter a token manually" may only
12
+ * appear when the endpoint accepts static tokens; "use your own OAuth app"
13
+ * only when BYOA is relevant; and when neither exists the notice must still
14
+ * explain the state — a disabled button is never the only signal.
15
+ */
16
+
17
+ const DOCS_URL = "https://vendor.example.com/oauth-docs";
18
+
19
+ function renderNotice(
20
+ overrides: Partial<Parameters<typeof VendorApprovalBlockedNotice>[0]> = {},
21
+ ) {
22
+ return render(
23
+ <VendorApprovalBlockedNotice
24
+ blocked
25
+ pending
26
+ manualEntrySupported
27
+ canBringOwnApp={false}
28
+ docsUrl={null}
29
+ {...overrides}
30
+ />,
31
+ );
32
+ }
33
+
34
+ describe("VendorApprovalBlockedNotice — self-gating", () => {
35
+ it("renders nothing when not blocked", () => {
36
+ const { container } = renderNotice({ blocked: false });
37
+ expect(container.innerHTML).toBe("");
38
+ });
39
+ });
40
+
41
+ describe("VendorApprovalBlockedNotice — status sentence honesty", () => {
42
+ it("says awaiting approval for a PENDING app", () => {
43
+ renderNotice({ pending: true });
44
+ expect(
45
+ screen.getByText(/is awaiting vendor approval/),
46
+ ).toBeTruthy();
47
+ });
48
+
49
+ it("says not approved for a REJECTED app — never 'pending'", () => {
50
+ renderNotice({ pending: false });
51
+ expect(
52
+ screen.getByText(/was not approved by the vendor/),
53
+ ).toBeTruthy();
54
+ expect(screen.queryByText(/awaiting vendor approval/)).toBeNull();
55
+ expect(screen.queryByText(/pending/i)).toBeNull();
56
+ });
57
+ });
58
+
59
+ describe("VendorApprovalBlockedNotice — alternative-path matrix", () => {
60
+ it("BYOA + manual: offers both (the copy depicted in the byoa-setup tour, byte-stable)", () => {
61
+ renderNotice({ canBringOwnApp: true, manualEntrySupported: true });
62
+ expect(
63
+ screen.getByText(
64
+ "The platform's OAuth app is awaiting vendor approval. You can use your own OAuth app or enter a token manually.",
65
+ ),
66
+ ).toBeTruthy();
67
+ });
68
+
69
+ it("BYOA + oauth_only: offers BYOA and never mentions manual entry", () => {
70
+ renderNotice({ canBringOwnApp: true, manualEntrySupported: false });
71
+ expect(screen.getByText(/You can use your own OAuth app\./)).toBeTruthy();
72
+ expect(screen.queryByText(/manually/)).toBeNull();
73
+ });
74
+
75
+ it("no BYOA + manual: offers manual entry", () => {
76
+ renderNotice({ canBringOwnApp: false, manualEntrySupported: true });
77
+ expect(
78
+ screen.getByText(/You can still connect by entering your own token manually\./),
79
+ ).toBeTruthy();
80
+ });
81
+
82
+ it("no BYOA + oauth_only: still explains itself with no false path", () => {
83
+ renderNotice({ canBringOwnApp: false, manualEntrySupported: false });
84
+ expect(
85
+ screen.getByText(/OAuth sign-in is temporarily unavailable for this server\./),
86
+ ).toBeTruthy();
87
+ expect(screen.queryByText(/manually/)).toBeNull();
88
+ expect(screen.queryByText(/your own OAuth app/)).toBeNull();
89
+ });
90
+ });
91
+
92
+ describe("VendorApprovalBlockedNotice — affordances", () => {
93
+ it("renders the BYOA call-to-action and routes clicks", () => {
94
+ const onBringOwnApp = vi.fn();
95
+ renderNotice({ canBringOwnApp: true, onBringOwnApp });
96
+
97
+ fireEvent.click(
98
+ screen.getByRole("button", { name: "Use your own OAuth app" }),
99
+ );
100
+ expect(onBringOwnApp).toHaveBeenCalledTimes(1);
101
+ });
102
+
103
+ it("omits the BYOA call-to-action when no action is wired, keeping the copy", () => {
104
+ renderNotice({ canBringOwnApp: true });
105
+ expect(
106
+ screen.queryByRole("button", { name: "Use your own OAuth app" }),
107
+ ).toBeNull();
108
+ expect(screen.getByText(/You can use your own OAuth app/)).toBeTruthy();
109
+ });
110
+
111
+ it("links the docs when BYOA is not offered inline", () => {
112
+ renderNotice({ canBringOwnApp: false, docsUrl: DOCS_URL });
113
+ const link = screen.getByRole("link", {
114
+ name: /Learn how to bring your own token/,
115
+ });
116
+ expect(link.getAttribute("href")).toBe(DOCS_URL);
117
+ expect(link.getAttribute("target")).toBe("_blank");
118
+ });
119
+
120
+ it("suppresses the docs link when the BYOA form (which carries it) is one click away", () => {
121
+ renderNotice({ canBringOwnApp: true, docsUrl: DOCS_URL, onBringOwnApp: vi.fn() });
122
+ expect(
123
+ screen.queryByRole("link", { name: /Learn how to bring your own token/ }),
124
+ ).toBeNull();
125
+ });
126
+
127
+ it("no-alternative floor: docs link is the way forward when present", () => {
128
+ renderNotice({
129
+ canBringOwnApp: false,
130
+ manualEntrySupported: false,
131
+ docsUrl: DOCS_URL,
132
+ });
133
+ expect(
134
+ screen.getByRole("link", { name: /Learn how to bring your own token/ }),
135
+ ).toBeTruthy();
136
+ });
137
+ });
138
+
139
+ describe("VendorApprovalBlockedNotice — compact variant", () => {
140
+ it("carries the same copy contract at the dense size", () => {
141
+ renderNotice({
142
+ compact: true,
143
+ pending: false,
144
+ canBringOwnApp: true,
145
+ manualEntrySupported: false,
146
+ onBringOwnApp: vi.fn(),
147
+ });
148
+ expect(screen.getByText(/was not approved by the vendor/)).toBeTruthy();
149
+ expect(screen.queryByText(/manually/)).toBeNull();
150
+ expect(
151
+ screen.getByRole("button", { name: "Use your own OAuth app" }),
152
+ ).toBeTruthy();
153
+ });
154
+ });
@@ -1,5 +1,6 @@
1
1
  import type { ResourceRef } from "@stigmer/sdk";
2
2
  import type { McpServer } from "@stigmer/protos/ai/stigmer/agentic/mcpserver/v1/api_pb";
3
+ import type { OAuthConnectionHealth } from "@stigmer/protos/ai/stigmer/agentic/mcpserver/v1/io_pb";
3
4
  import type { DiscoveredTool } from "@stigmer/protos/ai/stigmer/agentic/mcpserver/v1/status_pb";
4
5
  import type { ToolApprovalPolicy } from "@stigmer/protos/ai/stigmer/agentic/mcpserver/v1/spec_pb";
5
6
  import type { EnvVarFormVariable } from "../environment/EnvVarForm.js";
@@ -61,6 +62,8 @@ export type McpServerSetupPhase =
61
62
  readonly discoveredTools: DiscoveredTool[];
62
63
  /** Per-tool approval policies from the server spec. */
63
64
  readonly toolApprovals: ToolApprovalPolicy[];
65
+ /** OAuth grant health at resolve time — full doc on the `ready` variant. */
66
+ readonly oauthConnectionHealth?: OAuthConnectionHealth;
64
67
  }
65
68
  | {
66
69
  /** Environment variables are being persisted or the instance is being provisioned. */
@@ -73,6 +76,8 @@ export type McpServerSetupPhase =
73
76
  readonly discoveredTools: DiscoveredTool[];
74
77
  /** Per-tool approval policies from the server spec. */
75
78
  readonly toolApprovals: ToolApprovalPolicy[];
79
+ /** OAuth grant health at resolve time — full doc on the `ready` variant. */
80
+ readonly oauthConnectionHealth?: OAuthConnectionHealth;
76
81
  }
77
82
  | {
78
83
  /** The server is fully configured and ready for session creation. */
@@ -85,6 +90,15 @@ export type McpServerSetupPhase =
85
90
  readonly toolApprovals: ToolApprovalPolicy[];
86
91
  /** Tool names enabled for this session, after user selection. */
87
92
  readonly enabledTools: string[];
93
+ /**
94
+ * OAuth grant health at resolve time, from the grant-status lookup
95
+ * `addServer` performs for OAuth-declaring servers. `undefined` when
96
+ * no lookup ran (server has no OAuth declaration) or the lookup
97
+ * failed. Consumers use it to distinguish "signed in but tools never
98
+ * discovered" (offer bare discovery, stigmer/stigmer#418) from
99
+ * "token expired" (offer re-auth) without another RPC.
100
+ */
101
+ readonly oauthConnectionHealth?: OAuthConnectionHealth;
88
102
  };
89
103
 
90
104
  /**
@@ -145,6 +159,8 @@ export type McpServerSetupAction =
145
159
  readonly discoveredTools: DiscoveredTool[];
146
160
  /** Per-tool approval policies from the server spec. */
147
161
  readonly toolApprovals: ToolApprovalPolicy[];
162
+ /** OAuth grant health at resolve time, when a lookup ran. */
163
+ readonly oauthConnectionHealth?: OAuthConnectionHealth;
148
164
  }
149
165
  | {
150
166
  /** Server resolved and is ready (no env vars needed). */
@@ -159,6 +175,8 @@ export type McpServerSetupAction =
159
175
  readonly toolApprovals: ToolApprovalPolicy[];
160
176
  /** Tool names enabled for this session. */
161
177
  readonly enabledTools: string[];
178
+ /** OAuth grant health at resolve time, when a lookup ran. */
179
+ readonly oauthConnectionHealth?: OAuthConnectionHealth;
162
180
  }
163
181
  | {
164
182
  /** Re-evaluate missing variables after pool values arrive. */
@@ -254,6 +272,7 @@ export function mcpServerSetupReducer(
254
272
  missingVariables: action.missingVariables,
255
273
  discoveredTools: action.discoveredTools,
256
274
  toolApprovals: action.toolApprovals,
275
+ oauthConnectionHealth: action.oauthConnectionHealth,
257
276
  error: null,
258
277
  },
259
278
  };
@@ -270,6 +289,7 @@ export function mcpServerSetupReducer(
270
289
  discoveredTools: action.discoveredTools,
271
290
  toolApprovals: action.toolApprovals,
272
291
  enabledTools: action.enabledTools,
292
+ oauthConnectionHealth: action.oauthConnectionHealth,
273
293
  error: null,
274
294
  },
275
295
  };
@@ -288,6 +308,7 @@ export function mcpServerSetupReducer(
288
308
  discoveredTools: entry.discoveredTools,
289
309
  toolApprovals: entry.toolApprovals,
290
310
  enabledTools: action.enabledTools,
311
+ oauthConnectionHealth: entry.oauthConnectionHealth,
291
312
  error: null,
292
313
  },
293
314
  };
@@ -313,6 +334,7 @@ export function mcpServerSetupReducer(
313
334
  missingVariables: entry.missingVariables,
314
335
  discoveredTools: entry.discoveredTools,
315
336
  toolApprovals: entry.toolApprovals,
337
+ oauthConnectionHealth: entry.oauthConnectionHealth,
316
338
  error: null,
317
339
  },
318
340
  };
@@ -329,6 +351,7 @@ export function mcpServerSetupReducer(
329
351
  discoveredTools: entry.discoveredTools,
330
352
  toolApprovals: entry.toolApprovals,
331
353
  enabledTools: action.enabledTools,
354
+ oauthConnectionHealth: entry.oauthConnectionHealth,
332
355
  error: null,
333
356
  },
334
357
  };
@@ -345,6 +368,7 @@ export function mcpServerSetupReducer(
345
368
  missingVariables: entry.missingVariables,
346
369
  discoveredTools: entry.discoveredTools,
347
370
  toolApprovals: entry.toolApprovals,
371
+ oauthConnectionHealth: entry.oauthConnectionHealth,
348
372
  error: action.error,
349
373
  },
350
374
  };
@@ -5,6 +5,7 @@ import type { EnvVarInput, McpServerUsageInput, ResourceRef } from "@stigmer/sdk
5
5
  import { create } from "@bufbuild/protobuf";
6
6
  import type { McpServer } from "@stigmer/protos/ai/stigmer/agentic/mcpserver/v1/api_pb";
7
7
  import { GetOAuthGrantStatusInputSchema } from "@stigmer/protos/ai/stigmer/agentic/mcpserver/v1/io_pb";
8
+ import type { OAuthConnectionHealth } from "@stigmer/protos/ai/stigmer/agentic/mcpserver/v1/io_pb";
8
9
  import type { DiscoveredTool } from "@stigmer/protos/ai/stigmer/agentic/mcpserver/v1/status_pb";
9
10
  import { ApiResourceKind } from "@stigmer/protos/ai/stigmer/commons/apiresource/apiresourcekind/api_resource_kind_pb";
10
11
  import { useStigmer } from "../hooks.js";
@@ -287,6 +288,11 @@ export function useMcpServerSetup(
287
288
  Object.keys(personalEnv.environment?.spec?.data ?? {}),
288
289
  );
289
290
 
291
+ // Carried onto the entry so consumers can tell a healthy grant
292
+ // that merely lacks tool discovery (offer bare discovery,
293
+ // stigmer/stigmer#418) apart from an expired one (offer re-auth).
294
+ let oauthConnectionHealth: OAuthConnectionHealth | undefined;
295
+
290
296
  const auth = mcpServer.spec?.auth;
291
297
  if (auth?.targetEnvVar && mcpServer.metadata?.id) {
292
298
  try {
@@ -296,6 +302,7 @@ export function useMcpServerSetup(
296
302
  org,
297
303
  }),
298
304
  );
305
+ oauthConnectionHealth = grantStatus.connectionHealth;
299
306
  if (grantStatus.connected) {
300
307
  existingKeys.add(auth.targetEnvVar);
301
308
  }
@@ -319,6 +326,7 @@ export function useMcpServerSetup(
319
326
  mcpServer,
320
327
  discoveredTools,
321
328
  ),
329
+ oauthConnectionHealth,
322
330
  });
323
331
  return;
324
332
  }
@@ -330,6 +338,7 @@ export function useMcpServerSetup(
330
338
  missingVariables: requiredMissing,
331
339
  discoveredTools,
332
340
  toolApprovals,
341
+ oauthConnectionHealth,
333
342
  });
334
343
  } catch (err) {
335
344
  dispatch({ type: "SET_ERROR", key, error: toError(err) });
@@ -4,6 +4,7 @@ import { cn } from "@stigmer/theme";
4
4
  import { getUserMessage } from "@stigmer/sdk";
5
5
  import { timestampDate } from "@bufbuild/protobuf/wkt";
6
6
  import type { OAuthApp } from "@stigmer/protos/ai/stigmer/iam/oauthapp/v1/api_pb";
7
+ import { Tooltip, TooltipContent, TooltipTrigger } from "../internal/tooltip.js";
7
8
  import { useOAuthAppList } from "./useOAuthAppList.js";
8
9
 
9
10
  // ---------------------------------------------------------------------------
@@ -153,9 +154,16 @@ function OAuthAppRow({
153
154
 
154
155
  <div className="stg:hidden stg:shrink-0 stg:items-center stg:gap-4 stg:text-xs stg:text-muted-foreground stg:sm:flex">
155
156
  {createdAt && (
156
- <span title={`Created ${timestampDate(createdAt).toISOString()}`}>
157
- {formatShortDate(timestampDate(createdAt))}
158
- </span>
157
+ <Tooltip>
158
+ <TooltipTrigger
159
+ render={<time dateTime={timestampDate(createdAt).toISOString()} />}
160
+ >
161
+ {formatShortDate(timestampDate(createdAt))}
162
+ </TooltipTrigger>
163
+ <TooltipContent side="top">
164
+ {`Created ${timestampDate(createdAt).toISOString()}`}
165
+ </TooltipContent>
166
+ </Tooltip>
159
167
  )}
160
168
  </div>
161
169