@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.
- package/activity/useRecentActivity.d.ts +3 -2
- package/activity/useRecentActivity.d.ts.map +1 -1
- package/activity/useRecentActivity.js +3 -2
- package/activity/useRecentActivity.js.map +1 -1
- package/agent/AgentDetailView.d.ts +2 -12
- package/agent/AgentDetailView.d.ts.map +1 -1
- package/agent/AgentDetailView.js +10 -42
- package/agent/AgentDetailView.js.map +1 -1
- package/agent/internal/agentToInput.d.ts.map +1 -1
- package/agent/internal/agentToInput.js +0 -8
- package/agent/internal/agentToInput.js.map +1 -1
- package/agent-instance/AgentInstanceList.d.ts.map +1 -1
- package/agent-instance/AgentInstanceList.js +2 -1
- package/agent-instance/AgentInstanceList.js.map +1 -1
- package/api-key/ApiKeyListPanel.d.ts.map +1 -1
- package/api-key/ApiKeyListPanel.js +2 -1
- package/api-key/ApiKeyListPanel.js.map +1 -1
- package/attachment/AttachmentChipList.d.ts.map +1 -1
- package/attachment/AttachmentChipList.js +9 -8
- package/attachment/AttachmentChipList.js.map +1 -1
- package/attachment/AttachmentImageLightbox.d.ts.map +1 -1
- package/attachment/AttachmentImageLightbox.js +1 -1
- package/attachment/AttachmentImageLightbox.js.map +1 -1
- package/channel/AgentChannelsPanel.d.ts.map +1 -1
- package/channel/AgentChannelsPanel.js +2 -1
- package/channel/AgentChannelsPanel.js.map +1 -1
- package/channel/ChannelConversationsDialog.d.ts.map +1 -1
- package/channel/ChannelConversationsDialog.js +2 -1
- package/channel/ChannelConversationsDialog.js.map +1 -1
- package/channel/ChannelTemplatesDialog.d.ts.map +1 -1
- package/channel/ChannelTemplatesDialog.js +2 -1
- package/channel/ChannelTemplatesDialog.js.map +1 -1
- package/channel-app/internal.d.ts.map +1 -1
- package/channel-app/internal.js +2 -1
- package/channel-app/internal.js.map +1 -1
- package/composer/ComposerToolbar.d.ts.map +1 -1
- package/composer/ComposerToolbar.js +10 -7
- package/composer/ComposerToolbar.js.map +1 -1
- package/composer/ConfigureMenu.d.ts.map +1 -1
- package/composer/ConfigureMenu.js +2 -1
- package/composer/ConfigureMenu.js.map +1 -1
- package/composer/ContextChip.d.ts.map +1 -1
- package/composer/ContextChip.js +2 -1
- package/composer/ContextChip.js.map +1 -1
- package/composer/ContextPopover.d.ts.map +1 -1
- package/composer/ContextPopover.js +2 -1
- package/composer/ContextPopover.js.map +1 -1
- package/composer/SessionComposer.d.ts +13 -0
- package/composer/SessionComposer.d.ts.map +1 -1
- package/composer/SessionComposer.js +12 -2
- package/composer/SessionComposer.js.map +1 -1
- package/conversation/ConversationMediaAttachment.d.ts.map +1 -1
- package/conversation/ConversationMediaAttachment.js +2 -1
- package/conversation/ConversationMediaAttachment.js.map +1 -1
- package/conversation/ConversationTimelineView.d.ts.map +1 -1
- package/conversation/ConversationTimelineView.js +14 -4
- package/conversation/ConversationTimelineView.js.map +1 -1
- package/conversation/conversationPresentation.d.ts +28 -0
- package/conversation/conversationPresentation.d.ts.map +1 -1
- package/conversation/conversationPresentation.js +38 -1
- package/conversation/conversationPresentation.js.map +1 -1
- package/cursor-accounts/MemberCoverageTable.d.ts.map +1 -1
- package/cursor-accounts/MemberCoverageTable.js +6 -5
- package/cursor-accounts/MemberCoverageTable.js.map +1 -1
- package/dashboard/DashboardKPICards.d.ts.map +1 -1
- package/dashboard/DashboardKPICards.js +3 -1
- package/dashboard/DashboardKPICards.js.map +1 -1
- package/dependency-graph/DependencyTreeNode.d.ts.map +1 -1
- package/dependency-graph/DependencyTreeNode.js +1 -7
- package/dependency-graph/DependencyTreeNode.js.map +1 -1
- package/dependency-graph/types.d.ts +8 -20
- package/dependency-graph/types.d.ts.map +1 -1
- package/dependency-graph/useDependencyGraph.d.ts.map +1 -1
- package/dependency-graph/useDependencyGraph.js +2 -20
- package/dependency-graph/useDependencyGraph.js.map +1 -1
- package/environment/EnvironmentVariableEditor.d.ts.map +1 -1
- package/environment/EnvironmentVariableEditor.js +2 -1
- package/environment/EnvironmentVariableEditor.js.map +1 -1
- package/execution/ApprovalCard.d.ts.map +1 -1
- package/execution/ApprovalCard.js +1 -1
- package/execution/ApprovalCard.js.map +1 -1
- package/execution/ArtifactRowView.d.ts.map +1 -1
- package/execution/ArtifactRowView.js +2 -1
- package/execution/ArtifactRowView.js.map +1 -1
- package/execution/FilePathLink.d.ts +4 -4
- package/execution/FilePathLink.d.ts.map +1 -1
- package/execution/FilePathLink.js +4 -4
- package/execution/FilePathLink.js.map +1 -1
- package/execution/McpToolDetail.d.ts.map +1 -1
- package/execution/McpToolDetail.js +2 -1
- package/execution/McpToolDetail.js.map +1 -1
- package/execution/MessageAttachments.d.ts.map +1 -1
- package/execution/MessageAttachments.js +10 -8
- package/execution/MessageAttachments.js.map +1 -1
- package/execution/MessageEntry.d.ts.map +1 -1
- package/execution/MessageEntry.js +2 -1
- package/execution/MessageEntry.js.map +1 -1
- package/execution/PlanArtifactCard.d.ts.map +1 -1
- package/execution/PlanArtifactCard.js +7 -4
- package/execution/PlanArtifactCard.js.map +1 -1
- package/execution/ToolCallDetail.d.ts.map +1 -1
- package/execution/ToolCallDetail.js +1 -1
- package/execution/ToolCallDetail.js.map +1 -1
- package/execution/ToolCallItem.d.ts.map +1 -1
- package/execution/ToolCallItem.js +5 -1
- package/execution/ToolCallItem.js.map +1 -1
- package/execution/WriteBackCard.d.ts.map +1 -1
- package/execution/WriteBackCard.js +6 -4
- package/execution/WriteBackCard.js.map +1 -1
- package/execution/artifact-row-item.d.ts +1 -1
- package/execution/artifact-row-item.d.ts.map +1 -1
- package/file-reference/FileReferenceChipList.d.ts.map +1 -1
- package/file-reference/FileReferenceChipList.js +6 -1
- package/file-reference/FileReferenceChipList.js.map +1 -1
- package/iam-policy/OrgMembersPanel.d.ts.map +1 -1
- package/iam-policy/OrgMembersPanel.js +6 -5
- package/iam-policy/OrgMembersPanel.js.map +1 -1
- package/iam-policy/ProviderBadge.d.ts.map +1 -1
- package/iam-policy/ProviderBadge.js +3 -2
- package/iam-policy/ProviderBadge.js.map +1 -1
- package/iam-policy/RoleSelector.d.ts.map +1 -1
- package/iam-policy/RoleSelector.js +1 -1
- package/iam-policy/RoleSelector.js.map +1 -1
- package/identity-provider/IdentityProviderListPanel.d.ts.map +1 -1
- package/identity-provider/IdentityProviderListPanel.js +2 -1
- package/identity-provider/IdentityProviderListPanel.js.map +1 -1
- package/index.d.ts +0 -2
- package/index.d.ts.map +1 -1
- package/index.js +0 -6
- package/index.js.map +1 -1
- package/internal/truncated-text.d.ts +17 -0
- package/internal/truncated-text.d.ts.map +1 -0
- package/internal/truncated-text.js +27 -0
- package/internal/truncated-text.js.map +1 -0
- package/invitation/InvitationManager.d.ts.map +1 -1
- package/invitation/InvitationManager.js +4 -3
- package/invitation/InvitationManager.js.map +1 -1
- package/library/ScopeToggle.d.ts.map +1 -1
- package/library/ScopeToggle.js +10 -2
- package/library/ScopeToggle.js.map +1 -1
- package/library/VisibilitySelector.d.ts.map +1 -1
- package/library/VisibilitySelector.js +2 -1
- package/library/VisibilitySelector.js.map +1 -1
- package/library/useExportResource.d.ts +3 -4
- package/library/useExportResource.d.ts.map +1 -1
- package/library/useExportResource.js +1 -1
- package/library/useExportResource.js.map +1 -1
- package/manifest/EditResourceYamlDialog.d.ts.map +1 -1
- package/manifest/EditResourceYamlDialog.js.map +1 -1
- package/mcp-server/McpServerConfigPanel.d.ts +30 -1
- package/mcp-server/McpServerConfigPanel.d.ts.map +1 -1
- package/mcp-server/McpServerConfigPanel.js +18 -8
- package/mcp-server/McpServerConfigPanel.js.map +1 -1
- package/mcp-server/McpServerConnectDialog.d.ts +12 -1
- package/mcp-server/McpServerConnectDialog.d.ts.map +1 -1
- package/mcp-server/McpServerConnectDialog.js +8 -7
- package/mcp-server/McpServerConnectDialog.js.map +1 -1
- package/mcp-server/McpServerDetailView.d.ts.map +1 -1
- package/mcp-server/McpServerDetailView.js +4 -4
- package/mcp-server/McpServerDetailView.js.map +1 -1
- package/mcp-server/McpServerPicker.d.ts.map +1 -1
- package/mcp-server/McpServerPicker.js +86 -5
- package/mcp-server/McpServerPicker.js.map +1 -1
- package/mcp-server/McpToolSelector.d.ts.map +1 -1
- package/mcp-server/McpToolSelector.js +2 -1
- package/mcp-server/McpToolSelector.js.map +1 -1
- package/mcp-server/VendorApprovalBlockedNotice.d.ts +77 -0
- package/mcp-server/VendorApprovalBlockedNotice.d.ts.map +1 -0
- package/mcp-server/VendorApprovalBlockedNotice.js +62 -0
- package/mcp-server/VendorApprovalBlockedNotice.js.map +1 -0
- package/mcp-server/mcpServerSetupReducer.d.ts +18 -0
- package/mcp-server/mcpServerSetupReducer.d.ts.map +1 -1
- package/mcp-server/mcpServerSetupReducer.js +6 -0
- package/mcp-server/mcpServerSetupReducer.js.map +1 -1
- package/mcp-server/useMcpServerSetup.d.ts.map +1 -1
- package/mcp-server/useMcpServerSetup.js +7 -0
- package/mcp-server/useMcpServerSetup.js.map +1 -1
- package/oauth-app/OAuthAppListPanel.d.ts.map +1 -1
- package/oauth-app/OAuthAppListPanel.js +2 -1
- package/oauth-app/OAuthAppListPanel.js.map +1 -1
- package/package.json +4 -4
- package/platform-client/PlatformClientListPanel.d.ts.map +1 -1
- package/platform-client/PlatformClientListPanel.js +3 -2
- package/platform-client/PlatformClientListPanel.js.map +1 -1
- package/pricing-governance/BaselineEditor.d.ts.map +1 -1
- package/pricing-governance/BaselineEditor.js +7 -1
- package/pricing-governance/BaselineEditor.js.map +1 -1
- package/pricing-governance/ModelCatalogPanel.d.ts.map +1 -1
- package/pricing-governance/ModelCatalogPanel.js +2 -1
- package/pricing-governance/ModelCatalogPanel.js.map +1 -1
- package/pricing-governance/PricingGovernanceConsole.d.ts.map +1 -1
- package/pricing-governance/PricingGovernanceConsole.js +2 -1
- package/pricing-governance/PricingGovernanceConsole.js.map +1 -1
- package/pricing-governance/PricingGovernancePanel.d.ts.map +1 -1
- package/pricing-governance/PricingGovernancePanel.js +2 -1
- package/pricing-governance/PricingGovernancePanel.js.map +1 -1
- package/resource-workbench/components/StatusBadge.d.ts.map +1 -1
- package/resource-workbench/components/StatusBadge.js +2 -1
- package/resource-workbench/components/StatusBadge.js.map +1 -1
- package/schedule/CadenceField.d.ts.map +1 -1
- package/schedule/CadenceField.js +15 -8
- package/schedule/CadenceField.js.map +1 -1
- package/schedule/ScheduleRunsTable.d.ts.map +1 -1
- package/schedule/ScheduleRunsTable.js +3 -2
- package/schedule/ScheduleRunsTable.js.map +1 -1
- package/session/PlanEditor.d.ts.map +1 -1
- package/session/PlanEditor.js +3 -5
- package/session/PlanEditor.js.map +1 -1
- package/sharing/AgentShareList.d.ts.map +1 -1
- package/sharing/AgentShareList.js +3 -1
- package/sharing/AgentShareList.js.map +1 -1
- package/sharing/ShareAgentDialog.d.ts.map +1 -1
- package/sharing/ShareAgentDialog.js +2 -1
- package/sharing/ShareAgentDialog.js.map +1 -1
- package/skill/SkillDetailView.d.ts.map +1 -1
- package/skill/SkillDetailView.js +3 -2
- package/skill/SkillDetailView.js.map +1 -1
- package/src/__tests__/helpers/open-menu.ts +88 -0
- package/src/__tests__/portal-container.test.tsx +3 -3
- package/src/activity/useRecentActivity.ts +3 -2
- package/src/agent/AgentDetailView.tsx +6 -130
- package/src/agent/internal/__tests__/agentToInput.test.ts +2 -11
- package/src/agent/internal/agentToInput.ts +0 -11
- package/src/agent-instance/AgentInstanceList.tsx +5 -6
- package/src/agent-instance/__tests__/AgentInstanceList.test.tsx +5 -4
- package/src/api-key/ApiKeyListPanel.tsx +11 -3
- package/src/attachment/AttachmentChipList.tsx +74 -65
- package/src/attachment/AttachmentImageLightbox.tsx +5 -4
- package/src/attachment/__tests__/AttachmentChipList.test.tsx +4 -3
- package/src/channel/AgentChannelsPanel.tsx +5 -6
- package/src/channel/ChannelConversationsDialog.tsx +5 -3
- package/src/channel/ChannelTemplatesDialog.tsx +5 -6
- package/src/channel/__tests__/AgentChannelsPanel.test.tsx +14 -9
- package/src/channel-app/internal.tsx +5 -6
- package/src/composer/ComposerToolbar.tsx +122 -90
- package/src/composer/ConfigureMenu.tsx +33 -24
- package/src/composer/ContextChip.tsx +2 -3
- package/src/composer/ContextPopover.tsx +27 -18
- package/src/composer/SessionComposer.tsx +41 -9
- package/src/composer/__tests__/SessionComposer-agentSetupError.test.tsx +124 -0
- package/src/composer/__tests__/SessionComposer-lockAgent.test.tsx +4 -9
- package/src/conversation/ConversationMediaAttachment.tsx +2 -2
- package/src/conversation/ConversationTimelineView.tsx +19 -2
- package/src/conversation/__tests__/ConversationTimelineView.test.tsx +106 -3
- package/src/conversation/conversationPresentation.ts +52 -1
- package/src/cursor-accounts/MemberCoverageTable.tsx +15 -13
- package/src/cursor-accounts/__tests__/CursorAccountsConsole.test.tsx +4 -4
- package/src/dashboard/DashboardKPICards.tsx +2 -1
- package/src/dependency-graph/DependencyTreeNode.tsx +1 -7
- package/src/dependency-graph/__tests__/useDependencyGraph.test.ts +18 -34
- package/src/dependency-graph/types.ts +8 -20
- package/src/dependency-graph/useDependencyGraph.ts +2 -22
- package/src/environment/EnvironmentVariableEditor.tsx +17 -6
- package/src/execution/ApprovalCard.tsx +1 -3
- package/src/execution/ArtifactRowView.tsx +68 -48
- package/src/execution/FilePathLink.tsx +43 -27
- package/src/execution/McpToolDetail.tsx +6 -2
- package/src/execution/MessageAttachments.tsx +57 -41
- package/src/execution/MessageEntry.tsx +22 -15
- package/src/execution/PlanArtifactCard.tsx +25 -18
- package/src/execution/ToolCallDetail.tsx +1 -4
- package/src/execution/ToolCallItem.tsx +18 -7
- package/src/execution/WriteBackCard.tsx +38 -29
- package/src/execution/__tests__/ArtifactRow.test.tsx +6 -2
- package/src/execution/__tests__/ArtifactRowView.test.tsx +5 -2
- package/src/execution/__tests__/FilePathLink.test.tsx +10 -6
- package/src/execution/__tests__/FileReviewCard.test.tsx +2 -1
- package/src/execution/__tests__/MessageEntry-attachments.test.tsx +3 -2
- package/src/execution/__tests__/MessageThread.test.tsx +6 -1
- package/src/execution/__tests__/artifact-row-tooltips.layout.test.tsx +115 -0
- package/src/execution/artifact-row-item.ts +1 -1
- package/src/file-reference/FileReferenceChipList.tsx +29 -17
- package/src/file-reference/__tests__/FileReferenceChipList.test.tsx +5 -2
- package/src/iam-policy/OrgMembersPanel.tsx +26 -19
- package/src/iam-policy/ProviderBadge.tsx +17 -10
- package/src/iam-policy/RoleSelector.tsx +0 -1
- package/src/identity-provider/IdentityProviderListPanel.tsx +11 -3
- package/src/index.ts +0 -82
- package/src/internal/__tests__/truncated-text.layout.test.tsx +68 -0
- package/src/internal/__tests__/truncated-text.test.tsx +33 -0
- package/src/internal/truncated-text.tsx +81 -0
- package/src/invitation/InvitationManager.tsx +18 -5
- package/src/library/ScopeToggle.tsx +14 -2
- package/src/library/VisibilitySelector.tsx +21 -14
- package/src/library/useExportResource.ts +3 -4
- package/src/manifest/EditResourceYamlDialog.tsx +1 -2
- package/src/manifest/__tests__/ApplyManifestDialog.test.tsx +2 -2
- package/src/manifest/__tests__/EditResourceYamlDialog.test.tsx +9 -9
- package/src/mcp-server/McpServerConfigPanel.tsx +79 -37
- package/src/mcp-server/McpServerConnectDialog.tsx +41 -5
- package/src/mcp-server/McpServerDetailView.tsx +23 -39
- package/src/mcp-server/McpServerPicker.tsx +99 -7
- package/src/mcp-server/McpToolSelector.tsx +12 -7
- package/src/mcp-server/VendorApprovalBlockedNotice.tsx +221 -0
- package/src/mcp-server/__tests__/McpServerPicker.test.tsx +504 -0
- package/src/mcp-server/__tests__/VendorApprovalBlocked.surfaces.test.tsx +321 -0
- package/src/mcp-server/__tests__/VendorApprovalBlockedNotice.test.tsx +154 -0
- package/src/mcp-server/mcpServerSetupReducer.ts +24 -0
- package/src/mcp-server/useMcpServerSetup.ts +9 -0
- package/src/oauth-app/OAuthAppListPanel.tsx +11 -3
- package/src/platform-client/PlatformClientListPanel.tsx +35 -18
- package/src/pricing-governance/BaselineEditor.tsx +20 -0
- package/src/pricing-governance/ModelCatalogPanel.tsx +9 -5
- package/src/pricing-governance/PricingGovernanceConsole.tsx +9 -5
- package/src/pricing-governance/PricingGovernancePanel.tsx +13 -4
- package/src/pricing-governance/__tests__/ModelCatalogPanel.test.tsx +37 -0
- package/src/resource-workbench/components/StatusBadge.tsx +7 -3
- package/src/schedule/CadenceField.tsx +38 -27
- package/src/schedule/ScheduleRunsTable.tsx +23 -11
- package/src/schedule/__tests__/cadence-tooltips.layout.test.tsx +86 -0
- package/src/session/PlanEditor.tsx +9 -8
- package/src/sharing/AgentShareList.tsx +28 -22
- package/src/sharing/ShareAgentDialog.tsx +5 -6
- package/src/sharing/__tests__/AgentShareList.test.tsx +4 -4
- package/src/skill/SkillDetailView.tsx +23 -12
- package/src/version-history/VersionTimelineEntry.tsx +21 -12
- package/src/workflow/CanvasTransitionEdge.tsx +23 -16
- package/src/workflow/ExecutionActiveTaskIndicator.tsx +74 -59
- package/src/workflow/TaskPickerPopover.tsx +0 -1
- package/src/workflow/WorkflowCanvasEditor.tsx +95 -64
- package/src/workflow/WorkflowNode.tsx +13 -6
- package/src/workflow/WorkflowTaskApprovalSummary.tsx +18 -11
- package/src/workflow/WorkflowTaskList.tsx +2 -2
- package/src/workflow/WorkflowVersionBadge.tsx +33 -18
- package/src/workflow/WorkflowVersionTimeline.tsx +7 -6
- package/src/workflow/__tests__/WorkflowTaskApprovalSummary.test.tsx +3 -1
- package/src/workflow/__tests__/structured-data-viewer.test.tsx +5 -2
- package/src/workflow/execution-comparison/ExecutionComparisonView.tsx +5 -3
- package/src/workflow/execution-comparison/TaskComparisonTable.tsx +12 -5
- package/src/workflow/execution-history/ExecutionHistoryTable.tsx +24 -15
- package/src/workflow/inspector/InspectorHeader.tsx +20 -11
- package/src/workflow/inspector/NestedTaskList.tsx +18 -11
- package/src/workflow/inspector/WorkflowSummaryPanel.tsx +5 -3
- package/src/workflow/inspector/tabs/BranchesTab.tsx +61 -31
- package/src/workflow/instance/WorkflowInstanceList.tsx +5 -6
- package/src/workflow/instance/__tests__/WorkflowInstanceList.test.tsx +5 -4
- package/src/workflow/node-shell/DiffBadge.tsx +18 -11
- package/src/workflow/node-shell/ExecutionBadge.tsx +73 -46
- package/src/workflow/node-shell/NodeActions.tsx +128 -94
- package/src/workflow/task-detail/StructuredDataViewer.tsx +4 -2
- package/src/workspace/EditorTabs.tsx +102 -85
- package/src/workspace/ExplorerTree.tsx +47 -30
- package/src/workspace/FileViewer.tsx +11 -3
- package/src/workspace/PanelChip.tsx +32 -23
- package/src/workspace/WorkspaceEditor.tsx +21 -9
- package/src/workspace/WorkspaceSummary.tsx +21 -12
- package/src/workspace/WorkspaceSurface.tsx +86 -61
- package/src/workspace/__tests__/EditorTabs.test.tsx +5 -2
- package/src/workspace/__tests__/WorkspaceSurface.test.tsx +5 -2
- package/styles.css +1 -1
- package/version-history/VersionTimelineEntry.d.ts.map +1 -1
- package/version-history/VersionTimelineEntry.js +2 -1
- package/version-history/VersionTimelineEntry.js.map +1 -1
- package/workflow/CanvasTransitionEdge.d.ts +1 -1
- package/workflow/CanvasTransitionEdge.d.ts.map +1 -1
- package/workflow/CanvasTransitionEdge.js +3 -2
- package/workflow/CanvasTransitionEdge.js.map +1 -1
- package/workflow/ExecutionActiveTaskIndicator.d.ts.map +1 -1
- package/workflow/ExecutionActiveTaskIndicator.js +12 -11
- package/workflow/ExecutionActiveTaskIndicator.js.map +1 -1
- package/workflow/TaskPickerPopover.js +1 -1
- package/workflow/TaskPickerPopover.js.map +1 -1
- package/workflow/WorkflowCanvasEditor.d.ts.map +1 -1
- package/workflow/WorkflowCanvasEditor.js +9 -2
- package/workflow/WorkflowCanvasEditor.js.map +1 -1
- package/workflow/WorkflowNode.d.ts.map +1 -1
- package/workflow/WorkflowNode.js +2 -1
- package/workflow/WorkflowNode.js.map +1 -1
- package/workflow/WorkflowTaskApprovalSummary.d.ts.map +1 -1
- package/workflow/WorkflowTaskApprovalSummary.js +6 -4
- package/workflow/WorkflowTaskApprovalSummary.js.map +1 -1
- package/workflow/WorkflowTaskList.js +2 -2
- package/workflow/WorkflowTaskList.js.map +1 -1
- package/workflow/WorkflowVersionBadge.d.ts.map +1 -1
- package/workflow/WorkflowVersionBadge.js +2 -1
- package/workflow/WorkflowVersionBadge.js.map +1 -1
- package/workflow/WorkflowVersionTimeline.d.ts.map +1 -1
- package/workflow/WorkflowVersionTimeline.js +2 -1
- package/workflow/WorkflowVersionTimeline.js.map +1 -1
- package/workflow/execution-comparison/ExecutionComparisonView.d.ts.map +1 -1
- package/workflow/execution-comparison/ExecutionComparisonView.js +2 -1
- package/workflow/execution-comparison/ExecutionComparisonView.js.map +1 -1
- package/workflow/execution-comparison/TaskComparisonTable.d.ts.map +1 -1
- package/workflow/execution-comparison/TaskComparisonTable.js +2 -1
- package/workflow/execution-comparison/TaskComparisonTable.js.map +1 -1
- package/workflow/execution-history/ExecutionHistoryTable.d.ts.map +1 -1
- package/workflow/execution-history/ExecutionHistoryTable.js +6 -4
- package/workflow/execution-history/ExecutionHistoryTable.js.map +1 -1
- package/workflow/inspector/InspectorHeader.d.ts.map +1 -1
- package/workflow/inspector/InspectorHeader.js +4 -2
- package/workflow/inspector/InspectorHeader.js.map +1 -1
- package/workflow/inspector/NestedTaskList.d.ts.map +1 -1
- package/workflow/inspector/NestedTaskList.js +2 -1
- package/workflow/inspector/NestedTaskList.js.map +1 -1
- package/workflow/inspector/WorkflowSummaryPanel.d.ts.map +1 -1
- package/workflow/inspector/WorkflowSummaryPanel.js +2 -1
- package/workflow/inspector/WorkflowSummaryPanel.js.map +1 -1
- package/workflow/inspector/tabs/BranchesTab.d.ts.map +1 -1
- package/workflow/inspector/tabs/BranchesTab.js +5 -2
- package/workflow/inspector/tabs/BranchesTab.js.map +1 -1
- package/workflow/instance/WorkflowInstanceList.d.ts.map +1 -1
- package/workflow/instance/WorkflowInstanceList.js +2 -1
- package/workflow/instance/WorkflowInstanceList.js.map +1 -1
- package/workflow/node-shell/DiffBadge.d.ts.map +1 -1
- package/workflow/node-shell/DiffBadge.js +3 -2
- package/workflow/node-shell/DiffBadge.js.map +1 -1
- package/workflow/node-shell/ExecutionBadge.d.ts.map +1 -1
- package/workflow/node-shell/ExecutionBadge.js +5 -4
- package/workflow/node-shell/ExecutionBadge.js.map +1 -1
- package/workflow/node-shell/NodeActions.d.ts.map +1 -1
- package/workflow/node-shell/NodeActions.js +12 -11
- package/workflow/node-shell/NodeActions.js.map +1 -1
- package/workflow/task-detail/StructuredDataViewer.d.ts.map +1 -1
- package/workflow/task-detail/StructuredDataViewer.js +5 -1
- package/workflow/task-detail/StructuredDataViewer.js.map +1 -1
- package/workspace/EditorTabs.d.ts.map +1 -1
- package/workspace/EditorTabs.js +38 -37
- package/workspace/EditorTabs.js.map +1 -1
- package/workspace/ExplorerTree.d.ts.map +1 -1
- package/workspace/ExplorerTree.js +2 -1
- package/workspace/ExplorerTree.js.map +1 -1
- package/workspace/FileViewer.d.ts.map +1 -1
- package/workspace/FileViewer.js +2 -1
- package/workspace/FileViewer.js.map +1 -1
- package/workspace/PanelChip.d.ts.map +1 -1
- package/workspace/PanelChip.js +2 -1
- package/workspace/PanelChip.js.map +1 -1
- package/workspace/WorkspaceEditor.d.ts.map +1 -1
- package/workspace/WorkspaceEditor.js +2 -1
- package/workspace/WorkspaceEditor.js.map +1 -1
- package/workspace/WorkspaceSummary.d.ts.map +1 -1
- package/workspace/WorkspaceSummary.js +7 -2
- package/workspace/WorkspaceSummary.js.map +1 -1
- package/workspace/WorkspaceSurface.d.ts.map +1 -1
- package/workspace/WorkspaceSurface.js +12 -11
- package/workspace/WorkspaceSurface.js.map +1 -1
- package/datastore/CollectionRecordsBrowser.d.ts +0 -34
- package/datastore/CollectionRecordsBrowser.d.ts.map +0 -1
- package/datastore/CollectionRecordsBrowser.js +0 -223
- package/datastore/CollectionRecordsBrowser.js.map +0 -1
- package/datastore/CollectionSchemaView.d.ts +0 -29
- package/datastore/CollectionSchemaView.d.ts.map +0 -1
- package/datastore/CollectionSchemaView.js +0 -93
- package/datastore/CollectionSchemaView.js.map +0 -1
- package/datastore/DatastoreDetailView.d.ts +0 -44
- package/datastore/DatastoreDetailView.d.ts.map +0 -1
- package/datastore/DatastoreDetailView.js +0 -76
- package/datastore/DatastoreDetailView.js.map +0 -1
- package/datastore/DatastoreSyncReport.d.ts +0 -19
- package/datastore/DatastoreSyncReport.d.ts.map +0 -1
- package/datastore/DatastoreSyncReport.js +0 -45
- package/datastore/DatastoreSyncReport.js.map +0 -1
- package/datastore/DeleteDatastoreDialog.d.ts +0 -35
- package/datastore/DeleteDatastoreDialog.d.ts.map +0 -1
- package/datastore/DeleteDatastoreDialog.js +0 -90
- package/datastore/DeleteDatastoreDialog.js.map +0 -1
- package/datastore/FieldValueControl.d.ts +0 -55
- package/datastore/FieldValueControl.d.ts.map +0 -1
- package/datastore/FieldValueControl.js +0 -138
- package/datastore/FieldValueControl.js.map +0 -1
- package/datastore/RecordFilterBuilder.d.ts +0 -37
- package/datastore/RecordFilterBuilder.d.ts.map +0 -1
- package/datastore/RecordFilterBuilder.js +0 -122
- package/datastore/RecordFilterBuilder.js.map +0 -1
- package/datastore/RecordFormPanel.d.ts +0 -45
- package/datastore/RecordFormPanel.d.ts.map +0 -1
- package/datastore/RecordFormPanel.js +0 -215
- package/datastore/RecordFormPanel.js.map +0 -1
- package/datastore/index.d.ts +0 -43
- package/datastore/index.d.ts.map +0 -1
- package/datastore/index.js +0 -22
- package/datastore/index.js.map +0 -1
- package/datastore/recordFilter.d.ts +0 -62
- package/datastore/recordFilter.d.ts.map +0 -1
- package/datastore/recordFilter.js +0 -104
- package/datastore/recordFilter.js.map +0 -1
- package/datastore/recordValues.d.ts +0 -85
- package/datastore/recordValues.d.ts.map +0 -1
- package/datastore/recordValues.js +0 -282
- package/datastore/recordValues.js.map +0 -1
- package/datastore/useDatastore.d.ts +0 -39
- package/datastore/useDatastore.d.ts.map +0 -1
- package/datastore/useDatastore.js +0 -44
- package/datastore/useDatastore.js.map +0 -1
- package/datastore/useDatastoreCount.d.ts +0 -50
- package/datastore/useDatastoreCount.d.ts.map +0 -1
- package/datastore/useDatastoreCount.js +0 -27
- package/datastore/useDatastoreCount.js.map +0 -1
- package/datastore/useDatastoreDescription.d.ts +0 -54
- package/datastore/useDatastoreDescription.d.ts.map +0 -1
- package/datastore/useDatastoreDescription.js +0 -50
- package/datastore/useDatastoreDescription.js.map +0 -1
- package/datastore/useDatastoreList.d.ts +0 -57
- package/datastore/useDatastoreList.d.ts.map +0 -1
- package/datastore/useDatastoreList.js +0 -29
- package/datastore/useDatastoreList.js.map +0 -1
- package/datastore/useDatastoreSearch.d.ts +0 -19
- package/datastore/useDatastoreSearch.d.ts.map +0 -1
- package/datastore/useDatastoreSearch.js +0 -22
- package/datastore/useDatastoreSearch.js.map +0 -1
- package/datastore/useDeleteDatastore.d.ts +0 -53
- package/datastore/useDeleteDatastore.d.ts.map +0 -1
- package/datastore/useDeleteDatastore.js +0 -40
- package/datastore/useDeleteDatastore.js.map +0 -1
- package/datastore/useDeleteRecord.d.ts +0 -34
- package/datastore/useDeleteRecord.d.ts.map +0 -1
- package/datastore/useDeleteRecord.js +0 -43
- package/datastore/useDeleteRecord.js.map +0 -1
- package/datastore/useInsertRecord.d.ts +0 -50
- package/datastore/useInsertRecord.d.ts.map +0 -1
- package/datastore/useInsertRecord.js +0 -55
- package/datastore/useInsertRecord.js.map +0 -1
- package/datastore/useRecordCollection.d.ts +0 -104
- package/datastore/useRecordCollection.d.ts.map +0 -1
- package/datastore/useRecordCollection.js +0 -136
- package/datastore/useRecordCollection.js.map +0 -1
- package/datastore/useRecordList.d.ts +0 -66
- package/datastore/useRecordList.d.ts.map +0 -1
- package/datastore/useRecordList.js +0 -58
- package/datastore/useRecordList.js.map +0 -1
- package/datastore/useUpdateRecord.d.ts +0 -52
- package/datastore/useUpdateRecord.d.ts.map +0 -1
- package/datastore/useUpdateRecord.js +0 -55
- package/datastore/useUpdateRecord.js.map +0 -1
- package/src/agent/__tests__/AgentDetailView.datastores.test.tsx +0 -166
- package/src/datastore/CollectionRecordsBrowser.tsx +0 -570
- package/src/datastore/CollectionSchemaView.tsx +0 -247
- package/src/datastore/DatastoreDetailView.tsx +0 -201
- package/src/datastore/DatastoreSyncReport.tsx +0 -105
- package/src/datastore/DeleteDatastoreDialog.tsx +0 -202
- package/src/datastore/FieldValueControl.tsx +0 -289
- package/src/datastore/RecordFilterBuilder.tsx +0 -422
- package/src/datastore/RecordFormPanel.tsx +0 -432
- package/src/datastore/__tests__/CollectionRecordsBrowser.test.tsx +0 -245
- package/src/datastore/__tests__/DeleteDatastoreDialog.test.tsx +0 -133
- package/src/datastore/__tests__/FieldValueControl.test.tsx +0 -160
- package/src/datastore/__tests__/RecordFilterBuilder.test.tsx +0 -155
- package/src/datastore/__tests__/RecordFormPanel.test.tsx +0 -227
- package/src/datastore/__tests__/recordFilter.test.ts +0 -169
- package/src/datastore/__tests__/recordMutations.test.tsx +0 -195
- package/src/datastore/__tests__/recordValues.test.ts +0 -359
- package/src/datastore/__tests__/schemaAndSyncViews.test.tsx +0 -142
- package/src/datastore/__tests__/useDatastoreDescription.test.tsx +0 -143
- package/src/datastore/__tests__/useRecordCollection.test.tsx +0 -250
- package/src/datastore/__tests__/useRecordList.test.tsx +0 -85
- package/src/datastore/index.ts +0 -111
- package/src/datastore/recordFilter.ts +0 -154
- package/src/datastore/recordValues.ts +0 -327
- package/src/datastore/useDatastore.ts +0 -67
- package/src/datastore/useDatastoreCount.ts +0 -69
- package/src/datastore/useDatastoreDescription.ts +0 -90
- package/src/datastore/useDatastoreList.ts +0 -79
- package/src/datastore/useDatastoreSearch.ts +0 -39
- package/src/datastore/useDeleteDatastore.ts +0 -87
- package/src/datastore/useDeleteRecord.ts +0 -77
- package/src/datastore/useInsertRecord.ts +0 -92
- package/src/datastore/useRecordCollection.ts +0 -256
- package/src/datastore/useRecordList.ts +0 -131
- 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
|
-
<
|
|
157
|
-
|
|
158
|
-
|
|
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
|
|