clay-server 5.2.0-beta.1 → 5.2.0-beta.11
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.md +0 -4
- 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 +52 -0
- package/lib/clay-product-control.js +250 -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-vendor-usage.js +44 -0
- 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/github-star-count.js +147 -0
- 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 +92 -0
- package/lib/notes.js +51 -4
- 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 +40 -11
- 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 +160 -290
- package/lib/project-shared-browser.js +78 -17
- package/lib/project-start-protocol.js +29 -0
- package/lib/project-studio-presentation.js +58 -0
- package/lib/project-user-message.js +67 -1
- package/lib/project-vendor-login.js +8 -36
- package/lib/project-workspace-operations.js +126 -0
- package/lib/project-workspace-query.js +19 -2
- package/lib/project.js +181 -45
- package/lib/public/app.js +71 -17
- 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/filebrowser.css +1 -1
- 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/mate-loading-scene.css +21 -0
- package/lib/public/css/messages.css +6 -2
- package/lib/public/css/overlays.css +68 -258
- package/lib/public/css/project-admin-overview.css +13 -0
- package/lib/public/css/project-mate-creation.css +5 -6
- package/lib/public/css/project-start.css +108 -0
- package/lib/public/css/projects-hub.css +53 -14
- package/lib/public/css/session-folders.css +11 -0
- package/lib/public/css/session-github.css +46 -1
- package/lib/public/css/settings-shell.css +103 -0
- package/lib/public/css/shared-browser.css +35 -1
- package/lib/public/css/sidebar.css +7 -0
- package/lib/public/css/sticky-notes.css +87 -1
- package/lib/public/css/title-bar.css +79 -0
- package/lib/public/index.html +61 -68
- 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-invitations.js +2 -2
- package/lib/public/modules/admin-settings-projects.js +8 -4
- package/lib/public/modules/admin-settings-ui.js +20 -4
- package/lib/public/modules/admin-settings-users.js +4 -4
- 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-home-hub.js +2 -1
- 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 +125 -19
- 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 +14 -407
- package/lib/public/modules/app-rate-limit.js +19 -28
- 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 +343 -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 +252 -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/github-star.js +66 -0
- 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-loading-scene.js +17 -0
- 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 +12 -241
- 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-creation-workspace.js +13 -4
- package/lib/public/modules/project-mate-navigation.js +144 -22
- package/lib/public/modules/project-session-visibility-settings.js +19 -16
- package/lib/public/modules/project-settings.js +119 -129
- package/lib/public/modules/project-start-dialog.js +130 -0
- package/lib/public/modules/project-start-folder-state.js +78 -0
- package/lib/public/modules/project-start-folder-view.js +190 -0
- package/lib/public/modules/project-start-forms.js +66 -0
- package/lib/public/modules/project-start-path.js +60 -0
- package/lib/public/modules/project-start-state.js +54 -0
- package/lib/public/modules/project-start-submit.js +67 -0
- package/lib/public/modules/projects-hub-view.js +33 -14
- package/lib/public/modules/projects-hub.js +10 -6
- 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.js +36 -91
- 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/settings-project-target.js +56 -0
- package/lib/public/modules/settings-select.js +1 -1
- package/lib/public/modules/settings-shell-registry.js +88 -0
- package/lib/public/modules/settings-shell-view.js +104 -0
- package/lib/public/modules/settings-shell.js +342 -0
- 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 +12 -33
- package/lib/public/modules/sidebar-projects.js +3 -1
- 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 +18 -3
- 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 +14 -30
- package/lib/public/modules/user-settings-preferences.js +6 -2
- package/lib/public/modules/user-settings-profile.js +13 -3
- package/lib/public/modules/user-settings.js +18 -84
- 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/vendor-usage-format.js +93 -0
- package/lib/public/modules/vendor-usage-list.js +45 -0
- package/lib/public/modules/vendor-usage-model.js +215 -0
- package/lib/public/modules/vendor-usage-overview.js +312 -0
- package/lib/public/modules/wireframe-workbench.js +5 -2
- package/lib/public/muse-avatar.svg +4 -0
- package/lib/public/style.css +14 -6
- package/lib/public/sw.js +3 -1
- package/lib/public/welcome-art/conversation-desk.png +0 -0
- package/lib/public/welcome-art/mate-clay.png +0 -0
- package/lib/public/welcome-art/project-clay.png +0 -0
- 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 +348 -402
- package/lib/sdk-foreground-admission.js +16 -0
- package/lib/sdk-mcp-descriptors.js +2 -37
- package/lib/sdk-message-processor.js +61 -18
- package/lib/sdk-quota-snapshot.js +21 -3
- 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-github-stars.js +39 -0
- package/lib/server-global-ws.js +26 -32
- 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 +167 -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-notes-mcp-server.js +26 -4
- package/lib/session-notes-writes.js +88 -0
- package/lib/session-permission-mode.js +4 -3
- package/lib/session-skill-scope.js +11 -0
- package/lib/session-visibility.js +25 -10
- package/lib/session-work-primary.js +50 -0
- package/lib/sessions.js +66 -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/vendor-usage-acp-readers.js +97 -0
- package/lib/vendor-usage-capabilities.js +88 -0
- package/lib/vendor-usage-http-readers.js +214 -0
- package/lib/vendor-usage-metrics.js +47 -0
- package/lib/vendor-usage-native-readers.js +106 -0
- package/lib/vendor-usage-overview.js +406 -0
- package/lib/vendor-usage-service.js +281 -0
- 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 +22 -4
- 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 +66 -50
- package/lib/yoke/adapters/codex-query-contract.js +25 -0
- package/lib/yoke/adapters/codex.js +98 -123
- 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 +272 -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-dynamic-tool-names.js +80 -0
- package/lib/yoke/codex-idle-recovery.js +81 -1
- package/lib/yoke/codex-model-catalog.js +37 -3
- 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 +92 -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 +34 -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 +87 -3
- package/package.json +11 -4
- package/lib/public/modules/server-settings-navigation.js +0 -39
package/lib/project-sessions.js
CHANGED
|
@@ -2,15 +2,19 @@ var serverSettingsMessages = require("./project-server-settings");
|
|
|
2
2
|
var fs = require("fs");
|
|
3
3
|
var path = require("path");
|
|
4
4
|
var { execFileSync } = require("child_process");
|
|
5
|
-
var
|
|
5
|
+
var providerSettings = require("./yoke/settings");
|
|
6
6
|
var updateSnooze = require("./update-snooze");
|
|
7
7
|
var yoke = require("./yoke");
|
|
8
|
+
var startProtocol = require("./project-start-protocol");
|
|
9
|
+
var startReply = startProtocol.withRequestId;
|
|
10
|
+
var browseMeta = startProtocol.browseMeta;
|
|
8
11
|
var sessionVisibility = require("./session-visibility");
|
|
9
12
|
var contextUsageModule = require("./context-usage");
|
|
10
13
|
var sessionDeleteModule = require("./project-session-delete");
|
|
11
14
|
var sessionFoldersModule = require("./project-session-folders");
|
|
12
15
|
var elicitationResponse = require("./project-elicitation-response");
|
|
13
16
|
var sessionCreationModule = require("./project-session-creation");
|
|
17
|
+
var vendorUsageOverviewModule = require("./vendor-usage-overview");
|
|
14
18
|
|
|
15
19
|
function vendorSupportsTui(vendor) {
|
|
16
20
|
var info = yoke.getVendorInfo(vendor);
|
|
@@ -118,14 +122,20 @@ function attachSessions(ctx) {
|
|
|
118
122
|
var ensureProjectAccessForSession = ctx.ensureProjectAccessForSession;
|
|
119
123
|
var getOsUserInfoForWs = ctx.getOsUserInfoForWs;
|
|
120
124
|
var hydrateSkillCatalog = ctx.hydrateSkillCatalog || function () { return []; };
|
|
125
|
+
var sessionActions = require("./project-session-actions").attachSessionActions(ctx);
|
|
126
|
+
var sessionVendor = require("./project-session-vendor").attachSessionVendor(ctx);
|
|
127
|
+
var sessionRuntime = require("./project-session-runtime-actions").attachSessionRuntimeActions({ sm: sm, tm: tm, prepareGui: prepareTuiSessionForGuiView, isPendingQueuePaused: ctx.isPendingQueuePaused,
|
|
128
|
+
publishGui: function (session) {
|
|
129
|
+
clients.forEach(function (ws) {
|
|
130
|
+
if (ws.readyState !== 1 || ws._clayActiveSession !== session.localId) return;
|
|
131
|
+
if (usersModule.isMultiUser() && (!ws._clayUser || !usersModule.findUserById(ws._clayUser.id) || !usersModule.canAccessProject(ws._clayUser.id, getProjectAccess()) || !usersModule.canAccessSession(ws._clayUser.id, session, getProjectAccess()))) return;
|
|
132
|
+
sm.switchSession(session.localId, ws, ctx.hydrateImageRefs);
|
|
133
|
+
});
|
|
134
|
+
},
|
|
135
|
+
});
|
|
121
136
|
function stopSession(session, actor) {
|
|
122
137
|
if (!session) return false;
|
|
123
|
-
session
|
|
124
|
-
if (typeof ctx.onPendingQueuePause === "function") ctx.onPendingQueuePause(session, actor || null);
|
|
125
|
-
if (!session.isProcessing && !session._queryStarting) return true;
|
|
126
|
-
if (typeof ctx.onHumanPairStop === "function") ctx.onHumanPairStop(session);
|
|
127
|
-
session.taskStopRequested = true;
|
|
128
|
-
if (session.abortController) session.abortController.abort();
|
|
138
|
+
sessionActions.stop(session, actor);
|
|
129
139
|
return true;
|
|
130
140
|
}
|
|
131
141
|
var hydrateImageRefs = ctx.hydrateImageRefs;
|
|
@@ -143,12 +153,16 @@ function attachSessions(ctx) {
|
|
|
143
153
|
return !session.ownerId;
|
|
144
154
|
}
|
|
145
155
|
|
|
146
|
-
function respondToAskUser(session, msg) {
|
|
156
|
+
function respondToAskUser(session, msg, ws) {
|
|
147
157
|
if (!session || !msg || !msg.toolId) return false;
|
|
148
158
|
var toolId = msg.toolId;
|
|
149
159
|
var answers = msg.answers || {};
|
|
150
160
|
var pending = session.pendingAskUser && session.pendingAskUser[toolId];
|
|
151
161
|
if (!pending) return false;
|
|
162
|
+
if (pending.request && ["mcp-import", "product-control"].indexOf(pending.request.source) >= 0 &&
|
|
163
|
+
(typeof pending.request.authorizeResponse !== "function" || !pending.request.authorizeResponse(ws))) return false;
|
|
164
|
+
if (pending.request && ["work-primary", "mate-schedule"].indexOf(pending.request.source) >= 0 && usersModule.isMultiUser() &&
|
|
165
|
+
(!ws || !ws._clayUser || ws._clayUser.id !== session.ownerId)) return false;
|
|
152
166
|
if (pending.mode === "yoke") {
|
|
153
167
|
try { yoke.userInput.normalizeAnswers(pending.request.questions, answers); }
|
|
154
168
|
catch (e) { return false; }
|
|
@@ -209,6 +223,14 @@ function attachSessions(ctx) {
|
|
|
209
223
|
var setLatestVersion = ctx.setLatestVersion;
|
|
210
224
|
var loadContextSources = ctx.loadContextSources;
|
|
211
225
|
|
|
226
|
+
var sessionHistory = require("./project-session-history-actions").attachSessionHistoryActions(Object.assign({}, ctx, {
|
|
227
|
+
resolveSessionHome: resolveSessionHome, cancelPendingAskUser: cancelPendingAskUser,
|
|
228
|
+
}));
|
|
229
|
+
|
|
230
|
+
function boundedRequestId(msg) {
|
|
231
|
+
return typeof msg.requestId === "string" ? msg.requestId.substring(0, 200) : undefined;
|
|
232
|
+
}
|
|
233
|
+
|
|
212
234
|
function canAccessProjectSlug(ws, targetSlug) {
|
|
213
235
|
if (!targetSlug) return false;
|
|
214
236
|
if (!usersModule || typeof usersModule.isMultiUser !== "function" || !usersModule.isMultiUser()) return true;
|
|
@@ -244,7 +266,7 @@ function attachSessions(ctx) {
|
|
|
244
266
|
if (!session || !session.cliSessionId) return;
|
|
245
267
|
if (session._titleWatcherStop) return; // already watching
|
|
246
268
|
var watcher;
|
|
247
|
-
try { watcher = require("./claude-jsonl-watcher"); } catch (e) { return; }
|
|
269
|
+
try { watcher = require("./yoke/claude-jsonl-watcher"); } catch (e) { return; }
|
|
248
270
|
var home = resolveSessionHome(session);
|
|
249
271
|
var jsonlPath = watcher.jsonlPathFor(home, cwd, session.cliSessionId);
|
|
250
272
|
if (!jsonlPath) return;
|
|
@@ -312,7 +334,7 @@ function attachSessions(ctx) {
|
|
|
312
334
|
// message right away. The transcript is small enough that a full
|
|
313
335
|
// re-send beats maintaining a delta protocol.
|
|
314
336
|
try {
|
|
315
|
-
var newIndex = require("./tui-transcript-index").readAssistantIndex(resolveSessionHome(s), cwd, s.cliSessionId);
|
|
337
|
+
var newIndex = require("./yoke/tui-transcript-index").readAssistantIndex(resolveSessionHome(s), cwd, s.cliSessionId);
|
|
316
338
|
send({
|
|
317
339
|
type: "tui_transcript_state",
|
|
318
340
|
id: s.localId,
|
|
@@ -347,6 +369,11 @@ function attachSessions(ctx) {
|
|
|
347
369
|
getProjectAccess: getProjectAccess,
|
|
348
370
|
getVendorAvailability: function (ws) { return ctx.getVendorAvailability(ws); },
|
|
349
371
|
});
|
|
372
|
+
var vendorUsage = vendorUsageOverviewModule.attachVendorUsageOverview({
|
|
373
|
+
slug: slug, sm: sm, usersModule: usersModule, clients: clients, sendTo: sendTo, getProjectAccess: getProjectAccess,
|
|
374
|
+
getVendorAvailability: function (ws) { return ctx.getVendorAvailability(ws); },
|
|
375
|
+
adapters: ctx.adapters, osUsers: osUsers, getLinuxUserForWs: ctx.getLinuxUserForWs,
|
|
376
|
+
});
|
|
350
377
|
// Kick off watchers for any TUI sessions already loaded from disk so
|
|
351
378
|
// their titles refresh as soon as Claude Code rewrites the jsonl, even
|
|
352
379
|
// before the user clicks them.
|
|
@@ -436,10 +463,10 @@ function attachSessions(ctx) {
|
|
|
436
463
|
// Idempotent: if the PTY is already gone and history is populated, this
|
|
437
464
|
// is a no-op (avoids re-reading jsonl and re-writing the session file on
|
|
438
465
|
// every click while the user is reading the session in GUI mode).
|
|
439
|
-
function prepareTuiSessionForGuiView(session) {
|
|
466
|
+
function prepareTuiSessionForGuiView(session, options) {
|
|
440
467
|
if (!session || session.cliSessionId == null) return;
|
|
441
468
|
var cliSess;
|
|
442
|
-
try { cliSess = require("./cli-sessions"); } catch (e) { return; }
|
|
469
|
+
try { cliSess = require("./yoke/cli-sessions"); } catch (e) { return; }
|
|
443
470
|
// Re-read whenever the jsonl has changed since the last hydrate (a TUI
|
|
444
471
|
// turn appended messages), not just when history is empty. The earlier
|
|
445
472
|
// "already hydrated" short-circuit kept stale history after a
|
|
@@ -463,7 +490,7 @@ function attachSessions(ctx) {
|
|
|
463
490
|
try { tm.close(session.terminalId); } catch (e) {}
|
|
464
491
|
}
|
|
465
492
|
session.terminalId = null;
|
|
466
|
-
try { sm.saveSessionFile(session); } catch (e) {}
|
|
493
|
+
if (!options || !options.deferSave) { try { sm.saveSessionFile(session); } catch (e) {} }
|
|
467
494
|
}
|
|
468
495
|
|
|
469
496
|
// Resolve how a session should be presented to a viewer WITHOUT spawning a
|
|
@@ -588,7 +615,9 @@ function attachSessions(ctx) {
|
|
|
588
615
|
var targetFrom = typeof msg.target === "number" ? msg.target : before - sm.HISTORY_PAGE_SIZE;
|
|
589
616
|
var from = sm.findTurnBoundary(session.history, Math.max(0, targetFrom));
|
|
590
617
|
var to = before;
|
|
591
|
-
var items = session.history.slice(from, to).map(
|
|
618
|
+
var items = session.history.slice(from, to).map(function (item, index) {
|
|
619
|
+
return Object.assign({}, hydrateImageRefs(require("./yoke/usage").clientEvent(item, session.vendor || "claude")), { _historyIndex: from + index });
|
|
620
|
+
});
|
|
592
621
|
sendTo(ws, {
|
|
593
622
|
type: "history_prepend",
|
|
594
623
|
items: items,
|
|
@@ -739,13 +768,15 @@ function attachSessions(ctx) {
|
|
|
739
768
|
if (msg.type === "set_project_session_visibility_default") {
|
|
740
769
|
sessionVisibility.handleDefaultChange({
|
|
741
770
|
slug: slug, isMate: isMate, osUsers: osUsers, usersModule: usersModule, getProjectAccess: getProjectAccess,
|
|
742
|
-
|
|
771
|
+
getTargetAccess: typeof opts.onGetProjectAccess === "function" ? opts.onGetProjectAccess : null,
|
|
772
|
+
canAccessProjectSlug: canAccessProjectSlug, opts: opts, sendTo: sendTo,
|
|
743
773
|
}, ws, msg);
|
|
744
774
|
return true;
|
|
745
775
|
}
|
|
746
776
|
|
|
747
777
|
if (sessionFolders.handleMessage(ws, msg)) return true;
|
|
748
778
|
if (sessionCreation.handleMessage(ws, msg)) return true;
|
|
779
|
+
if (vendorUsage.handleMessage(ws, msg)) return true;
|
|
749
780
|
|
|
750
781
|
if (msg.type === "bulk_delete_sessions") {
|
|
751
782
|
sessionDelete.bulkDeleteSessions(ws, msg);
|
|
@@ -762,11 +793,10 @@ function attachSessions(ctx) {
|
|
|
762
793
|
sendTo(ws, { type: "error", text: "Cannot transfer ownership of home directory projects." });
|
|
763
794
|
return true;
|
|
764
795
|
}
|
|
765
|
-
var projectOwnerId =
|
|
766
|
-
var isAdmin = ws._clayUser && ws._clayUser.role === "admin";
|
|
796
|
+
var projectOwnerId = getProjectAccess().ownerId;
|
|
767
797
|
var isProjectOwner = ws._clayUser && projectOwnerId && ws._clayUser.id === projectOwnerId;
|
|
768
|
-
if (!ws._clayUser ||
|
|
769
|
-
sendTo(ws, { type: "error", text: "Only project owners
|
|
798
|
+
if (!ws._clayUser || !isProjectOwner) {
|
|
799
|
+
sendTo(ws, { type: "error", text: "Only project owners can transfer ownership." });
|
|
770
800
|
return true;
|
|
771
801
|
}
|
|
772
802
|
var targetUser = msg.userId ? usersModule.findUserById(msg.userId) : null;
|
|
@@ -774,11 +804,11 @@ function attachSessions(ctx) {
|
|
|
774
804
|
sendTo(ws, { type: "error", text: "User not found." });
|
|
775
805
|
return true;
|
|
776
806
|
}
|
|
807
|
+
// Persist before publishing runtime ownership.
|
|
808
|
+
if (!opts.onProjectOwnerChanged) return true;
|
|
809
|
+
var savedOwner = opts.onProjectOwnerChanged(slug, targetUser.id);
|
|
810
|
+
if (savedOwner && savedOwner.error) { sendTo(ws, { type: "error", text: savedOwner.error }); return true; }
|
|
777
811
|
setProjectOwnerId(targetUser.id);
|
|
778
|
-
// Persist via daemon callback
|
|
779
|
-
if (opts.onProjectOwnerChanged) {
|
|
780
|
-
opts.onProjectOwnerChanged(slug, targetUser.id);
|
|
781
|
-
}
|
|
782
812
|
send({ type: "project_owner_changed", ownerId: targetUser.id, ownerName: targetUser.displayName || targetUser.username });
|
|
783
813
|
return true;
|
|
784
814
|
}
|
|
@@ -789,18 +819,22 @@ function attachSessions(ctx) {
|
|
|
789
819
|
// adoptOrphanedCliSessions). Click a session in the sidebar instead.
|
|
790
820
|
|
|
791
821
|
if (msg.type === "switch_session") {
|
|
822
|
+
var paneActivation = require('./pane-session-activation').begin(ctx, ws, msg);
|
|
823
|
+
if (paneActivation === false) return true;
|
|
792
824
|
if (msg.id && sm.sessions.has(msg.id)) {
|
|
793
825
|
// resolveSessionForView sets runtimeMode / runtimeTerminalId /
|
|
794
826
|
// tuiSuspended (and hydrates the transcript) before sm.switchSession
|
|
795
827
|
// broadcasts session_switched. A live runtime keeps its actual mode
|
|
796
828
|
// for every viewer; idle sessions open in chat. Nothing is spawned here.
|
|
797
829
|
var xmTarget = sm.sessions.get(msg.id);
|
|
830
|
+
if (usersModule.isMultiUser() && (!ws._clayUser || !usersModule.canAccessSession(ws._clayUser.id, xmTarget, getProjectAccess()))) return true;
|
|
798
831
|
if (xmTarget && (!xmTarget.vendor || vendorSupportsTui(xmTarget.vendor))) {
|
|
799
832
|
// Single source of truth: live runtime wins (tui stays tui, gui stays
|
|
800
833
|
// gui); idle legacy sessions hydrate their transcript into chat.
|
|
801
834
|
resolveSessionForView(xmTarget, ws);
|
|
802
835
|
}
|
|
803
836
|
var switchTargetSess = sm.sessions.get(msg.id);
|
|
837
|
+
if (paneActivation && !paneActivation.validate()) return true;
|
|
804
838
|
var switchTargetVendor = switchTargetSess && (switchTargetSess.vendor || sm.defaultVendor || "claude");
|
|
805
839
|
if (switchTargetSess && !switchTargetSess.effort) {
|
|
806
840
|
switchTargetSess.effort = yoke.clampEffort(
|
|
@@ -813,20 +847,20 @@ function attachSessions(ctx) {
|
|
|
813
847
|
if (usersModule.isMultiUser() && ws._clayUser) {
|
|
814
848
|
var switchTarget = sm.sessions.get(msg.id);
|
|
815
849
|
if (!usersModule.canAccessSession(ws._clayUser.id, switchTarget, { visibility: "public" })) return true;
|
|
816
|
-
ws.
|
|
817
|
-
sm.switchSession(msg.id, ws, hydrateImageRefs);
|
|
850
|
+
sm.switchSession(msg.id, ws, hydrateImageRefs, paneActivation && paneActivation.send, paneActivation && paneActivation.validate);
|
|
818
851
|
if (!ws._clayPane) broadcastPresence();
|
|
819
852
|
} else {
|
|
820
|
-
ws.
|
|
821
|
-
sm.switchSession(msg.id, ws, hydrateImageRefs);
|
|
853
|
+
sm.switchSession(msg.id, ws, hydrateImageRefs, paneActivation && paneActivation.send, paneActivation && paneActivation.validate);
|
|
822
854
|
}
|
|
823
855
|
// Send per-session context sources
|
|
824
856
|
if (typeof loadContextSources === "function") {
|
|
825
857
|
var switchedSources = loadContextSources(slug, msg.id);
|
|
826
|
-
|
|
858
|
+
if (paneActivation) paneActivation.send({ type: "context_sources_state", active: switchedSources });
|
|
859
|
+
else sendTo(ws, { type: "context_sources_state", active: switchedSources });
|
|
827
860
|
}
|
|
828
861
|
var swPresKey = ws._clayUser ? ws._clayUser.id : "_default";
|
|
829
862
|
if (!ws._clayPane) userPresence.setPresence(slug, swPresKey, userPresence.sessionIdForPersistence(switchTargetSess), null);
|
|
863
|
+
if (paneActivation) paneActivation.finish();
|
|
830
864
|
}
|
|
831
865
|
return true;
|
|
832
866
|
}
|
|
@@ -902,7 +936,7 @@ function attachSessions(ctx) {
|
|
|
902
936
|
return true;
|
|
903
937
|
}
|
|
904
938
|
try {
|
|
905
|
-
var tprIndex = require("./tui-transcript-index").readAssistantIndex(resolveSessionHome(tprSess), cwd, tprSess.cliSessionId);
|
|
939
|
+
var tprIndex = require("./yoke/tui-transcript-index").readAssistantIndex(resolveSessionHome(tprSess), cwd, tprSess.cliSessionId);
|
|
906
940
|
sendTo(ws, {
|
|
907
941
|
type: "tui_transcript_state",
|
|
908
942
|
id: tprId,
|
|
@@ -933,19 +967,7 @@ function attachSessions(ctx) {
|
|
|
933
967
|
var s = sm.sessions.get(msg.id);
|
|
934
968
|
if (usersModule.isMultiUser() && (!ws._clayUser ||
|
|
935
969
|
!usersModule.canAccessSession(ws._clayUser.id, s, getProjectAccess()))) return true;
|
|
936
|
-
s
|
|
937
|
-
s.titleProvisional = false;
|
|
938
|
-
s.titleAutoGenerated = false;
|
|
939
|
-
s.titleManuallySet = true;
|
|
940
|
-
sm.saveSessionFile(s);
|
|
941
|
-
sm.notifySessionRenamed(s.localId);
|
|
942
|
-
sm.broadcastSessionList();
|
|
943
|
-
// Sync title to SDK session
|
|
944
|
-
if (s.cliSessionId) {
|
|
945
|
-
adapter.renameSession(s.cliSessionId, s.title, { dir: cwd }).catch(function(e) {
|
|
946
|
-
console.error("[project] SDK renameSession failed:", e.message);
|
|
947
|
-
});
|
|
948
|
-
}
|
|
970
|
+
sessionActions.rename(s, String(msg.title).substring(0, 100));
|
|
949
971
|
}
|
|
950
972
|
return true;
|
|
951
973
|
}
|
|
@@ -1080,7 +1102,12 @@ function attachSessions(ctx) {
|
|
|
1080
1102
|
|
|
1081
1103
|
if (msg.type === "stop") {
|
|
1082
1104
|
var session = getSessionForWs(ws);
|
|
1083
|
-
if (
|
|
1105
|
+
if (msg.sessionId != null || msg.sessionOriginId != null) {
|
|
1106
|
+
session = sm.sessions.get(msg.sessionId);
|
|
1107
|
+
if (!session || session.sessionOriginId !== msg.sessionOriginId ||
|
|
1108
|
+
!usersModule.isMultiUser() && session.ownerId ||
|
|
1109
|
+
usersModule.isMultiUser() && (!ws._clayUser || !usersModule.canAccessSession(ws._clayUser.id, session, getProjectAccess()))) return true;
|
|
1110
|
+
}
|
|
1084
1111
|
stopSession(session, ws && ws._clayUser);
|
|
1085
1112
|
return true;
|
|
1086
1113
|
}
|
|
@@ -1096,14 +1123,14 @@ function attachSessions(ctx) {
|
|
|
1096
1123
|
var pid = msg.pid;
|
|
1097
1124
|
if (!pid || typeof pid !== "number") return true;
|
|
1098
1125
|
// Verify target is actually a claude process before killing
|
|
1099
|
-
if (!sdk.
|
|
1100
|
-
console.error("[project] Refused to kill PID " + pid + ": not a
|
|
1101
|
-
sendTo(ws, { type: "error", text: "Process " + pid + " is not a
|
|
1126
|
+
if (!sdk.isProviderProcess(pid, getSessionForWs(ws))) {
|
|
1127
|
+
console.error("[project] Refused to kill PID " + pid + ": not a verified provider process");
|
|
1128
|
+
sendTo(ws, { type: "error", text: "Process " + pid + " is not a verified provider process." });
|
|
1102
1129
|
return true;
|
|
1103
1130
|
}
|
|
1104
1131
|
try {
|
|
1105
1132
|
process.kill(pid, "SIGTERM");
|
|
1106
|
-
console.log("[project] Sent SIGTERM to conflicting
|
|
1133
|
+
console.log("[project] Sent SIGTERM to conflicting provider process PID " + pid);
|
|
1107
1134
|
sendTo(ws, { type: "process_killed", pid: pid });
|
|
1108
1135
|
} catch (e) {
|
|
1109
1136
|
console.error("[project] Failed to kill PID " + pid + ":", e.message);
|
|
@@ -1181,38 +1208,14 @@ function attachSessions(ctx) {
|
|
|
1181
1208
|
|
|
1182
1209
|
if (msg.type === "set_vendor" && msg.vendor) {
|
|
1183
1210
|
var vendorSession = getSessionForWs(ws);
|
|
1184
|
-
if (vendorSession)
|
|
1185
|
-
|
|
1186
|
-
|
|
1187
|
-
|
|
1188
|
-
|
|
1189
|
-
|
|
1190
|
-
if (alreadyBound) {
|
|
1191
|
-
console.warn("[project] set_vendor ignored: session " + vendorSession.localId +
|
|
1192
|
-
" is bound to '" + vendorSession.vendor + "', refused rebind to '" + msg.vendor + "'");
|
|
1193
|
-
} else {
|
|
1194
|
-
vendorSession.vendor = msg.vendor;
|
|
1195
|
-
if (vendorSession.permissionMode === "auto" && msg.vendor !== "claude") {
|
|
1196
|
-
vendorSession.permissionMode = "default";
|
|
1197
|
-
vendorSession.effectivePermissionMode = null;
|
|
1198
|
-
}
|
|
1199
|
-
if (vendorSession.vendor !== msg.vendor) vendorSession.model = "";
|
|
1200
|
-
sm.saveSessionFile(vendorSession);
|
|
1201
|
-
sm.broadcastSessionList();
|
|
1202
|
-
}
|
|
1203
|
-
}
|
|
1204
|
-
if (msg.vendor) {
|
|
1205
|
-
var vendorModels = (sm.modelsByVendor && sm.modelsByVendor[msg.vendor]) || [];
|
|
1206
|
-
sendTo(ws, {
|
|
1207
|
-
type: "model_info",
|
|
1208
|
-
model: "",
|
|
1209
|
-
models: vendorModels,
|
|
1210
|
-
vendor: msg.vendor, sessionId: vendorSession ? vendorSession.localId : null,
|
|
1211
|
-
availableVendors: sm.availableVendors || [],
|
|
1212
|
-
installedVendors: sm.installedVendors || [],
|
|
1213
|
-
});
|
|
1214
|
-
send({ type: "config_state", vendor: null, sessionId: null, mode: sm.currentPermissionMode || "default", effort: sm.currentEffort || "medium", betas: sm.currentBetas || [], thinking: sm.currentThinking || "adaptive", thinkingBudget: sm.currentThinkingBudget || 10000 });
|
|
1211
|
+
if (!vendorSession) return true;
|
|
1212
|
+
// Re-selecting the provider of an established thread does not rebind it.
|
|
1213
|
+
if (vendorSession.cliSessionId && vendorSession.vendor === msg.vendor) return true;
|
|
1214
|
+
try {
|
|
1215
|
+
var vendorResult = sessionVendor.setVendor(vendorSession, msg.vendor);
|
|
1216
|
+
if (vendorResult.status === "failed") sendTo(ws, { type: "error", text: vendorResult.error });
|
|
1215
1217
|
}
|
|
1218
|
+
catch (error) { sendTo(ws, { type: "error", text: error.message }); }
|
|
1216
1219
|
return true;
|
|
1217
1220
|
}
|
|
1218
1221
|
|
|
@@ -1280,15 +1283,7 @@ function attachSessions(ctx) {
|
|
|
1280
1283
|
if (!valid.ok) { permissionResult(false, valid.error, true); return true; }
|
|
1281
1284
|
(async function() {
|
|
1282
1285
|
try {
|
|
1283
|
-
|
|
1284
|
-
await autonomousRun.stopForPermissionChange(session);
|
|
1285
|
-
}
|
|
1286
|
-
await fullAccessService.setMode(session, valid.mode);
|
|
1287
|
-
var state = permissionModes.clientState(session, sm.currentPermissionMode, sm.defaultVendor);
|
|
1288
|
-
sm.sendToSession(session, { type: "config_state", sessionId: session.localId, vendor: session.vendor || sm.defaultVendor || "claude", mode: state.requestedPermissionMode,
|
|
1289
|
-
effectivePermissionMode: state.effectivePermissionMode, permissionRequestId: requestId,
|
|
1290
|
-
permissionCapabilities: state.permissionCapabilities, mcpPermissionModeOverrides: state.mcpPermissionModeOverrides,
|
|
1291
|
-
effort: session.effort || sm.currentEffort || "medium", betas: sm.currentBetas || [] });
|
|
1286
|
+
await sessionActions.permission(session, valid.mode, requestId);
|
|
1292
1287
|
permissionResult(true, null, true);
|
|
1293
1288
|
} catch (error) {
|
|
1294
1289
|
permissionResult(false, "Failed to change permission mode: " + (error.message || error), true);
|
|
@@ -1358,10 +1353,9 @@ function attachSessions(ctx) {
|
|
|
1358
1353
|
sendTo(ws, { type: "error", text: "This effort level is not supported by the selected vendor." });
|
|
1359
1354
|
return true;
|
|
1360
1355
|
}
|
|
1361
|
-
|
|
1356
|
+
sessionActions.effort(session, sessionEffort).catch(function (e) {
|
|
1362
1357
|
sendTo(ws, { type: "error", text: "Failed to change reasoning effort: " + (e.message || e) });
|
|
1363
1358
|
});
|
|
1364
|
-
sm.sendToSession(session, { type: "config_state", model: session.model || ((sm.defaultModelByVendor || {})[effortVendor]) || "", vendor: effortVendor, sessionId: session.localId, mode: session.permissionMode || sm.currentPermissionMode || "default", effort: sessionEffort, betas: sm.currentBetas || [], thinking: sm.currentThinking || "adaptive", thinkingBudget: sm.currentThinkingBudget || 10000 });
|
|
1365
1359
|
}
|
|
1366
1360
|
return true;
|
|
1367
1361
|
}
|
|
@@ -1397,20 +1391,12 @@ function attachSessions(ctx) {
|
|
|
1397
1391
|
return true;
|
|
1398
1392
|
}
|
|
1399
1393
|
|
|
1400
|
-
|
|
1401
|
-
|
|
1402
|
-
|
|
1403
|
-
|
|
1404
|
-
|
|
1405
|
-
|
|
1406
|
-
if (msg.type === "set_codex_sandbox") {
|
|
1407
|
-
sm.codexSandbox = msg.sandbox || CODEX_DEFAULTS.sandbox;
|
|
1408
|
-
send(Object.assign({ type: "codex_config" }, getCodexConfig(sm)));
|
|
1409
|
-
return true;
|
|
1410
|
-
}
|
|
1411
|
-
if (msg.type === "set_codex_websearch") {
|
|
1412
|
-
sm.codexWebSearch = msg.webSearch || CODEX_DEFAULTS.webSearch;
|
|
1413
|
-
send(Object.assign({ type: "codex_config" }, getCodexConfig(sm)));
|
|
1394
|
+
var providerChange;
|
|
1395
|
+
try { providerChange = providerSettings.change(msg, sm); }
|
|
1396
|
+
catch (error) { sendTo(ws, { type: "error", text: error.message }); return true; }
|
|
1397
|
+
if (providerChange) {
|
|
1398
|
+
Object.keys(providerChange.patch).forEach(function(key) { sm[key] = providerChange.patch[key]; });
|
|
1399
|
+
providerChange.messages.forEach(function(message) { send(message); });
|
|
1414
1400
|
return true;
|
|
1415
1401
|
}
|
|
1416
1402
|
|
|
@@ -1438,92 +1424,9 @@ function attachSessions(ctx) {
|
|
|
1438
1424
|
sendTo(ws, { type: "rewind_error", text: "Rewind already in progress." });
|
|
1439
1425
|
return true;
|
|
1440
1426
|
}
|
|
1441
|
-
session.
|
|
1442
|
-
|
|
1443
|
-
|
|
1444
|
-
(async function () {
|
|
1445
|
-
try {
|
|
1446
|
-
// File restoration (delegated to adapter via sdk-bridge)
|
|
1447
|
-
if (mode !== "chat") {
|
|
1448
|
-
await sdk.rewindExecuteFiles(session, msg.uuid);
|
|
1449
|
-
}
|
|
1450
|
-
|
|
1451
|
-
// Conversation rollback (skip for files-only mode)
|
|
1452
|
-
if (mode !== "files") {
|
|
1453
|
-
var targetIdx = -1;
|
|
1454
|
-
for (var i = 0; i < session.messageUUIDs.length; i++) {
|
|
1455
|
-
if (session.messageUUIDs[i].uuid === msg.uuid) {
|
|
1456
|
-
targetIdx = i;
|
|
1457
|
-
break;
|
|
1458
|
-
}
|
|
1459
|
-
}
|
|
1460
|
-
|
|
1461
|
-
// Codex's thread/revert cuts at a turn id, not a count. Read the
|
|
1462
|
-
// target entry's turnId BEFORE trimming local history below.
|
|
1463
|
-
var hasTurnsToRollBack = false;
|
|
1464
|
-
var targetTurnId = null;
|
|
1465
|
-
if (targetIdx >= 0) {
|
|
1466
|
-
targetTurnId = session.messageUUIDs[targetIdx].turnId || null;
|
|
1467
|
-
for (var ri = targetIdx; ri < session.messageUUIDs.length; ri++) {
|
|
1468
|
-
if (session.messageUUIDs[ri].type === "user") { hasTurnsToRollBack = true; break; }
|
|
1469
|
-
}
|
|
1470
|
-
}
|
|
1471
|
-
|
|
1472
|
-
// Notify adapter of conversation rollback (e.g. Codex thread/revert)
|
|
1473
|
-
// BEFORE trimming local history below. Deliberately not caught
|
|
1474
|
-
// here: a failed or impossible (missing turnId) provider-side
|
|
1475
|
-
// rollback must abort the whole rewind via the outer catch, never
|
|
1476
|
-
// leave local history trimmed ahead of the real provider thread.
|
|
1477
|
-
if (hasTurnsToRollBack) {
|
|
1478
|
-
await sdk.rollbackConversation(session, targetTurnId);
|
|
1479
|
-
}
|
|
1480
|
-
|
|
1481
|
-
if (targetIdx >= 0) {
|
|
1482
|
-
var trimTo = session.messageUUIDs[targetIdx].historyIndex;
|
|
1483
|
-
for (var k = trimTo - 1; k >= 0; k--) {
|
|
1484
|
-
if (session.history[k].type === "user_message") {
|
|
1485
|
-
trimTo = k;
|
|
1486
|
-
break;
|
|
1487
|
-
}
|
|
1488
|
-
}
|
|
1489
|
-
session.history = session.history.slice(0, trimTo);
|
|
1490
|
-
session.messageUUIDs = session.messageUUIDs.slice(0, targetIdx);
|
|
1491
|
-
// Reset digest checkpoint if it points past the trimmed history
|
|
1492
|
-
if (typeof session._dmLastDigestedIndex === "number" && session._dmLastDigestedIndex > trimTo) {
|
|
1493
|
-
session._dmLastDigestedIndex = trimTo;
|
|
1494
|
-
}
|
|
1495
|
-
}
|
|
1496
|
-
|
|
1497
|
-
var kept = session.messageUUIDs;
|
|
1498
|
-
session.lastRewindUuid = kept.length > 0 ? kept[kept.length - 1].uuid : null;
|
|
1499
|
-
}
|
|
1500
|
-
|
|
1501
|
-
if (session.abortController) {
|
|
1502
|
-
try { session.abortController.abort(); } catch (e) {}
|
|
1503
|
-
}
|
|
1504
|
-
if (session.messageQueue) {
|
|
1505
|
-
try { session.messageQueue.end(); } catch (e) {}
|
|
1506
|
-
}
|
|
1507
|
-
session.queryInstance = null;
|
|
1508
|
-
session.messageQueue = null;
|
|
1509
|
-
session.abortController = null;
|
|
1510
|
-
session.blocks = {};
|
|
1511
|
-
session.sentToolResults = {};
|
|
1512
|
-
session.pendingPermissions = {};
|
|
1513
|
-
cancelPendingAskUser(session, "Conversation rewound");
|
|
1514
|
-
session.isProcessing = false;
|
|
1515
|
-
onProcessingChanged();
|
|
1516
|
-
|
|
1517
|
-
sm.saveSessionFile(session);
|
|
1518
|
-
sm.switchSession(session.localId, ws, hydrateImageRefs);
|
|
1519
|
-
sm.sendAndRecord(session, { type: "rewind_complete", mode: mode });
|
|
1520
|
-
sm.broadcastSessionList();
|
|
1521
|
-
} catch (err) {
|
|
1522
|
-
sendTo(ws, { type: "rewind_error", text: "Rewind failed: " + err.message });
|
|
1523
|
-
} finally {
|
|
1524
|
-
session._rewindInProgress = false;
|
|
1525
|
-
}
|
|
1526
|
-
})();
|
|
1427
|
+
sessionHistory.rewind(session, msg.uuid, msg.mode || "both", ws, function () {}).catch(function (error) {
|
|
1428
|
+
sendTo(ws, { type: "rewind_error", text: "Rewind failed: " + error.message });
|
|
1429
|
+
});
|
|
1527
1430
|
return true;
|
|
1528
1431
|
}
|
|
1529
1432
|
|
|
@@ -1533,69 +1436,17 @@ function attachSessions(ctx) {
|
|
|
1533
1436
|
sendTo(ws, { type: "error", text: "Cannot fork: no CLI session" });
|
|
1534
1437
|
return true;
|
|
1535
1438
|
}
|
|
1536
|
-
|
|
1537
|
-
|
|
1538
|
-
|
|
1539
|
-
|
|
1540
|
-
// Copy local history up to the target UUID
|
|
1541
|
-
var targetIdx = -1;
|
|
1542
|
-
for (var fi = 0; fi < session.messageUUIDs.length; fi++) {
|
|
1543
|
-
if (session.messageUUIDs[fi].uuid === msg.uuid) { targetIdx = fi; break; }
|
|
1544
|
-
}
|
|
1545
|
-
var forkHistory = [];
|
|
1546
|
-
if (targetIdx >= 0) {
|
|
1547
|
-
var trimTo = session.messageUUIDs[targetIdx].historyIndex;
|
|
1548
|
-
forkHistory = session.history.slice(0, trimTo);
|
|
1549
|
-
} else {
|
|
1550
|
-
forkHistory = session.history.slice();
|
|
1551
|
-
}
|
|
1552
|
-
var forked = sm.createSession({
|
|
1553
|
-
vendor: session.vendor,
|
|
1554
|
-
ownerId: session.ownerId || null,
|
|
1555
|
-
userKnowledgeOwnerId: session.userKnowledgeOwnerId || null,
|
|
1556
|
-
sessionVisibility: sessionVisibility.normalize(session.sessionVisibility),
|
|
1557
|
-
}, ws);
|
|
1558
|
-
forked.cliSessionId = result.sessionId;
|
|
1559
|
-
forked.title = forkTitle;
|
|
1560
|
-
forked.history = forkHistory;
|
|
1561
|
-
forked.messageUUIDs = [];
|
|
1562
|
-
for (var hi = 0; hi < forkHistory.length; hi++) {
|
|
1563
|
-
if (forkHistory[hi].type === "message_uuid") {
|
|
1564
|
-
forked.messageUUIDs.push({ uuid: forkHistory[hi].uuid, type: forkHistory[hi].messageType, historyIndex: hi, turnId: forkHistory[hi].turnId || null });
|
|
1565
|
-
}
|
|
1566
|
-
}
|
|
1567
|
-
sm.saveSessionFile(forked);
|
|
1568
|
-
sm.switchSession(forked.localId, ws, hydrateImageRefs);
|
|
1569
|
-
sendTo(ws, { type: "fork_complete", sessionId: forked.localId });
|
|
1570
|
-
sm.broadcastSessionList();
|
|
1571
|
-
} else {
|
|
1572
|
-
// Read history from CLI session files
|
|
1573
|
-
var cliSess = require("./cli-sessions");
|
|
1574
|
-
return cliSess.readCliSessionHistory(resolveSessionHome(session), cwd, result.sessionId).then(function(history) {
|
|
1575
|
-
var forked = sm.resumeSession(result.sessionId, {
|
|
1576
|
-
history: history,
|
|
1577
|
-
title: forkTitle,
|
|
1578
|
-
vendor: session.vendor,
|
|
1579
|
-
ownerId: session.ownerId || null,
|
|
1580
|
-
userKnowledgeOwnerId: session.userKnowledgeOwnerId || null,
|
|
1581
|
-
sessionVisibility: sessionVisibility.normalize(session.sessionVisibility),
|
|
1582
|
-
sessionVisibilityExplicit: session.sessionVisibilityExplicit === true,
|
|
1583
|
-
}, ws);
|
|
1584
|
-
if (forked) {
|
|
1585
|
-
ws._clayActiveSession = forked.localId;
|
|
1586
|
-
sendTo(ws, { type: "fork_complete", sessionId: forked.localId });
|
|
1587
|
-
}
|
|
1588
|
-
});
|
|
1589
|
-
}
|
|
1590
|
-
}).catch(function(e) {
|
|
1591
|
-
sendTo(ws, { type: "error", text: "Fork failed: " + (e.message || e) });
|
|
1439
|
+
sessionHistory.fork(session, msg.uuid, ws, function () {}).then(function (forked) {
|
|
1440
|
+
if (forked) sendTo(ws, { type: "fork_complete", sessionId: forked.localId });
|
|
1441
|
+
}).catch(function (error) {
|
|
1442
|
+
sendTo(ws, { type: "error", text: "Fork failed: " + error.message });
|
|
1592
1443
|
});
|
|
1593
1444
|
return true;
|
|
1594
1445
|
}
|
|
1595
1446
|
|
|
1596
1447
|
if (msg.type === "ask_user_response") {
|
|
1597
1448
|
var session = getSessionForWs(ws);
|
|
1598
|
-
if (session) respondToAskUser(session, msg);
|
|
1449
|
+
if (session) respondToAskUser(session, msg, ws);
|
|
1599
1450
|
return true;
|
|
1600
1451
|
}
|
|
1601
1452
|
|
|
@@ -1638,6 +1489,7 @@ function attachSessions(ctx) {
|
|
|
1638
1489
|
var sessionId = sm.permissionRequestIndex[requestId];
|
|
1639
1490
|
var session = sessionId ? sm.sessions.get(sessionId) : getSessionForWs(ws);
|
|
1640
1491
|
if (!session) return true;
|
|
1492
|
+
if (ws._clayPaneActivation && session.localId !== ws._clayPaneActivation.sessionId) return true;
|
|
1641
1493
|
var pending = session.pendingPermissions[requestId];
|
|
1642
1494
|
if (!pending) return true;
|
|
1643
1495
|
delete sm.permissionRequestIndex[requestId];
|
|
@@ -1803,14 +1655,6 @@ function attachSessions(ctx) {
|
|
|
1803
1655
|
if (msg.type === "browse_dir") {
|
|
1804
1656
|
var rawPath = (msg.path || "").replace(/^~/, require("./config").REAL_HOME);
|
|
1805
1657
|
var absTarget = path.resolve(rawPath);
|
|
1806
|
-
// Multi-user mode: non-admins can only browse their home directory
|
|
1807
|
-
if (osUsers && osUsers.length > 0 && ws._clayUser && ws._clayUser.role !== "admin") {
|
|
1808
|
-
var browseHome = ws._clayUser.linuxUser ? "/home/" + ws._clayUser.linuxUser : null;
|
|
1809
|
-
if (!browseHome || (absTarget !== browseHome && (absTarget + "/").indexOf(browseHome + "/") !== 0)) {
|
|
1810
|
-
sendTo(ws, { type: "browse_dir_result", path: msg.path, entries: [], error: "Access restricted to your home directory" });
|
|
1811
|
-
return true;
|
|
1812
|
-
}
|
|
1813
|
-
}
|
|
1814
1658
|
var parentDir, prefix;
|
|
1815
1659
|
try {
|
|
1816
1660
|
var stat = fs.statSync(absTarget);
|
|
@@ -1827,21 +1671,27 @@ function attachSessions(ctx) {
|
|
|
1827
1671
|
parentDir = path.dirname(absTarget);
|
|
1828
1672
|
prefix = path.basename(absTarget).toLowerCase();
|
|
1829
1673
|
}
|
|
1674
|
+
var canList = function (candidate) { return !opts.canUsePath || opts.canUsePath(ws._clayUser && ws._clayUser.id, candidate); };
|
|
1675
|
+
if (!canList(parentDir)) {
|
|
1676
|
+
sendTo(ws, startReply(msg, { type: "browse_dir_result", path: msg.path, entries: [], error: "Directory access is not permitted" }));
|
|
1677
|
+
return true;
|
|
1678
|
+
}
|
|
1830
1679
|
try {
|
|
1831
1680
|
var dirItems = fs.readdirSync(parentDir, { withFileTypes: true });
|
|
1832
1681
|
var dirEntries = [];
|
|
1833
1682
|
for (var di = 0; di < dirItems.length; di++) {
|
|
1834
1683
|
var d = dirItems[di];
|
|
1835
1684
|
if (!d.isDirectory()) continue;
|
|
1685
|
+
if (opts.canUsePath && !opts.canUsePath(ws._clayUser && ws._clayUser.id, path.join(parentDir, d.name))) continue;
|
|
1836
1686
|
if (d.name.charAt(0) === ".") continue;
|
|
1837
1687
|
if (IGNORED_DIRS.has(d.name)) continue;
|
|
1838
1688
|
if (prefix && !d.name.toLowerCase().startsWith(prefix)) continue;
|
|
1839
1689
|
dirEntries.push({ name: d.name, path: path.join(parentDir, d.name) });
|
|
1840
1690
|
}
|
|
1841
1691
|
dirEntries.sort(function (a, b) { return a.name.localeCompare(b.name); });
|
|
1842
|
-
sendTo(ws, { type: "browse_dir_result", path: msg.path, entries: dirEntries });
|
|
1692
|
+
sendTo(ws, Object.assign(browseMeta(msg, parentDir, prefix, canList), { type: "browse_dir_result", path: msg.path, entries: dirEntries }));
|
|
1843
1693
|
} catch (e) {
|
|
1844
|
-
sendTo(ws, { type: "browse_dir_result", path: msg.path, entries: [], error: e.message });
|
|
1694
|
+
sendTo(ws, startReply(msg, { type: "browse_dir_result", path: msg.path, entries: [], error: e.message }));
|
|
1845
1695
|
}
|
|
1846
1696
|
return true;
|
|
1847
1697
|
}
|
|
@@ -1850,33 +1700,25 @@ function attachSessions(ctx) {
|
|
|
1850
1700
|
if (msg.type === "add_project") {
|
|
1851
1701
|
var addPath = (msg.path || "").replace(/^~/, require("./config").REAL_HOME);
|
|
1852
1702
|
var addAbs = path.resolve(addPath);
|
|
1853
|
-
|
|
1854
|
-
|
|
1855
|
-
|
|
1856
|
-
sendTo(ws, { type: "add_project_result", ok: false, error: "No Linux user assigned" });
|
|
1857
|
-
return true;
|
|
1858
|
-
}
|
|
1859
|
-
var userHome = "/home/" + ws._clayUser.linuxUser;
|
|
1860
|
-
if (addAbs !== userHome && (addAbs + "/").indexOf(userHome + "/") !== 0) {
|
|
1861
|
-
sendTo(ws, { type: "add_project_result", ok: false, error: "Path not allowed. You can only add directories under " + userHome });
|
|
1862
|
-
return true;
|
|
1863
|
-
}
|
|
1703
|
+
if (opts.canUsePath && !opts.canUsePath(ws._clayUser && ws._clayUser.id, addAbs)) {
|
|
1704
|
+
sendTo(ws, startReply(msg, { type: "add_project_result", ok: false, error: "Directory access is not permitted" }));
|
|
1705
|
+
return true;
|
|
1864
1706
|
}
|
|
1865
1707
|
try {
|
|
1866
1708
|
var addStat = fs.statSync(addAbs);
|
|
1867
1709
|
if (!addStat.isDirectory()) {
|
|
1868
|
-
sendTo(ws, { type: "add_project_result", ok: false, error: "Not a directory" });
|
|
1710
|
+
sendTo(ws, startReply(msg, { type: "add_project_result", ok: false, error: "Not a directory" }));
|
|
1869
1711
|
return true;
|
|
1870
1712
|
}
|
|
1871
1713
|
} catch (e) {
|
|
1872
|
-
sendTo(ws, { type: "add_project_result", ok: false, error: "Directory not found" });
|
|
1714
|
+
sendTo(ws, startReply(msg, { type: "add_project_result", ok: false, error: "Directory not found" }));
|
|
1873
1715
|
return true;
|
|
1874
1716
|
}
|
|
1875
1717
|
if (typeof opts.onAddProject === "function") {
|
|
1876
1718
|
var result = opts.onAddProject(addAbs, ws._clayUser);
|
|
1877
|
-
sendTo(ws,
|
|
1719
|
+
sendTo(ws, startReply(msg, Object.assign({}, result, { type: "add_project_result" })));
|
|
1878
1720
|
} else {
|
|
1879
|
-
sendTo(ws, { type: "add_project_result", ok: false, error: "Not supported" });
|
|
1721
|
+
sendTo(ws, startReply(msg, { type: "add_project_result", ok: false, error: "Not supported" }));
|
|
1880
1722
|
}
|
|
1881
1723
|
return true;
|
|
1882
1724
|
}
|
|
@@ -1886,7 +1728,7 @@ function attachSessions(ctx) {
|
|
|
1886
1728
|
if (ws._clayUser) {
|
|
1887
1729
|
var cpPerms = usersModule.getEffectivePermissions(ws._clayUser, osUsers);
|
|
1888
1730
|
if (!cpPerms.createProject) {
|
|
1889
|
-
sendTo(ws, { type: "add_project_result", ok: false, error: "You do not have permission to create projects" });
|
|
1731
|
+
sendTo(ws, startReply(msg, { type: "add_project_result", ok: false, error: "You do not have permission to create projects" }));
|
|
1890
1732
|
return true;
|
|
1891
1733
|
}
|
|
1892
1734
|
}
|
|
@@ -1894,14 +1736,14 @@ function attachSessions(ctx) {
|
|
|
1894
1736
|
if (msg.type === "create_project") {
|
|
1895
1737
|
var createName = (msg.name || "").trim();
|
|
1896
1738
|
if (!createName || !/^[a-zA-Z0-9_-]+$/.test(createName)) {
|
|
1897
|
-
sendTo(ws, { type: "add_project_result", ok: false, error: "Invalid name. Use only letters, numbers, dashes, and underscores." });
|
|
1739
|
+
sendTo(ws, startReply(msg, { type: "add_project_result", ok: false, error: "Invalid name. Use only letters, numbers, dashes, and underscores." }));
|
|
1898
1740
|
return true;
|
|
1899
1741
|
}
|
|
1900
1742
|
if (typeof opts.onCreateProject === "function") {
|
|
1901
1743
|
var createResult = opts.onCreateProject(createName, ws._clayUser);
|
|
1902
|
-
sendTo(ws,
|
|
1744
|
+
sendTo(ws, startReply(msg, Object.assign({}, createResult, { type: "add_project_result" })));
|
|
1903
1745
|
} else {
|
|
1904
|
-
sendTo(ws, { type: "add_project_result", ok: false, error: "Not supported" });
|
|
1746
|
+
sendTo(ws, startReply(msg, { type: "add_project_result", ok: false, error: "Not supported" }));
|
|
1905
1747
|
}
|
|
1906
1748
|
return true;
|
|
1907
1749
|
}
|
|
@@ -1910,16 +1752,16 @@ function attachSessions(ctx) {
|
|
|
1910
1752
|
if (msg.type === "clone_project") {
|
|
1911
1753
|
var cloneUrl = (msg.url || "").trim();
|
|
1912
1754
|
if (!cloneUrl || (!/^https?:\/\//.test(cloneUrl) && !/^git@/.test(cloneUrl))) {
|
|
1913
|
-
sendTo(ws, { type: "add_project_result", ok: false, error: "Invalid URL. Use https:// or git@ format." });
|
|
1755
|
+
sendTo(ws, startReply(msg, { type: "add_project_result", ok: false, error: "Invalid URL. Use https:// or git@ format." }));
|
|
1914
1756
|
return true;
|
|
1915
1757
|
}
|
|
1916
|
-
sendTo(ws, { type: "clone_project_progress", status: "cloning" });
|
|
1758
|
+
sendTo(ws, startReply(msg, { type: "clone_project_progress", status: "cloning" }));
|
|
1917
1759
|
if (typeof opts.onCloneProject === "function") {
|
|
1918
1760
|
opts.onCloneProject(cloneUrl, ws._clayUser, function (cloneResult) {
|
|
1919
|
-
sendTo(ws, { type: "add_project_result", ok: cloneResult.ok, slug: cloneResult.slug, error: cloneResult.error });
|
|
1761
|
+
sendTo(ws, startReply(msg, { type: "add_project_result", ok: cloneResult.ok, slug: cloneResult.slug, error: cloneResult.error }));
|
|
1920
1762
|
});
|
|
1921
1763
|
} else {
|
|
1922
|
-
sendTo(ws, { type: "add_project_result", ok: false, error: "Not supported" });
|
|
1764
|
+
sendTo(ws, startReply(msg, { type: "add_project_result", ok: false, error: "Not supported" }));
|
|
1923
1765
|
}
|
|
1924
1766
|
return true;
|
|
1925
1767
|
}
|
|
@@ -1989,10 +1831,10 @@ function attachSessions(ctx) {
|
|
|
1989
1831
|
moveAllSchedulesToProject(removeSlug, msg.moveTasksTo);
|
|
1990
1832
|
}
|
|
1991
1833
|
if (typeof opts.onRemoveProject === "function") {
|
|
1992
|
-
// Send result before removing so the WS is still open
|
|
1993
|
-
sendTo(ws, { type: "remove_project_result", ok: true, slug: removeSlug });
|
|
1994
1834
|
var removeUserId = ws._clayUser ? ws._clayUser.id : null;
|
|
1995
|
-
opts.onRemoveProject(removeSlug, removeUserId);
|
|
1835
|
+
Promise.resolve().then(function () { return opts.onRemoveProject(removeSlug, removeUserId); }).then(function (result) {
|
|
1836
|
+
sendTo(ws, { type: "remove_project_result", ok: !!result && result.ok === true, slug: removeSlug, error: result && result.error });
|
|
1837
|
+
}, function (error) { sendTo(ws, { type: "remove_project_result", ok: false, slug: removeSlug, error: error.message }); });
|
|
1996
1838
|
} else {
|
|
1997
1839
|
sendTo(ws, { type: "remove_project_result", ok: false, error: "Not supported" });
|
|
1998
1840
|
}
|
|
@@ -2032,30 +1874,41 @@ function attachSessions(ctx) {
|
|
|
2032
1874
|
|
|
2033
1875
|
// --- Set project title (rename) ---
|
|
2034
1876
|
if (msg.type === "set_project_title") {
|
|
1877
|
+
var titleRequestId = boundedRequestId(msg);
|
|
2035
1878
|
if (!msg.slug) {
|
|
2036
|
-
sendTo(ws, { type: "set_project_title_result", ok: false, error: "Missing slug" });
|
|
1879
|
+
sendTo(ws, { type: "set_project_title_result", ok: false, error: "Missing slug", requestId: titleRequestId });
|
|
1880
|
+
return true;
|
|
1881
|
+
}
|
|
1882
|
+
// The target is named by the client; it must be a project this account can access.
|
|
1883
|
+
if (!canAccessProjectSlug(ws, msg.slug)) {
|
|
1884
|
+
sendTo(ws, { type: "set_project_title_result", ok: false, error: "Project access is not permitted", slug: msg.slug, requestId: titleRequestId });
|
|
2037
1885
|
return true;
|
|
2038
1886
|
}
|
|
2039
1887
|
if (typeof opts.onSetProjectTitle === "function") {
|
|
2040
1888
|
var titleResult = opts.onSetProjectTitle(msg.slug, msg.title || null);
|
|
2041
|
-
sendTo(ws, { type: "set_project_title_result",
|
|
1889
|
+
sendTo(ws, Object.assign({}, titleResult, { type: "set_project_title_result", slug: msg.slug, requestId: titleRequestId }));
|
|
2042
1890
|
} else {
|
|
2043
|
-
sendTo(ws, { type: "set_project_title_result", ok: false, error: "Not supported" });
|
|
1891
|
+
sendTo(ws, { type: "set_project_title_result", ok: false, error: "Not supported", requestId: titleRequestId });
|
|
2044
1892
|
}
|
|
2045
1893
|
return true;
|
|
2046
1894
|
}
|
|
2047
1895
|
|
|
2048
1896
|
// --- Set project icon (emoji) ---
|
|
2049
1897
|
if (msg.type === "set_project_icon") {
|
|
1898
|
+
var iconRequestId = boundedRequestId(msg);
|
|
2050
1899
|
if (!msg.slug) {
|
|
2051
|
-
sendTo(ws, { type: "set_project_icon_result", ok: false, error: "Missing slug" });
|
|
1900
|
+
sendTo(ws, { type: "set_project_icon_result", ok: false, error: "Missing slug", requestId: iconRequestId });
|
|
1901
|
+
return true;
|
|
1902
|
+
}
|
|
1903
|
+
if (!canAccessProjectSlug(ws, msg.slug)) {
|
|
1904
|
+
sendTo(ws, { type: "set_project_icon_result", ok: false, error: "Project access is not permitted", slug: msg.slug, requestId: iconRequestId });
|
|
2052
1905
|
return true;
|
|
2053
1906
|
}
|
|
2054
1907
|
if (typeof opts.onSetProjectIcon === "function") {
|
|
2055
1908
|
var iconResult = opts.onSetProjectIcon(msg.slug, msg.icon || null);
|
|
2056
|
-
sendTo(ws, { type: "set_project_icon_result", ok: iconResult.ok, slug: msg.slug, error: iconResult.error });
|
|
1909
|
+
sendTo(ws, { type: "set_project_icon_result", ok: iconResult.ok, slug: msg.slug, error: iconResult.error, requestId: iconRequestId });
|
|
2057
1910
|
} else {
|
|
2058
|
-
sendTo(ws, { type: "set_project_icon_result", ok: false, error: "Not supported" });
|
|
1911
|
+
sendTo(ws, { type: "set_project_icon_result", ok: false, error: "Not supported", requestId: iconRequestId });
|
|
2059
1912
|
}
|
|
2060
1913
|
return true;
|
|
2061
1914
|
}
|
|
@@ -2100,7 +1953,7 @@ function attachSessions(ctx) {
|
|
|
2100
1953
|
var galManaged = [];
|
|
2101
1954
|
var galUser = [];
|
|
2102
1955
|
try {
|
|
2103
|
-
var galInstaller = require("./claude-hook-installer");
|
|
1956
|
+
var galInstaller = require("./yoke/claude-hook-installer");
|
|
2104
1957
|
galManaged = galInstaller.CLAY_MANAGED_ALLOW || [];
|
|
2105
1958
|
} catch (e) {}
|
|
2106
1959
|
if (galUid) {
|
|
@@ -2126,7 +1979,7 @@ function attachSessions(ctx) {
|
|
|
2126
1979
|
// home (OS-mode: getent passwd; single-user: os.homedir()).
|
|
2127
1980
|
var salEffective = false;
|
|
2128
1981
|
try {
|
|
2129
|
-
var salInstaller = require("./claude-hook-installer");
|
|
1982
|
+
var salInstaller = require("./yoke/claude-hook-installer");
|
|
2130
1983
|
var salHome = null;
|
|
2131
1984
|
if (osUsers && ws._clayUser && ws._clayUser.linuxUser) {
|
|
2132
1985
|
try {
|
|
@@ -2181,6 +2034,18 @@ function attachSessions(ctx) {
|
|
|
2181
2034
|
}
|
|
2182
2035
|
|
|
2183
2036
|
return {
|
|
2037
|
+
invalidateVendorUsage: function () { vendorUsage.invalidateAll(); },
|
|
2038
|
+
// Canonical read-only inspection: the caller has already proven the owner and
|
|
2039
|
+
// project access; the OS user is re-derived from the live user record.
|
|
2040
|
+
readVendorUsage: function (request) {
|
|
2041
|
+
var installed = null;
|
|
2042
|
+
if (Array.isArray(sm.installedVendors)) {
|
|
2043
|
+
installed = Object.create(null);
|
|
2044
|
+
sm.installedVendors.forEach(function (vendor) { installed[vendor] = true; });
|
|
2045
|
+
}
|
|
2046
|
+
var linuxUser = osUsers && request.owner !== "default" ? ctx.getLinuxUserForSession({ ownerId: request.owner }) : null;
|
|
2047
|
+
return vendorUsage.readForOwner({ owner: request.owner, linuxUser: linuxUser, installed: installed, isCurrent: request.isCurrent });
|
|
2048
|
+
},
|
|
2184
2049
|
handleSessionsMessage: handleSessionsMessage,
|
|
2185
2050
|
resolveSessionForView: resolveSessionForView,
|
|
2186
2051
|
sendSessionFoldersState: sessionFolders.sendStateTo,
|
|
@@ -2192,6 +2057,11 @@ function attachSessions(ctx) {
|
|
|
2192
2057
|
return handleSessionsMessage(ws, { type: "permission_response", requestId: msg.requestId, decision: msg.decision });
|
|
2193
2058
|
},
|
|
2194
2059
|
stopHomeSession: stopSession,
|
|
2060
|
+
sessionActions: sessionActions,
|
|
2061
|
+
sessionHistoryActions: sessionHistory,
|
|
2062
|
+
sessionVendorActions: sessionVendor,
|
|
2063
|
+
sessionRuntimeActions: sessionRuntime,
|
|
2064
|
+
deleteProductControlPlan: function (plan) { sessionDelete.executeOwnedDeletion(plan); },
|
|
2195
2065
|
};
|
|
2196
2066
|
}
|
|
2197
2067
|
|