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
|
@@ -1,4 +1,5 @@
|
|
|
1
1
|
var mateCreationMcp = require("./mate-creation-mcp-server");
|
|
2
|
+
var scheduleInput = require("./mate-schedule-input");
|
|
2
3
|
var selectCatalogModel = require("./project-models").selectCatalogModel;
|
|
3
4
|
|
|
4
5
|
function attachMateCreationProposal(ctx) {
|
|
@@ -19,6 +20,8 @@ function attachMateCreationProposal(ctx) {
|
|
|
19
20
|
communicationStyle: Array.isArray(source.communicationStyle) ? source.communicationStyle.slice(0, 12) : [],
|
|
20
21
|
autonomy: clean(source.autonomy, 500),
|
|
21
22
|
identityMarkdown: clean(source.identityMarkdown, 30000),
|
|
23
|
+
scheduleIntent: source.scheduleIntent || null,
|
|
24
|
+
scheduleTimezone: scheduleInput.timezone(),
|
|
22
25
|
};
|
|
23
26
|
}
|
|
24
27
|
|
|
@@ -30,7 +33,8 @@ function attachMateCreationProposal(ctx) {
|
|
|
30
33
|
var projectOwnerId = typeof ctx.getProjectOwnerId === "function" ? ctx.getProjectOwnerId() : null;
|
|
31
34
|
var ownerValid = typeof ctx.isMultiUser === "function" && ctx.isMultiUser() ? !!(session && session.ownerId && (!projectOwnerId || session.ownerId === projectOwnerId)) : !!(session && !session.ownerId);
|
|
32
35
|
return !!(session && ctx.isMate === true && ctx.isHostAgent === true && session.mateCreationMode === true
|
|
33
|
-
&& ownerValid
|
|
36
|
+
&& ownerValid && !session.destroying && !session._mcpForeignInput
|
|
37
|
+
&& (!ctx.isLive || ctx.isLive(session)));
|
|
34
38
|
}
|
|
35
39
|
|
|
36
40
|
function hasInterviewAnswer(session) {
|
|
@@ -44,10 +48,19 @@ function attachMateCreationProposal(ctx) {
|
|
|
44
48
|
return mateCreationMcp.getToolDefs(function (definition) {
|
|
45
49
|
if (!validateBoundSession(boundSession)) return Promise.resolve({ action: "error", error: "Mate proposals require an owned Clay creation interview." });
|
|
46
50
|
if (!hasInterviewAnswer(boundSession)) return Promise.resolve({ action: "error", error: "Interview the user before proposing a Mate." });
|
|
51
|
+
if (definition.scheduleIntent && typeof definition.scheduleIntent === "string") {
|
|
52
|
+
try { definition.scheduleIntent = JSON.parse(definition.scheduleIntent); } catch (error) { return Promise.resolve({ action: "error", error: "scheduleIntent must be valid JSON." }); }
|
|
53
|
+
}
|
|
54
|
+
try {
|
|
55
|
+
if (definition.scheduleIntent) {
|
|
56
|
+
var checkedIntent = scheduleInput.normalize(definition.scheduleIntent);
|
|
57
|
+
definition.scheduleIntent = { message: checkedIntent.message, scheduleRule: checkedIntent.rule };
|
|
58
|
+
}
|
|
59
|
+
} catch (error) { return Promise.resolve({ action: "error", error: error.message }); }
|
|
47
60
|
return new Promise(function (resolve) {
|
|
48
61
|
var proposalId = "mp_" + Date.now() + "_" + Math.random().toString(36).slice(2, 8);
|
|
49
62
|
definition.proposalId = proposalId;
|
|
50
|
-
pending[proposalId] = { resolve: resolve, definition: definition, session: boundSession };
|
|
63
|
+
pending[proposalId] = { resolve: resolve, definition: definition, session: boundSession, generation: Number(boundSession._sdkQueryGeneration || 0) };
|
|
51
64
|
record(boundSession, { type: "mate_creation_proposal", proposal: publicProposal(definition) });
|
|
52
65
|
});
|
|
53
66
|
});
|
|
@@ -72,7 +85,8 @@ function attachMateCreationProposal(ctx) {
|
|
|
72
85
|
|
|
73
86
|
function handleHomeMessage(ws, msg, session) {
|
|
74
87
|
var entry = msg && msg.proposalId ? pending[msg.proposalId] : null;
|
|
75
|
-
if (!entry || entry.session !== session || !validateBoundSession(session)) return false;
|
|
88
|
+
if (!entry || entry.session !== session || !validateBoundSession(session) || entry.generation !== Number(session._sdkQueryGeneration || 0)) return false;
|
|
89
|
+
if (ctx.isMultiUser && ctx.isMultiUser() && (!ws || !ws._clayUser || ws._clayUser.id !== session.ownerId)) return false;
|
|
76
90
|
delete pending[msg.proposalId];
|
|
77
91
|
if (msg.action !== "create") {
|
|
78
92
|
record(session, { type: "mate_creation_proposal_resolved", proposalId: msg.proposalId, action: "cancel" });
|
|
@@ -93,6 +107,7 @@ function attachMateCreationProposal(ctx) {
|
|
|
93
107
|
return true;
|
|
94
108
|
}
|
|
95
109
|
Promise.resolve(ctx.getVendorModelCatalog(ws, vendor)).then(function (catalog) {
|
|
110
|
+
if (!validateBoundSession(session) || entry.generation !== Number(session._sdkQueryGeneration || 0)) throw new Error("The Mate creation approval is stale.");
|
|
96
111
|
var selected = catalog && catalog.status === "ready" ? selectCatalogModel(catalog.models || [], catalog.defaultModel, "deep") : null;
|
|
97
112
|
if (!selected) throw new Error((catalog && catalog.error) || "No high-capability Mate model is available for " + vendor + ".");
|
|
98
113
|
return ctx.createReadyMate(ws, session.ownerId || null, Object.assign({}, entry.definition, { vendor: vendor, model: selected.value }));
|
|
@@ -3,6 +3,7 @@ var fs = require("fs");
|
|
|
3
3
|
var path = require("path");
|
|
4
4
|
var crypto = require("crypto");
|
|
5
5
|
var mateSync = require("./mate-knowledge-sync");
|
|
6
|
+
var dmDigestCursor = require("./dm-digest-cursor");
|
|
6
7
|
|
|
7
8
|
// Mirror a Mate-owned journal into the Clay-wide Knowledge backend after the
|
|
8
9
|
// legacy append has already succeeded. Reconciling the whole journal keeps the
|
|
@@ -294,6 +295,9 @@ function attachMateInteraction(ctx) {
|
|
|
294
295
|
mirrorMateJournal(mateDir, "session-digests.jsonl", job);
|
|
295
296
|
} catch (e) {
|
|
296
297
|
console.error("[digest-worker] Write failed for " + job.mateId + ":", e.message);
|
|
298
|
+
if (job.onError) job.onError(e);
|
|
299
|
+
processDigestQueue();
|
|
300
|
+
return;
|
|
297
301
|
}
|
|
298
302
|
|
|
299
303
|
// Write user observations if present
|
|
@@ -422,63 +426,19 @@ function attachMateInteraction(ctx) {
|
|
|
422
426
|
// Delta-based: only collects new turns since the last successful digest.
|
|
423
427
|
// Concurrency debounce: turns that arrive while a digest is in-flight
|
|
424
428
|
// are naturally batched into the next flush.
|
|
425
|
-
var _dmDigestPending =
|
|
426
|
-
function digestDmTurn(session
|
|
427
|
-
if (!isMate || _dmDigestPending) return;
|
|
429
|
+
var _dmDigestPending = new WeakSet();
|
|
430
|
+
function digestDmTurn(session) {
|
|
431
|
+
if (!isMate || _dmDigestPending.has(session)) return;
|
|
428
432
|
var mateId = path.basename(cwd);
|
|
429
433
|
var mateCtx = matesModule.buildMateCtx(projectOwnerId);
|
|
430
434
|
if (!matesModule.isMate(mateCtx, mateId)) return;
|
|
431
435
|
|
|
432
|
-
//
|
|
433
|
-
//
|
|
434
|
-
|
|
435
|
-
|
|
436
|
-
|
|
437
|
-
|
|
438
|
-
if (session.history[ci].type === "digest_checkpoint") {
|
|
439
|
-
session._dmLastDigestedIndex = session.history[ci].digestedIndex;
|
|
440
|
-
break;
|
|
441
|
-
}
|
|
442
|
-
}
|
|
443
|
-
}
|
|
444
|
-
|
|
445
|
-
// Collect only new turns since the last successful digest
|
|
446
|
-
var conversationParts = [];
|
|
447
|
-
var totalLen = 0;
|
|
448
|
-
var CONV_CAP = 6000;
|
|
449
|
-
var startIndex = session._dmLastDigestedIndex;
|
|
450
|
-
for (var hi = startIndex; hi < session.history.length; hi++) {
|
|
451
|
-
if (totalLen >= CONV_CAP) break;
|
|
452
|
-
var entry = session.history[hi];
|
|
453
|
-
if (entry.type === "user_message" && entry.text) {
|
|
454
|
-
var uText = entry.text;
|
|
455
|
-
if (totalLen + uText.length > CONV_CAP) {
|
|
456
|
-
uText = uText.substring(0, Math.max(200, CONV_CAP - totalLen)) + "...";
|
|
457
|
-
}
|
|
458
|
-
conversationParts.push("User: " + uText);
|
|
459
|
-
totalLen += uText.length;
|
|
460
|
-
} else if (entry.type === "assistant_message" && entry.text) {
|
|
461
|
-
var aText = entry.text;
|
|
462
|
-
if (totalLen + aText.length > CONV_CAP) {
|
|
463
|
-
aText = aText.substring(0, Math.max(200, CONV_CAP - totalLen)) + "...";
|
|
464
|
-
}
|
|
465
|
-
conversationParts.push("Mate: " + aText);
|
|
466
|
-
totalLen += aText.length;
|
|
467
|
-
}
|
|
468
|
-
}
|
|
469
|
-
// If the latest response hasn't landed in history yet, append it
|
|
470
|
-
var lastResponseText = responsePreview || "";
|
|
471
|
-
if (lastResponseText && conversationParts.length > 0) {
|
|
472
|
-
var lastPart = conversationParts[conversationParts.length - 1];
|
|
473
|
-
if (lastPart.indexOf("Mate:") !== 0 || lastPart.indexOf(lastResponseText.substring(0, 50)) === -1) {
|
|
474
|
-
var rText = lastResponseText;
|
|
475
|
-
if (totalLen + rText.length > CONV_CAP) {
|
|
476
|
-
rText = rText.substring(0, Math.max(200, CONV_CAP - totalLen)) + "...";
|
|
477
|
-
}
|
|
478
|
-
conversationParts.push("Mate: " + rText);
|
|
479
|
-
}
|
|
480
|
-
}
|
|
481
|
-
if (conversationParts.length === 0) return;
|
|
436
|
+
// Recover the exact next unread position. Legacy index-only checkpoints
|
|
437
|
+
// remain readable and are treated as fully consumed entries.
|
|
438
|
+
var digestState = dmDigestCursor.readState(session.history);
|
|
439
|
+
var startCursor = digestState.cursor;
|
|
440
|
+
var chunk = dmDigestCursor.collectChunk(session.history, startCursor);
|
|
441
|
+
if (!chunk.conversationContent) return;
|
|
482
442
|
|
|
483
443
|
var mateDir = matesModule.getMateDir(mateCtx, mateId);
|
|
484
444
|
var knowledgeDir = path.join(mateDir, "knowledge");
|
|
@@ -500,8 +460,8 @@ function attachMateInteraction(ctx) {
|
|
|
500
460
|
}
|
|
501
461
|
} catch (e) {}
|
|
502
462
|
|
|
503
|
-
_dmDigestPending
|
|
504
|
-
var
|
|
463
|
+
_dmDigestPending.add(session);
|
|
464
|
+
var checkpointCursor = chunk.cursor;
|
|
505
465
|
|
|
506
466
|
enqueueDigest({
|
|
507
467
|
mateCtx: mateCtx,
|
|
@@ -509,17 +469,27 @@ function attachMateInteraction(ctx) {
|
|
|
509
469
|
mateId: mateId,
|
|
510
470
|
type: "dm",
|
|
511
471
|
priorSummary: priorSummary || "",
|
|
512
|
-
conversationContent:
|
|
472
|
+
conversationContent: chunk.conversationContent,
|
|
513
473
|
onDone: function () {
|
|
514
|
-
|
|
515
|
-
//
|
|
516
|
-
var checkpoint = { type: "digest_checkpoint",
|
|
474
|
+
// Journal and checkpoint are separate appends: if this append fails,
|
|
475
|
+
// retry may duplicate the saved digest, but must never skip its input.
|
|
476
|
+
var checkpoint = { type: "digest_checkpoint", cursor: checkpointCursor };
|
|
477
|
+
var saved = false;
|
|
478
|
+
try { saved = sm.appendToSessionFile(session, checkpoint) !== false; } catch (e) {
|
|
479
|
+
console.error("[dm-digest] Checkpoint append failed:", e.message);
|
|
480
|
+
}
|
|
481
|
+
if (!saved) {
|
|
482
|
+
_dmDigestPending.delete(session);
|
|
483
|
+
return;
|
|
484
|
+
}
|
|
517
485
|
session.history.push(checkpoint);
|
|
518
|
-
|
|
519
|
-
|
|
486
|
+
_dmDigestPending.delete(session);
|
|
487
|
+
if (dmDigestCursor.hasPending(session.history, checkpointCursor)) {
|
|
488
|
+
setImmediate(function () { digestDmTurn(session, ""); });
|
|
489
|
+
}
|
|
520
490
|
},
|
|
521
491
|
onError: function () {
|
|
522
|
-
_dmDigestPending
|
|
492
|
+
_dmDigestPending.delete(session);
|
|
523
493
|
},
|
|
524
494
|
});
|
|
525
495
|
}
|
|
@@ -570,6 +540,8 @@ function attachMateInteraction(ctx) {
|
|
|
570
540
|
|
|
571
541
|
var mateName = (mate.profile && mate.profile.displayName) || mate.name || "Mate";
|
|
572
542
|
var avatarColor = (mate.profile && mate.profile.avatarColor) || "#5857fc";
|
|
543
|
+
var avatarCatalogId = (mate.profile && mate.profile.avatarCatalogId) || "";
|
|
544
|
+
var avatarCustom = (mate.profile && mate.profile.avatarCustom) || "";
|
|
573
545
|
var avatarStyle = (mate.profile && mate.profile.avatarStyle) || "imprint";
|
|
574
546
|
var avatarSeed = (mate.profile && mate.profile.avatarSeed) || mate.id;
|
|
575
547
|
|
|
@@ -622,6 +594,8 @@ function attachMateInteraction(ctx) {
|
|
|
622
594
|
mateName: mateName,
|
|
623
595
|
avatarColor: avatarColor,
|
|
624
596
|
avatarStyle: avatarStyle,
|
|
597
|
+
avatarCatalogId: avatarCatalogId,
|
|
598
|
+
avatarCustom: avatarCustom,
|
|
625
599
|
avatarSeed: avatarSeed,
|
|
626
600
|
});
|
|
627
601
|
|
|
@@ -657,6 +631,8 @@ function attachMateInteraction(ctx) {
|
|
|
657
631
|
text: fullText,
|
|
658
632
|
avatarColor: avatarColor,
|
|
659
633
|
avatarStyle: avatarStyle,
|
|
634
|
+
avatarCatalogId: avatarCatalogId,
|
|
635
|
+
avatarCustom: avatarCustom,
|
|
660
636
|
avatarSeed: avatarSeed,
|
|
661
637
|
};
|
|
662
638
|
session.history.push(mentionResponseEntry);
|
|
@@ -820,6 +796,8 @@ function attachMateInteraction(ctx) {
|
|
|
820
796
|
name: (mate.profile && mate.profile.displayName) || mate.name || "Mate",
|
|
821
797
|
avatarColor: (mate.profile && mate.profile.avatarColor) || "#5857fc",
|
|
822
798
|
avatarStyle: (mate.profile && mate.profile.avatarStyle) || "imprint",
|
|
799
|
+
avatarCatalogId: (mate.profile && mate.profile.avatarCatalogId) || "",
|
|
800
|
+
avatarCustom: (mate.profile && mate.profile.avatarCustom) || "",
|
|
823
801
|
avatarSeed: (mate.profile && mate.profile.avatarSeed) || mateId,
|
|
824
802
|
};
|
|
825
803
|
}
|
package/lib/project-mcp.js
CHANGED
|
@@ -1,10 +1,19 @@
|
|
|
1
1
|
var crypto = require('crypto');
|
|
2
|
+
var path = require('path');
|
|
2
3
|
var createProxy = require('./mcp-proxy').createProxy;
|
|
3
4
|
var createStore = require('./mcp-connection-store').createConnectionStore;
|
|
4
5
|
var createRemoteConnections = require('./mcp-remote-connections').createRemoteConnections;
|
|
6
|
+
var SHARED_REGISTRIES = new Map();
|
|
5
7
|
|
|
6
8
|
function attachMcp(ctx) {
|
|
7
|
-
var
|
|
9
|
+
var storage = ctx.storage || createStore(ctx.root, ctx.slug, { shared: true });
|
|
10
|
+
var namespace = storage.namespace || (ctx.root ? path.resolve(ctx.root) : storage);
|
|
11
|
+
var registry = SHARED_REGISTRIES.get(namespace);
|
|
12
|
+
if (!registry) { registry = { devices: new Map(), pending: new Map(), managers: new Set() }; SHARED_REGISTRIES.set(namespace, registry); }
|
|
13
|
+
var devices = registry.devices, pending = registry.pending, manager = {};
|
|
14
|
+
registry.managers.add(manager);
|
|
15
|
+
function announce(owner) { registry.managers.forEach(function (source) { source.broadcast(owner); }); }
|
|
16
|
+
manager.broadcast = broadcast;
|
|
8
17
|
function ownerFor(ws) {
|
|
9
18
|
if (!ctx.canAccess(ws)) throw new Error('MCP access is not permitted.');
|
|
10
19
|
return ctx.isMultiUser() ? String(ws._clayUser.id) : 'default';
|
|
@@ -15,17 +24,32 @@ function attachMcp(ctx) {
|
|
|
15
24
|
try { if (ws.readyState === 1 && ownerFor(ws) === owner) ctx.sendTo(ws, Object.assign({ slug: ctx.slug }, msg)); } catch (error) {}
|
|
16
25
|
});
|
|
17
26
|
}
|
|
27
|
+
function isSession(subject) { return !!subject && ctx.canUseSession(subject); }
|
|
28
|
+
function sourceIdentity(subject) { return isSession(subject) ? ctx.ownerIdentity(ctx.isMultiUser() ? String(subject.ownerId) : 'default') : ctx.identity(subject); }
|
|
29
|
+
var discovery = require('./yoke/mcp-source-discovery').createDiscovery({ cwd: ctx.cwd || process.cwd(), home: ctx.discoveryHome,
|
|
30
|
+
identity: sourceIdentity, runtimeEnv: function (owner, subject) { return isSession(subject) ? ctx.runtimeEnvForSession(subject) : ctx.runtimeEnv ? ctx.runtimeEnv(owner, subject) : {}; }, authorize: function (owner, subject) {
|
|
31
|
+
var permitted = isSession(subject) ? (ctx.isMultiUser() ? String(subject.ownerId) : 'default') === owner && ctx.canDiscoverSession(subject) : ownerFor(subject) === owner && ctx.canDiscover && ctx.canDiscover(subject);
|
|
32
|
+
if (!permitted) throw new Error('Vendor discovery requires your authorized OS user mapping or a sole account installation.');
|
|
33
|
+
authorizeOwner(owner);
|
|
34
|
+
}, snapshot: function (owner) { return storage.snapshot(owner); } });
|
|
18
35
|
var remote = createRemoteConnections({
|
|
19
36
|
remoteFetch: ctx.remoteFetch, createLoginBrowser: ctx.createLoginBrowser,
|
|
20
|
-
storage:
|
|
21
|
-
changed: function (owner) {
|
|
37
|
+
storage: storage, authorize: authorizeOwner,
|
|
38
|
+
changed: function (owner) { announce(owner); }, sendOwner: sendOwner, sendTo: function (ws, msg) { ctx.sendTo(ws, Object.assign({ slug: ctx.slug }, msg)); },
|
|
39
|
+
ownerIdentity: ctx.ownerIdentity, selectImport: discovery.selected,
|
|
22
40
|
identity: ctx.identity,
|
|
23
41
|
canAccess: function (ws, owner) { try { return ownerFor(ws) === owner; } catch (error) { return false; } },
|
|
24
42
|
});
|
|
43
|
+
var agentTools = require('./mcp-agent-tools').attachMcpAgentTools({
|
|
44
|
+
available: function (session) { return typeof ctx.canDiscoverSession === "function" && typeof ctx.runtimeEnvForSession === "function" && ctx.canDiscoverSession(session); },
|
|
45
|
+
clients: ctx.clients, isMultiUser: ctx.isMultiUser, ownerFor: ownerFor, canUseSession: ctx.canUseSession,
|
|
46
|
+
authorizeOwner: authorizeOwner, discovery: discovery, importConnection: remote.importConnection,
|
|
47
|
+
userInput: ctx.userInput, consentTimeout: ctx.consentTimeout,
|
|
48
|
+
});
|
|
25
49
|
function deviceFor(owner) {
|
|
26
50
|
var device = devices.get(owner);
|
|
27
51
|
if (!device || device.ws.readyState !== 1) return null;
|
|
28
|
-
try { if (
|
|
52
|
+
try { authorizeOwner(owner); if (!device.authorized()) return null; } catch (error) { return null; }
|
|
29
53
|
return device;
|
|
30
54
|
}
|
|
31
55
|
function enabled(owner, name) {
|
|
@@ -59,13 +83,18 @@ function attachMcp(ctx) {
|
|
|
59
83
|
if (call.ws !== device.ws) return;
|
|
60
84
|
clearTimeout(call.timer); pending.delete(id); call.reject(new Error('Your computer disconnected.'));
|
|
61
85
|
});
|
|
62
|
-
|
|
86
|
+
announce(owner);
|
|
63
87
|
});
|
|
64
88
|
}
|
|
65
89
|
function handleMcpMessage(ws, msg) {
|
|
66
90
|
if (!msg || typeof msg.type !== 'string' || (msg.type.indexOf('mcp_') !== 0 && msg.type !== 'mcp_toggle_server')) return false;
|
|
67
91
|
var owner;
|
|
68
92
|
try { owner = ownerFor(ws); } catch (error) { return true; }
|
|
93
|
+
if (msg.type === 'mcp_discovery_request') {
|
|
94
|
+
try { ctx.sendTo(ws, Object.assign({ type: 'mcp_discovery_result', slug: ctx.slug, requestId: msg.requestId, ok: true }, discovery.scan(owner, ws, msg.file ? { file: msg.file, vendor: msg.vendor } : null))); }
|
|
95
|
+
catch (error) { ctx.sendTo(ws, { type: 'mcp_discovery_result', slug: ctx.slug, requestId: msg.requestId, ok: false, error: error.message }); }
|
|
96
|
+
return true;
|
|
97
|
+
}
|
|
69
98
|
if (msg.type === 'mcp_state_request') { sendConnectionState(ws); return true; }
|
|
70
99
|
if (msg.type === 'mcp_servers_available') {
|
|
71
100
|
var servers = Array.isArray(msg.servers) ? msg.servers : [];
|
|
@@ -75,8 +104,10 @@ function attachMcp(ctx) {
|
|
|
75
104
|
});
|
|
76
105
|
var old = devices.get(owner);
|
|
77
106
|
if (old && old.ws !== ws) disconnectDevice(old.ws);
|
|
78
|
-
devices.set(owner, { ws: ws, servers: servers, hostConnected: !!msg.hostConnected, extensionId: ctx.extensionId(ws)
|
|
79
|
-
|
|
107
|
+
devices.set(owner, { ws: ws, servers: servers, hostConnected: !!msg.hostConnected, extensionId: ctx.extensionId(ws), manager: manager,
|
|
108
|
+
authorized: function () { return ctx.clients.has(ws) && ownerFor(ws) === owner && ctx.canUseOwner(owner); },
|
|
109
|
+
send: function (message) { ctx.sendTo(ws, Object.assign({ slug: ctx.slug }, message)); } });
|
|
110
|
+
announce(owner); return true;
|
|
80
111
|
}
|
|
81
112
|
if (msg.type === 'mcp_tool_result' || msg.type === 'mcp_tool_error') {
|
|
82
113
|
var call = pending.get(msg.callId);
|
|
@@ -114,35 +145,42 @@ function attachMcp(ctx) {
|
|
|
114
145
|
if (!row || !row.tools.some(function (item) { return item.name === tool; })) throw new Error('Computer tool is unavailable.');
|
|
115
146
|
var id = crypto.randomUUID();
|
|
116
147
|
var timer = setTimeout(function () { pending.delete(id); reject(new Error('Computer tool timed out.')); }, 60000);
|
|
117
|
-
pending.set(id, { owner: owner, ws: device.ws, resolve: resolve, reject: reject, timer: timer, authorize: function () {
|
|
148
|
+
pending.set(id, { owner: owner, ws: device.ws, manager: manager, resolve: resolve, reject: reject, timer: timer, authorize: function () {
|
|
118
149
|
authorize(); if (!enabled(owner, server) || deviceFor(owner) !== device) throw new Error('Computer access changed.');
|
|
119
150
|
} });
|
|
120
|
-
|
|
151
|
+
device.send({ type: 'mcp_tool_call', callId: id, server: server, method: 'tools/call', params: { name: tool, arguments: args } });
|
|
121
152
|
});
|
|
122
153
|
}
|
|
123
|
-
function getMcpServers(session) {
|
|
124
|
-
if (!session || !ctx.canUseSession(session)) return {};
|
|
154
|
+
function getMcpServers(session, allowManagement) {
|
|
155
|
+
if (!session || !ctx.canUseSession(session) || !require('./yoke/session-tool-transport').capability(ctx.sessionVendor ? ctx.sessionVendor(session) : session.vendor || 'claude').supported) return {};
|
|
125
156
|
var owner = ctx.isMultiUser() ? String(session.ownerId) : 'default';
|
|
126
157
|
function authorize() {
|
|
127
158
|
authorizeOwner(owner);
|
|
128
159
|
if (!ctx.canUseSession(session) || (ctx.isMultiUser() && String(session.ownerId) !== owner)) throw new Error('Session MCP access changed.');
|
|
129
160
|
}
|
|
130
|
-
var result = {};
|
|
161
|
+
var result = {}, management = allowManagement === false ? null : agentTools.getServer(session);
|
|
162
|
+
if (management) result['clay-mcp-connections'] = management;
|
|
131
163
|
buildState(owner).servers.forEach(function (server) {
|
|
132
164
|
if (!server.projectEnabled || !server.extensionEnabled || !server.tools.length) return;
|
|
133
165
|
try {
|
|
134
166
|
result[server.name] = createProxy(server.name, server.tools, function (tool, args) {
|
|
135
|
-
return server.source
|
|
167
|
+
return server.source !== 'computer' ? remote.call(owner, server.id, tool, args, authorize) : callComputer(owner, server.name, tool, args, authorize);
|
|
136
168
|
});
|
|
137
169
|
} catch (error) { /* Unsupported schemas are not advertised as callable tools. */ }
|
|
138
170
|
});
|
|
139
171
|
return result;
|
|
140
172
|
}
|
|
141
173
|
function destroy() {
|
|
142
|
-
|
|
143
|
-
devices.
|
|
174
|
+
var removedSockets = [];
|
|
175
|
+
devices.forEach(function (device, owner) { if (device.manager === manager) { removedSockets.push(device.ws); devices.delete(owner); } });
|
|
176
|
+
pending.forEach(function (call, id) {
|
|
177
|
+
if (call.manager === manager || removedSockets.indexOf(call.ws) >= 0) { clearTimeout(call.timer); call.reject(new Error('MCP closed.')); pending.delete(id); }
|
|
178
|
+
});
|
|
179
|
+
agentTools.destroy(); remote.destroy(); discovery.destroy();
|
|
180
|
+
registry.managers.delete(manager);
|
|
181
|
+
if (!registry.managers.size) SHARED_REGISTRIES.delete(namespace);
|
|
144
182
|
}
|
|
145
|
-
return { handleMcpMessage: handleMcpMessage, getMcpServers: getMcpServers, sendConnectionState: sendConnectionState,
|
|
183
|
+
return { registerConsentViewer: agentTools.registerViewer, handleMcpMessage: handleMcpMessage, getMcpServers: getMcpServers, sendConnectionState: sendConnectionState,
|
|
146
184
|
handleExtensionDisconnect: disconnectDevice, rebuildAndBroadcast: function () { devices.forEach(function (device, owner) { broadcast(owner); }); }, destroy: destroy };
|
|
147
185
|
}
|
|
148
186
|
module.exports = { attachMcp: attachMcp };
|
package/lib/project-models.js
CHANGED
|
@@ -331,48 +331,30 @@ function attachModels(ctx) {
|
|
|
331
331
|
});
|
|
332
332
|
}
|
|
333
333
|
|
|
334
|
+
async function selectSessionModel(session, model, vendor, options) {
|
|
335
|
+
if (!session || sm.sessions.get(session.localId) !== session) throw new Error("Session was deleted or replaced.");
|
|
336
|
+
var sessionVendor = session.vendor || sm.defaultVendor || "claude";
|
|
337
|
+
if (vendor && vendor !== sessionVendor) throw new Error("The session vendor changed before model selection.");
|
|
338
|
+
var models = (sm.modelsByVendor && sm.modelsByVendor[sessionVendor]) || [];
|
|
339
|
+
if (models.length && !models.some(function (entry) { return modelEntryMatches(entry, model); })) throw new Error("That model is not available for the selected vendor.");
|
|
340
|
+
return sdk.setModel(session, model, options);
|
|
341
|
+
}
|
|
342
|
+
|
|
334
343
|
async function selectModel(ws, msg) {
|
|
335
344
|
var session = getSessionForWs(ws);
|
|
336
345
|
if (!session) {
|
|
337
346
|
sendTo(ws, { type: "model_selection_result", requestId: msg.requestId || null, ok: false, error: "No active session." });
|
|
338
347
|
return;
|
|
339
348
|
}
|
|
340
|
-
var
|
|
341
|
-
|
|
342
|
-
|
|
343
|
-
type: "model_selection_result",
|
|
344
|
-
requestId: msg.requestId || null,
|
|
345
|
-
ok: false,
|
|
346
|
-
error: "The session vendor changed before the model selection completed.",
|
|
347
|
-
});
|
|
348
|
-
return;
|
|
349
|
-
}
|
|
350
|
-
var knownModels = (sm.modelsByVendor && sm.modelsByVendor[sessionVendor]) || [];
|
|
351
|
-
if (knownModels.length > 0) {
|
|
352
|
-
var known = false;
|
|
353
|
-
for (var i = 0; i < knownModels.length; i++) {
|
|
354
|
-
if (modelEntryMatches(knownModels[i], msg.model)) {
|
|
355
|
-
known = true;
|
|
356
|
-
break;
|
|
357
|
-
}
|
|
358
|
-
}
|
|
359
|
-
if (!known) {
|
|
360
|
-
sendTo(ws, {
|
|
361
|
-
type: "model_selection_result",
|
|
362
|
-
requestId: msg.requestId || null,
|
|
363
|
-
ok: false,
|
|
364
|
-
error: "That model is not available for the selected vendor.",
|
|
365
|
-
});
|
|
366
|
-
return;
|
|
367
|
-
}
|
|
368
|
-
}
|
|
369
|
-
var result = await sdk.setModel(session, msg.model);
|
|
349
|
+
var result;
|
|
350
|
+
try { result = await selectSessionModel(session, msg.model, msg.vendor); }
|
|
351
|
+
catch (error) { result = { ok: false, error: error.message }; }
|
|
370
352
|
sendTo(ws, {
|
|
371
353
|
type: "model_selection_result",
|
|
372
354
|
requestId: msg.requestId || null,
|
|
373
355
|
ok: !!(result && result.ok),
|
|
374
356
|
model: result && result.model ? result.model : msg.model,
|
|
375
|
-
vendor:
|
|
357
|
+
vendor: session.vendor || sm.defaultVendor || "claude",
|
|
376
358
|
error: result && result.error ? result.error : "",
|
|
377
359
|
});
|
|
378
360
|
}
|
|
@@ -400,6 +382,7 @@ function attachModels(ctx) {
|
|
|
400
382
|
resolveConfiguredModel: resolveConfiguredModel,
|
|
401
383
|
loadVendorModels: loadVendorModels,
|
|
402
384
|
selectModel: selectModel,
|
|
385
|
+
selectSessionModel: selectSessionModel,
|
|
403
386
|
};
|
|
404
387
|
}
|
|
405
388
|
|
|
@@ -154,6 +154,21 @@ function attachNotifications(ctx) {
|
|
|
154
154
|
return notifications.length;
|
|
155
155
|
}
|
|
156
156
|
|
|
157
|
+
function controlProjection(item) { var value = Object.assign({}, item); delete value.controlRevision; return Object.assign(value, { controlRevision: require('./clay-control-target-projection').digest(value) }); }
|
|
158
|
+
function visible(ws) {
|
|
159
|
+
return notifications.filter(function (notification) { return !ctx.canView || ctx.canView(ws, notification); }).map(controlProjection);
|
|
160
|
+
}
|
|
161
|
+
|
|
162
|
+
function publish(payload) {
|
|
163
|
+
if (!ctx.forEachClient) return broadcastAll(payload);
|
|
164
|
+
ctx.forEachClient(function (ws) {
|
|
165
|
+
if (ws.readyState !== 1) return;
|
|
166
|
+
if (payload.notification && !ctx.canView(ws, payload.notification)) return;
|
|
167
|
+
var list = visible(ws);
|
|
168
|
+
ws.send(JSON.stringify(Object.assign({}, payload, { notification: payload.notification ? controlProjection(payload.notification) : undefined, unreadCount: list.length })));
|
|
169
|
+
});
|
|
170
|
+
}
|
|
171
|
+
|
|
157
172
|
// --- Core API ---
|
|
158
173
|
|
|
159
174
|
function notify(event, data) {
|
|
@@ -183,12 +198,13 @@ function attachNotifications(ctx) {
|
|
|
183
198
|
saveNotifications();
|
|
184
199
|
var payload = {
|
|
185
200
|
type: "notification_created",
|
|
186
|
-
notification: notif,
|
|
201
|
+
notification: controlProjection(notif),
|
|
187
202
|
unreadCount: getUnreadCount(),
|
|
188
203
|
};
|
|
189
|
-
//
|
|
190
|
-
|
|
191
|
-
|
|
204
|
+
// Project/session previews are projected for each authenticated viewer.
|
|
205
|
+
if (ctx.forEachClient) {
|
|
206
|
+
publish(payload);
|
|
207
|
+
} else if (notif.targetUserId && typeof sendToUser === "function") {
|
|
192
208
|
sendToUser(notif.targetUserId, payload);
|
|
193
209
|
} else {
|
|
194
210
|
broadcastAll(payload);
|
|
@@ -196,12 +212,14 @@ function attachNotifications(ctx) {
|
|
|
196
212
|
return notif;
|
|
197
213
|
}
|
|
198
214
|
|
|
199
|
-
function dismiss(ids) {
|
|
215
|
+
function dismiss(ids, ws) {
|
|
216
|
+
var permitted = visible(ws).map(function (notification) { return notification.id; });
|
|
217
|
+
ids = ids.filter(function (id) { return permitted.indexOf(id) !== -1; });
|
|
200
218
|
var before = notifications.length;
|
|
201
219
|
notifications = notifications.filter(function(n) { return ids.indexOf(n.id) === -1; });
|
|
202
220
|
if (notifications.length !== before) {
|
|
203
221
|
saveNotifications();
|
|
204
|
-
|
|
222
|
+
publish({
|
|
205
223
|
type: "notification_dismissed",
|
|
206
224
|
ids: ids,
|
|
207
225
|
unreadCount: getUnreadCount(),
|
|
@@ -209,12 +227,41 @@ function attachNotifications(ctx) {
|
|
|
209
227
|
}
|
|
210
228
|
}
|
|
211
229
|
|
|
212
|
-
function
|
|
213
|
-
|
|
214
|
-
|
|
215
|
-
|
|
216
|
-
|
|
217
|
-
|
|
230
|
+
function canReadOwned(principal, item) {
|
|
231
|
+
var owner = principal.userId || null;
|
|
232
|
+
return (owner ? (item.targetUserId === owner || item.ownerId === owner) && (!item.targetUserId || item.targetUserId === owner) : !item.ownerId && !item.targetUserId) &&
|
|
233
|
+
(!ctx.canViewPrincipal || ctx.canViewPrincipal(principal, item));
|
|
234
|
+
}
|
|
235
|
+
function authorizeOwned(principal, items) {
|
|
236
|
+
if (items.some(function (item) { return !canReadOwned(principal, item); })) throw new Error('Owned notification access changed.');
|
|
237
|
+
}
|
|
238
|
+
function listOwned(principal) {
|
|
239
|
+
return notifications.filter(function (item) { return canReadOwned(principal, item); }).slice(0, 100).map(function (item) { return JSON.parse(JSON.stringify(controlProjection(item))); });
|
|
240
|
+
}
|
|
241
|
+
function inspectOwned(principal, ids) {
|
|
242
|
+
var owned = listOwned(principal);
|
|
243
|
+
return ids.map(function (id) {
|
|
244
|
+
var item = owned.find(function (entry) { return entry.id === id; });
|
|
245
|
+
if (!item) throw new Error('The exact owned notification is absent or inaccessible.');
|
|
246
|
+
return item;
|
|
247
|
+
});
|
|
248
|
+
}
|
|
249
|
+
function dismissOwned(principal, ids, revalidate) {
|
|
250
|
+
revalidate(); inspectOwned(principal, ids);
|
|
251
|
+
var previous = notifications;
|
|
252
|
+
notifications = notifications.filter(function (item) { return ids.indexOf(item.id) < 0; });
|
|
253
|
+
var tmp = NOTIF_FILE + '.tmp';
|
|
254
|
+
try { fs.writeFileSync(tmp, JSON.stringify(notifications, null, 2)); fs.renameSync(tmp, NOTIF_FILE); }
|
|
255
|
+
catch (error) { notifications = previous; throw error; }
|
|
256
|
+
// Use the ordinary per-viewer notification state; no private IDs are broadcast.
|
|
257
|
+
var published = true;
|
|
258
|
+
if (ctx.forEachClient) ctx.forEachClient(function (ws) { try { sendConnectionState(ws, function (client, payload) { if (client.readyState === 1) client.send(JSON.stringify(payload)); }); } catch (error) { published = false; } });
|
|
259
|
+
try { revalidate(); } catch (error) { return { status: 'failed', persisted: true, dismissedIds: ids, error: error.message, retrySafe: false }; }
|
|
260
|
+
return { status: published ? 'completed' : 'failed', persisted: true, dismissedIds: ids, viewerPublication: published ? 'sent' : 'partial', retrySafe: false };
|
|
261
|
+
}
|
|
262
|
+
|
|
263
|
+
function dismissAll(ws) {
|
|
264
|
+
dismiss(visible(ws).map(function (notification) { return notification.id; }), ws);
|
|
218
265
|
}
|
|
219
266
|
|
|
220
267
|
// --- Periodic reminder ---
|
|
@@ -222,8 +269,15 @@ function attachNotifications(ctx) {
|
|
|
222
269
|
function startReminder() {
|
|
223
270
|
if (reminderTimer) return;
|
|
224
271
|
reminderTimer = setInterval(function () {
|
|
272
|
+
if (ctx.canView && ctx.getUsers && pushModule && pushModule.sendPushToUser) {
|
|
273
|
+
ctx.getUsers().forEach(function (user) {
|
|
274
|
+
var count = visible({ _clayUser: user }).length;
|
|
275
|
+
if (count) pushModule.sendPushToUser(user.id, { type: "reminder", title: "Clay", body: count + " unread notification" + (count > 1 ? "s" : ""), tag: "clay-notif-reminder" });
|
|
276
|
+
});
|
|
277
|
+
return;
|
|
278
|
+
}
|
|
225
279
|
var count = getUnreadCount();
|
|
226
|
-
if (count > 0 && pushModule) {
|
|
280
|
+
if (count > 0 && pushModule && !ctx.canView) {
|
|
227
281
|
pushModule.sendPush({
|
|
228
282
|
type: "reminder",
|
|
229
283
|
title: "Clay",
|
|
@@ -244,10 +298,11 @@ function attachNotifications(ctx) {
|
|
|
244
298
|
|
|
245
299
|
function sendConnectionState(ws, sendTo) {
|
|
246
300
|
if (!sendTo) return;
|
|
301
|
+
var list = visible(ws);
|
|
247
302
|
sendTo(ws, {
|
|
248
303
|
type: "notifications_state",
|
|
249
|
-
notifications:
|
|
250
|
-
unreadCount:
|
|
304
|
+
notifications: list,
|
|
305
|
+
unreadCount: list.length,
|
|
251
306
|
});
|
|
252
307
|
}
|
|
253
308
|
|
|
@@ -255,17 +310,21 @@ function attachNotifications(ctx) {
|
|
|
255
310
|
|
|
256
311
|
function handleNotificationMessage(ws, msg) {
|
|
257
312
|
if (msg.type === "notification_dismiss") {
|
|
258
|
-
dismiss(msg.ids || []);
|
|
313
|
+
dismiss(msg.ids || [], ws);
|
|
259
314
|
return true;
|
|
260
315
|
}
|
|
261
316
|
if (msg.type === "notification_dismiss_all") {
|
|
262
|
-
dismissAll();
|
|
317
|
+
dismissAll(ws);
|
|
263
318
|
return true;
|
|
264
319
|
}
|
|
265
320
|
return false;
|
|
266
321
|
}
|
|
267
322
|
|
|
268
323
|
return {
|
|
324
|
+
authorizeOwned: authorizeOwned,
|
|
325
|
+
listOwned: listOwned,
|
|
326
|
+
inspectOwned: inspectOwned,
|
|
327
|
+
dismissOwned: dismissOwned,
|
|
269
328
|
notify: notify,
|
|
270
329
|
getUnreadCount: getUnreadCount,
|
|
271
330
|
sendConnectionState: sendConnectionState,
|