clay-server 5.1.1-beta.1 → 5.2.0-beta.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/lib/account-auth-policy.js +21 -0
- package/lib/account-auth-socket.js +30 -0
- package/lib/account-auth-throttle.js +44 -0
- package/lib/account-auth-transport.js +48 -0
- package/lib/account-login-page.js +28 -0
- package/lib/account-passkey-challenges.js +31 -0
- package/lib/account-passkey-page.js +89 -0
- package/lib/account-passkey-policy.js +39 -0
- package/lib/account-password-page.js +69 -0
- package/lib/account-passwords.js +36 -0
- package/lib/account-remembered.js +77 -0
- package/lib/account-session-page.js +51 -0
- package/lib/account-session-store.js +82 -0
- package/lib/builtin-mates.js +19 -16
- package/lib/bundled-skills/clay-agent-browser/SKILL.md +6 -2
- package/lib/canonical-clay-record-authority.js +15 -0
- package/lib/canonical-clay-scheduling-authority.js +19 -0
- package/lib/claude-hook-installer.js +1 -239
- package/lib/claude-jsonl-watcher.js +1 -204
- package/lib/clay-control-presentation-binding.js +96 -0
- package/lib/clay-control-presentation.js +128 -0
- package/lib/clay-control-target-projection.js +26 -0
- package/lib/clay-mate-chat-receipts.js +26 -0
- package/lib/clay-mate-chat.js +88 -0
- package/lib/clay-mate-knowledge-input.js +26 -0
- package/lib/clay-mate-knowledge.js +95 -0
- package/lib/clay-mate-lifecycle.js +95 -0
- package/lib/clay-product-control-input.js +33 -0
- package/lib/clay-product-control-tools.js +51 -0
- package/lib/clay-product-control.js +247 -0
- package/lib/clay-project-lifecycle.js +154 -0
- package/lib/clay-project-record-input.js +44 -0
- package/lib/clay-project-records.js +84 -0
- package/lib/clay-scheduling-input.js +21 -0
- package/lib/clay-scheduling-receipts.js +26 -0
- package/lib/clay-scheduling.js +119 -0
- package/lib/clay-screen-controls.js +104 -0
- package/lib/clay-skill-install.js +1 -33
- package/lib/clay-workspace-controls.js +84 -0
- package/lib/clay-workspace-input.js +17 -0
- package/lib/clay-workspace-receipts.js +26 -0
- package/lib/cli-sessions.js +1 -300
- package/lib/codex-defaults.js +1 -28
- package/lib/context-usage.js +3 -2
- package/lib/contextual-screen-snapshot.js +38 -0
- package/lib/daemon-project-access.js +11 -0
- package/lib/daemon-project-lifecycle-callbacks.js +15 -0
- package/lib/daemon-project-lifecycle.js +262 -0
- package/lib/daemon-projects.js +1 -1
- package/lib/daemon.js +80 -276
- package/lib/default-ai-runtime.js +4 -8
- package/lib/dm-digest-cursor.js +120 -0
- package/lib/email-mcp-server.js +1 -1
- package/lib/issues-service.js +29 -15
- package/lib/kiro-defaults.js +1 -22
- package/lib/knowledge-db-import-validation.js +46 -0
- package/lib/knowledge-db-import.js +99 -0
- package/lib/knowledge-db-service.js +24 -33
- package/lib/knowledge-db-storage-nedb-maintenance.js +99 -0
- package/lib/knowledge-db-storage-nedb.js +66 -0
- package/lib/knowledge-db-storage.js +72 -0
- package/lib/knowledge-db-validation.js +0 -0
- package/lib/knowledge-document-index.js +2 -1
- package/lib/knowledge-file-store.js +7 -1
- package/lib/knowledge-product-operations.js +46 -0
- package/lib/mate-avatar-catalog.js +12 -0
- package/lib/mate-avatar-migration.js +41 -0
- package/lib/mate-context-service.js +138 -0
- package/lib/mate-context-tools.js +21 -0
- package/lib/mate-creation-mcp-server.js +2 -0
- package/lib/mate-knowledge-canonical-access.js +10 -0
- package/lib/mate-knowledge-mate-bound.js +53 -0
- package/lib/mate-knowledge-mcp-server.js +55 -8
- package/lib/mate-knowledge-service.js +16 -34
- package/lib/mate-knowledge-text-tools.js +106 -0
- package/lib/mate-lifecycle-service.js +94 -0
- package/lib/mate-message-delivery.js +43 -0
- package/lib/mate-ready-creation.js +9 -1
- package/lib/mate-schedule-input.js +29 -0
- package/lib/mate-schedule-lifecycle.js +151 -0
- package/lib/mate-scheduling.js +103 -0
- package/lib/mates.js +18 -6
- package/lib/mcp-agent-tools.js +117 -0
- package/lib/mcp-connection-store.js +119 -15
- package/lib/mcp-import-credentials.js +31 -0
- package/lib/mcp-local-transport.js +13 -0
- package/lib/mcp-oauth.js +8 -6
- package/lib/mcp-proxy.js +2 -32
- package/lib/mcp-query-bridge.js +30 -0
- package/lib/mcp-remote-connections.js +74 -20
- package/lib/mcp-source-adapters.js +1 -0
- package/lib/mcp-source-context.js +1 -0
- package/lib/mcp-source-discovery.js +1 -0
- package/lib/mcp-source-plugins.js +1 -0
- package/lib/mcp-source-restrictions.js +1 -0
- package/lib/mcp-tool-policy.js +9 -0
- package/lib/migrate-single-user.js +3 -23
- package/lib/notes-checklist.js +50 -0
- package/lib/notes.js +49 -3
- package/lib/os-user-diagnostics.js +2 -4
- package/lib/os-users.js +24 -70
- package/lib/pane-pending-interactions.js +20 -0
- package/lib/pane-session-activation.js +114 -0
- package/lib/pane-session-transport.js +26 -0
- package/lib/project-admin-overview.js +51 -0
- package/lib/project-ask-user.js +8 -4
- package/lib/project-connection.js +14 -10
- package/lib/project-control-git-view.js +12 -0
- package/lib/project-debate.js +1 -0
- package/lib/project-delegated-follow-up.js +2 -1
- package/lib/project-directory-claim.js +65 -0
- package/lib/project-file-operations.js +61 -0
- package/lib/project-filesystem.js +15 -85
- package/lib/project-full-access.js +23 -2
- package/lib/project-http.js +7 -4
- package/lib/project-knowledge.js +32 -18
- package/lib/project-lifecycle-operations.js +98 -0
- package/lib/project-lifecycle-process-witness.js +32 -0
- package/lib/project-lifecycle-runtime.js +50 -0
- package/lib/project-linux-access.js +22 -0
- package/lib/project-logs-canonical-clay.js +27 -0
- package/lib/project-logs-clay-query.js +16 -0
- package/lib/project-logs-schema.js +4 -2
- package/lib/project-logs-service.js +8 -7
- package/lib/project-logs.js +1 -0
- package/lib/project-loop.js +1 -0
- package/lib/project-mate-chat-control.js +55 -0
- package/lib/project-mate-creation-proposal.js +18 -3
- package/lib/project-mate-interaction.js +40 -62
- package/lib/project-mcp.js +54 -16
- package/lib/project-models.js +14 -31
- package/lib/project-notifications.js +76 -17
- package/lib/project-ownership.js +77 -0
- package/lib/project-pair-result-delivery.js +14 -3
- package/lib/project-pair-usage.js +12 -13
- package/lib/project-pending-message-queue.js +4 -1
- package/lib/project-product-control.js +89 -0
- package/lib/project-product-session-queue.js +46 -0
- package/lib/project-push-access.js +28 -0
- package/lib/project-scheduled-message-queue.js +30 -0
- package/lib/project-scheduled-messages.js +67 -68
- package/lib/project-scheduled-task-control.js +83 -0
- package/lib/project-scheduled-tasks.js +13 -2
- package/lib/project-scheduling-access.js +10 -0
- package/lib/project-server-settings.js +1 -0
- package/lib/project-session-actions.js +65 -0
- package/lib/project-session-delete.js +8 -1
- package/lib/project-session-document.js +27 -7
- package/lib/project-session-github.js +63 -19
- package/lib/project-session-history-actions.js +167 -0
- package/lib/project-session-linear.js +14 -6
- package/lib/project-session-notes.js +7 -3
- package/lib/project-session-pair.js +1 -1
- package/lib/project-session-runtime-actions.js +64 -0
- package/lib/project-session-spawn.js +2 -3
- package/lib/project-session-vendor.js +55 -0
- package/lib/project-sessions.js +103 -272
- package/lib/project-shared-browser.js +78 -17
- package/lib/project-studio-presentation.js +58 -0
- package/lib/project-user-knowledge.js +2 -1
- package/lib/project-user-message.js +67 -1
- package/lib/project-vendor-login.js +6 -36
- package/lib/project-workspace-operations.js +126 -0
- package/lib/project-workspace-query.js +19 -2
- package/lib/project.js +178 -45
- package/lib/public/app.js +46 -0
- package/lib/public/appearance-bootstrap.js +16 -0
- package/lib/public/auth/account-login.css +98 -0
- package/lib/public/auth/account-login.js +104 -0
- package/lib/public/css/clay-tool-activity.css +51 -0
- package/lib/public/css/clay-workspace.css +29 -0
- package/lib/public/css/command-palette.css +12 -33
- package/lib/public/css/contextual-clay.css +240 -0
- package/lib/public/css/home-debate-planning.css +2 -0
- package/lib/public/css/home-mate-creation.css +5 -0
- package/lib/public/css/input.css +6 -0
- package/lib/public/css/mate-avatar-gallery.css +12 -0
- package/lib/public/css/mate-conversation.css +10 -5
- package/lib/public/css/messages.css +6 -2
- package/lib/public/css/overlays.css +4 -2
- package/lib/public/css/project-admin-overview.css +13 -0
- package/lib/public/css/session-folders.css +11 -0
- package/lib/public/css/session-github.css +46 -1
- package/lib/public/css/shared-browser.css +35 -1
- package/lib/public/css/sticky-notes.css +87 -1
- package/lib/public/css/user-settings-sessions.css +42 -0
- package/lib/public/index.html +28 -10
- package/lib/public/mate-avatars/B01.png +0 -0
- package/lib/public/mate-avatars/B02.png +0 -0
- package/lib/public/mate-avatars/B03.png +0 -0
- package/lib/public/mate-avatars/B04.png +0 -0
- package/lib/public/mate-avatars/B05.png +0 -0
- package/lib/public/mate-avatars/B06.png +0 -0
- package/lib/public/mate-avatars/B07.png +0 -0
- package/lib/public/mate-avatars/B08.png +0 -0
- package/lib/public/mate-avatars/B09.png +0 -0
- package/lib/public/mate-avatars/B10.png +0 -0
- package/lib/public/mate-avatars/B11.png +0 -0
- package/lib/public/mate-avatars/B12.png +0 -0
- package/lib/public/mate-avatars/B13.png +0 -0
- package/lib/public/mate-avatars/B14.png +0 -0
- package/lib/public/mate-avatars/B15.png +0 -0
- package/lib/public/mate-avatars/B16.png +0 -0
- package/lib/public/mate-avatars/B17.png +0 -0
- package/lib/public/mate-avatars/B18.png +0 -0
- package/lib/public/mate-avatars/B19.png +0 -0
- package/lib/public/mate-avatars/B20.png +0 -0
- package/lib/public/mate-avatars/B21.png +0 -0
- package/lib/public/mate-avatars/B22.png +0 -0
- package/lib/public/mate-avatars/B23.png +0 -0
- package/lib/public/mate-avatars/B24.png +0 -0
- package/lib/public/mate-avatars/B25.png +0 -0
- package/lib/public/mate-avatars/B26.png +0 -0
- package/lib/public/mate-avatars/B27.png +0 -0
- package/lib/public/mate-avatars/B28.png +0 -0
- package/lib/public/mate-avatars/B29.png +0 -0
- package/lib/public/mate-avatars/B30.png +0 -0
- package/lib/public/mate-avatars/B31.png +0 -0
- package/lib/public/mate-avatars/B32.png +0 -0
- package/lib/public/mate-avatars/B33.png +0 -0
- package/lib/public/mate-avatars/B34.png +0 -0
- package/lib/public/mate-avatars/B35.png +0 -0
- package/lib/public/mate-avatars/B36.png +0 -0
- package/lib/public/mate-avatars/B37.png +0 -0
- package/lib/public/mate-avatars/B38.png +0 -0
- package/lib/public/mate-avatars/B39.png +0 -0
- package/lib/public/mate-avatars/B40.png +0 -0
- package/lib/public/mate-avatars/B41.png +0 -0
- package/lib/public/mate-avatars/B42.png +0 -0
- package/lib/public/mate-avatars/B43.png +0 -0
- package/lib/public/mate-avatars/B44.png +0 -0
- package/lib/public/mate-avatars/B45.png +0 -0
- package/lib/public/mate-avatars/B46.png +0 -0
- package/lib/public/mate-avatars/B47.png +0 -0
- package/lib/public/mate-avatars/B48.png +0 -0
- package/lib/public/mate-avatars/C01.png +0 -0
- package/lib/public/mate-avatars/C02.png +0 -0
- package/lib/public/mate-avatars/C03.png +0 -0
- package/lib/public/mate-avatars/C04.png +0 -0
- package/lib/public/mate-avatars/C05.png +0 -0
- package/lib/public/mate-avatars/C06.png +0 -0
- package/lib/public/mate-avatars/C07.png +0 -0
- package/lib/public/mate-avatars/C08.png +0 -0
- package/lib/public/mate-avatars/C09.png +0 -0
- package/lib/public/mate-avatars/C10.png +0 -0
- package/lib/public/mate-avatars/C11.png +0 -0
- package/lib/public/mate-avatars/C12.png +0 -0
- package/lib/public/mate-avatars/C13.png +0 -0
- package/lib/public/mate-avatars/C14.png +0 -0
- package/lib/public/mate-avatars/C15.png +0 -0
- package/lib/public/mate-avatars/C16.png +0 -0
- package/lib/public/mate-avatars/C17.png +0 -0
- package/lib/public/mate-avatars/C18.png +0 -0
- package/lib/public/mate-avatars/C19.png +0 -0
- package/lib/public/mate-avatars/C20.png +0 -0
- package/lib/public/mate-avatars/C21.png +0 -0
- package/lib/public/mate-avatars/C22.png +0 -0
- package/lib/public/mate-avatars/C23.png +0 -0
- package/lib/public/mate-avatars/C24.png +0 -0
- package/lib/public/mate-avatars/C25.png +0 -0
- package/lib/public/mate-avatars/C26.png +0 -0
- package/lib/public/mate-avatars/C27.png +0 -0
- package/lib/public/mate-avatars/C28.png +0 -0
- package/lib/public/mate-avatars/C29.png +0 -0
- package/lib/public/mate-avatars/C30.png +0 -0
- package/lib/public/mate-avatars/C31.png +0 -0
- package/lib/public/mate-avatars/C32.png +0 -0
- package/lib/public/mate-avatars/C33.png +0 -0
- package/lib/public/mate-avatars/C34.png +0 -0
- package/lib/public/mate-avatars/C35.png +0 -0
- package/lib/public/mate-avatars/C36.png +0 -0
- package/lib/public/mate-avatars/C37.png +0 -0
- package/lib/public/mate-avatars/C38.png +0 -0
- package/lib/public/mate-avatars/C39.png +0 -0
- package/lib/public/mate-avatars/C40.png +0 -0
- package/lib/public/mate-avatars/C41.png +0 -0
- package/lib/public/mate-avatars/C42.png +0 -0
- package/lib/public/mate-avatars/C43.png +0 -0
- package/lib/public/mate-avatars/C44.png +0 -0
- package/lib/public/mate-avatars/C45.png +0 -0
- package/lib/public/mate-avatars/C46.png +0 -0
- package/lib/public/mate-avatars/C47.png +0 -0
- package/lib/public/mate-avatars/C48.png +0 -0
- package/lib/public/mate-avatars/catalog.json +482 -0
- package/lib/public/mate-avatars/lead-clay.png +0 -0
- package/lib/public/modules/account-auth-settings.js +71 -0
- package/lib/public/modules/account-transport-settings.js +51 -0
- package/lib/public/modules/admin-settings-projects.js +6 -2
- package/lib/public/modules/app-connection.js +11 -1
- package/lib/public/modules/app-favicon.js +18 -9
- package/lib/public/modules/app-header.js +7 -4
- package/lib/public/modules/app-loop-ui.js +2 -0
- package/lib/public/modules/app-message-router.js +22 -1
- package/lib/public/modules/app-messages.js +119 -17
- package/lib/public/modules/app-misc.js +3 -1
- package/lib/public/modules/app-notifications.js +11 -5
- package/lib/public/modules/app-panels.js +61 -123
- package/lib/public/modules/app-projects.js +13 -0
- package/lib/public/modules/app-rate-limit.js +7 -27
- package/lib/public/modules/app-rendering.js +4 -3
- package/lib/public/modules/avatar.js +15 -41
- package/lib/public/modules/chat-render-runtime.js +20 -0
- package/lib/public/modules/clay-browser-links.js +47 -0
- package/lib/public/modules/clay-control-activity.js +214 -0
- package/lib/public/modules/clay-control-copy.js +36 -0
- package/lib/public/modules/clay-control-detail-targets.js +44 -0
- package/lib/public/modules/clay-control-object-targets.js +52 -0
- package/lib/public/modules/clay-control-target-visibility.js +12 -0
- package/lib/public/modules/clay-control-targets.js +44 -0
- package/lib/public/modules/clay-log-links.js +23 -0
- package/lib/public/modules/clay-navigation-render.js +52 -0
- package/lib/public/modules/clay-owner-navigation.js +33 -0
- package/lib/public/modules/clay-session-links.js +31 -0
- package/lib/public/modules/clay-studio-bridge.js +20 -0
- package/lib/public/modules/clay-studio-document.js +67 -0
- package/lib/public/modules/clay-studio-render.js +146 -0
- package/lib/public/modules/clay-tool-activity.js +140 -0
- package/lib/public/modules/clay-tool-presentation.js +342 -0
- package/lib/public/modules/command-palette.js +162 -40
- package/lib/public/modules/contextual-ask-session.js +26 -0
- package/lib/public/modules/contextual-clay-geometry.js +155 -0
- package/lib/public/modules/contextual-clay-session.js +130 -0
- package/lib/public/modules/contextual-clay-workspace.js +169 -0
- package/lib/public/modules/contextual-clay.js +250 -0
- package/lib/public/modules/contextual-composer.js +91 -0
- package/lib/public/modules/contextual-mate-context.js +117 -0
- package/lib/public/modules/contextual-mate-hint.js +40 -0
- package/lib/public/modules/contextual-mate-identity.js +23 -0
- package/lib/public/modules/contextual-mate-sessions.js +134 -0
- package/lib/public/modules/contextual-search.js +137 -0
- package/lib/public/modules/contextual-session-citations.js +58 -0
- package/lib/public/modules/debate.js +1 -0
- package/lib/public/modules/default-ai.js +11 -3
- package/lib/public/modules/elicitation-form.js +5 -0
- package/lib/public/modules/filebrowser.js +20 -1
- package/lib/public/modules/generation-stop.js +8 -5
- package/lib/public/modules/git-panel.js +3 -1
- package/lib/public/modules/history-replay-batch.js +13 -1
- package/lib/public/modules/home-debate-live.js +2 -0
- package/lib/public/modules/home-debate-planning.js +7 -7
- package/lib/public/modules/home-mate-avatar-editor.js +127 -208
- package/lib/public/modules/home-mate-chat.js +8 -6
- package/lib/public/modules/home-mate-creation.js +73 -1
- package/lib/public/modules/home-mate-settings.js +19 -12
- package/lib/public/modules/icon-strip-tooltip.js +2 -1
- package/lib/public/modules/input.js +88 -10
- package/lib/public/modules/issues-render.js +3 -2
- package/lib/public/modules/knowledge-db-workbench.js +4 -4
- package/lib/public/modules/markdown.js +6 -34
- package/lib/public/modules/mate-avatar-catalog.js +97 -0
- package/lib/public/modules/mate-knowledge-workbench.js +1 -1
- package/lib/public/modules/mate-management.js +40 -7
- package/lib/public/modules/mcp-connection-view.js +31 -13
- package/lib/public/modules/mcp-discovery-view.js +31 -0
- package/lib/public/modules/mcp-ui.js +23 -4
- package/lib/public/modules/mention.js +3 -0
- package/lib/public/modules/message-delivery.js +20 -2
- package/lib/public/modules/model-picker.js +2 -0
- package/lib/public/modules/pane-activation.js +214 -0
- package/lib/public/modules/pane-binding.js +82 -0
- package/lib/public/modules/pane-bridge.js +7 -4
- package/lib/public/modules/pane-browser-bridge.js +22 -0
- package/lib/public/modules/pane-file-bridge.js +4 -0
- package/lib/public/modules/pane-issue-bridge.js +4 -1
- package/lib/public/modules/passkey-browser.js +69 -0
- package/lib/public/modules/passkey-server-settings.js +57 -0
- package/lib/public/modules/pending-message-queue.js +1 -0
- package/lib/public/modules/permission-control.js +5 -4
- package/lib/public/modules/personal-settings-dialog.js +7 -1
- package/lib/public/modules/product-review.js +26 -0
- package/lib/public/modules/profile.js +1 -238
- package/lib/public/modules/project-access-recovery.js +17 -0
- package/lib/public/modules/project-admin-overview.js +21 -0
- package/lib/public/modules/project-chat-identity.js +13 -4
- package/lib/public/modules/project-logs-render.js +6 -2
- package/lib/public/modules/project-mate-navigation.js +144 -22
- package/lib/public/modules/rewind.js +5 -0
- package/lib/public/modules/scheduled-tasks.js +2 -0
- package/lib/public/modules/scheduler.js +2 -0
- package/lib/public/modules/search-clay-chat.js +5 -440
- package/lib/public/modules/server-settings-controls.js +10 -0
- package/lib/public/modules/server-settings.js +7 -2
- package/lib/public/modules/session-actions.js +5 -2
- package/lib/public/modules/session-context-menu.js +5 -0
- package/lib/public/modules/session-create-form.js +10 -10
- package/lib/public/modules/session-folder-layout.js +1 -1
- package/lib/public/modules/session-folder-view-menu.js +9 -0
- package/lib/public/modules/session-github.js +85 -14
- package/lib/public/modules/session-rich-drafts.js +21 -0
- package/lib/public/modules/session-switch-defer.js +67 -0
- package/lib/public/modules/session-work-primary.js +51 -0
- package/lib/public/modules/settings-defaults.js +27 -28
- package/lib/public/modules/shared-browser-settings.js +112 -0
- package/lib/public/modules/shared-browser-tabs.js +13 -3
- package/lib/public/modules/shared-browser.js +29 -6
- package/lib/public/modules/sidebar-mobile.js +4 -3
- package/lib/public/modules/sidebar-projects.js +1 -0
- package/lib/public/modules/sidebar-session-folders-ui.js +1 -1
- package/lib/public/modules/sidebar-sessions.js +1 -0
- package/lib/public/modules/split-group-restore.js +68 -0
- package/lib/public/modules/split-pair-ui.js +1 -0
- package/lib/public/modules/split-pane-reconciler.js +15 -0
- package/lib/public/modules/split-pane-renderer.js +87 -6
- package/lib/public/modules/split-session-boundary.js +1 -1
- package/lib/public/modules/split-view.js +60 -68
- package/lib/public/modules/sticky-note-markdown.js +72 -6
- package/lib/public/modules/sticky-notes-actions.js +30 -0
- package/lib/public/modules/sticky-notes-browser.js +9 -2
- package/lib/public/modules/sticky-notes-card.js +23 -7
- package/lib/public/modules/sticky-notes-checklist.js +116 -0
- package/lib/public/modules/sticky-notes-editor.js +108 -44
- package/lib/public/modules/sticky-notes-shared.js +50 -2
- package/lib/public/modules/sticky-notes-state.js +66 -0
- package/lib/public/modules/sticky-notes.js +34 -51
- package/lib/public/modules/stt-controller.js +4 -1
- package/lib/public/modules/stt-recording.js +1 -1
- package/lib/public/modules/stt.js +7 -2
- package/lib/public/modules/terminal.js +9 -0
- package/lib/public/modules/theme.js +8 -1
- package/lib/public/modules/thinking-lifecycle.js +33 -3
- package/lib/public/modules/thinking-view.js +23 -1
- package/lib/public/modules/tools.js +60 -11
- package/lib/public/modules/tui-grab.js +1 -2
- package/lib/public/modules/user-settings-account.js +14 -1
- package/lib/public/modules/user-settings-appearance.js +10 -3
- package/lib/public/modules/user-settings-editors.js +1 -1
- package/lib/public/modules/user-settings-layout.js +11 -2
- package/lib/public/modules/user-settings-preferences.js +6 -2
- package/lib/public/modules/user-settings-profile.js +12 -2
- package/lib/public/modules/user-settings-sessions.js +120 -0
- package/lib/public/modules/user-settings.js +6 -2
- package/lib/public/modules/vendor-login-browser.js +5 -3
- package/lib/public/modules/vendor-login.js +2 -2
- package/lib/public/modules/vendor-priority.js +15 -1
- package/lib/public/modules/wireframe-workbench.js +5 -2
- package/lib/public/modules/you-activity.js +3 -1
- package/lib/public/modules/you.js +91 -6
- package/lib/public/muse-avatar.svg +4 -0
- package/lib/public/style.css +6 -0
- package/lib/public/sw.js +3 -1
- package/lib/safe-bash-commands.js +3 -45
- package/lib/scheduled-task-records.js +3 -1
- package/lib/scheduler.js +2 -0
- package/lib/sdk-bridge.js +342 -401
- package/lib/sdk-foreground-admission.js +16 -0
- package/lib/sdk-mcp-descriptors.js +2 -37
- package/lib/sdk-message-processor.js +52 -17
- package/lib/sdk-quota-snapshot.js +1 -1
- package/lib/sdk-response-recovery.js +1 -0
- package/lib/sdk-worker.js +2 -677
- package/lib/server-account-passkeys.js +186 -0
- package/lib/server-account-passwords.js +127 -0
- package/lib/server-account-security.js +53 -0
- package/lib/server-admin.js +63 -16
- package/lib/server-appearance-settings.js +13 -1
- package/lib/server-auth.js +107 -79
- package/lib/server-contextual-clay-settings.js +40 -0
- package/lib/server-contextual-mate-sessions.js +70 -0
- package/lib/server-dm.js +2 -1
- package/lib/server-global-ws.js +10 -20
- package/lib/server-home-chat-events.js +18 -4
- package/lib/server-home-chat.js +22 -20
- package/lib/server-home-clay-entry.js +23 -4
- package/lib/server-home-clay-session-links.js +29 -9
- package/lib/server-home-mate-creation.js +1 -0
- package/lib/server-home-mcp-consent.js +14 -0
- package/lib/server-mates.js +25 -62
- package/lib/server-owner-ui.js +118 -0
- package/lib/server-path-access.js +38 -0
- package/lib/server-project-removal.js +22 -0
- package/lib/server-settings.js +8 -2
- package/lib/server.js +165 -43
- package/lib/session-config-transition.js +45 -0
- package/lib/session-folders.js +7 -2
- package/lib/session-fork-history.js +21 -0
- package/lib/session-github.js +9 -2
- package/lib/session-hygiene.js +3 -35
- package/lib/session-permission-mode.js +4 -3
- package/lib/session-skill-scope.js +11 -0
- package/lib/session-visibility.js +5 -2
- package/lib/session-work-primary.js +50 -0
- package/lib/sessions.js +64 -99
- package/lib/shared-browser-cookie-sync.js +32 -0
- package/lib/shared-browser-cookies.js +79 -0
- package/lib/shared-browser-runtime.js +25 -9
- package/lib/shared-browser-storage-sync.js +43 -0
- package/lib/shared-browser-storage.js +101 -0
- package/lib/shared-browser-tools.js +2 -1
- package/lib/shared-browser-worker.js +46 -10
- package/lib/terminal-manager.js +65 -6
- package/lib/tool-llm.js +1 -1
- package/lib/tui-transcript-index.js +1 -132
- package/lib/user-knowledge-service.js +23 -1
- package/lib/users-auth.js +38 -3
- package/lib/users-contextual-clay-preferences.js +31 -0
- package/lib/users-create.js +97 -0
- package/lib/users-permissions.js +2 -8
- package/lib/users-server-pin.js +37 -0
- package/lib/users.js +18 -84
- package/lib/vendor-login-browser.js +1 -11
- package/lib/workspace-assignment-service.js +25 -0
- package/lib/workspace-query-access.js +4 -1
- package/lib/workspace-query-mcp-server.js +1 -1
- package/lib/workspace-query-service.js +13 -2
- package/lib/ws-request.js +1 -0
- package/lib/ws-schema.js +18 -2
- package/lib/yoke/acp-agent-profiles.js +7 -5
- package/lib/yoke/adapters/antigravity.js +3 -14
- package/lib/yoke/adapters/claude-query-contract.js +9 -0
- package/lib/yoke/adapters/claude.js +54 -50
- package/lib/yoke/adapters/codex-query-contract.js +24 -0
- package/lib/yoke/adapters/codex.js +53 -111
- package/lib/yoke/adapters/kiro.js +3 -1
- package/lib/yoke/adapters/muse-query-contract.js +7 -0
- package/lib/yoke/adapters/muse.js +122 -0
- package/lib/yoke/auth-events.js +17 -0
- package/lib/yoke/claude-hook-installer.js +271 -0
- package/lib/yoke/claude-jsonl-watcher.js +204 -0
- package/lib/yoke/claude-maintenance.js +55 -0
- package/lib/yoke/claude-permission-patterns.js +53 -0
- package/lib/yoke/claude-response-recovery.js +155 -0
- package/lib/yoke/claude-transcript-hygiene.js +34 -0
- package/lib/yoke/claude-worker-startup.js +28 -0
- package/lib/yoke/clay-skill-install.js +33 -0
- package/lib/yoke/cli-sessions.js +300 -0
- package/lib/yoke/codex-app-server.js +7 -12
- package/lib/yoke/codex-idle-recovery.js +81 -1
- package/lib/yoke/codex-recovery-admission.js +164 -0
- package/lib/yoke/configuration.js +13 -0
- package/lib/yoke/discovery.js +70 -0
- package/lib/yoke/errors.js +8 -0
- package/lib/yoke/host-environment.js +7 -0
- package/lib/yoke/index.js +9 -51
- package/lib/yoke/interface.js +116 -0
- package/lib/yoke/kiro-acp-server.js +5 -5
- package/lib/yoke/legacy-sessions.js +89 -0
- package/lib/yoke/login-protocol.js +25 -0
- package/lib/yoke/maintenance.js +12 -0
- package/lib/yoke/mcp-proxy.js +32 -0
- package/lib/yoke/mcp-source-adapters.js +91 -0
- package/lib/yoke/mcp-source-context.js +42 -0
- package/lib/yoke/mcp-source-discovery.js +169 -0
- package/lib/yoke/mcp-source-plugins.js +68 -0
- package/lib/yoke/mcp-source-restrictions.js +47 -0
- package/lib/yoke/mcp-tool-policy-normalize.js +28 -0
- package/lib/yoke/model-preferences.js +6 -0
- package/lib/yoke/muse-artifacts.js +36 -0
- package/lib/yoke/muse-controls.js +50 -0
- package/lib/yoke/muse-input.js +64 -0
- package/lib/yoke/muse-items.js +157 -0
- package/lib/yoke/muse-policy.js +52 -0
- package/lib/yoke/muse-query.js +428 -0
- package/lib/yoke/muse-runtime.js +211 -0
- package/lib/yoke/muse-services.js +79 -0
- package/lib/yoke/muse-skills.js +79 -0
- package/lib/yoke/muse-turns.js +71 -0
- package/lib/yoke/options/acp.js +2 -0
- package/lib/yoke/options/antigravity.js +2 -0
- package/lib/yoke/options/claude.js +21 -0
- package/lib/yoke/options/codex-defaults.js +29 -0
- package/lib/yoke/options/codex-settings.js +21 -0
- package/lib/yoke/options/codex.js +6 -0
- package/lib/yoke/options/kiro-defaults.js +22 -0
- package/lib/yoke/options/kiro.js +5 -0
- package/lib/yoke/options/muse.js +5 -0
- package/lib/yoke/provider-contract.js +5 -0
- package/lib/yoke/providers/antigravity-executable.js +8 -0
- package/lib/yoke/providers/claude-executable.js +40 -0
- package/lib/yoke/providers/claude-model-descriptions.js +14 -0
- package/lib/yoke/providers/claude-process.js +97 -0
- package/lib/yoke/providers/claude-provision.js +75 -0
- package/lib/yoke/providers/codex-errors.js +8 -0
- package/lib/yoke/providers/muse-executable.js +17 -0
- package/lib/yoke/provisioning.js +6 -0
- package/lib/yoke/query-options.js +10 -0
- package/lib/yoke/response-recovery.js +41 -0
- package/lib/yoke/sdk-mcp-descriptors.js +37 -0
- package/lib/yoke/sdk-server-factory.js +7 -0
- package/lib/yoke/session-history.js +8 -0
- package/lib/yoke/session-tool-transport.js +34 -13
- package/lib/yoke/settings.js +23 -0
- package/lib/yoke/source-locations.js +4 -0
- package/lib/yoke/title-query.js +18 -7
- package/lib/yoke/tui-transcript-index.js +132 -0
- package/lib/yoke/usage.js +48 -0
- package/lib/yoke/user-input.js +13 -0
- package/lib/yoke/vendor-registry.js +81 -1
- package/package.json +11 -4
|
@@ -0,0 +1,40 @@
|
|
|
1
|
+
import { store } from './store.js';
|
|
2
|
+
import { contextualMate, contextualTrigger } from './contextual-mate-identity.js';
|
|
3
|
+
import { getHomeMateName } from './home-mate-selection.js';
|
|
4
|
+
|
|
5
|
+
export function renderContextualMateHint() {
|
|
6
|
+
var state = store.get('contextualClay') || {};
|
|
7
|
+
var mate = contextualMate(state.mateId);
|
|
8
|
+
var active = state.mode === 'popover' && mate;
|
|
9
|
+
var narrow = window.matchMedia('(max-width: 768px)').matches;
|
|
10
|
+
var moved = document.querySelector('.contextual-mate-mobile-trigger');
|
|
11
|
+
if (moved && (!active || !narrow || moved.dataset.mateId !== mate.id)) {
|
|
12
|
+
moved.classList.remove('contextual-mate-mobile-trigger');
|
|
13
|
+
document.getElementById('icon-strip-projects').appendChild(moved);
|
|
14
|
+
}
|
|
15
|
+
var anchor = active && contextualTrigger(mate.id);
|
|
16
|
+
if (anchor && narrow && mate.builtinKey !== 'clay') {
|
|
17
|
+
anchor.classList.add('contextual-mate-mobile-trigger'); if (anchor.parentNode !== document.body) document.body.appendChild(anchor);
|
|
18
|
+
}
|
|
19
|
+
document.body.classList.toggle('contextual-mate-hint-mobile', !!active && narrow);
|
|
20
|
+
document.body.classList.toggle('contextual-mate-ordinary-mobile', !!active && narrow && mate.builtinKey !== 'clay');
|
|
21
|
+
document.querySelectorAll('[aria-describedby="contextual-mate-hint"]').forEach(function (item) { if (item !== anchor) item.removeAttribute('aria-describedby'); });
|
|
22
|
+
var hint = document.getElementById('contextual-mate-hint');
|
|
23
|
+
if (!hint || !active || !anchor || !anchor.getClientRects().length) { if (hint) hint.hidden = true; return null; }
|
|
24
|
+
anchor.setAttribute('aria-describedby', hint.id);
|
|
25
|
+
var name = getHomeMateName(mate);
|
|
26
|
+
hint.textContent = (window.matchMedia('(pointer: coarse)').matches ? 'Tap' : 'Click') + ' again to open ' + name;
|
|
27
|
+
hint.title = hint.textContent;
|
|
28
|
+
hint.setAttribute('aria-label', 'Open ' + name + ' workspace');
|
|
29
|
+
hint.hidden = false;
|
|
30
|
+
var rect = anchor.getBoundingClientRect();
|
|
31
|
+
hint.style.maxWidth = (narrow ? window.innerWidth - 64 : Math.min(260, window.innerWidth - rect.right - 24)) + 'px';
|
|
32
|
+
hint.style.left = (narrow ? 50 : rect.right + 8) + 'px';
|
|
33
|
+
hint.style.top = (narrow ? 8 : Math.max(8, Math.min(window.innerHeight - 38, rect.top + (rect.height - 28) / 2))) + 'px';
|
|
34
|
+
return hint.getBoundingClientRect();
|
|
35
|
+
}
|
|
36
|
+
export function initContextualMateHint(activate) {
|
|
37
|
+
var hint = document.createElement('button'); hint.type = 'button'; hint.id = 'contextual-mate-hint'; hint.hidden = true;
|
|
38
|
+
hint.addEventListener('click', function () { activate((store.get('contextualClay') || {}).mateId); });
|
|
39
|
+
document.body.appendChild(hint);
|
|
40
|
+
}
|
|
@@ -0,0 +1,23 @@
|
|
|
1
|
+
import { store } from './store.js';
|
|
2
|
+
|
|
3
|
+
export function contextualMate(id) {
|
|
4
|
+
var mate = (store.get('cachedMatesList') || []).find(function (item) { return item && item.id === id; });
|
|
5
|
+
if (!mate || mate.archived || mate.contentAccess === false || mate.accessible === false) return null;
|
|
6
|
+
var owner = store.get('myUserId');
|
|
7
|
+
if (owner && mate.createdBy && mate.createdBy !== owner) return null;
|
|
8
|
+
var project = (store.get('projectsHubList') || []).find(function (item) { return item.slug === 'mate-' + id; });
|
|
9
|
+
if (project && project.contentAccess === false) return null;
|
|
10
|
+
return mate;
|
|
11
|
+
}
|
|
12
|
+
export function contextualMateStamp(mate) { return JSON.stringify([mate.id, mate.createdBy || null, mate.createdAt || null, mate.builtinKey || null]); }
|
|
13
|
+
export function contextualFrame(id, sessionId) {
|
|
14
|
+
var mateId = id || (store.get('contextualClay') || {}).mateId;
|
|
15
|
+
var current = store.get('contextualClay') || {};
|
|
16
|
+
if (!sessionId && current.mateId === mateId && current.startingAsk) return null;
|
|
17
|
+
var selected = sessionId || (current.mateId === mateId && current.sessionId) || (store.get('contextualSessionSelection') || {})[mateId];
|
|
18
|
+
return Array.from(document.querySelectorAll('#contextual-clay iframe')).find(function (frame) { return frame.dataset.mateId === mateId && (!selected || String(selected) === frame.dataset.sessionId); }) || null;
|
|
19
|
+
}
|
|
20
|
+
export function contextualTrigger(id) {
|
|
21
|
+
var mate = contextualMate(id || (store.get('contextualClay') || {}).mateId);
|
|
22
|
+
return mate && mate.builtinKey !== 'clay' ? document.querySelector('.icon-strip-project-mate[data-mate-id="' + CSS.escape(mate.id) + '"]') : document.querySelector('.icon-strip-brand');
|
|
23
|
+
}
|
|
@@ -0,0 +1,134 @@
|
|
|
1
|
+
// Saved conversations are independent of which compact renderers are mounted.
|
|
2
|
+
import { store } from './store.js';
|
|
3
|
+
import { getWs } from './ws-ref.js';
|
|
4
|
+
import { contextualMate, contextualMateStamp, contextualFrame } from './contextual-mate-identity.js';
|
|
5
|
+
import { selectContextualConversation } from './contextual-clay.js';
|
|
6
|
+
import { pauseContextualSearchForSelection } from './contextual-search.js';
|
|
7
|
+
import { iconHtml, refreshIcons } from './icons.js';
|
|
8
|
+
import { showToast } from './utils.js';
|
|
9
|
+
|
|
10
|
+
function selection() { var value = store.get('contextualClay') || {}; return JSON.stringify([value.mateId, value.sessionId, value.startingAsk]); }
|
|
11
|
+
function host() { return document.getElementById('contextual-clay'); }
|
|
12
|
+
function requestState(kind) { return store.get(kind === 'list' ? 'contextualConversationHistory' : 'contextualConversationRequest'); }
|
|
13
|
+
function save(kind, value) { var update = {}; update[kind === 'list' ? 'contextualConversationHistory' : 'contextualConversationRequest'] = value; store.set(update); }
|
|
14
|
+
function valid(request) { var mate = request && contextualMate(request.mateId); return request && request.ownerId === store.get('myUserId') && mate && contextualMateStamp(mate) === request.stamp; }
|
|
15
|
+
function guardDraft() {
|
|
16
|
+
var frame = contextualFrame();
|
|
17
|
+
try {
|
|
18
|
+
if (frame && frame.conversation) frame.conversation.checkDraft();
|
|
19
|
+
return true;
|
|
20
|
+
} catch (error) { showToast(error.message, 'warn'); return false; }
|
|
21
|
+
}
|
|
22
|
+
function send(kind, item, lookup) {
|
|
23
|
+
var mate = contextualMate((store.get('contextualClay') || {}).mateId), socket = getWs();
|
|
24
|
+
if (!mate) return;
|
|
25
|
+
var old = requestState(kind);
|
|
26
|
+
if (kind !== 'list' && old && old.status === 'loading') { showToast('Wait for the current conversation request to finish.', 'warn'); return; }
|
|
27
|
+
if (kind !== 'list' && !guardDraft()) return;
|
|
28
|
+
var request = lookup ? Object.assign({}, old) : { requestId: 'mate-conversations-' + crypto.randomUUID(), mateId: mate.id, stamp: contextualMateStamp(mate), ownerId: store.get('myUserId'), selection: selection(), kind: kind, item: item };
|
|
29
|
+
if (!valid(request)) return;
|
|
30
|
+
request.status = 'loading'; request.error = null; request.socket = socket;
|
|
31
|
+
save(kind, request);
|
|
32
|
+
if (!store.get('connected') || !socket || socket.readyState !== 1) { save(kind, Object.assign({}, request, { status: 'error', error: 'Reconnect to load or start a conversation.' })); return; }
|
|
33
|
+
var payload = { type: kind === 'list' ? 'home_mate_sessions_list' : kind === 'new' ? 'home_mate_new_session' : 'home_mate_session_open', presentation: 'contextual', mateId: request.mateId, mateStamp: request.stamp, requestId: request.requestId };
|
|
34
|
+
if (item) { payload.sessionId = item.id; payload.sessionOriginId = item.sessionOriginId; }
|
|
35
|
+
if (lookup && kind === 'new') payload.lookupOnly = true;
|
|
36
|
+
try { socket.send(JSON.stringify(payload)); }
|
|
37
|
+
catch (error) { save(kind, Object.assign({}, request, { status: 'error', error: 'The request is unconfirmed. Check again after reconnecting.' })); }
|
|
38
|
+
setTimeout(function () {
|
|
39
|
+
var current = requestState(kind);
|
|
40
|
+
if (current && current.requestId === request.requestId && current.status === 'loading') save(kind, Object.assign({}, current, { status: 'error', error: kind === 'new' ? 'Creation is unconfirmed. Check the same request or browse history.' : 'Conversation history did not respond. Try again.' }));
|
|
41
|
+
}, 15000);
|
|
42
|
+
}
|
|
43
|
+
function age(timestamp) {
|
|
44
|
+
if (!timestamp) return '';
|
|
45
|
+
var date = new Date(timestamp), today = new Date();
|
|
46
|
+
return date.toDateString() === today.toDateString() ? 'Today' : date.toLocaleDateString(undefined, { month: 'short', day: 'numeric' });
|
|
47
|
+
}
|
|
48
|
+
function render() {
|
|
49
|
+
var surface = host(); if (!surface) return;
|
|
50
|
+
var mateId = (store.get('contextualClay') || {}).mateId;
|
|
51
|
+
var request = requestState('action'), history = requestState('list');
|
|
52
|
+
var busy = request && request.mateId === mateId && request.status === 'loading';
|
|
53
|
+
surface.querySelector('[data-mate-new]').disabled = !!busy;
|
|
54
|
+
surface.querySelector('[data-mate-new]').setAttribute('aria-busy', String(!!busy));
|
|
55
|
+
var notice = surface.querySelector('[data-conversation-notice]');
|
|
56
|
+
notice.hidden = !request || request.mateId !== mateId || request.status === 'done';
|
|
57
|
+
if (!notice.hidden) {
|
|
58
|
+
notice.querySelector('span').textContent = request.error || (request.kind === 'new' ? 'Starting a new chat…' : 'Opening conversation…');
|
|
59
|
+
notice.querySelector('button').hidden = request.status !== 'error';
|
|
60
|
+
notice.querySelector('button').textContent = request.kind === 'new' ? 'Check request' : 'Try again';
|
|
61
|
+
}
|
|
62
|
+
var list = surface.querySelector('[data-mate-session-list]');
|
|
63
|
+
if (!surface.querySelector('[data-mate-history]').open) return;
|
|
64
|
+
var key = JSON.stringify([history && history.requestId, history && history.status, history && history.error, mateId, (store.get('contextualClay') || {}).sessionId, !!busy]);
|
|
65
|
+
if (list.dataset.renderKey === key) return;
|
|
66
|
+
list.dataset.renderKey = key;
|
|
67
|
+
list.replaceChildren();
|
|
68
|
+
if (!history || history.mateId !== mateId || history.status !== 'done') {
|
|
69
|
+
var status = document.createElement('p'); status.setAttribute('role', 'status');
|
|
70
|
+
status.textContent = history && history.mateId === mateId && history.error || 'Loading conversations…'; list.appendChild(status);
|
|
71
|
+
if (history && history.status === 'error') { var retry = document.createElement('button'); retry.type = 'button'; retry.textContent = 'Try again'; retry.onclick = function () { send('list'); }; list.appendChild(retry); }
|
|
72
|
+
return;
|
|
73
|
+
}
|
|
74
|
+
if (!history.sessions.length) { var empty = document.createElement('p'); empty.textContent = 'No saved conversations yet.'; list.appendChild(empty); }
|
|
75
|
+
history.sessions.forEach(function (item) {
|
|
76
|
+
var button = document.createElement('button'); button.type = 'button'; button.dataset.sessionId = String(item.localId);
|
|
77
|
+
button.setAttribute('aria-current', String(String((store.get('contextualClay') || {}).sessionId) === String(item.localId)));
|
|
78
|
+
var title = document.createElement('span'); title.textContent = item.title || 'New conversation';
|
|
79
|
+
var detail = document.createElement('small'); detail.textContent = item.isProcessing ? 'Working' : age(item.lastActivity || item.createdAt);
|
|
80
|
+
button.append(title, detail); button.title = title.textContent; button.disabled = !!busy;
|
|
81
|
+
button.onclick = function () { send('open', item); };
|
|
82
|
+
list.appendChild(button);
|
|
83
|
+
});
|
|
84
|
+
if (history.truncated) { var limit = document.createElement('p'); limit.textContent = 'Showing the 500 most recent conversations.'; list.appendChild(limit); }
|
|
85
|
+
}
|
|
86
|
+
export function attachContextualConversations(surface) {
|
|
87
|
+
var actions = surface.querySelector('.contextual-clay-actions');
|
|
88
|
+
var tools = document.createElement('div'); tools.className = 'contextual-conversation-tools';
|
|
89
|
+
tools.innerHTML = '<button type="button" data-mate-new aria-label="New chat" title="New chat">' + iconHtml('square-pen') + '<span>New chat</span></button><details data-mate-history><summary role="button" aria-label="Conversation history" aria-haspopup="dialog" aria-expanded="false" aria-controls="contextual-conversation-history" title="Conversation history">' + iconHtml('history') + '</summary><div id="contextual-conversation-history" role="dialog" aria-label="Conversation history"><span class="contextual-history-label">Conversations</span><div data-mate-session-list></div></div></details>';
|
|
90
|
+
actions.prepend(tools);
|
|
91
|
+
var notice = document.createElement('div'); notice.dataset.conversationNotice = ''; notice.hidden = true;
|
|
92
|
+
notice.innerHTML = '<span role="status"></span><button type="button">Check request</button>';
|
|
93
|
+
surface.insertBefore(notice, surface.querySelector('.contextual-clay-body'));
|
|
94
|
+
tools.querySelector('[data-mate-new]').onclick = function () { send('new'); };
|
|
95
|
+
tools.querySelector('details').addEventListener('toggle', function () { this.querySelector('summary').setAttribute('aria-expanded', String(this.open)); if (this.open) send('list'); });
|
|
96
|
+
surface.addEventListener('pointerdown', function (event) { var menu = tools.querySelector('details'); if (menu.open && !menu.contains(event.target)) menu.open = false; });
|
|
97
|
+
|
|
98
|
+
notice.querySelector('button').onclick = function () { var value = requestState('action'); if (value) send(value.kind, value.item, true); };
|
|
99
|
+
tools.addEventListener('keydown', function (event) {
|
|
100
|
+
if (event.key === 'Tab') {
|
|
101
|
+
var menu = tools.querySelector('details'), items = Array.from(tools.querySelectorAll('[data-mate-session-list] button:not(:disabled)'));
|
|
102
|
+
if (menu.open && (event.shiftKey && event.target === menu.querySelector('summary') || !event.shiftKey && event.target === items[items.length - 1])) queueMicrotask(function () { menu.open = false; });
|
|
103
|
+
return;
|
|
104
|
+
}
|
|
105
|
+
if (!/^Arrow(Down|Up)$/.test(event.key)) return;
|
|
106
|
+
var buttons = Array.from(tools.querySelectorAll('[data-mate-session-list] button:not(:disabled)'));
|
|
107
|
+
if (!buttons.length) return;
|
|
108
|
+
var index = buttons.indexOf(document.activeElement);
|
|
109
|
+
buttons[index < 0 ? (event.key === 'ArrowDown' ? 0 : buttons.length - 1) : (index + (event.key === 'ArrowDown' ? 1 : buttons.length - 1)) % buttons.length].focus(); event.preventDefault();
|
|
110
|
+
});
|
|
111
|
+
refreshIcons(); render();
|
|
112
|
+
}
|
|
113
|
+
export function handleContextualConversations(msg) {
|
|
114
|
+
if (msg.type !== 'contextual_mate_sessions_result') return false;
|
|
115
|
+
var kind = requestState('list') && requestState('list').requestId === msg.requestId ? 'list' : 'action';
|
|
116
|
+
var request = requestState(kind);
|
|
117
|
+
if (!request || request.status !== 'loading' || request.requestId !== msg.requestId || request.socket !== getWs() || !valid(request) || msg.mateId !== request.mateId || msg.mateStamp !== request.stamp) return true;
|
|
118
|
+
if (!msg.ok) { save(kind, Object.assign({}, request, { status: 'error', error: msg.error || 'Conversation unavailable.' })); return true; }
|
|
119
|
+
if (kind === 'list') { save(kind, Object.assign({}, request, { status: 'done', sessions: msg.sessions || [], truncated: msg.truncated })); return true; }
|
|
120
|
+
if (!Number.isSafeInteger(msg.sessionId) || msg.sessionId <= 0 || typeof msg.sessionOriginId !== 'string') return true;
|
|
121
|
+
if (request.selection !== selection() || (store.get('contextualClay') || {}).mode !== 'popover') { save(kind, Object.assign({}, request, { status: 'error', error: 'Your selection changed. The conversation remains in history.' })); return true; }
|
|
122
|
+
if (!guardDraft()) { save(kind, Object.assign({}, request, { status: 'error', error: 'Finish uploading or recording, then check this conversation again.' })); return true; }
|
|
123
|
+
pauseContextualSearchForSelection();
|
|
124
|
+
if (!selectContextualConversation(contextualMate(request.mateId), msg.sessionId, msg.sessionOriginId)) { save(kind, Object.assign({}, request, { status: 'error', error: 'This conversation could not be opened. Your draft is retained.' })); return true; }
|
|
125
|
+
surfaceClose(true); save(kind, Object.assign({}, request, { status: 'done' })); return true;
|
|
126
|
+
}
|
|
127
|
+
function surfaceClose(restoreFocus) { var surface = host(); if (surface) { var menu = surface.querySelector('[data-mate-history]'); var focused = menu.contains(document.activeElement); menu.open = false; if (focused || restoreFocus) menu.querySelector('summary').focus({ preventScroll: true }); } }
|
|
128
|
+
store.subscribe(function (value, previous) {
|
|
129
|
+
if (value.paneMode) return;
|
|
130
|
+
if (value.myUserId !== previous.myUserId) { store.set({ contextualConversationHistory: null, contextualConversationRequest: null }); return; }
|
|
131
|
+
if ((value.contextualClay || {}).mateId !== (previous.contextualClay || {}).mateId) surfaceClose();
|
|
132
|
+
if (previous.connected && !value.connected) ['list', 'action'].forEach(function (kind) { var request = requestState(kind); if (request && request.status === 'loading') save(kind, Object.assign({}, request, { status: 'error', error: 'Disconnected. Check again when connected; your conversation is retained.' })); });
|
|
133
|
+
render();
|
|
134
|
+
});
|
|
@@ -0,0 +1,137 @@
|
|
|
1
|
+
import { store } from './store.js';
|
|
2
|
+
import { getWs } from './ws-ref.js';
|
|
3
|
+
import { activateContextualMate } from './project-mate-navigation.js';
|
|
4
|
+
import { contextualMate, contextualMateStamp, contextualFrame } from './contextual-mate-identity.js';
|
|
5
|
+
import { showContextualAsk, enterComposer } from './contextual-clay.js';
|
|
6
|
+
import { showToast } from './utils.js';
|
|
7
|
+
|
|
8
|
+
function current() { return store.get('contextualSearchAsk'); }
|
|
9
|
+
function view() { return JSON.stringify([store.get('myUserId'), store.get('currentSlug'), store.get('activeSessionId'), store.get('homeShellVisible'), store.get('homeSubSurface'), store.get('dmMode'), store.get('rightWorkbenchOwner'), store.get('rightWorkbenchRevision')]); }
|
|
10
|
+
function patch(change) { store.set({ contextualSearchAsk: Object.assign({}, current(), change) }); }
|
|
11
|
+
function live(request) {
|
|
12
|
+
var mate = contextualMate(request.mateId);
|
|
13
|
+
return request.ownerId === store.get('myUserId') && mate && mate.builtinKey === 'clay' && contextualMateStamp(mate) === request.stamp;
|
|
14
|
+
}
|
|
15
|
+
function sendCreation() {
|
|
16
|
+
var request = current(), ws = getWs();
|
|
17
|
+
if (!request || !live(request)) { patch({ status: 'error', error: 'Clay is unavailable. Your question is retained.' }); return; }
|
|
18
|
+
if (!store.get('connected') || !ws || ws.readyState !== 1) { patch({ status: 'error', error: 'Reconnect, then retry. Your question is retained.' }); return; }
|
|
19
|
+
patch({ status: 'creating', socket: ws, view: view(), error: null });
|
|
20
|
+
try { ws.send(JSON.stringify({ type: 'home_clay_ask', presentation: 'contextual', requestId: request.requestId, text: request.text, sessionOriginId: request.sessionOriginId || null })); }
|
|
21
|
+
catch (error) { patch({ status: 'error', error: 'Creation is unconfirmed. Retry checks the same request.' }); }
|
|
22
|
+
setTimeout(function () { if (current() && current().requestId === request.requestId && current().status === 'creating') patch({ status: 'error', error: 'Conversation creation is unconfirmed. Retry checks the same request.' }); }, 15000);
|
|
23
|
+
}
|
|
24
|
+
export function pauseContextualSearchForSelection() {
|
|
25
|
+
if (current() && /^(creating|opening)$/.test(current().status)) stop();
|
|
26
|
+
}
|
|
27
|
+
function stop(execution) {
|
|
28
|
+
var request = current(), frame = request && request.sessionId && contextualFrame(request.mateId, request.sessionId);
|
|
29
|
+
if (frame && frame.conversation) { if (execution === true) frame.conversation.stopAsk(); else frame.conversation.pauseAsk(); }
|
|
30
|
+
patch({ status: 'stopped', error: request && request.clientMessageId ? 'Automatic delivery is paused. Inspect the conversation to confirm whether work stopped.' : 'Stopped before submission. Your question is retained; it will not be submitted automatically.' });
|
|
31
|
+
}
|
|
32
|
+
function resume() {
|
|
33
|
+
var request = current();
|
|
34
|
+
if (!request || !live(request)) return;
|
|
35
|
+
if (request.clientMessageId) { showToast('Inspect this conversation before retrying an uncertain message.', 'warn'); return; }
|
|
36
|
+
showContextualAsk(contextualMate(request.mateId), request.requestId, request.sessionId);
|
|
37
|
+
sendCreation();
|
|
38
|
+
}
|
|
39
|
+
function submit() {
|
|
40
|
+
var request = current();
|
|
41
|
+
if (!request || request.status !== 'opening') return;
|
|
42
|
+
if (!live(request) || request.view !== view()) { patch({ status: 'error', error: 'The view changed. Retry explicitly from the current view.' }); return; }
|
|
43
|
+
var frame = contextualFrame(request.mateId, request.sessionId);
|
|
44
|
+
if (!frame || frame.hidden || !frame.conversation || !frame.conversation.identity().ready) return;
|
|
45
|
+
var identity = frame.conversation.identity();
|
|
46
|
+
if (identity.ownerId !== request.ownerId || identity.sessionId !== request.sessionId || identity.sessionOriginId !== request.sessionOriginId || identity.mateId !== request.mateId) { patch({ status: 'error', error: 'The exact conversation identity changed. Nothing was submitted.' }); return; }
|
|
47
|
+
patch({ status: 'sending' });
|
|
48
|
+
var receipt = frame.conversation.submitAsk({ requestId: request.requestId, text: request.text, ownerId: request.ownerId, sessionId: request.sessionId, sessionOriginId: request.sessionOriginId });
|
|
49
|
+
if (!receipt || !receipt.clientMessageId) { patch({ status: 'error', error: 'Submission is unconfirmed. Inspect the retained question before retrying.' }); return; }
|
|
50
|
+
patch({ status: 'sent', clientMessageId: receipt.clientMessageId });
|
|
51
|
+
}
|
|
52
|
+
function render() {
|
|
53
|
+
var host = document.getElementById('contextual-clay');
|
|
54
|
+
if (!host) return;
|
|
55
|
+
var status = host.querySelector('[data-contextual-ask-status]');
|
|
56
|
+
if (!status) {
|
|
57
|
+
status = document.createElement('section'); status.dataset.contextualAskStatus = ''; status.setAttribute('role', 'region'); status.setAttribute('aria-label', 'Pending question');
|
|
58
|
+
status.innerHTML = '<div class="contextual-pending-question"><span>Pending question</span><blockquote data-ask-question></blockquote></div><div class="contextual-pending-progress"><p role="status" aria-live="polite" aria-atomic="true"></p><div><button type="button" data-ask-retry>Retry</button><button type="button" data-ask-stop>Stop</button><button type="button" data-ask-inspect>Open conversation</button></div></div>';
|
|
59
|
+
host.querySelector('.contextual-clay-body').appendChild(status);
|
|
60
|
+
status.querySelector('[data-ask-inspect]').addEventListener('click', function () { var request = current(); if (request && live(request)) activateContextualMate(request.mateId); });
|
|
61
|
+
status.querySelector('[data-ask-retry]').addEventListener('click', resume);
|
|
62
|
+
status.querySelector('[data-ask-stop]').addEventListener('click', function () { stop(true); });
|
|
63
|
+
host.addEventListener('contextual-clay-ready', submit);
|
|
64
|
+
host.addEventListener('contextual-clay-availability', function () {
|
|
65
|
+
var request = current(), frame = request && contextualFrame(request.mateId, request.sessionId);
|
|
66
|
+
if (request && request.status === 'opening' && frame && frame.conversation && frame.conversation.identity().available === false) patch({ status: 'error', error: 'This new conversation is unavailable. Your question is retained.' });
|
|
67
|
+
});
|
|
68
|
+
host.addEventListener('contextual-context-submitted', function (event) {
|
|
69
|
+
var request = current(), frame = request && contextualFrame(request.mateId, request.sessionId);
|
|
70
|
+
if (request && frame && frame.contentWindow === event.detail.source && request.clientMessageId && request.clientMessageId === event.detail.message.clientMessageId) patch({ status: 'acknowledged', acknowledged: true });
|
|
71
|
+
});
|
|
72
|
+
host.addEventListener('contextual-ask-stopped', function (event) { var request = current(), frame = request && contextualFrame(request.mateId, request.sessionId); if (frame && frame.contentWindow === event.detail.source) stop(); });
|
|
73
|
+
}
|
|
74
|
+
var focused = document.activeElement, ownedFocus = status.contains(focused);
|
|
75
|
+
var request = current(), selected = store.get('contextualClay') || {};
|
|
76
|
+
status.hidden = !request || selected.mateId !== request.mateId || request.acknowledged || request.status === 'acknowledged' || selected.sessionId && selected.sessionId !== request.sessionId;
|
|
77
|
+
if (request) {
|
|
78
|
+
status.querySelector('[data-ask-question]').textContent = request.text;
|
|
79
|
+
status.querySelector('p').textContent = request.error || (request.status === 'creating' ? 'Starting a new conversation. Your question is waiting.' : request.status === 'opening' ? 'Preparing this conversation. Nothing submitted yet.' : 'Waiting for confirmation. Delivery is not confirmed yet.');
|
|
80
|
+
status.querySelector('[data-ask-inspect]').hidden = !request.clientMessageId;
|
|
81
|
+
status.querySelector('[data-ask-retry]').hidden = request.status !== 'error' && request.status !== 'stopped' || !!request.clientMessageId;
|
|
82
|
+
status.querySelector('[data-ask-stop]').hidden = request.status === 'stopped';
|
|
83
|
+
}
|
|
84
|
+
host.dataset.askPending = String(!status.hidden);
|
|
85
|
+
var selectedFrame = contextualFrame();
|
|
86
|
+
host.querySelector('[data-clay-loading]').hidden = !status.hidden || !!(selectedFrame && selectedFrame.conversation && selectedFrame.conversation.identity().ready);
|
|
87
|
+
host.querySelectorAll('iframe').forEach(function (frame) { frame.inert = !status.hidden && frame.dataset.mateId === request.mateId && String(frame.dataset.sessionId) === String(request.sessionId); });
|
|
88
|
+
if (status.hidden) {
|
|
89
|
+
enterComposer();
|
|
90
|
+
if (ownedFocus && selectedFrame && selectedFrame.conversation && selectedFrame.conversation.identity().ready) selectedFrame.contentDocument.getElementById('input').focus({ preventScroll: true });
|
|
91
|
+
} else if (ownedFocus && focused.hidden) {
|
|
92
|
+
var nextControl = status.querySelector('[data-ask-retry]:not([hidden]), [data-ask-inspect]:not([hidden]), [data-ask-stop]:not([hidden])');
|
|
93
|
+
if (nextControl) nextControl.focus({ preventScroll: true });
|
|
94
|
+
}
|
|
95
|
+
|
|
96
|
+
}
|
|
97
|
+
|
|
98
|
+
export function startContextualSearch(text) {
|
|
99
|
+
text = typeof text === 'string' ? text.trim().slice(0, 12000) : '';
|
|
100
|
+
var mate = (store.get('cachedMatesList') || []).find(function (item) { return item.builtinKey === 'clay' && contextualMate(item.id); });
|
|
101
|
+
if (!text || !mate) { showToast('Clay is unavailable. Your question remains in Search.', 'warn'); return false; }
|
|
102
|
+
var request = current();
|
|
103
|
+
if (request && /^(creating|opening|sending|sent)$/.test(request.status)) { showToast('Clay is still starting the previous question. This question remains in Search.', 'warn'); return false; }
|
|
104
|
+
var requestId = 'contextual-search-' + crypto.randomUUID();
|
|
105
|
+
if (!showContextualAsk(mate, requestId, null)) return false;
|
|
106
|
+
store.set({ contextualSearchAsk: { requestId: requestId, text: text, mateId: mate.id, ownerId: store.get('myUserId'), stamp: contextualMateStamp(mate), status: 'creating', view: view() } });
|
|
107
|
+
render(); sendCreation(); return true;
|
|
108
|
+
}
|
|
109
|
+
export function retryContextualSearch() {
|
|
110
|
+
var request = current();
|
|
111
|
+
if (!request || !live(request) || request.clientMessageId || !/^(error|stopped)$/.test(request.status)) return false;
|
|
112
|
+
resume(); return true;
|
|
113
|
+
}
|
|
114
|
+
export function handleContextualSearchMessage(msg) {
|
|
115
|
+
var request = current();
|
|
116
|
+
if (!request || request.requestId !== msg.requestId) return false;
|
|
117
|
+
if (msg.type === 'home_mate_error') { patch({ status: 'error', error: msg.text || 'The conversation could not be started. Your question is retained.' }); return true; }
|
|
118
|
+
if (msg.type !== 'home_clay_contextual_session') return false;
|
|
119
|
+
if (request.status !== 'creating' || request.socket !== getWs() || !live(request) || request.mateId !== msg.mateId || !Number.isSafeInteger(msg.sessionId) || msg.sessionId <= 0 || typeof msg.sessionOriginId !== 'string' || request.sessionOriginId && request.sessionOriginId !== msg.sessionOriginId) return true;
|
|
120
|
+
if (request.view !== view()) { patch({ sessionId: msg.sessionId, sessionOriginId: msg.sessionOriginId, status: 'error', error: 'The view changed. Retry explicitly from the current view.' }); return true; }
|
|
121
|
+
patch({ sessionId: msg.sessionId, sessionOriginId: msg.sessionOriginId, status: 'opening' });
|
|
122
|
+
showContextualAsk(contextualMate(request.mateId), request.requestId, msg.sessionId);
|
|
123
|
+
var frame = contextualFrame(request.mateId, msg.sessionId);
|
|
124
|
+
if (frame) frame.dataset.contextualTitle = request.text.slice(0, 80);
|
|
125
|
+
setTimeout(function () { if (current() && current().requestId === request.requestId && current().status === 'opening') patch({ status: 'error', error: 'The conversation is not ready. Retry checks this same conversation.' }); }, 15000);
|
|
126
|
+
submit(); return true;
|
|
127
|
+
}
|
|
128
|
+
store.subscribe(function (value, previous) {
|
|
129
|
+
if (current() && current().ownerId !== value.myUserId) { store.set({ contextualSearchAsk: null }); return; }
|
|
130
|
+
if (current() && !live(current()) && /^(creating|opening)$/.test(current().status)) patch({ status: 'error', error: 'Clay is no longer available. Your question is retained.' });
|
|
131
|
+
if (current() && previous.connected && !value.connected && /^(creating|opening)$/.test(current().status)) patch({ status: 'error', error: 'Disconnected. Retry checks the same new conversation; your question is retained.' });
|
|
132
|
+
render();
|
|
133
|
+
});
|
|
134
|
+
document.addEventListener('click', function (event) {
|
|
135
|
+
var request = current();
|
|
136
|
+
if (request && store.get('currentSlug') === 'mate-' + request.mateId && store.get('activeSessionId') === request.sessionId && event.target.closest('#generation-stop, #autonomous-run-stop, #send-btn.stop')) stop();
|
|
137
|
+
}, true);
|
|
@@ -0,0 +1,58 @@
|
|
|
1
|
+
// Human citation clicks leave the pinned pane intact and use the parent viewer's
|
|
2
|
+
// existing authenticated reference resolver, never a project label as a target.
|
|
3
|
+
import { store } from './store.js';
|
|
4
|
+
import { getWs } from './ws-ref.js';
|
|
5
|
+
import { contextualFrame, contextualMate, contextualMateStamp } from './contextual-mate-identity.js';
|
|
6
|
+
import { parseClaySessionReference } from './clay-log-links.js';
|
|
7
|
+
import { requestClayRecordLink } from './command-palette.js';
|
|
8
|
+
|
|
9
|
+
function capture() {
|
|
10
|
+
var frame = contextualFrame(), state = store.get('contextualClay') || {}, mate = contextualMate(state.mateId);
|
|
11
|
+
var identity = frame && frame.conversation && frame.conversation.identity();
|
|
12
|
+
if (!mate || state.mode !== 'popover' || !frame || frame.hidden || frame.inert || !identity || !identity.ready || frame.conversation.source !== frame.contentWindow || identity.ownerId !== store.get('myUserId') || identity.mateId !== mate.id || frame.dataset.identityStamp !== contextualMateStamp(mate)) return null;
|
|
13
|
+
var surface = document.getElementById('contextual-clay');
|
|
14
|
+
return { mateId: mate.id, stamp: contextualMateStamp(mate), sessionId: identity.sessionId, originId: identity.sessionOriginId, ownerId: identity.ownerId, view: surface.dataset.screenReference, socket: getWs() };
|
|
15
|
+
}
|
|
16
|
+
export function validContextualCitation(context) {
|
|
17
|
+
var live = capture();
|
|
18
|
+
return !!(context && live && live.socket === context.socket && live.mateId === context.mateId && live.stamp === context.stamp && live.sessionId === context.sessionId && live.originId === context.originId && live.ownerId === context.ownerId && live.view === context.view);
|
|
19
|
+
}
|
|
20
|
+
export function contextualCitationLink(context, requestId) {
|
|
21
|
+
var frames = Array.from(document.querySelectorAll('#contextual-clay iframe'));
|
|
22
|
+
for (var frame of frames) {
|
|
23
|
+
var mate = contextualMate(frame.dataset.mateId), identity = frame.conversation && frame.conversation.identity();
|
|
24
|
+
if (!mate || !identity || identity.ownerId !== store.get('myUserId') || frame.dataset.identityStamp !== contextualMateStamp(mate)) continue;
|
|
25
|
+
if (context && (identity.mateId !== context.mateId || identity.sessionId !== context.sessionId || identity.sessionOriginId !== context.originId || context.ownerId !== identity.ownerId)) continue;
|
|
26
|
+
var link = Array.from(frame.contentDocument.querySelectorAll('.clayos-session-link')).find(function (item) { return item.dataset.sessionRequest === requestId; });
|
|
27
|
+
if (link) return link;
|
|
28
|
+
}
|
|
29
|
+
return null;
|
|
30
|
+
}
|
|
31
|
+
export function attachContextualSessionCitations(surface) {
|
|
32
|
+
surface.resolveSessionCitation = function (source, link) {
|
|
33
|
+
var context = capture(), frame = contextualFrame();
|
|
34
|
+
if (!context || !frame || frame.contentWindow !== source || !link || link.ownerDocument !== frame.contentDocument || !link.closest('.msg-assistant') || !parseClaySessionReference(link.dataset.sessionRef || '')) return false;
|
|
35
|
+
context.ref = link.dataset.sessionRef;
|
|
36
|
+
return requestClayRecordLink(link, context);
|
|
37
|
+
};
|
|
38
|
+
}
|
|
39
|
+
export function forwardContextualSessionCitation(link) {
|
|
40
|
+
if (!store.get('paneMode') || new URLSearchParams(location.search).get('contextual') !== '1') return false;
|
|
41
|
+
try {
|
|
42
|
+
var surface = window.parent.document.getElementById('contextual-clay');
|
|
43
|
+
if (surface && surface.resolveSessionCitation && surface.resolveSessionCitation(window, link)) return true;
|
|
44
|
+
} catch (error) { /* A changed authentication document cannot receive clicks. */ }
|
|
45
|
+
if (link.classList.contains('is-error')) return true;
|
|
46
|
+
link.classList.add('is-error'); link.title = 'This conversation or view changed. Reopen it before navigating.';
|
|
47
|
+
return true;
|
|
48
|
+
}
|
|
49
|
+
// Project transport replacement may discard an old reply before the palette
|
|
50
|
+
// sees it. Retire that pending UI receipt at the context change itself.
|
|
51
|
+
store.subscribe(function (value) {
|
|
52
|
+
var pending = value.sessionNavigationRequestContext;
|
|
53
|
+
if (value.paneMode || !pending || !pending.citation) return;
|
|
54
|
+
if (pending.projectSlug === value.currentSlug && pending.sessionId === value.activeSessionId && validContextualCitation(pending.citation)) return;
|
|
55
|
+
var link = contextualCitationLink(pending.citation, value.sessionNavigationRequestId);
|
|
56
|
+
if (link) { link.classList.remove('is-loading'); link.classList.add('is-error'); link.title = 'The view changed. Click again from the current conversation.'; delete link.dataset.sessionRequest; }
|
|
57
|
+
store.set({ sessionNavigationRequestId: null, sessionNavigationRequestContext: null });
|
|
58
|
+
});
|
|
@@ -58,6 +58,7 @@ function buildAvatarUrl(meta) {
|
|
|
58
58
|
return mateAvatarUrl({
|
|
59
59
|
id: meta.mateId,
|
|
60
60
|
profile: {
|
|
61
|
+
avatarCatalogId: meta.avatarCatalogId || "",
|
|
61
62
|
avatarStyle: meta.avatarStyle || "imprint",
|
|
62
63
|
avatarSeed: meta.avatarSeed || meta.mateId || "mate",
|
|
63
64
|
avatarColor: meta.avatarColor || "#5857fc",
|
|
@@ -110,6 +110,13 @@ function inlineCurrentSelection(state, draft) {
|
|
|
110
110
|
return state.preference || state.selection || draft || {};
|
|
111
111
|
}
|
|
112
112
|
|
|
113
|
+
function updateDraft(draft) {
|
|
114
|
+
var state = store.get('defaultAiState') || {};
|
|
115
|
+
var saved = state.preference || state.selection || {};
|
|
116
|
+
var dirty = ['vendor', 'model', 'effort'].some(function (key) {return (draft[key] || '') !== (saved[key] || '');});
|
|
117
|
+
store.set({defaultAiDraft:draft, defaultAiDraftDirty:dirty});
|
|
118
|
+
}
|
|
119
|
+
|
|
113
120
|
function renderInlineSummary() {
|
|
114
121
|
var state = store.get("defaultAiState") || {};
|
|
115
122
|
var draft = store.get("defaultAiDraft") || {};
|
|
@@ -209,16 +216,16 @@ function render() {
|
|
|
209
216
|
effort.disabled = !models.length || state.saving === true;
|
|
210
217
|
|
|
211
218
|
vendor.addEventListener("change", function () {
|
|
212
|
-
|
|
219
|
+
updateDraft({ vendor: vendor.value, model: "", effort: "" });
|
|
213
220
|
requestCatalog(vendor.value);
|
|
214
221
|
render();
|
|
215
222
|
});
|
|
216
223
|
model.addEventListener("change", function () {
|
|
217
|
-
|
|
224
|
+
updateDraft({ vendor: vendor.value, model: model.value, effort: "" });
|
|
218
225
|
render();
|
|
219
226
|
});
|
|
220
227
|
effort.addEventListener("change", function () {
|
|
221
|
-
|
|
228
|
+
updateDraft({ vendor: vendor.value, model: model.value, effort: effort.value });
|
|
222
229
|
render();
|
|
223
230
|
});
|
|
224
231
|
addFieldLabel("Provider", vendor);
|
|
@@ -304,6 +311,7 @@ function applyCatalogMessage(msg, state) {
|
|
|
304
311
|
draft = Object.assign({}, draft, { model: msg.selection.model, effort: msg.selection.effort || "" });
|
|
305
312
|
}
|
|
306
313
|
store.set({ defaultAiState: next, defaultAiDraft: draft });
|
|
314
|
+
updateDraft(draft);
|
|
307
315
|
}
|
|
308
316
|
|
|
309
317
|
function applyStateMessage(msg, state) {
|
|
@@ -4,6 +4,8 @@
|
|
|
4
4
|
import { escapeHtml } from './utils.js';
|
|
5
5
|
import { iconHtml } from './icons.js';
|
|
6
6
|
import { getWs } from './ws-ref.js';
|
|
7
|
+
import { store } from './store.js';
|
|
8
|
+
import { currentPaneReview } from './pane-binding.js';
|
|
7
9
|
import { fieldInfo, patternIsBounded, validateForm } from './elicitation-schema.js';
|
|
8
10
|
|
|
9
11
|
var UNSET = "__clay_unset__";
|
|
@@ -154,12 +156,14 @@ function showFormError(container, message) {
|
|
|
154
156
|
}
|
|
155
157
|
|
|
156
158
|
function send(container, action, content, onSent) {
|
|
159
|
+
if (!currentPaneReview(container)) return false;
|
|
157
160
|
var ws = getWs();
|
|
158
161
|
if (!ws || ws.readyState !== 1) {
|
|
159
162
|
showFormError(container, "Not connected. Try again when the connection is restored.");
|
|
160
163
|
return false;
|
|
161
164
|
}
|
|
162
165
|
var msg = { type: "elicitation_response", requestId: container.dataset.requestId, action: action };
|
|
166
|
+
if (container.paneBinding) msg.paneBinding = container.paneBinding;
|
|
163
167
|
if (action === "accept") msg.content = content;
|
|
164
168
|
ws.send(JSON.stringify(msg));
|
|
165
169
|
setBusy(container, true);
|
|
@@ -177,6 +181,7 @@ function actionButton(label, className, handler) {
|
|
|
177
181
|
|
|
178
182
|
export function buildElicitationCard(msg, onSent) {
|
|
179
183
|
var container = el("div", "permission-container elicitation-container");
|
|
184
|
+
container.paneBinding = store.get('panePendingBinding') || store.get('paneCommittedBinding') || null;
|
|
180
185
|
container.dataset.requestId = msg.requestId;
|
|
181
186
|
var header = el("div", "permission-header");
|
|
182
187
|
header.innerHTML = '<span class="permission-icon">' + iconHtml("key") + '</span>' +
|
|
@@ -1,3 +1,5 @@
|
|
|
1
|
+
import { presentedDocument, refreshPresentedDocument, closePresentedDocument } from './clay-studio-document.js';
|
|
2
|
+
import { registerStudioPaint } from './clay-studio-render.js';
|
|
1
3
|
import { iconHtml, refreshIcons } from './icons.js';
|
|
2
4
|
import { escapeHtml, copyToClipboard } from './utils.js';
|
|
3
5
|
import { renderMarkdown, highlightCodeBlocks, renderMermaidBlocks, exportMarkdownAsPdf } from './markdown.js';
|
|
@@ -192,6 +194,9 @@ export function initFileBrowser(_ctx) {
|
|
|
192
194
|
|
|
193
195
|
document.getElementById("file-viewer-download").addEventListener("click", function () {
|
|
194
196
|
if (!currentFilePath) return;
|
|
197
|
+
if ((store.get("studioDocumentView") || {}).descriptor && store.get("studioDocumentView").descriptor.path === currentFilePath) {
|
|
198
|
+
var link = document.createElement('a'); link.href = URL.createObjectURL(new Blob([currentContent || ''], { type: 'text/markdown;charset=utf-8' })); link.download = currentFilePath.split('/').pop(); link.click(); setTimeout(function () { URL.revokeObjectURL(link.href); }, 1000); return;
|
|
199
|
+
}
|
|
195
200
|
downloadProjectFile(currentFilePath);
|
|
196
201
|
});
|
|
197
202
|
|
|
@@ -459,12 +464,14 @@ function handleTreeKeyDown(e) {
|
|
|
459
464
|
|
|
460
465
|
// --- File watch helpers ---
|
|
461
466
|
function sendWatch(filePath) {
|
|
467
|
+
if ((store.get("studioDocumentView") || {}).descriptor && store.get("studioDocumentView").descriptor.path === filePath) return;
|
|
462
468
|
if (ctx.ws && ctx.connected) {
|
|
463
469
|
ctx.ws.send(JSON.stringify({ type: "fs_watch", path: filePath }));
|
|
464
470
|
}
|
|
465
471
|
}
|
|
466
472
|
|
|
467
473
|
function sendUnwatch() {
|
|
474
|
+
if (store.get("studioDocumentView")) { closePresentedDocument(); return; }
|
|
468
475
|
if (ctx.ws && ctx.connected) {
|
|
469
476
|
ctx.ws.send(JSON.stringify({ type: "fs_unwatch" }));
|
|
470
477
|
}
|
|
@@ -532,6 +539,7 @@ export function resetFileBrowser() {
|
|
|
532
539
|
treeData = {};
|
|
533
540
|
currentContent = null;
|
|
534
541
|
currentFilePath = null;
|
|
542
|
+
store.set({ clayControlFileView: null });
|
|
535
543
|
isRendered = false;
|
|
536
544
|
currentIsMarkdown = false;
|
|
537
545
|
currentIsSvg = false;
|
|
@@ -568,6 +576,7 @@ export function openFile(filePath, opts) {
|
|
|
568
576
|
if (!state.connected) return false;
|
|
569
577
|
if (opts && opts.projectSlug && opts.projectSlug !== state.currentSlug) return false;
|
|
570
578
|
if (opts && opts.sessionId && String(opts.sessionId) !== String(state.activeSessionId)) return false;
|
|
579
|
+
closePresentedDocument();
|
|
571
580
|
var workbenchRevision = claimRightWorkbench("file-viewer");
|
|
572
581
|
if (followedFileChanged(filePath) || (opts && opts.diff && isFollowingMarkdown(filePath))) {
|
|
573
582
|
cancelMarkdownFollow();
|
|
@@ -635,6 +644,7 @@ export function presentMarkdownEdit(msg) {
|
|
|
635
644
|
content: typeof msg.content === "string" ? msg.content : "",
|
|
636
645
|
size: msg.size || 0,
|
|
637
646
|
});
|
|
647
|
+
registerStudioPaint(msg, document.querySelector("#file-viewer .file-viewer-header"), null, document.getElementById("file-viewer-body"));
|
|
638
648
|
}
|
|
639
649
|
|
|
640
650
|
function followedFileChanged(filePath) {
|
|
@@ -723,6 +733,7 @@ function requestDirectory(dirPath) {
|
|
|
723
733
|
}
|
|
724
734
|
|
|
725
735
|
function requestFileContent(filePath) {
|
|
736
|
+
if (refreshPresentedDocument(filePath)) return;
|
|
726
737
|
var requestId = "file-read-" + Date.now() + "-" + Math.random().toString(36).slice(2);
|
|
727
738
|
var state = store.snap();
|
|
728
739
|
store.set({ fileReadRequest: { requestId: requestId, path: filePath, projectSlug: state.currentSlug || null, sessionId: state.activeSessionId != null ? String(state.activeSessionId) : null, accountId: state.myUserId || null, workbenchRevision: store.get('rightWorkbenchRevision') || 0 } });
|
|
@@ -1148,6 +1159,7 @@ function renderEntries(container, entries, depth) {
|
|
|
1148
1159
|
// --- File viewer ---
|
|
1149
1160
|
|
|
1150
1161
|
function showFileContent(msg, expectedRevision) {
|
|
1162
|
+
var priorTarget = document.querySelector("#file-viewer .file-viewer-header"); if (priorTarget) delete priorTarget.dataset.controlSurface;
|
|
1151
1163
|
if (!updateFileViewerTab(msg.path, { content: msg.content })) return;
|
|
1152
1164
|
if (expectedRevision != null && !isRightWorkbenchCurrent("file-viewer", expectedRevision)) return;
|
|
1153
1165
|
var pathEl = document.getElementById("file-viewer-path");
|
|
@@ -1170,6 +1182,8 @@ function showFileContent(msg, expectedRevision) {
|
|
|
1170
1182
|
pendingRefresh = false;
|
|
1171
1183
|
currentContent = null;
|
|
1172
1184
|
currentFilePath = msg.path;
|
|
1185
|
+
var sourceView = store.get('studioDocumentView'), sourceDescriptor = sourceView && sourceView.descriptor.path === msg.path ? sourceView.descriptor : null;
|
|
1186
|
+
store.set({ clayControlFileView: { path: msg.path, revision: msg.controlRevision || null, projectSlug: sourceDescriptor ? sourceDescriptor.sourceSlug : store.get('currentSlug'), runtimeId: sourceDescriptor ? sourceDescriptor.runtimeId : store.get('controlRuntimeId') } });
|
|
1173
1187
|
currentIsMarkdown = false;
|
|
1174
1188
|
currentIsSvg = false;
|
|
1175
1189
|
store.set({ fileViewerIsPlantUml: false, fileViewerIsHtml: false });
|
|
@@ -1279,6 +1293,8 @@ function showFileContent(msg, expectedRevision) {
|
|
|
1279
1293
|
store.set({ pendingFileNavigation: null });
|
|
1280
1294
|
}
|
|
1281
1295
|
|
|
1296
|
+
var sourceView = presentedDocument(msg.path);
|
|
1297
|
+
if (sourceView) Array.from(bodyEl.querySelectorAll('.clay-file-link')).forEach(function (link) { link.dataset.fileProjectSlug = sourceView.descriptor.sourceSlug; link.dataset.fileSessionId = String(sourceView.descriptor.sourceSessionId); });
|
|
1282
1298
|
// Request edit history for this file (skip on auto-refresh)
|
|
1283
1299
|
if (!keepRenderState) {
|
|
1284
1300
|
historyVisible = false;
|
|
@@ -1361,7 +1377,9 @@ function pathsReferToSameFile(left, right) {
|
|
|
1361
1377
|
return a === b || a.endsWith("/" + b) || b.endsWith("/" + a);
|
|
1362
1378
|
}
|
|
1363
1379
|
|
|
1364
|
-
export function handleFileChanged(msg) {
|
|
1380
|
+
export function handleFileChanged(msg, presentedSource) {
|
|
1381
|
+
var source = store.get('studioDocumentView');
|
|
1382
|
+
if (source && source.descriptor.path === msg.path && (!presentedSource || presentedDocument(msg.path) !== presentedSource)) return;
|
|
1365
1383
|
if (!msg.path || !pathsReferToSameFile(msg.path, currentFilePath)) return;
|
|
1366
1384
|
if (ctx.fileViewerEl.classList.contains("hidden")) return;
|
|
1367
1385
|
if (historyVisible || inlineDiffActive) return;
|
|
@@ -1602,6 +1620,7 @@ function formatSize(bytes) {
|
|
|
1602
1620
|
// --- File edit history ---
|
|
1603
1621
|
|
|
1604
1622
|
function requestFileHistory(filePath) {
|
|
1623
|
+
if ((store.get("studioDocumentView") || {}).descriptor && store.get("studioDocumentView").descriptor.path === filePath) return;
|
|
1605
1624
|
if (ctx.ws && ctx.connected) {
|
|
1606
1625
|
ctx.ws.send(JSON.stringify({ type: "fs_file_history", path: filePath }));
|
|
1607
1626
|
}
|
|
@@ -2,6 +2,13 @@ import { store } from './store.js';
|
|
|
2
2
|
import { getWs } from './ws-ref.js';
|
|
3
3
|
import { isDriverOperatedView } from './worker-pane-lock.js';
|
|
4
4
|
|
|
5
|
+
export function stopGeneration() {
|
|
6
|
+
var ws = getWs();
|
|
7
|
+
if (!store.get('processing') || !store.get('connected') || !ws || ws.readyState !== 1) return false;
|
|
8
|
+
ws.send(JSON.stringify({ type: 'stop' }));
|
|
9
|
+
return true;
|
|
10
|
+
}
|
|
11
|
+
|
|
5
12
|
// Fallback Stop control for when Send cannot double as Stop: a draft sitting
|
|
6
13
|
// in the composer (Send stays Send so the draft can still go out), or a
|
|
7
14
|
// locked configured Worker pane (Send and the rest of the composer are
|
|
@@ -31,11 +38,7 @@ export function initGenerationStop() {
|
|
|
31
38
|
button.title = store.get('connected') ? 'Stop generating' : 'Reconnect to stop generating';
|
|
32
39
|
place();
|
|
33
40
|
}
|
|
34
|
-
button.addEventListener('click',
|
|
35
|
-
var ws = getWs();
|
|
36
|
-
if (!store.get('processing') || !store.get('connected') || !ws || ws.readyState !== 1) return;
|
|
37
|
-
ws.send(JSON.stringify({ type: 'stop' }));
|
|
38
|
-
});
|
|
41
|
+
button.addEventListener('click', stopGeneration);
|
|
39
42
|
store.subscribe(function (state, previous) {
|
|
40
43
|
if (state.processing !== previous.processing || state.connected !== previous.connected
|
|
41
44
|
|| state.splitGroups !== previous.splitGroups || state.activeSessionId !== previous.activeSessionId
|