@kortix/ui 0.14.8 → 0.14.10
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/README.md +2 -2
- package/dist/_vendor/kortix-shared.js +116 -3
- package/dist/_vendor/shared/app-config.d.ts +175 -0
- package/dist/_vendor/shared/artifact-comments.d.ts +235 -0
- package/dist/_vendor/shared/channel-descriptors.d.ts +96 -0
- package/dist/_vendor/shared/channel-message.d.ts +45 -5
- package/dist/_vendor/shared/index.d.ts +2 -0
- package/dist/_vendor/shared/space-slug.d.ts +37 -0
- package/dist/access/access/access-detail-shell.js +1 -1
- package/dist/access/access/principal-picker.d.ts +11 -0
- package/dist/access/access/principal-picker.js +3 -2
- package/dist/apps/app-preview-pool.d.ts +7 -2
- package/dist/apps/app-preview-pool.js +30 -7
- package/dist/apps/app-shared.d.ts +22 -15
- package/dist/apps/app-shared.js +37 -19
- package/dist/apps/index.d.ts +2 -2
- package/dist/apps/index.js +2 -2
- package/dist/artifacts/artifact-frame.d.ts +16 -0
- package/dist/artifacts/artifact-frame.js +55 -0
- package/dist/artifacts/artifact-session.d.ts +18 -0
- package/dist/artifacts/artifact-session.js +101 -0
- package/dist/artifacts/frame-policy.d.ts +30 -0
- package/dist/artifacts/frame-policy.js +61 -0
- package/dist/artifacts/index.d.ts +3 -0
- package/dist/artifacts/index.js +5 -0
- package/dist/browser/sandbox-browser-chrome.d.ts +4 -1
- package/dist/browser/sandbox-browser-chrome.js +2 -2
- package/dist/customize/agents/agent-grant-pages.d.ts +5 -1
- package/dist/customize/agents/agent-grant-pages.js +30 -4
- package/dist/customize/agents/agent-page.js +3 -1
- package/dist/customize/agents/agent-policy-sets.d.ts +43 -0
- package/dist/customize/agents/agent-policy-sets.js +72 -0
- package/dist/customize/agents/agent-triggers-section.js +2 -1
- package/dist/customize/connectors/add-mcp/add-mcp-server-dialog.d.ts +6 -1
- package/dist/customize/connectors/add-mcp/add-mcp-server-dialog.js +10 -4
- package/dist/customize/connectors/agent-access.d.ts +35 -0
- package/dist/customize/connectors/agent-access.js +77 -0
- package/dist/customize/connectors/catalog/browse-sections.d.ts +2 -29
- package/dist/customize/connectors/catalog/browse-sections.js +7 -74
- package/dist/customize/connectors/catalog/catalog-entry.d.ts +18 -37
- package/dist/customize/connectors/catalog/catalog-entry.js +28 -40
- package/dist/customize/connectors/catalog/connector-browse.d.ts +3 -32
- package/dist/customize/connectors/catalog/connector-browse.js +19 -50
- package/dist/customize/connectors/catalog/use-catalog.d.ts +20 -59
- package/dist/customize/connectors/catalog/use-catalog.js +48 -175
- package/dist/customize/connectors/connector-identity.d.ts +9 -11
- package/dist/customize/connectors/connector-identity.js +13 -42
- package/dist/customize/connectors/connector-moves-banner.d.ts +2 -1
- package/dist/customize/connectors/connector-moves-banner.js +4 -6
- package/dist/customize/connectors/connector-routes.d.ts +21 -9
- package/dist/customize/connectors/connector-routes.js +29 -20
- package/dist/customize/connectors/connectors-page.js +53 -82
- package/dist/customize/connectors/detail/app-page.js +226 -98
- package/dist/customize/connectors/detail/computer-app-page.d.ts +16 -0
- package/dist/customize/connectors/detail/computer-app-page.js +39 -0
- package/dist/customize/connectors/detail/connector-accounts.js +3 -1
- package/dist/customize/connectors/detail/connector-advanced-tools.d.ts +4 -1
- package/dist/customize/connectors/detail/connector-advanced-tools.js +2 -2
- package/dist/customize/connectors/detail/connector-agents.d.ts +14 -0
- package/dist/customize/connectors/detail/connector-agents.js +69 -0
- package/dist/customize/connectors/detail/connector-detail-tabs.js +2 -1
- package/dist/customize/connectors/detail/connector-move-row.d.ts +8 -5
- package/dist/customize/connectors/detail/connector-move-row.js +23 -14
- package/dist/customize/connectors/detail/connector-page.d.ts +4 -1
- package/dist/customize/connectors/detail/connector-page.js +14 -10
- package/dist/customize/connectors/detail/connector-policy-sets.d.ts +28 -0
- package/dist/customize/connectors/detail/connector-policy-sets.js +203 -0
- package/dist/customize/connectors/detail/connector-settings.d.ts +4 -1
- package/dist/customize/connectors/detail/connector-settings.js +7 -3
- package/dist/customize/connectors/detail/connector-status.d.ts +19 -6
- package/dist/customize/connectors/detail/connector-status.js +34 -10
- package/dist/customize/connectors/detail/connector-tabs.d.ts +4 -1
- package/dist/customize/connectors/detail/connector-tabs.js +8 -2
- package/dist/customize/connectors/detail/connector-tools.d.ts +3 -3
- package/dist/customize/connectors/detail/connector-tools.js +105 -48
- package/dist/customize/connectors/detail/email-inboxes.d.ts +43 -0
- package/dist/customize/connectors/detail/email-inboxes.js +184 -0
- package/dist/customize/connectors/detail/provider-info.d.ts +1 -1
- package/dist/customize/connectors/detail/provider-info.js +2 -2
- package/dist/customize/connectors/detail/status-badge.d.ts +1 -1
- package/dist/customize/connectors/detail/status-badge.js +4 -5
- package/dist/customize/connectors/detail/use-connector-detail.d.ts +6 -0
- package/dist/customize/connectors/detail/use-connector-detail.js +14 -4
- package/dist/customize/connectors/install/install-dialog.d.ts +23 -0
- package/dist/customize/connectors/install/install-dialog.js +40 -0
- package/dist/customize/connectors/install/install.d.ts +13 -2
- package/dist/customize/connectors/install/install.js +9 -4
- package/dist/customize/connectors/install/use-install.d.ts +19 -2
- package/dist/customize/connectors/install/use-install.js +65 -37
- package/dist/customize/connectors/install/way-kind.d.ts +5 -0
- package/dist/customize/connectors/install/way-kind.js +16 -0
- package/dist/customize/connectors/provider-label.d.ts +2 -1
- package/dist/customize/connectors/provider-label.js +13 -3
- package/dist/customize/connectors/tools/pattern-rule-draft.d.ts +4 -0
- package/dist/customize/connectors/tools/pattern-rule-draft.js +12 -3
- package/dist/customize/connectors/tools/policy-sets.d.ts +27 -0
- package/dist/customize/connectors/tools/policy-sets.js +41 -0
- package/dist/customize/connectors/tools/tool-groups.d.ts +32 -9
- package/dist/customize/connectors/tools/tool-groups.js +78 -16
- package/dist/customize/connectors/tools/tool-policy-control.d.ts +11 -10
- package/dist/customize/connectors/tools/tool-policy-control.js +15 -16
- package/dist/customize/connectors/tools/tool-policy-labels.d.ts +6 -5
- package/dist/customize/connectors/tools/tool-policy-labels.js +17 -16
- package/dist/customize/connectors/tools/tool-policy.d.ts +50 -4
- package/dist/customize/connectors/tools/tool-policy.js +74 -8
- package/dist/customize/connectors/use-agent-access.d.ts +85 -0
- package/dist/customize/connectors/use-agent-access.js +72 -0
- package/dist/customize/migrate-to-v2/index.d.ts +1 -2
- package/dist/customize/migrate-to-v2/index.js +1 -2
- package/dist/customize/migrate-to-v2/migration-prompt.d.ts +12 -25
- package/dist/customize/migrate-to-v2/migration-prompt.js +34 -236
- package/dist/customize/migrate-to-v2/upgrade-defs.d.ts +1 -1
- package/dist/customize/migrate-to-v2/upgrade-defs.js +7 -6
- package/dist/customize/migrate-to-v2/upgrade-view.js +7 -7
- package/dist/customize/migrate-to-v2/use-run-upgrade.d.ts +3 -3
- package/dist/customize/providers/provider-accordion.js +17 -2
- package/dist/customize/sections/component/channel-access-panel.d.ts +16 -0
- package/dist/customize/sections/component/channel-access-panel.js +146 -0
- package/dist/customize/sections/component/channel-connect-hero.d.ts +3 -2
- package/dist/customize/sections/component/channel-connect-hero.js +3 -2
- package/dist/customize/sections/component/channel-hero-frame.d.ts +31 -0
- package/dist/customize/sections/component/channel-hero-frame.js +40 -0
- package/dist/customize/sections/component/channel-mocks.d.ts +6 -0
- package/dist/customize/sections/component/channel-mocks.js +46 -0
- package/dist/customize/sections/component/channel-row.d.ts +13 -3
- package/dist/customize/sections/component/channel-row.js +10 -4
- package/dist/customize/sections/component/email-connect-form.d.ts +27 -0
- package/dist/customize/sections/component/email-connect-form.js +183 -0
- package/dist/customize/sections/component/slack-connect-card.d.ts +7 -0
- package/dist/customize/sections/component/slack-connect-card.js +2 -3
- package/dist/customize/sections/component/teams-connect-card.d.ts +7 -0
- package/dist/customize/sections/component/teams-connect-card.js +2 -3
- package/dist/customize/sections/component/telegram-channel-row.js +21 -28
- package/dist/customize/sections/connectors-view.d.ts +1 -15
- package/dist/customize/sections/connectors-view.js +81 -314
- package/dist/customize/sections/view/agent-editor-catalog.js +10 -0
- package/dist/customize/sections/view/channels-view.d.ts +6 -1
- package/dist/customize/sections/view/channels-view.js +72 -81
- package/dist/customize/sections/view/gateway/gateway-overview.js +10 -2
- package/dist/customize/settings/rail.js +9 -0
- package/dist/customize/settings/settings-tabs.d.ts +1 -1
- package/dist/customize/settings/settings-tabs.js +1 -0
- package/dist/customize/settings/tabs/chrome-connections-tab.d.ts +6 -0
- package/dist/customize/settings/tabs/chrome-connections-tab.js +99 -0
- package/dist/customize/settings/tabs/experimental-tab.js +35 -16
- package/dist/customize/shared/catalog/catalog-empty-state.d.ts +4 -15
- package/dist/customize/shared/catalog/catalog-empty-state.js +9 -7
- package/dist/customize/shared/channels-switch-dialog.d.ts +18 -0
- package/dist/customize/shared/channels-switch-dialog.js +30 -0
- package/dist/customize/shared/feature-gate-screen.js +27 -9
- package/dist/customize/shared/use-customize-prefetch.d.ts +2 -3
- package/dist/customize/shared/use-customize-prefetch.js +9 -27
- package/dist/customize/triggers/schedule/post-to-field.d.ts +18 -0
- package/dist/customize/triggers/schedule/post-to-field.js +49 -0
- package/dist/customize/triggers/schedule/schedule-copy.d.ts +10 -6
- package/dist/customize/triggers/schedule/schedule-copy.js +42 -11
- package/dist/customize/triggers/schedule/schedule-detail-sheet.js +2 -1
- package/dist/customize/triggers/schedule/trigger-composer-logic.d.ts +22 -0
- package/dist/customize/triggers/schedule/trigger-composer-logic.js +25 -0
- package/dist/customize/triggers/schedule/trigger-composer.d.ts +5 -0
- package/dist/customize/triggers/schedule/trigger-composer.js +23 -14
- package/dist/customize/triggers/schedule/trigger-edit-logic.js +3 -0
- package/dist/customize/triggers/schedule/trigger-filter.js +1 -1
- package/dist/customize/triggers/schedule/trigger-runs-logic.d.ts +2 -2
- package/dist/customize/triggers/schedule/trigger-runs-panel.js +1 -0
- package/dist/customize/triggers/schedule/trigger-toast.js +2 -1
- package/dist/customize/triggers/schedule-view.js +5 -2
- package/dist/files/index.d.ts +1 -0
- package/dist/files/index.js +1 -0
- package/dist/files/project/change-request-recovery.d.ts +1 -26
- package/dist/files/project/change-request-recovery.js +1 -59
- package/dist/files/project/components/change-request-detail-dialog.js +13 -3
- package/dist/files/project/components/drive-explorer.js +15 -15
- package/dist/files/project/components/drive-toolbar.d.ts +16 -2
- package/dist/files/project/components/drive-toolbar.js +14 -5
- package/dist/files/project/hooks/use-change-request-recovery.js +3 -19
- package/dist/files/project/hooks/use-change-requests.d.ts +1 -0
- package/dist/files/project/hooks/use-change-requests.js +11 -2
- package/dist/files/renderers/image-frame.d.ts +48 -0
- package/dist/files/renderers/image-frame.js +59 -0
- package/dist/files/renderers/image-renderer.d.ts +11 -1
- package/dist/files/renderers/image-renderer.js +13 -3
- package/dist/files/renderers/pdf/pdf-clipboard.d.ts +2 -0
- package/dist/files/renderers/pdf/pdf-clipboard.js +21 -0
- package/dist/files/renderers/pdf/pdf-viewer.js +4 -2
- package/dist/files/renderers/show-content-renderer.d.ts +9 -1
- package/dist/files/renderers/show-content-renderer.js +56 -14
- package/dist/files/runtime/file-source.js +2 -0
- package/dist/files/runtime/hooks/use-binary-blob.d.ts +10 -1
- package/dist/files/runtime/hooks/use-binary-blob.js +10 -4
- package/dist/files/runtime/hooks/use-shared-image.d.ts +41 -0
- package/dist/files/runtime/hooks/use-shared-image.js +177 -0
- package/dist/files/viewer/file-content-renderer.d.ts +22 -1
- package/dist/files/viewer/file-content-renderer.js +50 -7
- package/dist/files/viewer/file-header.d.ts +7 -3
- package/dist/files/viewer/file-header.js +20 -11
- package/dist/files/viewer/file-preview-modal.d.ts +1 -1
- package/dist/files/viewer/file-preview-modal.js +10 -22
- package/dist/files/viewer/file-source.d.ts +13 -0
- package/dist/files/viewer/use-file-content-state.d.ts +2 -0
- package/dist/files/viewer/use-file-content-state.js +28 -10
- package/dist/files/viewer/viewer-actions.d.ts +3 -1
- package/dist/files/viewer/viewer-actions.js +2 -2
- package/dist/hooks/use-media-query.d.ts +1 -0
- package/dist/hooks/use-mobile.d.ts +5 -0
- package/dist/hooks/use-mobile.js +8 -0
- package/dist/i18n/en.d.ts +1062 -85
- package/dist/i18n/en.js +1078 -101
- package/dist/i18n/ui-catalog/localize-ui-catalog.js +4 -0
- package/dist/i18n/ui-catalog/remaining-ui-translation-keys.generated.js +15 -3
- package/dist/index.d.ts +2 -2
- package/dist/index.js +2 -2
- package/dist/internal/account-hub/account-settings-sidebar.js +1 -1
- package/dist/internal/account-hub/hub-sheet.d.ts +9 -1
- package/dist/internal/account-hub/hub-sheet.js +21 -5
- package/dist/internal/account-hub/sections.d.ts +1 -1
- package/dist/internal/account-hub/sections.js +2 -1
- package/dist/internal/apps-and-extensions/apps-modal.d.ts +9 -0
- package/dist/internal/apps-and-extensions/apps-modal.js +107 -0
- package/dist/internal/auth/auth-card-shell.js +3 -3
- package/dist/internal/chrome/browser-icon.d.ts +24 -0
- package/dist/internal/chrome/browser-icon.js +58 -0
- package/dist/internal/chrome/chrome-card-state.d.ts +16 -0
- package/dist/internal/chrome/chrome-card-state.js +9 -0
- package/dist/internal/chrome/chrome-connect.d.ts +69 -0
- package/dist/internal/chrome/chrome-connect.js +178 -0
- package/dist/internal/chrome/chrome-mock.d.ts +4 -0
- package/dist/internal/chrome/chrome-mock.js +15 -0
- package/dist/internal/chrome/chrome-names.d.ts +15 -0
- package/dist/internal/chrome/chrome-names.js +35 -0
- package/dist/internal/chrome/extension.d.ts +47 -0
- package/dist/internal/chrome/extension.js +91 -0
- package/dist/internal/chrome/use-chrome-offered.d.ts +11 -0
- package/dist/internal/chrome/use-chrome-offered.js +22 -0
- package/dist/internal/components/agent-mark.js +5 -2
- package/dist/internal/connector-logo/connector-logo-source.d.ts +64 -0
- package/dist/internal/connector-logo/connector-logo-source.js +49 -0
- package/dist/internal/connector-logo/connector-logo.d.ts +39 -0
- package/dist/internal/connector-logo/connector-logo.js +56 -0
- package/dist/internal/connector-logo/connector-mark-files.d.ts +11 -0
- package/dist/internal/connector-logo/connector-mark-files.js +35 -0
- package/dist/internal/files/file-read-retry.d.ts +13 -0
- package/dist/internal/files/file-read-retry.js +23 -3
- package/dist/internal/files/session-drive-files.d.ts +5 -1
- package/dist/internal/files/session-drive-files.js +7 -2
- package/dist/internal/hooks/channels/use-channels-installations.d.ts +32 -5
- package/dist/internal/hooks/channels/use-channels-installations.js +55 -7
- package/dist/internal/hooks/channels/use-email-inboxes.d.ts +19 -0
- package/dist/internal/hooks/channels/use-email-inboxes.js +48 -0
- package/dist/internal/hooks/connectors/use-add-account.js +1 -1
- package/dist/internal/hooks/index.d.ts +1 -1
- package/dist/internal/hooks/index.js +1 -1
- package/dist/internal/hooks/projects/use-new-project-session.d.ts +9 -0
- package/dist/internal/hooks/projects/use-new-project-session.js +28 -12
- package/dist/internal/hooks/use-auto-scroll.d.ts +8 -1
- package/dist/internal/hooks/use-auto-scroll.js +4 -4
- package/dist/internal/icons/edge.d.ts +5 -0
- package/dist/internal/icons/edge.js +10 -0
- package/dist/internal/icons/telegram.d.ts +5 -0
- package/dist/internal/icons/telegram.js +6 -1
- package/dist/internal/layout/nav-hover-card.d.ts +35 -0
- package/dist/internal/layout/nav-hover-card.js +84 -0
- package/dist/internal/layout/project-nav-row.d.ts +3 -1
- package/dist/internal/layout/project-nav-row.js +3 -2
- package/dist/internal/layout/project-page-header.d.ts +4 -2
- package/dist/internal/layout/project-page-header.js +4 -3
- package/dist/internal/layout/project-settings-nav.js +59 -2
- package/dist/internal/lib/browser-error-noise.d.ts +1 -1
- package/dist/internal/lib/browser-error-noise.js +1 -1
- package/dist/internal/lib/browser-noise/rules/extensions.js +17 -3
- package/dist/internal/lib/browser-noise/rules/injected-scripts.d.ts +7 -0
- package/dist/internal/lib/browser-noise/rules/injected-scripts.js +15 -0
- package/dist/internal/lib/detect-os.d.ts +43 -0
- package/dist/internal/lib/detect-os.js +70 -0
- package/dist/internal/lib/manifest-version.d.ts +1 -1
- package/dist/internal/lib/manifest-version.js +2 -2
- package/dist/internal/lib/memory-href.d.ts +16 -0
- package/dist/internal/lib/memory-href.js +46 -0
- package/dist/internal/lib/use-project-feature-flags.js +13 -9
- package/dist/internal/lib/utils/heic-convert.d.ts +1 -1
- package/dist/internal/lib/utils/heic-convert.js +3 -4
- package/dist/internal/lib/web-notifications.d.ts +20 -0
- package/dist/internal/lib/web-notifications.js +48 -4
- package/dist/internal/notifications/notification-bell.d.ts +4 -1
- package/dist/internal/notifications/notification-bell.js +2 -2
- package/dist/internal/selection/selection-bar.d.ts +2 -1
- package/dist/internal/selection/selection-bar.js +1 -1
- package/dist/internal/stores/apps-modal-store.d.ts +8 -0
- package/dist/internal/stores/apps-modal-store.js +6 -0
- package/dist/internal/stores/composer-prefill-store.d.ts +12 -5
- package/dist/internal/stores/file-preview-store.d.ts +29 -2
- package/dist/internal/stores/file-preview-store.js +19 -1
- package/dist/internal/stores/kortix-computer-store.js +3 -0
- package/dist/internal/stores/sidebar-nav-store.d.ts +1 -1
- package/dist/internal/stores/sidebar-nav-store.js +3 -1
- package/dist/lib/routes.d.ts +13 -1
- package/dist/lib/routes.js +13 -0
- package/dist/markdown/index.d.ts +2 -1
- package/dist/markdown/index.js +2 -1
- package/dist/markdown/setup-links/approval-decision.d.ts +1 -0
- package/dist/markdown/setup-links/approval-decision.js +9 -3
- package/dist/markdown/setup-links/connector-handshake.d.ts +3 -1
- package/dist/markdown/setup-links/connector-handshake.js +12 -10
- package/dist/markdown/setup-links/secret-intake-form.d.ts +0 -10
- package/dist/markdown/setup-links/secret-intake-form.js +1 -1
- package/dist/markdown/setup-links/show-connect-hero.d.ts +28 -0
- package/dist/markdown/setup-links/show-connect-hero.js +91 -0
- package/dist/markdown/unified-markdown.js +5 -5
- package/dist/primitives/badge.d.ts +1 -1
- package/dist/primitives/badge.js +2 -0
- package/dist/primitives/disclosure.js +14 -2
- package/dist/primitives/empty-art.d.ts +12 -0
- package/dist/primitives/empty-art.js +11 -0
- package/dist/primitives/empty-state.d.ts +2 -2
- package/dist/primitives/empty-state.js +6 -5
- package/dist/primitives/mermaid-renderer.d.ts +2 -0
- package/dist/primitives/mermaid-renderer.js +21 -15
- package/dist/primitives/resizable.js +6 -1
- package/dist/primitives/resize-seam.d.ts +11 -0
- package/dist/primitives/resize-seam.js +12 -0
- package/dist/primitives/sidebar-panel.js +4 -7
- package/dist/primitives/tabs.d.ts +14 -1
- package/dist/primitives/tabs.js +1 -1
- package/dist/providers/ui-provider.d.ts +9 -0
- package/dist/session/composer/ComposerAboveCard.d.ts +1 -1
- package/dist/session/composer/ComposerAboveCard.js +2 -2
- package/dist/session/composer/ComposerCard.d.ts +1 -1
- package/dist/session/composer/ComposerCard.js +3 -3
- package/dist/session/composer/agent-selector.d.ts +13 -1
- package/dist/session/composer/agent-selector.js +25 -5
- package/dist/session/composer/composer-agent-access.d.ts +15 -0
- package/dist/session/composer/composer-agent-access.js +27 -0
- package/dist/session/composer/composer-chat-input.d.ts +8 -2
- package/dist/session/composer/composer-chat-input.js +8 -6
- package/dist/session/composer/composer-logic.d.ts +16 -0
- package/dist/session/composer/composer-logic.js +12 -0
- package/dist/session/composer/composer-underbar.d.ts +3 -1
- package/dist/session/composer/composer-underbar.js +4 -3
- package/dist/session/composer/composer.d.ts +15 -1
- package/dist/session/composer/composer.js +19 -1
- package/dist/session/composer/draft/composer-draft.d.ts +6 -2
- package/dist/session/composer/draft/composer-draft.js +5 -1
- package/dist/session/composer/reasoning-effort-selector.js +1 -1
- package/dist/session/models/chatgpt-connection-button.d.ts +11 -0
- package/dist/session/models/chatgpt-connection-button.js +54 -0
- package/dist/session/models/model-selector.js +5 -2
- package/dist/session/models/use-model-connection-gate.d.ts +5 -5
- package/dist/session/models/use-model-connection-gate.js +5 -5
- package/dist/session/outcomes/jump-to-outcome.d.ts +10 -0
- package/dist/session/outcomes/jump-to-outcome.js +11 -0
- package/dist/session/outcomes/session-outcomes-bridge.d.ts +14 -0
- package/dist/session/outcomes/session-outcomes-bridge.js +12 -0
- package/dist/session/outcomes/session-outcomes-provider.d.ts +3 -1
- package/dist/session/outcomes/session-outcomes-provider.js +33 -3
- package/dist/session/panel/easy/app-preview.d.ts +10 -0
- package/dist/session/panel/easy/app-preview.js +31 -12
- package/dist/session/panel/easy/change-requests-card.d.ts +7 -0
- package/dist/session/panel/easy/change-requests-card.js +17 -0
- package/dist/session/panel/easy/easy-panel-logic.js +7 -1
- package/dist/session/panel/easy/easy-panel.js +5 -2
- package/dist/session/panel/easy/file-preview.js +1 -1
- package/dist/session/panel/easy/outputs-card.d.ts +2 -1
- package/dist/session/panel/easy/outputs-card.js +3 -2
- package/dist/session/panel/mobile-tool-drawer.js +7 -1
- package/dist/session/panel/session-audit-panel.js +9 -2
- package/dist/session/panel/session-audit-shared.js +3 -1
- package/dist/session/panel/session-detail-panel.js +9 -3
- package/dist/session/panel/session-files-explorer.d.ts +9 -0
- package/dist/session/panel/session-files-explorer.js +12 -3
- package/dist/session/panel/session-panel-provider.d.ts +15 -1
- package/dist/session/panel/session-panel-provider.js +32 -7
- package/dist/session/panel/shared/derive-panels.d.ts +8 -1
- package/dist/session/panel/shared/derive-panels.js +12 -2
- package/dist/session/panel/shared/output-priority.js +2 -0
- package/dist/session/participants/session-participants.d.ts +8 -2
- package/dist/session/participants/session-participants.js +11 -4
- package/dist/session/prompts/approval-request.d.ts +5 -0
- package/dist/session/prompts/approval-request.js +9 -1
- package/dist/session/prompts/session-approval-review.d.ts +9 -0
- package/dist/session/prompts/session-approval-review.js +18 -0
- package/dist/session/status/session-error-banner.js +2 -49
- package/dist/session/status/session-starting-loader.d.ts +14 -2
- package/dist/session/status/session-starting-loader.js +16 -4
- package/dist/session/thread/after-first-prompt.d.ts +7 -0
- package/dist/session/thread/after-first-prompt.js +8 -0
- package/dist/session/thread/detect-command.d.ts +12 -0
- package/dist/session/thread/detect-command.js +20 -0
- package/dist/session/thread/session-chat.d.ts +3 -1
- package/dist/session/thread/session-chat.js +377 -252
- package/dist/session/thread/session-thread.d.ts +15 -1
- package/dist/session/thread/session-thread.js +20 -3
- package/dist/session/thread/session-transcript-class.d.ts +5 -1
- package/dist/session/thread/session-transcript-class.js +5 -1
- package/dist/session/thread/thread-boot-rows.d.ts +36 -0
- package/dist/session/thread/thread-boot-rows.js +89 -0
- package/dist/session/thread/transcript-rows.d.ts +31 -0
- package/dist/session/thread/transcript-rows.js +3 -0
- package/dist/session/thread/transcript.d.ts +0 -9
- package/dist/session/thread/transcript.js +104 -19
- package/dist/session/tool/shared/infrastructure-contexts.d.ts +28 -0
- package/dist/session/tool/shared/infrastructure-contexts.js +31 -3
- package/dist/session/tool/tool-part-renderer.d.ts +5 -4
- package/dist/session/tool/tool-part-renderer.js +8 -3
- package/dist/session/tool/tools/bash-tool.js +7 -6
- package/dist/session/tool/tools/channel-send-card.d.ts +1 -2
- package/dist/session/tool/tools/channel-send.d.ts +2 -1
- package/dist/session/tool/tools/codemode-tool.js +1 -1
- package/dist/session/tool/tools/connector-tools.js +1 -1
- package/dist/session/tool/tools/image-gen-tool.d.ts +1 -1
- package/dist/session/tool/tools/image-gen-tool.js +241 -53
- package/dist/session/tool/tools/show-tool.js +19 -8
- package/dist/session/turn/channel-brand.d.ts +8 -3
- package/dist/session/turn/channel-brand.js +20 -4
- package/dist/session/turn/message-author.d.ts +8 -0
- package/dist/session/turn/message-author.js +24 -0
- package/dist/session/turn/message-row.d.ts +52 -0
- package/dist/session/turn/message-row.js +44 -0
- package/dist/session/turn/plan-anchor.d.ts +1 -1
- package/dist/session/turn/plan-anchor.js +1 -1
- package/dist/session/turn/user-message.d.ts +14 -6
- package/dist/session/turn/user-message.js +35 -15
- package/dist/styles.css +1 -1
- package/dist/workspace/home/access-requests-bell.d.ts +9 -2
- package/dist/workspace/home/access-requests-bell.js +20 -6
- package/dist/workspace/home/first-chat.d.ts +8 -21
- package/dist/workspace/home/first-chat.js +22 -72
- package/dist/workspace/index.d.ts +6 -0
- package/dist/workspace/index.js +6 -0
- package/dist/workspace/layout/project-home.d.ts +14 -2
- package/dist/workspace/layout/project-home.js +60 -21
- package/dist/workspace/layout/use-project-home-send.d.ts +9 -1
- package/dist/workspace/layout/use-project-home-send.js +82 -3
- package/dist/workspace/memory/body-doc.d.ts +17 -0
- package/dist/workspace/memory/body-doc.js +208 -0
- package/dist/workspace/memory/body-extensions.d.ts +38 -0
- package/dist/workspace/memory/body-extensions.js +103 -0
- package/dist/workspace/memory/company-memory-page.d.ts +8 -0
- package/dist/workspace/memory/company-memory-page.js +16 -0
- package/dist/workspace/memory/memory-all.d.ts +20 -0
- package/dist/workspace/memory/memory-all.js +27 -0
- package/dist/workspace/memory/memory-body.d.ts +19 -0
- package/dist/workspace/memory/memory-body.js +139 -0
- package/dist/workspace/memory/memory-empty.d.ts +13 -0
- package/dist/workspace/memory/memory-empty.js +28 -0
- package/dist/workspace/memory/memory-history.d.ts +27 -0
- package/dist/workspace/memory/memory-history.js +108 -0
- package/dist/workspace/memory/memory-labels.d.ts +16 -0
- package/dist/workspace/memory/memory-labels.js +47 -0
- package/dist/workspace/memory/memory-page-list.d.ts +34 -0
- package/dist/workspace/memory/memory-page-list.js +156 -0
- package/dist/workspace/memory/memory-reader.d.ts +58 -0
- package/dist/workspace/memory/memory-reader.js +123 -0
- package/dist/workspace/memory/memory-view.d.ts +21 -0
- package/dist/workspace/memory/memory-view.js +124 -0
- package/dist/workspace/memory/remember-popover.d.ts +19 -0
- package/dist/workspace/memory/remember-popover.js +61 -0
- package/dist/workspace/memory/remember-this.d.ts +12 -0
- package/dist/workspace/memory/remember-this.js +89 -0
- package/dist/workspace/memory/source-mark.d.ts +18 -0
- package/dist/workspace/memory/source-mark.js +79 -0
- package/dist/workspace/memory/used-memory-chip.d.ts +14 -0
- package/dist/workspace/memory/used-memory-chip.js +61 -0
- package/dist/workspace/new/advanced-fields.d.ts +2 -1
- package/dist/workspace/new/advanced-fields.js +2 -2
- package/dist/workspace/new/source-param.d.ts +1 -1
- package/dist/workspace/new/source-param.js +3 -1
- package/dist/workspace/new/use-create-workspace.d.ts +8 -10
- package/dist/workspace/new/use-create-workspace.js +3 -3
- package/dist/workspace/projects/onboarding/app-logo.d.ts +7 -2
- package/dist/workspace/projects/onboarding/app-logo.js +6 -13
- package/dist/workspace/projects/policies-panel.js +5 -3
- package/dist/workspace/review/review-actions.d.ts +4 -2
- package/dist/workspace/review/review-actions.js +8 -2
- package/dist/workspace/review/review-center.js +11 -7
- package/dist/workspace/review/review-detail.d.ts +10 -0
- package/dist/workspace/review/review-detail.js +101 -13
- package/dist/workspace/saved-session-skeleton.d.ts +2 -2
- package/dist/workspace/saved-session-skeleton.js +3 -3
- package/dist/workspace/session-workspace.js +15 -13
- package/dist/workspace/sessions/project-sessions-view.js +3 -2
- package/dist/workspace/sessions/session-label-badges.js +2 -1
- package/dist/workspace/sessions/sessions-toolbar.d.ts +3 -1
- package/dist/workspace/sessions/sessions-toolbar.js +2 -2
- package/dist/workspace/sidebar/footer/project-apps-nav.d.ts +5 -0
- package/dist/workspace/sidebar/footer/project-apps-nav.js +41 -2
- package/dist/workspace/sidebar/footer/project-artifacts-nav.d.ts +6 -0
- package/dist/workspace/sidebar/footer/project-artifacts-nav.js +22 -0
- package/dist/workspace/sidebar/footer/project-chrome-nav.d.ts +10 -0
- package/dist/workspace/sidebar/footer/project-chrome-nav.js +56 -0
- package/dist/workspace/sidebar/footer/project-manifest-upgrade-alert.js +13 -13
- package/dist/workspace/sidebar/footer/project-memory-nav.d.ts +7 -0
- package/dist/workspace/sidebar/footer/project-memory-nav.js +19 -0
- package/dist/workspace/sidebar/nav-row-meta.js +14 -2
- package/dist/workspace/sidebar/project-nav-items.js +3 -0
- package/dist/workspace/sidebar/project-session-list.js +68 -56
- package/dist/workspace/sidebar/project-sidebar.js +13 -2
- package/dist/workspace/sidebar/project-spaces-nav.d.ts +8 -0
- package/dist/workspace/sidebar/project-spaces-nav.js +69 -0
- package/dist/workspace/sidebar/session-group-order.d.ts +9 -0
- package/dist/workspace/sidebar/session-group-order.js +25 -0
- package/dist/workspace/sidebar/session-group-sections.d.ts +62 -0
- package/dist/workspace/sidebar/session-group-sections.js +267 -0
- package/dist/workspace/sidebar/session-list-chrome.d.ts +28 -0
- package/dist/workspace/sidebar/session-list-chrome.js +50 -0
- package/dist/workspace/spaces/channel-glyph.d.ts +5 -0
- package/dist/workspace/spaces/channel-glyph.js +6 -0
- package/dist/workspace/spaces/channel-setup.d.ts +16 -0
- package/dist/workspace/spaces/channel-setup.js +105 -0
- package/dist/workspace/spaces/channels-onboarding.d.ts +13 -0
- package/dist/workspace/spaces/channels-onboarding.js +37 -0
- package/dist/workspace/spaces/create-channel-dialog.d.ts +16 -0
- package/dist/workspace/spaces/create-channel-dialog.js +158 -0
- package/dist/workspace/spaces/private-channels-not-in.d.ts +9 -0
- package/dist/workspace/spaces/private-channels-not-in.js +69 -0
- package/dist/workspace/spaces/space-agents.d.ts +10 -0
- package/dist/workspace/spaces/space-agents.js +10 -0
- package/dist/workspace/spaces/space-details-dialog.d.ts +20 -0
- package/dist/workspace/spaces/space-details-dialog.js +176 -0
- package/dist/workspace/spaces/space-link-label.d.ts +49 -0
- package/dist/workspace/spaces/space-link-label.js +73 -0
- package/dist/workspace/spaces/space-links.d.ts +19 -0
- package/dist/workspace/spaces/space-links.js +230 -0
- package/dist/workspace/spaces/space-members.d.ts +46 -0
- package/dist/workspace/spaces/space-members.js +182 -0
- package/dist/workspace/spaces/space-roster.d.ts +15 -0
- package/dist/workspace/spaces/space-roster.js +44 -0
- package/dist/workspace/spaces/space-threads-tab.d.ts +56 -0
- package/dist/workspace/spaces/space-threads-tab.js +156 -0
- package/dist/workspace/spaces/space-timeline-view.d.ts +254 -0
- package/dist/workspace/spaces/space-timeline-view.js +235 -0
- package/dist/workspace/spaces/space-timeline.d.ts +106 -0
- package/dist/workspace/spaces/space-timeline.js +183 -0
- package/dist/workspace/spaces/space-triggers.d.ts +13 -0
- package/dist/workspace/spaces/space-triggers.js +78 -0
- package/dist/workspace/spaces/space-view.d.ts +37 -0
- package/dist/workspace/spaces/space-view.js +436 -0
- package/package.json +67 -36
- package/skills/kortix-ui/SKILL.md +3 -3
- package/skills/kortix-ui/references/custom-dashboard.md +3 -3
- package/skills/kortix-ui/references/modules.md +29 -5
- package/skills/kortix-ui/references/theming.md +1 -1
- package/dist/customize/connectors/catalog/merge-search.d.ts +0 -10
- package/dist/customize/connectors/catalog/merge-search.js +0 -26
- package/dist/customize/connectors/detail/find-easy-connect-app.d.ts +0 -29
- package/dist/customize/connectors/detail/find-easy-connect-app.js +0 -22
- package/dist/customize/migrate-to-v2/use-migrate-to-v2.d.ts +0 -9
- package/dist/customize/migrate-to-v2/use-migrate-to-v2.js +0 -24
- package/dist/customize/sections/connector-connection-header.d.ts +0 -36
- package/dist/customize/sections/connector-connection-header.js +0 -33
- package/dist/customize/sections/connector-connection-modal.d.ts +0 -34
- package/dist/customize/sections/connector-connection-modal.js +0 -72
- package/dist/customize/sections/discover-catalogue-card.d.ts +0 -19
- package/dist/customize/sections/discover-catalogue-card.js +0 -26
- package/dist/customize/sections/discover-catalogue-detail.d.ts +0 -15
- package/dist/customize/sections/discover-catalogue-detail.js +0 -24
- package/dist/customize/sections/discover-catalogue.d.ts +0 -17
- package/dist/customize/sections/discover-catalogue.js +0 -132
- package/dist/customize/sections/llm-provider/provider-access-menu.d.ts +0 -10
- package/dist/customize/sections/llm-provider/provider-access-menu.js +0 -23
- package/dist/files/project/components/drive-empty-art.d.ts +0 -2
- package/dist/files/project/components/drive-empty-art.js +0 -5
- package/dist/internal/hooks/use-media-query.d.ts +0 -2
- package/dist/internal/share/public-share-link-button.d.ts +0 -14
- package/dist/internal/share/public-share-link-button.js +0 -17
- package/dist/markdown/setup-links/app-credentials-form.d.ts +0 -12
- package/dist/markdown/setup-links/app-credentials-form.js +0 -115
- /package/dist/{internal/hooks → hooks}/use-media-query.js +0 -0
|
@@ -0,0 +1,54 @@
|
|
|
1
|
+
'use client';
|
|
2
|
+
import { jsx as _jsx, jsxs as _jsxs } from "react/jsx-runtime";
|
|
3
|
+
import { useTranslations } from '../../i18n/index.js';
|
|
4
|
+
import { Button } from '../../primitives/button.js';
|
|
5
|
+
import { cn } from '../../lib/utils.js';
|
|
6
|
+
import { useSessionIds } from '../../providers/session-ids.js';
|
|
7
|
+
import { useUiComponents, useUiViewerId } from '../../providers/ui-provider.js';
|
|
8
|
+
import { useFeatureFlag, useModelAccess, useProjectSession, useSessionProviderSecretPools, } from '@kortix/sdk/react';
|
|
9
|
+
import { useState } from 'react';
|
|
10
|
+
import { chatGptActionApplies } from './chatgpt-connection-action.js';
|
|
11
|
+
import { sessionPersonalUser } from '../overrides/provider-pool-draft.js';
|
|
12
|
+
/**
|
|
13
|
+
* The ChatGPT fix for a failed turn or tool call (the session error row, the
|
|
14
|
+
* image card). It needs the session the call belongs to, so it renders only on
|
|
15
|
+
* a session route; elsewhere the row stays informational.
|
|
16
|
+
*/
|
|
17
|
+
export function ChatGptConnectionSlot({ action, className = 'mt-2 pl-7', }) {
|
|
18
|
+
const ids = useSessionIds();
|
|
19
|
+
const projectId = ids.projectId ?? null;
|
|
20
|
+
const sessionId = ids.sessionId ?? null;
|
|
21
|
+
if (!projectId || !sessionId)
|
|
22
|
+
return null;
|
|
23
|
+
return _jsx(ChatGptConnectionButton, { action: action, projectId: projectId, sessionId: sessionId, className: className });
|
|
24
|
+
}
|
|
25
|
+
/**
|
|
26
|
+
* Opens the ChatGPT accounts dialog, which exists only with pooled provider
|
|
27
|
+
* secrets and the LLM gateway on. Shown only where connecting or
|
|
28
|
+
* reconnecting an account can fix this session (`chatGptActionApplies`).
|
|
29
|
+
*/
|
|
30
|
+
function ChatGptConnectionButton({ action, projectId, sessionId, className, }) {
|
|
31
|
+
const t = useTranslations('pooledSecrets');
|
|
32
|
+
const viewerId = useUiViewerId();
|
|
33
|
+
const pooled = useFeatureFlag(projectId, 'pooled_provider_secrets');
|
|
34
|
+
const enabled = pooled.enabled;
|
|
35
|
+
const access = useModelAccess(enabled ? projectId : null);
|
|
36
|
+
const session = useProjectSession(projectId, sessionId, { enabled });
|
|
37
|
+
const pools = useSessionProviderSecretPools(enabled ? projectId : null, sessionId);
|
|
38
|
+
const [open, setOpen] = useState(false);
|
|
39
|
+
const { ProviderAccountsModal } = useUiComponents();
|
|
40
|
+
const applies = !!ProviderAccountsModal &&
|
|
41
|
+
enabled &&
|
|
42
|
+
!(access.data?.disabledProviders ?? []).includes('codex') &&
|
|
43
|
+
chatGptActionApplies({
|
|
44
|
+
action,
|
|
45
|
+
personalUser: sessionPersonalUser(session.data),
|
|
46
|
+
viewerId: viewerId,
|
|
47
|
+
explicitSelection: pools.isSuccess
|
|
48
|
+
? pools.data.pools.some((pool) => pool.provider_id === 'codex')
|
|
49
|
+
: undefined,
|
|
50
|
+
});
|
|
51
|
+
if (!applies || !ProviderAccountsModal)
|
|
52
|
+
return null;
|
|
53
|
+
return (_jsxs("div", { className: cn(className), children: [_jsx(Button, { size: "sm", className: "active:scale-[0.96]", onClick: () => setOpen(true), children: t(action === 'reconnect' ? 'reconnectChatGpt' : 'connectChatGpt') }), _jsx(ProviderAccountsModal, { projectId: projectId, providerId: "codex", open: open, onOpenChange: setOpen })] }));
|
|
54
|
+
}
|
|
@@ -106,7 +106,7 @@ function ModelRow({ model, groupProviderID, groupProviderName, isSelected, isAcc
|
|
|
106
106
|
providerID: model.providerID,
|
|
107
107
|
modelID: model.modelID,
|
|
108
108
|
});
|
|
109
|
-
}, className: cn('absolute inset-0 flex cursor-pointer items-center justify-center rounded-md', 'text-muted-foreground
|
|
109
|
+
}, className: cn('absolute inset-0 flex cursor-pointer items-center justify-center rounded-md', 'text-muted-foreground hover:text-foreground hover:bg-foreground/10',
|
|
110
110
|
/* `opacity` is NOT in this list, on purpose — see above. These
|
|
111
111
|
only ever run on the one row the cursor is on, so they cannot
|
|
112
112
|
leave a trail. */
|
|
@@ -304,7 +304,10 @@ export function ModelSelector({ models, selectedModel, onSelect, defaultControls
|
|
|
304
304
|
setOpen(false);
|
|
305
305
|
openUpgrade();
|
|
306
306
|
}, [openUpgrade, setOpen]);
|
|
307
|
-
return (_jsxs(_Fragment, { children: [connectionModal, projectId && chatGptPossible && ProviderAccountsModal && (_jsx(ProviderAccountsModal, { projectId: projectId, providerId: "codex", open: chatGptOpen, onOpenChange: setChatGptOpen })), _jsxs(CommandPopover, { open: disabled ? false : open, onOpenChange: (next) => !disabled && setOpen(next), children: [_jsx(CommandPopoverTrigger, { children: appearance === 'field' ? (_jsxs("button", { type: "button", disabled: disabled, className: cn(triggerVariants(), 'h-9 w-full'), children: [_jsx("span", { className: "truncate", children: displayName }), disabled ? null : _jsx(ChevronDown, { className: cn(TRIGGER_CARET_CLASS, 'size-4') })] })) : (_jsxs(Button, { type: "button", variant: triggerVariant, size: "sm",
|
|
307
|
+
return (_jsxs(_Fragment, { children: [connectionModal, projectId && chatGptPossible && ProviderAccountsModal && (_jsx(ProviderAccountsModal, { projectId: projectId, providerId: "codex", open: chatGptOpen, onOpenChange: setChatGptOpen })), _jsxs(CommandPopover, { open: disabled ? false : open, onOpenChange: (next) => !disabled && setOpen(next), children: [_jsx(CommandPopoverTrigger, { children: appearance === 'field' ? (_jsxs("button", { type: "button", disabled: disabled, className: cn(triggerVariants(), 'h-9 w-full'), children: [_jsx("span", { className: "truncate", children: displayName }), disabled ? null : _jsx(ChevronDown, { className: cn(TRIGGER_CARET_CLASS, 'size-4') })] })) : (_jsxs(Button, { type: "button", variant: triggerVariant, size: "sm",
|
|
308
|
+
// `min-w-0 shrink`: in a narrow toolbar (a channel's thread panel) the
|
|
309
|
+
// model name truncates; the controls beside it keep their width.
|
|
310
|
+
className: cn('min-w-0 shrink rounded-lg hit-area-y-3', triggerVariant === 'ghost' && 'text-muted-foreground'), children: [_jsx("span", { className: cn('max-w-30 truncate', triggerLabelClassName), children: displayName }), _jsx(ChevronDown, { className: cn('duration-moderate size-3 transition-transform ease-out', open && 'rotate-180') })] })) }), _jsx(CommandPopoverContent, { side: "top", align: "start", sideOffset: 8, className: "w-[min(300px,calc(100vw-1.5rem))]", children: _jsxs(_Fragment, { children: [_jsx(CommandInput, { compact: true, placeholder: tModel('search'), value: search, onValueChange: setSearch, rightElement: canManageModels && canConnectProvider ? (_jsxs("div", { className: "-mr-0.5 flex shrink-0 items-center gap-0.5", children: [_jsx(Hint, { label: tModel('connectProvider'), side: "top", className: "z-50", children: _jsx("button", { type: "button", "aria-label": tModel('addProvider'), onClick: () => handleOpenProviderModal('providers'), className: "text-muted-foreground hover:text-foreground hover:bg-muted flex size-8 cursor-pointer items-center justify-center rounded-md transition-colors", children: _jsx(Plus, { className: "size-4" }) }) }), _jsx(Hint, { label: tModel('manageModels'), side: "top", className: "z-50", children: _jsx("button", { type: "button", "aria-label": tModel('manageModels'), onClick: () => handleOpenProviderModal('models'), className: "text-muted-foreground hover:text-foreground hover:bg-muted flex size-8 cursor-pointer items-center justify-center rounded-md transition-colors", children: _jsx(SlidersHorizontal, { className: "size-4" }) }) })] })) : undefined }), grouped.length > 1 && _jsx(CommandSeparator, { className: "bg-border/60" }), _jsx(CommandList, { className: "max-h-[380px]", children: modelsLoading || entitlementsPending ? (_jsx("div", { className: "flex min-h-32 items-center justify-center", role: "status", "aria-label": tModel('loading'), children: _jsx(Loading, { className: "text-muted-foreground size-4 shrink-0" }) })) : grouped.length > 0 ? (_jsxs(_Fragment, { children: [pinnedDefault && (_jsxs(_Fragment, { children: [_jsx(CommandGroup, { heading: _jsx(GroupHeading, { children: tModel('yourDefault') }), forceMount: true, children: _jsx(ModelRow, { model: pinnedDefault.model, groupProviderID: pinnedDefault.providerID, groupProviderName: pinnedDefault.providerName, isSelected: availableSelectedModel?.providerID === pinnedDefault.model.providerID &&
|
|
308
311
|
availableSelectedModel?.modelID === pinnedDefault.model.modelID, isAccountDefault: true, defaultControls: rowDefaultControls, onSelect: handleSelect, connectLabel: tPooled('connect'), scope: "pinned" }) }), _jsx(CommandSeparator, {})] })), sections.map((section, sectionIndex) => {
|
|
309
312
|
const selectedInSection = section.models.find((m) => availableSelectedModel?.providerID === m.providerID &&
|
|
310
313
|
availableSelectedModel?.modelID === m.modelID);
|
|
@@ -12,11 +12,9 @@ export declare function projectProviderModalTab(tab: ProviderModalTab): 'provide
|
|
|
12
12
|
* route segment is the fallback.
|
|
13
13
|
*
|
|
14
14
|
* The fallback is what every original caller relies on — they all render under
|
|
15
|
-
* `/projects/[id]`. The explicit id
|
|
16
|
-
*
|
|
17
|
-
*
|
|
18
|
-
* `openConnectProvider` renders nothing while the step's only control never
|
|
19
|
-
* advances the wizard.
|
|
15
|
+
* `/projects/[id]`. The explicit id serves callers outside that route, such as
|
|
16
|
+
* Customize's provider list: there the route may yield `null`, `modal` is
|
|
17
|
+
* then `null`, and `openConnectProvider` renders nothing.
|
|
20
18
|
*
|
|
21
19
|
* `!== undefined`, never `??`: a caller that deliberately passes `null` means
|
|
22
20
|
* "act on no project", and must not silently inherit whatever route it happens
|
|
@@ -47,6 +45,8 @@ export declare function useModelConnectionGate(models?: FlatModel[], options?: {
|
|
|
47
45
|
projectId?: string | null;
|
|
48
46
|
}): {
|
|
49
47
|
canConnectProvider: boolean;
|
|
48
|
+
/** The viewer holds `project.model.write`: the provider modal can change the project's models. */
|
|
49
|
+
canWriteProviders: boolean;
|
|
50
50
|
openConnectProvider: (tab?: ProviderModalTab) => void;
|
|
51
51
|
openUpgrade: () => void;
|
|
52
52
|
modal: import("react").JSX.Element | null;
|
|
@@ -27,11 +27,9 @@ export function projectProviderModalTab(tab) {
|
|
|
27
27
|
* route segment is the fallback.
|
|
28
28
|
*
|
|
29
29
|
* The fallback is what every original caller relies on — they all render under
|
|
30
|
-
* `/projects/[id]`. The explicit id
|
|
31
|
-
*
|
|
32
|
-
*
|
|
33
|
-
* `openConnectProvider` renders nothing while the step's only control never
|
|
34
|
-
* advances the wizard.
|
|
30
|
+
* `/projects/[id]`. The explicit id serves callers outside that route, such as
|
|
31
|
+
* Customize's provider list: there the route may yield `null`, `modal` is
|
|
32
|
+
* then `null`, and `openConnectProvider` renders nothing.
|
|
35
33
|
*
|
|
36
34
|
* `!== undefined`, never `??`: a caller that deliberately passes `null` means
|
|
37
35
|
* "act on no project", and must not silently inherit whatever route it happens
|
|
@@ -154,6 +152,8 @@ export function useModelConnectionGate(models = [], options) {
|
|
|
154
152
|
const showUpgradeOption = !!platformConfig().billingEnabled;
|
|
155
153
|
return {
|
|
156
154
|
canConnectProvider,
|
|
155
|
+
/** The viewer holds `project.model.write`: the provider modal can change the project's models. */
|
|
156
|
+
canWriteProviders,
|
|
157
157
|
openConnectProvider,
|
|
158
158
|
openUpgrade,
|
|
159
159
|
modal,
|
|
@@ -0,0 +1,10 @@
|
|
|
1
|
+
import { type LoadEntireHistoryOptions } from '../print/load-entire-history.js';
|
|
2
|
+
/** Resolve again after paging: older pages can change the first loaded turn's anchor. */
|
|
3
|
+
export declare function jumpToOutcome({ needsHistory, history, resolve, scroll, unavailable, loadError }: {
|
|
4
|
+
needsHistory: boolean;
|
|
5
|
+
history: LoadEntireHistoryOptions;
|
|
6
|
+
resolve: () => string | undefined;
|
|
7
|
+
scroll: (key: string) => Promise<boolean>;
|
|
8
|
+
unavailable: () => void;
|
|
9
|
+
loadError: () => void;
|
|
10
|
+
}): Promise<void>;
|
|
@@ -0,0 +1,11 @@
|
|
|
1
|
+
import { loadEntireHistory } from '../print/load-entire-history.js';
|
|
2
|
+
/** Resolve again after paging: older pages can change the first loaded turn's anchor. */
|
|
3
|
+
export async function jumpToOutcome({ needsHistory, history, resolve, scroll, unavailable, loadError }) {
|
|
4
|
+
if (needsHistory && !(await loadEntireHistory(history)).exhausted) {
|
|
5
|
+
loadError();
|
|
6
|
+
return;
|
|
7
|
+
}
|
|
8
|
+
const key = resolve();
|
|
9
|
+
if (!key || !await scroll(key))
|
|
10
|
+
unavailable();
|
|
11
|
+
}
|
|
@@ -0,0 +1,14 @@
|
|
|
1
|
+
import { type Dispatch, type ReactNode, type SetStateAction } from 'react';
|
|
2
|
+
import type { ChangeRequest } from '@kortix/sdk';
|
|
3
|
+
export interface SessionChangeRequests {
|
|
4
|
+
requests: ChangeRequest[];
|
|
5
|
+
onOpen: (crId: string) => void;
|
|
6
|
+
onJump: (crId: string) => Promise<void>;
|
|
7
|
+
jumping: boolean;
|
|
8
|
+
}
|
|
9
|
+
/** Chat and the mobile panel are siblings. Share the existing read, never a second query. */
|
|
10
|
+
export declare function SessionOutcomesBridge({ children }: {
|
|
11
|
+
children: ReactNode;
|
|
12
|
+
}): import("react").JSX.Element;
|
|
13
|
+
export declare const useSessionChangeRequestsPanel: () => SessionChangeRequests | null;
|
|
14
|
+
export declare const usePublishSessionChangeRequests: () => Dispatch<SetStateAction<SessionChangeRequests | null>> | null;
|
|
@@ -0,0 +1,12 @@
|
|
|
1
|
+
'use client';
|
|
2
|
+
import { jsx as _jsx } from "react/jsx-runtime";
|
|
3
|
+
import { createContext, useContext, useState } from 'react';
|
|
4
|
+
const ReadContext = createContext(null);
|
|
5
|
+
const WriteContext = createContext(null);
|
|
6
|
+
/** Chat and the mobile panel are siblings. Share the existing read, never a second query. */
|
|
7
|
+
export function SessionOutcomesBridge({ children }) {
|
|
8
|
+
const [value, setValue] = useState(null);
|
|
9
|
+
return (_jsx(WriteContext.Provider, { value: setValue, children: _jsx(ReadContext.Provider, { value: value, children: children }) }));
|
|
10
|
+
}
|
|
11
|
+
export const useSessionChangeRequestsPanel = () => useContext(ReadContext);
|
|
12
|
+
export const usePublishSessionChangeRequests = () => useContext(WriteContext);
|
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
import { type ReactNode } from 'react';
|
|
2
2
|
import { type TurnSpan } from './anchor-outcomes.js';
|
|
3
3
|
import type { Outcome } from '../../internal/outcomes/outcome-types.js';
|
|
4
|
-
export declare function SessionOutcomesProvider({ projectSessionId, turnSpans, busy, onOpen, children, }: {
|
|
4
|
+
export declare function SessionOutcomesProvider({ projectSessionId, turnSpans, busy, onOpen, children, onJump, jumping, }: {
|
|
5
5
|
/** The git session id a change request records as `origin_session_id`. */
|
|
6
6
|
projectSessionId: string | undefined;
|
|
7
7
|
turnSpans: TurnSpan[];
|
|
@@ -9,6 +9,8 @@ export declare function SessionOutcomesProvider({ projectSessionId, turnSpans, b
|
|
|
9
9
|
busy: boolean;
|
|
10
10
|
onOpen: (outcome: Outcome) => void;
|
|
11
11
|
children: ReactNode;
|
|
12
|
+
onJump: (resolveTurn: () => string | undefined, createdAt: number) => Promise<void>;
|
|
13
|
+
jumping: boolean;
|
|
12
14
|
}): import("react").JSX.Element;
|
|
13
15
|
/** A turn's outcomes, oldest first. `EMPTY` is a module constant so a turn with
|
|
14
16
|
* no outcomes gets the SAME array every render and never re-renders for it. */
|
|
@@ -45,6 +45,9 @@ import { useProjectContext } from '../../files/project/context.js';
|
|
|
45
45
|
// NOT `@kortix/sdk/react`'s change-request hook. See the note above — this is
|
|
46
46
|
// a cache-coherence requirement, not a style preference.
|
|
47
47
|
import { invalidateChangeRequestReads, useSessionChangeRequests, } from '../../files/project/hooks/use-change-requests.js';
|
|
48
|
+
import { usePublishSessionChangeRequests } from './session-outcomes-bridge.js';
|
|
49
|
+
import { useProjectCan } from '../../internal/lib/use-project-can.js';
|
|
50
|
+
import { PROJECT_ACTIONS } from '../../internal/lib/project-actions.js';
|
|
48
51
|
import { anchorOutcomes } from './anchor-outcomes.js';
|
|
49
52
|
import { changeRequestOutcomes } from './change-request-outcomes.js';
|
|
50
53
|
const EMPTY = [];
|
|
@@ -52,7 +55,7 @@ const OutcomesContext = createContext(null);
|
|
|
52
55
|
/** A change request the agent opens as its turn closes can land after the
|
|
53
56
|
* turn-end read: read once more after this delay. */
|
|
54
57
|
const CHANGE_REQUEST_SETTLE_MS = 2_500;
|
|
55
|
-
export function SessionOutcomesProvider({ projectSessionId, turnSpans, busy, onOpen, children, }) {
|
|
58
|
+
export function SessionOutcomesProvider({ projectSessionId, turnSpans, busy, onOpen, children, onJump, jumping, }) {
|
|
56
59
|
const tI18nComplete = useTranslations('hardcodedUi.i18nComplete');
|
|
57
60
|
// No `projectId` argument: this hook reads it from `ProjectFilesProvider`,
|
|
58
61
|
// which is what keeps it on the same cache entry the dialog invalidates.
|
|
@@ -60,15 +63,42 @@ export function SessionOutcomesProvider({ projectSessionId, turnSpans, busy, onO
|
|
|
60
63
|
// the turn that produced it — it just reads "Applied" or "Closed".
|
|
61
64
|
// Only THIS session's change requests, filtered by the server; the key sits
|
|
62
65
|
// under the project-files list scope the dialog's mutations invalidate.
|
|
63
|
-
const
|
|
66
|
+
const projectId = useProjectContext()?.projectId;
|
|
67
|
+
const { allowed } = useProjectCan(projectId, PROJECT_ACTIONS.PROJECT_GITOPS_READ);
|
|
68
|
+
const { data } = useSessionChangeRequests(projectSessionId, { refetchInterval: busy ? 5_000 : 60_000, enabled: allowed });
|
|
69
|
+
const requests = useMemo(() => allowed ? (data?.change_requests ?? []) : [], [allowed, data?.change_requests]);
|
|
64
70
|
useRefreshChangeRequestsOnTurnEnd(busy);
|
|
65
71
|
const all = useMemo(
|
|
66
72
|
// Change requests are the only outcome a turn produces. The derived
|
|
67
73
|
// pipeline (files, schedules, background tasks, connector links) was built
|
|
68
74
|
// and removed — see `OutcomeKind` for why each one could not be tied to the
|
|
69
75
|
// turn that showed it.
|
|
70
|
-
() => changeRequestOutcomes(
|
|
76
|
+
() => changeRequestOutcomes(requests, projectSessionId, tI18nComplete), [requests, projectSessionId, tI18nComplete]);
|
|
71
77
|
const byTurn = useMemo(() => anchorOutcomes(all, turnSpans), [all, turnSpans]);
|
|
78
|
+
const anchorsRef = useRef(byTurn);
|
|
79
|
+
useEffect(() => { anchorsRef.current = byTurn; }, [byTurn]);
|
|
80
|
+
const publish = usePublishSessionChangeRequests();
|
|
81
|
+
const panelValue = useMemo(() => ({
|
|
82
|
+
requests,
|
|
83
|
+
onOpen: (crId) => {
|
|
84
|
+
const outcome = all.find((item) => item.id === `cr:${crId}`);
|
|
85
|
+
// Rows open this request, not a superseding request's detail.
|
|
86
|
+
if (outcome)
|
|
87
|
+
onOpen({ ...outcome, action: { ...outcome.action, target: crId } });
|
|
88
|
+
},
|
|
89
|
+
onJump: (crId) => onJump(() => {
|
|
90
|
+
for (const [key, outcomes] of anchorsRef.current) {
|
|
91
|
+
if (outcomes.some((item) => item.id === `cr:${crId}`))
|
|
92
|
+
return key;
|
|
93
|
+
}
|
|
94
|
+
return undefined;
|
|
95
|
+
}, Date.parse(requests.find((cr) => cr.cr_id === crId)?.created_at ?? '')),
|
|
96
|
+
jumping,
|
|
97
|
+
}), [requests, all, onOpen, onJump, jumping]);
|
|
98
|
+
useEffect(() => {
|
|
99
|
+
publish?.(panelValue);
|
|
100
|
+
return () => publish?.(null);
|
|
101
|
+
}, [publish, panelValue]);
|
|
72
102
|
const value = useMemo(() => ({ byTurn, onOpen }), [byTurn, onOpen]);
|
|
73
103
|
return _jsx(OutcomesContext.Provider, { value: value, children: children });
|
|
74
104
|
}
|
|
@@ -1,3 +1,4 @@
|
|
|
1
|
+
import { type ReactNode } from 'react';
|
|
1
2
|
import { type ShareContext } from '../../../files/viewer/viewer-actions.js';
|
|
2
3
|
export declare function AppPreview({ url, name, projectId, shareContext, onClose, onSendToAgent, }: {
|
|
3
4
|
/** The internal sandbox URL the agent handed over, e.g. http://localhost:3000. */
|
|
@@ -17,3 +18,12 @@ export declare function AppPreview({ url, name, projectId, shareContext, onClose
|
|
|
17
18
|
* shows only Retry, exactly as before. */
|
|
18
19
|
onSendToAgent?: () => void;
|
|
19
20
|
}): import("react").JSX.Element;
|
|
21
|
+
/**
|
|
22
|
+
* The Browser card while the session's computer boots: the real toolbar, every
|
|
23
|
+
* control that needs the computer disabled, over `children` (the boot status).
|
|
24
|
+
* Mounts nothing that reaches the sandbox: no proxy, no app list, no frame.
|
|
25
|
+
*/
|
|
26
|
+
export declare function AppPreviewBooting({ onClose, children, }: {
|
|
27
|
+
onClose: () => void;
|
|
28
|
+
children: ReactNode;
|
|
29
|
+
}): import("react").JSX.Element;
|
|
@@ -36,7 +36,7 @@ import { useBrowserRecentsStore } from '../../../internal/stores/browser-recents
|
|
|
36
36
|
import { probePreviewPort } from '@kortix/sdk';
|
|
37
37
|
import { useRuntimeConnectionStore } from '@kortix/sdk/react';
|
|
38
38
|
import { ArrowSquareOutIcon, GlobeIcon as Globe, SparkleIcon as SparklesSolid, WarningIcon, } from '@phosphor-icons/react';
|
|
39
|
-
import { useCallback, useEffect, useMemo, useRef, useState, useSyncExternalStore } from 'react';
|
|
39
|
+
import { useCallback, useEffect, useMemo, useRef, useState, useSyncExternalStore, } from 'react';
|
|
40
40
|
import { PreviewLoadingOverlay, SandboxAddressBar, } from '../../../browser/sandbox-browser-chrome.js';
|
|
41
41
|
import { BrowserLanding } from '../../../browser/browser-landing.js';
|
|
42
42
|
import { CloseButton, DetailSidebarToggle } from './detail-view.js';
|
|
@@ -97,7 +97,6 @@ export function AppPreview({ url, name, projectId, shareContext, onClose, onSend
|
|
|
97
97
|
// Still loading past PREVIEW_SLOW_MS: the overlay says so and offers Reload.
|
|
98
98
|
const [slow, setSlow] = useState(false);
|
|
99
99
|
const addressRef = useRef(null);
|
|
100
|
-
const isMobile = useIsMobile();
|
|
101
100
|
// Copy link mints a PUBLIC share and copies `/share/session/{token}`.
|
|
102
101
|
// It used to copy `previewUrl` — the authenticated `/v1/p/{sandbox}/{port}/…`
|
|
103
102
|
// proxy URL — which only ever worked in the tab that had the
|
|
@@ -235,16 +234,11 @@ export function AppPreview({ url, name, projectId, shareContext, onClose, onSend
|
|
|
235
234
|
setIndex((i) => i + 1);
|
|
236
235
|
reload();
|
|
237
236
|
}, [canGoForward, reload]);
|
|
238
|
-
return (_jsxs("div", { className: "bg-background flex h-full min-h-0 min-w-0 flex-col", children: [
|
|
239
|
-
|
|
240
|
-
|
|
241
|
-
|
|
242
|
-
|
|
243
|
-
if (!previewUrl)
|
|
244
|
-
return;
|
|
245
|
-
track('app_opened_new_tab');
|
|
246
|
-
window.open(previewUrl, '_blank', 'noopener,noreferrer');
|
|
247
|
-
}, className: "size-7 shrink-0 active:scale-[0.96]", children: _jsx(ArrowSquareOutIcon, { className: "size-3.5" }) }) }), _jsx(PanelWidthButton, { isMobile: isMobile }), _jsx(CloseButton, { onClose: onClose })] })] }), _jsxs("div", { className: "relative min-h-0 flex-1 overflow-hidden", children: [isLoading && hasPreview && !noApp && (_jsx(PreviewLoadingOverlay, { label: tI18nComplete.raw('textc4cf2b2ccb5d'), detail: slow ? previewSlowReason({ port }) : undefined, action: slow ? (_jsx(Button, { variant: "outline", size: "sm", className: "gap-1.5", onClick: reload, children: tI18nComplete.raw('textbdc090ec61e3') })) : undefined })), (hasError || hostPreview.failed) && !noApp && (_jsx(ErrorState, { icon: WarningIcon, size: "sm", className: "bg-background absolute inset-0 z-10", title: tI18nComplete('textba601cdb484b', { value0: title }),
|
|
237
|
+
return (_jsxs("div", { className: "bg-background flex h-full min-h-0 min-w-0 flex-col", children: [_jsx(AppPreviewToolbar, { previewUrl: previewUrl, onClose: onClose, displayValue: current, isLoading: isLoading, canGoBack: canGoBack, canGoForward: canGoForward, onBack: goBack, onForward: goForward, onReload: reload, onHome: () => navigateTo(''), onNavigate: navigateTo, suggestions: suggestions, inputRef: addressRef, trailing:
|
|
238
|
+
// An app has no file to save and no text to put on a clipboard, so
|
|
239
|
+
// `Copy link` is the one copy action — the thing you can hand
|
|
240
|
+
// someone for a running port.
|
|
241
|
+
_jsx(ViewerActions, { copy: appCopy, shareContext: shareContext, shareInput: shareInput }) }), _jsxs("div", { className: "relative min-h-0 flex-1 overflow-hidden", children: [isLoading && hasPreview && !noApp && (_jsx(PreviewLoadingOverlay, { label: tI18nComplete.raw('textc4cf2b2ccb5d'), detail: slow ? previewSlowReason({ port }) : undefined, action: slow ? (_jsx(Button, { variant: "outline", size: "sm", className: "gap-1.5", onClick: reload, children: tI18nComplete.raw('textbdc090ec61e3') })) : undefined })), (hasError || hostPreview.failed) && !noApp && (_jsx(ErrorState, { icon: WarningIcon, size: "sm", className: "bg-background absolute inset-0 z-10", title: tI18nComplete('textba601cdb484b', { value0: title }),
|
|
248
242
|
/* The single most common cause, said plainly: the agent started the
|
|
249
243
|
server a moment ago and it isn't listening yet. Only a SETTLED
|
|
250
244
|
`dead` verdict earns the stopped-workspace wording — see
|
|
@@ -274,6 +268,31 @@ export function AppPreview({ url, name, projectId, shareContext, onClose, onSend
|
|
|
274
268
|
// frame reads as "your app is broken".
|
|
275
269
|
_jsx("div", { className: "flex h-full items-center justify-center", children: _jsx(Loading, { className: "size-4" }) }))] })] }));
|
|
276
270
|
}
|
|
271
|
+
/**
|
|
272
|
+
* The Browser card's toolbar: sidebar toggle, address bar, open in a new tab,
|
|
273
|
+
* width, close. Shared by the live preview and the booting card, so the two
|
|
274
|
+
* cannot drift.
|
|
275
|
+
*/
|
|
276
|
+
function AppPreviewToolbar({ previewUrl, onClose, ...address }) {
|
|
277
|
+
const tI18nComplete = useTranslations('hardcodedUi.i18nComplete');
|
|
278
|
+
const isMobile = useIsMobile();
|
|
279
|
+
return (_jsxs("div", { className: "border-border flex shrink-0 items-center gap-0.5 border-b px-2 py-1", children: [_jsx(DetailSidebarToggle, {}), _jsx(SandboxAddressBar, { ...address, hasPreview: !!previewUrl, placeholder: tI18nComplete.raw('text878abd024f27') }), _jsxs(ButtonGroup, { className: "shrink-0", children: [_jsx(Hint, { label: tI18nComplete.raw('text306ef19c8ac3'), side: "bottom", children: _jsx(Button, { variant: "secondary", size: "icon", disabled: !previewUrl, "aria-label": tI18nComplete.raw('text306ef19c8ac3'), onClick: () => {
|
|
280
|
+
if (!previewUrl)
|
|
281
|
+
return;
|
|
282
|
+
track('app_opened_new_tab');
|
|
283
|
+
window.open(previewUrl, '_blank', 'noopener,noreferrer');
|
|
284
|
+
}, className: "size-7 shrink-0 active:scale-[0.96]", children: _jsx(ArrowSquareOutIcon, { className: "size-3.5" }) }) }), _jsx(PanelWidthButton, { isMobile: isMobile }), _jsx(CloseButton, { onClose: onClose })] })] }));
|
|
285
|
+
}
|
|
286
|
+
const noop = () => { };
|
|
287
|
+
/**
|
|
288
|
+
* The Browser card while the session's computer boots: the real toolbar, every
|
|
289
|
+
* control that needs the computer disabled, over `children` (the boot status).
|
|
290
|
+
* Mounts nothing that reaches the sandbox: no proxy, no app list, no frame.
|
|
291
|
+
*/
|
|
292
|
+
export function AppPreviewBooting({ onClose, children, }) {
|
|
293
|
+
const addressRef = useRef(null);
|
|
294
|
+
return (_jsxs("div", { className: "bg-background flex h-full min-h-0 min-w-0 flex-col", children: [_jsx(AppPreviewToolbar, { onClose: onClose, displayValue: "", isLoading: false, canGoBack: false, canGoForward: false, onBack: noop, onForward: noop, onReload: noop, onHome: noop, onNavigate: noop, inputRef: addressRef, disabled: true }), _jsx("div", { className: "relative min-h-0 flex-1 overflow-hidden", children: children })] }));
|
|
295
|
+
}
|
|
277
296
|
function SearchHint() {
|
|
278
297
|
const tI18nComplete = useTranslations('hardcodedUi.i18nComplete');
|
|
279
298
|
return (_jsx("div", { className: "flex flex-1 items-center justify-center", children: _jsxs("div", { className: "text-muted-foreground flex flex-col items-center gap-4 px-4 text-center", children: [_jsx(Globe, { className: "size-12 opacity-20" }), _jsx("p", { className: "text-sm", children: tI18nComplete.raw('text2f883b75cd2d') })] }) }));
|
|
@@ -0,0 +1,7 @@
|
|
|
1
|
+
import type { ChangeRequest } from '@kortix/sdk';
|
|
2
|
+
export declare function ChangeRequestsCard({ requests, onOpen, onJump, jumping }: {
|
|
3
|
+
requests: ChangeRequest[];
|
|
4
|
+
onOpen: (crId: string) => void;
|
|
5
|
+
onJump: (crId: string) => Promise<void>;
|
|
6
|
+
jumping?: boolean;
|
|
7
|
+
}): import("react").JSX.Element | null;
|
|
@@ -0,0 +1,17 @@
|
|
|
1
|
+
'use client';
|
|
2
|
+
import { jsxs as _jsxs, jsx as _jsx } from "react/jsx-runtime";
|
|
3
|
+
import { ArrowBendUpLeftIcon } from '@phosphor-icons/react';
|
|
4
|
+
import { useLocale, useTranslations } from '../../../i18n/index.js';
|
|
5
|
+
import { relativeTime } from '../../../internal/lib/relative-time.js';
|
|
6
|
+
import { ChangeRequestStatusBadge } from '../../../files/project/components/change-request-status-badge.js';
|
|
7
|
+
import { Badge } from '../../../primitives/badge.js';
|
|
8
|
+
import { Button } from '../../../primitives/button.js';
|
|
9
|
+
import Hint from '../../../primitives/hint.js';
|
|
10
|
+
import { PanelCard } from './panel-card.js';
|
|
11
|
+
export function ChangeRequestsCard({ requests, onOpen, onJump, jumping = false }) {
|
|
12
|
+
const t = useTranslations('sessionChangeRequests');
|
|
13
|
+
const locale = useLocale();
|
|
14
|
+
if (requests.length === 0)
|
|
15
|
+
return null;
|
|
16
|
+
return (_jsx(PanelCard, { title: t('title'), count: requests.length, isEmpty: false, defaultExpanded: true, fill: true, contentClassName: "min-h-0 overflow-y-auto px-2 py-2", children: _jsx("ul", { children: [...requests].sort((a, b) => Date.parse(b.created_at) - Date.parse(a.created_at)).map((cr) => (_jsxs("li", { className: "flex items-center gap-1", children: [_jsxs("button", { type: "button", "data-cr-id": cr.cr_id, onClick: () => onOpen(cr.cr_id), className: "hover:bg-accent flex min-w-0 flex-1 flex-col gap-1 rounded-sm px-2 py-2 text-left", children: [_jsxs("span", { className: "flex w-full min-w-0 items-baseline gap-2", children: [_jsxs("span", { className: "text-muted-foreground shrink-0 text-xs tabular-nums", children: ["#", cr.number] }), _jsx("span", { className: "text-foreground truncate text-sm", children: cr.title })] }), _jsxs("span", { className: "flex flex-wrap items-center gap-2", children: [cr.status === 'open' ? _jsx(Badge, { variant: "secondary", size: "sm", children: t('open') }) : _jsx(ChangeRequestStatusBadge, { cr: cr }), _jsx("time", { dateTime: cr.created_at, className: "text-muted-foreground text-xs", children: relativeTime(cr.created_at, locale) })] })] }), _jsx(Hint, { label: t('jump', { number: cr.number }), children: _jsx(Button, { variant: "ghost", size: "icon", disabled: jumping, "aria-label": t('jump', { number: cr.number }), onClick: () => onJump(cr.cr_id), children: _jsx(ArrowBendUpLeftIcon, { className: "size-3.5 shrink-0" }) }) })] }, cr.cr_id))) }) }));
|
|
17
|
+
}
|
|
@@ -2,6 +2,7 @@
|
|
|
2
2
|
* Pure logic for `EasyPanel`, split out from the client component purely so
|
|
3
3
|
* it is unit-testable without a DOM.
|
|
4
4
|
*/
|
|
5
|
+
import { parseArtifactUrl } from '../../../artifacts/frame-policy.js';
|
|
5
6
|
import { isKortixAppUrl } from '../../../apps/kortix-app-url.js';
|
|
6
7
|
import { parseLocalhostUrl } from '@kortix/sdk';
|
|
7
8
|
/**
|
|
@@ -43,6 +44,10 @@ export function quickBrowserOutput(apps,
|
|
|
43
44
|
* wrong page.
|
|
44
45
|
*/
|
|
45
46
|
target) {
|
|
47
|
+
// An artifact's app link opens as the artifact (the browser cannot frame the Kortix app).
|
|
48
|
+
if (target?.url && parseArtifactUrl(target.url)) {
|
|
49
|
+
return { callID: 'quick-browser', name: target.title || 'Artifact', kind: 'artifact', url: target.url };
|
|
50
|
+
}
|
|
46
51
|
return {
|
|
47
52
|
callID: 'quick-browser',
|
|
48
53
|
name: target?.title || 'Browser',
|
|
@@ -98,7 +103,7 @@ export function sandboxRecents(recents) {
|
|
|
98
103
|
* - web pages (`.html/.htm` — same viewport assumption as apps).
|
|
99
104
|
*/
|
|
100
105
|
export function isWideDeliverable(output) {
|
|
101
|
-
if (output.kind === 'presentation' || output.kind === 'app')
|
|
106
|
+
if (output.kind === 'presentation' || output.kind === 'app' || output.kind === 'artifact')
|
|
102
107
|
return true;
|
|
103
108
|
return /\.(pptx?|key|xlsx?|csv|tsv|html?)$/i.test(output.name);
|
|
104
109
|
}
|
|
@@ -168,6 +173,7 @@ export function deriveIsRunning(stepsRunning, sessionBusy) {
|
|
|
168
173
|
* "Apps"). */
|
|
169
174
|
const KIND_GROUP_LABEL = {
|
|
170
175
|
app: 'Apps',
|
|
176
|
+
artifact: 'Artifacts',
|
|
171
177
|
presentation: 'Presentations',
|
|
172
178
|
image: 'Images',
|
|
173
179
|
video: 'Videos',
|
|
@@ -29,6 +29,8 @@ import { jsx as _jsx, jsxs as _jsxs } from "react/jsx-runtime";
|
|
|
29
29
|
import { usePlanInChat } from '../../thread/plan-surface.js';
|
|
30
30
|
import { useSessionComposerPrefillStore } from '../../composer/stores/session-composer-prefill-store.js';
|
|
31
31
|
import { useOptionalSessionPanel } from '../session-panel-provider.js';
|
|
32
|
+
import { useSessionChangeRequestsPanel } from '../../outcomes/session-outcomes-bridge.js';
|
|
33
|
+
import { ChangeRequestsCard } from './change-requests-card.js';
|
|
32
34
|
import { AppsCard } from './apps-card.js';
|
|
33
35
|
import { ContextCard } from './context-card.js';
|
|
34
36
|
import { pathOutput } from './easy-panel-logic.js';
|
|
@@ -36,6 +38,7 @@ import { OutputsCard } from './outputs-card.js';
|
|
|
36
38
|
import { PlanPanelCard } from './plan-card.js';
|
|
37
39
|
export function EasyPanel() {
|
|
38
40
|
const panel = useOptionalSessionPanel();
|
|
41
|
+
const changeRequests = useSessionChangeRequestsPanel();
|
|
39
42
|
// Exactly one plan surface is mounted, ever. This card stands down only on
|
|
40
43
|
// mobile, where this same component is the detail drawer's home view and the
|
|
41
44
|
// drawer is shut by default, so the transcript keeps the plan. On desktop it
|
|
@@ -58,9 +61,9 @@ export function EasyPanel() {
|
|
|
58
61
|
// through everything above them.
|
|
59
62
|
//
|
|
60
63
|
// Now the column owns the height (`h-full`) and hands the leftover to
|
|
61
|
-
// exactly one card
|
|
64
|
+
// exactly one card: Change requests when present, otherwise Outputs. Context and
|
|
62
65
|
// Preview keep `shrink-0` and stay on screen at their full height, always.
|
|
63
66
|
// `min-h-0` is what lets this shrink at all — a flex container defaults to
|
|
64
67
|
// its content's minimum height and would otherwise refuse.
|
|
65
|
-
_jsxs("div", { className: "flex h-full min-h-0 flex-col gap-2", children: [_jsx(OutputsCard, { outputs: files, defaultExpanded: outputsDefaultOpen, onOpenOutput: (o) => handleOpenOutput(o, files) }), _jsx(ContextCard, { files: context.files, web: context.web, tools: context.tools, sessionId: sessionId, onOpenDetail: openDetail, onOpenFile: (path, allPaths) => handleOpenOutput(pathOutput(path), allPaths.map(pathOutput)), onAddContext: () => useSessionComposerPrefillStore.getState().requestAttach(sessionId) }), apps.length > 0 && _jsx(AppsCard, { apps: apps, onOpenApp: (a) => handleOpenOutput(a, apps) }), !planInChat && _jsx(PlanPanelCard, { sessionId: sessionId })] }));
|
|
68
|
+
_jsxs("div", { className: "flex h-full min-h-0 flex-col gap-2", children: [_jsx(OutputsCard, { fill: !changeRequests?.requests.length, outputs: files, defaultExpanded: outputsDefaultOpen, onOpenOutput: (o) => handleOpenOutput(o, files) }), _jsx(ContextCard, { files: context.files, web: context.web, tools: context.tools, sessionId: sessionId, onOpenDetail: openDetail, onOpenFile: (path, allPaths) => handleOpenOutput(pathOutput(path), allPaths.map(pathOutput)), onAddContext: () => useSessionComposerPrefillStore.getState().requestAttach(sessionId) }), apps.length > 0 && _jsx(AppsCard, { apps: apps, onOpenApp: (a) => handleOpenOutput(a, apps) }), !planInChat && _jsx(PlanPanelCard, { sessionId: sessionId }), changeRequests && _jsx(ChangeRequestsCard, { ...changeRequests })] }));
|
|
66
69
|
}
|
|
@@ -215,7 +215,7 @@ export function FilePreview({ path, name, fileName = name, shareContext, onClose
|
|
|
215
215
|
setPanelAspect(null);
|
|
216
216
|
}, [setPanelAspect]);
|
|
217
217
|
if (rich) {
|
|
218
|
-
return (_jsx(PreviewShell, { name: name, shareContext: shareContext, fileName: fileName, path: path, onClose: onClose, onPresent: onPresent, refresh: refresh, children: _jsx(FileSourceProvider, { value: workspaceFileSource, children: _jsx(PreviewFitProvider, { onMeasure: ({ width, height }) => setPanelAspect(width / height), onUnmeasurable: () => setPanelAspect(null), children: _jsx(FileContentRenderer, { filePath: path, reloadKey: reloadKey, showHeader: false, className: "h-full", fitOnOpen: isPdf, onStatusChange: handleStatusChange }) }) }) }));
|
|
218
|
+
return (_jsx(PreviewShell, { name: name, shareContext: shareContext, fileName: fileName, path: path, onClose: onClose, onPresent: onPresent, refresh: refresh, children: _jsx(FileSourceProvider, { value: workspaceFileSource, children: _jsx(PreviewFitProvider, { onMeasure: ({ width, height }) => setPanelAspect(width / height), onUnmeasurable: () => setPanelAspect(null), children: _jsx(FileContentRenderer, { filePath: path, reloadKey: reloadKey, showCaption: true, showHeader: false, className: "h-full", fitOnOpen: isPdf, onStatusChange: handleStatusChange }) }) }) }));
|
|
219
219
|
}
|
|
220
220
|
if (isLoading) {
|
|
221
221
|
return (_jsx(PreviewShell, { name: name, shareContext: shareContext, fileName: fileName, path: path, onClose: onClose, onPresent: onPresent, refresh: refresh, children: _jsx(Centered, { children: _jsx(Loading, {}) }) }));
|
|
@@ -14,8 +14,9 @@ export declare function OutputRows({ outputs, onOpenOutput, initialShowAll, }: {
|
|
|
14
14
|
*/
|
|
15
15
|
initialShowAll?: boolean;
|
|
16
16
|
}): import("react").JSX.Element;
|
|
17
|
-
export declare function OutputsCard({ outputs, defaultExpanded, onOpenOutput, }: {
|
|
17
|
+
export declare function OutputsCard({ outputs, defaultExpanded, onOpenOutput, fill, }: {
|
|
18
18
|
outputs: OutputItem[];
|
|
19
|
+
fill?: boolean;
|
|
19
20
|
/** Auto-expands when a run finishes with something to show — the payoff moment. */
|
|
20
21
|
defaultExpanded: boolean;
|
|
21
22
|
onOpenOutput: (output: OutputItem) => void;
|
|
@@ -34,6 +34,7 @@ const KIND_ICON = {
|
|
|
34
34
|
video: VideoIcon,
|
|
35
35
|
presentation: PresentationIcon,
|
|
36
36
|
app: AppWindow,
|
|
37
|
+
artifact: FileText,
|
|
37
38
|
};
|
|
38
39
|
/** `callID:path` → object URL, shared across rows and re-renders. Keyed by
|
|
39
40
|
* call, not bare path: paths repeat across sessions (`output.png`), and callID
|
|
@@ -193,9 +194,9 @@ function DownloadAllAction({ outputs }) {
|
|
|
193
194
|
};
|
|
194
195
|
return (_jsx(Hint, { label: tI18nComplete.raw('textf7917eced9c2'), side: "bottom", children: _jsx(Button, { variant: "ghost", size: "icon", onClick: () => void handleDownload(), disabled: busy, "aria-label": tI18nComplete.raw('textf7917eced9c2'), "aria-busy": busy, className: "size-7 active:scale-[0.96] disabled:opacity-100", children: busy ? (_jsx(Loading, { className: "text-muted-foreground size-3.5 motion-reduce:animate-none" })) : (_jsx(Download, { className: "size-3.5" })) }) }));
|
|
195
196
|
}
|
|
196
|
-
export function OutputsCard({ outputs, defaultExpanded, onOpenOutput, }) {
|
|
197
|
+
export function OutputsCard({ outputs, defaultExpanded, onOpenOutput, fill = true, }) {
|
|
197
198
|
const tI18nComplete = useTranslations('hardcodedUi.i18nComplete');
|
|
198
|
-
return (_jsx(PanelCard, { title: tI18nComplete.raw('texte7ce99764a2d'), count: outputs.length, isEmpty: outputs.length === 0, defaultExpanded: defaultExpanded, emptyArt: _jsx(OutputsArt, {}), emptyText: tI18nComplete.raw('textd5f2ad00f99b'), contentClassName:
|
|
199
|
+
return (_jsx(PanelCard, { title: tI18nComplete.raw('texte7ce99764a2d'), count: outputs.length, isEmpty: outputs.length === 0, defaultExpanded: defaultExpanded, emptyArt: _jsx(OutputsArt, {}), emptyText: tI18nComplete.raw('textd5f2ad00f99b'), contentClassName: cn('flex min-h-0 flex-col px-2 py-2', !fill && 'max-h-40 overflow-y-auto'), fill: fill, headerAction: _jsx(DownloadAllAction, { outputs: outputs }), children: _jsx(OutputRows, { outputs: outputs, onOpenOutput: onOpenOutput }) }));
|
|
199
200
|
}
|
|
200
201
|
/**
|
|
201
202
|
* Soft placeholder art — a stacked-document glyph, matching the reference.
|
|
@@ -24,6 +24,8 @@ import { SessionAuditPanel } from './session-audit-panel.js';
|
|
|
24
24
|
import { SessionRemindersPanel } from './session-reminders-panel.js';
|
|
25
25
|
import { SessionFilesExplorer } from './session-files-explorer.js';
|
|
26
26
|
import { SessionTerminalPanel } from '../../terminal/session-terminal-panel.js';
|
|
27
|
+
import { SessionBootStatus } from '../status/session-starting-loader.js';
|
|
28
|
+
import { useOptionalSessionPanel } from './session-panel-provider.js';
|
|
27
29
|
import { useLocalizedUiCatalog } from '../../i18n/ui-catalog/use-localized-ui-catalog.js';
|
|
28
30
|
import { useKortixComputerStore } from '../../internal/stores/kortix-computer-store.js';
|
|
29
31
|
import { sessionPreviewTabId } from '../../internal/stores/session-browser-store.js';
|
|
@@ -40,5 +42,9 @@ export function MobileToolDrawer({ sessionId, projectId, projectSessionId, }) {
|
|
|
40
42
|
const closeMobileTool = useKortixComputerStore((s) => s.closeMobileTool);
|
|
41
43
|
const toolMeta = useLocalizedUiCatalog(TOOL_META);
|
|
42
44
|
const meta = view ? toolMeta[view] : null;
|
|
43
|
-
|
|
45
|
+
// Terminal, Browser and Files need the computer: while it boots, the drawer
|
|
46
|
+
// shows the wake status in their place.
|
|
47
|
+
const booting = !!useOptionalSessionPanel()?.booting &&
|
|
48
|
+
(view === 'terminal' || view === 'browser' || view === 'files');
|
|
49
|
+
return (_jsx(Drawer, { open: view !== null, onOpenChange: (next) => !next && closeMobileTool(), children: _jsxs(DrawerContent, { className: "flex h-[95dvh] max-h-[95dvh] min-h-[95dvh] flex-col overflow-hidden p-0", children: [_jsx(DrawerHeader, { className: "shrink-0 px-4 py-3 text-left", children: _jsxs(DrawerTitle, { className: "flex items-center justify-between gap-2 text-base", children: [_jsxs("span", { className: "flex items-center gap-2.5", children: [meta && _jsx(meta.Icon, { className: "text-muted-foreground size-4 shrink-0" }), meta?.label] }), _jsx(CloseButton, { onClose: closeMobileTool, variant: "ghost" })] }) }), _jsxs("div", { className: "min-h-0 flex-1 overflow-hidden", children: [booting && _jsx(SessionBootStatus, { projectId: projectId, sessionId: projectSessionId }), !booting && view === 'terminal' && (_jsx(SessionTerminalPanel, { sessionId: sessionId, projectId: projectId, projectSessionId: projectSessionId })), !booting && view === 'browser' && (_jsx(BrowserPanel, { tabId: sessionPreviewTabId(sessionId), projectId: projectId, projectSessionId: projectSessionId })), !booting && view === 'files' && (_jsx(SessionFilesExplorer, { chatSessionId: sessionId, projectId: projectId, projectSessionId: projectSessionId })), view === 'audit' && (_jsx(SessionAuditPanel, { projectId: projectId, projectSessionId: projectSessionId })), view === 'reminders' && (_jsx("div", { className: "h-full overflow-y-auto p-4", children: _jsx(SessionRemindersPanel, { projectId: projectId, projectSessionId: projectSessionId }) }))] })] }) }));
|
|
44
50
|
}
|
|
@@ -8,15 +8,20 @@ import { Modal, ModalBody, ModalContent, ModalDescription, ModalHeader, ModalTit
|
|
|
8
8
|
import { errorToast, successToast } from '../../primitives/toast.js';
|
|
9
9
|
import { EmptyState } from '../../primitives/empty-state.js';
|
|
10
10
|
import { ErrorState } from '../../primitives/error-state.js';
|
|
11
|
-
import { approvalLauncherName, approvalRequestFromAction, } from '../prompts/session-approval-review.js';
|
|
11
|
+
import { approvalLauncherName, approvalRequestFromAction, auditPolicySet, } from '../prompts/session-approval-review.js';
|
|
12
12
|
import { isPendingAction, relativeTime, riskTone, statusLabel, statusTone, useResolveApproval, useSessionAudit, useSessionAuditTimeline, } from './session-audit-shared.js';
|
|
13
13
|
import { credentialVia } from './audit/audit-credential-label.js';
|
|
14
14
|
import { useTranslations } from '../../i18n/index.js';
|
|
15
15
|
import { useProjectSession } from '@kortix/sdk/react';
|
|
16
16
|
import { CaretRightIcon, ShieldCheckIcon } from '@phosphor-icons/react';
|
|
17
17
|
import { useMemo, useState } from 'react';
|
|
18
|
+
/** The policy set that decided a history row, if one did. */
|
|
19
|
+
function setNameOf(action) {
|
|
20
|
+
return auditPolicySet(action.result_summary)?.name ?? null;
|
|
21
|
+
}
|
|
18
22
|
export function SessionAuditPanel({ projectId, projectSessionId, }) {
|
|
19
23
|
const tI18nComplete = useTranslations('hardcodedUi.i18nComplete');
|
|
24
|
+
const tSets = useTranslations('connectorPolicySets');
|
|
20
25
|
const approvalQuery = useSessionAudit(projectId, projectSessionId);
|
|
21
26
|
const { data } = approvalQuery;
|
|
22
27
|
const timelineQuery = useSessionAuditTimeline(projectId, projectSessionId, {
|
|
@@ -74,7 +79,9 @@ export function SessionAuditPanel({ projectId, projectSessionId, }) {
|
|
|
74
79
|
: 'muted', size: "xs", className: "capitalize", children: event.outcome ?? 'recorded' })] }), _jsxs("p", { className: "text-muted-foreground mt-0.5 truncate text-xs", children: [credentialVia(event, (key) => tI18nComplete.raw(key)) ??
|
|
75
80
|
event.authoritative_source ??
|
|
76
81
|
event.source ??
|
|
77
|
-
'system', ' ', "\u00B7", ' ', relativeTime(event.occurred_at)] })] }), _jsx(CaretRightIcon, { className: "text-muted-foreground size-4 shrink-0" })] }) }, event.event_id))) }), timelineQuery.hasNextPage ? (_jsx("div", { className: "flex justify-center pt-1", children: _jsxs(Button, { size: "sm", variant: "outline", disabled: timelineQuery.isFetchingNextPage, onClick: () => void timelineQuery.fetchNextPage(), children: [timelineQuery.isFetchingNextPage ? _jsx(Loading, { className: "size-3.5" }) : null, tI18nComplete.raw('text96f2482de866')] }) })) : null] })) : null, history.length > 0 ? (_jsxs("section", { className: "space-y-3", children: [_jsx("h3", { className: "text-muted-foreground text-xs font-medium", children: tI18nComplete.raw('text0e7696009337') }), _jsx("ul", { className: "bg-popover overflow-hidden rounded-md border", children: history.map((action) => (_jsx("li", { className: "border-border border-b last:border-b-0", children: _jsxs("button", { type: "button", className: "hover:bg-primary/[0.03] flex min-h-12 w-full items-center gap-3 px-4 py-2 text-left transition-[background-color,transform] active:scale-[0.96]", onClick: () => setSelected(action), children: [_jsxs("div", { className: "min-w-0 flex-1", children: [_jsxs("div", { className: "flex flex-wrap items-center gap-1.5", children: [_jsx("code", { className: "text-foreground truncate font-mono text-sm", children: action.action }), action.risk ? (_jsx(Badge, { variant: riskTone(action.risk), size: "xs", className: "capitalize", children: action.risk })) : null, _jsx(Badge, { variant: statusTone(action.status), size: "xs", children: statusLabel(action.status) })] }), _jsxs("p", { className: "text-muted-foreground mt-0.5 truncate text-xs", children: [action.acted_by_email ?? 'agent', " \u00B7 ", relativeTime(action.at), action
|
|
82
|
+
'system', ' ', "\u00B7", ' ', relativeTime(event.occurred_at)] })] }), _jsx(CaretRightIcon, { className: "text-muted-foreground size-4 shrink-0" })] }) }, event.event_id))) }), timelineQuery.hasNextPage ? (_jsx("div", { className: "flex justify-center pt-1", children: _jsxs(Button, { size: "sm", variant: "outline", disabled: timelineQuery.isFetchingNextPage, onClick: () => void timelineQuery.fetchNextPage(), children: [timelineQuery.isFetchingNextPage ? _jsx(Loading, { className: "size-3.5" }) : null, tI18nComplete.raw('text96f2482de866')] }) })) : null] })) : null, history.length > 0 ? (_jsxs("section", { className: "space-y-3", children: [_jsx("h3", { className: "text-muted-foreground text-xs font-medium", children: tI18nComplete.raw('text0e7696009337') }), _jsx("ul", { className: "bg-popover overflow-hidden rounded-md border", children: history.map((action) => (_jsx("li", { className: "border-border border-b last:border-b-0", children: _jsxs("button", { type: "button", className: "hover:bg-primary/[0.03] flex min-h-12 w-full items-center gap-3 px-4 py-2 text-left transition-[background-color,transform] active:scale-[0.96]", onClick: () => setSelected(action), children: [_jsxs("div", { className: "min-w-0 flex-1", children: [_jsxs("div", { className: "flex flex-wrap items-center gap-1.5", children: [_jsx("code", { className: "text-foreground truncate font-mono text-sm", children: action.action }), action.risk ? (_jsx(Badge, { variant: riskTone(action.risk), size: "xs", className: "capitalize", children: action.risk })) : null, _jsx(Badge, { variant: statusTone(action.status), size: "xs", children: statusLabel(action.status) })] }), _jsxs("p", { className: "text-muted-foreground mt-0.5 truncate text-xs", children: [action.acted_by_email ?? 'agent', " \u00B7 ", relativeTime(action.at), setNameOf(action)
|
|
83
|
+
? ` · ${tSets('auditSet', { set: setNameOf(action) })}`
|
|
84
|
+
: '', action.resolved_by_email
|
|
78
85
|
? tI18nComplete('text0e16f24ee012', {
|
|
79
86
|
value0: action.status === 'denied' ? 'denied' : 'approved',
|
|
80
87
|
value1: action.resolved_by_email,
|
|
@@ -151,7 +151,7 @@ export function riskTone(risk) {
|
|
|
151
151
|
}
|
|
152
152
|
/** Terminal outcome of a gated action → badge tone. */
|
|
153
153
|
export function statusTone(status) {
|
|
154
|
-
if (status === 'ok')
|
|
154
|
+
if (status === 'ok' || status === 'approved')
|
|
155
155
|
return 'success';
|
|
156
156
|
if (status === 'denied' || status === 'error')
|
|
157
157
|
return 'destructive';
|
|
@@ -164,6 +164,8 @@ export function statusLabel(status) {
|
|
|
164
164
|
switch (status) {
|
|
165
165
|
case 'ok':
|
|
166
166
|
return 'Allowed';
|
|
167
|
+
case 'approved':
|
|
168
|
+
return 'Approved';
|
|
167
169
|
case 'denied':
|
|
168
170
|
return 'Denied';
|
|
169
171
|
case 'error':
|