@kortix/ui 0.14.12 → 0.14.14
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 +1 -1
- package/dist/_vendor/kortix-shared.js +521 -7045
- package/dist/_vendor/shared/app-config.d.ts +8 -0
- package/dist/_vendor/shared/artifact-annotations.d.ts +708 -0
- package/dist/_vendor/shared/artifact-comments.d.ts +327 -0
- package/dist/_vendor/shared/index.d.ts +3 -1
- package/dist/_vendor/shared/my-kortix-agent.d.ts +40 -0
- package/dist/_vendor/shared/peer-message-prompt.d.ts +35 -0
- package/dist/_vendor/shared/pixel-mark.d.ts +11 -0
- package/dist/_vendor/shared/prompt-attachments.d.ts +1 -0
- package/dist/_vendor/shared/reminder-prompt.d.ts +8 -2
- package/dist/_vendor/shared/runtime-versions.d.ts +8 -0
- package/dist/artifacts/artifact-frame.d.ts +1 -0
- package/dist/artifacts/artifact-frame.js +18 -5
- package/dist/artifacts/frame-policy.d.ts +1 -1
- package/dist/artifacts/frame-policy.js +10 -5
- package/dist/customize/agents/agent-access-text.d.ts +16 -0
- package/dist/customize/agents/agent-access-text.js +54 -0
- package/dist/customize/agents/agent-approval-rules.d.ts +8 -0
- package/dist/customize/agents/agent-approval-rules.js +26 -0
- package/dist/customize/agents/agent-authority-card.js +4 -1
- package/dist/customize/agents/agent-cover-card.d.ts +4 -1
- package/dist/customize/agents/agent-cover-card.js +2 -2
- package/dist/customize/agents/agent-detail-aside.d.ts +1 -2
- package/dist/customize/agents/agent-detail-aside.js +8 -11
- package/dist/customize/agents/agent-drives-section.d.ts +23 -7
- package/dist/customize/agents/agent-drives-section.js +107 -41
- package/dist/customize/agents/agent-instructions.d.ts +11 -0
- package/dist/customize/agents/agent-instructions.js +114 -0
- package/dist/customize/agents/agent-model-view.d.ts +17 -0
- package/dist/customize/agents/agent-model-view.js +67 -0
- package/dist/customize/agents/agent-overview.d.ts +53 -0
- package/dist/customize/agents/agent-overview.js +242 -0
- package/dist/customize/agents/agent-page-chrome.d.ts +128 -0
- package/dist/customize/agents/agent-page-chrome.js +145 -0
- package/dist/customize/agents/agent-page.d.ts +13 -1
- package/dist/customize/agents/agent-page.js +478 -367
- package/dist/customize/agents/agent-pin-button.d.ts +10 -0
- package/dist/customize/agents/agent-pin-button.js +20 -0
- package/dist/customize/agents/agent-policy-sets-section.d.ts +16 -0
- package/dist/customize/agents/agent-policy-sets-section.js +80 -0
- package/dist/customize/agents/agent-policy-sets.js +1 -1
- package/dist/customize/agents/agent-section-rail.d.ts +21 -0
- package/dist/customize/agents/agent-section-rail.js +23 -0
- package/dist/customize/agents/agent-share-control.d.ts +4 -3
- package/dist/customize/agents/agent-share-control.js +15 -16
- package/dist/customize/agents/{agent-people-section.d.ts → agent-share-dialog.d.ts} +3 -1
- package/dist/customize/agents/{agent-people-section.js → agent-share-dialog.js} +21 -21
- package/dist/customize/agents/agent-tabs.d.ts +95 -0
- package/dist/customize/agents/agent-tabs.js +199 -0
- package/dist/customize/agents/agents-page.d.ts +0 -21
- package/dist/customize/agents/agents-page.js +104 -118
- package/dist/customize/agents/connectors-required.d.ts +16 -0
- package/dist/customize/agents/connectors-required.js +19 -0
- package/dist/customize/agents/create-agent-modal.d.ts +19 -0
- package/dist/customize/agents/create-agent-modal.js +94 -0
- package/dist/customize/connectors/agent-access.d.ts +4 -4
- package/dist/customize/connectors/agent-access.js +7 -10
- package/dist/customize/connectors/connector-identity.d.ts +12 -0
- package/dist/customize/connectors/connector-identity.js +15 -2
- package/dist/customize/connectors/connector-routes.js +2 -2
- package/dist/customize/connectors/connectors-page.d.ts +14 -1
- package/dist/customize/connectors/connectors-page.js +101 -32
- package/dist/customize/connectors/detail/app-page.js +1 -1
- package/dist/customize/connectors/detail/connector-agents.js +0 -3
- package/dist/customize/connectors/detail/connector-page.d.ts +1 -1
- package/dist/customize/connectors/detail/connector-page.js +5 -2
- package/dist/customize/connectors/detail/connector-policy-sets.js +1 -1
- package/dist/customize/connectors/detail/connector-triggers.js +2 -2
- package/dist/customize/connectors/use-agent-access.d.ts +7 -5
- package/dist/customize/connectors/use-agent-access.js +2 -6
- package/dist/customize/models/models-page.d.ts +7 -1
- package/dist/customize/models/models-page.js +2 -2
- package/dist/customize/project-settings/project-admin-sections.d.ts +63 -0
- package/dist/customize/project-settings/project-admin-sections.js +80 -0
- package/dist/customize/project-settings/project-settings-page.d.ts +1 -1
- package/dist/customize/project-settings/project-settings-page.js +4 -13
- package/dist/customize/project-settings/project-settings-sections.d.ts +5 -5
- package/dist/customize/project-settings/project-settings-sections.js +6 -20
- package/dist/customize/providers/provider-accordion.js +29 -17
- package/dist/customize/providers/provider-connect.js +1 -1
- package/dist/customize/providers/provider-sheet.d.ts +4 -1
- package/dist/customize/providers/provider-sheet.js +15 -5
- package/dist/customize/secrets/secrets-page.d.ts +5 -1
- package/dist/customize/secrets/secrets-page.js +2 -2
- package/dist/customize/sections/gateway-view.d.ts +10 -2
- package/dist/customize/sections/gateway-view.js +16 -4
- package/dist/customize/sections/llm-provider/chatgpt-subscription-connect.d.ts +12 -5
- package/dist/customize/sections/llm-provider/chatgpt-subscription-connect.js +131 -8
- package/dist/customize/sections/llm-provider/claude-code-step.d.ts +10 -0
- package/dist/customize/sections/llm-provider/claude-code-step.js +32 -0
- package/dist/customize/sections/llm-provider/models-tab.js +5 -1
- package/dist/customize/sections/view/account-secret-resources-panel.d.ts +5 -3
- package/dist/customize/sections/view/account-secret-resources-panel.js +122 -19
- package/dist/customize/sections/view/agent-editor-access-fields.d.ts +1 -1
- package/dist/customize/sections/view/agent-editor-access-fields.js +8 -4
- package/dist/customize/sections/view/agent-editor-basics-fields.d.ts +4 -1
- package/dist/customize/sections/view/agent-editor-basics-fields.js +33 -4
- package/dist/customize/sections/view/agent-editor-catalog.d.ts +2 -2
- package/dist/customize/sections/view/agent-editor-catalog.js +10 -12
- package/dist/customize/sections/view/agent-editor-primitives.d.ts +1 -1
- package/dist/customize/sections/view/agent-editor-primitives.js +4 -4
- package/dist/customize/sections/view/agent-editor.d.ts +37 -26
- package/dist/customize/sections/view/agent-editor.js +19 -19
- package/dist/customize/sections/view/grant-mode-field.d.ts +8 -20
- package/dist/customize/sections/view/grant-mode-field.js +31 -57
- package/dist/customize/sections/view/permission-editor.d.ts +3 -1
- package/dist/customize/sections/view/permission-editor.js +19 -10
- package/dist/customize/sections/view/review-view.d.ts +8 -0
- package/dist/customize/sections/view/review-view.js +12 -1
- package/dist/customize/sections/view/secret-delivery.js +1 -4
- package/dist/customize/sections/view/secrets-view.d.ts +7 -1
- package/dist/customize/sections/view/secrets-view.js +42 -6
- package/dist/customize/settings/rail.js +2 -8
- package/dist/customize/settings/settings-tabs.d.ts +2 -2
- package/dist/customize/settings/settings-tabs.js +17 -19
- package/dist/customize/settings/tabs/experimental-tab.d.ts +3 -0
- package/dist/customize/settings/tabs/experimental-tab.js +6 -1
- package/dist/customize/settings/tabs/sandbox-tab.d.ts +4 -6
- package/dist/customize/settings/tabs/sandbox-tab.js +9 -9
- package/dist/customize/shared/access-list.d.ts +39 -0
- package/dist/customize/shared/access-list.js +62 -0
- package/dist/customize/shared/agent-resource-scope.d.ts +87 -0
- package/dist/customize/shared/agent-resource-scope.js +123 -0
- package/dist/customize/shared/capability-library.d.ts +41 -0
- package/dist/customize/shared/capability-library.js +271 -0
- package/dist/customize/shared/capability-page-shell.d.ts +18 -1
- package/dist/customize/shared/capability-page-shell.js +21 -1
- package/dist/customize/shared/catalog/catalog-space-tabs.d.ts +14 -0
- package/dist/customize/shared/catalog/catalog-space-tabs.js +20 -0
- package/dist/customize/shared/customize-tab-bar.d.ts +13 -0
- package/dist/customize/shared/customize-tab-bar.js +95 -0
- package/dist/customize/shared/entity/entity-modal.d.ts +17 -1
- package/dist/customize/shared/entity/entity-modal.js +10 -9
- package/dist/customize/shared/leave-guard.d.ts +23 -0
- package/dist/customize/shared/leave-guard.js +87 -0
- package/dist/customize/shared/standalone-settings-nav.js +4 -1
- package/dist/customize/shared/tool-rules.d.ts +11 -0
- package/dist/customize/shared/tool-rules.js +29 -0
- package/dist/customize/skills/builtin-skill-modal.d.ts +6 -0
- package/dist/customize/skills/builtin-skill-modal.js +41 -0
- package/dist/customize/skills/skills-page.d.ts +21 -18
- package/dist/customize/skills/skills-page.js +16 -110
- package/dist/customize/triggers/runtime-triggers.d.ts +17 -0
- package/dist/customize/triggers/runtime-triggers.js +57 -0
- package/dist/customize/triggers/schedule/event-trigger-copy.js +2 -2
- package/dist/customize/triggers/schedule/post-to-field.js +2 -2
- package/dist/customize/triggers/schedule/schedule-copy.d.ts +11 -6
- package/dist/customize/triggers/schedule/schedule-copy.js +29 -8
- package/dist/customize/triggers/schedule/schedule-detail-sheet.js +7 -3
- package/dist/customize/triggers/schedule/trigger-composer-logic.d.ts +26 -1
- package/dist/customize/triggers/schedule/trigger-composer-logic.js +64 -3
- package/dist/customize/triggers/schedule/trigger-composer.js +57 -20
- package/dist/customize/triggers/schedule/trigger-edit-logic.js +18 -5
- package/dist/customize/triggers/schedule/trigger-filter.d.ts +10 -0
- package/dist/customize/triggers/schedule/trigger-filter.js +16 -0
- 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/use-trigger-mutations.d.ts +1 -1
- package/dist/customize/triggers/schedule/use-trigger-mutations.js +1 -1
- package/dist/customize/triggers/schedule/when-app.d.ts +15 -0
- package/dist/customize/triggers/schedule/when-app.js +21 -0
- package/dist/customize/triggers/schedule/when-change-request.d.ts +10 -0
- package/dist/customize/triggers/schedule/when-change-request.js +15 -0
- package/dist/customize/triggers/schedule-view.d.ts +17 -3
- package/dist/customize/triggers/schedule-view.js +46 -16
- package/dist/customize/triggers/triggers-page.d.ts +3 -3
- package/dist/customize/triggers/triggers-page.js +2 -2
- package/dist/customize/use-configure-thread.d.ts +8 -2
- package/dist/customize/use-configure-thread.js +30 -18
- package/dist/files/project/components/change-request-detail-dialog.js +2 -3
- package/dist/files/project/components/drive-explorer.js +6 -5
- package/dist/files/project/explorer-source.d.ts +3 -0
- package/dist/files/project/upload-batch.d.ts +3 -3
- package/dist/files/project/upload-batch.js +7 -6
- package/dist/files/runtime/sandbox-explorer-source.js +3 -3
- package/dist/i18n/en.d.ts +1330 -53
- package/dist/i18n/en.js +1422 -145
- package/dist/i18n/ui-catalog/remaining-ui-translation-keys.generated.js +16 -7
- package/dist/internal/auth/auth-primitives.d.ts +1 -3
- package/dist/internal/auth/auth-primitives.js +2 -2
- package/dist/internal/billing/session-cost-format.d.ts +1 -0
- package/dist/internal/billing/session-cost-format.js +11 -0
- package/dist/internal/components/agent-mark.d.ts +12 -1
- package/dist/internal/components/agent-mark.js +34 -11
- package/dist/internal/components/nav-rail.d.ts +22 -0
- package/dist/internal/components/nav-rail.js +16 -0
- package/dist/internal/components/repository-disconnected.js +2 -2
- package/dist/internal/goals/goal-meta.d.ts +15 -1
- package/dist/internal/goals/goal-meta.js +42 -2
- package/dist/internal/hooks/projects/use-agent-config.d.ts +11 -7
- package/dist/internal/hooks/projects/use-agent-config.js +28 -11
- package/dist/internal/hooks/use-slash-focus.d.ts +7 -1
- package/dist/internal/hooks/use-slash-focus.js +9 -3
- package/dist/internal/layout/project-capability-nav.d.ts +24 -0
- package/dist/internal/layout/project-capability-nav.js +86 -0
- package/dist/internal/layout/project-page-header.d.ts +1 -1
- package/dist/internal/layout/project-page-header.js +1 -1
- package/dist/internal/layout/project-settings-nav.d.ts +3 -2
- package/dist/internal/layout/project-settings-nav.js +5 -3
- package/dist/internal/lib/browser-noise/rules/old-browsers.js +1 -1
- package/dist/internal/lib/capability-tab-routes.d.ts +34 -3
- package/dist/internal/lib/capability-tab-routes.js +76 -8
- package/dist/internal/lib/manifest-health.d.ts +10 -0
- package/dist/internal/lib/manifest-health.js +20 -0
- package/dist/internal/lib/pixel-mark.d.ts +4 -1
- package/dist/internal/lib/pixel-mark.js +33 -6
- package/dist/internal/lib/project-actions.d.ts +1 -1
- package/dist/internal/lib/project-actions.js +0 -4
- package/dist/internal/lib/provider-branding.js +2 -0
- package/dist/internal/lib/space-scope.d.ts +29 -0
- package/dist/internal/lib/space-scope.js +28 -0
- package/dist/internal/lib/use-project-feature-flags.js +3 -3
- package/dist/internal/lib/web-notifications.d.ts +74 -8
- package/dist/internal/lib/web-notifications.js +243 -117
- package/dist/internal/notifications/notification-rows.d.ts +14 -7
- package/dist/internal/notifications/notification-rows.js +21 -14
- package/dist/internal/notifications/session-toast-cards.d.ts +2 -2
- package/dist/internal/reminders/reminder-format.d.ts +6 -2
- package/dist/internal/reminders/reminder-format.js +7 -1
- package/dist/internal/stores/active-space-store.d.ts +35 -0
- package/dist/internal/stores/active-space-store.js +29 -0
- package/dist/internal/stores/kortix-computer-store.js +13 -4
- package/dist/internal/stores/pinned-agents-store.d.ts +26 -0
- package/dist/internal/stores/pinned-agents-store.js +20 -0
- package/dist/internal/stores/session-panel-memory-store.js +3 -0
- package/dist/internal/stores/turn-attention-store.d.ts +5 -4
- package/dist/lib/routes.d.ts +16 -1
- package/dist/lib/routes.js +15 -3
- package/dist/markdown/doc-editor/doc-embed.d.ts +31 -0
- package/dist/markdown/doc-editor/doc-embed.js +168 -0
- package/dist/markdown/doc-editor/doc-extensions.d.ts +26 -0
- package/dist/markdown/doc-editor/doc-extensions.js +149 -0
- package/dist/markdown/doc-editor/doc-menus.d.ts +9 -0
- package/dist/markdown/doc-editor/doc-menus.js +56 -0
- package/dist/markdown/doc-editor/markdown.d.ts +12 -0
- package/dist/markdown/doc-editor/markdown.js +140 -0
- package/dist/markdown/genui/components/inline.d.ts +1 -1
- package/dist/primitives/badge.d.ts +1 -1
- package/dist/primitives/button.d.ts +1 -1
- package/dist/primitives/pixel-kortix-mark.d.ts +5 -4
- package/dist/primitives/pixel-kortix-mark.js +5 -15
- package/dist/primitives/tag.d.ts +1 -1
- package/dist/primitives/textarea.js +14 -0
- package/dist/primitives/toast.d.ts +2 -0
- package/dist/primitives/toast.js +4 -2
- package/dist/providers/ui-provider.d.ts +16 -0
- package/dist/session/actions/session-label.d.ts +1 -1
- package/dist/session/actions/session-label.js +3 -3
- package/dist/session/agents/agent-model.d.ts +92 -0
- package/dist/session/agents/agent-model.js +123 -0
- package/dist/session/agents/agent-state-mark.d.ts +10 -0
- package/dist/session/agents/agent-state-mark.js +22 -0
- package/dist/session/agents/agent-strip.d.ts +58 -0
- package/dist/session/agents/agent-strip.js +259 -0
- package/dist/session/agents/held-messages.d.ts +33 -0
- package/dist/session/agents/held-messages.js +50 -0
- package/dist/session/agents/legacy-subagent-chat.d.ts +11 -0
- package/dist/session/agents/legacy-subagent-chat.js +19 -0
- package/dist/session/agents/session-peek.d.ts +20 -0
- package/dist/session/agents/session-peek.js +67 -0
- package/dist/session/agents/session-prompt.d.ts +13 -0
- package/dist/session/agents/session-prompt.js +18 -0
- package/dist/session/agents/steer-session.d.ts +13 -0
- package/dist/session/agents/steer-session.js +29 -0
- package/dist/session/agents/subagent-dialog-content.d.ts +11 -0
- package/dist/session/agents/subagent-dialog-content.js +115 -0
- package/dist/session/agents/subagent-view.d.ts +8 -0
- package/dist/session/agents/subagent-view.js +18 -0
- package/dist/session/agents/tasks-panel.d.ts +13 -0
- package/dist/session/agents/tasks-panel.js +41 -0
- package/dist/session/agents/workflow-run-controls.d.ts +43 -0
- package/dist/session/agents/workflow-run-controls.js +141 -0
- package/dist/session/composer/ComposerCard.d.ts +1 -1
- package/dist/session/composer/ComposerCard.js +3 -3
- package/dist/session/composer/agent-selector.js +13 -19
- package/dist/session/composer/composer-underbar.d.ts +3 -1
- package/dist/session/composer/composer-underbar.js +2 -2
- package/dist/session/composer/composer.d.ts +5 -0
- package/dist/session/composer/composer.js +16 -10
- package/dist/session/composer/editor/composer-editor.js +19 -8
- package/dist/session/composer/editor/ultracode.d.ts +34 -0
- package/dist/session/composer/editor/ultracode.js +127 -0
- package/dist/session/composer/send-blockers.d.ts +1 -11
- package/dist/session/composer/send-blockers.js +1 -11
- package/dist/session/composer/session-composer-readiness.d.ts +1 -28
- package/dist/session/composer/session-composer-readiness.js +5 -16
- package/dist/session/header/reminder-parts.d.ts +1 -1
- package/dist/session/header/session-site-header.js +6 -3
- package/dist/session/header/subagent-hover-card.d.ts +0 -2
- package/dist/session/header/subagent-hover-card.js +1 -4
- package/dist/session/models/claude-connection-slot.d.ts +11 -0
- package/dist/session/models/claude-connection-slot.js +30 -0
- package/dist/session/models/model-availability.d.ts +3 -1
- package/dist/session/models/model-availability.js +3 -0
- package/dist/session/models/model-selector.js +11 -12
- package/dist/session/models/model-tags.d.ts +9 -0
- package/dist/session/models/model-tags.js +8 -0
- package/dist/session/panel/easy/easy-panel.js +1 -1
- package/dist/session/panel/easy/step-icon.js +5 -1
- package/dist/session/panel/mobile-tool-drawer.js +1 -1
- package/dist/session/panel/session-action-panel-column.js +1 -1
- package/dist/session/panel/session-desktop.js +41 -14
- package/dist/session/panel/session-panel-provider.d.ts +1 -1
- package/dist/session/panel/session-panel-provider.js +7 -11
- package/dist/session/prompts/question-prompt.js +3 -1
- package/dist/session/status/session-error-banner.js +4 -1
- package/dist/session/thread/session-chat.js +286 -296
- package/dist/session/thread/session-context-modal.js +29 -10
- package/dist/session/thread/session-context-spawned-sessions.d.ts +13 -0
- package/dist/session/thread/session-context-spawned-sessions.js +44 -0
- package/dist/session/thread/session-context-sub-sessions.js +3 -8
- package/dist/session/thread/transcript.d.ts +3 -0
- package/dist/session/thread/transcript.js +32 -8
- package/dist/session/tool/shared/full-view-action.d.ts +29 -0
- package/dist/session/tool/shared/full-view-action.js +43 -0
- package/dist/session/tool/tool-part-renderer.js +10 -2
- package/dist/session/tool/tools/agent-message-tool.js +2 -2
- package/dist/session/tool/tools/agent-spawn-tool.js +2 -2
- package/dist/session/tool/tools/agent-status-tool.js +2 -2
- package/dist/session/tool/tools/kortix-action-tool.d.ts +2 -0
- package/dist/session/tool/tools/kortix-action-tool.js +148 -0
- package/dist/session/tool/tools/kortix-tool-card.d.ts +83 -0
- package/dist/session/tool/tools/kortix-tool-card.js +186 -0
- package/dist/session/tool/tools/multi-agent-tool-bodies.d.ts +11 -0
- package/dist/session/tool/tools/multi-agent-tool-bodies.js +141 -0
- package/dist/session/tool/tools/multi-agent-tool-data.d.ts +63 -0
- package/dist/session/tool/tools/multi-agent-tool-data.js +118 -0
- package/dist/session/tool/tools/multi-agent-tools.d.ts +9 -0
- package/dist/session/tool/tools/multi-agent-tools.js +38 -0
- package/dist/session/tool/tools/question-tool.js +1 -1
- package/dist/session/tool/tools/register.d.ts +3 -0
- package/dist/session/tool/tools/register.js +3 -0
- package/dist/session/tool/tools/session-spawn-tool.js +2 -2
- package/dist/session/tool/tools/task-tool.d.ts +1 -1
- package/dist/session/tool/tools/task-tool.js +29 -41
- package/dist/session/tool/tools/workflow-progress.d.ts +34 -0
- package/dist/session/tool/tools/workflow-progress.js +186 -0
- package/dist/session/tool/tools/workflow-run.d.ts +128 -0
- package/dist/session/tool/tools/workflow-run.js +251 -0
- package/dist/session/tool/tools/workflow-tool.d.ts +9 -0
- package/dist/session/tool/tools/workflow-tool.js +253 -0
- package/dist/session/turn/notice-batch-group.d.ts +12 -0
- package/dist/session/turn/notice-batch-group.js +17 -0
- package/dist/session/turn/peer-message-row.d.ts +14 -0
- package/dist/session/turn/peer-message-row.js +57 -0
- package/dist/session/turn/subagent-notice-row.d.ts +4 -0
- package/dist/session/turn/subagent-notice-row.js +50 -0
- package/dist/session/turn/subagent-notice.d.ts +58 -0
- package/dist/session/turn/subagent-notice.js +111 -0
- package/dist/session/turn/user-message.js +24 -5
- package/dist/styles/tokens.css +2 -0
- package/dist/styles.css +1 -1
- package/dist/terminal/session-terminal-connect-bar.js +1 -1
- package/dist/workspace/admin/project-admin-dashboard.d.ts +53 -0
- package/dist/workspace/admin/project-admin-dashboard.js +252 -0
- package/dist/workspace/admin/project-admin-nav.d.ts +20 -0
- package/dist/workspace/admin/project-admin-nav.js +41 -0
- package/dist/workspace/home/welcome-body.js +25 -3
- package/dist/workspace/index.d.ts +6 -2
- package/dist/workspace/index.js +12 -2
- package/dist/workspace/layout/new-session-create.js +3 -3
- package/dist/workspace/layout/project-home.js +3 -3
- package/dist/workspace/memory/memory-labels.js +5 -0
- package/dist/workspace/repository-disconnected.js +2 -2
- package/dist/workspace/sessions/board-dispatch.d.ts +52 -0
- package/dist/workspace/sessions/board-dispatch.js +110 -0
- package/dist/workspace/sessions/board-grouping.d.ts +63 -0
- package/dist/workspace/sessions/board-grouping.js +141 -0
- package/dist/workspace/sessions/board-peek.d.ts +15 -0
- package/dist/workspace/sessions/board-peek.js +54 -0
- package/dist/workspace/sessions/board-state-mark.d.ts +15 -0
- package/dist/workspace/sessions/board-state-mark.js +24 -0
- package/dist/workspace/sessions/project-sessions-view.js +42 -31
- package/dist/workspace/sessions/sessions-board.d.ts +12 -0
- package/dist/workspace/sessions/sessions-board.js +214 -0
- package/dist/workspace/sidebar/footer/project-manifest-issues-alert.d.ts +46 -0
- package/dist/workspace/sidebar/footer/project-manifest-issues-alert.js +85 -0
- package/dist/workspace/sidebar/footer/sidebar-alert.js +1 -1
- package/dist/workspace/sidebar/new-agent-modal-provider.d.ts +12 -0
- package/dist/workspace/sidebar/new-agent-modal-provider.js +19 -0
- package/dist/workspace/sidebar/project-nav-items.d.ts +3 -1
- package/dist/workspace/sidebar/project-nav-items.js +53 -5
- package/dist/workspace/sidebar/project-session-list.js +35 -12
- package/dist/workspace/sidebar/project-sidebar.js +6 -3
- package/dist/workspace/sidebar/session-filter-menu.js +2 -1
- package/dist/workspace/space/space-blocks.d.ts +25 -0
- package/dist/workspace/space/space-blocks.js +124 -0
- package/dist/workspace/space/space-filter-tabs.d.ts +17 -0
- package/dist/workspace/space/space-filter-tabs.js +31 -0
- package/dist/workspace/space/space-page.d.ts +24 -0
- package/dist/workspace/space/space-page.js +157 -0
- package/dist/workspace/space/space-room.d.ts +20 -0
- package/dist/workspace/space/space-room.js +27 -0
- package/dist/workspace/space/space-tab-menu.d.ts +14 -0
- package/dist/workspace/space/space-tab-menu.js +127 -0
- package/dist/workspace/space/space-tab-panels.d.ts +9 -0
- package/dist/workspace/space/space-tab-panels.js +203 -0
- package/dist/workspace/space/space-templates.d.ts +34 -0
- package/dist/workspace/space/space-templates.js +71 -0
- package/dist/workspace/space/use-space-filter.d.ts +10 -0
- package/dist/workspace/space/use-space-filter.js +40 -0
- package/dist/workspace/space/use-space-manifest.d.ts +8 -0
- package/dist/workspace/space/use-space-manifest.js +27 -0
- package/dist/workspace/spaces/space-timeline.js +2 -2
- package/package.json +56 -53
- package/skills/kortix-ui/SKILL.md +1 -1
- package/skills/kortix-ui/references/custom-dashboard.md +10 -4
- package/skills/kortix-ui/references/modules.md +10 -8
- package/dist/_vendor/shared/meta-agent.d.ts +0 -7
- package/dist/customize/agents/agent-grant-pages.d.ts +0 -37
- package/dist/customize/agents/agent-grant-pages.js +0 -226
- package/dist/customize/agents/agent-triggers-section.d.ts +0 -17
- package/dist/customize/agents/agent-triggers-section.js +0 -109
- package/dist/customize/migrate-to-v2/index.d.ts +0 -5
- package/dist/customize/migrate-to-v2/index.js +0 -5
- package/dist/customize/migrate-to-v2/migration-prompt.d.ts +0 -16
- package/dist/customize/migrate-to-v2/migration-prompt.js +0 -59
- package/dist/customize/migrate-to-v2/upgrade-defs.d.ts +0 -30
- package/dist/customize/migrate-to-v2/upgrade-defs.js +0 -43
- package/dist/customize/migrate-to-v2/upgrade-view.d.ts +0 -32
- package/dist/customize/migrate-to-v2/upgrade-view.js +0 -152
- package/dist/customize/migrate-to-v2/use-run-upgrade.d.ts +0 -18
- package/dist/customize/migrate-to-v2/use-run-upgrade.js +0 -16
- package/dist/customize/shared/capability-tabs.d.ts +0 -3
- package/dist/customize/shared/capability-tabs.js +0 -137
- package/dist/customize/skills/skill-scope.d.ts +0 -14
- package/dist/customize/skills/skill-scope.js +0 -18
- package/dist/internal/lib/manifest-version.d.ts +0 -21
- package/dist/internal/lib/manifest-version.js +0 -55
- package/dist/session/composer/hooks/use-composer-escape-stop.d.ts +0 -6
- package/dist/session/composer/hooks/use-composer-escape-stop.js +0 -28
- package/dist/session/thread/sub-session-modal-content.d.ts +0 -8
- package/dist/session/thread/sub-session-modal-content.js +0 -23
- package/dist/session/thread/sub-session-modal.d.ts +0 -2
- package/dist/session/thread/sub-session-modal.js +0 -14
- package/dist/workspace/sidebar/footer/project-manifest-upgrade-alert.d.ts +0 -13
- package/dist/workspace/sidebar/footer/project-manifest-upgrade-alert.js +0 -48
|
@@ -0,0 +1,141 @@
|
|
|
1
|
+
'use client';
|
|
2
|
+
import { jsx as _jsx, jsxs as _jsxs, Fragment as _Fragment } from "react/jsx-runtime";
|
|
3
|
+
import { Badge } from '../../primitives/badge.js';
|
|
4
|
+
import { Button } from '../../primitives/button.js';
|
|
5
|
+
import { ButtonGroup } from '../../primitives/button-group.js';
|
|
6
|
+
import { Hint } from '../../primitives/hint.js';
|
|
7
|
+
import Loading from '../../primitives/loading.js';
|
|
8
|
+
import { errorToast, successToast } from '../../primitives/toast.js';
|
|
9
|
+
import { useTranslations } from '../../i18n/index.js';
|
|
10
|
+
import { FloppyDiskIcon, PauseIcon, PlayIcon, SquareIcon, WarningIcon } from '@phosphor-icons/react';
|
|
11
|
+
import { useEffect, useMemo, useState } from 'react';
|
|
12
|
+
import { WORKFLOW_LARGE_AGENT_COUNT } from '@kortix/sdk';
|
|
13
|
+
import { useSessionWorkflows } from '@kortix/sdk/react';
|
|
14
|
+
import { parseWorkflowRun } from '../tool/tools/workflow-run.js';
|
|
15
|
+
import { useSessionPromptSend } from './session-prompt.js';
|
|
16
|
+
/**
|
|
17
|
+
* One workflow run's controls, for the run card in the chat and the strip's
|
|
18
|
+
* "Workflows" group: Claude Code's `/workflows` keys as buttons. Pause or
|
|
19
|
+
* resume (`p`), stop the run (`x`), save its script as a workflow (`s`), and,
|
|
20
|
+
* per agent row, restart (`r`). Every control goes to the box that runs the
|
|
21
|
+
* run: the session that called `workflow`, or a background run's runner.
|
|
22
|
+
*/
|
|
23
|
+
/** A run's large-run warning: more agents than Claude Code's "Large workflow" threshold, or the run says so. */
|
|
24
|
+
export function isLargeRun(run) {
|
|
25
|
+
return run.large === true || run.agents.length > WORKFLOW_LARGE_AGENT_COUNT;
|
|
26
|
+
}
|
|
27
|
+
/** The file name a run saves as: its saved name, else its title in kebab case. */
|
|
28
|
+
export function workflowFileName(run) {
|
|
29
|
+
const base = (run.name || run.title || '')
|
|
30
|
+
.toLowerCase()
|
|
31
|
+
.normalize('NFKD')
|
|
32
|
+
.replace(/[^a-z0-9]+/g, '-')
|
|
33
|
+
.replace(/^-+|-+$/g, '')
|
|
34
|
+
.slice(0, 48)
|
|
35
|
+
.replace(/-+$/g, '');
|
|
36
|
+
return base || 'workflow';
|
|
37
|
+
}
|
|
38
|
+
/**
|
|
39
|
+
* The live copy of a run: a background run's progress lives on its runner's box,
|
|
40
|
+
* so it is read from there (`useSessionWorkflows(project, runner)`, polled while it
|
|
41
|
+
* runs) and keeps updating after this session's turn ended. A foreground run is the
|
|
42
|
+
* card's own metadata. `controlSessionId` is the session whose box takes the controls.
|
|
43
|
+
*/
|
|
44
|
+
export function useLiveWorkflowRun(projectId, sessionId, run) {
|
|
45
|
+
const runner = run?.background?.sessionId;
|
|
46
|
+
const { data } = useSessionWorkflows(projectId, runner, { enabled: !!projectId && !!runner });
|
|
47
|
+
const live = useMemo(() => {
|
|
48
|
+
if (!run || !runner || !data)
|
|
49
|
+
return null;
|
|
50
|
+
const match = data.find((candidate) => candidate.runId === run.runId) ?? (run.runId ? undefined : data[0]);
|
|
51
|
+
const parsed = match ? parseWorkflowRun(match) : null;
|
|
52
|
+
// The runner runs it in the foreground; this card still knows it as a background run.
|
|
53
|
+
return parsed ? { ...parsed, background: run.background } : null;
|
|
54
|
+
}, [run, runner, data]);
|
|
55
|
+
if (!run)
|
|
56
|
+
return { run: null, controlSessionId: undefined, fromRunner: false };
|
|
57
|
+
if (runner)
|
|
58
|
+
return { run: live ?? run, controlSessionId: runner, fromRunner: !!live };
|
|
59
|
+
return { run, controlSessionId: sessionId, fromRunner: false };
|
|
60
|
+
}
|
|
61
|
+
/** The current time, every second while `active`: a live run's elapsed labels tick. */
|
|
62
|
+
export function useNow(active) {
|
|
63
|
+
const [now, setNow] = useState(() => Date.now());
|
|
64
|
+
useEffect(() => {
|
|
65
|
+
if (!active)
|
|
66
|
+
return;
|
|
67
|
+
const timer = setInterval(() => setNow(Date.now()), 1_000);
|
|
68
|
+
return () => clearInterval(timer);
|
|
69
|
+
}, [active]);
|
|
70
|
+
return now;
|
|
71
|
+
}
|
|
72
|
+
/** The prompt "Save" sends to the session that owns the run. */
|
|
73
|
+
export function useSaveWorkflowPrompt() {
|
|
74
|
+
const t = useTranslations('multiAgent.workflow');
|
|
75
|
+
return (run) => t('savePrompt', { title: run.title || run.name || run.runId, runId: run.runId, file: `.kortix/workflows/${workflowFileName(run)}.js` });
|
|
76
|
+
}
|
|
77
|
+
export function LargeRunBadge() {
|
|
78
|
+
const t = useTranslations('multiAgent.workflow');
|
|
79
|
+
return (_jsx(Hint, { label: t('largeHint'), side: "top", children: _jsxs(Badge, { variant: "warning", size: "sm", children: [_jsx(WarningIcon, { weight: "fill", "aria-hidden": true }), t('large')] }) }));
|
|
80
|
+
}
|
|
81
|
+
export function WorkflowRunControls({ projectId, controlSessionId, ownerSessionId, run }) {
|
|
82
|
+
const t = useTranslations('multiAgent.workflow');
|
|
83
|
+
const { control } = useSessionWorkflows(projectId, controlSessionId, { enabled: false });
|
|
84
|
+
const send = useSessionPromptSend(ownerSessionId);
|
|
85
|
+
const savePrompt = useSaveWorkflowPrompt();
|
|
86
|
+
const running = run.status === 'running';
|
|
87
|
+
const canControl = !!projectId && !!controlSessionId && !!run.runId && running;
|
|
88
|
+
const pending = control.isPending ? control.variables?.body.action : undefined;
|
|
89
|
+
const act = (action) => control.mutate({ runId: run.runId, body: { action } }, {
|
|
90
|
+
onError: (error) => errorToast(t(`failed.${action}`), { description: error instanceof Error ? error.message : undefined }),
|
|
91
|
+
});
|
|
92
|
+
const save = async () => {
|
|
93
|
+
if (!send)
|
|
94
|
+
return;
|
|
95
|
+
try {
|
|
96
|
+
await send(savePrompt(run));
|
|
97
|
+
successToast(t('saveSent'));
|
|
98
|
+
}
|
|
99
|
+
catch (error) {
|
|
100
|
+
errorToast(t('saveFailed'), { description: error instanceof Error ? error.message : undefined });
|
|
101
|
+
}
|
|
102
|
+
};
|
|
103
|
+
const buttons = [
|
|
104
|
+
canControl && (_jsx(Hint, { label: run.paused ? t('resumeHint') : t('pauseHint'), side: "top", children: _jsx(Button, { type: "button", variant: "ghost", size: "icon-xs", "aria-label": run.paused ? t('resume') : t('pause'), disabled: !!pending, onClick: (event) => {
|
|
105
|
+
event.stopPropagation();
|
|
106
|
+
act(run.paused ? 'resume' : 'pause');
|
|
107
|
+
}, children: pending === 'pause' || pending === 'resume' ? (_jsx(Loading, { className: "size-3 shrink-0" })) : run.paused ? (_jsx(PlayIcon, { weight: "fill", className: "size-3 shrink-0" })) : (_jsx(PauseIcon, { weight: "fill", className: "size-3 shrink-0" })) }) }, "pause")),
|
|
108
|
+
canControl && (_jsx(Hint, { label: t('stopHint'), side: "top", children: _jsx(Button, { type: "button", variant: "ghost", size: "icon-xs", "aria-label": t('stop'), disabled: !!pending, onClick: (event) => {
|
|
109
|
+
event.stopPropagation();
|
|
110
|
+
act('stop');
|
|
111
|
+
}, children: pending === 'stop' ? _jsx(Loading, { className: "size-3 shrink-0" }) : _jsx(SquareIcon, { weight: "fill", className: "size-2.5 shrink-0" }) }) }, "stop")),
|
|
112
|
+
// A saved workflow is a file already; any other run can become one.
|
|
113
|
+
!run.name && send && run.runId && (_jsx(Hint, { label: t('saveHint'), side: "top", children: _jsx(Button, { type: "button", variant: "ghost", size: "icon-xs", "aria-label": t('save'), onClick: (event) => {
|
|
114
|
+
event.stopPropagation();
|
|
115
|
+
void save();
|
|
116
|
+
}, children: _jsx(FloppyDiskIcon, { className: "size-3 shrink-0" }) }) }, "save")),
|
|
117
|
+
].filter(Boolean);
|
|
118
|
+
if (buttons.length === 0)
|
|
119
|
+
return null;
|
|
120
|
+
return buttons.length === 1 ? _jsx(_Fragment, { children: buttons }) : _jsx(ButtonGroup, { children: buttons });
|
|
121
|
+
}
|
|
122
|
+
/** `restart_agent` for one agent row of a run, on the box that runs it. */
|
|
123
|
+
export function useRestartAgent(projectId, controlSessionId, run) {
|
|
124
|
+
const t = useTranslations('multiAgent.workflow');
|
|
125
|
+
const { control } = useSessionWorkflows(projectId, controlSessionId, { enabled: false });
|
|
126
|
+
const enabled = !!projectId && !!controlSessionId && !!run?.runId && run.status === 'running';
|
|
127
|
+
const restarting = control.isPending && control.variables?.body.action === 'restart_agent' ? control.variables.body.session_id : undefined;
|
|
128
|
+
return {
|
|
129
|
+
enabled,
|
|
130
|
+
restarting,
|
|
131
|
+
restart: (agent) => {
|
|
132
|
+
if (!enabled || !agent.sessionId || !run)
|
|
133
|
+
return;
|
|
134
|
+
control.mutate({ runId: run.runId, body: { action: 'restart_agent', session_id: agent.sessionId } }, {
|
|
135
|
+
onError: (error) => errorToast(t('failed.restart', { label: agent.label }), {
|
|
136
|
+
description: error instanceof Error ? error.message : undefined,
|
|
137
|
+
}),
|
|
138
|
+
});
|
|
139
|
+
},
|
|
140
|
+
};
|
|
141
|
+
}
|
|
@@ -71,4 +71,4 @@ export interface ComposerCardDerived {
|
|
|
71
71
|
noModelsConnected: boolean;
|
|
72
72
|
}
|
|
73
73
|
export type ComposerCardProps = SessionChatInputProps & ComposerCardDerived;
|
|
74
|
-
export declare function ComposerCard({ tHardcodedUi, isDragOver, handleDragEnter, handleDragOver, handleDragLeave, handleDropFiles, attachedFiles, promptAttachmentItems, removeAttachedFile, retryAttachedFile, pastes, removePaste, onOpenPastedContent, commandAttachmentPlan, editorDisabled, editorRef, setEditorRef, editorPlaceholder, animatePlaceholder, handleSubmit, handleArrowUpAtStart, setIsEmpty, handleDocChange, allSessions, slashActions, handleSelectAction, dockId, setMenuOpen, fileInputRef, handleFileSelect, sessionId, handleAttachClick, primaryAgents, availableSelectedModel, agentMenuOpen, setAgentMenuOpen, modelMenuOpen, setModelMenuOpen, reasoningMenuOpen, setReasoningMenuOpen, isEmpty, canSubmit, submitDisabled, attachmentFailed, modelRejectingImages, imagesUnsupportedReason, modelUnavailable, agentUnavailable, noModelsConnected, agents, commands, slashFiles, models, notice, disabled, lockForQuestion, lockForApproval, questionButtonLabel, questionActive, submitLabel, questionCanAct, escCount, isBusy, isSending, onStop, stopDisabled, canStop, modelsLoading, modelRequired, onModelChange, modelDefaultControls, providers, variants, selectedVariant, onVariantChange, projectId, toolbarSlot, rewind, selectedAgent, onAgentChange, noAccessibleAgents, onContextClick, messages, underbarPlacement, agentPickerCompact, slashMenuPlacement, cardClassName, onArrowUpAtStart, }: ComposerCardProps): import("react").JSX.Element;
|
|
74
|
+
export declare function ComposerCard({ tHardcodedUi, isDragOver, handleDragEnter, handleDragOver, handleDragLeave, handleDropFiles, attachedFiles, promptAttachmentItems, removeAttachedFile, retryAttachedFile, pastes, removePaste, onOpenPastedContent, commandAttachmentPlan, editorDisabled, editorRef, setEditorRef, editorPlaceholder, animatePlaceholder, handleSubmit, handleArrowUpAtStart, setIsEmpty, handleDocChange, allSessions, slashActions, handleSelectAction, dockId, setMenuOpen, fileInputRef, handleFileSelect, sessionId, handleAttachClick, primaryAgents, availableSelectedModel, agentMenuOpen, setAgentMenuOpen, modelMenuOpen, setModelMenuOpen, reasoningMenuOpen, setReasoningMenuOpen, isEmpty, canSubmit, submitDisabled, attachmentFailed, modelRejectingImages, imagesUnsupportedReason, modelUnavailable, agentUnavailable, noModelsConnected, agents, commands, slashFiles, models, notice, disabled, lockForQuestion, lockForApproval, questionButtonLabel, questionActive, submitLabel, questionCanAct, escCount, isBusy, isSending, onStop, stopDisabled, canStop, modelsLoading, modelRequired, onModelChange, modelDefaultControls, providers, variants, selectedVariant, onVariantChange, projectId, toolbarSlot, underbarSlot, rewind, selectedAgent, onAgentChange, noAccessibleAgents, onContextClick, messages, underbarPlacement, agentPickerCompact, slashMenuPlacement, cardClassName, onArrowUpAtStart, }: ComposerCardProps): import("react").JSX.Element;
|
|
@@ -21,7 +21,7 @@ export function ComposerCard({ tHardcodedUi, isDragOver, handleDragEnter, handle
|
|
|
21
21
|
// Raw props the moved JSX reads; `{...props}` carries the rest. These
|
|
22
22
|
// defaults mirror `ComposerImpl`'s, because the spread passes the raw
|
|
23
23
|
// values, not the component's defaulted locals.
|
|
24
|
-
agents = EMPTY_AGENTS, commands = EMPTY_COMMANDS, slashFiles = EMPTY_SLASH_FILES, models = EMPTY_MODELS, notice = null, disabled = false, lockForQuestion = false, lockForApproval = false, questionButtonLabel = null, questionActive = false, submitLabel = null, questionCanAct = true, escCount = 0, isBusy = false, isSending = false, onStop, stopDisabled = false, canStop = true, modelsLoading = false, modelRequired = false, onModelChange, modelDefaultControls, providers, variants = EMPTY_VARIANTS, selectedVariant = null, onVariantChange, projectId, toolbarSlot, rewind, selectedAgent = null, onAgentChange, noAccessibleAgents = false, onContextClick, messages, underbarPlacement = 'below', agentPickerCompact = false, slashMenuPlacement = 'above', cardClassName, onArrowUpAtStart, }) {
|
|
24
|
+
agents = EMPTY_AGENTS, commands = EMPTY_COMMANDS, slashFiles = EMPTY_SLASH_FILES, models = EMPTY_MODELS, notice = null, disabled = false, lockForQuestion = false, lockForApproval = false, questionButtonLabel = null, questionActive = false, submitLabel = null, questionCanAct = true, escCount = 0, isBusy = false, isSending = false, onStop, stopDisabled = false, canStop = true, modelsLoading = false, modelRequired = false, onModelChange, modelDefaultControls, providers, variants = EMPTY_VARIANTS, selectedVariant = null, onVariantChange, projectId, toolbarSlot, underbarSlot, rewind, selectedAgent = null, onAgentChange, noAccessibleAgents = false, onContextClick, messages, underbarPlacement = 'below', agentPickerCompact = false, slashMenuPlacement = 'above', cardClassName, onArrowUpAtStart, }) {
|
|
25
25
|
const cardRef = useRef(null);
|
|
26
26
|
const { attachAccept } = useUiHostConfig();
|
|
27
27
|
const inlineUnderbar = underbarPlacement === 'inline';
|
|
@@ -51,7 +51,7 @@ agents = EMPTY_AGENTS, commands = EMPTY_COMMANDS, slashFiles = EMPTY_SLASH_FILES
|
|
|
51
51
|
// the div and immediately fights the caret we are placing.
|
|
52
52
|
e.preventDefault();
|
|
53
53
|
editorRef.current?.focus();
|
|
54
|
-
}, children: [_jsx(AnimatedComposerPlaceholder, { placeholder: editorPlaceholder, active: animatePlaceholder }), _jsx(Suspense, { fallback: _jsx(ComposerEditorFallback, {}), children: _jsx(ComposerEditorLazy, { ref: setEditorRef, placeholder: animatePlaceholder ? '' : editorPlaceholder, disabled: editorDisabled, onSubmit: handleSubmit, onArrowUpAtStart: onArrowUpAtStart ? handleArrowUpAtStart : undefined, onEmptyChange: setIsEmpty, onDocChange: handleDocChange, agents: agents, sessions: allSessions ?? [], currentSessionId: sessionId, commands: commands, actions: slashActions, files: slashFiles, onSelectAction: handleSelectAction, slashDockSelector: `#${dockId}`, onMenuOpenChange: setMenuOpen }) })] }), _jsx("input", { ref: fileInputRef, type: "file", accept: attachAccept ?? DEFAULT_ATTACH_ACCEPT, multiple: true, className: "hidden", onChange: handleFileSelect }), _jsx(ComposerToolbar, { leading: inlineUnderbar ? (_jsx(ComposerUnderbar, { variant: "inline", agentPickerCompact: agentPickerCompact, onAttachClick: handleAttachClick, agents: primaryAgents, selectedAgent: selectedAgent, onAgentChange: onAgentChange, agentMenuOpen: agentMenuOpen, onAgentMenuOpenChange: setAgentMenuOpen, noAccessibleAgents: noAccessibleAgents, messages: messages, models: models, selectedModel: availableSelectedModel, onContextClick: onContextClick })) : null, modelsLoading: modelsLoading, models: models, selectedModel: availableSelectedModel, onModelChange: onModelChange, modelDefaultControls: modelDefaultControls, providers: providers, modelRequired: modelRequired, modelMenuOpen: modelMenuOpen, onModelMenuOpenChange: setModelMenuOpen, reasoningMenuOpen: reasoningMenuOpen, onReasoningMenuOpenChange: setReasoningMenuOpen, variants: variants, selectedVariant: selectedVariant, onVariantChange: onVariantChange, projectId: projectId,
|
|
54
|
+
}, children: [_jsx(AnimatedComposerPlaceholder, { placeholder: editorPlaceholder, active: animatePlaceholder }), _jsx(Suspense, { fallback: _jsx(ComposerEditorFallback, {}), children: _jsx(ComposerEditorLazy, { ref: setEditorRef, placeholder: animatePlaceholder ? '' : editorPlaceholder, disabled: editorDisabled, onSubmit: handleSubmit, onArrowUpAtStart: onArrowUpAtStart ? handleArrowUpAtStart : undefined, onEmptyChange: setIsEmpty, onDocChange: handleDocChange, agents: agents, sessions: allSessions ?? [], currentSessionId: sessionId, commands: commands, actions: slashActions, files: slashFiles, onSelectAction: handleSelectAction, slashDockSelector: `#${dockId}`, onMenuOpenChange: setMenuOpen }) })] }), _jsx("input", { ref: fileInputRef, type: "file", accept: attachAccept ?? DEFAULT_ATTACH_ACCEPT, multiple: true, className: "hidden", onChange: handleFileSelect }), _jsx(ComposerToolbar, { leading: inlineUnderbar ? (_jsx(ComposerUnderbar, { variant: "inline", agentPickerCompact: agentPickerCompact, onAttachClick: handleAttachClick, agents: primaryAgents, selectedAgent: selectedAgent, onAgentChange: onAgentChange, agentMenuOpen: agentMenuOpen, onAgentMenuOpenChange: setAgentMenuOpen, noAccessibleAgents: noAccessibleAgents, messages: messages, models: models, selectedModel: availableSelectedModel, onContextClick: onContextClick, agentsSlot: underbarSlot })) : null, modelsLoading: modelsLoading, models: models, selectedModel: availableSelectedModel, onModelChange: onModelChange, modelDefaultControls: modelDefaultControls, providers: providers, modelRequired: modelRequired, modelMenuOpen: modelMenuOpen, onModelMenuOpenChange: setModelMenuOpen, reasoningMenuOpen: reasoningMenuOpen, onReasoningMenuOpenChange: setReasoningMenuOpen, variants: variants, selectedVariant: selectedVariant, onVariantChange: onVariantChange, projectId: projectId,
|
|
55
55
|
// Inline placement has no under-row, so the slot (the session
|
|
56
56
|
// overrides gear, meta indicator) rides the toolbar itself. With
|
|
57
57
|
// the 'below' placement the ComposerUnderbar further down renders
|
|
@@ -59,5 +59,5 @@ agents = EMPTY_AGENTS, commands = EMPTY_COMMANDS, slashFiles = EMPTY_SLASH_FILES
|
|
|
59
59
|
toolbarSlot: inlineUnderbar ? toolbarSlot : undefined, rewind: rewind, isSending: isSending, isBusy: isBusy, onStop: onStop, stopDisabled: stopDisabled, canStop: canStop, escCount: escCount, lockForQuestion: lockForQuestion, questionButtonLabel: questionButtonLabel, submitLabel: submitLabel, questionCanAct: questionCanAct, hasText: !isEmpty, canSubmit: canSubmit, submitDisabled: submitDisabled ||
|
|
60
60
|
attachmentFailed ||
|
|
61
61
|
modelRejectingImages !== null ||
|
|
62
|
-
commandAttachmentPlan.kind === 'refuse', attachmentFailed: attachmentFailed, attachmentUnsupported: imagesUnsupportedReason, disabled: disabled, modelUnavailable: modelUnavailable, agentUnavailable: agentUnavailable, onSubmit: () => handleSubmit() })] })] })] }), _jsx(ModelConnectionBar, { show: noModelsConnected }), _jsx(ImagesUnsupportedBar, { modelName: noModelsConnected ? null : modelRejectingImages }), inlineUnderbar ? null : (_jsx(ComposerUnderbar, { onAttachClick: handleAttachClick, agents: primaryAgents, selectedAgent: selectedAgent, onAgentChange: onAgentChange, agentMenuOpen: agentMenuOpen, onAgentMenuOpenChange: setAgentMenuOpen, noAccessibleAgents: noAccessibleAgents, messages: messages, models: models, selectedModel: availableSelectedModel, onContextClick: onContextClick, toolbarSlot: toolbarSlot })), slashMenuPlacement === 'below' && (_jsx("div", { id: dockId, className: "absolute top-full right-4 left-4 z-99 mt-3.5" }))] }));
|
|
62
|
+
commandAttachmentPlan.kind === 'refuse', attachmentFailed: attachmentFailed, attachmentUnsupported: imagesUnsupportedReason, disabled: disabled, modelUnavailable: modelUnavailable, agentUnavailable: agentUnavailable, onSubmit: () => handleSubmit() })] })] })] }), _jsx(ModelConnectionBar, { show: noModelsConnected }), _jsx(ImagesUnsupportedBar, { modelName: noModelsConnected ? null : modelRejectingImages }), inlineUnderbar ? null : (_jsx(ComposerUnderbar, { onAttachClick: handleAttachClick, agents: primaryAgents, selectedAgent: selectedAgent, onAgentChange: onAgentChange, agentMenuOpen: agentMenuOpen, onAgentMenuOpenChange: setAgentMenuOpen, noAccessibleAgents: noAccessibleAgents, messages: messages, models: models, selectedModel: availableSelectedModel, onContextClick: onContextClick, toolbarSlot: toolbarSlot, agentsSlot: underbarSlot })), slashMenuPlacement === 'below' && (_jsx("div", { id: dockId, className: "absolute top-full right-4 left-4 z-99 mt-3.5" }))] }));
|
|
63
63
|
}
|
|
@@ -1,6 +1,5 @@
|
|
|
1
1
|
'use client';
|
|
2
2
|
import { jsx as _jsx, jsxs as _jsxs, Fragment as _Fragment } from "react/jsx-runtime";
|
|
3
|
-
import { Badge } from '../../primitives/badge.js';
|
|
4
3
|
import { Button } from '../../primitives/button.js';
|
|
5
4
|
import { CommandGroup, CommandInput, CommandItem, CommandList, CommandPopover, CommandPopoverContent, CommandPopoverTrigger, CommandSeparator, } from '../../primitives/command.js';
|
|
6
5
|
import Hint from '../../primitives/hint.js';
|
|
@@ -8,7 +7,7 @@ import { useTranslations } from '../../i18n/index.js';
|
|
|
8
7
|
import { useUiHostConfig } from '../../providers/ui-provider.js';
|
|
9
8
|
import { cn } from '../../lib/utils.js';
|
|
10
9
|
import { TRIGGER_CARET_CLASS, triggerVariants } from '../../primitives/trigger-variants.js';
|
|
11
|
-
import { capitalizeWords,
|
|
10
|
+
import { capitalizeWords, isMyKortixAgentName, MY_KORTIX_DISPLAY_NAME } from '../../_vendor/kortix-shared.js';
|
|
12
11
|
import { CaretDownIcon, CheckIcon } from '@phosphor-icons/react';
|
|
13
12
|
import { AgentMark } from '../../internal/components/agent-mark.js';
|
|
14
13
|
import { createContext, useContext, useEffect, useMemo, useState } from 'react';
|
|
@@ -42,7 +41,7 @@ export function agentDisplayLabel(agents, selectedAgent) {
|
|
|
42
41
|
const name = resolveDisplayedAgentName(composerSelectableAgents(agents), selectedAgent);
|
|
43
42
|
if (!name)
|
|
44
43
|
return 'Agent';
|
|
45
|
-
return
|
|
44
|
+
return isMyKortixAgentName(name) ? MY_KORTIX_DISPLAY_NAME : capitalizeWords(name);
|
|
46
45
|
}
|
|
47
46
|
export function AgentSelector({ agents, selectedAgent, onSelect, disabled = false, triggerLabelClassName, unavailableHint, open: controlledOpen, onOpenChange, compact = false, appearance = 'chip', }) {
|
|
48
47
|
const tHardcodedUi = useTranslations('hardcodedUi');
|
|
@@ -60,7 +59,7 @@ export function AgentSelector({ agents, selectedAgent, onSelect, disabled = fals
|
|
|
60
59
|
return agents.filter((a) => offeredNames.has(a.name));
|
|
61
60
|
}, [agents, offeredAgents]);
|
|
62
61
|
const primaryAgents = useMemo(() => composerSelectableAgents(offered), [offered]);
|
|
63
|
-
const label = (name) => agentLabels?.[name] ?? (
|
|
62
|
+
const label = (name) => agentLabels?.[name] ?? (isMyKortixAgentName(name) ? MY_KORTIX_DISPLAY_NAME : capitalizeWords(name));
|
|
64
63
|
// A `flash` state, a `prevAgentRef` feeding it, two effects and a 400ms
|
|
65
64
|
// timer used to live here. Nothing ever READ `flash` — it was written on
|
|
66
65
|
// every agent change and rendered nowhere, so the whole apparatus bought a
|
|
@@ -77,8 +76,8 @@ export function AgentSelector({ agents, selectedAgent, onSelect, disabled = fals
|
|
|
77
76
|
(agentLabels?.[a.name] ?? '').toLowerCase().includes(q) ||
|
|
78
77
|
(a.description || '').toLowerCase().includes(q));
|
|
79
78
|
}, [primaryAgents, search, agentLabels]);
|
|
80
|
-
const filteredMeta = useMemo(() => filteredPrimary.filter((a) =>
|
|
81
|
-
const filteredProject = useMemo(() => filteredPrimary.filter((a) => !
|
|
79
|
+
const filteredMeta = useMemo(() => filteredPrimary.filter((a) => isMyKortixAgentName(a.name)), [filteredPrimary]);
|
|
80
|
+
const filteredProject = useMemo(() => filteredPrimary.filter((a) => !isMyKortixAgentName(a.name)), [filteredPrimary]);
|
|
82
81
|
// The place's agents, in its order, then every other agent.
|
|
83
82
|
const featured = useContext(FeaturedAgentsContext);
|
|
84
83
|
const filteredFeatured = useMemo(() => (featured?.names ?? []).flatMap((name) => {
|
|
@@ -106,16 +105,11 @@ export function AgentSelector({ agents, selectedAgent, onSelect, disabled = fals
|
|
|
106
105
|
const field = appearance === 'field';
|
|
107
106
|
const fieldTrigger = (caret, props) => (_jsxs("button", { type: "button", className: cn(triggerVariants(), 'h-9 w-full'), ...props, children: [_jsxs("span", { className: "flex min-w-0 items-center gap-2", children: [triggerMark, _jsx("span", { className: "truncate", children: displayName })] }), caret ? _jsx(CaretDownIcon, { className: cn(TRIGGER_CARET_CLASS, 'size-4') }) : null] }));
|
|
108
107
|
/**
|
|
109
|
-
* One agent:
|
|
110
|
-
* one in use.
|
|
108
|
+
* One agent: its mark, name and description (My Kortix: what picking it
|
|
109
|
+
* does), and a check when it is the one in use.
|
|
111
110
|
*
|
|
112
|
-
*
|
|
113
|
-
*
|
|
114
|
-
* tell apart, and there usually is not — most projects have no meta agents
|
|
115
|
-
* at all, so the list rendered a lone "Agents" label over a single group,
|
|
116
|
-
* captioning something that needed no caption. A badge says the same thing
|
|
117
|
-
* where it is actually useful (on the row that differs) and disappears
|
|
118
|
-
* entirely when every agent is the same kind.
|
|
111
|
+
* No type badge and no group heading: My Kortix sorts first, a separator
|
|
112
|
+
* follows it, and its own line says what it does.
|
|
119
113
|
*
|
|
120
114
|
* Selection is shown ONCE, by the check plus the tinted row. It used to be
|
|
121
115
|
* said three times — check, tinted row, AND a heavier font weight on the
|
|
@@ -131,7 +125,7 @@ export function AgentSelector({ agents, selectedAgent, onSelect, disabled = fals
|
|
|
131
125
|
className: cn('items-start gap-2 py-2', isSelected && 'bg-primary/[0.06]'), onSelect: () => {
|
|
132
126
|
onSelect(agent.name);
|
|
133
127
|
setOpen(false);
|
|
134
|
-
}, children: [agent.description ? (_jsx(AgentMark, { slug: agent.name, size: 28, tile: 36 })) : (_jsx(AgentMark, { slug: agent.name, size: 14 })), _jsxs("div", { className: "min-w-0 flex-1", children: [
|
|
128
|
+
}, children: [agent.description || meta ? (_jsx(AgentMark, { slug: agent.name, size: 28, tile: 36 })) : (_jsx(AgentMark, { slug: agent.name, size: 14 })), _jsxs("div", { className: "min-w-0 flex-1", children: [_jsx("span", { className: "text-foreground block truncate text-sm font-medium", children: label(agent.name) }), meta ? (_jsx("p", { className: "text-muted-foreground text-xs", children: t('myKortixRoutes') })) : agent.description ? (_jsx("p", { className: "text-muted-foreground line-clamp-2 text-xs text-pretty", children: agent.description })) : null] }), isSelected && (
|
|
135
129
|
// `mt-0.5` optically centres the 16px check against the first line
|
|
136
130
|
// rather than the top edge of the text box.
|
|
137
131
|
_jsx(CheckIcon, { className: "text-foreground mt-0.5 size-4 shrink-0" }))] }, agent.name));
|
|
@@ -173,11 +167,11 @@ export function AgentSelector({ agents, selectedAgent, onSelect, disabled = fals
|
|
|
173
167
|
// The mark alone: the name is the tooltip and the menu's checked row.
|
|
174
168
|
// A placeholder name has no mark, so it shows as text.
|
|
175
169
|
triggerMark ?? _jsx("span", { className: cn('max-w-[100px] truncate', triggerLabelClassName), children: displayName })) : (_jsxs(_Fragment, { children: [triggerMark, _jsx("span", { className: cn('max-w-[100px] truncate', triggerLabelClassName), children: displayName }), _jsx(CaretDownIcon, { className: cn('size-3 transition-transform duration-moderate ease-out', open && 'rotate-180') })] })) })) }));
|
|
176
|
-
return (_jsxs(CommandPopover, { open: open, onOpenChange: setOpen, children: [compact ? (_jsx(Hint, { side: "top", label: displayName, children: trigger })) : (trigger), _jsxs(CommandPopoverContent, { side: "top", align: "start", sideOffset: 8, className: "w-[min(
|
|
170
|
+
return (_jsxs(CommandPopover, { open: open, onOpenChange: setOpen, children: [compact ? (_jsx(Hint, { side: "top", label: displayName, children: trigger })) : (trigger), _jsxs(CommandPopoverContent, { side: "top", align: "start", sideOffset: 8, className: "w-[min(340px,calc(100vw-1.5rem))]", children: [_jsx("div", { className: showSearch ? undefined : 'sr-only', children: _jsx(CommandInput, { compact: true, placeholder: tHardcodedUi.raw('componentsSessionSessionChatInput.line231JsxAttrPlaceholderSearchAgents'), value: search, onValueChange: setSearch }) }), _jsxs(CommandList, { className: "max-h-[320px]", children: [filteredFeatured.length > 0 && featured ? (
|
|
177
171
|
// Two groups, so each earns its heading: the place's agents, then the rest.
|
|
178
|
-
_jsxs(_Fragment, { children: [_jsx(CommandGroup, { forceMount: true, heading: featured.label, className: "[&_[cmdk-group-items]]:flex [&_[cmdk-group-items]]:flex-col [&_[cmdk-group-items]]:gap-px", children: filteredFeatured.map((agent) => renderAgentItem(agent,
|
|
172
|
+
_jsxs(_Fragment, { children: [_jsx(CommandGroup, { forceMount: true, heading: featured.label, className: "[&_[cmdk-group-items]]:flex [&_[cmdk-group-items]]:flex-col [&_[cmdk-group-items]]:gap-px", children: filteredFeatured.map((agent) => renderAgentItem(agent, isMyKortixAgentName(agent.name))) }), filteredPrimary.length > filteredFeatured.length && (_jsx(CommandGroup, { forceMount: true, heading: featured.restLabel, className: "[&_[cmdk-group-items]]:flex [&_[cmdk-group-items]]:flex-col [&_[cmdk-group-items]]:gap-px", children: filteredPrimary
|
|
179
173
|
.filter((agent) => !filteredFeatured.includes(agent))
|
|
180
|
-
.map((agent) => renderAgentItem(agent,
|
|
174
|
+
.map((agent) => renderAgentItem(agent, isMyKortixAgentName(agent.name))) }))] })) : filteredPrimary.length > 0 && (
|
|
181
175
|
// `gap-px` between rows: a selected row and a hovered row next to it
|
|
182
176
|
// otherwise draw one merged grey block.
|
|
183
177
|
_jsxs(CommandGroup, { forceMount: true, className: "[&_[cmdk-group-items]]:flex [&_[cmdk-group-items]]:flex-col [&_[cmdk-group-items]]:gap-px", children: [filteredMeta.map((agent) => renderAgentItem(agent, true)), filteredMeta.length > 0 && filteredProject.length > 0 && (_jsx(CommandSeparator, { className: "my-1" })), filteredProject.map((agent) => renderAgentItem(agent, false))] })), filteredPrimary.length === 0 && search.trim() && (_jsxs("div", { className: "text-muted-foreground py-8 text-center text-xs", children: [tHardcodedUi.raw('componentsSessionSessionChatInput.line273JsxTextNoAgentsMatchLdquo'), search.trim(), tHardcodedUi.raw('componentsSessionSessionChatInput.line273JsxTextRdquo')] }))] })] })] }));
|
|
@@ -52,5 +52,7 @@ export interface ComposerUnderbarProps {
|
|
|
52
52
|
/** See `SessionChatInputProps.agentPickerCompact`. */
|
|
53
53
|
agentPickerCompact?: boolean;
|
|
54
54
|
toolbarSlot?: React.ReactNode;
|
|
55
|
+
/** Right of the agent picker: the session's agents line. Same row, no added height. */
|
|
56
|
+
agentsSlot?: React.ReactNode;
|
|
55
57
|
}
|
|
56
|
-
export declare function ComposerUnderbar({ onAttachClick, agents, selectedAgent, agentMenuOpen, onAgentMenuOpenChange, onAgentChange, noAccessibleAgents, messages, models, selectedModel, onContextClick, variant, agentPickerCompact, toolbarSlot, }: ComposerUnderbarProps): import("react").JSX.Element;
|
|
58
|
+
export declare function ComposerUnderbar({ onAttachClick, agents, selectedAgent, agentMenuOpen, onAgentMenuOpenChange, onAgentChange, noAccessibleAgents, messages, models, selectedModel, onContextClick, variant, agentPickerCompact, toolbarSlot, agentsSlot, }: ComposerUnderbarProps): import("react").JSX.Element;
|
|
@@ -14,7 +14,7 @@ import { TokenProgress } from './token-progress.js';
|
|
|
14
14
|
const NO_AGENT_SELECT = () => { };
|
|
15
15
|
/** Stable identity so the empty roster doesn't remount the picker per render. */
|
|
16
16
|
const EMPTY_AGENTS = [];
|
|
17
|
-
export function ComposerUnderbar({ onAttachClick, agents, selectedAgent, agentMenuOpen, onAgentMenuOpenChange, onAgentChange, noAccessibleAgents = false, messages, models, selectedModel, onContextClick, variant = 'row', agentPickerCompact = false, toolbarSlot, }) {
|
|
17
|
+
export function ComposerUnderbar({ onAttachClick, agents, selectedAgent, agentMenuOpen, onAgentMenuOpenChange, onAgentChange, noAccessibleAgents = false, messages, models, selectedModel, onContextClick, variant = 'row', agentPickerCompact = false, toolbarSlot, agentsSlot, }) {
|
|
18
18
|
const t = useTranslations('threads');
|
|
19
19
|
const { contextMeterEnabled } = useUiHostConfig();
|
|
20
20
|
/*
|
|
@@ -55,5 +55,5 @@ export function ComposerUnderbar({ onAttachClick, agents, selectedAgent, agentMe
|
|
|
55
55
|
: 'kortix-composer-underbar flex items-center justify-between gap-2 px-px pt-1.5 pb-2', children: [_jsxs("div", { className: "flex min-w-0 items-center gap-1", children: [_jsx(Hint, { side: "top", label: t('attachFiles'), children: _jsx(Button, { type: "button", variant: "ghost", size: "icon-base", onClick: onAttachClick, "aria-label": t('attachFiles'),
|
|
56
56
|
// `hit-area-3` — the ≈29px ghost chip clears the 44px mobile tap
|
|
57
57
|
// floor only with the shared pseudo-element extension.
|
|
58
|
-
className: "text-muted-foreground hit-area-3 rounded-lg", children: _jsx(Paperclip, { className: "size-4 shrink-0" }) }) }), _jsx(AgentSelector, { compact: agentPickerCompact, agents: noAccessibleAgents ? EMPTY_AGENTS : agents, selectedAgent: selectedAgent, open: agentMenuOpen, onOpenChange: onAgentMenuOpenChange, onSelect: onAgentChange ?? NO_AGENT_SELECT, triggerLabelClassName: "max-w-[7rem]", unavailableHint: noAccessibleAgents ? NO_AGENT_ACCESS_MESSAGE : undefined })] }), _jsxs("div", { className: "flex items-center gap-1", children: [(inline && !messages) || !contextMeterEnabled ? null : (_jsx(TokenProgress, { messages: messages, models: models, selectedModel: selectedModel, onContextClick: onContextClick })), toolbarSlot] })] }));
|
|
58
|
+
className: "text-muted-foreground hit-area-3 rounded-lg", children: _jsx(Paperclip, { className: "size-4 shrink-0" }) }) }), _jsx(AgentSelector, { compact: agentPickerCompact, agents: noAccessibleAgents ? EMPTY_AGENTS : agents, selectedAgent: selectedAgent, open: agentMenuOpen, onOpenChange: onAgentMenuOpenChange, onSelect: onAgentChange ?? NO_AGENT_SELECT, triggerLabelClassName: "max-w-[7rem]", unavailableHint: noAccessibleAgents ? NO_AGENT_ACCESS_MESSAGE : undefined }), agentsSlot] }), _jsxs("div", { className: "flex items-center gap-1", children: [(inline && !messages) || !contextMeterEnabled ? null : (_jsx(TokenProgress, { messages: messages, models: models, selectedModel: selectedModel, onContextClick: onContextClick })), toolbarSlot] })] }));
|
|
59
59
|
}
|
|
@@ -234,6 +234,11 @@ export interface SessionChatInputProps {
|
|
|
234
234
|
aboveSlot?: React.ReactNode;
|
|
235
235
|
inputSlot?: React.ReactNode;
|
|
236
236
|
toolbarSlot?: React.ReactNode;
|
|
237
|
+
/**
|
|
238
|
+
* Rides the under-row right of the agent picker, in both placements: the
|
|
239
|
+
* session's agents line (`AgentsLine`). It must not add height to the row.
|
|
240
|
+
*/
|
|
241
|
+
underbarSlot?: React.ReactNode;
|
|
237
242
|
/**
|
|
238
243
|
* Where the under-row's controls live — attach, the agent picker and the
|
|
239
244
|
* context ring.
|
|
@@ -5,7 +5,8 @@ import { useUiHostConfig } from '../../providers/ui-provider.js';
|
|
|
5
5
|
import { useTranslations } from '../../i18n/index.js';
|
|
6
6
|
import { cn } from '../../lib/utils.js';
|
|
7
7
|
import { isImageFile } from '../../internal/lib/utils/file-utils.js';
|
|
8
|
-
import { usePromptAttachments, useRuntimeSessions } from '@kortix/sdk/react';
|
|
8
|
+
import { useProjectConfig, usePromptAttachments, useRuntimeSessions } from '@kortix/sdk/react';
|
|
9
|
+
import { useActiveSpace } from '../../internal/stores/active-space-store.js';
|
|
9
10
|
import { newPastedContentId, splitPastedContent, trimPastedText } from '../../_vendor/kortix-shared.js';
|
|
10
11
|
import { memo, useCallback, useEffect, useId, useLayoutEffect, useMemo, useRef, useState, useSyncExternalStore, } from 'react';
|
|
11
12
|
import { extractClipboardFiles } from './clipboard-files.js';
|
|
@@ -16,7 +17,6 @@ import { isModelRequiredButUnavailable, NO_MODEL_AVAILABLE_ACTION_MESSAGE, NO_MO
|
|
|
16
17
|
import { useModelConnectionGate } from '../models/use-model-connection-gate.js';
|
|
17
18
|
import { NO_AGENT_ACCESS_HINT, NO_AGENT_ACCESS_LABEL } from './composer-agent-access.js';
|
|
18
19
|
import { useComposerDropZone } from './composer-drop-zone.js';
|
|
19
|
-
import { useComposerEscapeStop } from './hooks/use-composer-escape-stop.js';
|
|
20
20
|
import { finishedDraftUploads, keepUnsentUploadFile, restoreDraftUploads } from './draft/draft-uploads.js';
|
|
21
21
|
import { useComposerDraft } from './draft/use-composer-draft.js';
|
|
22
22
|
import { commandBlocker, sendBlocker, sendBlockerMessage } from './send-blockers.js';
|
|
@@ -110,7 +110,7 @@ function setDocumentWithoutStealingFocus(handle, doc) {
|
|
|
110
110
|
}
|
|
111
111
|
}
|
|
112
112
|
function ComposerImpl(props) {
|
|
113
|
-
const { onSend, promptAttachments: hostPromptAttachments, isBusy = false, sessionWorking, runtimeReady = true, onStop, stopDisabled = false,
|
|
113
|
+
const { onSend, promptAttachments: hostPromptAttachments, isBusy = false, sessionWorking, runtimeReady = true, onStop, stopDisabled = false, isSending = false, rewind, agents = EMPTY_AGENTS, selectedAgent = null, onAgentChange, noAccessibleAgents = false, commands: runtimeCommands = EMPTY_COMMANDS,
|
|
114
114
|
/** Whether the live command list has EVER resolved — see `planUnresolvedCommandChip`. */
|
|
115
115
|
commandsResolved = false, slashFiles = EMPTY_SLASH_FILES, onCommand, onHoldCommand, models = EMPTY_MODELS, selectedModel = null, onModelChange, modelDefaultControls, variants = EMPTY_VARIANTS, selectedVariant = null, onVariantChange, messages, sessionId, projectId, draftScope = null, draftActive = true, disabled = false, notice = null, onNoticeRetry, clearOnSend = true, modelRequired = false, modelsLoading = false, autoFocus, placeholder = 'Ask anything…', hint, onArrowUpAtStart, prefill = null, onPrefillApplied, attachRequestId = null, providers, onContextClick, onCompactClick, inputSlot, toolbarSlot, underbarPlacement = 'below', slashMenuPlacement = 'above', cardClassName, quoteRequests = NO_QUOTE_REQUESTS, onQuoteRequestsApplied, lockForQuestion = false, lockForApproval = false, onCustomAnswer, questionButtonLabel = null, questionCanAct = true, onQuestionAction, escCount = 0, parentClassName, } = props;
|
|
116
116
|
const tI18nComplete = useTranslations('hardcodedUi.i18nComplete');
|
|
@@ -317,7 +317,19 @@ function ComposerImpl(props) {
|
|
|
317
317
|
handleDocChange(doc, isEmpty);
|
|
318
318
|
}, [handleDocChange]);
|
|
319
319
|
const { data: allSessions } = useRuntimeSessions();
|
|
320
|
-
|
|
320
|
+
// Scope the startable agents to the active space (the sidebar's Spaces
|
|
321
|
+
// selection): in a space you start only that space's agents. The current
|
|
322
|
+
// agent is always kept so a session's own agent never disappears while you
|
|
323
|
+
// are viewing another space. No space selected = every agent, as before.
|
|
324
|
+
const [activeSpace] = useActiveSpace(projectId ?? '');
|
|
325
|
+
const scopeConfig = useProjectConfig(projectId);
|
|
326
|
+
const primaryAgents = useMemo(() => {
|
|
327
|
+
const base = agents.filter((a) => !a.hidden && a.mode !== 'subagent');
|
|
328
|
+
if (!activeSpace || !scopeConfig)
|
|
329
|
+
return base;
|
|
330
|
+
const spaceByName = new Map(scopeConfig.agents.map((a) => [a.name, a.space ?? null]));
|
|
331
|
+
return base.filter((a) => spaceByName.get(a.name) === activeSpace || a.name === selectedAgent);
|
|
332
|
+
}, [agents, activeSpace, scopeConfig, selectedAgent]);
|
|
321
333
|
const editorDisabled = disabled || lockForApproval;
|
|
322
334
|
const appendAttachedFiles = useCallback((files) => {
|
|
323
335
|
// The host keeps files in its own store: they go there, not to the session.
|
|
@@ -676,12 +688,6 @@ function ComposerImpl(props) {
|
|
|
676
688
|
const canSubmit = !isEmpty ||
|
|
677
689
|
attachedFiles.length > 0 ||
|
|
678
690
|
(!lockForQuestion && (quotes.length > 0 || pastes.length > 0));
|
|
679
|
-
useComposerEscapeStop({
|
|
680
|
-
editorElement,
|
|
681
|
-
enabled: isBusy && canStop && !stopDisabled && !isSending && !lockForQuestion && !props.submitLabel,
|
|
682
|
-
hasDraft: canSubmit,
|
|
683
|
-
onStop,
|
|
684
|
-
});
|
|
685
691
|
/**
|
|
686
692
|
* No agent may run this prompt. Refused here rather than at the server:
|
|
687
693
|
* `lockForQuestion` is exempt because answering an open question is not a new
|
|
@@ -1,9 +1,9 @@
|
|
|
1
1
|
'use client';
|
|
2
|
-
import { jsx as _jsx } from "react/jsx-runtime";
|
|
2
|
+
import { jsx as _jsx, jsxs as _jsxs, Fragment as _Fragment } from "react/jsx-runtime";
|
|
3
3
|
import { useTranslations } from '../../../i18n/index.js';
|
|
4
4
|
import { cn } from '../../../lib/utils.js';
|
|
5
5
|
import { EditorContent, useEditor } from '@tiptap/react';
|
|
6
|
-
import { forwardRef, useEffect, useImperativeHandle, useMemo, useRef } from 'react';
|
|
6
|
+
import { forwardRef, useEffect, useImperativeHandle, useMemo, useRef, useState } from 'react';
|
|
7
7
|
import { textToParagraphs } from '../composer-logic.js';
|
|
8
8
|
import { COMPOSER_TEXT_METRICS } from '../composer-text-metrics.js';
|
|
9
9
|
import { useLatestRef } from '../hooks/use-latest-ref.js';
|
|
@@ -15,6 +15,7 @@ import { isCursorOnFirstVisualLine } from './first-visual-line.js';
|
|
|
15
15
|
import { MentionNode } from './mention-node.js';
|
|
16
16
|
import { serializeDocument } from './serialize.js';
|
|
17
17
|
import { createSuggestionExtension } from './suggestion.js';
|
|
18
|
+
import { UltracodeHighlight } from './ultracode.js';
|
|
18
19
|
/**
|
|
19
20
|
* Wraps `onEmptyChange` so it fires ONLY on the empty<->non-empty boundary.
|
|
20
21
|
* Exported (rather than kept as an inline `useEditor({ onUpdate })` closure)
|
|
@@ -161,8 +162,16 @@ export function insertTextAtCursor(editor, text) {
|
|
|
161
162
|
return;
|
|
162
163
|
editor.commands.insertContent(content);
|
|
163
164
|
}
|
|
165
|
+
/** The dismiss shortcut as the person's keyboard prints it. */
|
|
166
|
+
function dismissKeyLabel() {
|
|
167
|
+
const platform = typeof navigator !== 'undefined' ? navigator.platform || navigator.userAgent : '';
|
|
168
|
+
return /Mac|iPhone|iPad/.test(platform) ? '⌥W' : 'Alt+W';
|
|
169
|
+
}
|
|
164
170
|
export const ComposerEditor = forwardRef(function ComposerEditor({ placeholder, disabled, autoFocus = false, onSubmit, onArrowUpAtStart, onEmptyChange, onDocChange, agents, sessions, currentSessionId, commands, onSelectCommand, onSelectAction, actions, files, slashDockSelector, onMenuOpenChange, }, ref) {
|
|
165
171
|
const t = useTranslations('threads');
|
|
172
|
+
const tUltracode = useTranslations('multiAgent.ultracode');
|
|
173
|
+
// A marked `ultracode` keyword: the one-line hint under the text says what it does.
|
|
174
|
+
const [ultracodeActive, setUltracodeActive] = useState(false);
|
|
166
175
|
const tI18nComplete = useTranslations('hardcodedUi.i18nComplete');
|
|
167
176
|
const defaultActions = useMemo(() => localizedSlashActions(tI18nComplete), [tI18nComplete]);
|
|
168
177
|
// Mirrors use-composer-focus.ts's onTypeAheadRef: @tiptap/react only
|
|
@@ -277,6 +286,8 @@ export const ComposerEditor = forwardRef(function ComposerEditor({ placeholder,
|
|
|
277
286
|
extensions: [
|
|
278
287
|
...baseExtensions(() => placeholderRef.current),
|
|
279
288
|
MentionNode,
|
|
289
|
+
// `setUltracodeActive` is a state setter: stable, so freezing it at construction is safe.
|
|
290
|
+
UltracodeHighlight.configure({ onActiveChange: setUltracodeActive }),
|
|
280
291
|
// The one `@tiptap/suggestion` code path both `@` and `/` register
|
|
281
292
|
// through (editor/suggestion.ts's `createSuggestionExtension`).
|
|
282
293
|
// Built fresh every render like every extension above, but only the
|
|
@@ -427,10 +438,10 @@ export const ComposerEditor = forwardRef(function ComposerEditor({ placeholder,
|
|
|
427
438
|
isEmpty: () => editor?.isEmpty ?? true,
|
|
428
439
|
getElement: () => (editor && !editor.isDestroyed ? editor.view.dom : null),
|
|
429
440
|
}), [editor]);
|
|
430
|
-
return (_jsx(EditorContent, { editor: editor, className: cn(
|
|
431
|
-
|
|
432
|
-
|
|
433
|
-
|
|
434
|
-
|
|
435
|
-
|
|
441
|
+
return (_jsxs(_Fragment, { children: [_jsx(EditorContent, { editor: editor, className: cn(
|
|
442
|
+
// `text-base` (16px) on mobile, NOT 15px: iOS Safari force-zooms the
|
|
443
|
+
// page on focus for any input under 16px, and the composer is the one
|
|
444
|
+
// field on the screen. `sm:text-sm` above 640px, which is the size
|
|
445
|
+
// `styles/components.css`'s slash-trigger rule already documents.
|
|
446
|
+
'kortix-composer-editor w-full text-sm', disabled && 'opacity-50') }), ultracodeActive ? (_jsxs("p", { "data-slot": "ultracode-hint", className: "text-muted-foreground mt-1 truncate text-xs", children: [tUltracode('hint'), _jsx("span", { "aria-hidden": true, className: "px-1", children: "\u00B7" }), tUltracode('dismiss', { key: dismissKeyLabel() })] })) : null] }));
|
|
436
447
|
});
|
|
@@ -0,0 +1,34 @@
|
|
|
1
|
+
import { Extension } from '@tiptap/core';
|
|
2
|
+
import type { Node as ProseMirrorNode } from '@tiptap/pm/model';
|
|
3
|
+
import { PluginKey, type EditorState, type Transaction } from '@tiptap/pm/state';
|
|
4
|
+
import { DecorationSet } from '@tiptap/pm/view';
|
|
5
|
+
/** The utility classes of a marked keyword: the mention chip's tint, no padding (the caret must not jump). */
|
|
6
|
+
export declare const ULTRACODE_MARK_CLASS = "kortix-ultracode rounded-sm bg-primary/[0.08] font-medium text-foreground";
|
|
7
|
+
export interface UltracodeRange {
|
|
8
|
+
from: number;
|
|
9
|
+
to: number;
|
|
10
|
+
}
|
|
11
|
+
/** Every occurrence of the keyword in a document, as document positions. */
|
|
12
|
+
export declare function findUltracodeRanges(doc: ProseMirrorNode): UltracodeRange[];
|
|
13
|
+
/** True for a plain-text keyword check (the sent prompt, a test). Same rule as the editor mark. */
|
|
14
|
+
export declare function hasUltracodeKeyword(text: string): boolean;
|
|
15
|
+
export interface UltracodeState {
|
|
16
|
+
/** The person dismissed the keyword for this prompt. */
|
|
17
|
+
dismissed: boolean;
|
|
18
|
+
ranges: UltracodeRange[];
|
|
19
|
+
/** At least one marked keyword: the host shows the hint. */
|
|
20
|
+
active: boolean;
|
|
21
|
+
decorations: DecorationSet;
|
|
22
|
+
}
|
|
23
|
+
export declare const ultracodePluginKey: PluginKey<UltracodeState>;
|
|
24
|
+
/** The next state after a transaction: a dismiss meta sets it, an empty document resets it. */
|
|
25
|
+
export declare function nextUltracodeState(tr: Transaction, previous: UltracodeState, state: EditorState): UltracodeState;
|
|
26
|
+
/** Dismiss the keyword for this prompt. Returns false when nothing is marked. */
|
|
27
|
+
export declare function dismissUltracode(state: EditorState, dispatch?: (tr: Transaction) => void): boolean;
|
|
28
|
+
/** Alt+W anywhere, or Backspace with the caret right after a marked keyword. */
|
|
29
|
+
export declare function isUltracodeDismissKey(event: Pick<KeyboardEvent, 'key' | 'code' | 'altKey' | 'ctrlKey' | 'metaKey' | 'shiftKey'>, state: EditorState): boolean;
|
|
30
|
+
export interface UltracodeOptions {
|
|
31
|
+
/** Fires when the hint should appear or go: a marked keyword exists, or none does. */
|
|
32
|
+
onActiveChange?: (active: boolean) => void;
|
|
33
|
+
}
|
|
34
|
+
export declare const UltracodeHighlight: Extension<UltracodeOptions, any>;
|
|
@@ -0,0 +1,127 @@
|
|
|
1
|
+
import { Extension } from '@tiptap/core';
|
|
2
|
+
import { Plugin, PluginKey } from '@tiptap/pm/state';
|
|
3
|
+
import { Decoration, DecorationSet } from '@tiptap/pm/view';
|
|
4
|
+
/**
|
|
5
|
+
* The `ultracode` keyword, as Claude Code's dynamic workflows treat it: a
|
|
6
|
+
* prompt that holds the word runs as a workflow of agents. The composer marks
|
|
7
|
+
* each occurrence in place and the host shows a one-line hint, so the person
|
|
8
|
+
* sees the opt-in before they send. The prompt text never changes: the word
|
|
9
|
+
* is sent as typed, and the agent reads it.
|
|
10
|
+
*
|
|
11
|
+
* Alt+W (Option+W on a Mac), or Backspace right after a marked word, dismisses
|
|
12
|
+
* the mark and the hint for this prompt. A dismissed prompt stays dismissed
|
|
13
|
+
* while the person keeps typing; an empty composer (the prompt was sent or
|
|
14
|
+
* cleared) arms the keyword again.
|
|
15
|
+
*/
|
|
16
|
+
/** Whole word, any case. `\b` keeps `ultracoder` and `myultracode` plain text. */
|
|
17
|
+
const KEYWORD = /\bultracode\b/gi;
|
|
18
|
+
/** The utility classes of a marked keyword: the mention chip's tint, no padding (the caret must not jump). */
|
|
19
|
+
export const ULTRACODE_MARK_CLASS = 'kortix-ultracode rounded-sm bg-primary/[0.08] font-medium text-foreground';
|
|
20
|
+
/** Every occurrence of the keyword in a document, as document positions. */
|
|
21
|
+
export function findUltracodeRanges(doc) {
|
|
22
|
+
const ranges = [];
|
|
23
|
+
doc.descendants((node, pos) => {
|
|
24
|
+
if (!node.isText || !node.text)
|
|
25
|
+
return;
|
|
26
|
+
for (const match of node.text.matchAll(KEYWORD)) {
|
|
27
|
+
const from = pos + (match.index ?? 0);
|
|
28
|
+
ranges.push({ from, to: from + match[0].length });
|
|
29
|
+
}
|
|
30
|
+
});
|
|
31
|
+
return ranges;
|
|
32
|
+
}
|
|
33
|
+
/** True for a plain-text keyword check (the sent prompt, a test). Same rule as the editor mark. */
|
|
34
|
+
export function hasUltracodeKeyword(text) {
|
|
35
|
+
KEYWORD.lastIndex = 0;
|
|
36
|
+
const found = KEYWORD.test(text);
|
|
37
|
+
KEYWORD.lastIndex = 0;
|
|
38
|
+
return found;
|
|
39
|
+
}
|
|
40
|
+
export const ultracodePluginKey = new PluginKey('ultracode');
|
|
41
|
+
const isBlank = (doc) => doc.textContent.trim().length === 0;
|
|
42
|
+
function stateFor(doc, dismissed) {
|
|
43
|
+
const ranges = dismissed ? [] : findUltracodeRanges(doc);
|
|
44
|
+
return {
|
|
45
|
+
dismissed,
|
|
46
|
+
ranges,
|
|
47
|
+
active: ranges.length > 0,
|
|
48
|
+
decorations: ranges.length
|
|
49
|
+
? DecorationSet.create(doc, ranges.map(({ from, to }) => Decoration.inline(from, to, { class: ULTRACODE_MARK_CLASS, 'data-ultracode': '' })))
|
|
50
|
+
: DecorationSet.empty,
|
|
51
|
+
};
|
|
52
|
+
}
|
|
53
|
+
/** The next state after a transaction: a dismiss meta sets it, an empty document resets it. */
|
|
54
|
+
export function nextUltracodeState(tr, previous, state) {
|
|
55
|
+
const meta = tr.getMeta(ultracodePluginKey);
|
|
56
|
+
let dismissed = meta?.dismiss ? true : previous.dismissed;
|
|
57
|
+
if (dismissed && isBlank(state.doc))
|
|
58
|
+
dismissed = false;
|
|
59
|
+
if (!tr.docChanged && dismissed === previous.dismissed)
|
|
60
|
+
return previous;
|
|
61
|
+
return stateFor(state.doc, dismissed);
|
|
62
|
+
}
|
|
63
|
+
/** Dismiss the keyword for this prompt. Returns false when nothing is marked. */
|
|
64
|
+
export function dismissUltracode(state, dispatch) {
|
|
65
|
+
if (!ultracodePluginKey.getState(state)?.active)
|
|
66
|
+
return false;
|
|
67
|
+
dispatch?.(state.tr.setMeta(ultracodePluginKey, { dismiss: true }));
|
|
68
|
+
return true;
|
|
69
|
+
}
|
|
70
|
+
/** Alt+W anywhere, or Backspace with the caret right after a marked keyword. */
|
|
71
|
+
export function isUltracodeDismissKey(event, state) {
|
|
72
|
+
const plugin = ultracodePluginKey.getState(state);
|
|
73
|
+
if (!plugin?.active)
|
|
74
|
+
return false;
|
|
75
|
+
// `code`, not `key`: Option+W on a Mac types `∑`.
|
|
76
|
+
if (event.altKey && !event.ctrlKey && !event.metaKey && event.code === 'KeyW')
|
|
77
|
+
return true;
|
|
78
|
+
if (event.key !== 'Backspace' || event.altKey || event.ctrlKey || event.metaKey || event.shiftKey)
|
|
79
|
+
return false;
|
|
80
|
+
const { empty, from } = state.selection;
|
|
81
|
+
return empty && plugin.ranges.some((range) => range.to === from);
|
|
82
|
+
}
|
|
83
|
+
export const UltracodeHighlight = Extension.create({
|
|
84
|
+
name: 'ultracodeHighlight',
|
|
85
|
+
addOptions() {
|
|
86
|
+
return { onActiveChange: undefined };
|
|
87
|
+
},
|
|
88
|
+
addProseMirrorPlugins() {
|
|
89
|
+
const options = this.options;
|
|
90
|
+
return [
|
|
91
|
+
new Plugin({
|
|
92
|
+
key: ultracodePluginKey,
|
|
93
|
+
state: {
|
|
94
|
+
init: (_config, state) => stateFor(state.doc, false),
|
|
95
|
+
apply: (tr, previous, _old, state) => nextUltracodeState(tr, previous, state),
|
|
96
|
+
},
|
|
97
|
+
props: {
|
|
98
|
+
decorations: (state) => ultracodePluginKey.getState(state)?.decorations ?? DecorationSet.empty,
|
|
99
|
+
handleKeyDown: (view, event) => {
|
|
100
|
+
if (!isUltracodeDismissKey(event, view.state))
|
|
101
|
+
return false;
|
|
102
|
+
event.preventDefault();
|
|
103
|
+
return dismissUltracode(view.state, view.dispatch);
|
|
104
|
+
},
|
|
105
|
+
},
|
|
106
|
+
view: (view) => {
|
|
107
|
+
let reported = ultracodePluginKey.getState(view.state)?.active ?? false;
|
|
108
|
+
if (reported)
|
|
109
|
+
options.onActiveChange?.(true);
|
|
110
|
+
return {
|
|
111
|
+
update: (next) => {
|
|
112
|
+
const active = ultracodePluginKey.getState(next.state)?.active ?? false;
|
|
113
|
+
if (active === reported)
|
|
114
|
+
return;
|
|
115
|
+
reported = active;
|
|
116
|
+
options.onActiveChange?.(active);
|
|
117
|
+
},
|
|
118
|
+
destroy: () => {
|
|
119
|
+
if (reported)
|
|
120
|
+
options.onActiveChange?.(false);
|
|
121
|
+
},
|
|
122
|
+
};
|
|
123
|
+
},
|
|
124
|
+
}),
|
|
125
|
+
];
|
|
126
|
+
},
|
|
127
|
+
});
|