clay-server 5.2.0-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-socket.js +1 -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 +78 -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/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-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-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/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/index.html +11 -5
- 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/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 +115 -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/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 +3 -0
- 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/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-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.js +3 -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/muse-avatar.svg +4 -0
- package/lib/public/style.css +5 -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-admin.js +63 -16
- package/lib/server-appearance-settings.js +13 -1
- 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 +6 -1
- package/lib/server.js +163 -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/users-contextual-clay-preferences.js +31 -0
- package/lib/users-permissions.js +2 -8
- package/lib/users.js +7 -0
- 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 +10 -4
|
@@ -1,3 +1,6 @@
|
|
|
1
|
+
import { registerStudioPaint } from './clay-studio-render.js';
|
|
2
|
+
import { browserLinkTarget, initBrowserLinks } from './clay-browser-links.js';
|
|
3
|
+
import { browserSettingsHtml, bindBrowserSettings, renderBrowserSettings, closeBrowserSettings, handleBrowserSettingsMessage } from './shared-browser-settings.js';
|
|
1
4
|
import { renderBrowserTabs } from './shared-browser-tabs.js';
|
|
2
5
|
import { store } from './store.js';
|
|
3
6
|
import { getWs } from './ws-ref.js';
|
|
@@ -50,15 +53,15 @@ function ensurePanel() {
|
|
|
50
53
|
el.className = 'shared-browser-panel hidden';
|
|
51
54
|
el.setAttribute('aria-label', 'Shared browser');
|
|
52
55
|
el.innerHTML = '<header class="shared-browser-header"><span class="shared-browser-title">' + iconHtml('globe') + 'Browser</span><span class="shared-browser-phase" role="status">Ready</span><div class="shared-browser-window">' +
|
|
53
|
-
iconButton('wide', 'chevrons-left-right', 'Widen browser panel') + iconButton('fullscreen', 'maximize-2', 'Toggle browser fullscreen') + iconButton('hide', 'x', 'Hide browser panel') + '</div></header>' +
|
|
56
|
+
iconButton('settings', 'settings-2', 'Browser settings') + iconButton('wide', 'chevrons-left-right', 'Widen browser panel') + iconButton('fullscreen', 'maximize-2', 'Toggle browser fullscreen') + iconButton('hide', 'x', 'Hide browser panel') + '</div></header>' +
|
|
54
57
|
'<div class="shared-browser-tabs" role="tablist" aria-label="Browser tabs"></div><form class="shared-browser-address">' + iconButton('back', 'arrow-left', 'Back') + iconButton('forward', 'arrow-right', 'Forward') + iconButton('reload', 'rotate-cw', 'Reload') +
|
|
55
58
|
'<input aria-label="Browser address" placeholder="Enter a URL" type="text" autocomplete="off" spellcheck="false"><button type="submit" aria-label="Open address">' + iconHtml('arrow-right') + '</button></form>' +
|
|
56
|
-
'<div class="shared-browser-viewport"><div class="shared-browser-monitor"><div class="shared-browser-pointer-layer" aria-hidden="true"><div class="shared-browser-pointer" hidden><svg viewBox="0 0 24 28"><path d="M3 2 L3 22 L8 17 L12 26 L16 24 L12 15 L20 15 Z"/></svg><i></i></div></div><canvas width="1280" height="800" tabindex="0" aria-label="Shared browser page"></canvas>' +
|
|
57
|
-
'<div class="shared-browser-empty">' + iconHtml('globe') + '<h3>A browser you can
|
|
59
|
+
browserSettingsHtml() + '<div class="shared-browser-viewport"><div class="shared-browser-monitor"><div class="shared-browser-pointer-layer" aria-hidden="true"><div class="shared-browser-pointer" hidden><svg viewBox="0 0 24 28"><path d="M3 2 L3 22 L8 17 L12 26 L16 24 L12 15 L20 15 Z"/></svg><i></i></div></div><canvas width="1280" height="800" tabindex="0" aria-label="Shared browser page"></canvas>' +
|
|
60
|
+
'<div class="shared-browser-empty">' + iconHtml('globe') + '<h3>A browser you can use with Clay</h3><p>Enter an address to browse together.<br>Localhost connects to the Clay host.</p><p class="shared-browser-private">Site data lasts only for this browser session.</p></div>' +
|
|
58
61
|
'<textarea class="shared-browser-keyboard" aria-label="Type into shared browser" autocomplete="off" autocapitalize="off" spellcheck="false"></textarea><span class="shared-browser-monitor-brand" aria-hidden="true">Clay Studio</span><span class="shared-browser-monitor-detail" aria-hidden="true"></span><span class="shared-browser-monitor-stand" aria-hidden="true"></span></div><div class="shared-browser-caption"><span class="shared-browser-monitor-label"></span>' + activityHtml() + '</div></div>' +
|
|
59
62
|
'<p class="shared-browser-error hidden" role="status"></p>' +
|
|
60
63
|
'<footer class="shared-browser-footer"><div class="shared-browser-control"><span class="shared-browser-control-status" role="status" aria-live="polite">You and Clay can control this browser</span><button type="button" data-action="control" aria-pressed="false"></button></div>' +
|
|
61
|
-
'<div class="shared-browser-details">' + viewportMenuHtml() + '<button type="button" data-action="end">End browser</button></div></footer>';
|
|
64
|
+
'<div class="shared-browser-details"><span class="shared-browser-cookie-mode"></span>' + viewportMenuHtml() + '<button type="button" data-action="end">End browser</button></div></footer>';
|
|
62
65
|
root.appendChild(el);
|
|
63
66
|
el.querySelector('[data-action="hide"]').onclick = hideSharedBrowser;
|
|
64
67
|
el.querySelector('[data-action="wide"]').onclick = function () { var wide = !(store.get('sharedBrowserUi') || {}).wide; ui({ wide: wide }); render(); };
|
|
@@ -69,8 +72,9 @@ function ensurePanel() {
|
|
|
69
72
|
var browser = store.get('sharedBrowser');
|
|
70
73
|
if (browser) send('control', { control: browser.control === 'user' ? 'agent' : 'user' });
|
|
71
74
|
};
|
|
72
|
-
el.querySelector('[data-action="end"]').onclick = function () { var browser = store.get('sharedBrowser'); send(browser && browser.phase === 'ended' ? 'open' : 'end'); };
|
|
75
|
+
el.querySelector('[data-action="end"]').onclick = function () { var browser = store.get('sharedBrowser'); send(browser && browser.phase === 'ended' ? 'open' : 'end', browser && browser.phase === 'ended' ? { incognito: browser.incognito } : undefined); };
|
|
73
76
|
bindViewportMenu(el);
|
|
77
|
+
bindBrowserSettings(el);
|
|
74
78
|
var observer = new ResizeObserver(layoutMonitor);
|
|
75
79
|
observer.observe(el.querySelector('.shared-browser-viewport'));
|
|
76
80
|
bindBrowserInput(el.querySelector('canvas'), el.querySelector('textarea'));
|
|
@@ -141,11 +145,16 @@ function render() {
|
|
|
141
145
|
el.querySelector('[data-action="control"]').hidden = !live;
|
|
142
146
|
el.querySelector('[data-action="end"]').disabled = !browser || !connected;
|
|
143
147
|
el.querySelector('[data-action="end"]').textContent = browser && browser.phase === 'ended' ? 'New browser' : 'End browser';
|
|
148
|
+
var personal = browser && browser.incognito === false;
|
|
149
|
+
el.querySelector('.shared-browser-cookie-mode').textContent = personal ? 'Personal browser' : 'Incognito';
|
|
150
|
+
el.querySelector('.shared-browser-cookie-mode').title = personal ? 'Cookies and site storage are saved for your account across your Mates.' : 'Cookies and site storage are isolated and discarded when this tab ends.';
|
|
151
|
+
el.querySelector('.shared-browser-private').textContent = personal ? 'Your cookies and site storage are remembered across your Mates and browser restarts.' : 'Site data lasts only for this browser session.';
|
|
144
152
|
var error = state.error || (browser && browser.error) || '';
|
|
145
153
|
el.querySelector('.shared-browser-error').textContent = error;
|
|
146
154
|
el.querySelector('.shared-browser-error').classList.toggle('hidden', !error);
|
|
147
155
|
el.querySelector('.shared-browser-empty').classList.toggle('hidden', !!(browser && browser.url && state.hasFrame));
|
|
148
156
|
renderViewportMenu(el, browser, operable);
|
|
157
|
+
renderBrowserSettings();
|
|
149
158
|
renderBrowserActivity(el, browser, connected);
|
|
150
159
|
layoutMonitor();
|
|
151
160
|
}
|
|
@@ -163,6 +172,16 @@ function selectBrowserTab(id) {
|
|
|
163
172
|
setBrowserTab(browser);
|
|
164
173
|
send('view', { visible: desktop() && !document.hidden }); render();
|
|
165
174
|
}
|
|
175
|
+
export function openSharedBrowserAt(value) {
|
|
176
|
+
var url = browserLinkTarget('browser:' + value);
|
|
177
|
+
if (!url) throw new Error('Enter a valid HTTP or HTTPS browser address.');
|
|
178
|
+
if (!desktop()) throw new Error('Clay Browser is available on desktop screens.');
|
|
179
|
+
if (!eligible()) throw new Error('Browser access is unavailable in this conversation.');
|
|
180
|
+
if (!store.get('connected')) throw new Error('Reconnect before opening this browser link.');
|
|
181
|
+
ensurePanel(); closeBrowserSettings(false);
|
|
182
|
+
claimRightWorkbench('browser'); store.set({ sharedBrowserOpen: true });
|
|
183
|
+
ui({ error: '' }); send('open', { url: url }); render();
|
|
184
|
+
}
|
|
166
185
|
export function openSharedBrowser() {
|
|
167
186
|
if (!eligible() || !store.get('connected')) return;
|
|
168
187
|
ensurePanel();
|
|
@@ -175,6 +194,7 @@ export function openSharedBrowser() {
|
|
|
175
194
|
}
|
|
176
195
|
export function hideSharedBrowser() {
|
|
177
196
|
closeViewportMenu();
|
|
197
|
+
closeBrowserSettings();
|
|
178
198
|
clearBrowserInput();
|
|
179
199
|
if (store.get('sharedBrowserOpen')) send('view', { visible: false });
|
|
180
200
|
store.set({ sharedBrowserOpen: false });
|
|
@@ -184,6 +204,7 @@ export function hideSharedBrowser() {
|
|
|
184
204
|
export function handleSharedBrowserMessage(msg) {
|
|
185
205
|
if (!msg.type || msg.type.indexOf('shared_browser_') !== 0) return false;
|
|
186
206
|
if (String(msg.sessionId) !== String(store.get('activeSessionId'))) return true;
|
|
207
|
+
if (handleBrowserSettingsMessage(msg)) return true;
|
|
187
208
|
if (msg.type === 'shared_browser_state') {
|
|
188
209
|
var old = store.get('sharedBrowser');
|
|
189
210
|
var tabs = msg.browsers || (msg.browser ? [msg.browser] : []);
|
|
@@ -209,6 +230,7 @@ export function handleSharedBrowserMessage(msg) {
|
|
|
209
230
|
var canvas = panel().querySelector('canvas'); canvas.width = image.naturalWidth; canvas.height = image.naturalHeight;
|
|
210
231
|
canvas.getContext('2d').drawImage(image, 0, 0);
|
|
211
232
|
ui({ decoding: false, hasFrame: true }); render();
|
|
233
|
+
registerStudioPaint(msg, canvas, null, canvas);
|
|
212
234
|
}
|
|
213
235
|
};
|
|
214
236
|
image.onerror = function () { if (store.get('activeSessionId') === sessionId) ui({ decoding: false }); };
|
|
@@ -217,6 +239,7 @@ export function handleSharedBrowserMessage(msg) {
|
|
|
217
239
|
return true;
|
|
218
240
|
}
|
|
219
241
|
export function initSharedBrowser() {
|
|
242
|
+
initBrowserLinks();
|
|
220
243
|
var button = document.getElementById('shared-browser-btn');
|
|
221
244
|
if (button) button.onclick = openSharedBrowser;
|
|
222
245
|
var toggle = document.getElementById('shared-browser-toggle-btn');
|
|
@@ -233,7 +256,7 @@ registerRightWorkbench('browser', hideSharedBrowser);
|
|
|
233
256
|
store.subscribe(function (state, previous) {
|
|
234
257
|
if (state.currentSlug !== previous.currentSlug || state.activeSessionId !== previous.activeSessionId || state.myUserId !== previous.myUserId) {
|
|
235
258
|
clearBrowserInput(); releaseRightWorkbench('browser');
|
|
236
|
-
store.set({ sharedBrowser: null, sharedBrowsers: [], sharedBrowserOpen: false, sharedBrowserUi: {} });
|
|
259
|
+
store.set({ sharedBrowser: null, sharedBrowsers: [], sharedBrowserOpen: false, sharedBrowserUi: {}, sharedBrowserSettings: {} });
|
|
237
260
|
if (state.connected) send('state_request');
|
|
238
261
|
render();
|
|
239
262
|
} else if (state.connected !== previous.connected) {
|
|
@@ -1,4 +1,5 @@
|
|
|
1
|
-
import {
|
|
1
|
+
import { contextualMate } from './contextual-mate-identity.js';
|
|
2
|
+
import { activateContextualMate, isMateWorkspace } from './project-mate-navigation.js';
|
|
2
3
|
import { appendGithubWork } from './session-github.js';
|
|
3
4
|
// sidebar-mobile.js - Mobile sheet overlays, tab bar, and mobile-specific rendering
|
|
4
5
|
// Extracted from sidebar.js (PR-38)
|
|
@@ -258,7 +259,7 @@ function renderSheetSessions(listEl) {
|
|
|
258
259
|
}
|
|
259
260
|
|
|
260
261
|
var visibleChipMates = getCachedMates().filter(function (m) {
|
|
261
|
-
return m && !m.archived;
|
|
262
|
+
return m && !m.archived && contextualMate(m.id);
|
|
262
263
|
});
|
|
263
264
|
var sortedChipMates = visibleChipMates.sort(function (a, b) {
|
|
264
265
|
var aBuiltin = a.builtinKey ? 1 : 0;
|
|
@@ -327,7 +328,7 @@ function renderSheetSessions(listEl) {
|
|
|
327
328
|
renderMobileSessionsInto(sessionListEl);
|
|
328
329
|
} else if (type === "mate") {
|
|
329
330
|
closeMobileSheet();
|
|
330
|
-
|
|
331
|
+
activateContextualMate(mateId);
|
|
331
332
|
}
|
|
332
333
|
|
|
333
334
|
refreshIcons();
|
|
@@ -822,6 +822,7 @@ function createIconItem(p, currentSlug) {
|
|
|
822
822
|
var el = document.createElement("a");
|
|
823
823
|
var isActive = p.slug === currentSlug && !currentDmUserId;
|
|
824
824
|
el.className = "icon-strip-item" + (isActive ? " active" : "");
|
|
825
|
+
el.dataset.controlRuntime = p.controlRuntimeId || "";
|
|
825
826
|
el.href = "/p/" + p.slug + "/";
|
|
826
827
|
el.dataset.slug = p.slug;
|
|
827
828
|
|
|
@@ -353,7 +353,7 @@ function renderSection(section, ctx, kind) {
|
|
|
353
353
|
body.appendChild(empty);
|
|
354
354
|
}
|
|
355
355
|
var view = currentFolderState().view;
|
|
356
|
-
var dateGroups = isFavorites ? null : groupUnitsByDate(section.units, view.sort, view.direction);
|
|
356
|
+
var dateGroups = isFavorites || view.showDateHeadings === false ? null : groupUnitsByDate(section.units, view.sort, view.direction);
|
|
357
357
|
if (dateGroups) {
|
|
358
358
|
for (var g = 0; g < dateGroups.length; g++) {
|
|
359
359
|
var ids = groupRootSessionIds(dateGroups[g].units);
|
|
@@ -826,6 +826,7 @@ function renderSessionItem(s, options) {
|
|
|
826
826
|
el.className = "session-item" + (displaySession.active ? " active" : "") + (isMatch ? " search-match" : "");
|
|
827
827
|
if (itemOptions.worker) el.classList.add("session-worker-item");
|
|
828
828
|
el.dataset.sessionId = s.id;
|
|
829
|
+
el.dataset.controlSessionOrigin = s.sessionOriginId || '';
|
|
829
830
|
|
|
830
831
|
var textSpan = document.createElement("span");
|
|
831
832
|
textSpan.className = "session-item-text";
|
|
@@ -0,0 +1,68 @@
|
|
|
1
|
+
import { store } from './store.js';
|
|
2
|
+
import { getWs } from './ws-ref.js';
|
|
3
|
+
import { getCachedSessions } from './sidebar-sessions.js';
|
|
4
|
+
import { isCurrentProjectSessionReady } from './split-session-boundary.js';
|
|
5
|
+
import { splitPanesMatchProject, reconcileRestoredSplit } from './project-activation.js';
|
|
6
|
+
import { splitGroupMemberIds } from './split-group-helpers.js';
|
|
7
|
+
import { splitPaneForSession } from './split-pane-reconciler.js';
|
|
8
|
+
import { clearProjectSplitState } from './split-session-boundary.js';
|
|
9
|
+
|
|
10
|
+
export function reconcileSplitIdentity(state, previous, host) {
|
|
11
|
+
var ownerChanged = (previous.authIdentityLoaded === true || state.splitIdentityHydrated) && state.myUserId !== previous.myUserId;
|
|
12
|
+
if (state.authIdentityLoaded && !state.splitIdentityHydrated) store.set({ splitIdentityHydrated: true });
|
|
13
|
+
if (state.currentSlug === previous.currentSlug && state.myUserId === previous.myUserId) return false;
|
|
14
|
+
Array.from(host.querySelectorAll('.split-pane-frame')).forEach(function (frame) {
|
|
15
|
+
if (frame.clayPane) frame.clayPane.suspend();
|
|
16
|
+
});
|
|
17
|
+
host.innerHTML = '';
|
|
18
|
+
if (ownerChanged) {
|
|
19
|
+
// This socket was authenticated as the previous owner. Fresh metadata on
|
|
20
|
+
// that connection cannot establish the replacement owner's pane boundary.
|
|
21
|
+
store.set({ splitIdentityBlockedSocket: getWs(), paneBindingSessions: [] });
|
|
22
|
+
clearProjectSplitState();
|
|
23
|
+
} else if (state.splitPanes) store.set({ splitPanes: null });
|
|
24
|
+
return true;
|
|
25
|
+
}
|
|
26
|
+
|
|
27
|
+
// The initial owner response can arrive after history and split metadata.
|
|
28
|
+
// Wait for it so identity cleanup cannot discard panes we just restored.
|
|
29
|
+
export function restoreSplitGroup(openGroup) {
|
|
30
|
+
var state = store.snap();
|
|
31
|
+
if (state.authIdentityLoaded === false || state.isMultiUserMode && !state.myUserId) return;
|
|
32
|
+
if (!isCurrentProjectSessionReady(state, getWs())) return;
|
|
33
|
+
var split = state.splitPanes;
|
|
34
|
+
if (split && !splitPanesMatchProject(split, state.currentSlug)) {
|
|
35
|
+
store.set({ splitPanes: null });
|
|
36
|
+
return;
|
|
37
|
+
}
|
|
38
|
+
if (state.paneMode) return;
|
|
39
|
+
if (split) {
|
|
40
|
+
var reconciliation = reconcileRestoredSplit(split, state.splitGroups);
|
|
41
|
+
if (reconciliation.action === "clear") {
|
|
42
|
+
store.set({ splitPanes: null });
|
|
43
|
+
return;
|
|
44
|
+
}
|
|
45
|
+
if (reconciliation.action === "rebuild") {
|
|
46
|
+
var rebuilt = reconciliation.group;
|
|
47
|
+
if (rebuilt.members.some(function (id) { return !getCachedSessions().some(function (session) { return session.id === id; }); })) {
|
|
48
|
+
store.set({ splitPanes: null });
|
|
49
|
+
return;
|
|
50
|
+
}
|
|
51
|
+
store.set({ splitPanes: {
|
|
52
|
+
groupId: rebuilt.id,
|
|
53
|
+
panes: splitGroupMemberIds(rebuilt).map(function (id) { return splitPaneForSession(id, state.currentSlug, getCachedSessions()); }),
|
|
54
|
+
} });
|
|
55
|
+
}
|
|
56
|
+
return;
|
|
57
|
+
}
|
|
58
|
+
var activeId = store.get('activeSessionId');
|
|
59
|
+
if (!activeId) return;
|
|
60
|
+
var groups = store.get('splitGroups') || [];
|
|
61
|
+
for (var i = 0; i < groups.length; i++) {
|
|
62
|
+
var members = groups[i].members || [];
|
|
63
|
+
if (members.indexOf(activeId) !== -1) {
|
|
64
|
+
openGroup(groups[i]);
|
|
65
|
+
return;
|
|
66
|
+
}
|
|
67
|
+
}
|
|
68
|
+
}
|
|
@@ -236,6 +236,7 @@ function sendSetPair(groupId, driverId) {
|
|
|
236
236
|
|
|
237
237
|
export function syncPairChrome(host, split) {
|
|
238
238
|
if (!host || !split || !split.groupId) return;
|
|
239
|
+
if (Array.from(host.querySelectorAll('.split-pane-frame')).some(function (frame) { return !!frame.dataset.requestedSessionId; })) return;
|
|
239
240
|
var groups = store.get('splitGroups') || [];
|
|
240
241
|
var group = null;
|
|
241
242
|
for (var i = 0; i < groups.length; i++) {
|
|
@@ -2,6 +2,11 @@
|
|
|
2
2
|
// (and their iframe browsing contexts) are reused by stable project/session
|
|
3
3
|
// identity while metadata and visual order are refreshed.
|
|
4
4
|
|
|
5
|
+
export function splitPaneForSession(id, slug, sessions) {
|
|
6
|
+
var session = (sessions || []).find(function (item) { return item.id === id; });
|
|
7
|
+
return { slug: slug, sessionId: id, title: session && session.title || ('Session ' + id) };
|
|
8
|
+
}
|
|
9
|
+
|
|
5
10
|
export function splitPaneIdentity(pane) {
|
|
6
11
|
return String(pane && pane.slug || "") + "#" + String(pane && pane.sessionId || "");
|
|
7
12
|
}
|
|
@@ -16,9 +21,19 @@ export function reconcileSplitPanes(host, panes, createPane, updatePane) {
|
|
|
16
21
|
var pane = desired[pi];
|
|
17
22
|
var key = splitPaneIdentity(pane);
|
|
18
23
|
var paneEl = byKey.get(key);
|
|
24
|
+
if (!paneEl) {
|
|
25
|
+
for (var ci = 0; ci < existing.length; ci++) {
|
|
26
|
+
var candidate = existing[ci], frame = candidate.querySelector('.split-pane-frame');
|
|
27
|
+
if (!used.has(candidate) && frame && frame.dataset.projectSlug === pane.slug && frame.clayPane &&
|
|
28
|
+
!desired.some(function (item) { return splitPaneIdentity(item) === candidate.dataset.splitPaneKey; })) {
|
|
29
|
+
paneEl = candidate; break;
|
|
30
|
+
}
|
|
31
|
+
}
|
|
32
|
+
}
|
|
19
33
|
if (!paneEl) paneEl = createPane(pane, pi);
|
|
20
34
|
paneEl.dataset.splitPaneKey = key;
|
|
21
35
|
updatePane(paneEl, pane, pi);
|
|
36
|
+
if (paneEl.style) paneEl.style.order = String(pi);
|
|
22
37
|
used.add(paneEl);
|
|
23
38
|
if (!paneEl.parentNode) host.appendChild(paneEl);
|
|
24
39
|
}
|
|
@@ -6,6 +6,8 @@ import { formatTokens } from './app-panels.js';
|
|
|
6
6
|
import { VENDOR_AVATARS, VENDOR_NAMES } from './app-rendering.js';
|
|
7
7
|
import { createPermissionControl, bindPermissionControl, renderPermissionControl } from './permission-control.js';
|
|
8
8
|
import { splitGroupRoles } from './split-group-helpers.js';
|
|
9
|
+
import { paneTarget, livePaneBinding, samePaneTarget } from './pane-binding.js';
|
|
10
|
+
import { syncPairChrome } from './split-pair-ui.js';
|
|
9
11
|
|
|
10
12
|
function sessionById(sessionId) {
|
|
11
13
|
var sessions = getCachedSessions() || [];
|
|
@@ -17,17 +19,31 @@ function paneUrl(pane) {
|
|
|
17
19
|
return "/p/" + encodeURIComponent(pane.slug) + "/?pane=1&session=" + encodeURIComponent(pane.sessionId);
|
|
18
20
|
}
|
|
19
21
|
|
|
22
|
+
function headerBindingStamp(frame) {
|
|
23
|
+
var live = frame.clayPane && frame.clayPane.identity();
|
|
24
|
+
return JSON.stringify([frame.dataset.sessionId, frame.dataset.sessionOriginId,
|
|
25
|
+
live && live.binding && live.binding.requestId, live && live.binding && live.binding.generation]);
|
|
26
|
+
}
|
|
27
|
+
|
|
20
28
|
function startPaneRename(header, titleEl, pane) {
|
|
21
29
|
if (header.querySelector(".split-pane-rename-input")) return;
|
|
22
30
|
var input = document.createElement("input");
|
|
23
31
|
input.type = "text"; input.className = "split-pane-rename-input"; input.value = pane.title;
|
|
24
32
|
titleEl.style.display = "none"; header.insertBefore(input, titleEl); input.focus(); input.select();
|
|
25
33
|
var done = false;
|
|
34
|
+
var section = header.parentNode, frame = section.querySelector('.split-pane-frame');
|
|
35
|
+
var origin = frame.dataset.sessionOriginId, binding = frame.clayPane && frame.clayPane.identity().binding, socket = getWs();
|
|
36
|
+
function current() {
|
|
37
|
+
var live = frame.clayPane && frame.clayPane.identity();
|
|
38
|
+
return header.isConnected && !header.inert && socket === getWs() && store.get('connected') &&
|
|
39
|
+
frame.dataset.sessionId === String(pane.sessionId) && frame.dataset.sessionOriginId === origin && !frame.dataset.requestedSessionId &&
|
|
40
|
+
(!frame.clayPane || livePaneBinding(frame) && live.binding === binding);
|
|
41
|
+
}
|
|
26
42
|
function finish(commit) {
|
|
27
43
|
if (done) return;
|
|
28
44
|
done = true;
|
|
29
45
|
var newTitle = input.value.trim(); input.remove(); titleEl.style.display = "";
|
|
30
|
-
if (!commit || !newTitle || newTitle === pane.title) return;
|
|
46
|
+
if (!commit || !current() || !newTitle || newTitle === pane.title) return;
|
|
31
47
|
pane.title = newTitle; titleEl.textContent = newTitle;
|
|
32
48
|
var ws = getWs();
|
|
33
49
|
if (ws && ws.readyState === 1) ws.send(JSON.stringify({ type: "rename_session", id: pane.sessionId, title: newTitle }));
|
|
@@ -37,6 +53,7 @@ function startPaneRename(header, titleEl, pane) {
|
|
|
37
53
|
if (event.key === "Escape") { event.preventDefault(); finish(false); }
|
|
38
54
|
});
|
|
39
55
|
input.addEventListener("blur", function () { finish(true); });
|
|
56
|
+
header.addEventListener('clay-pane-retarget', function cancel() { finish(false); header.removeEventListener('clay-pane-retarget', cancel); });
|
|
40
57
|
input.addEventListener("click", function (event) { event.stopPropagation(); });
|
|
41
58
|
}
|
|
42
59
|
|
|
@@ -73,33 +90,97 @@ export function createSplitPane(pane, closePane) {
|
|
|
73
90
|
var vendorIcon = document.createElement("img"); vendorIcon.className = "split-pane-vendor";
|
|
74
91
|
vendorIcon.src = VENDOR_AVATARS[vendor] || VENDOR_AVATARS.claude; vendorIcon.alt = ""; vendorIcon.title = VENDOR_NAMES[vendor] || vendor; header.appendChild(vendorIcon);
|
|
75
92
|
var title = document.createElement("span"); title.className = "split-pane-title"; title.textContent = pane.title; title.title = "Rename session";
|
|
76
|
-
title.addEventListener("click", function () { startPaneRename(header, title,
|
|
93
|
+
title.addEventListener("click", function () { var current = sessionById(Number(paneEl.dataset.sessionId)); if (current) startPaneRename(header, title, { sessionId: current.id, title: current.title }); }); header.appendChild(title);
|
|
77
94
|
var frame = document.createElement("iframe"); frame.className = "split-pane-frame"; frame.dataset.projectSlug = pane.slug;
|
|
78
95
|
frame.dataset.sessionId = String(pane.sessionId); frame.src = paneUrl(pane); frame.title = pane.title;
|
|
96
|
+
frame.dataset.sessionOriginId = session && session.sessionOriginId || '';
|
|
97
|
+
header.addEventListener('pointerdown', function () { header.dataset.pointerSessionId = frame.dataset.sessionId; header.dataset.pointerBinding = headerBindingStamp(frame); });
|
|
98
|
+
header.addEventListener('click', function (event) {
|
|
99
|
+
if (frame.clayPane && (!livePaneBinding(frame) || event.detail && header.dataset.pointerBinding !== headerBindingStamp(frame))) {
|
|
100
|
+
event.preventDefault(); event.stopImmediatePropagation();
|
|
101
|
+
}
|
|
102
|
+
}, true);
|
|
103
|
+
['keydown', 'keyup'].forEach(function (name) {
|
|
104
|
+
header.addEventListener(name, function (event) {
|
|
105
|
+
var stamp = headerBindingStamp(frame);
|
|
106
|
+
if (name === 'keydown' && !event.repeat) header.dataset.keyBinding = stamp;
|
|
107
|
+
if (header.inert || header.dataset.keyBinding !== stamp) { event.preventDefault(); event.stopImmediatePropagation(); }
|
|
108
|
+
}, true);
|
|
109
|
+
});
|
|
79
110
|
var ctxChip = document.createElement("button"); ctxChip.type = "button"; ctxChip.className = "split-pane-context"; ctxChip.title = "Context usage";
|
|
80
111
|
ctxChip.innerHTML = '<span class="split-pane-context-bar"><span class="split-pane-context-fill"></span></span><span class="split-pane-context-label"></span>';
|
|
81
|
-
ctxChip.addEventListener("click", function () { if (frame.contentWindow) frame.contentWindow.postMessage({ type: "clay-pane-toggle-context" }, window.location.origin); }); header.appendChild(ctxChip);
|
|
112
|
+
ctxChip.addEventListener("click", function () { if (frame.contentWindow && (!frame.clayPane || livePaneBinding(frame))) frame.contentWindow.postMessage({ type: "clay-pane-toggle-context", paneBinding: frame.clayPane && frame.clayPane.identity().binding }, window.location.origin); }); header.appendChild(ctxChip);
|
|
82
113
|
var fullAccess = createPermissionControl("split-pane-full-access hidden", "Driver session permission mode");
|
|
83
|
-
updatePaneFullAccessButton(fullAccess, session); bindPermissionControl(fullAccess, function () { return permissionState(sessionById(
|
|
114
|
+
updatePaneFullAccessButton(fullAccess, session); bindPermissionControl(fullAccess, function () { return permissionState(sessionById(Number(paneEl.dataset.sessionId))); }); header.appendChild(fullAccess); header.insertBefore(fullAccess, ctxChip);
|
|
84
115
|
var close = document.createElement("button"); close.type = "button"; close.className = "split-pane-close"; close.title = "Close pane"; close.setAttribute("aria-label", "Close pane"); close.innerHTML = iconHtml("x");
|
|
85
116
|
close.dataset.sessionId = String(pane.sessionId); close.addEventListener("click", function () { closePane(Number(this.dataset.sessionId)); }); header.appendChild(close);
|
|
117
|
+
frame.addEventListener('clay-pane-ready', function () {
|
|
118
|
+
var id = Number(frame.dataset.requestedSessionId || frame.dataset.sessionId), current = sessionById(id);
|
|
119
|
+
var live = frame.clayPane && frame.clayPane.identity(), target = paneTarget(store.snap(), getCachedSessions(), id);
|
|
120
|
+
if (!current || !live || !live.ready || !samePaneTarget(target, live.binding) || live.sessionId !== id) return;
|
|
121
|
+
frame.dataset.sessionId = String(id); delete frame.dataset.requestedSessionId;
|
|
122
|
+
frame.dataset.sessionOriginId = live.binding.sessionOriginId;
|
|
123
|
+
updateSplitPaneMetadata(paneEl, { slug: frame.dataset.projectSlug, sessionId: id, title: current.title });
|
|
124
|
+
syncPairChrome(paneEl.parentNode, store.get('splitPanes'));
|
|
125
|
+
});
|
|
126
|
+
frame.addEventListener('clay-pane-activation-failed', function () {
|
|
127
|
+
var id = Number(frame.dataset.requestedSessionId || frame.dataset.sessionId);
|
|
128
|
+
var fallbackTarget = paneTarget(store.snap(), getCachedSessions(), id);
|
|
129
|
+
if (!fallbackTarget) { header.inert = true; return; }
|
|
130
|
+
frame.dataset.sessionOriginId = fallbackTarget.sessionOriginId;
|
|
131
|
+
frame.src = paneUrl({ slug: frame.dataset.projectSlug, sessionId: id });
|
|
132
|
+
frame.dataset.sessionId = String(id); delete frame.dataset.requestedSessionId;
|
|
133
|
+
});
|
|
86
134
|
paneEl.appendChild(header); paneEl.appendChild(frame); return paneEl;
|
|
87
135
|
}
|
|
88
136
|
|
|
89
137
|
export function updateSplitPaneMetadata(paneEl, pane) {
|
|
90
138
|
var session = sessionById(pane.sessionId); var header = paneEl.querySelector(".split-pane-header");
|
|
91
139
|
var title = paneEl.querySelector(".split-pane-title"); var frame = paneEl.querySelector(".split-pane-frame"); var vendor = paneEl.querySelector(".split-pane-vendor");
|
|
140
|
+
var live = frame && frame.clayPane && frame.clayPane.identity();
|
|
141
|
+
var retarget = frame && (Number(frame.dataset.sessionId) !== pane.sessionId || frame.dataset.sessionOriginId !== (session && session.sessionOriginId || '') || frame.clayPane && (!live || !live.ready));
|
|
142
|
+
if (retarget && header) {
|
|
143
|
+
header.dispatchEvent(new Event('clay-pane-retarget'));
|
|
144
|
+
header.inert = true;
|
|
145
|
+
header.title = 'Loading conversation';
|
|
146
|
+
if (title) { title.style.display = ''; title.textContent = 'Loading conversation'; }
|
|
147
|
+
if (vendor) vendor.hidden = true;
|
|
148
|
+
var permission = paneEl.querySelector('.split-pane-full-access');
|
|
149
|
+
if (permission) permission.classList.add('hidden');
|
|
150
|
+
resetPaneContextChip(paneEl);
|
|
151
|
+
}
|
|
152
|
+
if (frame && frame.clayPane && retarget) {
|
|
153
|
+
var target = paneTarget(store.snap(), getCachedSessions(), pane.sessionId);
|
|
154
|
+
if (target && frame.clayPane.source === frame.contentWindow && frame.clayPane.document === frame.contentDocument && frame.clayPane.activate(pane.sessionId, false, target)) {
|
|
155
|
+
frame.dataset.requestedSessionId = String(pane.sessionId);
|
|
156
|
+
if (header) header.inert = true;
|
|
157
|
+
return;
|
|
158
|
+
}
|
|
159
|
+
frame.src = paneUrl(pane);
|
|
160
|
+
frame.dataset.sessionId = String(pane.sessionId); frame.dataset.projectSlug = pane.slug;
|
|
161
|
+
frame.dataset.sessionOriginId = session && session.sessionOriginId || '';
|
|
162
|
+
}
|
|
163
|
+
if (header) header.inert = false;
|
|
92
164
|
paneEl.dataset.sessionId = String(pane.sessionId); paneEl.dataset.projectSlug = pane.slug;
|
|
93
165
|
if (header) header.title = pane.title; if (title && title.style.display !== "none") title.textContent = pane.title; if (frame) frame.title = pane.title;
|
|
94
|
-
if (vendor) { var vendorName = session && session.vendor || "claude"; vendor.src = VENDOR_AVATARS[vendorName] || VENDOR_AVATARS.claude; vendor.title = VENDOR_NAMES[vendorName] || vendorName; }
|
|
166
|
+
if (vendor) { vendor.hidden = false; var vendorName = session && session.vendor || "claude"; vendor.src = VENDOR_AVATARS[vendorName] || VENDOR_AVATARS.claude; vendor.title = VENDOR_NAMES[vendorName] || vendorName; }
|
|
167
|
+
updatePaneFullAccessButton(paneEl.querySelector('.split-pane-full-access'), session);
|
|
95
168
|
var close = paneEl.querySelector(".split-pane-close");
|
|
96
169
|
if (close) {
|
|
97
170
|
close.dataset.sessionId = String(pane.sessionId); close.disabled = false; close.title = "Close pane"; close.setAttribute("aria-label", close.title);
|
|
98
171
|
}
|
|
99
172
|
}
|
|
100
173
|
|
|
174
|
+
function resetPaneContextChip(paneEl) {
|
|
175
|
+
var chip = paneEl.querySelector('.split-pane-context'); if (!chip) return;
|
|
176
|
+
chip.classList.remove('has-data'); chip.title = 'Context usage';
|
|
177
|
+
var fill = chip.querySelector('.split-pane-context-fill'), label = chip.querySelector('.split-pane-context-label');
|
|
178
|
+
if (fill) { fill.style.width = '0%'; fill.className = 'split-pane-context-fill'; }
|
|
179
|
+
if (label) label.textContent = '';
|
|
180
|
+
}
|
|
181
|
+
|
|
101
182
|
export function updatePaneContextChip(paneEl, msg) {
|
|
102
|
-
if (!paneEl) return; var chip = paneEl.querySelector(".split-pane-context"); if (!chip) return; var pct = msg.pct || 0; if (pct <= 0) return;
|
|
183
|
+
if (!paneEl) return; var chip = paneEl.querySelector(".split-pane-context"); if (!chip) return; var pct = msg.pct || 0; if (pct <= 0) { resetPaneContextChip(paneEl); return; }
|
|
103
184
|
chip.classList.add("has-data"); var fill = chip.querySelector(".split-pane-context-fill"); var label = chip.querySelector(".split-pane-context-label");
|
|
104
185
|
fill.style.width = Math.min(100, pct).toFixed(1) + "%"; fill.className = "split-pane-context-fill" + (msg.cls || ""); label.textContent = pct.toFixed(0) + "%";
|
|
105
186
|
var tip = "Context " + pct.toFixed(0) + "% (" + formatTokens(msg.used || 0) + " / " + formatTokens(msg.win || 0) + " tokens)";
|
|
@@ -2,7 +2,7 @@ import { store } from './store.js';
|
|
|
2
2
|
import { isProjectSessionReady } from './project-activation.js';
|
|
3
3
|
|
|
4
4
|
export function isCurrentProjectSessionReady(state, socket) {
|
|
5
|
-
return isProjectSessionReady(state, socket);
|
|
5
|
+
return socket !== state.splitIdentityBlockedSocket && isProjectSessionReady(state, socket);
|
|
6
6
|
}
|
|
7
7
|
|
|
8
8
|
export function clearProjectSplitState() {
|