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/server-home-chat.js
CHANGED
|
@@ -31,7 +31,7 @@ function attachHomeChat(deps) {
|
|
|
31
31
|
}
|
|
32
32
|
if (!mateId && allMates[i].builtinKey === "clay") mate = allMates[i];
|
|
33
33
|
}
|
|
34
|
-
if (!mate) return null;
|
|
34
|
+
if (!mate || mate.lifecycleDeletion) return null;
|
|
35
35
|
var slug = "mate-" + mate.id;
|
|
36
36
|
if (!projects.has(slug)) {
|
|
37
37
|
if (!ensureRegistered) return null;
|
|
@@ -123,6 +123,7 @@ function attachHomeChat(deps) {
|
|
|
123
123
|
model: sessionString(session.model, 240),
|
|
124
124
|
createdAt: createdAt,
|
|
125
125
|
lastActivity: lastActivity,
|
|
126
|
+
sessionOriginId: session.sessionOriginId || null,
|
|
126
127
|
isProcessing: !!session.isProcessing,
|
|
127
128
|
sessionRole: hierarchy[session.localId].role,
|
|
128
129
|
parentSessionId: hierarchy[session.localId].parentSessionId == null ? null : sessionReference(sessionManager.sessions.get(hierarchy[session.localId].parentSessionId)),
|
|
@@ -184,6 +185,12 @@ function attachHomeChat(deps) {
|
|
|
184
185
|
}
|
|
185
186
|
});
|
|
186
187
|
if (!unsubscribe) return;
|
|
188
|
+
var unregisterConsent = null;
|
|
189
|
+
if (openedSession && typeof found.ctx.registerMcpConsentViewer === 'function') {
|
|
190
|
+
try { unregisterConsent = found.ctx.registerMcpConsentViewer(ws, openedSession); } catch (error) {}
|
|
191
|
+
}
|
|
192
|
+
var unsubscribeEvents = unsubscribe;
|
|
193
|
+
unsubscribe = function () { if (unregisterConsent) unregisterConsent(); unsubscribeEvents(); };
|
|
187
194
|
ws[tapKey] = {
|
|
188
195
|
unsubscribe: unsubscribe,
|
|
189
196
|
sessionId: sessionId,
|
|
@@ -222,6 +229,7 @@ function attachHomeChat(deps) {
|
|
|
222
229
|
var homeDebates = attachHomeDebates({ mates: mates, findMateProject: findMateProject, ownsSession: ownsSession, sessionReference: sessionReference, sendMessage: sendMessage });
|
|
223
230
|
var homeClaySessionLinks = attachHomeClaySessionLinks({
|
|
224
231
|
projects: projects,
|
|
232
|
+
findMateProject: findMateProject, ownsSession: ownsSession, isActorLive: isActorLive,
|
|
225
233
|
workspaceQueryService: deps.workspaceQueryService,
|
|
226
234
|
projectLogsService: deps.projectLogsService,
|
|
227
235
|
sendMessage: sendMessage,
|
|
@@ -238,7 +246,7 @@ function attachHomeChat(deps) {
|
|
|
238
246
|
requestId: requestId || null,
|
|
239
247
|
model: session.model || null,
|
|
240
248
|
vendor: session.vendor || null,
|
|
241
|
-
messages: historyToHomeChat(session.history || [], session.debateSetupMode === true, session.mateCreationMode === true),
|
|
249
|
+
messages: historyToHomeChat(session.history || [], session.debateSetupMode === true, session.mateCreationMode === true, session.pendingAskUser),
|
|
242
250
|
isProcessing: session.isProcessing === true,
|
|
243
251
|
};
|
|
244
252
|
if (session.homeClayEntryMode === "search") {
|
|
@@ -293,7 +301,10 @@ function attachHomeChat(deps) {
|
|
|
293
301
|
homeModels: homeModels, isActorLive: isActorLive, persistActiveSession: persistActiveSession,
|
|
294
302
|
});
|
|
295
303
|
var homeMateCreation = attachHomeMateCreation({ findMateProject: findMateProject, resolveHomeSession: resolveHomeSession, sessionReference: sessionReference, setupTap: setupTap, sendHistory: sendHistory, sendSessionList: sendSessionList, sendError: sendError, sendModelError: sendModelError, homeModels: homeModels, isActorLive: isActorLive, persistActiveSession: persistActiveSession });
|
|
296
|
-
var
|
|
304
|
+
var homeMcpConsent = require('./server-home-mcp-consent').attachHomeMcpConsent({ findMateProject: findMateProject, resolveHomeSession: resolveHomeSession, messageTap: messageTap, isActorLive: isActorLive, sendError: sendError });
|
|
305
|
+
var homeClayEntry = attachHomeClayEntry({ findMateProject: findMateProject, ownsSession: ownsSession, sessionReference: sessionReference, setupSearchTap: setupSearchTap, sendHistory: sendHistory, sendSessionList: sendSessionList, sendError: sendError, sendModelError: sendModelError, sendMessage: sendMessage, homeModels: homeModels, isActorLive: isActorLive });
|
|
306
|
+
|
|
307
|
+
var contextualSessions = require('./server-contextual-mate-sessions').attachContextualMateSessions({ findMateProject: findMateProject, ownsSession: ownsSession, resolveHomeSession: resolveHomeSession, listHomeSessions: listHomeSessions, isActorLive: isActorLive, homeModels: homeModels, sendMessage: sendMessage });
|
|
297
308
|
|
|
298
309
|
async function openExactSession(ws, found, userId, selected, msg) {
|
|
299
310
|
await ensureSessionModel(ws, found, userId, selected, null);
|
|
@@ -397,20 +408,8 @@ function attachHomeChat(deps) {
|
|
|
397
408
|
historyError.sessionId = sessionReference(activeSession);
|
|
398
409
|
throw historyError;
|
|
399
410
|
}
|
|
400
|
-
sessionManager.sendAndRecord(activeSession, { type: "user_message", text: text });
|
|
401
411
|
try {
|
|
402
|
-
|
|
403
|
-
activeSession.isProcessing = true;
|
|
404
|
-
activeSession.sentToolResults = {};
|
|
405
|
-
if (typeof options.onRecorded === "function") options.onRecorded(activeSession);
|
|
406
|
-
if (!activeSession.queryInstance && (!activeSession.worker || activeSession.messageQueue !== "worker")) {
|
|
407
|
-
sdk.startQuery(activeSession, options.queryText || text, null, null);
|
|
408
|
-
} else {
|
|
409
|
-
sdk.pushMessage(activeSession, options.queryText || text, null);
|
|
410
|
-
}
|
|
411
|
-
} else {
|
|
412
|
-
sdk.pushMessage(activeSession, options.queryText || text, null);
|
|
413
|
-
}
|
|
412
|
+
await require('./mate-message-delivery').deliver({ sm: sessionManager, sdk: sdk }, activeSession, text, options);
|
|
414
413
|
} catch (error) {
|
|
415
414
|
error.sessionId = sessionReference(activeSession);
|
|
416
415
|
throw error;
|
|
@@ -418,7 +417,7 @@ function attachHomeChat(deps) {
|
|
|
418
417
|
return sessionReferenceValue;
|
|
419
418
|
}
|
|
420
419
|
|
|
421
|
-
function handleMessage(ws, msg) {
|
|
420
|
+
function handleMessage(ws, msg, routedProjectSlug) {
|
|
422
421
|
if (!msg || typeof msg.type !== "string") return false;
|
|
423
422
|
if (msg.type === "home_mate_stop" || msg.type === "home_mate_permission_response") {
|
|
424
423
|
var controlUserId = ws._clayUser ? ws._clayUser.id : null;
|
|
@@ -449,10 +448,12 @@ function attachHomeChat(deps) {
|
|
|
449
448
|
}
|
|
450
449
|
return true;
|
|
451
450
|
}
|
|
452
|
-
if (msg.type !== "issue_reference_resolve" && msg.type !== "home_debates_list" && msg.type !== "home_clay_ask" && msg.type !== "home_clay_session_resolve" && msg.type !== "home_clay_log_resolve" && msg.type !== "home_mate_present" && msg.type !== "home_mate_open" && msg.type !== "home_mate_sessions_list" && msg.type !== "home_mate_session_open" && msg.type !== "home_mate_send" && msg.type !== "home_mate_new_session" && msg.type !== "home_mate_debate_plan" && msg.type !== "home_debate_proposal_response" && msg.type !== "home_debate_question_response" && msg.type !== "home_debate_control" && msg.type !== "home_mate_creation_plan" && msg.type !== "home_mate_creation_question_response" && msg.type !== "home_mate_creation_proposal_response" && msg.type !== "home_mate_close" && msg.type !== "home_mate_memory_list" && msg.type !== "home_mate_knowledge_list" && msg.type !== "home_mate_models_get" && msg.type !== "home_mate_model_set") {
|
|
451
|
+
if (msg.type !== "issue_reference_resolve" && msg.type !== "home_debates_list" && msg.type !== "home_clay_ask" && msg.type !== "home_clay_session_resolve" && msg.type !== "home_clay_log_resolve" && msg.type !== "home_mate_present" && msg.type !== "home_mate_open" && msg.type !== "home_mate_sessions_list" && msg.type !== "home_mate_session_open" && msg.type !== "home_mate_send" && msg.type !== "home_mate_new_session" && msg.type !== "home_mate_debate_plan" && msg.type !== "home_debate_proposal_response" && msg.type !== "home_mcp_import_response" && msg.type !== "home_mate_question_response" && msg.type !== "home_debate_question_response" && msg.type !== "home_debate_control" && msg.type !== "home_mate_creation_plan" && msg.type !== "home_mate_creation_question_response" && msg.type !== "home_mate_creation_proposal_response" && msg.type !== "home_mate_close" && msg.type !== "home_mate_memory_list" && msg.type !== "home_mate_knowledge_list" && msg.type !== "home_mate_models_get" && msg.type !== "home_mate_model_set") {
|
|
453
452
|
return false;
|
|
454
453
|
}
|
|
455
454
|
|
|
455
|
+
if (contextualSessions.handle(ws, ws._clayUser ? ws._clayUser.id : null, msg)) return true;
|
|
456
|
+
|
|
456
457
|
if (msg.type === "home_mate_present") {
|
|
457
458
|
ws._homeChatPresented = msg.visible === true;
|
|
458
459
|
return true;
|
|
@@ -474,11 +475,12 @@ function attachHomeChat(deps) {
|
|
|
474
475
|
return true;
|
|
475
476
|
}
|
|
476
477
|
|
|
478
|
+
if (msg.type === "home_mcp_import_response" || msg.type === "home_mate_question_response") { homeMcpConsent.respond(ws, userId, msg); return true; }
|
|
477
479
|
if (msg.type === "issue_reference_resolve") { resolveIssueLink(ws, msg); return true; }
|
|
478
480
|
if (homeDebates.handle(ws, userId, msg)) return true;
|
|
479
481
|
if (msg.type === "home_clay_ask") { homeClayEntry.start(ws, userId, msg); return true; }
|
|
480
|
-
if (msg.type === "home_clay_session_resolve") { homeClaySessionLinks.resolve(ws, msg); return true; }
|
|
481
|
-
if (msg.type === "home_clay_log_resolve") { homeClaySessionLinks.resolveLog(ws, msg); return true; }
|
|
482
|
+
if (msg.type === "home_clay_session_resolve") { homeClaySessionLinks.resolve(ws, msg, routedProjectSlug); return true; }
|
|
483
|
+
if (msg.type === "home_clay_log_resolve") { homeClaySessionLinks.resolveLog(ws, msg, routedProjectSlug); return true; }
|
|
482
484
|
|
|
483
485
|
if (msg.type === "home_mate_debate_plan") {
|
|
484
486
|
homeDebate.start(ws, userId, msg);
|
|
@@ -15,10 +15,12 @@ function attachHomeClayEntry(ctx) {
|
|
|
15
15
|
}
|
|
16
16
|
|
|
17
17
|
async function start(ws, userId, msg) {
|
|
18
|
+
var contextual = msg.presentation === 'contextual';
|
|
18
19
|
var text = typeof msg.text === "string" ? msg.text.replace(/[\u0000-\u001f\u007f]/g, " ").trim().slice(0, 12000) : "";
|
|
19
20
|
var requestId = typeof msg.requestId === "string" ? msg.requestId.slice(0, 240) : null;
|
|
21
|
+
if (ctx.isActorLive && !ctx.isActorLive(ws, userId)) { ctx.sendError(ws, null, 'Your account is no longer available.', requestId, null, 'actor_unavailable'); return; }
|
|
20
22
|
var found = ctx.findMateProject(userId, null, true);
|
|
21
|
-
if (!found || found.mate.builtinKey !== "clay") {
|
|
23
|
+
if (!found || found.mate.builtinKey !== "clay" || found.mate.archived || ctx.isActorLive && !ctx.isActorLive(ws, userId)) {
|
|
22
24
|
ctx.sendError(ws, null, "Clay is not available.", requestId, null, "mate_unavailable");
|
|
23
25
|
return;
|
|
24
26
|
}
|
|
@@ -27,26 +29,43 @@ function attachHomeClayEntry(ctx) {
|
|
|
27
29
|
return;
|
|
28
30
|
}
|
|
29
31
|
var manager = found.ctx.getSessionManager();
|
|
32
|
+
var mateStamp = JSON.stringify([found.mate.id, found.mate.createdAt || null, found.mate.createdBy || null]);
|
|
30
33
|
if (!manager || typeof manager.sendAndRecord !== "function") {
|
|
31
34
|
ctx.sendError(ws, found.mate.id, "Conversation history is unavailable.", requestId, null, "session_unavailable");
|
|
32
35
|
return;
|
|
33
36
|
}
|
|
34
37
|
var existing = findExisting(manager, userId, requestId);
|
|
35
38
|
if (existing) {
|
|
39
|
+
if (contextual) {
|
|
40
|
+
if (existing.homeClayEntryMode !== 'contextual' || existing.homeClayEntryText !== text || msg.sessionOriginId && msg.sessionOriginId !== existing.sessionOriginId) { ctx.sendError(ws, found.mate.id, 'This request belongs to a different conversation.', requestId, null, 'request_mismatch'); return; }
|
|
41
|
+
ctx.sendMessage(ws, { type: 'home_clay_contextual_session', requestId: requestId, mateId: found.mate.id, sessionId: existing.localId, sessionOriginId: existing.sessionOriginId }); return;
|
|
42
|
+
}
|
|
36
43
|
ctx.setupSearchTap(ws, found, existing.localId, requestId);
|
|
37
44
|
ctx.sendHistory(ws, found, existing, requestId);
|
|
38
45
|
ctx.sendSessionList(ws, found, userId);
|
|
39
46
|
return;
|
|
40
47
|
}
|
|
48
|
+
if (contextual && msg.sessionOriginId) { ctx.sendError(ws, found.mate.id, 'This new conversation is no longer available. Start a new Ask.', requestId, null, 'session_unavailable'); return; }
|
|
41
49
|
var session = null;
|
|
42
50
|
try {
|
|
43
51
|
var resolved = await ctx.homeModels.resolveMateModel(ws, found, userId);
|
|
44
52
|
if (ctx.isActorLive && !ctx.isActorLive(ws, userId)) throw new Error("Your account is no longer available.");
|
|
45
53
|
var liveFound = ctx.findMateProject(userId, null, true);
|
|
46
|
-
if (!liveFound || liveFound.ctx !== found.ctx || !liveFound.mate || liveFound.mate.builtinKey !== "clay") throw new Error("Clay is no longer available.");
|
|
47
|
-
|
|
54
|
+
if (!liveFound || liveFound.ctx !== found.ctx || !liveFound.mate || liveFound.ctx.getSessionManager() !== manager || liveFound.mate.builtinKey !== "clay" || JSON.stringify([liveFound.mate.id, liveFound.mate.createdAt || null, liveFound.mate.createdBy || null]) !== mateStamp || liveFound.mate.archived) throw new Error("Clay is no longer available.");
|
|
55
|
+
// Another request may have completed while model resolution was awaiting.
|
|
56
|
+
if (findExisting(manager, userId, requestId)) return start(ws, userId, msg);
|
|
57
|
+
var options = { ownerId: userId, vendor: resolved.vendor, model: resolved.model, effort: resolved.effort || null };
|
|
58
|
+
// Background creation must not switch any existing pane/native writer.
|
|
59
|
+
session = contextual ? manager.createSessionRaw(options) : manager.createSession(options, null);
|
|
48
60
|
session.homeClayEntryRequestId = requestId;
|
|
49
|
-
session.homeClayEntryMode =
|
|
61
|
+
session.homeClayEntryMode = contextual ? 'contextual' : 'search';
|
|
62
|
+
if (contextual) {
|
|
63
|
+
session.homeClayEntryText = text;
|
|
64
|
+
session.title = text.slice(0, 80);
|
|
65
|
+
manager.saveSessionFile(session);
|
|
66
|
+
ctx.sendMessage(ws, { type: 'home_clay_contextual_session', requestId: requestId, mateId: found.mate.id, sessionId: session.localId, sessionOriginId: session.sessionOriginId });
|
|
67
|
+
return;
|
|
68
|
+
}
|
|
50
69
|
manager.sendAndRecord(session, { type: "user_message", text: text });
|
|
51
70
|
session.isProcessing = true;
|
|
52
71
|
session.sentToolResults = {};
|
|
@@ -2,23 +2,43 @@
|
|
|
2
2
|
// owner-bound source session.
|
|
3
3
|
|
|
4
4
|
function attachHomeClaySessionLinks(ctx) {
|
|
5
|
-
function source(ws, msg) {
|
|
5
|
+
function source(ws, msg, routedProjectSlug) {
|
|
6
|
+
if (Object.prototype.hasOwnProperty.call(msg, "contextualSource")) {
|
|
7
|
+
var hint = msg.contextualSource, userId = ws && ws._clayUser && ws._clayUser.id;
|
|
8
|
+
if (!hint || typeof hint.mateId !== "string" || !Number.isSafeInteger(hint.sessionId) || typeof hint.sessionOriginId !== "string" || typeof hint.mateStamp !== "string" || !ctx.isActorLive || !ctx.isActorLive(ws, userId)) return {};
|
|
9
|
+
var found = ctx.findMateProject && ctx.findMateProject(userId, hint.mateId, false);
|
|
10
|
+
if (!found || found.mate.archived || found.mate.lifecycleDeletion || found.mate.createdBy && found.mate.createdBy !== userId) return {};
|
|
11
|
+
var stamp = JSON.stringify([found.mate.id, found.mate.createdBy || null, found.mate.createdAt || null, found.mate.builtinKey || null]);
|
|
12
|
+
if (stamp !== hint.mateStamp || ctx.projects.get(found.slug) !== found.ctx) return {};
|
|
13
|
+
var manager = found.ctx.getSessionManager && found.ctx.getSessionManager();
|
|
14
|
+
var session = manager && manager.sessions.get(hint.sessionId);
|
|
15
|
+
if (!ctx.ownsSession(session, userId) || session.sessionOriginId !== hint.sessionOriginId) return {};
|
|
16
|
+
return { tap: { mateSlug: found.slug, mateId: found.mate.id, sessionId: hint.sessionId }, project: found.ctx, session: session };
|
|
17
|
+
}
|
|
6
18
|
var tap = msg.surface === "search" ? ws._searchClayTap : ws._homeChatTap;
|
|
19
|
+
if (!tap && routedProjectSlug) {
|
|
20
|
+
var routedProject = ctx.projects.get(routedProjectSlug);
|
|
21
|
+
var routedManager = routedProject && routedProject.getSessionManager ? routedProject.getSessionManager() : null;
|
|
22
|
+
var routedSession = routedManager && ws._clayActiveSession ? routedManager.sessions.get(ws._clayActiveSession) : null;
|
|
23
|
+
return { tap: { mateSlug: routedProjectSlug, sessionId: ws._clayActiveSession }, project: routedProject, session: routedSession };
|
|
24
|
+
}
|
|
7
25
|
var sourceProject = tap && tap.mateSlug ? ctx.projects.get(tap.mateSlug) : null;
|
|
8
26
|
var sourceManager = sourceProject && sourceProject.getSessionManager ? sourceProject.getSessionManager() : null;
|
|
9
27
|
var sourceSession = sourceManager && tap ? sourceManager.sessions.get(tap.sessionId) : null;
|
|
10
28
|
return { tap: tap, project: sourceProject, session: sourceSession };
|
|
11
29
|
}
|
|
12
30
|
|
|
13
|
-
function resolve(ws, msg) {
|
|
14
|
-
var selected = source(ws, msg);
|
|
15
|
-
var bound = ctx.workspaceQueryService && selected.session
|
|
16
|
-
? ctx.workspaceQueryService.bindProjectSession({ projectSlug: selected.tap.mateSlug, session: selected.session })
|
|
17
|
-
: null;
|
|
31
|
+
function resolve(ws, msg, routedProjectSlug) {
|
|
32
|
+
var selected = source(ws, msg, routedProjectSlug);
|
|
18
33
|
var payload = { type: "home_clay_session_target", requestId: msg.requestId || null, sessionRef: msg.sessionRef || null, status: "error" };
|
|
19
34
|
try {
|
|
35
|
+
var binding = selected.session ? { projectSlug: selected.tap.mateSlug, session: selected.session } : null;
|
|
36
|
+
if (binding && ws && ws._clayUser) binding.viewerId = ws._clayUser.id;
|
|
37
|
+
var bound = ctx.workspaceQueryService && binding
|
|
38
|
+
? ctx.workspaceQueryService.bindProjectSession(binding)
|
|
39
|
+
: null;
|
|
20
40
|
if (!bound) throw new Error("The source conversation is no longer available.");
|
|
21
|
-
payload.target = bound.resolveSessionNavigation({ sessionRef: msg.sessionRef });
|
|
41
|
+
payload.target = bound.resolveSessionNavigation({ sessionRef: msg.sessionRef, entryIndex: msg.entryIndex });
|
|
22
42
|
payload.status = "ready";
|
|
23
43
|
} catch (error) {
|
|
24
44
|
payload.error = error.message || "Session not available.";
|
|
@@ -26,8 +46,8 @@ function attachHomeClaySessionLinks(ctx) {
|
|
|
26
46
|
ctx.sendMessage(ws, payload);
|
|
27
47
|
}
|
|
28
48
|
|
|
29
|
-
function resolveLog(ws, msg) {
|
|
30
|
-
var selected = source(ws, msg);
|
|
49
|
+
function resolveLog(ws, msg, routedProjectSlug) {
|
|
50
|
+
var selected = source(ws, msg, routedProjectSlug);
|
|
31
51
|
var status = selected.project && selected.project.getStatus ? selected.project.getStatus() : null;
|
|
32
52
|
var bound = ctx.projectLogsService && selected.session && status
|
|
33
53
|
? ctx.projectLogsService.bindMate({
|
|
@@ -18,6 +18,7 @@ var INITIATION_PROMPT = [
|
|
|
18
18
|
"Before the user answers again, your first and only action must be the next most useful AskUserQuestion. Before presenting it, do not use Bash, Read, Glob, Grep, workspace history, general knowledge, or any other inspection tool, and do not add a preface.",
|
|
19
19
|
"When that tool returns the user's answer, continue the interview normally. Inspect only bounded context that is directly relevant to what the user supplied, and do not bulk-read knowledge files.",
|
|
20
20
|
"Then explore the working relationship, recurring activities and context, communication preferences, autonomy, boundaries, and escalation behavior. Use grounded choices only when helpful. Every three to five exchanges, briefly summarize what you understand inside the next question and let the user correct it.",
|
|
21
|
+
"If the user explicitly asks the future Mate to send a scheduled message, collect the message and exact local date/time, timezone, and repetition only through one focused structured question at a time. Treat it as optional schedule intent: never create or register a job during this interview; include it only in propose_mate after reviewing it with the user.",
|
|
21
22
|
"Choose the Mate's name last. Do not write files and do not create or update a Mate directly.",
|
|
22
23
|
"When the identity is complete, end only by calling propose_mate with a concise public bio, structured preferences, and a complete first-person identityMarkdown. Do not emit a normal assistant preface or conclusion.",
|
|
23
24
|
].join("\n");
|
|
@@ -0,0 +1,14 @@
|
|
|
1
|
+
// Home transcript responses retain the project's server-owned consent request.
|
|
2
|
+
function attachHomeMcpConsent(ctx) {
|
|
3
|
+
function respond(ws, userId, msg) {
|
|
4
|
+
var found = ctx.findMateProject(userId, msg.mateId || null, false);
|
|
5
|
+
var session = found && ctx.resolveHomeSession(found, userId, msg.sessionId);
|
|
6
|
+
var tap = ctx.messageTap(ws, msg), pending = session && session.pendingAskUser && session.pendingAskUser[msg.toolId];
|
|
7
|
+
if (!ctx.isActorLive(ws, userId) || !found || !session || !tap || tap.mateSlug !== found.slug || tap.sessionId !== session.localId || (tap.requestId || null) !== (msg.requestId || null) || !pending || !pending.request || ['mcp-import', 'mate-schedule', 'mcp_fallback', 'product-control'].indexOf(pending.request.source) < 0) {
|
|
8
|
+
ctx.sendError(ws, found && found.mate.id, 'This owner question is unavailable or expired.', msg.requestId || null, msg.sessionId || null, 'question_expired', { toolId: msg.toolId }); return;
|
|
9
|
+
}
|
|
10
|
+
if (!found.ctx.handleHomeAskUserResponse({ type: 'ask_user_response', toolId: msg.toolId, answers: msg.answers || {} }, session, ws)) ctx.sendError(ws, found.mate.id, 'This question could not be submitted.', msg.requestId || null, msg.sessionId, 'question_refused', { toolId: msg.toolId });
|
|
11
|
+
}
|
|
12
|
+
return { respond: respond };
|
|
13
|
+
}
|
|
14
|
+
module.exports = { attachHomeMcpConsent: attachHomeMcpConsent };
|
package/lib/server-mates.js
CHANGED
|
@@ -74,12 +74,26 @@ function attachMates(ctx) {
|
|
|
74
74
|
var mateSlug = "mate-" + mate.id;
|
|
75
75
|
var mateName = (mate.profile && mate.profile.displayName) || mate.name || "Mate";
|
|
76
76
|
var registered = false;
|
|
77
|
+
var boundScheduleJob = null;
|
|
77
78
|
var favorites;
|
|
78
79
|
try {
|
|
79
80
|
registered = addProject(mateDir, mateSlug, mateName, null, mate.createdBy || effectiveUserId, null, { isMate: true, mateDisplayName: mateName }) !== false;
|
|
80
81
|
if (!registered) throw new Error("The Mate project could not be registered.");
|
|
82
|
+
var intent = mate.seedData && mate.seedData.scheduleIntent;
|
|
83
|
+
if (intent && intent.message && intent.scheduleRule) {
|
|
84
|
+
var targetProject = projects.get(mateSlug);
|
|
85
|
+
var targetManager = targetProject && targetProject.getSessionManager();
|
|
86
|
+
if (!targetProject || !targetManager || typeof targetProject.bindMateSchedule !== "function") throw new Error("The Mate schedule could not be bound to the new Mate.");
|
|
87
|
+
var targetSession = targetManager.createSessionRaw({ ownerId: users.isMultiUser() ? effectiveUserId : null, vendor: mate.vendor, model: mate.model });
|
|
88
|
+
boundScheduleJob = targetProject.bindMateSchedule(targetSession, intent, "creation-" + mate.id);
|
|
89
|
+
if (!boundScheduleJob) throw new Error("The Mate schedule could not be persisted.");
|
|
90
|
+
mates.updateMate(mateCtx, mate.id, { seedData: Object.assign({}, mate.seedData, { scheduleIntent: null }) });
|
|
91
|
+
}
|
|
81
92
|
favorites = users.addDmFavorite(effectiveUserId, mate.id);
|
|
82
93
|
} catch (error) {
|
|
94
|
+
if (targetSession && targetSession.mateSchedules && targetProject && typeof targetProject.cancelMateSchedule === "function") {
|
|
95
|
+
try { targetSession.mateSchedules.forEach(function (record) { targetProject.cancelMateSchedule(targetSession, record); }); } catch (cancelError) {}
|
|
96
|
+
}
|
|
83
97
|
if (registered) try { removeProject(mateSlug); } catch (removeError) {}
|
|
84
98
|
try { mates.deleteMate(mateCtx, mate.id); } catch (deleteError) {}
|
|
85
99
|
throw error;
|
|
@@ -97,6 +111,10 @@ function attachMates(ctx) {
|
|
|
97
111
|
return mate;
|
|
98
112
|
}
|
|
99
113
|
|
|
114
|
+
var lifecycle = require("./mate-lifecycle-service").attachMateLifecycleService({
|
|
115
|
+
users: users, mates: mates, projects: projects, removeProject: removeProject, refresh: refreshTeamSections,
|
|
116
|
+
});
|
|
117
|
+
|
|
100
118
|
// --- Mate message handlers ---
|
|
101
119
|
|
|
102
120
|
function handleMessage(ws, msg) {
|
|
@@ -168,7 +186,7 @@ function attachMates(ctx) {
|
|
|
168
186
|
for (var mi = 0; mi < mateList.length; mi++) {
|
|
169
187
|
var m = mateList[mi];
|
|
170
188
|
var mSlug = "mate-" + m.id;
|
|
171
|
-
if (!projects.has(mSlug)) {
|
|
189
|
+
if (!m.lifecycleDeletion && !projects.has(mSlug)) {
|
|
172
190
|
var mDir = mates.getMateDir(mateCtx5, m.id);
|
|
173
191
|
fs.mkdirSync(mDir, { recursive: true });
|
|
174
192
|
var mName = (m.profile && m.profile.displayName) || m.name || "New Mate";
|
|
@@ -200,45 +218,9 @@ function attachMates(ctx) {
|
|
|
200
218
|
|
|
201
219
|
if (msg.type === "mate_delete") {
|
|
202
220
|
if (!msg.mateId) return true;
|
|
203
|
-
|
|
204
|
-
|
|
205
|
-
|
|
206
|
-
if (mateToDelete && mateToDelete.builtinKey) {
|
|
207
|
-
users.addDeletedBuiltinKey(userId, mateToDelete.builtinKey);
|
|
208
|
-
}
|
|
209
|
-
var result = mates.deleteMate(mateCtx6, msg.mateId);
|
|
210
|
-
if (result.error) {
|
|
211
|
-
ws.send(JSON.stringify({ type: "mate_error", error: result.error }));
|
|
212
|
-
} else {
|
|
213
|
-
removeProject("mate-" + msg.mateId);
|
|
214
|
-
// Build updated available builtins list
|
|
215
|
-
var builtinDefs3 = require("./builtin-mates");
|
|
216
|
-
var missingKeys3 = mates.getMissingBuiltinKeys(mateCtx6);
|
|
217
|
-
var availableBuiltins3 = [];
|
|
218
|
-
for (var abk3 = 0; abk3 < missingKeys3.length; abk3++) {
|
|
219
|
-
var bDef3 = builtinDefs3.getBuiltinByKey(missingKeys3[abk3]);
|
|
220
|
-
if (bDef3) {
|
|
221
|
-
availableBuiltins3.push({
|
|
222
|
-
key: bDef3.key,
|
|
223
|
-
displayName: bDef3.displayName,
|
|
224
|
-
bio: bDef3.bio,
|
|
225
|
-
avatarCustom: bDef3.avatarCustom || "",
|
|
226
|
-
avatarStyle: bDef3.avatarStyle || "imprint",
|
|
227
|
-
avatarColor: bDef3.avatarColor || "",
|
|
228
|
-
});
|
|
229
|
-
}
|
|
230
|
-
}
|
|
231
|
-
ws.send(JSON.stringify({ type: "mate_deleted", mateId: msg.mateId, availableBuiltins: availableBuiltins3 }));
|
|
232
|
-
// Broadcast to all clients so strips update
|
|
233
|
-
projects.forEach(function (pCtx) {
|
|
234
|
-
pCtx.forEachClient(function (otherWs) {
|
|
235
|
-
if (otherWs === ws) return;
|
|
236
|
-
if (users.isMultiUser() && (!otherWs._clayUser || otherWs._clayUser.id !== userId)) return;
|
|
237
|
-
if (otherWs.readyState !== 1) return;
|
|
238
|
-
otherWs.send(JSON.stringify({ type: "mate_deleted", mateId: msg.mateId, availableBuiltins: availableBuiltins3 }));
|
|
239
|
-
});
|
|
240
|
-
});
|
|
241
|
-
}
|
|
221
|
+
lifecycle.remove(userId, msg.mateId, null, ws).then(function () {}, function (error) {
|
|
222
|
+
ws.send(JSON.stringify({ type: "mate_error", mateId: msg.mateId, error: error.message }));
|
|
223
|
+
});
|
|
242
224
|
return true;
|
|
243
225
|
}
|
|
244
226
|
|
|
@@ -303,28 +285,8 @@ function attachMates(ctx) {
|
|
|
303
285
|
ws.send(JSON.stringify({ type: "mate_error", mateId: msg.mateId, error: "Use the Mate model selector to change this setting." }));
|
|
304
286
|
return true;
|
|
305
287
|
}
|
|
306
|
-
|
|
307
|
-
|
|
308
|
-
if (updated && updated.error) {
|
|
309
|
-
ws.send(JSON.stringify({ type: "mate_error", mateId: msg.mateId, requestId: msg.requestId, error: updated.error }));
|
|
310
|
-
return true;
|
|
311
|
-
}
|
|
312
|
-
if (updated) {
|
|
313
|
-
ws.send(JSON.stringify({ type: "mate_updated", mate: updated, requestId: msg.requestId }));
|
|
314
|
-
// Broadcast update
|
|
315
|
-
projects.forEach(function (pCtx) {
|
|
316
|
-
pCtx.forEachClient(function (otherWs) {
|
|
317
|
-
if (otherWs === ws) return;
|
|
318
|
-
if (users.isMultiUser() && (!otherWs._clayUser || otherWs._clayUser.id !== userId)) return;
|
|
319
|
-
if (otherWs.readyState !== 1) return;
|
|
320
|
-
otherWs.send(JSON.stringify({ type: "mate_updated", mate: updated }));
|
|
321
|
-
});
|
|
322
|
-
});
|
|
323
|
-
// Re-enforce team sections across all mate projects so roster stays current
|
|
324
|
-
refreshTeamSections(mateCtx7);
|
|
325
|
-
} else {
|
|
326
|
-
ws.send(JSON.stringify({ type: "mate_error", mateId: msg.mateId, requestId: msg.requestId, error: "Mate not found" }));
|
|
327
|
-
}
|
|
288
|
+
try { lifecycle.update(userId, msg.mateId, msg.updates, ws, msg.requestId); }
|
|
289
|
+
catch (error) { ws.send(JSON.stringify({ type: "mate_error", mateId: msg.mateId, requestId: msg.requestId, error: error.message })); }
|
|
328
290
|
return true;
|
|
329
291
|
}
|
|
330
292
|
|
|
@@ -333,6 +295,7 @@ function attachMates(ctx) {
|
|
|
333
295
|
|
|
334
296
|
return {
|
|
335
297
|
handleMessage: handleMessage,
|
|
298
|
+
lifecycle: lifecycle,
|
|
336
299
|
scheduleRegistryRefresh: scheduleRegistryRefresh,
|
|
337
300
|
createReadyMateFromInterview: createReadyMateFromInterview,
|
|
338
301
|
};
|
|
@@ -0,0 +1,118 @@
|
|
|
1
|
+
var crypto = require('crypto');
|
|
2
|
+
// Only authenticated application sockets enumerated by the server are targets.
|
|
3
|
+
function attachOwnerUi(ctx) {
|
|
4
|
+
var identities = new WeakMap(), capabilities = new WeakMap(), deliveries = new Map();
|
|
5
|
+
var activityOrder = 0;
|
|
6
|
+
function activity(owner, slug, sessionId, mateId, selected, source, validateSource, navigationTarget) {
|
|
7
|
+
var order = ++activityOrder;
|
|
8
|
+
var viewers = selected ? [check(owner, selected)] : sockets(owner).filter(function (viewer) {
|
|
9
|
+
var tap = viewer.ws._homeChatTap;
|
|
10
|
+
return viewer.slug === slug && viewer.sessionId === sessionId || tap && tap.mateSlug === slug && tap.sessionId === sessionId;
|
|
11
|
+
});
|
|
12
|
+
function send(message, receiptViewer) {
|
|
13
|
+
viewers.forEach(function (viewer) {
|
|
14
|
+
try {
|
|
15
|
+
if (receiptViewer && viewer.ws !== receiptViewer || !alive(viewer.ws, owner)) return;
|
|
16
|
+
if (message.phase !== 'clear' && validateSource) validateSource();
|
|
17
|
+
var live = inspect(owner, viewer.ref), tap = live.ws._homeChatTap;
|
|
18
|
+
if (message.phase !== 'clear' && (selected ? (live.slug !== viewer.slug || live.sessionId !== viewer.sessionId) && !(message.phase === 'rendered' && navigationTarget && live.slug === navigationTarget.projectSlug && live.sessionId === navigationTarget.sessionId) : !(live.slug === slug && live.sessionId === sessionId || tap && tap.mateSlug === slug && tap.sessionId === sessionId))) return;
|
|
19
|
+
live.ws.send(JSON.stringify(Object.assign({ type: 'clay_control_activity', ownerId: owner, mateId: mateId,
|
|
20
|
+
sourceSlug: slug, sourceSessionId: sessionId, order: order, recipientViewerRef: live.ref }, source, message)));
|
|
21
|
+
} catch (error) { /* Presentation cannot alter the authoritative effect. */ }
|
|
22
|
+
});
|
|
23
|
+
}
|
|
24
|
+
return { send: send, clear: function (id, sequence) { send({ version: 1, id: id, sequence: sequence, phase: 'clear' }); } };
|
|
25
|
+
}
|
|
26
|
+
function alive(ws, owner) {
|
|
27
|
+
return ws && ws.readyState === 1 && (!ws._clayAuthCheck || ws._clayAuthCheck()) &&
|
|
28
|
+
(ctx.isMultiUser() ? !!owner && ws._clayUser && ws._clayUser.id === owner && !!ctx.findUser(owner) : !ws._clayUser);
|
|
29
|
+
}
|
|
30
|
+
function sockets(owner) {
|
|
31
|
+
var all = new Map();
|
|
32
|
+
ctx.forEachClient(function (ws, slug) {
|
|
33
|
+
if (!alive(ws, owner) || all.has(ws)) return;
|
|
34
|
+
if (!identities.has(ws)) identities.set(ws, 'viewer:' + crypto.randomUUID());
|
|
35
|
+
all.set(ws, { ws: ws, ref: identities.get(ws), slug: slug || null, sessionId: ws._clayActiveSession || null,
|
|
36
|
+
supported: capabilities.get(ws) === 1 && !ws._clayPane });
|
|
37
|
+
});
|
|
38
|
+
return Array.from(all.values());
|
|
39
|
+
}
|
|
40
|
+
function get(owner, ref) { return sockets(owner).find(function (item) { return item.ref === ref; }); }
|
|
41
|
+
function inspect(owner, ref) {
|
|
42
|
+
var viewer = get(owner, ref);
|
|
43
|
+
if (!viewer) throw new Error('The exact owner UI connection is absent or revoked.');
|
|
44
|
+
return viewer;
|
|
45
|
+
}
|
|
46
|
+
function check(owner, original) {
|
|
47
|
+
var live = inspect(owner, original.ref);
|
|
48
|
+
if (live.ws !== original.ws || live.slug !== original.slug || live.sessionId !== original.sessionId || live.supported !== original.supported) throw new Error('The selected viewer context changed. Inspect again.');
|
|
49
|
+
return live;
|
|
50
|
+
}
|
|
51
|
+
function deliver(owner, original, target, revalidate, activity) {
|
|
52
|
+
revalidate(); var viewer = check(owner, original);
|
|
53
|
+
if (!viewer.supported) return { status: 'unsupported', delivered: false, acknowledged: false, visible: 'unknown' };
|
|
54
|
+
if (deliveries.size >= 100) {
|
|
55
|
+
deliveries.forEach(function (item, key) { if (Date.now() - item.created > 300000) deliveries.delete(key); });
|
|
56
|
+
if (deliveries.size >= 100) throw new Error('UI delivery capacity is full; wait for earlier attempts to expire.');
|
|
57
|
+
}
|
|
58
|
+
var id = 'navigation:' + crypto.randomUUID();
|
|
59
|
+
var renderToken = crypto.randomUUID();
|
|
60
|
+
var record = { owner: owner, viewer: viewer, target: target, revalidate: revalidate, activity: activity, created: Date.now(), claimed: false, renderToken: renderToken, renderClosed: false,
|
|
61
|
+
result: { status: 'delivered', deliveryId: id, delivered: false, acknowledged: false, visible: 'unknown' } };
|
|
62
|
+
deliveries.set(id, record);
|
|
63
|
+
record.renderTimer = setTimeout(function () {
|
|
64
|
+
if (record.renderClosed) return;
|
|
65
|
+
record.renderClosed = true; record.result.renderStatus = 'unknown';
|
|
66
|
+
if (record.activity) record.activity.navigation('unknown');
|
|
67
|
+
}, ctx.renderTimeoutMs || 5000); record.renderTimer.unref();
|
|
68
|
+
try {
|
|
69
|
+
viewer.ws.send(JSON.stringify({ type: 'clay_navigation_offer', deliveryId: id }));
|
|
70
|
+
if (!alive(viewer.ws, owner)) throw new Error('Viewer authorization or connection ended during delivery.');
|
|
71
|
+
record.result.delivered = true;
|
|
72
|
+
} catch (error) { record.result.status = 'failed'; record.result.error = error.message; record.result.retrySafe = false; }
|
|
73
|
+
return Object.assign({}, record.result);
|
|
74
|
+
}
|
|
75
|
+
function read(owner, id) {
|
|
76
|
+
var record = deliveries.get(id);
|
|
77
|
+
if (!record || record.owner !== owner) throw new Error('No delivery exists for this owner.');
|
|
78
|
+
if (Date.now() - record.created > 300000) { deliveries.delete(id); throw new Error('The five-minute navigation receipt expired. Inspect the current view before any new reviewed request.'); }
|
|
79
|
+
record.revalidate();
|
|
80
|
+
return Object.assign({}, record.result);
|
|
81
|
+
}
|
|
82
|
+
function handleMessage(ws, msg) {
|
|
83
|
+
if (['clay_ui_ready', 'clay_navigation_claim', 'clay_navigation_ack', 'clay_navigation_rendered'].indexOf(msg.type) < 0) return false;
|
|
84
|
+
var owner = ctx.isMultiUser() ? ws._clayUser && ws._clayUser.id : null;
|
|
85
|
+
if (!sockets(owner).some(function (item) { return item.ws === ws; })) return true;
|
|
86
|
+
if (msg.type === 'clay_ui_ready') {
|
|
87
|
+
if (msg.version === 1) { capabilities.set(ws, 1); ws.send(JSON.stringify({ type: 'clay_control_viewer', viewerRef: identities.get(ws) })); }
|
|
88
|
+
return true;
|
|
89
|
+
}
|
|
90
|
+
var record = deliveries.get(msg.deliveryId);
|
|
91
|
+
if (!record || record.viewer.ws !== ws || record.owner !== owner || Date.now() - record.created > 30000) return true;
|
|
92
|
+
try {
|
|
93
|
+
record.revalidate();
|
|
94
|
+
if (msg.type === 'clay_navigation_rendered') {
|
|
95
|
+
if (!record.renderClosed && Date.now() > record.created + (ctx.renderTimeoutMs || 5000)) { record.renderClosed = true; clearTimeout(record.renderTimer); record.result.renderStatus = 'unknown'; if (record.activity) record.activity.navigation('unknown'); }
|
|
96
|
+
if (record.renderClosed || !record.claimed || !record.result.acknowledged || record.result.clientStatus !== 'accepted' || msg.renderToken !== record.renderToken) return true;
|
|
97
|
+
var current = inspect(owner, record.viewer.ref);
|
|
98
|
+
if (current.ws !== ws || msg.sessionOriginId !== record.target.sessionOriginId || !record.target.sessionOriginId || msg.projectSlug !== record.target.projectSlug || msg.sessionId !== record.target.sessionId || msg.surface !== 'conversation' || msg.entryIndex !== record.target.entryIndex || current.slug !== record.target.projectSlug || current.sessionId !== record.target.sessionId) throw new Error('Rendered target or authenticated viewer changed.');
|
|
99
|
+
record.renderClosed = true; clearTimeout(record.renderTimer);
|
|
100
|
+
record.result.renderStatus = msg.visible === true ? 'rendered' : 'unknown'; record.result.visible = msg.visible === true ? true : 'unknown';
|
|
101
|
+
if (record.activity) record.activity.navigation(msg.visible === true ? 'rendered' : 'unknown');
|
|
102
|
+
} else if (msg.type === 'clay_navigation_claim') {
|
|
103
|
+
if (record.claimed) return true;
|
|
104
|
+
check(owner, record.viewer); record.claimed = true;
|
|
105
|
+
ws.send(JSON.stringify({ type: 'clay_navigation_apply', deliveryId: msg.deliveryId, target: record.target, renderToken: record.renderToken, renderDeadline: record.created + (ctx.renderTimeoutMs || 5000) }));
|
|
106
|
+
} else if (record.claimed && !record.result.acknowledged && ['accepted', 'refused', 'failed'].indexOf(msg.status) >= 0) {
|
|
107
|
+
record.result.acknowledged = true;
|
|
108
|
+
// Accepted only confirms invocation of the existing navigator, never rendering.
|
|
109
|
+
record.result.clientStatus = msg.status;
|
|
110
|
+
if (msg.status !== 'accepted') { record.renderClosed = true; clearTimeout(record.renderTimer); }
|
|
111
|
+
if (record.activity) record.activity.navigation(msg.status === 'accepted' ? 'acknowledged' : msg.status === 'refused' ? 'cancelled' : 'failed');
|
|
112
|
+
}
|
|
113
|
+
} catch (error) { record.renderClosed = true; clearTimeout(record.renderTimer); record.result.visible = 'unknown'; record.result.status = 'failed'; record.result.error = error.message; record.result.retrySafe = false; if (record.activity) record.activity.cancel(); }
|
|
114
|
+
return true;
|
|
115
|
+
}
|
|
116
|
+
return { list: sockets, inspect: inspect, check: check, deliver: deliver, read: read, handleMessage: handleMessage, activity: activity };
|
|
117
|
+
}
|
|
118
|
+
module.exports = { attachOwnerUi: attachOwnerUi };
|
|
@@ -0,0 +1,38 @@
|
|
|
1
|
+
// Directory pickers and project registration must not become content-access
|
|
2
|
+
// bypasses through another spelling, symlink or nested directory.
|
|
3
|
+
var fs = require("fs");
|
|
4
|
+
var path = require("path");
|
|
5
|
+
function inside(root, target) {
|
|
6
|
+
var relative = path.relative(root, target);
|
|
7
|
+
return relative !== ".." && relative.indexOf(".." + path.sep) !== 0 && !path.isAbsolute(relative);
|
|
8
|
+
}
|
|
9
|
+
function attachPathAccess(ctx) {
|
|
10
|
+
return function (userId, requested) {
|
|
11
|
+
if (!ctx.users.isMultiUser()) return true;
|
|
12
|
+
var user = userId && ctx.users.findUserById(userId);
|
|
13
|
+
if (!user) return false;
|
|
14
|
+
var target;
|
|
15
|
+
try { target = fs.realpathSync(requested); } catch (error) { return false; }
|
|
16
|
+
var allowed = false;
|
|
17
|
+
var denied = false;
|
|
18
|
+
ctx.projects.forEach(function (project, slug) {
|
|
19
|
+
var status = project.getStatus();
|
|
20
|
+
var root;
|
|
21
|
+
try { root = fs.realpathSync(status.path); } catch (error) { return; }
|
|
22
|
+
if (inside(root, target) || inside(target, root)) {
|
|
23
|
+
if (!ctx.canAccess(userId, slug)) denied = true;
|
|
24
|
+
else if (inside(root, target)) allowed = true;
|
|
25
|
+
}
|
|
26
|
+
});
|
|
27
|
+
if (denied) return false;
|
|
28
|
+
if (ctx.osUsers) {
|
|
29
|
+
if (!user.linuxUser) return false;
|
|
30
|
+
try {
|
|
31
|
+
var identity = ctx.resolveIdentity(user.linuxUser);
|
|
32
|
+
return inside(fs.realpathSync(identity.home), target);
|
|
33
|
+
} catch (error) { return false; }
|
|
34
|
+
}
|
|
35
|
+
return allowed || ctx.users.getAllUsers().length === 1;
|
|
36
|
+
};
|
|
37
|
+
}
|
|
38
|
+
module.exports = { attachPathAccess: attachPathAccess };
|
|
@@ -0,0 +1,22 @@
|
|
|
1
|
+
// Shared runtime removal used by the server callback and lifecycle controls.
|
|
2
|
+
function removeProjectRuntime(projects, slug, awaitCompletion, registryRefresh) {
|
|
3
|
+
var project = projects.get(slug);
|
|
4
|
+
if (!project) return false;
|
|
5
|
+
var wasMate = project.getStatus().isMate;
|
|
6
|
+
var shutdownResult = project.destroy();
|
|
7
|
+
if (!awaitCompletion) projects.delete(slug);
|
|
8
|
+
if (shutdownResult && typeof shutdownResult.catch === 'function') {
|
|
9
|
+
shutdownResult.catch(function (error) {
|
|
10
|
+
console.error('[server] Project destroy failed for ' + slug + ':', error && error.message ? error.message : error);
|
|
11
|
+
});
|
|
12
|
+
}
|
|
13
|
+
if (!wasMate && registryRefresh) registryRefresh();
|
|
14
|
+
if (awaitCompletion) return Promise.resolve(shutdownResult).then(function (result) {
|
|
15
|
+
if (result !== true) throw new Error('Project runtime shutdown did not complete successfully: ' + slug);
|
|
16
|
+
if (projects.get(slug) !== project) throw new Error('Project runtime was replaced during shutdown: ' + slug);
|
|
17
|
+
projects.delete(slug);
|
|
18
|
+
return true;
|
|
19
|
+
});
|
|
20
|
+
return true;
|
|
21
|
+
}
|
|
22
|
+
module.exports = { removeProjectRuntime: removeProjectRuntime };
|
package/lib/server-settings.js
CHANGED
|
@@ -12,11 +12,13 @@ function attachSettings(ctx) {
|
|
|
12
12
|
var CONFIG_DIR = ctx.CONFIG_DIR;
|
|
13
13
|
|
|
14
14
|
var profilePath = path.join(CONFIG_DIR, "profile.json");
|
|
15
|
+
var contextualClaySettings = require('./server-contextual-clay-settings').attachContextualClaySettings(ctx);
|
|
15
16
|
var appearanceSettings = require('./server-appearance-settings').attachAppearanceSettings(ctx);
|
|
16
17
|
var notificationSettings = require('./server-notification-settings').attachNotificationSettings(ctx);
|
|
17
18
|
var experimentalSettings = attachExperimentalSettings(ctx);
|
|
18
19
|
|
|
19
20
|
function handleRequest(req, res, fullUrl) {
|
|
21
|
+
if (contextualClaySettings.handleRequest(req, res, fullUrl)) return true;
|
|
20
22
|
if (appearanceSettings.handleRequest(req, res, fullUrl)) return true;
|
|
21
23
|
if (notificationSettings.handleRequest(req, res, fullUrl)) return true;
|
|
22
24
|
if (experimentalSettings.handleRequest(req, res, fullUrl)) return true;
|
|
@@ -755,7 +757,10 @@ function attachSettings(ctx) {
|
|
|
755
757
|
return false;
|
|
756
758
|
}
|
|
757
759
|
|
|
758
|
-
return {
|
|
760
|
+
return {
|
|
761
|
+
handleRequest: handleRequest,
|
|
762
|
+
getInitialAppearance: appearanceSettings.getInitialAppearance
|
|
763
|
+
};
|
|
759
764
|
}
|
|
760
765
|
|
|
761
766
|
module.exports = { attachSettings: attachSettings };
|