@jini-ai/ui 0.5.5 → 0.5.6
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/CHANGELOG.md +4 -0
- package/dist/core/theme/validation.js +40 -38
- package/dist/features/a2ui/renderer.js +15 -13
- package/dist/features/about/react/components/AboutTab.js +64 -34
- package/dist/features/about/rules.d.ts +2 -2
- package/dist/features/about/rules.js +156 -129
- package/dist/features/admin-widgets/components/ImagePreviewModal.d.ts +4 -3
- package/dist/features/admin-widgets/components/ImagePreviewModal.js +6 -10
- package/dist/features/admin-widgets/components/InfoTip.d.ts +3 -2
- package/dist/features/admin-widgets/components/InfoTip.hooks.js +2 -0
- package/dist/features/admin-widgets/components/InfoTip.js +34 -7
- package/dist/features/admin-widgets/components/InfoTip.rules.d.ts +13 -0
- package/dist/features/admin-widgets/components/InfoTip.rules.js +43 -10
- package/dist/features/admin-widgets/components/Lightbox/Lightbox.d.ts +30 -0
- package/dist/features/admin-widgets/components/Lightbox/Lightbox.hooks.d.ts +40 -0
- package/dist/features/admin-widgets/components/Lightbox/Lightbox.hooks.js +128 -0
- package/dist/features/admin-widgets/components/Lightbox/Lightbox.js +18 -0
- package/dist/features/admin-widgets/components/MiddleTruncate.d.ts +14 -0
- package/dist/features/admin-widgets/components/MiddleTruncate.js +12 -0
- package/dist/features/admin-widgets/components/MiddleTruncate.rules.d.ts +20 -0
- package/dist/features/admin-widgets/components/MiddleTruncate.rules.js +21 -0
- package/dist/features/admin-widgets/components/ScrollJump/ScrollJump.d.ts +18 -0
- package/dist/features/admin-widgets/components/ScrollJump/ScrollJump.hooks.d.ts +16 -0
- package/dist/features/admin-widgets/components/ScrollJump/ScrollJump.hooks.js +45 -0
- package/dist/features/admin-widgets/components/ScrollJump/ScrollJump.js +18 -0
- package/dist/features/admin-widgets/components/ScrollJump/ScrollJump.rules.d.ts +32 -0
- package/dist/features/admin-widgets/components/ScrollJump/ScrollJump.rules.js +26 -0
- package/dist/features/admin-widgets/components/SuggestInput/SuggestInput.hooks.js +29 -14
- package/dist/features/admin-widgets/index.d.ts +14 -2
- package/dist/features/admin-widgets/index.js +7 -1
- package/dist/features/admin-widgets/styles/admin-widgets.css +1 -0
- package/dist/features/asset-grid/react/components/AssetCard.js +7 -1
- package/dist/features/asset-grid/react/components/AssetGrid.d.ts +1 -1
- package/dist/features/asset-grid/react/components/AssetGrid.js +38 -18
- package/dist/features/asset-grid/react/components/useAssetGridFilters.d.ts +21 -0
- package/dist/features/asset-grid/react/components/useAssetGridFilters.js +19 -0
- package/dist/features/asset-grid/react/hooks/useAssetGridKeyboardShortcuts.js +16 -11
- package/dist/features/asset-grid/react/hooks/useAssetGridLiveUpdates.d.ts +2 -0
- package/dist/features/asset-grid/react/hooks/useAssetGridLiveUpdates.js +35 -11
- package/dist/features/asset-tree-browser/react/components/AssetTreeBrowser.d.ts +6 -6
- package/dist/features/asset-tree-browser/react/components/AssetTreeBrowser.js +10 -129
- package/dist/features/asset-tree-browser/react/components/AssetTreeBrowserParts.d.ts +50 -0
- package/dist/features/asset-tree-browser/react/components/AssetTreeBrowserParts.js +95 -0
- package/dist/features/asset-tree-browser/react/components/useAssetTreeBrowserController.d.ts +56 -0
- package/dist/features/asset-tree-browser/react/components/useAssetTreeBrowserController.js +80 -0
- package/dist/features/asset-tree-browser/rules.js +40 -22
- package/dist/features/browser-chrome/rules.js +74 -70
- package/dist/features/charts/browser.js +11 -5
- package/dist/features/charts/react.js +2 -2
- package/dist/features/charts/table.js +2 -2
- package/dist/features/command-palette/react/hooks/useCommandPalette.js +3 -9
- package/dist/features/connectors/ConnectorsBrowser.d.ts +4 -4
- package/dist/features/connectors/ConnectorsBrowser.js +26 -14
- package/dist/features/connectors/components/ConnectorCard.js +67 -38
- package/dist/features/connectors/components/ConnectorDetailDrawer.js +62 -31
- package/dist/features/connectors/components/ConnectorGrid.js +11 -6
- package/dist/features/connectors/hooks/useConnectorAuthorization.js +6 -0
- package/dist/features/connectors/hooks/useConnectorCatalog.d.ts +2 -0
- package/dist/features/connectors/hooks/useConnectorCatalog.js +32 -13
- package/dist/features/connectors/hooks/useWiredConnectorsBrowser.d.ts +3 -3
- package/dist/features/connectors/rules.d.ts +8 -1
- package/dist/features/connectors/rules.js +42 -20
- package/dist/features/connectors/types.d.ts +11 -0
- package/dist/features/execution/constants.d.ts +4 -10
- package/dist/features/execution/constants.js +9 -94
- package/dist/features/execution/react/components/ByokProviderForm.d.ts +2 -4
- package/dist/features/execution/react/components/ByokProviderForm.js +140 -43
- package/dist/features/execution/react/components/ExecutionTab.d.ts +1 -2
- package/dist/features/execution/react/components/ExecutionTab.js +52 -30
- package/dist/features/execution/react/components/LocalCliAgentCard.js +12 -3
- package/dist/features/execution/react/components/LocalCliAgentList.js +14 -3
- package/dist/features/execution/react/components/LocalCliAgentSettings.js +14 -3
- package/dist/features/execution/react/hooks/useLocalCliAgentCard.js +54 -36
- package/dist/features/execution/react/hooks/useReasoningControl.js +114 -78
- package/dist/features/execution/rules.d.ts +2 -2
- package/dist/features/execution/rules.js +31 -15
- package/dist/features/execution/types.d.ts +4 -42
- package/dist/features/execution/types.js +0 -17
- package/dist/features/external-mcp/react/components/ExternalMcpTab.d.ts +6 -2
- package/dist/features/external-mcp/react/components/ExternalMcpTab.js +9 -2
- package/dist/features/file-dropzone/react/components/FileDropzone.js +24 -25
- package/dist/features/file-dropzone/react/components/FileDropzoneLightbox.d.ts +2 -2
- package/dist/features/file-dropzone/react/components/FileDropzoneLightbox.js +35 -30
- package/dist/features/file-dropzone/react/components/FileDropzoneThumbnailGrid.js +30 -24
- package/dist/features/file-dropzone/react/components/FileDropzoneZone.d.ts +14 -0
- package/dist/features/file-dropzone/react/components/FileDropzoneZone.js +26 -0
- package/dist/features/html-editor/canvas-content-wrapper.js +13 -13
- package/dist/features/html-editor/canvas-embed-placeholders.js +46 -37
- package/dist/features/html-editor/css.js +76 -69
- package/dist/features/html-editor/editor-blocks.js +47 -33
- package/dist/features/html-editor/editor-serialization.js +6 -5
- package/dist/features/html-editor/protected-elements.js +39 -28
- package/dist/features/html-editor/react/hooks/useInteractiveHtmlEditor.js +4 -4
- package/dist/features/html-editor/source-splice.js +51 -30
- package/dist/features/i18n/dictionaries/settings-dialog.ja.js +1 -0
- package/dist/features/i18n/dictionaries/settings-dialog.zh-CN.js +1 -0
- package/dist/features/i18n/dictionaries/settings-dialog.zh-TW.js +1 -0
- package/dist/features/i18n/locale.js +20 -16
- package/dist/features/iframe-pool/react/dom-sync.js +8 -6
- package/dist/features/integrations/react/components/CodexInstallToggleButton.js +19 -4
- package/dist/features/integrations/react/components/IntegrationsTab.js +60 -14
- package/dist/features/interactive-ui/interactive-ui.css +1 -1
- package/dist/features/interactive-ui/providers/shadcn/data-table.js +10 -7
- package/dist/features/lexical-rich-text-editor/mention-parser.js +60 -57
- package/dist/features/lexical-rich-text-editor/react/hooks/useKeyboardCommands.js +33 -38
- package/dist/features/lexical-rich-text-editor/rules.js +87 -74
- package/dist/features/lexical-rich-text-editor/serialize.js +27 -25
- package/dist/features/mcp-ui/secret-card.js +111 -61
- package/dist/features/mcp-ui/surfaces/confirmation.js +39 -21
- package/dist/features/mcp-ui/surfaces/document.d.ts +1 -1
- package/dist/features/mcp-ui/surfaces/document.js +10 -2
- package/dist/features/mcp-ui/surfaces/fields.js +30 -50
- package/dist/features/mcp-ui/surfaces/form.d.ts +6 -0
- package/dist/features/mcp-ui/surfaces/form.js +43 -21
- package/dist/features/mcp-ui/surfaces/outcome.js +30 -20
- package/dist/features/mcp-ui/surfaces/text-input.js +33 -21
- package/dist/features/mcp-ui/surfaces/tokens.d.ts +6 -1
- package/dist/features/mcp-ui/surfaces/tokens.js +5 -2
- package/dist/features/media-providers/constants.d.ts +1 -0
- package/dist/features/media-providers/constants.js +2 -81
- package/dist/features/media-providers/index.d.ts +1 -1
- package/dist/features/media-providers/ports.d.ts +2 -0
- package/dist/features/media-providers/react/components/MediaProviderCard.d.ts +22 -0
- package/dist/features/media-providers/react/components/MediaProviderCard.js +50 -0
- package/dist/features/media-providers/react/components/MediaProvidersTab.d.ts +5 -6
- package/dist/features/media-providers/react/components/MediaProvidersTab.js +40 -72
- package/dist/features/media-providers/react/components/media-providers-tab-labels.d.ts +11 -0
- package/dist/features/media-providers/react/components/media-providers-tab-labels.js +57 -0
- package/dist/features/media-providers/react/hooks/useMediaProvidersTab.d.ts +4 -2
- package/dist/features/media-providers/react/hooks/useMediaProvidersTab.js +37 -23
- package/dist/features/media-providers/rules.js +17 -10
- package/dist/features/media-providers/types.d.ts +4 -22
- package/dist/features/media-providers/types.js +3 -8
- package/dist/features/memory/formatters.js +127 -92
- package/dist/features/memory/react/components/MemoryConnectedPanel.js +92 -36
- package/dist/features/memory/react/components/MemoryList.js +37 -18
- package/dist/features/memory/react/hooks/useMemoryExtractions.store.js +42 -36
- package/dist/features/notifications/react/components/NotificationsTab.js +28 -28
- package/dist/features/observability/long-task.d.ts +0 -12
- package/dist/features/observability/long-task.js +15 -19
- package/dist/features/observability/resource-error.d.ts +0 -10
- package/dist/features/observability/resource-error.js +18 -13
- package/dist/features/observability/stuck-run.js +10 -6
- package/dist/features/observability/telemetry-url.d.ts +6 -0
- package/dist/features/observability/telemetry-url.js +16 -0
- package/dist/features/observability/white-screen.js +12 -24
- package/dist/features/panel-kit/fetch-query/adapter.react.d.ts +2 -2
- package/dist/features/panel-kit/fetch-query/adapter.react.js +4 -2
- package/dist/features/panel-kit/fetch-query/adapter.tanstack.js +46 -33
- package/dist/features/panel-kit/helpers/standing-draft-local-backup.js +3 -1
- package/dist/features/panel-kit/hooks/use-settings-slice.hooks.js +3 -1
- package/dist/features/privacy/react/components/PrivacyTab.js +24 -13
- package/dist/features/progress-card/components/ProgressCard.js +7 -3
- package/dist/features/progress-card/reference-adapters.js +59 -54
- package/dist/features/project-locations/react/components/ProjectLocationsTab.js +24 -15
- package/dist/features/project-locations/react/hooks/useProjectLocationsTab.d.ts +8 -0
- package/dist/features/project-locations/react/hooks/useProjectLocationsTab.js +31 -23
- package/dist/features/resource-dashboard/react/components/ResourceBoard.js +6 -47
- package/dist/features/resource-dashboard/react/components/ResourceBoardView.d.ts +2 -2
- package/dist/features/resource-dashboard/react/components/ResourceBoardView.js +3 -6
- package/dist/features/resource-dashboard/react/components/ResourceBoardViewParts.d.ts +15 -0
- package/dist/features/resource-dashboard/react/components/ResourceBoardViewParts.js +35 -0
- package/dist/features/resource-dashboard/react/components/ResourceCard.js +5 -16
- package/dist/features/resource-dashboard/react/components/ResourceCardParts.d.ts +34 -0
- package/dist/features/resource-dashboard/react/components/ResourceCardParts.js +34 -0
- package/dist/features/resource-dashboard/react/components/ResourceRowList.js +3 -1
- package/dist/features/resource-dashboard/react/components/ResourceRowListItem.js +2 -2
- package/dist/features/resource-dashboard/react/components/ResourceRowListItemParts.d.ts +19 -0
- package/dist/features/resource-dashboard/react/components/ResourceRowListItemParts.js +11 -0
- package/dist/features/resource-dashboard/react/components/ResourceRowListView.d.ts +1 -1
- package/dist/features/resource-dashboard/react/components/ResourceRowListView.js +4 -4
- package/dist/features/resource-dashboard/react/components/ResourceRowListViewParts.d.ts +10 -0
- package/dist/features/resource-dashboard/react/components/ResourceRowListViewParts.js +20 -0
- package/dist/features/resource-dashboard/react/components/resourceBoardProps.d.ts +48 -0
- package/dist/features/resource-dashboard/react/components/resourceBoardProps.js +70 -0
- package/dist/features/resource-dashboard/react/components/resourceRowListProps.d.ts +19 -0
- package/dist/features/resource-dashboard/react/components/resourceRowListProps.js +14 -0
- package/dist/features/resource-dashboard/react/components/translatedErrorLabelProps.d.ts +16 -0
- package/dist/features/resource-dashboard/react/components/translatedErrorLabelProps.js +13 -0
- package/dist/features/resource-dashboard/rules.js +2 -8
- package/dist/features/sketch-editor/dom.js +150 -99
- package/dist/features/sketch-editor/react/components/SketchEditor.js +26 -15
- package/dist/features/skills/react/components/SkillDraftForm.js +13 -19
- package/dist/features/skills/react/components/SkillDraftForm.labels.d.ts +31 -0
- package/dist/features/skills/react/components/SkillDraftForm.labels.js +54 -0
- package/dist/features/skills/react/components/SkillRow.js +38 -18
- package/dist/features/skills/react/components/SkillRow.labels.d.ts +7 -0
- package/dist/features/skills/react/components/SkillRow.labels.js +18 -0
- package/dist/features/skills/react/components/SkillsTab.js +24 -14
- package/dist/features/skills/react/components/SkillsTab.labels.d.ts +7 -0
- package/dist/features/skills/react/components/SkillsTab.labels.js +11 -0
- package/dist/features/skills/rules.js +32 -23
- package/dist/features/source-config-list/agent-handles.js +2 -1
- package/dist/features/source-config-list/dependencies.js +53 -49
- package/dist/features/source-config-list/index.d.ts +3 -3
- package/dist/features/source-config-list/react/components/SourceConfigAddForm.d.ts +6 -5
- package/dist/features/source-config-list/react/components/SourceConfigAddForm.js +38 -7
- package/dist/features/source-config-list/react/components/SourceConfigField.js +69 -25
- package/dist/features/source-config-list/react/components/SourceConfigItemCard.d.ts +6 -5
- package/dist/features/source-config-list/react/components/SourceConfigItemCard.js +76 -20
- package/dist/features/source-config-list/react/components/SourceConfigListView.d.ts +5 -3
- package/dist/features/source-config-list/react/components/SourceConfigListView.js +33 -3
- package/dist/features/source-config-list/react/components/SourceConfigTestControl.js +17 -1
- package/dist/features/source-config-list/react/components/SourceConfigTrustOptions.d.ts +11 -0
- package/dist/features/source-config-list/react/components/SourceConfigTrustOptions.js +12 -0
- package/dist/features/source-config-list/types.d.ts +14 -0
- package/dist/features/tab-launcher-menu/react/components/TabLauncherMenu.js +25 -1
- package/dist/features/tab-launcher-menu/react/hooks/useTabLauncherMenu.js +15 -16
- package/dist/features/tab-strip/react/components/TabBar.js +8 -1
- package/dist/features/tabbed-dialog/react/components/TabbedDialog.js +8 -30
- package/dist/features/tabbed-dialog/react/components/TabbedDialogChrome.d.ts +15 -0
- package/dist/features/tabbed-dialog/react/components/TabbedDialogChrome.js +8 -0
- package/dist/features/tabbed-dialog/react/components/TabbedDialogHeader.d.ts +12 -0
- package/dist/features/tabbed-dialog/react/components/TabbedDialogHeader.js +6 -0
- package/dist/features/tabbed-dialog/react/components/TabbedDialogSidebar.d.ts +27 -0
- package/dist/features/tabbed-dialog/react/components/TabbedDialogSidebar.js +12 -0
- package/dist/features/tabbed-dialog/react/components/tabbedDialogView.d.ts +43 -0
- package/dist/features/tabbed-dialog/react/components/tabbedDialogView.js +59 -0
- package/dist/features/version-manager/dependencies.d.ts +3 -1
- package/dist/features/version-manager/dependencies.js +3 -2
- package/dist/features/version-manager/react/components/VersionManagerModal.js +10 -6
- package/dist/features/version-manager/react/hooks/useVersionManager.js +7 -4
- package/dist/features/viewer-shell/react/components/CommentSidePanel.js +103 -50
- package/dist/features/viewer-shell/react/components/MarkdownSplitPane.js +28 -8
- package/dist/features/viewer-shell/react/hooks/useCommentReorder.js +22 -16
- package/dist/features/viewer-shell/rules.js +19 -23
- package/dist/react/components/CustomSelect.d.ts +38 -1
- package/dist/react/components/CustomSelect.js +94 -38
- package/dist/react/components/OnboardingDropdown.js +20 -8
- package/dist/react/components/RemixIcon.stylesheet.js +3 -1
- package/dist/react/components/Toast.js +13 -2
- package/dist/react/components/TooltipLayer.js +5 -14
- package/dist/react/components/WorkingDirPicker.js +78 -50
- package/dist/react/components/remixicon-font-recovery.js +38 -30
- package/dist/react/components/select-popover.d.ts +8 -6
- package/dist/react/components/select-popover.js +33 -29
- package/dist/react/mcp-ui/McpUiHost.d.ts +1 -1
- package/dist/react/mcp-ui/McpUiHost.js +10 -11
- package/dist/react/mcp-ui/host-message-source.d.ts +14 -2
- package/dist/react/mcp-ui/host-message-source.js +15 -5
- package/dist/react/mcp-ui/mcp-ui-host-frame.d.ts +41 -0
- package/dist/react/mcp-ui/mcp-ui-host-frame.js +39 -0
- package/dist/renderers/annotation-canvas/react/components/AnnotationCanvas.js +97 -69
- package/dist/renderers/preview-modal-shell/react/components/PreviewModalShell.js +59 -30
- package/dist/renderers/react/components/ArtifactView.js +9 -6
- package/dist/renderers/srcdoc/build.d.ts +4 -1
- package/dist/renderers/srcdoc/build.js +62 -48
- package/dist/styles/admin.css +29 -14
- package/dist/styles/lightbox.css +142 -0
- package/dist/styles/variables.css +128 -0
- package/dist/theme/apply.js +9 -5
- package/dist/utils/auto-open-file.d.ts +2 -1
- package/dist/utils/auto-open-file.js +69 -85
- package/dist/utils/markdown-scroll-sync.js +108 -87
- package/dist/utils/polygon-selection.js +25 -26
- package/dist/utils/smooth-scroll-to-top.d.ts +1 -1
- package/dist/utils/smooth-scroll-to-top.js +2 -32
- package/dist/utils/sse.js +26 -26
- package/dist/utils/unit-bezier.d.ts +7 -0
- package/dist/utils/unit-bezier.js +38 -0
- package/package.json +7 -10
- package/dist/features/admin-widgets/components/ImagePreviewModal.hooks.d.ts +0 -13
- package/dist/features/admin-widgets/components/ImagePreviewModal.hooks.js +0 -46
|
@@ -2,38 +2,19 @@ import { jsx as _jsx, jsxs as _jsxs, Fragment as _Fragment } from "react/jsx-run
|
|
|
2
2
|
import { useEffect, useRef } from 'react';
|
|
3
3
|
import { agentHandleProps } from '@jini-ai/agentic';
|
|
4
4
|
import { useT } from '../../i18n/index.js';
|
|
5
|
-
import { getConnectorDisplayToolCount, getDisplayableConnectorAccountLabel, statusLabel, toolsBadgeTranslation, } from '../rules.js';
|
|
5
|
+
import { connectorActionFlags, getConnectorDisplayToolCount, getDisplayableConnectorAccountLabel, statusLabel, toolsBadgeTranslation, } from '../rules.js';
|
|
6
6
|
import { Icon } from '../../../react/components/Icon.js';
|
|
7
7
|
import { ConnectorLogo } from './ConnectorLogo.js';
|
|
8
|
-
|
|
9
|
-
* Modal detail drawer with a paginated tool list. Keeps its own
|
|
10
|
-
* escape-key-to-close and body-scroll-lock behavior inline (standard modal
|
|
11
|
-
* a11y idioms, not business/transport logic) — see
|
|
12
|
-
* `packages/ui/source-map.md`'s purity-check note for why these two
|
|
13
|
-
* `document`/`window` touches were kept here rather than routed through
|
|
14
|
-
* `dependencies.ts`.
|
|
15
|
-
*/
|
|
16
|
-
export function ConnectorDetailDrawer({ connector, disabled, pendingAction, authorizationPending, authorizationCancelFailed, authorizationError, toolsPreviewLoading, toolsLoaded, onClose, onConnect, onDisconnect, onCancelAuthorization, onLoadMoreTools, onOpenExternalUrl, getCategoryLabel = (category) => category, getDisplayableAccountLabel = getDisplayableConnectorAccountLabel, cancelFailedMessage, continueInBrowserLabel, agentHandle, }) {
|
|
8
|
+
function ConnectorDrawerHead({ connector, categoryLabel, isAuthorizationPending, toolsLoaded, closeBtnRef, onClose, agentHandle, }) {
|
|
17
9
|
const t = useT();
|
|
18
|
-
const
|
|
19
|
-
const
|
|
20
|
-
const isConnected = connector.status === 'connected';
|
|
21
|
-
const isConnecting = pendingAction === 'connect';
|
|
22
|
-
const isDisconnecting = pendingAction === 'disconnect';
|
|
23
|
-
const isAuthorizationPending = !isConnected && authorizationPending !== undefined;
|
|
24
|
-
const isPending = pendingAction !== null || isAuthorizationPending;
|
|
25
|
-
const canConnect = !disabled && !isPending && connector.status === 'available';
|
|
26
|
-
const canDisconnect = !disabled && !isPending && isConnected;
|
|
27
|
-
const accountLabel = getDisplayableAccountLabel(connector);
|
|
28
|
-
const actualToolCount = connector.tools.length;
|
|
29
|
-
const toolCount = getConnectorDisplayToolCount(connector);
|
|
30
|
-
const isLoadingTools = toolsPreviewLoading || !toolsLoaded;
|
|
31
|
-
const toolDetailsUnavailable = toolsLoaded && actualToolCount === 0 && toolCount > 0;
|
|
32
|
-
const showToolsBadge = connector.toolCount !== undefined || actualToolCount > 0 || toolsLoaded;
|
|
33
|
-
const closeBtnRef = useRef(null);
|
|
34
|
-
const categoryLabel = getCategoryLabel(connector.category);
|
|
35
|
-
const toolsBadge = toolsBadgeTranslation(toolCount);
|
|
10
|
+
const showToolsBadge = connector.toolCount !== undefined || connector.tools.length > 0 || toolsLoaded;
|
|
11
|
+
const toolsBadge = toolsBadgeTranslation(getConnectorDisplayToolCount(connector));
|
|
36
12
|
const toolsBadgeLabel = t(toolsBadge.key, toolsBadge.vars);
|
|
13
|
+
const statusTone = isAuthorizationPending ? 'pending' : connector.status;
|
|
14
|
+
return (_jsxs("header", { className: "connector-drawer-head", children: [_jsx(ConnectorLogo, { connectorId: connector.id, connectorName: connector.name, logoUrl: connector.logoUrl, size: "lg" }), _jsxs("div", { className: "connector-drawer-titles", children: [_jsxs("div", { className: "connector-drawer-eyebrow", children: [_jsx("span", { children: categoryLabel }), _jsx("span", { className: "connector-meta-dot", "aria-hidden": true, children: "\u00B7" }), _jsx("span", { children: connector.provider })] }), _jsx("h2", { id: "connector-drawer-title", children: connector.name }), _jsxs("div", { className: "connector-drawer-status", children: [_jsxs("span", { className: `connector-status-pill status-${statusTone}`, children: [_jsx("span", { className: "connector-status-dot", "aria-hidden": true }), isAuthorizationPending ? t('Authorization pending') : t(statusLabel(connector.status))] }), showToolsBadge ? (_jsx("span", { className: "connector-drawer-tool-count-chip", title: toolsBadgeLabel, children: _jsx("span", { children: toolsBadgeLabel }) })) : null] })] }), _jsx("button", { ref: closeBtnRef, type: "button", className: "ghost connector-drawer-close", onClick: onClose, "aria-label": t('Close'), "data-testid": "connector-drawer-close", ...agentHandleProps({}, { base: agentHandle, action: 'close', role: 'button', label: t('Close') }), children: _jsx(Icon, { name: "close", size: 14 }) })] }));
|
|
15
|
+
}
|
|
16
|
+
function ConnectorDrawerAbout({ description, isAuthorizationPending, redirectUrl, continueInBrowserLabel, onOpenExternalUrl, }) {
|
|
17
|
+
const t = useT();
|
|
37
18
|
function continueAuthorization(event) {
|
|
38
19
|
event.stopPropagation();
|
|
39
20
|
// `continueAuthorization`'s only call site (the "continue in browser"
|
|
@@ -43,8 +24,44 @@ export function ConnectorDetailDrawer({ connector, disabled, pendingAction, auth
|
|
|
43
24
|
// re-check here was dead code for every real click, removed rather
|
|
44
25
|
// than tested around (same pattern as this package's `ConnectorCard.tsx`
|
|
45
26
|
// precedent; see packages/ui/source-map.md's 2026-07-22 dated entry).
|
|
46
|
-
onOpenExternalUrl?.(
|
|
27
|
+
onOpenExternalUrl?.(redirectUrl);
|
|
47
28
|
}
|
|
29
|
+
return (_jsxs("section", { className: "connector-drawer-section", children: [_jsx("h3", { className: "connector-drawer-section-title", children: t('About') }), _jsx("p", { className: "connector-drawer-description", children: description }), isAuthorizationPending ? (_jsxs("div", { className: "connector-authorization-block", role: "status", children: [_jsx("p", { className: "connector-authorization-hint", children: t('Authorization in progress. It should finish shortly.') }), redirectUrl ? (_jsx("button", { type: "button", className: "connector-authorization-link", onClick: continueAuthorization, children: continueInBrowserLabel ?? t('Continue in browser') })) : null] })) : null] }));
|
|
30
|
+
}
|
|
31
|
+
function ConnectorDrawerAlert({ message }) {
|
|
32
|
+
return (_jsx("p", { className: "connector-authorization-hint connector-authorization-error", role: "alert", children: message }));
|
|
33
|
+
}
|
|
34
|
+
function ConnectorDrawerDetails({ connector, categoryLabel, accountLabel, flags, onDisconnect, agentHandle }) {
|
|
35
|
+
const t = useT();
|
|
36
|
+
const { isDisconnecting } = flags;
|
|
37
|
+
return (_jsxs("section", { className: "connector-drawer-section", children: [_jsxs("div", { className: "connector-drawer-section-head", children: [_jsx("h3", { className: "connector-drawer-section-title", children: t('Details') }), flags.isConnected ? (_jsxs("button", { type: "button", className: `ghost connector-drawer-inline-action connector-action is-disconnect${isDisconnecting ? ' is-loading' : ''}`, disabled: !flags.canDisconnect, "aria-busy": isDisconnecting || undefined, onClick: () => onDisconnect(connector.id), ...agentHandleProps({}, { base: agentHandle, action: 'disconnect', role: 'button', label: t('Disconnect') }), children: [isDisconnecting ? _jsx(Icon, { name: "spinner", size: 12 }) : null, _jsx("span", { children: t('Disconnect') })] })) : null] }), _jsxs("dl", { className: "connector-drawer-details", children: [_jsxs("div", { children: [_jsx("dt", { children: t('Status') }), _jsx("dd", { children: t(statusLabel(connector.status)) })] }), _jsxs("div", { children: [_jsx("dt", { children: t('Category') }), _jsx("dd", { children: categoryLabel })] }), _jsxs("div", { children: [_jsx("dt", { children: t('Provider') }), _jsx("dd", { children: connector.provider })] }), accountLabel ? (_jsxs("div", { children: [_jsx("dt", { children: t('Account') }), _jsx("dd", { children: accountLabel })] })) : null, connector.lastError ? (_jsxs("div", { className: "connector-drawer-details-error", children: [_jsx("dt", { children: t('Error') }), _jsx("dd", { children: connector.lastError })] })) : null] })] }));
|
|
38
|
+
}
|
|
39
|
+
function ConnectorDrawerTool({ tool }) {
|
|
40
|
+
return (_jsxs("li", { className: "connector-drawer-tool", children: [_jsxs("div", { className: "connector-drawer-tool-head", children: [_jsx("span", { className: "connector-drawer-tool-title", children: tool.title || tool.name }), _jsx("span", { className: `connector-drawer-tool-badge side-${tool.safety.sideEffect}`, title: tool.safety.reason, children: tool.safety.sideEffect })] }), tool.description ? _jsx("p", { className: "connector-drawer-tool-desc", children: tool.description }) : null, _jsx("code", { className: "connector-drawer-tool-name", children: tool.name })] }));
|
|
41
|
+
}
|
|
42
|
+
/** The tools section body: loading, unavailable, empty, or the list with an optional load-more. */
|
|
43
|
+
function ConnectorDrawerToolsBody({ connector, toolsPreviewLoading, toolsLoaded, onLoadMoreTools }) {
|
|
44
|
+
const t = useT();
|
|
45
|
+
const actualToolCount = connector.tools.length;
|
|
46
|
+
const toolCount = getConnectorDisplayToolCount(connector);
|
|
47
|
+
if (toolsPreviewLoading || !toolsLoaded) {
|
|
48
|
+
return (_jsxs("p", { className: "connector-drawer-empty", children: [_jsx(Icon, { name: "spinner", size: 12 }), " ", t('Loading tools…')] }));
|
|
49
|
+
}
|
|
50
|
+
if (actualToolCount === 0 && toolCount > 0) {
|
|
51
|
+
return _jsx("p", { className: "connector-drawer-empty", children: t('Tool details unavailable ({count})', { count: toolCount }) });
|
|
52
|
+
}
|
|
53
|
+
if (actualToolCount === 0)
|
|
54
|
+
return _jsx("p", { className: "connector-drawer-empty", children: t('No tools available') });
|
|
55
|
+
return (_jsxs(_Fragment, { children: [_jsx("ul", { className: "connector-drawer-tools", children: connector.tools.map((tool) => (_jsx(ConnectorDrawerTool, { tool: tool }, tool.name))) }), connector.toolsNextCursor ? (_jsx("button", { type: "button", className: "ghost connector-drawer-load-more", disabled: toolsPreviewLoading, onClick: () => onLoadMoreTools(connector.id, connector.toolsNextCursor), children: _jsx("span", { children: t('Load more tools') }) })) : null] }));
|
|
56
|
+
}
|
|
57
|
+
function ConnectorDrawerFoot({ connectorId, flags, onConnect, onCancelAuthorization, agentHandle }) {
|
|
58
|
+
const t = useT();
|
|
59
|
+
const { isAuthorizationPending } = flags;
|
|
60
|
+
const isBusy = flags.isConnecting || isAuthorizationPending;
|
|
61
|
+
return (_jsxs("footer", { className: "connector-drawer-foot", children: [_jsxs("button", { type: "button", className: `primary connector-action is-connect${isBusy ? ' is-loading' : ''}`, disabled: !flags.canConnect, "aria-busy": isBusy || undefined, onClick: () => onConnect(connectorId), ...agentHandleProps({}, { base: agentHandle, action: 'connect', role: 'button', label: t('Connect') }), children: [isBusy ? _jsx(Icon, { name: "spinner", size: 12 }) : null, _jsx("span", { children: isAuthorizationPending ? t('Authorization pending') : t('Connect') })] }), isAuthorizationPending ? (_jsx("button", { type: "button", className: "ghost connector-action is-cancel-authorization", onClick: () => onCancelAuthorization(connectorId), ...agentHandleProps({}, { base: agentHandle, action: 'cancel-authorization', role: 'button', label: t('Cancel authorization') }), children: _jsx("span", { children: t('Cancel authorization') }) })) : null] }));
|
|
62
|
+
}
|
|
63
|
+
/** Escape-to-close, initial focus on the close button, and body-scroll lock for the drawer's lifetime. */
|
|
64
|
+
function useDrawerModalBehavior({ onClose, closeBtnRef, }) {
|
|
48
65
|
useEffect(() => {
|
|
49
66
|
function onKey(e) {
|
|
50
67
|
if (e.key === 'Escape') {
|
|
@@ -61,10 +78,24 @@ export function ConnectorDetailDrawer({ connector, disabled, pendingAction, auth
|
|
|
61
78
|
document.body.style.overflow = previousOverflow;
|
|
62
79
|
};
|
|
63
80
|
}, [onClose]);
|
|
64
|
-
|
|
81
|
+
}
|
|
82
|
+
/**
|
|
83
|
+
* Modal detail drawer with a paginated tool list. Keeps its own
|
|
84
|
+
* escape-key-to-close and body-scroll-lock behavior inline (standard modal
|
|
85
|
+
* a11y idioms, not business/transport logic) — see
|
|
86
|
+
* `packages/ui/source-map.md`'s purity-check note for why these two
|
|
87
|
+
* `document`/`window` touches were kept here rather than routed through
|
|
88
|
+
* `dependencies.ts`.
|
|
89
|
+
*/
|
|
90
|
+
export function ConnectorDetailDrawer({ connector, disabled, pendingAction, authorizationPending, authorizationCancelFailed, authorizationError, toolsPreviewLoading, toolsLoaded, onClose, onConnect, onDisconnect, onCancelAuthorization, onLoadMoreTools, onOpenExternalUrl, getCategoryLabel = (category) => category, getDisplayableAccountLabel = getDisplayableConnectorAccountLabel, cancelFailedMessage, continueInBrowserLabel, agentHandle, }) {
|
|
91
|
+
const t = useT();
|
|
92
|
+
const flags = connectorActionFlags({ connector, pendingAction, authorizationPending, disabled });
|
|
93
|
+
const closeBtnRef = useRef(null);
|
|
94
|
+
const categoryLabel = getCategoryLabel(connector.category);
|
|
95
|
+
useDrawerModalBehavior({ onClose, closeBtnRef });
|
|
65
96
|
return (_jsx("div", { className: "connector-drawer-backdrop", role: "presentation", onMouseDown: (e) => {
|
|
66
97
|
if (e.target === e.currentTarget)
|
|
67
98
|
onClose();
|
|
68
|
-
}, children: _jsxs("aside", { className: "connector-drawer", role: "dialog", "aria-modal": "true", "aria-labelledby": "connector-drawer-title", "data-testid": "connector-drawer", onClick: (e) => e.stopPropagation(), ...agentHandleProps({}, { base: agentHandle,
|
|
99
|
+
}, children: _jsxs("aside", { className: "connector-drawer", role: "dialog", "aria-modal": "true", "aria-labelledby": "connector-drawer-title", "data-testid": "connector-drawer", onClick: (e) => e.stopPropagation(), ...agentHandleProps({}, { base: agentHandle, role: 'region', label: connector.name }), children: [_jsx(ConnectorDrawerHead, { connector: connector, categoryLabel: categoryLabel, isAuthorizationPending: flags.isAuthorizationPending, toolsLoaded: toolsLoaded, closeBtnRef: closeBtnRef, onClose: onClose, agentHandle: agentHandle }), _jsxs("div", { className: "connector-drawer-body", children: [connector.description ? (_jsx(ConnectorDrawerAbout, { description: connector.description, isAuthorizationPending: flags.isAuthorizationPending, redirectUrl: flags.redirectUrl, continueInBrowserLabel: continueInBrowserLabel, onOpenExternalUrl: onOpenExternalUrl })) : null, authorizationError ? _jsx(ConnectorDrawerAlert, { message: authorizationError }) : null, authorizationCancelFailed ? (_jsx(ConnectorDrawerAlert, { message: cancelFailedMessage ?? t("Couldn't cancel authorization. Try again.") })) : null, _jsx(ConnectorDrawerDetails, { connector: connector, categoryLabel: categoryLabel, accountLabel: getDisplayableAccountLabel(connector), flags: flags, onDisconnect: onDisconnect, agentHandle: agentHandle }), _jsxs("section", { className: "connector-drawer-section", children: [_jsxs("h3", { className: "connector-drawer-section-title", children: [t('Tools'), " ", _jsx("span", { className: "connector-drawer-count", children: getConnectorDisplayToolCount(connector) })] }), _jsx(ConnectorDrawerToolsBody, { connector: connector, toolsPreviewLoading: toolsPreviewLoading, toolsLoaded: toolsLoaded, onLoadMoreTools: onLoadMoreTools })] })] }), !flags.isConnected ? (_jsx(ConnectorDrawerFoot, { connectorId: connector.id, flags: flags, onConnect: onConnect, onCancelAuthorization: onCancelAuthorization, agentHandle: agentHandle })) : null] }) }));
|
|
69
100
|
}
|
|
70
101
|
//# sourceMappingURL=ConnectorDetailDrawer.js.map
|
|
@@ -3,13 +3,18 @@ import { agentHandleProps, buildAgentListHandles } from '@jini-ai/agentic';
|
|
|
3
3
|
import { useT } from '../../i18n/index.js';
|
|
4
4
|
import { ConnectorCard } from './ConnectorCard.js';
|
|
5
5
|
import { ConnectorGate } from './ConnectorGate.js';
|
|
6
|
+
/** Search-empty state: the no-match title/body and a clear-search action, each copy line host-overridable. */
|
|
7
|
+
function ConnectorGridEmpty({ searchQuery, onClearSearch, emptyNoMatchTitle, emptyNoMatchBody, emptyNoMatchAction, agentHandle, }) {
|
|
8
|
+
const t = useT();
|
|
9
|
+
const title = emptyNoMatchTitle
|
|
10
|
+
? emptyNoMatchTitle(searchQuery.trim())
|
|
11
|
+
: t('No connectors match "{query}"', { query: searchQuery.trim() });
|
|
12
|
+
const action = emptyNoMatchAction ?? t('Clear search');
|
|
13
|
+
return (_jsxs("div", { className: "tab-empty connectors-empty", role: "status", "aria-live": "polite", "data-testid": "connectors-empty", children: [_jsx("p", { className: "connectors-empty-title", children: title }), _jsx("p", { className: "connectors-empty-body", children: emptyNoMatchBody ?? t('Try a different search term.') }), _jsx("button", { type: "button", className: "ghost connectors-empty-action", onClick: onClearSearch, ...agentHandleProps({}, { base: agentHandle, action: 'clear-search', role: 'button', label: action }), children: action })] }));
|
|
14
|
+
}
|
|
6
15
|
/** Card grid + the search-empty-state and locked-gate overlays. */
|
|
7
16
|
export function ConnectorGrid({ connectors, locked, hasNoResults, searchQuery, pendingConnectorAction, authorizationPending, authorizationCancelFailed, toolsLoaded, onConnect, onDisconnect, onCancelAuthorization, onOpenDetails, onOpenExternalUrl, getCategoryLabel, onClearSearch, gate, emptyNoMatchTitle, emptyNoMatchBody, emptyNoMatchAction, agentHandle, }) {
|
|
8
|
-
const
|
|
9
|
-
|
|
10
|
-
const resolvedEmptyNoMatchBody = emptyNoMatchBody ?? t('Try a different search term.');
|
|
11
|
-
const resolvedEmptyNoMatchAction = emptyNoMatchAction ?? t('Clear search');
|
|
12
|
-
const cardHandles = agentHandle ? buildAgentListHandles({ prefix: agentHandle, ids: connectors.map((c) => c.id) }) : undefined;
|
|
13
|
-
return (_jsxs("div", { className: `connector-grid-wrap${locked ? ' is-masked' : ''}`, "data-testid": "connector-grid-wrap", children: [hasNoResults && !locked ? (_jsxs("div", { className: "tab-empty connectors-empty", role: "status", "aria-live": "polite", "data-testid": "connectors-empty", children: [_jsx("p", { className: "connectors-empty-title", children: resolvedEmptyNoMatchTitle(searchQuery.trim()) }), _jsx("p", { className: "connectors-empty-body", children: resolvedEmptyNoMatchBody }), _jsx("button", { type: "button", className: "ghost connectors-empty-action", onClick: onClearSearch, ...agentHandleProps({}, { base: agentHandle, ...({ action: 'clear-search', role: 'button', label: resolvedEmptyNoMatchAction }) }), children: resolvedEmptyNoMatchAction })] })) : (_jsx("div", { className: "connector-grid", "aria-hidden": locked || undefined, children: connectors.map((connector, index) => (_jsx(ConnectorCard, { connector: connector, disabled: locked, pendingAction: pendingConnectorAction?.connectorId === connector.id ? pendingConnectorAction.action : null, authorizationPending: authorizationPending[connector.id], authorizationCancelFailed: authorizationCancelFailed[connector.id] === true, toolsLoaded: toolsLoaded, onConnect: onConnect, onDisconnect: onDisconnect, onCancelAuthorization: onCancelAuthorization, onOpenDetails: onOpenDetails, ...(getCategoryLabel ? { getCategoryLabel } : {}), ...(onOpenExternalUrl ? { onOpenExternalUrl } : {}), ...(cardHandles?.[index] ? { agentHandle: cardHandles[index] } : {}) }, connector.id))) })), locked && gate ? _jsx(ConnectorGate, { ...gate }) : null] }));
|
|
17
|
+
const cardHandles = agentHandle ? buildAgentListHandles({ prefix: agentHandle, ids: connectors.map((c) => c.id) }) : [];
|
|
18
|
+
return (_jsxs("div", { className: `connector-grid-wrap${locked ? ' is-masked' : ''}`, "data-testid": "connector-grid-wrap", children: [hasNoResults && !locked ? (_jsx(ConnectorGridEmpty, { searchQuery: searchQuery, onClearSearch: onClearSearch, emptyNoMatchTitle: emptyNoMatchTitle, emptyNoMatchBody: emptyNoMatchBody, emptyNoMatchAction: emptyNoMatchAction, agentHandle: agentHandle })) : (_jsx("div", { className: "connector-grid", "aria-hidden": locked || undefined, children: connectors.map((connector, index) => (_jsx(ConnectorCard, { connector: connector, disabled: locked, pendingAction: pendingConnectorAction?.connectorId === connector.id ? pendingConnectorAction.action : null, authorizationPending: authorizationPending[connector.id], authorizationCancelFailed: authorizationCancelFailed[connector.id] === true, toolsLoaded: toolsLoaded, onConnect: onConnect, onDisconnect: onDisconnect, onCancelAuthorization: onCancelAuthorization, onOpenDetails: onOpenDetails, ...(getCategoryLabel ? { getCategoryLabel } : {}), ...(onOpenExternalUrl ? { onOpenExternalUrl } : {}), ...(cardHandles[index] ? { agentHandle: cardHandles[index] } : {}) }, connector.id))) })), locked && gate ? _jsx(ConnectorGate, { ...gate }) : null] }));
|
|
14
19
|
}
|
|
15
20
|
//# sourceMappingURL=ConnectorGrid.js.map
|
|
@@ -152,6 +152,12 @@ export function useConnectorAuthorization(port, authPendingStorage, authBridge,
|
|
|
152
152
|
// (not stripped) as a guard against a future refactor breaking
|
|
153
153
|
// that invariant — see packages/ui/archived provenance ledger's 2026-07-22
|
|
154
154
|
// dated entry for the full proof.
|
|
155
|
+
// Correction (2026-10-21 coverage pass): the proof above misses one interleaving. While this
|
|
156
|
+
// sweep's `cancelConnectorAuthorization` call is still awaiting, a `runConnectorAction(id,
|
|
157
|
+
// 'connect')` that resolves with `{ error }` sets `authError[id]`; the cancel then succeeds and
|
|
158
|
+
// this clear removes that NEWER error. Reproduced in
|
|
159
|
+
// `__tests__/hooks/useConnectorAuthorization.stale-race.test.ts`; flagged for an owner decision
|
|
160
|
+
// on whether the sweep should leave a fresher error alone.
|
|
155
161
|
setAuthError((curr) => {
|
|
156
162
|
if (curr[connectorId] === undefined)
|
|
157
163
|
return curr;
|
|
@@ -19,6 +19,8 @@ export interface ConnectorCatalogController {
|
|
|
19
19
|
* fetch (so already-configured connectors render immediately), then a lazy
|
|
20
20
|
* enrichment pass gated on `unlocked` — heavier, only worth it once the
|
|
21
21
|
* host's provider is actually configured.
|
|
22
|
+
* Failed reads retain the current catalog, settle their loading state and
|
|
23
|
+
* report a fixed diagnostic; host/provider errors may contain credentials.
|
|
22
24
|
*/
|
|
23
25
|
export declare function useConnectorCatalog(port: ConnectorsPort, options: ConnectorCatalogOptions): ConnectorCatalogController;
|
|
24
26
|
//# sourceMappingURL=useConnectorCatalog.d.ts.map
|
|
@@ -5,6 +5,8 @@ import { mergeConnectors } from '../rules.js';
|
|
|
5
5
|
* fetch (so already-configured connectors render immediately), then a lazy
|
|
6
6
|
* enrichment pass gated on `unlocked` — heavier, only worth it once the
|
|
7
7
|
* host's provider is actually configured.
|
|
8
|
+
* Failed reads retain the current catalog, settle their loading state and
|
|
9
|
+
* report a fixed diagnostic; host/provider errors may contain credentials.
|
|
8
10
|
*/
|
|
9
11
|
export function useConnectorCatalog(port, options) {
|
|
10
12
|
const { unlocked, refreshKey = 0 } = options;
|
|
@@ -16,12 +18,20 @@ export function useConnectorCatalog(port, options) {
|
|
|
16
18
|
let cancelled = false;
|
|
17
19
|
setLoading(true);
|
|
18
20
|
setEnriched(false);
|
|
19
|
-
(async () => {
|
|
20
|
-
|
|
21
|
-
|
|
22
|
-
|
|
23
|
-
|
|
24
|
-
|
|
21
|
+
void (async () => {
|
|
22
|
+
try {
|
|
23
|
+
const next = await port.fetchConnectors();
|
|
24
|
+
if (!cancelled)
|
|
25
|
+
setConnectors((curr) => mergeConnectors(curr, next));
|
|
26
|
+
}
|
|
27
|
+
catch {
|
|
28
|
+
if (!cancelled)
|
|
29
|
+
console.error('[connectors] Catalog load failed.');
|
|
30
|
+
}
|
|
31
|
+
finally {
|
|
32
|
+
if (!cancelled)
|
|
33
|
+
setLoading(false);
|
|
34
|
+
}
|
|
25
35
|
})();
|
|
26
36
|
return () => {
|
|
27
37
|
cancelled = true;
|
|
@@ -38,13 +48,22 @@ export function useConnectorCatalog(port, options) {
|
|
|
38
48
|
return;
|
|
39
49
|
let cancelled = false;
|
|
40
50
|
setEnriching(true);
|
|
41
|
-
(async () => {
|
|
42
|
-
|
|
43
|
-
|
|
44
|
-
|
|
45
|
-
|
|
46
|
-
|
|
47
|
-
|
|
51
|
+
void (async () => {
|
|
52
|
+
try {
|
|
53
|
+
const next = await port.fetchConnectorEnrichment({ refresh: true });
|
|
54
|
+
if (cancelled)
|
|
55
|
+
return;
|
|
56
|
+
setConnectors((curr) => mergeConnectors(curr, next));
|
|
57
|
+
setEnriched(true);
|
|
58
|
+
}
|
|
59
|
+
catch {
|
|
60
|
+
if (!cancelled)
|
|
61
|
+
console.error('[connectors] Catalog enrichment failed.');
|
|
62
|
+
}
|
|
63
|
+
finally {
|
|
64
|
+
if (!cancelled)
|
|
65
|
+
setEnriching(false);
|
|
66
|
+
}
|
|
48
67
|
})();
|
|
49
68
|
return () => {
|
|
50
69
|
cancelled = true;
|
|
@@ -11,9 +11,9 @@ export interface UseWiredConnectorsBrowserParams {
|
|
|
11
11
|
onConnectorsChanged?: (() => void) | undefined;
|
|
12
12
|
onConnectorAuthResult?: ((event: ConnectorAuthResultEvent) => void) | undefined;
|
|
13
13
|
/** Custom hook overrides for dependency injection / testing — mirrors `ConnectorsBrowserProps`. */
|
|
14
|
-
useConnectorCatalog?: typeof useConnectorCatalog;
|
|
15
|
-
useConnectorAuthorization?: typeof useConnectorAuthorization;
|
|
16
|
-
useConnectorDetail?: typeof useConnectorDetail;
|
|
14
|
+
useConnectorCatalog?: typeof useConnectorCatalog | undefined;
|
|
15
|
+
useConnectorAuthorization?: typeof useConnectorAuthorization | undefined;
|
|
16
|
+
useConnectorDetail?: typeof useConnectorDetail | undefined;
|
|
17
17
|
}
|
|
18
18
|
export interface WiredConnectorsBrowserController {
|
|
19
19
|
/** The resolved dependency bundle (host-supplied, or the package's fake) — still needed by the host
|
|
@@ -1,10 +1,17 @@
|
|
|
1
1
|
/** Connector callback-origin validation and search/display sorting; no React, transport or DOM. */
|
|
2
|
-
import type { Connector, ConnectorAuthorizationPendingState, ConnectorActionResult, ConnectorStatusMap, ConnectorPanelAlert, ConnectorStatus, ProviderTab } from './types.js';
|
|
2
|
+
import type { Connector, ConnectorAction, ConnectorActionFlags, ConnectorAuthorizationPending, ConnectorAuthorizationPendingState, ConnectorActionResult, ConnectorStatusMap, ConnectorPanelAlert, ConnectorStatus, ProviderTab } from './types.js';
|
|
3
3
|
/** Restricts the catalog to a single provider tab's `match` predicate, defaulting to the first tab. */
|
|
4
4
|
export declare function scopeConnectorsToProvider(connectors: Connector[], providerTabs: readonly ProviderTab[], selectedProviderId: string): Connector[];
|
|
5
5
|
export declare function mergeConnectors(current: Connector[], incoming: Connector[]): Connector[];
|
|
6
6
|
export declare function pruneConnectorAuthorizationPending(pending: ConnectorAuthorizationPendingState, nowMs: number): ConnectorAuthorizationPendingState;
|
|
7
7
|
export declare function parseConnectorAuthorizationPendingState(raw: string): ConnectorAuthorizationPendingState;
|
|
8
|
+
/** Derives the connect/disconnect/authorization-pending flags a card or drawer renders its actions from. */
|
|
9
|
+
export declare function connectorActionFlags({ connector, pendingAction, authorizationPending, disabled, }: {
|
|
10
|
+
connector: Connector;
|
|
11
|
+
pendingAction: ConnectorAction | null;
|
|
12
|
+
authorizationPending: ConnectorAuthorizationPending | undefined;
|
|
13
|
+
disabled: boolean;
|
|
14
|
+
}): ConnectorActionFlags;
|
|
8
15
|
export declare function updateConnectorAuthorizationPendingFromConnectResponse(pending: ConnectorAuthorizationPendingState, response: ConnectorActionResult, nowMs: number): ConnectorAuthorizationPendingState;
|
|
9
16
|
export declare function updateConnectorAuthorizationPendingFromStatuses(pending: ConnectorAuthorizationPendingState, statuses: ConnectorStatusMap, nowMs: number): ConnectorAuthorizationPendingState;
|
|
10
17
|
export declare function clearConnectorAuthorizationErrorsForConnected(errors: Record<string, string>, statuses: ConnectorStatusMap): Record<string, string>;
|
|
@@ -45,32 +45,54 @@ export function pruneConnectorAuthorizationPending(pending, nowMs) {
|
|
|
45
45
|
}
|
|
46
46
|
return next;
|
|
47
47
|
}
|
|
48
|
+
function isPlainRecord(value) {
|
|
49
|
+
return !!value && typeof value === 'object' && !Array.isArray(value);
|
|
50
|
+
}
|
|
51
|
+
function isNonBlankString(value) {
|
|
52
|
+
return typeof value === 'string' && !!value.trim();
|
|
53
|
+
}
|
|
54
|
+
function parsePendingEntry(state) {
|
|
55
|
+
if (!isPlainRecord(state))
|
|
56
|
+
return {};
|
|
57
|
+
const { expiresAt, redirectUrl } = state;
|
|
58
|
+
return {
|
|
59
|
+
...(isNonBlankString(expiresAt) ? { expiresAt } : {}),
|
|
60
|
+
...(isNonBlankString(redirectUrl) ? { redirectUrl } : {}),
|
|
61
|
+
};
|
|
62
|
+
}
|
|
48
63
|
export function parseConnectorAuthorizationPendingState(raw) {
|
|
64
|
+
let parsed;
|
|
49
65
|
try {
|
|
50
|
-
|
|
51
|
-
if (!parsed || typeof parsed !== 'object' || Array.isArray(parsed))
|
|
52
|
-
return {};
|
|
53
|
-
const pending = {};
|
|
54
|
-
for (const [connectorId, state] of Object.entries(parsed)) {
|
|
55
|
-
if (!connectorId)
|
|
56
|
-
continue;
|
|
57
|
-
if (state && typeof state === 'object' && !Array.isArray(state)) {
|
|
58
|
-
const expiresAt = state.expiresAt;
|
|
59
|
-
const redirectUrl = state.redirectUrl;
|
|
60
|
-
pending[connectorId] = {
|
|
61
|
-
...(typeof expiresAt === 'string' && expiresAt.trim() ? { expiresAt } : {}),
|
|
62
|
-
...(typeof redirectUrl === 'string' && redirectUrl.trim() ? { redirectUrl } : {}),
|
|
63
|
-
};
|
|
64
|
-
}
|
|
65
|
-
else {
|
|
66
|
-
pending[connectorId] = {};
|
|
67
|
-
}
|
|
68
|
-
}
|
|
69
|
-
return pending;
|
|
66
|
+
parsed = JSON.parse(raw);
|
|
70
67
|
}
|
|
71
68
|
catch {
|
|
72
69
|
return {};
|
|
73
70
|
}
|
|
71
|
+
if (!isPlainRecord(parsed))
|
|
72
|
+
return {};
|
|
73
|
+
const pending = {};
|
|
74
|
+
for (const [connectorId, state] of Object.entries(parsed)) {
|
|
75
|
+
if (!connectorId)
|
|
76
|
+
continue;
|
|
77
|
+
pending[connectorId] = parsePendingEntry(state);
|
|
78
|
+
}
|
|
79
|
+
return pending;
|
|
80
|
+
}
|
|
81
|
+
/** Derives the connect/disconnect/authorization-pending flags a card or drawer renders its actions from. */
|
|
82
|
+
export function connectorActionFlags({ connector, pendingAction, authorizationPending, disabled, }) {
|
|
83
|
+
const isConnected = connector.status === 'connected';
|
|
84
|
+
const isAuthorizationPending = !isConnected && authorizationPending !== undefined;
|
|
85
|
+
const isPending = pendingAction !== null || isAuthorizationPending;
|
|
86
|
+
const canAct = !disabled && !isPending;
|
|
87
|
+
return {
|
|
88
|
+
isConnecting: pendingAction === 'connect',
|
|
89
|
+
isDisconnecting: pendingAction === 'disconnect',
|
|
90
|
+
isConnected,
|
|
91
|
+
isAuthorizationPending,
|
|
92
|
+
canConnect: canAct && connector.status === 'available',
|
|
93
|
+
canDisconnect: canAct && isConnected,
|
|
94
|
+
redirectUrl: isAuthorizationPending ? authorizationPending.redirectUrl : undefined,
|
|
95
|
+
};
|
|
74
96
|
}
|
|
75
97
|
export function updateConnectorAuthorizationPendingFromConnectResponse(pending, response, nowMs) {
|
|
76
98
|
if (!response.connector)
|
|
@@ -78,4 +78,15 @@ export interface ConnectorAuthResultEvent {
|
|
|
78
78
|
result: 'success' | 'failed' | 'cancelled';
|
|
79
79
|
errorCode?: string;
|
|
80
80
|
}
|
|
81
|
+
/** Derived connect/disconnect state shared by the connector card and detail drawer. */
|
|
82
|
+
export interface ConnectorActionFlags {
|
|
83
|
+
isConnecting: boolean;
|
|
84
|
+
isDisconnecting: boolean;
|
|
85
|
+
isConnected: boolean;
|
|
86
|
+
isAuthorizationPending: boolean;
|
|
87
|
+
canConnect: boolean;
|
|
88
|
+
canDisconnect: boolean;
|
|
89
|
+
/** The pending authorization's redirect URL — only set while authorization is pending. */
|
|
90
|
+
redirectUrl: string | undefined;
|
|
91
|
+
}
|
|
81
92
|
//# sourceMappingURL=types.d.ts.map
|
|
@@ -1,6 +1,5 @@
|
|
|
1
1
|
import type { AgentCliEnvFieldSpec, ApiProtocol, ProviderPreset } from './types.js';
|
|
2
|
-
/**
|
|
3
|
-
* the operator has not typed a base URL. Origin: `DEFAULT_BASE_URL_BY_PROTOCOL`. */
|
|
2
|
+
/** @deprecated Endpoints come from host presets. Blank means the operator must supply an endpoint. */
|
|
4
3
|
export declare const DEFAULT_BASE_URL_BY_PROTOCOL: Readonly<Record<ApiProtocol, string>>;
|
|
5
4
|
/** Display order and English labels for the protocol row. Values are i18n
|
|
6
5
|
* keys (this package's convention is "the English string is the key"). */
|
|
@@ -18,8 +17,8 @@ export declare const CUSTOM_MODEL_SENTINEL = "__custom__";
|
|
|
18
17
|
/**
|
|
19
18
|
* The shortest string `apiKeyFormatWarning` will let pass without remark.
|
|
20
19
|
*
|
|
21
|
-
* Chosen from evidence rather than taste. The shortest real key shape
|
|
22
|
-
*
|
|
20
|
+
* Chosen from evidence rather than taste. The shortest real key shape in the integrations
|
|
21
|
+
* starter presets is Azure OpenAI's bare 32-character hex string;
|
|
23
22
|
* Google's is `AIza` + 35 = 39, OpenAI's `sk-` + 48 = 51, OpenRouter's `sk-or-v1-` + 64 = 73, and
|
|
24
23
|
* Anthropic's longer again. 20 therefore sits 12 characters below that floor, so no credential this
|
|
25
24
|
* catalog knows about can trip it, while it still catches the failure the check exists for: the
|
|
@@ -45,12 +44,7 @@ export declare const API_KEY_CROSS_VENDOR_WARNING = "This looks like an API key
|
|
|
45
44
|
/** Shown when a key is shorter than {@link MIN_PLAUSIBLE_API_KEY_LENGTH}. Carries no placeholders:
|
|
46
45
|
* the length floor is global, so there is no vendor to name. */
|
|
47
46
|
export declare const API_KEY_TOO_SHORT_WARNING = "This is shorter than any provider API key \u2014 check that the whole key was pasted. You can still save and test it.";
|
|
48
|
-
/**
|
|
49
|
-
* A small, vendor-shaped starting catalog. Deliberately NOT the origin's full
|
|
50
|
-
* ~30-entry list: that list is hand-curated product content that goes stale,
|
|
51
|
-
* and this package's rule for tables like this (see `LanguageTab`) is that the
|
|
52
|
-
* host owns them. Pass your own `presets` to replace this wholesale.
|
|
53
|
-
*/
|
|
47
|
+
/** @deprecated Supply host presets. The former starter set is exported by integrations/media-providers/catalog. */
|
|
54
48
|
export declare const DEFAULT_PROVIDER_PRESETS: readonly ProviderPreset[];
|
|
55
49
|
/**
|
|
56
50
|
* One-line descriptions for the code-agent CLIs this package knows about,
|
|
@@ -1,11 +1,9 @@
|
|
|
1
|
-
|
|
2
|
-
/** Fallback endpoint per protocol, used when a host supplies no preset and
|
|
3
|
-
* the operator has not typed a base URL. Origin: `DEFAULT_BASE_URL_BY_PROTOCOL`. */
|
|
1
|
+
/** @deprecated Endpoints come from host presets. Blank means the operator must supply an endpoint. */
|
|
4
2
|
export const DEFAULT_BASE_URL_BY_PROTOCOL = {
|
|
5
|
-
anthropic:
|
|
6
|
-
openai:
|
|
7
|
-
azure:
|
|
8
|
-
google:
|
|
3
|
+
anthropic: '',
|
|
4
|
+
openai: '',
|
|
5
|
+
azure: '',
|
|
6
|
+
google: '',
|
|
9
7
|
};
|
|
10
8
|
/** Display order and English labels for the protocol row. Values are i18n
|
|
11
9
|
* keys (this package's convention is "the English string is the key"). */
|
|
@@ -25,8 +23,8 @@ export const CUSTOM_MODEL_SENTINEL = '__custom__';
|
|
|
25
23
|
/**
|
|
26
24
|
* The shortest string `apiKeyFormatWarning` will let pass without remark.
|
|
27
25
|
*
|
|
28
|
-
* Chosen from evidence rather than taste. The shortest real key shape
|
|
29
|
-
*
|
|
26
|
+
* Chosen from evidence rather than taste. The shortest real key shape in the integrations
|
|
27
|
+
* starter presets is Azure OpenAI's bare 32-character hex string;
|
|
30
28
|
* Google's is `AIza` + 35 = 39, OpenAI's `sk-` + 48 = 51, OpenRouter's `sk-or-v1-` + 64 = 73, and
|
|
31
29
|
* Anthropic's longer again. 20 therefore sits 12 characters below that floor, so no credential this
|
|
32
30
|
* catalog knows about can trip it, while it still catches the failure the check exists for: the
|
|
@@ -52,91 +50,8 @@ export const API_KEY_CROSS_VENDOR_WARNING = 'This looks like an API key for {ven
|
|
|
52
50
|
/** Shown when a key is shorter than {@link MIN_PLAUSIBLE_API_KEY_LENGTH}. Carries no placeholders:
|
|
53
51
|
* the length floor is global, so there is no vendor to name. */
|
|
54
52
|
export const API_KEY_TOO_SHORT_WARNING = 'This is shorter than any provider API key — check that the whole key was pasted. You can still save and test it.';
|
|
55
|
-
/**
|
|
56
|
-
|
|
57
|
-
* ~30-entry list: that list is hand-curated product content that goes stale,
|
|
58
|
-
* and this package's rule for tables like this (see `LanguageTab`) is that the
|
|
59
|
-
* host owns them. Pass your own `presets` to replace this wholesale.
|
|
60
|
-
*/
|
|
61
|
-
export const DEFAULT_PROVIDER_PRESETS = [
|
|
62
|
-
{
|
|
63
|
-
id: 'anthropic',
|
|
64
|
-
title: 'Anthropic',
|
|
65
|
-
protocol: 'anthropic',
|
|
66
|
-
baseUrl: VENDOR_API_BASE_URLS.anthropic,
|
|
67
|
-
preferredModels: ['claude-sonnet-5', 'claude-opus-5', 'claude-haiku-4-5'],
|
|
68
|
-
kind: 'protocol',
|
|
69
|
-
apiKeyPrefix: 'sk-ant-',
|
|
70
|
-
},
|
|
71
|
-
{
|
|
72
|
-
id: 'openai',
|
|
73
|
-
title: 'OpenAI',
|
|
74
|
-
protocol: 'openai',
|
|
75
|
-
baseUrl: VENDOR_API_BASE_URLS.openai,
|
|
76
|
-
// `gpt-4o`/`gpt-4o-mini`/`o3`/`o4-mini` are stale: OpenAI's GPT-5.6 family
|
|
77
|
-
// (released 2026-07-09, per the API changelog) replaced the old
|
|
78
|
-
// flagship/mini/nano naming with named tiers — sol/terra/luna. `sol` is
|
|
79
|
-
// the one the changelog and pricing docs call out as "recommended for
|
|
80
|
-
// production API usage", so it leads (see `preferredModels[0]` default
|
|
81
|
-
// in `rules.ts`) rather than the newer, pricier `gpt-6-astra` flagship
|
|
82
|
-
// (released 2026-09-03) — picking that as the silent default would jump
|
|
83
|
-
// an existing user's cost without them choosing it.
|
|
84
|
-
preferredModels: ['gpt-5.6-sol', 'gpt-5.6-terra', 'gpt-5.6-luna'],
|
|
85
|
-
kind: 'protocol',
|
|
86
|
-
apiKeyPrefix: 'sk-',
|
|
87
|
-
},
|
|
88
|
-
{
|
|
89
|
-
id: 'azure-openai',
|
|
90
|
-
title: 'Azure OpenAI',
|
|
91
|
-
protocol: 'azure',
|
|
92
|
-
baseUrl: VENDOR_API_BASE_URLS.azure,
|
|
93
|
-
preferredModels: [],
|
|
94
|
-
kind: 'protocol',
|
|
95
|
-
// No `apiKeyPrefix` deliberately: an Azure OpenAI key is a bare hex string with no vendor
|
|
96
|
-
// prefix, so any value here would be a guess — and a wrong prefix claim does not merely stay
|
|
97
|
-
// silent, it lets some OTHER vendor's valid key be announced as Azure's. Its 32 hex characters
|
|
98
|
-
// are also the shortest real key shape in this catalog, which is what sets
|
|
99
|
-
// `MIN_PLAUSIBLE_API_KEY_LENGTH`.
|
|
100
|
-
},
|
|
101
|
-
{
|
|
102
|
-
id: 'google-gemini',
|
|
103
|
-
title: 'Google Gemini',
|
|
104
|
-
protocol: 'google',
|
|
105
|
-
baseUrl: VENDOR_API_BASE_URLS.google,
|
|
106
|
-
// Ordered newest-first: `rules.ts`'s `saved?.model ?? preset.preferredModels[0]` makes entry [0]
|
|
107
|
-
// the default for anyone who has never picked a model, so a stale head silently pins new users
|
|
108
|
-
// to an old generation. Reported live: the field defaulted to `gemini-2.5-flash` while the
|
|
109
|
-
// operator was actually running `gemini-3.6-flash`. This list is only a FALLBACK — the form
|
|
110
|
-
// prefers live `listModels` discovery and drops back here when that call fails.
|
|
111
|
-
preferredModels: ['gemini-3.6-flash', 'gemini-2.5-flash', 'gemini-2.5-pro'],
|
|
112
|
-
kind: 'protocol',
|
|
113
|
-
// `AIza` + 35 characters is the classic Google key shape, and it is recorded here so a key of
|
|
114
|
-
// this shape is recognised as GOOGLE'S when it turns up in some other provider's field.
|
|
115
|
-
// Emphatically not a test that a Google key must look like this: an operator pasted a real,
|
|
116
|
-
// working Gemini key in a newer shape and the old allowlist told them it was not a Google key.
|
|
117
|
-
apiKeyPrefix: 'AIza',
|
|
118
|
-
},
|
|
119
|
-
{
|
|
120
|
-
id: 'openrouter',
|
|
121
|
-
title: 'OpenRouter',
|
|
122
|
-
protocol: 'openai',
|
|
123
|
-
baseUrl: VENDOR_API_BASE_URLS.openrouter,
|
|
124
|
-
preferredModels: ['anthropic/claude-sonnet-5', 'google/gemini-2.5-pro', 'openai/gpt-5.6-sol'],
|
|
125
|
-
kind: 'gateway',
|
|
126
|
-
// Longer than OpenAI's `sk-`, and deliberately so: `apiKeyFormatWarning` resolves a key to the
|
|
127
|
-
// MOST specific prefix that claims it, so `sk-or-v1-…` is attributed here rather than to OpenAI.
|
|
128
|
-
apiKeyPrefix: 'sk-or-',
|
|
129
|
-
},
|
|
130
|
-
{
|
|
131
|
-
id: 'ollama',
|
|
132
|
-
title: 'Ollama',
|
|
133
|
-
protocol: 'openai',
|
|
134
|
-
baseUrl: VENDOR_API_BASE_URLS.ollama,
|
|
135
|
-
preferredModels: [],
|
|
136
|
-
kind: 'gateway',
|
|
137
|
-
requiresApiKey: false,
|
|
138
|
-
},
|
|
139
|
-
];
|
|
53
|
+
/** @deprecated Supply host presets. The former starter set is exported by integrations/media-providers/catalog. */
|
|
54
|
+
export const DEFAULT_PROVIDER_PRESETS = [];
|
|
140
55
|
/**
|
|
141
56
|
* One-line descriptions for the code-agent CLIs this package knows about,
|
|
142
57
|
* keyed by the agent id `ExecutionPort` reports. Origin:
|
|
@@ -10,10 +10,8 @@ export interface ByokProviderFormProps {
|
|
|
10
10
|
* as ANOTHER row's, so `apiKeyFormatWarning` can say whose it looks like. Never used to validate
|
|
11
11
|
* the selected preset's own key — see that function for why that direction is forbidden.
|
|
12
12
|
*
|
|
13
|
-
* Defaults to
|
|
14
|
-
*
|
|
15
|
-
* than losing the check silently. A host with its own catalog should pass it, exactly as
|
|
16
|
-
* `ExecutionTab` does.
|
|
13
|
+
* Defaults to no presets. Hosts rendering this card standalone must pass their catalog
|
|
14
|
+
* to enable cross-provider prefix hints, exactly as `ExecutionTab` does.
|
|
17
15
|
*/
|
|
18
16
|
presets?: readonly ProviderPreset[];
|
|
19
17
|
/** Live model-discovery result. `'ok'` suggestions win over the preset's
|