@stigmer/react 0.4.8 → 0.5.1
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/action-menu/ActionMenu.d.ts +64 -0
- package/action-menu/ActionMenu.d.ts.map +1 -0
- package/action-menu/ActionMenu.js +78 -0
- package/action-menu/ActionMenu.js.map +1 -0
- package/action-menu/index.d.ts +3 -0
- package/action-menu/index.d.ts.map +1 -0
- package/action-menu/index.js +2 -0
- package/action-menu/index.js.map +1 -0
- package/action-menu/types.d.ts +65 -0
- package/action-menu/types.d.ts.map +1 -0
- package/action-menu/types.js +2 -0
- package/action-menu/types.js.map +1 -0
- package/agent/AgentCreationWizard.d.ts +55 -0
- package/agent/AgentCreationWizard.d.ts.map +1 -0
- package/agent/AgentCreationWizard.js +115 -0
- package/agent/AgentCreationWizard.js.map +1 -0
- package/agent/AgentDetailView.d.ts +77 -9
- package/agent/AgentDetailView.d.ts.map +1 -1
- package/agent/AgentDetailView.js +265 -87
- package/agent/AgentDetailView.js.map +1 -1
- package/agent/index.d.ts +8 -0
- package/agent/index.d.ts.map +1 -1
- package/agent/index.js +4 -0
- package/agent/index.js.map +1 -1
- package/agent/internal/agentToInput.d.ts +12 -0
- package/agent/internal/agentToInput.d.ts.map +1 -0
- package/agent/internal/agentToInput.js +72 -0
- package/agent/internal/agentToInput.js.map +1 -0
- package/agent/steps/CapabilitiesStep.d.ts +16 -0
- package/agent/steps/CapabilitiesStep.d.ts.map +1 -0
- package/agent/steps/CapabilitiesStep.js +80 -0
- package/agent/steps/CapabilitiesStep.js.map +1 -0
- package/agent/steps/IdentityStep.d.ts +18 -0
- package/agent/steps/IdentityStep.d.ts.map +1 -0
- package/agent/steps/IdentityStep.js +43 -0
- package/agent/steps/IdentityStep.js.map +1 -0
- package/agent/steps/ReviewStep.d.ts +23 -0
- package/agent/steps/ReviewStep.d.ts.map +1 -0
- package/agent/steps/ReviewStep.js +73 -0
- package/agent/steps/ReviewStep.js.map +1 -0
- package/agent/steps/types.d.ts +35 -0
- package/agent/steps/types.d.ts.map +1 -0
- package/agent/steps/types.js +16 -0
- package/agent/steps/types.js.map +1 -0
- package/agent/useCreateAgent.d.ts +45 -0
- package/agent/useCreateAgent.d.ts.map +1 -0
- package/agent/useCreateAgent.js +50 -0
- package/agent/useCreateAgent.js.map +1 -0
- package/agent/useUpdateAgent.d.ts +24 -0
- package/agent/useUpdateAgent.d.ts.map +1 -0
- package/agent/useUpdateAgent.js +35 -0
- package/agent/useUpdateAgent.js.map +1 -0
- package/composer/ContextChip.d.ts +7 -2
- package/composer/ContextChip.d.ts.map +1 -1
- package/composer/ContextChip.js +2 -1
- package/composer/ContextChip.js.map +1 -1
- package/composer/SessionComposer.d.ts +11 -0
- package/composer/SessionComposer.d.ts.map +1 -1
- package/composer/SessionComposer.js +33 -4
- package/composer/SessionComposer.js.map +1 -1
- package/dependency-graph/DependencyGraph.d.ts +37 -0
- package/dependency-graph/DependencyGraph.d.ts.map +1 -0
- package/dependency-graph/DependencyGraph.js +88 -0
- package/dependency-graph/DependencyGraph.js.map +1 -0
- package/dependency-graph/DependencyTreeNode.d.ts +23 -0
- package/dependency-graph/DependencyTreeNode.d.ts.map +1 -0
- package/dependency-graph/DependencyTreeNode.js +99 -0
- package/dependency-graph/DependencyTreeNode.js.map +1 -0
- package/dependency-graph/index.d.ts +4 -0
- package/dependency-graph/index.d.ts.map +1 -0
- package/dependency-graph/index.js +5 -0
- package/dependency-graph/index.js.map +1 -0
- package/dependency-graph/types.d.ts +130 -0
- package/dependency-graph/types.d.ts.map +1 -0
- package/dependency-graph/types.js +2 -0
- package/dependency-graph/types.js.map +1 -0
- package/dependency-graph/useDependencyGraph.d.ts +27 -0
- package/dependency-graph/useDependencyGraph.d.ts.map +1 -0
- package/dependency-graph/useDependencyGraph.js +129 -0
- package/dependency-graph/useDependencyGraph.js.map +1 -0
- package/empty-state/EmptyState.d.ts +29 -0
- package/empty-state/EmptyState.d.ts.map +1 -0
- package/empty-state/EmptyState.js +45 -0
- package/empty-state/EmptyState.js.map +1 -0
- package/empty-state/index.d.ts +4 -0
- package/empty-state/index.d.ts.map +1 -0
- package/empty-state/index.js +3 -0
- package/empty-state/index.js.map +1 -0
- package/empty-state/types.d.ts +73 -0
- package/empty-state/types.d.ts.map +1 -0
- package/empty-state/types.js +2 -0
- package/empty-state/types.js.map +1 -0
- package/empty-state/useEmptyState.d.ts +18 -0
- package/empty-state/useEmptyState.d.ts.map +1 -0
- package/empty-state/useEmptyState.js +72 -0
- package/empty-state/useEmptyState.js.map +1 -0
- package/environment/usePersonalEnvironment.d.ts.map +1 -1
- package/environment/usePersonalEnvironment.js +1 -0
- package/environment/usePersonalEnvironment.js.map +1 -1
- package/feedback/StigmerToaster.d.ts +18 -0
- package/feedback/StigmerToaster.d.ts.map +1 -0
- package/feedback/StigmerToaster.js +31 -0
- package/feedback/StigmerToaster.js.map +1 -0
- package/feedback/index.d.ts +4 -0
- package/feedback/index.d.ts.map +1 -0
- package/feedback/index.js +3 -0
- package/feedback/index.js.map +1 -0
- package/feedback/toast.d.ts +14 -0
- package/feedback/toast.d.ts.map +1 -0
- package/feedback/toast.js +14 -0
- package/feedback/toast.js.map +1 -0
- package/feedback/types.d.ts +4 -0
- package/feedback/types.d.ts.map +1 -0
- package/feedback/types.js +2 -0
- package/feedback/types.js.map +1 -0
- package/index.d.ts +32 -12
- package/index.d.ts.map +1 -1
- package/index.js +30 -10
- package/index.js.map +1 -1
- package/inline-edit/InlineEditImage.d.ts +20 -0
- package/inline-edit/InlineEditImage.d.ts.map +1 -0
- package/inline-edit/InlineEditImage.js +85 -0
- package/inline-edit/InlineEditImage.js.map +1 -0
- package/inline-edit/InlineEditKeyValue.d.ts +33 -0
- package/inline-edit/InlineEditKeyValue.d.ts.map +1 -0
- package/inline-edit/InlineEditKeyValue.js +67 -0
- package/inline-edit/InlineEditKeyValue.js.map +1 -0
- package/inline-edit/InlineEditResourceList.d.ts +34 -0
- package/inline-edit/InlineEditResourceList.d.ts.map +1 -0
- package/inline-edit/InlineEditResourceList.js +99 -0
- package/inline-edit/InlineEditResourceList.js.map +1 -0
- package/inline-edit/InlineEditSelect.d.ts +18 -0
- package/inline-edit/InlineEditSelect.d.ts.map +1 -0
- package/inline-edit/InlineEditSelect.js +54 -0
- package/inline-edit/InlineEditSelect.js.map +1 -0
- package/inline-edit/InlineEditText.d.ts +23 -0
- package/inline-edit/InlineEditText.d.ts.map +1 -0
- package/inline-edit/InlineEditText.js +79 -0
- package/inline-edit/InlineEditText.js.map +1 -0
- package/inline-edit/InlineEditTextarea.d.ts +22 -0
- package/inline-edit/InlineEditTextarea.d.ts.map +1 -0
- package/inline-edit/InlineEditTextarea.js +83 -0
- package/inline-edit/InlineEditTextarea.js.map +1 -0
- package/inline-edit/index.d.ts +16 -0
- package/inline-edit/index.d.ts.map +1 -0
- package/inline-edit/index.js +8 -0
- package/inline-edit/index.js.map +1 -0
- package/inline-edit/types.d.ts +42 -0
- package/inline-edit/types.d.ts.map +1 -0
- package/inline-edit/types.js +2 -0
- package/inline-edit/types.js.map +1 -0
- package/inline-edit/useInlineFieldSave.d.ts +23 -0
- package/inline-edit/useInlineFieldSave.d.ts.map +1 -0
- package/inline-edit/useInlineFieldSave.js +44 -0
- package/inline-edit/useInlineFieldSave.js.map +1 -0
- package/internal/Tabs.d.ts +4 -38
- package/internal/Tabs.d.ts.map +1 -1
- package/internal/Tabs.js +3 -62
- package/internal/Tabs.js.map +1 -1
- package/internal/useFetch.js +2 -2
- package/internal/useFetch.js.map +1 -1
- package/library/ImportResourceDialog.d.ts +43 -0
- package/library/ImportResourceDialog.d.ts.map +1 -0
- package/library/ImportResourceDialog.js +90 -0
- package/library/ImportResourceDialog.js.map +1 -0
- package/library/index.d.ts +7 -4
- package/library/index.d.ts.map +1 -1
- package/library/index.js +4 -2
- package/library/index.js.map +1 -1
- package/library/serialize-resource-yaml.d.ts +53 -0
- package/library/serialize-resource-yaml.d.ts.map +1 -1
- package/library/serialize-resource-yaml.js +275 -0
- package/library/serialize-resource-yaml.js.map +1 -1
- package/library/useExportResource.d.ts +56 -0
- package/library/useExportResource.d.ts.map +1 -0
- package/library/useExportResource.js +137 -0
- package/library/useExportResource.js.map +1 -0
- package/library/useImportResource.d.ts +84 -0
- package/library/useImportResource.d.ts.map +1 -0
- package/library/useImportResource.js +188 -0
- package/library/useImportResource.js.map +1 -0
- package/mcp-server/McpServerCreationWizard.d.ts +55 -0
- package/mcp-server/McpServerCreationWizard.d.ts.map +1 -0
- package/mcp-server/McpServerCreationWizard.js +121 -0
- package/mcp-server/McpServerCreationWizard.js.map +1 -0
- package/mcp-server/McpServerDetailView.d.ts +21 -1
- package/mcp-server/McpServerDetailView.d.ts.map +1 -1
- package/mcp-server/McpServerDetailView.js +235 -43
- package/mcp-server/McpServerDetailView.js.map +1 -1
- package/mcp-server/index.d.ts +8 -0
- package/mcp-server/index.d.ts.map +1 -1
- package/mcp-server/index.js +4 -0
- package/mcp-server/index.js.map +1 -1
- package/mcp-server/internal/mcpServerToInput.d.ts +12 -0
- package/mcp-server/internal/mcpServerToInput.d.ts.map +1 -0
- package/mcp-server/internal/mcpServerToInput.js +81 -0
- package/mcp-server/internal/mcpServerToInput.js.map +1 -0
- package/mcp-server/steps/EnvironmentAuthStep.d.ts +15 -0
- package/mcp-server/steps/EnvironmentAuthStep.d.ts.map +1 -0
- package/mcp-server/steps/EnvironmentAuthStep.js +55 -0
- package/mcp-server/steps/EnvironmentAuthStep.js.map +1 -0
- package/mcp-server/steps/IdentityTransportStep.d.ts +19 -0
- package/mcp-server/steps/IdentityTransportStep.d.ts.map +1 -0
- package/mcp-server/steps/IdentityTransportStep.js +73 -0
- package/mcp-server/steps/IdentityTransportStep.js.map +1 -0
- package/mcp-server/steps/ReviewStep.d.ts +23 -0
- package/mcp-server/steps/ReviewStep.d.ts.map +1 -0
- package/mcp-server/steps/ReviewStep.js +137 -0
- package/mcp-server/steps/ReviewStep.js.map +1 -0
- package/mcp-server/steps/types.d.ts +56 -0
- package/mcp-server/steps/types.d.ts.map +1 -0
- package/mcp-server/steps/types.js +27 -0
- package/mcp-server/steps/types.js.map +1 -0
- package/mcp-server/useCreateMcpServer.d.ts +45 -0
- package/mcp-server/useCreateMcpServer.d.ts.map +1 -0
- package/mcp-server/useCreateMcpServer.js +50 -0
- package/mcp-server/useCreateMcpServer.js.map +1 -0
- package/mcp-server/useUpdateMcpServer.d.ts +24 -0
- package/mcp-server/useUpdateMcpServer.d.ts.map +1 -0
- package/mcp-server/useUpdateMcpServer.js +35 -0
- package/mcp-server/useUpdateMcpServer.js.map +1 -0
- package/models/ModelRegistryContext.d.ts +2 -0
- package/models/ModelRegistryContext.d.ts.map +1 -1
- package/models/ModelRegistryContext.js +1 -0
- package/models/ModelRegistryContext.js.map +1 -1
- package/models/ModelSelector.d.ts.map +1 -1
- package/models/ModelSelector.js +2 -2
- package/models/ModelSelector.js.map +1 -1
- package/models/__tests__/useModelRegistry.test.js +4 -3
- package/models/__tests__/useModelRegistry.test.js.map +1 -1
- package/models/useModelRegistry.d.ts +2 -0
- package/models/useModelRegistry.d.ts.map +1 -1
- package/models/useModelRegistry.js +3 -2
- package/models/useModelRegistry.js.map +1 -1
- package/package.json +8 -4
- package/provider.d.ts.map +1 -1
- package/provider.js +69 -22
- package/provider.js.map +1 -1
- package/resource-creation/CreationPicker.d.ts +60 -0
- package/resource-creation/CreationPicker.d.ts.map +1 -0
- package/resource-creation/CreationPicker.js +74 -0
- package/resource-creation/CreationPicker.js.map +1 -0
- package/resource-creation/StepIndicator.d.ts +28 -0
- package/resource-creation/StepIndicator.d.ts.map +1 -0
- package/resource-creation/StepIndicator.js +40 -0
- package/resource-creation/StepIndicator.js.map +1 -0
- package/resource-creation/TemplateCard.d.ts +24 -0
- package/resource-creation/TemplateCard.d.ts.map +1 -0
- package/resource-creation/TemplateCard.js +68 -0
- package/resource-creation/TemplateCard.js.map +1 -0
- package/resource-creation/TemplateGallery.d.ts +43 -0
- package/resource-creation/TemplateGallery.d.ts.map +1 -0
- package/resource-creation/TemplateGallery.js +78 -0
- package/resource-creation/TemplateGallery.js.map +1 -0
- package/resource-creation/WizardNav.d.ts +31 -0
- package/resource-creation/WizardNav.d.ts.map +1 -0
- package/resource-creation/WizardNav.js +29 -0
- package/resource-creation/WizardNav.js.map +1 -0
- package/resource-creation/WizardShell.d.ts +41 -0
- package/resource-creation/WizardShell.d.ts.map +1 -0
- package/resource-creation/WizardShell.js +55 -0
- package/resource-creation/WizardShell.js.map +1 -0
- package/resource-creation/index.d.ts +21 -0
- package/resource-creation/index.d.ts.map +1 -0
- package/resource-creation/index.js +14 -0
- package/resource-creation/index.js.map +1 -0
- package/resource-creation/templates/agent-templates.d.ts +15 -0
- package/resource-creation/templates/agent-templates.d.ts.map +1 -0
- package/resource-creation/templates/agent-templates.js +148 -0
- package/resource-creation/templates/agent-templates.js.map +1 -0
- package/resource-creation/templates/index.d.ts +5 -0
- package/resource-creation/templates/index.d.ts.map +1 -0
- package/resource-creation/templates/index.js +5 -0
- package/resource-creation/templates/index.js.map +1 -0
- package/resource-creation/templates/mcp-server-templates.d.ts +15 -0
- package/resource-creation/templates/mcp-server-templates.d.ts.map +1 -0
- package/resource-creation/templates/mcp-server-templates.js +92 -0
- package/resource-creation/templates/mcp-server-templates.js.map +1 -0
- package/resource-creation/templates/types.d.ts +48 -0
- package/resource-creation/templates/types.d.ts.map +1 -0
- package/resource-creation/templates/types.js +16 -0
- package/resource-creation/templates/types.js.map +1 -0
- package/resource-creation/types.d.ts +88 -0
- package/resource-creation/types.d.ts.map +1 -0
- package/resource-creation/types.js +2 -0
- package/resource-creation/types.js.map +1 -0
- package/resource-creation/useTemplateFilter.d.ts +43 -0
- package/resource-creation/useTemplateFilter.d.ts.map +1 -0
- package/resource-creation/useTemplateFilter.js +73 -0
- package/resource-creation/useTemplateFilter.js.map +1 -0
- package/resource-creation/useWizardState.d.ts +67 -0
- package/resource-creation/useWizardState.d.ts.map +1 -0
- package/resource-creation/useWizardState.js +143 -0
- package/resource-creation/useWizardState.js.map +1 -0
- package/resource-detail/ConfirmDialog.d.ts +44 -0
- package/resource-detail/ConfirmDialog.d.ts.map +1 -0
- package/resource-detail/ConfirmDialog.js +62 -0
- package/resource-detail/ConfirmDialog.js.map +1 -0
- package/resource-detail/ResourceActionBar.d.ts +42 -0
- package/resource-detail/ResourceActionBar.d.ts.map +1 -0
- package/resource-detail/ResourceActionBar.js +64 -0
- package/resource-detail/ResourceActionBar.js.map +1 -0
- package/resource-detail/ResourceDetailShell.d.ts +36 -0
- package/resource-detail/ResourceDetailShell.d.ts.map +1 -0
- package/resource-detail/ResourceDetailShell.js +65 -0
- package/resource-detail/ResourceDetailShell.js.map +1 -0
- package/resource-detail/Section.d.ts +18 -0
- package/resource-detail/Section.d.ts.map +1 -0
- package/resource-detail/Section.js +18 -0
- package/resource-detail/Section.js.map +1 -0
- package/resource-detail/index.d.ts +15 -0
- package/resource-detail/index.d.ts.map +1 -0
- package/resource-detail/index.js +10 -0
- package/resource-detail/index.js.map +1 -0
- package/resource-detail/types.d.ts +146 -0
- package/resource-detail/types.d.ts.map +1 -0
- package/resource-detail/types.js +2 -0
- package/resource-detail/types.js.map +1 -0
- package/resource-detail/useConfirmAction.d.ts +41 -0
- package/resource-detail/useConfirmAction.d.ts.map +1 -0
- package/resource-detail/useConfirmAction.js +30 -0
- package/resource-detail/useConfirmAction.js.map +1 -0
- package/resource-detail/useCopyResource.d.ts +28 -0
- package/resource-detail/useCopyResource.d.ts.map +1 -0
- package/resource-detail/useCopyResource.js +46 -0
- package/resource-detail/useCopyResource.js.map +1 -0
- package/resource-detail/useDeleteResource.d.ts +40 -0
- package/resource-detail/useDeleteResource.d.ts.map +1 -0
- package/resource-detail/useDeleteResource.js +83 -0
- package/resource-detail/useDeleteResource.js.map +1 -0
- package/resource-detail/useDetailTabs.d.ts +46 -0
- package/resource-detail/useDetailTabs.d.ts.map +1 -0
- package/resource-detail/useDetailTabs.js +47 -0
- package/resource-detail/useDetailTabs.js.map +1 -0
- package/resource-workbench/components/BulkActionBar.d.ts +36 -0
- package/resource-workbench/components/BulkActionBar.d.ts.map +1 -0
- package/resource-workbench/components/BulkActionBar.js +35 -0
- package/resource-workbench/components/BulkActionBar.js.map +1 -0
- package/resource-workbench/components/ColumnHeader.d.ts +23 -0
- package/resource-workbench/components/ColumnHeader.d.ts.map +1 -0
- package/resource-workbench/components/ColumnHeader.js +25 -0
- package/resource-workbench/components/ColumnHeader.js.map +1 -0
- package/resource-workbench/components/FilterBar.d.ts +33 -0
- package/resource-workbench/components/FilterBar.d.ts.map +1 -0
- package/resource-workbench/components/FilterBar.js +72 -0
- package/resource-workbench/components/FilterBar.js.map +1 -0
- package/resource-workbench/components/ResourceAvatar.d.ts +29 -0
- package/resource-workbench/components/ResourceAvatar.d.ts.map +1 -0
- package/resource-workbench/components/ResourceAvatar.js +51 -0
- package/resource-workbench/components/ResourceAvatar.js.map +1 -0
- package/resource-workbench/components/ResourceCards.d.ts +39 -0
- package/resource-workbench/components/ResourceCards.d.ts.map +1 -0
- package/resource-workbench/components/ResourceCards.js +41 -0
- package/resource-workbench/components/ResourceCards.js.map +1 -0
- package/resource-workbench/components/ResourceInspector.d.ts +26 -0
- package/resource-workbench/components/ResourceInspector.d.ts.map +1 -0
- package/resource-workbench/components/ResourceInspector.js +22 -0
- package/resource-workbench/components/ResourceInspector.js.map +1 -0
- package/resource-workbench/components/ResourceList.d.ts +39 -0
- package/resource-workbench/components/ResourceList.d.ts.map +1 -0
- package/resource-workbench/components/ResourceList.js +41 -0
- package/resource-workbench/components/ResourceList.js.map +1 -0
- package/resource-workbench/components/ResourceTable.d.ts +47 -0
- package/resource-workbench/components/ResourceTable.d.ts.map +1 -0
- package/resource-workbench/components/ResourceTable.js +78 -0
- package/resource-workbench/components/ResourceTable.js.map +1 -0
- package/resource-workbench/components/ResourceWorkbench.d.ts +131 -0
- package/resource-workbench/components/ResourceWorkbench.d.ts.map +1 -0
- package/resource-workbench/components/ResourceWorkbench.js +170 -0
- package/resource-workbench/components/ResourceWorkbench.js.map +1 -0
- package/resource-workbench/components/SelectionCheckbox.d.ts +24 -0
- package/resource-workbench/components/SelectionCheckbox.d.ts.map +1 -0
- package/resource-workbench/components/SelectionCheckbox.js +16 -0
- package/resource-workbench/components/SelectionCheckbox.js.map +1 -0
- package/resource-workbench/components/StatusBadge.d.ts +31 -0
- package/resource-workbench/components/StatusBadge.d.ts.map +1 -0
- package/resource-workbench/components/StatusBadge.js +75 -0
- package/resource-workbench/components/StatusBadge.js.map +1 -0
- package/resource-workbench/components/ViewSwitcher.d.ts +21 -0
- package/resource-workbench/components/ViewSwitcher.d.ts.map +1 -0
- package/resource-workbench/components/ViewSwitcher.js +37 -0
- package/resource-workbench/components/ViewSwitcher.js.map +1 -0
- package/resource-workbench/hooks/useResourceCollection.d.ts +93 -0
- package/resource-workbench/hooks/useResourceCollection.d.ts.map +1 -0
- package/resource-workbench/hooks/useResourceCollection.js +133 -0
- package/resource-workbench/hooks/useResourceCollection.js.map +1 -0
- package/resource-workbench/hooks/useResourceFilters.d.ts +73 -0
- package/resource-workbench/hooks/useResourceFilters.d.ts.map +1 -0
- package/resource-workbench/hooks/useResourceFilters.js +105 -0
- package/resource-workbench/hooks/useResourceFilters.js.map +1 -0
- package/resource-workbench/hooks/useResourceSelection.d.ts +44 -0
- package/resource-workbench/hooks/useResourceSelection.d.ts.map +1 -0
- package/resource-workbench/hooks/useResourceSelection.js +123 -0
- package/resource-workbench/hooks/useResourceSelection.js.map +1 -0
- package/resource-workbench/hooks/useViewPreference.d.ts +32 -0
- package/resource-workbench/hooks/useViewPreference.d.ts.map +1 -0
- package/resource-workbench/hooks/useViewPreference.js +60 -0
- package/resource-workbench/hooks/useViewPreference.js.map +1 -0
- package/resource-workbench/index.d.ts +34 -0
- package/resource-workbench/index.d.ts.map +1 -0
- package/resource-workbench/index.js +19 -0
- package/resource-workbench/index.js.map +1 -0
- package/resource-workbench/types.d.ts +165 -0
- package/resource-workbench/types.d.ts.map +1 -0
- package/resource-workbench/types.js +2 -0
- package/resource-workbench/types.js.map +1 -0
- package/runner/RunnerDetailView.d.ts +44 -0
- package/runner/RunnerDetailView.d.ts.map +1 -0
- package/runner/RunnerDetailView.js +154 -0
- package/runner/RunnerDetailView.js.map +1 -0
- package/runner/RunnerListPanel.d.ts +26 -1
- package/runner/RunnerListPanel.d.ts.map +1 -1
- package/runner/RunnerListPanel.js +68 -46
- package/runner/RunnerListPanel.js.map +1 -1
- package/runner/index.d.ts +7 -1
- package/runner/index.d.ts.map +1 -1
- package/runner/index.js +3 -0
- package/runner/index.js.map +1 -1
- package/runner/shared.d.ts +31 -0
- package/runner/shared.d.ts.map +1 -0
- package/runner/shared.js +55 -0
- package/runner/shared.js.map +1 -0
- package/runner/useRunner.d.ts +37 -0
- package/runner/useRunner.d.ts.map +1 -0
- package/runner/useRunner.js +24 -0
- package/runner/useRunner.js.map +1 -0
- package/session/__tests__/group-sessions.test.js +3 -3
- package/session/__tests__/group-sessions.test.js.map +1 -1
- package/session/__tests__/session-spec-converters.test.d.ts +2 -0
- package/session/__tests__/session-spec-converters.test.d.ts.map +1 -0
- package/session/__tests__/session-spec-converters.test.js +162 -0
- package/session/__tests__/session-spec-converters.test.js.map +1 -0
- package/session/__tests__/useNewSessionFlow.test.js +2 -2
- package/session/__tests__/useNewSessionFlow.test.js.map +1 -1
- package/session/__tests__/usePersistedModel.test.js +1 -1
- package/session/__tests__/usePersistedModel.test.js.map +1 -1
- package/session/group-sessions.d.ts +17 -0
- package/session/group-sessions.d.ts.map +1 -1
- package/session/group-sessions.js +46 -0
- package/session/group-sessions.js.map +1 -1
- package/session/index.d.ts +4 -2
- package/session/index.d.ts.map +1 -1
- package/session/index.js +2 -1
- package/session/index.js.map +1 -1
- package/session/session-spec-converters.d.ts +24 -0
- package/session/session-spec-converters.d.ts.map +1 -0
- package/session/session-spec-converters.js +72 -0
- package/session/session-spec-converters.js.map +1 -0
- package/session/useSessionConversation.d.ts.map +1 -1
- package/session/useSessionConversation.js +1 -56
- package/session/useSessionConversation.js.map +1 -1
- package/session/useSessionPageFlow.d.ts +5 -0
- package/session/useSessionPageFlow.d.ts.map +1 -1
- package/session/useSessionPageFlow.js +20 -6
- package/session/useSessionPageFlow.js.map +1 -1
- package/session/useSessionSearch.d.ts +57 -0
- package/session/useSessionSearch.d.ts.map +1 -0
- package/session/useSessionSearch.js +94 -0
- package/session/useSessionSearch.js.map +1 -0
- package/skill/SkillDetailView.d.ts +70 -7
- package/skill/SkillDetailView.d.ts.map +1 -1
- package/skill/SkillDetailView.js +107 -39
- package/skill/SkillDetailView.js.map +1 -1
- package/skill/SkillDiffDialog.d.ts +42 -0
- package/skill/SkillDiffDialog.d.ts.map +1 -0
- package/skill/SkillDiffDialog.js +72 -0
- package/skill/SkillDiffDialog.js.map +1 -0
- package/skill/SkillFileBrowser.d.ts +31 -0
- package/skill/SkillFileBrowser.d.ts.map +1 -0
- package/skill/SkillFileBrowser.js +105 -0
- package/skill/SkillFileBrowser.js.map +1 -0
- package/skill/SkillUploader.d.ts +39 -0
- package/skill/SkillUploader.d.ts.map +1 -0
- package/skill/SkillUploader.js +141 -0
- package/skill/SkillUploader.js.map +1 -0
- package/skill/index.d.ts +18 -0
- package/skill/index.d.ts.map +1 -1
- package/skill/index.js +9 -0
- package/skill/index.js.map +1 -1
- package/skill/internal/computeArtifactHash.d.ts +9 -0
- package/skill/internal/computeArtifactHash.d.ts.map +1 -0
- package/skill/internal/computeArtifactHash.js +14 -0
- package/skill/internal/computeArtifactHash.js.map +1 -0
- package/skill/internal/fetchAndUnpackArtifact.d.ts +16 -0
- package/skill/internal/fetchAndUnpackArtifact.d.ts.map +1 -0
- package/skill/internal/fetchAndUnpackArtifact.js +34 -0
- package/skill/internal/fetchAndUnpackArtifact.js.map +1 -0
- package/skill/usePushSkill.d.ts +53 -0
- package/skill/usePushSkill.d.ts.map +1 -0
- package/skill/usePushSkill.js +57 -0
- package/skill/usePushSkill.js.map +1 -0
- package/skill/useSkillArtifact.d.ts +37 -0
- package/skill/useSkillArtifact.d.ts.map +1 -0
- package/skill/useSkillArtifact.js +76 -0
- package/skill/useSkillArtifact.js.map +1 -0
- package/skill/useSkillDiff.d.ts +31 -0
- package/skill/useSkillDiff.d.ts.map +1 -0
- package/skill/useSkillDiff.js +97 -0
- package/skill/useSkillDiff.js.map +1 -0
- package/skill/useSkillDuplicateCheck.d.ts +34 -0
- package/skill/useSkillDuplicateCheck.d.ts.map +1 -0
- package/skill/useSkillDuplicateCheck.js +58 -0
- package/skill/useSkillDuplicateCheck.js.map +1 -0
- package/skill/useSkillUpload.d.ts +69 -0
- package/skill/useSkillUpload.d.ts.map +1 -0
- package/skill/useSkillUpload.js +157 -0
- package/skill/useSkillUpload.js.map +1 -0
- package/skill/useSkillVersions.d.ts +46 -0
- package/skill/useSkillVersions.d.ts.map +1 -0
- package/skill/useSkillVersions.js +104 -0
- package/skill/useSkillVersions.js.map +1 -0
- package/src/action-menu/ActionMenu.tsx +151 -0
- package/src/action-menu/index.ts +9 -0
- package/src/action-menu/types.ts +70 -0
- package/src/agent/AgentCreationWizard.tsx +201 -0
- package/src/agent/AgentDetailView.tsx +817 -321
- package/src/agent/index.ts +16 -0
- package/src/agent/internal/agentToInput.ts +95 -0
- package/src/agent/steps/CapabilitiesStep.tsx +363 -0
- package/src/agent/steps/IdentityStep.tsx +259 -0
- package/src/agent/steps/ReviewStep.tsx +211 -0
- package/src/agent/steps/types.ts +53 -0
- package/src/agent/useCreateAgent.ts +76 -0
- package/src/agent/useUpdateAgent.ts +55 -0
- package/src/composer/ContextChip.tsx +20 -11
- package/src/composer/SessionComposer.tsx +52 -3
- package/src/dependency-graph/DependencyGraph.tsx +153 -0
- package/src/dependency-graph/DependencyTreeNode.tsx +282 -0
- package/src/dependency-graph/index.ts +15 -0
- package/src/dependency-graph/types.ts +131 -0
- package/src/dependency-graph/useDependencyGraph.ts +158 -0
- package/src/empty-state/EmptyState.tsx +90 -0
- package/src/empty-state/index.ts +9 -0
- package/src/empty-state/types.ts +81 -0
- package/src/empty-state/useEmptyState.ts +85 -0
- package/src/environment/usePersonalEnvironment.ts +1 -0
- package/src/feedback/StigmerToaster.tsx +45 -0
- package/src/feedback/index.ts +3 -0
- package/src/feedback/toast.ts +13 -0
- package/src/feedback/types.ts +7 -0
- package/src/index.ts +275 -8
- package/src/inline-edit/InlineEditImage.tsx +208 -0
- package/src/inline-edit/InlineEditKeyValue.tsx +301 -0
- package/src/inline-edit/InlineEditResourceList.tsx +325 -0
- package/src/inline-edit/InlineEditSelect.tsx +150 -0
- package/src/inline-edit/InlineEditText.tsx +211 -0
- package/src/inline-edit/InlineEditTextarea.tsx +209 -0
- package/src/inline-edit/index.ts +28 -0
- package/src/inline-edit/types.ts +47 -0
- package/src/inline-edit/useInlineFieldSave.ts +62 -0
- package/src/internal/Tabs.tsx +4 -164
- package/src/internal/useFetch.ts +2 -2
- package/src/library/ImportResourceDialog.tsx +227 -0
- package/src/library/index.ts +18 -8
- package/src/library/serialize-resource-yaml.ts +356 -0
- package/src/library/useExportResource.ts +183 -0
- package/src/library/useImportResource.ts +253 -0
- package/src/mcp-server/McpServerCreationWizard.tsx +206 -0
- package/src/mcp-server/McpServerDetailView.tsx +816 -155
- package/src/mcp-server/index.ts +16 -0
- package/src/mcp-server/internal/mcpServerToInput.ts +95 -0
- package/src/mcp-server/steps/EnvironmentAuthStep.tsx +462 -0
- package/src/mcp-server/steps/IdentityTransportStep.tsx +531 -0
- package/src/mcp-server/steps/ReviewStep.tsx +297 -0
- package/src/mcp-server/steps/types.ts +85 -0
- package/src/mcp-server/useCreateMcpServer.ts +76 -0
- package/src/mcp-server/useUpdateMcpServer.ts +55 -0
- package/src/models/ModelRegistryContext.ts +3 -0
- package/src/models/ModelSelector.tsx +25 -2
- package/src/models/__tests__/useModelRegistry.test.tsx +5 -3
- package/src/models/useModelRegistry.ts +5 -2
- package/src/provider.tsx +69 -18
- package/src/resource-creation/CreationPicker.tsx +292 -0
- package/src/resource-creation/StepIndicator.tsx +156 -0
- package/src/resource-creation/TemplateCard.tsx +143 -0
- package/src/resource-creation/TemplateGallery.tsx +222 -0
- package/src/resource-creation/WizardNav.tsx +163 -0
- package/src/resource-creation/WizardShell.tsx +124 -0
- package/src/resource-creation/index.ts +45 -0
- package/src/resource-creation/templates/agent-templates.ts +160 -0
- package/src/resource-creation/templates/index.ts +7 -0
- package/src/resource-creation/templates/mcp-server-templates.ts +106 -0
- package/src/resource-creation/templates/types.ts +64 -0
- package/src/resource-creation/types.ts +105 -0
- package/src/resource-creation/useTemplateFilter.ts +117 -0
- package/src/resource-creation/useWizardState.ts +223 -0
- package/src/resource-detail/ConfirmDialog.tsx +127 -0
- package/src/resource-detail/ResourceActionBar.tsx +157 -0
- package/src/resource-detail/ResourceDetailShell.tsx +184 -0
- package/src/resource-detail/Section.tsx +78 -0
- package/src/resource-detail/index.ts +34 -0
- package/src/resource-detail/types.ts +177 -0
- package/src/resource-detail/useConfirmAction.ts +70 -0
- package/src/resource-detail/useCopyResource.ts +74 -0
- package/src/resource-detail/useDeleteResource.ts +110 -0
- package/src/resource-detail/useDetailTabs.ts +93 -0
- package/src/resource-workbench/components/BulkActionBar.tsx +122 -0
- package/src/resource-workbench/components/ColumnHeader.tsx +105 -0
- package/src/resource-workbench/components/FilterBar.tsx +173 -0
- package/src/resource-workbench/components/ResourceAvatar.tsx +109 -0
- package/src/resource-workbench/components/ResourceCards.tsx +126 -0
- package/src/resource-workbench/components/ResourceInspector.tsx +88 -0
- package/src/resource-workbench/components/ResourceList.tsx +121 -0
- package/src/resource-workbench/components/ResourceTable.tsx +222 -0
- package/src/resource-workbench/components/ResourceWorkbench.tsx +695 -0
- package/src/resource-workbench/components/SelectionCheckbox.tsx +52 -0
- package/src/resource-workbench/components/StatusBadge.tsx +119 -0
- package/src/resource-workbench/components/ViewSwitcher.tsx +135 -0
- package/src/resource-workbench/hooks/useResourceCollection.ts +261 -0
- package/src/resource-workbench/hooks/useResourceFilters.ts +216 -0
- package/src/resource-workbench/hooks/useResourceSelection.ts +178 -0
- package/src/resource-workbench/hooks/useViewPreference.ts +75 -0
- package/src/resource-workbench/index.ts +73 -0
- package/src/resource-workbench/types.ts +220 -0
- package/src/runner/RunnerDetailView.tsx +410 -0
- package/src/runner/RunnerListPanel.tsx +126 -111
- package/src/runner/index.ts +13 -1
- package/src/runner/shared.tsx +124 -0
- package/src/runner/useRunner.ts +59 -0
- package/src/session/__tests__/group-sessions.test.ts +5 -3
- package/src/session/__tests__/session-spec-converters.test.ts +185 -0
- package/src/session/__tests__/useNewSessionFlow.test.tsx +2 -2
- package/src/session/__tests__/usePersistedModel.test.tsx +1 -1
- package/src/session/group-sessions.ts +65 -0
- package/src/session/index.ts +8 -2
- package/src/session/session-spec-converters.ts +86 -0
- package/src/session/useSessionConversation.ts +5 -64
- package/src/session/useSessionPageFlow.ts +28 -7
- package/src/session/useSessionSearch.ts +149 -0
- package/src/skill/SkillDetailView.tsx +371 -165
- package/src/skill/SkillDiffDialog.tsx +213 -0
- package/src/skill/SkillFileBrowser.tsx +289 -0
- package/src/skill/SkillUploader.tsx +481 -0
- package/src/skill/index.ts +34 -0
- package/src/skill/internal/computeArtifactHash.ts +13 -0
- package/src/skill/internal/fetchAndUnpackArtifact.ts +48 -0
- package/src/skill/usePushSkill.ts +101 -0
- package/src/skill/useSkillArtifact.ts +107 -0
- package/src/skill/useSkillDiff.ts +128 -0
- package/src/skill/useSkillDuplicateCheck.ts +92 -0
- package/src/skill/useSkillUpload.ts +231 -0
- package/src/skill/useSkillVersions.ts +165 -0
- package/src/styles.css +28 -0
- package/src/tabs/Tabs.tsx +184 -0
- package/src/tabs/index.ts +2 -0
- package/src/version-history/DiffFileList.tsx +111 -0
- package/src/version-history/DiffSummary.tsx +61 -0
- package/src/version-history/DiffViewer.tsx +163 -0
- package/src/version-history/MultiFileDiffView.tsx +114 -0
- package/src/version-history/VersionTimeline.tsx +232 -0
- package/src/version-history/VersionTimelineEntry.tsx +254 -0
- package/src/version-history/computeDiff.ts +61 -0
- package/src/version-history/computeMultiFileDiff.ts +97 -0
- package/src/version-history/index.ts +22 -0
- package/src/version-history/types.ts +129 -0
- package/styles.css +1 -1
- package/tabs/Tabs.d.ts +58 -0
- package/tabs/Tabs.d.ts.map +1 -0
- package/tabs/Tabs.js +80 -0
- package/tabs/Tabs.js.map +1 -0
- package/tabs/index.d.ts +3 -0
- package/tabs/index.d.ts.map +1 -0
- package/tabs/index.js +2 -0
- package/tabs/index.js.map +1 -0
- package/version-history/DiffFileList.d.ts +22 -0
- package/version-history/DiffFileList.d.ts.map +1 -0
- package/version-history/DiffFileList.js +37 -0
- package/version-history/DiffFileList.js.map +1 -0
- package/version-history/DiffSummary.d.ts +21 -0
- package/version-history/DiffSummary.d.ts.map +1 -0
- package/version-history/DiffSummary.js +16 -0
- package/version-history/DiffSummary.js.map +1 -0
- package/version-history/DiffViewer.d.ts +31 -0
- package/version-history/DiffViewer.d.ts.map +1 -0
- package/version-history/DiffViewer.js +60 -0
- package/version-history/DiffViewer.js.map +1 -0
- package/version-history/MultiFileDiffView.d.ts +30 -0
- package/version-history/MultiFileDiffView.d.ts.map +1 -0
- package/version-history/MultiFileDiffView.js +40 -0
- package/version-history/MultiFileDiffView.js.map +1 -0
- package/version-history/VersionTimeline.d.ts +29 -0
- package/version-history/VersionTimeline.d.ts.map +1 -0
- package/version-history/VersionTimeline.js +87 -0
- package/version-history/VersionTimeline.js.map +1 -0
- package/version-history/VersionTimelineEntry.d.ts +22 -0
- package/version-history/VersionTimelineEntry.d.ts.map +1 -0
- package/version-history/VersionTimelineEntry.js +98 -0
- package/version-history/VersionTimelineEntry.js.map +1 -0
- package/version-history/computeDiff.d.ts +16 -0
- package/version-history/computeDiff.d.ts.map +1 -0
- package/version-history/computeDiff.js +54 -0
- package/version-history/computeDiff.js.map +1 -0
- package/version-history/computeMultiFileDiff.d.ts +15 -0
- package/version-history/computeMultiFileDiff.d.ts.map +1 -0
- package/version-history/computeMultiFileDiff.js +83 -0
- package/version-history/computeMultiFileDiff.js.map +1 -0
- package/version-history/index.d.ts +14 -0
- package/version-history/index.d.ts.map +1 -0
- package/version-history/index.js +9 -0
- package/version-history/index.js.map +1 -0
- package/version-history/types.d.ts +106 -0
- package/version-history/types.d.ts.map +1 -0
- package/version-history/types.js +2 -0
- package/version-history/types.js.map +1 -0
- package/library/ResourceListView.d.ts +0 -174
- package/library/ResourceListView.d.ts.map +0 -1
- package/library/ResourceListView.js +0 -318
- package/library/ResourceListView.js.map +0 -1
- package/src/library/ResourceListView.tsx +0 -956
|
@@ -15,6 +15,8 @@ import { ValidationState } from "@stigmer/protos/ai/stigmer/agentic/mcpserver/v1
|
|
|
15
15
|
import type { EnvVarDeclaration } from "@stigmer/protos/ai/stigmer/agentic/environment/v1/spec_pb";
|
|
16
16
|
import { ApiResourceVisibility } from "@stigmer/protos/ai/stigmer/commons/apiresource/enum_pb";
|
|
17
17
|
import { useMcpServer } from "./useMcpServer";
|
|
18
|
+
import { useUpdateMcpServer } from "./useUpdateMcpServer";
|
|
19
|
+
import { mcpServerToInput } from "./internal/mcpServerToInput";
|
|
18
20
|
import { useMcpServerConnect } from "./useMcpServerConnect";
|
|
19
21
|
import { useMcpServerCredentials } from "./useMcpServerCredentials";
|
|
20
22
|
import { useMcpServerOAuthConnect } from "./useMcpServerOAuthConnect";
|
|
@@ -26,7 +28,16 @@ import { ErrorMessage } from "../error/ErrorMessage";
|
|
|
26
28
|
import { EnvVarForm } from "../environment/EnvVarForm";
|
|
27
29
|
import type { EnvVarFormVariable } from "../environment/EnvVarForm";
|
|
28
30
|
import { VisibilityToggle } from "../library/VisibilityToggle";
|
|
29
|
-
import { Tabs, type TabItem } from "../
|
|
31
|
+
import { Tabs, type TabItem } from "../tabs/Tabs";
|
|
32
|
+
import { ResourceActionBar } from "../resource-detail/ResourceActionBar";
|
|
33
|
+
import { Section } from "../resource-detail/Section";
|
|
34
|
+
import type { DetailAction } from "../resource-detail/types";
|
|
35
|
+
import { InlineEditText } from "../inline-edit/InlineEditText";
|
|
36
|
+
import { InlineEditTextarea } from "../inline-edit/InlineEditTextarea";
|
|
37
|
+
import { InlineEditImage } from "../inline-edit/InlineEditImage";
|
|
38
|
+
import { InlineEditSelect } from "../inline-edit/InlineEditSelect";
|
|
39
|
+
import { InlineEditKeyValue } from "../inline-edit/InlineEditKeyValue";
|
|
40
|
+
import type { KeyValueRow, SelectOption } from "../inline-edit/types";
|
|
30
41
|
|
|
31
42
|
/** Tab identifier for the MCP server capability panel. */
|
|
32
43
|
export type CapabilityTab = "tools" | "policies" | "resources";
|
|
@@ -85,6 +96,24 @@ export interface McpServerDetailViewProps {
|
|
|
85
96
|
* When omitted, falls back to the `org` prop (MCP server's org).
|
|
86
97
|
*/
|
|
87
98
|
readonly activeOrg?: string;
|
|
99
|
+
/**
|
|
100
|
+
* Primary action rendered as a visible button in the header area.
|
|
101
|
+
*/
|
|
102
|
+
readonly primaryAction?: DetailAction;
|
|
103
|
+
/**
|
|
104
|
+
* Secondary actions rendered in the kebab overflow menu.
|
|
105
|
+
*/
|
|
106
|
+
readonly actions?: readonly DetailAction[];
|
|
107
|
+
/**
|
|
108
|
+
* When `true`, fields on the detail view become click-to-edit.
|
|
109
|
+
* Each field saves independently via `stigmer.mcpServer.update()`.
|
|
110
|
+
* @default false
|
|
111
|
+
*/
|
|
112
|
+
readonly editable?: boolean;
|
|
113
|
+
/**
|
|
114
|
+
* Called after a successful inline field save with the updated server.
|
|
115
|
+
*/
|
|
116
|
+
readonly onResourceUpdated?: (server: McpServer) => void;
|
|
88
117
|
/** Additional CSS classes for the root container. */
|
|
89
118
|
readonly className?: string;
|
|
90
119
|
}
|
|
@@ -123,9 +152,34 @@ export function McpServerDetailView({
|
|
|
123
152
|
defaultShowCredentialForm = false,
|
|
124
153
|
credentialPoolValues,
|
|
125
154
|
activeOrg,
|
|
155
|
+
primaryAction,
|
|
156
|
+
actions,
|
|
157
|
+
editable = false,
|
|
158
|
+
onResourceUpdated,
|
|
126
159
|
className,
|
|
127
160
|
}: McpServerDetailViewProps) {
|
|
128
161
|
const { mcpServer, isLoading, error, refetch } = useMcpServer(org, slug);
|
|
162
|
+
const { update: updateMcpServer, isUpdating } = useUpdateMcpServer();
|
|
163
|
+
|
|
164
|
+
const saveMcpField = useCallback(
|
|
165
|
+
async <K extends keyof import("@stigmer/sdk").McpServerInput>(
|
|
166
|
+
field: K,
|
|
167
|
+
value: import("@stigmer/sdk").McpServerInput[K],
|
|
168
|
+
): Promise<boolean> => {
|
|
169
|
+
if (!mcpServer) return false;
|
|
170
|
+
const input = mcpServerToInput(mcpServer);
|
|
171
|
+
(input as unknown as Record<string, unknown>)[field] = value;
|
|
172
|
+
try {
|
|
173
|
+
const updated = await updateMcpServer(input);
|
|
174
|
+
onResourceUpdated?.(updated);
|
|
175
|
+
refetch();
|
|
176
|
+
return true;
|
|
177
|
+
} catch {
|
|
178
|
+
return false;
|
|
179
|
+
}
|
|
180
|
+
},
|
|
181
|
+
[mcpServer, updateMcpServer, onResourceUpdated, refetch],
|
|
182
|
+
);
|
|
129
183
|
const credentials = useMcpServerCredentials(activeOrg ?? org, mcpServer ?? null);
|
|
130
184
|
const connection = useMcpServerConnect();
|
|
131
185
|
const oauth = useMcpServerOAuthConnect();
|
|
@@ -199,20 +253,16 @@ export function McpServerDetailView({
|
|
|
199
253
|
credentials.refetch();
|
|
200
254
|
}
|
|
201
255
|
|
|
202
|
-
setShowCredentialForm(false);
|
|
203
|
-
|
|
204
256
|
if (mcpServer?.metadata?.id) {
|
|
205
257
|
const envKeys = Object.keys(mcpServer.spec?.env ?? {});
|
|
206
258
|
const connectOrg = activeOrg ?? org;
|
|
207
|
-
|
|
208
|
-
await connection.connect(mcpServer.metadata.id, connectOrg, undefined, envKeys);
|
|
209
|
-
} else {
|
|
210
|
-
await connection.connect(mcpServer.metadata.id, connectOrg, values, envKeys);
|
|
211
|
-
}
|
|
259
|
+
await connection.connect(mcpServer.metadata.id, connectOrg, values, envKeys);
|
|
212
260
|
refetch();
|
|
213
261
|
}
|
|
262
|
+
|
|
263
|
+
setShowCredentialForm(false);
|
|
214
264
|
} catch {
|
|
215
|
-
// error state is managed by the hooks
|
|
265
|
+
// error state is managed by the hooks — form stays open for retry
|
|
216
266
|
}
|
|
217
267
|
},
|
|
218
268
|
[credentials, mcpServer, connection, refetch],
|
|
@@ -312,33 +362,73 @@ export function McpServerDetailView({
|
|
|
312
362
|
<ValidationBanner message={status.validationMessage} />
|
|
313
363
|
)}
|
|
314
364
|
|
|
315
|
-
<
|
|
316
|
-
|
|
317
|
-
|
|
318
|
-
|
|
319
|
-
|
|
320
|
-
|
|
321
|
-
|
|
322
|
-
|
|
323
|
-
|
|
324
|
-
|
|
325
|
-
|
|
326
|
-
|
|
327
|
-
|
|
328
|
-
|
|
329
|
-
|
|
330
|
-
|
|
365
|
+
<div className="flex items-start justify-between gap-4">
|
|
366
|
+
<Header
|
|
367
|
+
server={mcpServer}
|
|
368
|
+
createdAt={
|
|
369
|
+
specAudit?.createdAt ? timestampDate(specAudit.createdAt) : null
|
|
370
|
+
}
|
|
371
|
+
updatedAt={
|
|
372
|
+
specAudit?.updatedAt ? timestampDate(specAudit.updatedAt) : null
|
|
373
|
+
}
|
|
374
|
+
lastDiscoveredAt={
|
|
375
|
+
capabilities?.lastDiscoveredAt
|
|
376
|
+
? timestampDate(capabilities.lastDiscoveredAt)
|
|
377
|
+
: null
|
|
378
|
+
}
|
|
379
|
+
onVisibilityChange={onVisibilityChange}
|
|
380
|
+
isVisibilityPending={isVisibilityPending}
|
|
381
|
+
editable={editable}
|
|
382
|
+
isSaving={isUpdating}
|
|
383
|
+
saveMcpField={saveMcpField}
|
|
384
|
+
/>
|
|
385
|
+
<ResourceActionBar
|
|
386
|
+
primaryAction={primaryAction}
|
|
387
|
+
actions={actions}
|
|
388
|
+
className="shrink-0"
|
|
389
|
+
/>
|
|
390
|
+
</div>
|
|
391
|
+
|
|
392
|
+
{(editable || spec?.description) && (
|
|
393
|
+
<Section title="Description">
|
|
394
|
+
{editable && saveMcpField ? (
|
|
395
|
+
<div className="max-h-20 overflow-y-auto p-3">
|
|
396
|
+
<InlineEditTextarea
|
|
397
|
+
value={spec?.description || ""}
|
|
398
|
+
onSave={(v) => saveMcpField("description", v || undefined)}
|
|
399
|
+
isSaving={isUpdating}
|
|
400
|
+
placeholder="Add a description"
|
|
401
|
+
minRows={2}
|
|
402
|
+
/>
|
|
403
|
+
</div>
|
|
404
|
+
) : (
|
|
405
|
+
<div className="p-3">
|
|
406
|
+
<pre className="whitespace-pre-wrap break-words text-sm text-foreground font-sans">
|
|
407
|
+
{spec?.description}
|
|
408
|
+
</pre>
|
|
409
|
+
</div>
|
|
410
|
+
)}
|
|
411
|
+
</Section>
|
|
412
|
+
)}
|
|
331
413
|
|
|
332
414
|
{hasSource && <SourceSection spec={spec} />}
|
|
333
415
|
|
|
334
|
-
{spec?.serverType.case && (
|
|
335
|
-
<ServerConfigSection
|
|
416
|
+
{(editable || spec?.serverType.case) && (
|
|
417
|
+
<ServerConfigSection
|
|
418
|
+
serverType={spec?.serverType}
|
|
419
|
+
editable={editable}
|
|
420
|
+
isSaving={isUpdating}
|
|
421
|
+
saveMcpField={saveMcpField}
|
|
422
|
+
/>
|
|
336
423
|
)}
|
|
337
424
|
|
|
338
|
-
{spec?.env && Object.keys(spec.env).length > 0 && (
|
|
425
|
+
{(editable || (spec?.env && Object.keys(spec.env).length > 0)) && (
|
|
339
426
|
<EnvSection
|
|
340
|
-
data={spec
|
|
427
|
+
data={spec?.env ?? {}}
|
|
341
428
|
oauthTargetEnvVar={credentials.oauthTargetEnvVar}
|
|
429
|
+
editable={editable}
|
|
430
|
+
isSaving={isUpdating}
|
|
431
|
+
saveMcpField={saveMcpField}
|
|
342
432
|
/>
|
|
343
433
|
)}
|
|
344
434
|
|
|
@@ -349,8 +439,6 @@ export function McpServerDetailView({
|
|
|
349
439
|
onConnect={handleConnectClick}
|
|
350
440
|
onClearConnectionError={combinedClearError}
|
|
351
441
|
hasDiscoveredTools={hasDiscoveredTools}
|
|
352
|
-
toolCount={tools.length}
|
|
353
|
-
policyCount={totalPolicyCount}
|
|
354
442
|
credentialsLoading={credentials.isLoading}
|
|
355
443
|
oauthPhase={oauth.phase}
|
|
356
444
|
authMode={credentials.authMode}
|
|
@@ -455,7 +543,9 @@ export function McpServerDetailView({
|
|
|
455
543
|
</Tabs>
|
|
456
544
|
</Section>
|
|
457
545
|
|
|
458
|
-
{spec && spec.tags.length > 0 &&
|
|
546
|
+
{(editable || (spec && spec.tags.length > 0)) && (
|
|
547
|
+
<TagsSection tags={spec?.tags ?? []} editable={editable} isSaving={isUpdating} saveMcpField={saveMcpField} />
|
|
548
|
+
)}
|
|
459
549
|
</div>
|
|
460
550
|
);
|
|
461
551
|
}
|
|
@@ -539,8 +629,6 @@ function ConnectBar({
|
|
|
539
629
|
onConnect,
|
|
540
630
|
onClearConnectionError,
|
|
541
631
|
hasDiscoveredTools,
|
|
542
|
-
toolCount,
|
|
543
|
-
policyCount,
|
|
544
632
|
credentialsLoading,
|
|
545
633
|
oauthPhase,
|
|
546
634
|
authMode,
|
|
@@ -574,8 +662,6 @@ function ConnectBar({
|
|
|
574
662
|
readonly onConnect: () => void;
|
|
575
663
|
readonly onClearConnectionError: () => void;
|
|
576
664
|
readonly hasDiscoveredTools: boolean;
|
|
577
|
-
readonly toolCount: number;
|
|
578
|
-
readonly policyCount: number;
|
|
579
665
|
readonly credentialsLoading: boolean;
|
|
580
666
|
readonly oauthPhase: OAuthConnectPhase;
|
|
581
667
|
readonly authMode: "manual" | "oauth";
|
|
@@ -647,7 +733,7 @@ function ConnectBar({
|
|
|
647
733
|
}
|
|
648
734
|
if (isOrgOAuthApp && showOAuthPrimary) return "Using your OAuth app";
|
|
649
735
|
if (manualOverride) return "Entering token manually";
|
|
650
|
-
if (hasDiscoveredTools) return
|
|
736
|
+
if (hasDiscoveredTools) return "Connected";
|
|
651
737
|
return "Not connected yet";
|
|
652
738
|
})();
|
|
653
739
|
|
|
@@ -990,13 +1076,6 @@ function oauthPhaseLabel(phase: OAuthConnectPhase): string {
|
|
|
990
1076
|
}
|
|
991
1077
|
}
|
|
992
1078
|
|
|
993
|
-
function formatConnectionSummary(toolCount: number, policyCount: number): string {
|
|
994
|
-
const toolLabel = `${toolCount} tool${toolCount !== 1 ? "s" : ""}`;
|
|
995
|
-
if (policyCount === 0) return toolLabel;
|
|
996
|
-
const policyLabel = `${policyCount} ${policyCount !== 1 ? "policies" : "policy"}`;
|
|
997
|
-
return `${toolLabel}, ${policyLabel}`;
|
|
998
|
-
}
|
|
999
|
-
|
|
1000
1079
|
function formatTokenExpiry(expiresAtSeconds: bigint): string | null {
|
|
1001
1080
|
if (expiresAtSeconds === BigInt(0)) return null;
|
|
1002
1081
|
const nowSeconds = BigInt(Math.floor(Date.now() / 1000));
|
|
@@ -1039,6 +1118,9 @@ function Header({
|
|
|
1039
1118
|
lastDiscoveredAt,
|
|
1040
1119
|
onVisibilityChange,
|
|
1041
1120
|
isVisibilityPending,
|
|
1121
|
+
editable,
|
|
1122
|
+
isSaving,
|
|
1123
|
+
saveMcpField,
|
|
1042
1124
|
}: {
|
|
1043
1125
|
readonly server: McpServer;
|
|
1044
1126
|
readonly createdAt: Date | null;
|
|
@@ -1046,6 +1128,12 @@ function Header({
|
|
|
1046
1128
|
readonly lastDiscoveredAt: Date | null;
|
|
1047
1129
|
readonly onVisibilityChange?: (v: ApiResourceVisibility) => void;
|
|
1048
1130
|
readonly isVisibilityPending?: boolean;
|
|
1131
|
+
readonly editable?: boolean;
|
|
1132
|
+
readonly isSaving?: boolean;
|
|
1133
|
+
readonly saveMcpField?: <K extends keyof import("@stigmer/sdk").McpServerInput>(
|
|
1134
|
+
field: K,
|
|
1135
|
+
value: import("@stigmer/sdk").McpServerInput[K],
|
|
1136
|
+
) => Promise<boolean>;
|
|
1049
1137
|
}) {
|
|
1050
1138
|
const meta = server.metadata;
|
|
1051
1139
|
const spec = server.spec;
|
|
@@ -1056,7 +1144,15 @@ function Header({
|
|
|
1056
1144
|
|
|
1057
1145
|
return (
|
|
1058
1146
|
<div className="flex items-start gap-3">
|
|
1059
|
-
{
|
|
1147
|
+
{editable && saveMcpField ? (
|
|
1148
|
+
<InlineEditImage
|
|
1149
|
+
value={spec?.iconUrl ?? ""}
|
|
1150
|
+
onSave={(v) => saveMcpField("iconUrl", v || undefined)}
|
|
1151
|
+
isSaving={isSaving}
|
|
1152
|
+
fallback={<McpServerIcon className="size-6 text-muted-foreground" />}
|
|
1153
|
+
size="md"
|
|
1154
|
+
/>
|
|
1155
|
+
) : spec?.iconUrl ? (
|
|
1060
1156
|
<img
|
|
1061
1157
|
src={spec.iconUrl}
|
|
1062
1158
|
alt=""
|
|
@@ -1067,9 +1163,20 @@ function Header({
|
|
|
1067
1163
|
)}
|
|
1068
1164
|
<div className="min-w-0 flex-1">
|
|
1069
1165
|
<div className="flex items-center gap-2">
|
|
1070
|
-
|
|
1071
|
-
|
|
1072
|
-
|
|
1166
|
+
{editable && saveMcpField ? (
|
|
1167
|
+
<InlineEditText
|
|
1168
|
+
value={meta?.name || ""}
|
|
1169
|
+
onSave={(v) => saveMcpField("name", v)}
|
|
1170
|
+
isSaving={isSaving}
|
|
1171
|
+
variant="heading"
|
|
1172
|
+
placeholder="Server name"
|
|
1173
|
+
validate={(v) => (v.trim() ? null : "Name is required")}
|
|
1174
|
+
/>
|
|
1175
|
+
) : (
|
|
1176
|
+
<h2 className="truncate text-lg font-semibold text-foreground">
|
|
1177
|
+
{displayName}
|
|
1178
|
+
</h2>
|
|
1179
|
+
)}
|
|
1073
1180
|
{onVisibilityChange && meta ? (
|
|
1074
1181
|
<VisibilityToggle
|
|
1075
1182
|
visibility={meta.visibility}
|
|
@@ -1113,11 +1220,6 @@ function Header({
|
|
|
1113
1220
|
</>
|
|
1114
1221
|
)}
|
|
1115
1222
|
</div>
|
|
1116
|
-
{spec?.description && (
|
|
1117
|
-
<p className="mt-2 text-sm text-muted-foreground">
|
|
1118
|
-
{spec.description}
|
|
1119
|
-
</p>
|
|
1120
|
-
)}
|
|
1121
1223
|
</div>
|
|
1122
1224
|
</div>
|
|
1123
1225
|
);
|
|
@@ -1151,13 +1253,94 @@ function ValidationStateBadge({
|
|
|
1151
1253
|
}
|
|
1152
1254
|
}
|
|
1153
1255
|
|
|
1256
|
+
const TRANSPORT_OPTIONS: SelectOption[] = [
|
|
1257
|
+
{ value: "http", label: "HTTP", description: "Connect via HTTP/SSE endpoint" },
|
|
1258
|
+
{ value: "stdio", label: "Stdio", description: "Launch a local process with stdin/stdout" },
|
|
1259
|
+
];
|
|
1260
|
+
|
|
1154
1261
|
function ServerConfigSection({
|
|
1155
1262
|
serverType,
|
|
1263
|
+
editable,
|
|
1264
|
+
isSaving,
|
|
1265
|
+
saveMcpField,
|
|
1156
1266
|
}: {
|
|
1157
|
-
readonly serverType
|
|
1158
|
-
|
|
1159
|
-
|
|
1267
|
+
readonly serverType?: import("@stigmer/protos/ai/stigmer/agentic/mcpserver/v1/spec_pb").McpServerSpec["serverType"];
|
|
1268
|
+
readonly editable?: boolean;
|
|
1269
|
+
readonly isSaving?: boolean;
|
|
1270
|
+
readonly saveMcpField?: <K extends keyof import("@stigmer/sdk").McpServerInput>(
|
|
1271
|
+
field: K,
|
|
1272
|
+
value: import("@stigmer/sdk").McpServerInput[K],
|
|
1273
|
+
) => Promise<boolean>;
|
|
1160
1274
|
}) {
|
|
1275
|
+
const [headersEditing, setHeadersEditing] = useState(false);
|
|
1276
|
+
const [queryParamsEditing, setQueryParamsEditing] = useState(false);
|
|
1277
|
+
|
|
1278
|
+
const currentHttpConfig = useMemo(() => {
|
|
1279
|
+
if (serverType?.case !== "http") return null;
|
|
1280
|
+
const v = serverType.value;
|
|
1281
|
+
return {
|
|
1282
|
+
url: v.url,
|
|
1283
|
+
headers: v.headers && Object.keys(v.headers).length > 0 ? { ...v.headers } : undefined,
|
|
1284
|
+
queryParams: v.queryParams && Object.keys(v.queryParams).length > 0 ? { ...v.queryParams } : undefined,
|
|
1285
|
+
timeoutSeconds: v.timeoutSeconds || undefined,
|
|
1286
|
+
};
|
|
1287
|
+
}, [serverType]);
|
|
1288
|
+
|
|
1289
|
+
const handleTransportChange = useCallback(
|
|
1290
|
+
async (newType: string) => {
|
|
1291
|
+
if (!saveMcpField) return false;
|
|
1292
|
+
if (newType === "http") {
|
|
1293
|
+
const ok = await saveMcpField("http", { url: "" });
|
|
1294
|
+
if (ok) await saveMcpField("stdio", undefined);
|
|
1295
|
+
return ok;
|
|
1296
|
+
}
|
|
1297
|
+
const ok = await saveMcpField("stdio", { command: "" });
|
|
1298
|
+
if (ok) await saveMcpField("http", undefined);
|
|
1299
|
+
return ok;
|
|
1300
|
+
},
|
|
1301
|
+
[saveMcpField],
|
|
1302
|
+
);
|
|
1303
|
+
|
|
1304
|
+
const headerRows: KeyValueRow[] = useMemo(() => {
|
|
1305
|
+
if (!currentHttpConfig?.headers) return [];
|
|
1306
|
+
return Object.entries(currentHttpConfig.headers).map(([key, value]) => ({ key, value }));
|
|
1307
|
+
}, [currentHttpConfig?.headers]);
|
|
1308
|
+
|
|
1309
|
+
const queryParamRows: KeyValueRow[] = useMemo(() => {
|
|
1310
|
+
if (!currentHttpConfig?.queryParams) return [];
|
|
1311
|
+
return Object.entries(currentHttpConfig.queryParams).map(([key, value]) => ({ key, value }));
|
|
1312
|
+
}, [currentHttpConfig?.queryParams]);
|
|
1313
|
+
|
|
1314
|
+
const handleHeadersSave = useCallback(
|
|
1315
|
+
async (rows: KeyValueRow[]) => {
|
|
1316
|
+
if (!saveMcpField || !currentHttpConfig) return false;
|
|
1317
|
+
const headers: Record<string, string> = {};
|
|
1318
|
+
for (const row of rows) {
|
|
1319
|
+
if (row.key.trim()) headers[row.key.trim()] = row.value;
|
|
1320
|
+
}
|
|
1321
|
+
return saveMcpField("http", {
|
|
1322
|
+
...currentHttpConfig,
|
|
1323
|
+
headers: Object.keys(headers).length > 0 ? headers : undefined,
|
|
1324
|
+
});
|
|
1325
|
+
},
|
|
1326
|
+
[saveMcpField, currentHttpConfig],
|
|
1327
|
+
);
|
|
1328
|
+
|
|
1329
|
+
const handleQueryParamsSave = useCallback(
|
|
1330
|
+
async (rows: KeyValueRow[]) => {
|
|
1331
|
+
if (!saveMcpField || !currentHttpConfig) return false;
|
|
1332
|
+
const queryParams: Record<string, string> = {};
|
|
1333
|
+
for (const row of rows) {
|
|
1334
|
+
if (row.key.trim()) queryParams[row.key.trim()] = row.value;
|
|
1335
|
+
}
|
|
1336
|
+
return saveMcpField("http", {
|
|
1337
|
+
...currentHttpConfig,
|
|
1338
|
+
queryParams: Object.keys(queryParams).length > 0 ? queryParams : undefined,
|
|
1339
|
+
});
|
|
1340
|
+
},
|
|
1341
|
+
[saveMcpField, currentHttpConfig],
|
|
1342
|
+
);
|
|
1343
|
+
|
|
1161
1344
|
return (
|
|
1162
1345
|
<Section title="Server Configuration">
|
|
1163
1346
|
<div className="flex flex-col gap-2 p-3">
|
|
@@ -1165,63 +1348,265 @@ function ServerConfigSection({
|
|
|
1165
1348
|
<span className="text-xs font-medium text-muted-foreground">
|
|
1166
1349
|
Type
|
|
1167
1350
|
</span>
|
|
1168
|
-
|
|
1169
|
-
|
|
1170
|
-
|
|
1351
|
+
{editable && saveMcpField ? (
|
|
1352
|
+
<InlineEditSelect
|
|
1353
|
+
value={serverType?.case ?? "http"}
|
|
1354
|
+
options={TRANSPORT_OPTIONS}
|
|
1355
|
+
onSave={handleTransportChange}
|
|
1356
|
+
isSaving={isSaving}
|
|
1357
|
+
/>
|
|
1358
|
+
) : (
|
|
1359
|
+
<span className="rounded bg-muted px-1.5 py-0.5 font-mono text-xs font-medium text-foreground">
|
|
1360
|
+
{serverType?.case ?? "none"}
|
|
1361
|
+
</span>
|
|
1362
|
+
)}
|
|
1171
1363
|
</div>
|
|
1172
1364
|
|
|
1173
|
-
{serverType
|
|
1365
|
+
{serverType?.case === "stdio" && (
|
|
1174
1366
|
<>
|
|
1175
1367
|
<div className="flex items-baseline gap-2">
|
|
1176
1368
|
<span className="text-xs font-medium text-muted-foreground">
|
|
1177
1369
|
Command
|
|
1178
1370
|
</span>
|
|
1179
|
-
|
|
1180
|
-
|
|
1181
|
-
|
|
1182
|
-
|
|
1183
|
-
|
|
1371
|
+
{editable && saveMcpField ? (
|
|
1372
|
+
<InlineEditText
|
|
1373
|
+
value={`${serverType.value.command}${serverType.value.args.length > 0 ? ` ${serverType.value.args.join(" ")}` : ""}`}
|
|
1374
|
+
onSave={async (v) => {
|
|
1375
|
+
const parts = v.trim().split(/\s+/);
|
|
1376
|
+
return saveMcpField("stdio", {
|
|
1377
|
+
command: parts[0] || "",
|
|
1378
|
+
args: parts.slice(1),
|
|
1379
|
+
});
|
|
1380
|
+
}}
|
|
1381
|
+
isSaving={isSaving}
|
|
1382
|
+
placeholder="e.g. npx -y @modelcontextprotocol/server"
|
|
1383
|
+
/>
|
|
1384
|
+
) : (
|
|
1385
|
+
<code className="font-mono text-sm text-foreground">
|
|
1386
|
+
{serverType.value.command}
|
|
1387
|
+
{serverType.value.args.length > 0 &&
|
|
1388
|
+
` ${serverType.value.args.join(" ")}`}
|
|
1389
|
+
</code>
|
|
1390
|
+
)}
|
|
1184
1391
|
</div>
|
|
1185
|
-
{serverType.value.workingDir && (
|
|
1392
|
+
{(editable || serverType.value.workingDir) && (
|
|
1186
1393
|
<div className="flex items-baseline gap-2">
|
|
1187
1394
|
<span className="text-xs font-medium text-muted-foreground">
|
|
1188
1395
|
Working Dir
|
|
1189
1396
|
</span>
|
|
1190
|
-
|
|
1191
|
-
|
|
1192
|
-
|
|
1397
|
+
{editable && saveMcpField ? (
|
|
1398
|
+
<InlineEditText
|
|
1399
|
+
value={serverType.value.workingDir ?? ""}
|
|
1400
|
+
onSave={async (v) =>
|
|
1401
|
+
saveMcpField("stdio", {
|
|
1402
|
+
command: serverType.value.command,
|
|
1403
|
+
args: [...serverType.value.args],
|
|
1404
|
+
workingDir: v || undefined,
|
|
1405
|
+
})
|
|
1406
|
+
}
|
|
1407
|
+
isSaving={isSaving}
|
|
1408
|
+
placeholder="/path/to/working/dir"
|
|
1409
|
+
/>
|
|
1410
|
+
) : (
|
|
1411
|
+
<code className="font-mono text-xs text-foreground">
|
|
1412
|
+
{serverType.value.workingDir}
|
|
1413
|
+
</code>
|
|
1414
|
+
)}
|
|
1193
1415
|
</div>
|
|
1194
1416
|
)}
|
|
1195
1417
|
</>
|
|
1196
1418
|
)}
|
|
1197
1419
|
|
|
1198
|
-
{serverType
|
|
1420
|
+
{serverType?.case === "http" && (
|
|
1199
1421
|
<>
|
|
1200
1422
|
<div className="flex items-baseline gap-2">
|
|
1201
1423
|
<span className="text-xs font-medium text-muted-foreground">
|
|
1202
1424
|
URL
|
|
1203
1425
|
</span>
|
|
1204
|
-
|
|
1205
|
-
|
|
1206
|
-
|
|
1426
|
+
{editable && saveMcpField ? (
|
|
1427
|
+
<InlineEditText
|
|
1428
|
+
value={serverType.value.url}
|
|
1429
|
+
onSave={async (v) =>
|
|
1430
|
+
saveMcpField("http", { ...currentHttpConfig!, url: v })
|
|
1431
|
+
}
|
|
1432
|
+
isSaving={isSaving}
|
|
1433
|
+
placeholder="https://example.com/mcp"
|
|
1434
|
+
/>
|
|
1435
|
+
) : (
|
|
1436
|
+
<code className="break-all font-mono text-sm text-foreground">
|
|
1437
|
+
{serverType.value.url}
|
|
1438
|
+
</code>
|
|
1439
|
+
)}
|
|
1207
1440
|
</div>
|
|
1208
|
-
{serverType.value.timeoutSeconds > 0 && (
|
|
1441
|
+
{(editable || serverType.value.timeoutSeconds > 0) && (
|
|
1209
1442
|
<div className="flex items-baseline gap-2">
|
|
1210
1443
|
<span className="text-xs font-medium text-muted-foreground">
|
|
1211
1444
|
Timeout
|
|
1212
1445
|
</span>
|
|
1213
|
-
|
|
1214
|
-
|
|
1215
|
-
|
|
1446
|
+
{editable && saveMcpField ? (
|
|
1447
|
+
<InlineEditText
|
|
1448
|
+
value={serverType.value.timeoutSeconds > 0 ? String(serverType.value.timeoutSeconds) : ""}
|
|
1449
|
+
onSave={async (v) =>
|
|
1450
|
+
saveMcpField("http", {
|
|
1451
|
+
...currentHttpConfig!,
|
|
1452
|
+
timeoutSeconds: v ? Number(v) : undefined,
|
|
1453
|
+
})
|
|
1454
|
+
}
|
|
1455
|
+
isSaving={isSaving}
|
|
1456
|
+
placeholder="30"
|
|
1457
|
+
validate={(v) => {
|
|
1458
|
+
if (v && (isNaN(Number(v)) || Number(v) < 0)) return "Must be a positive number";
|
|
1459
|
+
return null;
|
|
1460
|
+
}}
|
|
1461
|
+
/>
|
|
1462
|
+
) : (
|
|
1463
|
+
<span className="text-xs text-foreground">
|
|
1464
|
+
{serverType.value.timeoutSeconds}s
|
|
1465
|
+
</span>
|
|
1466
|
+
)}
|
|
1216
1467
|
</div>
|
|
1217
1468
|
)}
|
|
1218
1469
|
</>
|
|
1219
1470
|
)}
|
|
1220
1471
|
</div>
|
|
1472
|
+
|
|
1473
|
+
{serverType?.case === "http" && (editable || headerRows.length > 0) && (
|
|
1474
|
+
<HttpKeyValueSubsection
|
|
1475
|
+
title="Headers"
|
|
1476
|
+
count={headerRows.length}
|
|
1477
|
+
rows={headerRows}
|
|
1478
|
+
editable={editable}
|
|
1479
|
+
isSaving={isSaving}
|
|
1480
|
+
editing={headersEditing}
|
|
1481
|
+
onEditingChange={setHeadersEditing}
|
|
1482
|
+
onSave={handleHeadersSave}
|
|
1483
|
+
keyLabel="Header name"
|
|
1484
|
+
/>
|
|
1485
|
+
)}
|
|
1486
|
+
|
|
1487
|
+
{serverType?.case === "http" && (editable || queryParamRows.length > 0) && (
|
|
1488
|
+
<HttpKeyValueSubsection
|
|
1489
|
+
title="Query Parameters"
|
|
1490
|
+
count={queryParamRows.length}
|
|
1491
|
+
rows={queryParamRows}
|
|
1492
|
+
editable={editable}
|
|
1493
|
+
isSaving={isSaving}
|
|
1494
|
+
editing={queryParamsEditing}
|
|
1495
|
+
onEditingChange={setQueryParamsEditing}
|
|
1496
|
+
onSave={handleQueryParamsSave}
|
|
1497
|
+
keyLabel="Parameter name"
|
|
1498
|
+
/>
|
|
1499
|
+
)}
|
|
1221
1500
|
</Section>
|
|
1222
1501
|
);
|
|
1223
1502
|
}
|
|
1224
1503
|
|
|
1504
|
+
/** Renders a key-value subsection (headers or query params) within ServerConfigSection. */
|
|
1505
|
+
function HttpKeyValueSubsection({
|
|
1506
|
+
title,
|
|
1507
|
+
count,
|
|
1508
|
+
rows,
|
|
1509
|
+
editable,
|
|
1510
|
+
isSaving,
|
|
1511
|
+
editing,
|
|
1512
|
+
onEditingChange,
|
|
1513
|
+
onSave,
|
|
1514
|
+
keyLabel,
|
|
1515
|
+
}: {
|
|
1516
|
+
readonly title: string;
|
|
1517
|
+
readonly count: number;
|
|
1518
|
+
readonly rows: readonly KeyValueRow[];
|
|
1519
|
+
readonly editable?: boolean;
|
|
1520
|
+
readonly isSaving?: boolean;
|
|
1521
|
+
readonly editing: boolean;
|
|
1522
|
+
readonly onEditingChange: (v: boolean) => void;
|
|
1523
|
+
readonly onSave: (rows: KeyValueRow[]) => Promise<boolean>;
|
|
1524
|
+
readonly keyLabel: string;
|
|
1525
|
+
}) {
|
|
1526
|
+
return (
|
|
1527
|
+
<div className="border-t border-border">
|
|
1528
|
+
<div className="flex items-center justify-between px-3 py-2">
|
|
1529
|
+
<div className="flex items-center gap-1.5">
|
|
1530
|
+
<span className="text-xs font-medium text-muted-foreground">{title}</span>
|
|
1531
|
+
{count > 0 && (
|
|
1532
|
+
<span className="inline-flex min-w-[1.25rem] items-center justify-center rounded-full bg-muted px-1 py-px text-[10px] font-medium leading-none text-muted-foreground">
|
|
1533
|
+
{count}
|
|
1534
|
+
</span>
|
|
1535
|
+
)}
|
|
1536
|
+
</div>
|
|
1537
|
+
{editable && (
|
|
1538
|
+
<button
|
|
1539
|
+
type="button"
|
|
1540
|
+
onClick={() => onEditingChange(!editing)}
|
|
1541
|
+
className="text-[11px] text-muted-foreground underline decoration-muted-foreground/40 underline-offset-2 hover:text-foreground hover:decoration-foreground"
|
|
1542
|
+
>
|
|
1543
|
+
{editing ? "Done" : "Edit"}
|
|
1544
|
+
</button>
|
|
1545
|
+
)}
|
|
1546
|
+
</div>
|
|
1547
|
+
{editable && editing ? (
|
|
1548
|
+
<InlineEditKeyValue
|
|
1549
|
+
value={[...rows]}
|
|
1550
|
+
onSave={onSave}
|
|
1551
|
+
isSaving={isSaving}
|
|
1552
|
+
editing={editing}
|
|
1553
|
+
onEditingChange={onEditingChange}
|
|
1554
|
+
keyLabel={keyLabel}
|
|
1555
|
+
showValue
|
|
1556
|
+
valueLabel="Value"
|
|
1557
|
+
/>
|
|
1558
|
+
) : (
|
|
1559
|
+
<div className="flex flex-col divide-y divide-border">
|
|
1560
|
+
{rows.map((row) => (
|
|
1561
|
+
<div key={row.key} className="flex items-start gap-2 px-3 py-1.5">
|
|
1562
|
+
<code className="shrink-0 font-mono text-xs font-medium text-foreground">
|
|
1563
|
+
{row.key}
|
|
1564
|
+
</code>
|
|
1565
|
+
<span className="min-w-0 break-all font-mono text-xs text-muted-foreground">
|
|
1566
|
+
{renderHeaderValue(row.value)}
|
|
1567
|
+
</span>
|
|
1568
|
+
</div>
|
|
1569
|
+
))}
|
|
1570
|
+
</div>
|
|
1571
|
+
)}
|
|
1572
|
+
</div>
|
|
1573
|
+
);
|
|
1574
|
+
}
|
|
1575
|
+
|
|
1576
|
+
const ENV_VAR_PLACEHOLDER = /\$\{([^}]+)\}/g;
|
|
1577
|
+
|
|
1578
|
+
/** Renders a header value, highlighting ${VAR} placeholders with a variable badge. */
|
|
1579
|
+
function renderHeaderValue(value: string): React.ReactNode {
|
|
1580
|
+
if (!ENV_VAR_PLACEHOLDER.test(value)) return value;
|
|
1581
|
+
|
|
1582
|
+
ENV_VAR_PLACEHOLDER.lastIndex = 0;
|
|
1583
|
+
const parts: React.ReactNode[] = [];
|
|
1584
|
+
let lastIndex = 0;
|
|
1585
|
+
let match: RegExpExecArray | null;
|
|
1586
|
+
|
|
1587
|
+
while ((match = ENV_VAR_PLACEHOLDER.exec(value)) !== null) {
|
|
1588
|
+
if (match.index > lastIndex) {
|
|
1589
|
+
parts.push(value.slice(lastIndex, match.index));
|
|
1590
|
+
}
|
|
1591
|
+
parts.push(
|
|
1592
|
+
<span
|
|
1593
|
+
key={match.index}
|
|
1594
|
+
className="inline-flex items-center gap-0.5 rounded bg-primary-subtle px-1 py-px text-[10px] font-medium text-primary"
|
|
1595
|
+
title={`Resolved from environment variable: ${match[1]}`}
|
|
1596
|
+
>
|
|
1597
|
+
{match[0]}
|
|
1598
|
+
</span>,
|
|
1599
|
+
);
|
|
1600
|
+
lastIndex = match.index + match[0].length;
|
|
1601
|
+
}
|
|
1602
|
+
|
|
1603
|
+
if (lastIndex < value.length) {
|
|
1604
|
+
parts.push(value.slice(lastIndex));
|
|
1605
|
+
}
|
|
1606
|
+
|
|
1607
|
+
return <>{parts}</>;
|
|
1608
|
+
}
|
|
1609
|
+
|
|
1225
1610
|
function SourceSection({
|
|
1226
1611
|
spec,
|
|
1227
1612
|
}: {
|
|
@@ -1294,53 +1679,138 @@ function ResourceTemplatesList({
|
|
|
1294
1679
|
function EnvSection({
|
|
1295
1680
|
data,
|
|
1296
1681
|
oauthTargetEnvVar,
|
|
1682
|
+
editable,
|
|
1683
|
+
isSaving,
|
|
1684
|
+
saveMcpField,
|
|
1297
1685
|
}: {
|
|
1298
1686
|
readonly data: { [key: string]: EnvVarDeclaration };
|
|
1299
1687
|
readonly oauthTargetEnvVar: string | null;
|
|
1688
|
+
readonly editable?: boolean;
|
|
1689
|
+
readonly isSaving?: boolean;
|
|
1690
|
+
readonly saveMcpField?: <K extends keyof import("@stigmer/sdk").McpServerInput>(
|
|
1691
|
+
field: K,
|
|
1692
|
+
value: import("@stigmer/sdk").McpServerInput[K],
|
|
1693
|
+
) => Promise<boolean>;
|
|
1300
1694
|
}) {
|
|
1301
1695
|
const entries = Object.entries(data).sort(([a], [b]) =>
|
|
1302
1696
|
a.localeCompare(b),
|
|
1303
1697
|
);
|
|
1304
1698
|
|
|
1699
|
+
const envRows: KeyValueRow[] = useMemo(
|
|
1700
|
+
() =>
|
|
1701
|
+
entries.map(([key, decl]) => ({
|
|
1702
|
+
key,
|
|
1703
|
+
value: "",
|
|
1704
|
+
isSecret: decl.isSecret,
|
|
1705
|
+
description: decl.description,
|
|
1706
|
+
optional: decl.optional,
|
|
1707
|
+
})),
|
|
1708
|
+
[entries],
|
|
1709
|
+
);
|
|
1710
|
+
|
|
1711
|
+
const handleEnvSave = useCallback(
|
|
1712
|
+
async (rows: KeyValueRow[]) => {
|
|
1713
|
+
if (!saveMcpField) return false;
|
|
1714
|
+
const env: Record<string, { isSecret?: boolean; description?: string; optional?: boolean }> = {};
|
|
1715
|
+
for (const row of rows) {
|
|
1716
|
+
if (row.key.trim()) {
|
|
1717
|
+
env[row.key.trim()] = {
|
|
1718
|
+
isSecret: row.isSecret || undefined,
|
|
1719
|
+
description: row.description || undefined,
|
|
1720
|
+
optional: row.optional || undefined,
|
|
1721
|
+
};
|
|
1722
|
+
}
|
|
1723
|
+
}
|
|
1724
|
+
return saveMcpField("env", Object.keys(env).length > 0 ? env : undefined);
|
|
1725
|
+
},
|
|
1726
|
+
[saveMcpField],
|
|
1727
|
+
);
|
|
1728
|
+
|
|
1729
|
+
const [envEditing, setEnvEditing] = useState(false);
|
|
1730
|
+
|
|
1305
1731
|
return (
|
|
1306
|
-
<Section title=
|
|
1307
|
-
|
|
1308
|
-
|
|
1309
|
-
|
|
1310
|
-
|
|
1311
|
-
|
|
1312
|
-
|
|
1313
|
-
|
|
1314
|
-
|
|
1315
|
-
|
|
1316
|
-
|
|
1317
|
-
|
|
1318
|
-
|
|
1319
|
-
|
|
1320
|
-
|
|
1321
|
-
|
|
1322
|
-
|
|
1323
|
-
|
|
1324
|
-
|
|
1325
|
-
|
|
1326
|
-
|
|
1327
|
-
|
|
1328
|
-
|
|
1329
|
-
|
|
1330
|
-
{env.description}
|
|
1732
|
+
<Section title="Environment Variables" count={entries.length} onEdit={editable ? () => setEnvEditing((v) => !v) : undefined}>
|
|
1733
|
+
{editable ? (
|
|
1734
|
+
<InlineEditKeyValue
|
|
1735
|
+
value={envRows}
|
|
1736
|
+
onSave={handleEnvSave}
|
|
1737
|
+
isSaving={isSaving}
|
|
1738
|
+
editing={envEditing}
|
|
1739
|
+
onEditingChange={setEnvEditing}
|
|
1740
|
+
showSecretToggle
|
|
1741
|
+
showOptionalToggle
|
|
1742
|
+
showDescription
|
|
1743
|
+
keyLabel="Variable name"
|
|
1744
|
+
/>
|
|
1745
|
+
) : (
|
|
1746
|
+
<div className="flex flex-col divide-y divide-border">
|
|
1747
|
+
{entries.map(([name, env]) => {
|
|
1748
|
+
const isOAuthManaged = name === oauthTargetEnvVar;
|
|
1749
|
+
return (
|
|
1750
|
+
<div key={name} className="flex items-start gap-3 px-3 py-2">
|
|
1751
|
+
<code className="shrink-0 font-mono text-sm font-medium text-foreground">
|
|
1752
|
+
{name}
|
|
1753
|
+
</code>
|
|
1754
|
+
<span className="shrink-0 rounded bg-muted px-1.5 py-0.5 text-[10px] font-medium text-muted-foreground">
|
|
1755
|
+
{env.isSecret ? "secret" : "config"}
|
|
1331
1756
|
</span>
|
|
1332
|
-
|
|
1333
|
-
|
|
1334
|
-
|
|
1335
|
-
|
|
1336
|
-
|
|
1757
|
+
{isOAuthManaged && (
|
|
1758
|
+
<span className="shrink-0 rounded bg-primary-subtle px-1.5 py-0.5 text-[10px] font-medium text-primary">
|
|
1759
|
+
oauth
|
|
1760
|
+
</span>
|
|
1761
|
+
)}
|
|
1762
|
+
{env.optional && (
|
|
1763
|
+
<span className="shrink-0 rounded bg-muted px-1.5 py-0.5 text-[10px] font-medium text-muted-foreground-subtle">
|
|
1764
|
+
optional
|
|
1765
|
+
</span>
|
|
1766
|
+
)}
|
|
1767
|
+
{env.description && (
|
|
1768
|
+
<span className="text-xs text-muted-foreground">
|
|
1769
|
+
{env.description}
|
|
1770
|
+
</span>
|
|
1771
|
+
)}
|
|
1772
|
+
</div>
|
|
1773
|
+
);
|
|
1774
|
+
})}
|
|
1775
|
+
</div>
|
|
1776
|
+
)}
|
|
1337
1777
|
</Section>
|
|
1338
1778
|
);
|
|
1339
1779
|
}
|
|
1340
1780
|
|
|
1341
|
-
function TagsSection({
|
|
1781
|
+
function TagsSection({
|
|
1782
|
+
tags,
|
|
1783
|
+
editable,
|
|
1784
|
+
isSaving,
|
|
1785
|
+
saveMcpField,
|
|
1786
|
+
}: {
|
|
1787
|
+
readonly tags: readonly string[];
|
|
1788
|
+
readonly editable?: boolean;
|
|
1789
|
+
readonly isSaving?: boolean;
|
|
1790
|
+
readonly saveMcpField?: <K extends keyof import("@stigmer/sdk").McpServerInput>(
|
|
1791
|
+
field: K,
|
|
1792
|
+
value: import("@stigmer/sdk").McpServerInput[K],
|
|
1793
|
+
) => Promise<boolean>;
|
|
1794
|
+
}) {
|
|
1795
|
+
const tagRows: KeyValueRow[] = useMemo(
|
|
1796
|
+
() => tags.map((t) => ({ key: t, value: "" })),
|
|
1797
|
+
[tags],
|
|
1798
|
+
);
|
|
1799
|
+
|
|
1800
|
+
const handleTagsSave = useCallback(
|
|
1801
|
+
async (rows: KeyValueRow[]) => {
|
|
1802
|
+
if (!saveMcpField) return false;
|
|
1803
|
+
// Tags are stored as string[] on the spec but not directly on McpServerInput.
|
|
1804
|
+
// For now, save them through the full input by modifying the spec.
|
|
1805
|
+
// Tags don't have a direct field on McpServerInput, so we handle this at
|
|
1806
|
+
// a higher level if needed. For now, show read-only in edit mode.
|
|
1807
|
+
return false;
|
|
1808
|
+
},
|
|
1809
|
+
[saveMcpField],
|
|
1810
|
+
);
|
|
1811
|
+
|
|
1342
1812
|
return (
|
|
1343
|
-
<Section title=
|
|
1813
|
+
<Section title="Tags" count={tags.length}>
|
|
1344
1814
|
<div className="flex flex-wrap gap-1.5 p-3">
|
|
1345
1815
|
{tags.map((tag) => (
|
|
1346
1816
|
<span
|
|
@@ -1350,6 +1820,9 @@ function TagsSection({ tags }: { readonly tags: readonly string[] }) {
|
|
|
1350
1820
|
{tag}
|
|
1351
1821
|
</span>
|
|
1352
1822
|
))}
|
|
1823
|
+
{editable && tags.length === 0 && (
|
|
1824
|
+
<p className="text-xs text-muted-foreground italic">No tags</p>
|
|
1825
|
+
)}
|
|
1353
1826
|
</div>
|
|
1354
1827
|
</Section>
|
|
1355
1828
|
);
|
|
@@ -1364,6 +1837,19 @@ function ToolsTabContent({
|
|
|
1364
1837
|
}: {
|
|
1365
1838
|
readonly tools: readonly DiscoveredTool[];
|
|
1366
1839
|
}) {
|
|
1840
|
+
const [search, setSearch] = useState("");
|
|
1841
|
+
const [expandedTool, setExpandedTool] = useState<string | null>(null);
|
|
1842
|
+
|
|
1843
|
+
const filtered = useMemo(() => {
|
|
1844
|
+
if (!search.trim()) return tools;
|
|
1845
|
+
const q = search.toLowerCase();
|
|
1846
|
+
return tools.filter(
|
|
1847
|
+
(t) =>
|
|
1848
|
+
t.name.toLowerCase().includes(q) ||
|
|
1849
|
+
t.description?.toLowerCase().includes(q),
|
|
1850
|
+
);
|
|
1851
|
+
}, [tools, search]);
|
|
1852
|
+
|
|
1367
1853
|
if (tools.length === 0) {
|
|
1368
1854
|
return (
|
|
1369
1855
|
<div className="px-3 py-8 text-center">
|
|
@@ -1375,20 +1861,97 @@ function ToolsTabContent({
|
|
|
1375
1861
|
);
|
|
1376
1862
|
}
|
|
1377
1863
|
|
|
1864
|
+
const isFiltered = search.trim().length > 0;
|
|
1865
|
+
|
|
1378
1866
|
return (
|
|
1379
|
-
<div className="flex flex-col
|
|
1380
|
-
|
|
1381
|
-
<div
|
|
1382
|
-
<
|
|
1383
|
-
|
|
1384
|
-
|
|
1385
|
-
|
|
1386
|
-
|
|
1387
|
-
|
|
1388
|
-
|
|
1867
|
+
<div className="flex flex-col">
|
|
1868
|
+
<div className="flex items-center gap-2 px-3 pb-2">
|
|
1869
|
+
<div className="relative flex-1">
|
|
1870
|
+
<SearchIcon className="pointer-events-none absolute left-2 top-1/2 size-3.5 -translate-y-1/2 text-muted-foreground" />
|
|
1871
|
+
<input
|
|
1872
|
+
type="text"
|
|
1873
|
+
value={search}
|
|
1874
|
+
onChange={(e) => setSearch(e.target.value)}
|
|
1875
|
+
placeholder="Search tools…"
|
|
1876
|
+
aria-label="Search tools"
|
|
1877
|
+
className="w-full rounded-md border border-border bg-background py-1.5 pl-7 pr-7 text-xs text-foreground placeholder:text-muted-foreground focus:outline-none focus:ring-2 focus:ring-ring"
|
|
1878
|
+
/>
|
|
1879
|
+
{isFiltered && (
|
|
1880
|
+
<button
|
|
1881
|
+
type="button"
|
|
1882
|
+
onClick={() => setSearch("")}
|
|
1883
|
+
aria-label="Clear search"
|
|
1884
|
+
className="absolute right-2 top-1/2 -translate-y-1/2 text-muted-foreground hover:text-foreground"
|
|
1885
|
+
>
|
|
1886
|
+
<CloseIcon className="size-3" />
|
|
1887
|
+
</button>
|
|
1389
1888
|
)}
|
|
1390
1889
|
</div>
|
|
1391
|
-
|
|
1890
|
+
<span className="shrink-0 text-[10px] text-muted-foreground">
|
|
1891
|
+
{isFiltered ? `${filtered.length} of ${tools.length}` : tools.length}
|
|
1892
|
+
</span>
|
|
1893
|
+
</div>
|
|
1894
|
+
|
|
1895
|
+
{filtered.length === 0 ? (
|
|
1896
|
+
<div className="px-3 py-6 text-center">
|
|
1897
|
+
<p className="text-xs text-muted-foreground">
|
|
1898
|
+
No tools matching “{search}”
|
|
1899
|
+
</p>
|
|
1900
|
+
</div>
|
|
1901
|
+
) : (
|
|
1902
|
+
<div className="max-h-96 overflow-y-auto">
|
|
1903
|
+
<div className="flex flex-col divide-y divide-border">
|
|
1904
|
+
{filtered.map((tool) => {
|
|
1905
|
+
const isExpanded = expandedTool === tool.name;
|
|
1906
|
+
const hasSchema =
|
|
1907
|
+
tool.inputSchema != null &&
|
|
1908
|
+
Object.keys(tool.inputSchema).length > 0;
|
|
1909
|
+
|
|
1910
|
+
return (
|
|
1911
|
+
<div key={tool.name}>
|
|
1912
|
+
<button
|
|
1913
|
+
type="button"
|
|
1914
|
+
onClick={() =>
|
|
1915
|
+
setExpandedTool(isExpanded ? null : tool.name)
|
|
1916
|
+
}
|
|
1917
|
+
className="flex w-full items-start gap-2 px-3 py-2.5 text-left transition-colors hover:bg-muted-faint"
|
|
1918
|
+
aria-expanded={isExpanded}
|
|
1919
|
+
>
|
|
1920
|
+
<ChevronIcon
|
|
1921
|
+
className={cn(
|
|
1922
|
+
"mt-0.5 size-3 shrink-0 text-muted-foreground transition-transform",
|
|
1923
|
+
isExpanded && "rotate-90",
|
|
1924
|
+
)}
|
|
1925
|
+
/>
|
|
1926
|
+
<div className="min-w-0 flex-1">
|
|
1927
|
+
<code className="font-mono text-sm font-medium text-foreground">
|
|
1928
|
+
{tool.name}
|
|
1929
|
+
</code>
|
|
1930
|
+
{tool.description && (
|
|
1931
|
+
<p className="mt-0.5 text-xs text-muted-foreground">
|
|
1932
|
+
{tool.description}
|
|
1933
|
+
</p>
|
|
1934
|
+
)}
|
|
1935
|
+
</div>
|
|
1936
|
+
{hasSchema && (
|
|
1937
|
+
<span className="mt-0.5 shrink-0 rounded bg-muted px-1.5 py-0.5 text-[10px] font-medium text-muted-foreground">
|
|
1938
|
+
schema
|
|
1939
|
+
</span>
|
|
1940
|
+
)}
|
|
1941
|
+
</button>
|
|
1942
|
+
{isExpanded && hasSchema && (
|
|
1943
|
+
<div className="border-t border-border bg-muted-faint px-3 py-2">
|
|
1944
|
+
<pre className="max-h-64 overflow-auto whitespace-pre-wrap break-words rounded border border-border bg-background p-2 font-mono text-[11px] text-foreground">
|
|
1945
|
+
{JSON.stringify(tool.inputSchema, null, 2)}
|
|
1946
|
+
</pre>
|
|
1947
|
+
</div>
|
|
1948
|
+
)}
|
|
1949
|
+
</div>
|
|
1950
|
+
);
|
|
1951
|
+
})}
|
|
1952
|
+
</div>
|
|
1953
|
+
</div>
|
|
1954
|
+
)}
|
|
1392
1955
|
</div>
|
|
1393
1956
|
);
|
|
1394
1957
|
}
|
|
@@ -1402,9 +1965,33 @@ function PoliciesTabContent({
|
|
|
1402
1965
|
readonly classifiedPolicies: readonly ToolApprovalPolicy[];
|
|
1403
1966
|
readonly hasDiscoveredTools: boolean;
|
|
1404
1967
|
}) {
|
|
1405
|
-
const
|
|
1406
|
-
|
|
1407
|
-
const
|
|
1968
|
+
const [search, setSearch] = useState("");
|
|
1969
|
+
|
|
1970
|
+
const totalCount = pinnedPolicies.length + classifiedPolicies.length;
|
|
1971
|
+
const hasAnyPolicies = totalCount > 0;
|
|
1972
|
+
|
|
1973
|
+
const filteredPinned = useMemo(() => {
|
|
1974
|
+
if (!search.trim()) return pinnedPolicies;
|
|
1975
|
+
const q = search.toLowerCase();
|
|
1976
|
+
return pinnedPolicies.filter(
|
|
1977
|
+
(p) =>
|
|
1978
|
+
p.toolName.toLowerCase().includes(q) ||
|
|
1979
|
+
p.message?.toLowerCase().includes(q),
|
|
1980
|
+
);
|
|
1981
|
+
}, [pinnedPolicies, search]);
|
|
1982
|
+
|
|
1983
|
+
const filteredClassified = useMemo(() => {
|
|
1984
|
+
if (!search.trim()) return classifiedPolicies;
|
|
1985
|
+
const q = search.toLowerCase();
|
|
1986
|
+
return classifiedPolicies.filter(
|
|
1987
|
+
(p) =>
|
|
1988
|
+
p.toolName.toLowerCase().includes(q) ||
|
|
1989
|
+
p.message?.toLowerCase().includes(q),
|
|
1990
|
+
);
|
|
1991
|
+
}, [classifiedPolicies, search]);
|
|
1992
|
+
|
|
1993
|
+
const filteredTotal = filteredPinned.length + filteredClassified.length;
|
|
1994
|
+
const isFiltered = search.trim().length > 0;
|
|
1408
1995
|
|
|
1409
1996
|
if (!hasAnyPolicies) {
|
|
1410
1997
|
return (
|
|
@@ -1421,19 +2008,56 @@ function PoliciesTabContent({
|
|
|
1421
2008
|
|
|
1422
2009
|
return (
|
|
1423
2010
|
<div className="flex flex-col">
|
|
1424
|
-
|
|
1425
|
-
<
|
|
1426
|
-
|
|
1427
|
-
|
|
1428
|
-
|
|
1429
|
-
|
|
1430
|
-
|
|
1431
|
-
|
|
1432
|
-
|
|
1433
|
-
|
|
1434
|
-
|
|
1435
|
-
|
|
1436
|
-
|
|
2011
|
+
<div className="flex items-center gap-2 px-3 pb-2">
|
|
2012
|
+
<div className="relative flex-1">
|
|
2013
|
+
<SearchIcon className="pointer-events-none absolute left-2 top-1/2 size-3.5 -translate-y-1/2 text-muted-foreground" />
|
|
2014
|
+
<input
|
|
2015
|
+
type="text"
|
|
2016
|
+
value={search}
|
|
2017
|
+
onChange={(e) => setSearch(e.target.value)}
|
|
2018
|
+
placeholder="Search policies…"
|
|
2019
|
+
aria-label="Search policies"
|
|
2020
|
+
className="w-full rounded-md border border-border bg-background py-1.5 pl-7 pr-7 text-xs text-foreground placeholder:text-muted-foreground focus:outline-none focus:ring-2 focus:ring-ring"
|
|
2021
|
+
/>
|
|
2022
|
+
{isFiltered && (
|
|
2023
|
+
<button
|
|
2024
|
+
type="button"
|
|
2025
|
+
onClick={() => setSearch("")}
|
|
2026
|
+
aria-label="Clear search"
|
|
2027
|
+
className="absolute right-2 top-1/2 -translate-y-1/2 text-muted-foreground hover:text-foreground"
|
|
2028
|
+
>
|
|
2029
|
+
<CloseIcon className="size-3" />
|
|
2030
|
+
</button>
|
|
2031
|
+
)}
|
|
2032
|
+
</div>
|
|
2033
|
+
<span className="shrink-0 text-[10px] text-muted-foreground">
|
|
2034
|
+
{isFiltered ? `${filteredTotal} of ${totalCount}` : totalCount}
|
|
2035
|
+
</span>
|
|
2036
|
+
</div>
|
|
2037
|
+
|
|
2038
|
+
{filteredTotal === 0 ? (
|
|
2039
|
+
<div className="px-3 py-6 text-center">
|
|
2040
|
+
<p className="text-xs text-muted-foreground">
|
|
2041
|
+
No policies matching “{search}”
|
|
2042
|
+
</p>
|
|
2043
|
+
</div>
|
|
2044
|
+
) : (
|
|
2045
|
+
<div className="max-h-96 overflow-y-auto">
|
|
2046
|
+
{filteredPinned.length > 0 && (
|
|
2047
|
+
<PolicyGroup
|
|
2048
|
+
icon={<PinIcon className="size-3.5" />}
|
|
2049
|
+
label="Pinned"
|
|
2050
|
+
policies={filteredPinned}
|
|
2051
|
+
/>
|
|
2052
|
+
)}
|
|
2053
|
+
{filteredClassified.length > 0 && (
|
|
2054
|
+
<PolicyGroup
|
|
2055
|
+
icon={<SparklesIcon className="size-3.5" />}
|
|
2056
|
+
label="Auto-classified"
|
|
2057
|
+
policies={filteredClassified}
|
|
2058
|
+
/>
|
|
2059
|
+
)}
|
|
2060
|
+
</div>
|
|
1437
2061
|
)}
|
|
1438
2062
|
</div>
|
|
1439
2063
|
);
|
|
@@ -1466,7 +2090,10 @@ function PolicyGroup({
|
|
|
1466
2090
|
<code className="font-mono text-sm font-medium text-foreground">
|
|
1467
2091
|
{policy.toolName}
|
|
1468
2092
|
</code>
|
|
1469
|
-
<
|
|
2093
|
+
<span className="inline-flex items-center gap-1 rounded bg-amber-500/10 px-1.5 py-0.5 text-[10px] font-medium text-amber-600 dark:text-amber-400">
|
|
2094
|
+
<ShieldIcon className="size-2.5" />
|
|
2095
|
+
requires approval
|
|
2096
|
+
</span>
|
|
1470
2097
|
</div>
|
|
1471
2098
|
{policy.message && (
|
|
1472
2099
|
<p className="mt-0.5 text-xs text-muted-foreground">
|
|
@@ -1484,24 +2111,6 @@ function PolicyGroup({
|
|
|
1484
2111
|
// Shared layout primitives
|
|
1485
2112
|
// ---------------------------------------------------------------------------
|
|
1486
2113
|
|
|
1487
|
-
function Section({
|
|
1488
|
-
title,
|
|
1489
|
-
children,
|
|
1490
|
-
}: {
|
|
1491
|
-
readonly title: string;
|
|
1492
|
-
readonly children: React.ReactNode;
|
|
1493
|
-
}) {
|
|
1494
|
-
return (
|
|
1495
|
-
<section>
|
|
1496
|
-
<h3 className="mb-2 text-xs font-medium uppercase tracking-wider text-muted-foreground">
|
|
1497
|
-
{title}
|
|
1498
|
-
</h3>
|
|
1499
|
-
<div className="overflow-hidden rounded-lg border border-border">
|
|
1500
|
-
{children}
|
|
1501
|
-
</div>
|
|
1502
|
-
</section>
|
|
1503
|
-
);
|
|
1504
|
-
}
|
|
1505
2114
|
|
|
1506
2115
|
function Dot() {
|
|
1507
2116
|
return (
|
|
@@ -1768,6 +2377,58 @@ function ExternalLinkIcon({ className }: { readonly className?: string }) {
|
|
|
1768
2377
|
);
|
|
1769
2378
|
}
|
|
1770
2379
|
|
|
2380
|
+
function SearchIcon({ className }: { readonly className?: string }) {
|
|
2381
|
+
return (
|
|
2382
|
+
<svg
|
|
2383
|
+
className={className}
|
|
2384
|
+
viewBox="0 0 16 16"
|
|
2385
|
+
fill="none"
|
|
2386
|
+
stroke="currentColor"
|
|
2387
|
+
strokeWidth="1.5"
|
|
2388
|
+
strokeLinecap="round"
|
|
2389
|
+
strokeLinejoin="round"
|
|
2390
|
+
aria-hidden="true"
|
|
2391
|
+
>
|
|
2392
|
+
<circle cx="7" cy="7" r="4.5" />
|
|
2393
|
+
<path d="m10.5 10.5 3 3" />
|
|
2394
|
+
</svg>
|
|
2395
|
+
);
|
|
2396
|
+
}
|
|
2397
|
+
|
|
2398
|
+
function CloseIcon({ className }: { readonly className?: string }) {
|
|
2399
|
+
return (
|
|
2400
|
+
<svg
|
|
2401
|
+
className={className}
|
|
2402
|
+
viewBox="0 0 16 16"
|
|
2403
|
+
fill="none"
|
|
2404
|
+
stroke="currentColor"
|
|
2405
|
+
strokeWidth="2"
|
|
2406
|
+
strokeLinecap="round"
|
|
2407
|
+
strokeLinejoin="round"
|
|
2408
|
+
aria-hidden="true"
|
|
2409
|
+
>
|
|
2410
|
+
<path d="m4 4 8 8M12 4l-8 8" />
|
|
2411
|
+
</svg>
|
|
2412
|
+
);
|
|
2413
|
+
}
|
|
2414
|
+
|
|
2415
|
+
function ChevronIcon({ className }: { readonly className?: string }) {
|
|
2416
|
+
return (
|
|
2417
|
+
<svg
|
|
2418
|
+
className={className}
|
|
2419
|
+
viewBox="0 0 16 16"
|
|
2420
|
+
fill="none"
|
|
2421
|
+
stroke="currentColor"
|
|
2422
|
+
strokeWidth="2"
|
|
2423
|
+
strokeLinecap="round"
|
|
2424
|
+
strokeLinejoin="round"
|
|
2425
|
+
aria-hidden="true"
|
|
2426
|
+
>
|
|
2427
|
+
<path d="m6 4 4 4-4 4" />
|
|
2428
|
+
</svg>
|
|
2429
|
+
);
|
|
2430
|
+
}
|
|
2431
|
+
|
|
1771
2432
|
function Spinner() {
|
|
1772
2433
|
return (
|
|
1773
2434
|
<svg
|