clay-server 5.2.0-beta.1 → 5.2.0-beta.10
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/lib/account-auth-socket.js +1 -0
- package/lib/builtin-mates.js +19 -16
- package/lib/bundled-skills/clay-agent-browser/SKILL.md +6 -2
- package/lib/canonical-clay-record-authority.js +15 -0
- package/lib/canonical-clay-scheduling-authority.js +19 -0
- package/lib/claude-hook-installer.js +1 -239
- package/lib/claude-jsonl-watcher.js +1 -204
- package/lib/clay-control-presentation-binding.js +96 -0
- package/lib/clay-control-presentation.js +128 -0
- package/lib/clay-control-target-projection.js +26 -0
- package/lib/clay-mate-chat-receipts.js +26 -0
- package/lib/clay-mate-chat.js +88 -0
- package/lib/clay-mate-knowledge-input.js +26 -0
- package/lib/clay-mate-knowledge.js +95 -0
- package/lib/clay-mate-lifecycle.js +95 -0
- package/lib/clay-product-control-input.js +33 -0
- package/lib/clay-product-control-tools.js +51 -0
- package/lib/clay-product-control.js +247 -0
- package/lib/clay-project-lifecycle.js +154 -0
- package/lib/clay-project-record-input.js +44 -0
- package/lib/clay-project-records.js +84 -0
- package/lib/clay-scheduling-input.js +21 -0
- package/lib/clay-scheduling-receipts.js +26 -0
- package/lib/clay-scheduling.js +119 -0
- package/lib/clay-screen-controls.js +104 -0
- package/lib/clay-skill-install.js +1 -33
- package/lib/clay-workspace-controls.js +84 -0
- package/lib/clay-workspace-input.js +17 -0
- package/lib/clay-workspace-receipts.js +26 -0
- package/lib/cli-sessions.js +1 -300
- package/lib/codex-defaults.js +1 -28
- package/lib/context-usage.js +3 -2
- package/lib/contextual-screen-snapshot.js +38 -0
- package/lib/daemon-project-access.js +11 -0
- package/lib/daemon-project-lifecycle-callbacks.js +15 -0
- package/lib/daemon-project-lifecycle.js +262 -0
- package/lib/daemon-projects.js +1 -1
- package/lib/daemon.js +78 -276
- package/lib/default-ai-runtime.js +4 -8
- package/lib/dm-digest-cursor.js +120 -0
- package/lib/email-mcp-server.js +1 -1
- package/lib/issues-service.js +29 -15
- package/lib/kiro-defaults.js +1 -22
- package/lib/knowledge-db-import-validation.js +46 -0
- package/lib/knowledge-db-import.js +99 -0
- package/lib/knowledge-db-service.js +24 -33
- package/lib/knowledge-db-storage-nedb-maintenance.js +99 -0
- package/lib/knowledge-db-storage-nedb.js +66 -0
- package/lib/knowledge-db-storage.js +72 -0
- package/lib/knowledge-db-validation.js +0 -0
- package/lib/knowledge-document-index.js +2 -1
- package/lib/knowledge-file-store.js +7 -1
- package/lib/knowledge-product-operations.js +46 -0
- package/lib/mate-avatar-catalog.js +12 -0
- package/lib/mate-avatar-migration.js +41 -0
- package/lib/mate-context-service.js +138 -0
- package/lib/mate-context-tools.js +21 -0
- package/lib/mate-creation-mcp-server.js +2 -0
- package/lib/mate-knowledge-canonical-access.js +10 -0
- package/lib/mate-knowledge-mate-bound.js +53 -0
- package/lib/mate-knowledge-mcp-server.js +55 -8
- package/lib/mate-knowledge-service.js +16 -34
- package/lib/mate-knowledge-text-tools.js +106 -0
- package/lib/mate-lifecycle-service.js +94 -0
- package/lib/mate-message-delivery.js +43 -0
- package/lib/mate-ready-creation.js +9 -1
- package/lib/mate-schedule-input.js +29 -0
- package/lib/mate-schedule-lifecycle.js +151 -0
- package/lib/mate-scheduling.js +103 -0
- package/lib/mates.js +18 -6
- package/lib/mcp-agent-tools.js +117 -0
- package/lib/mcp-connection-store.js +119 -15
- package/lib/mcp-import-credentials.js +31 -0
- package/lib/mcp-local-transport.js +13 -0
- package/lib/mcp-oauth.js +8 -6
- package/lib/mcp-proxy.js +2 -32
- package/lib/mcp-query-bridge.js +30 -0
- package/lib/mcp-remote-connections.js +74 -20
- package/lib/mcp-source-adapters.js +1 -0
- package/lib/mcp-source-context.js +1 -0
- package/lib/mcp-source-discovery.js +1 -0
- package/lib/mcp-source-plugins.js +1 -0
- package/lib/mcp-source-restrictions.js +1 -0
- package/lib/mcp-tool-policy.js +9 -0
- package/lib/notes-checklist.js +50 -0
- package/lib/notes.js +49 -3
- package/lib/os-user-diagnostics.js +2 -4
- package/lib/os-users.js +24 -70
- package/lib/pane-pending-interactions.js +20 -0
- package/lib/pane-session-activation.js +114 -0
- package/lib/pane-session-transport.js +26 -0
- package/lib/project-admin-overview.js +51 -0
- package/lib/project-ask-user.js +8 -4
- package/lib/project-connection.js +14 -10
- package/lib/project-control-git-view.js +12 -0
- package/lib/project-debate.js +1 -0
- package/lib/project-delegated-follow-up.js +2 -1
- package/lib/project-directory-claim.js +65 -0
- package/lib/project-file-operations.js +61 -0
- package/lib/project-filesystem.js +15 -85
- package/lib/project-full-access.js +23 -2
- package/lib/project-http.js +7 -4
- package/lib/project-knowledge.js +32 -18
- package/lib/project-lifecycle-operations.js +98 -0
- package/lib/project-lifecycle-process-witness.js +32 -0
- package/lib/project-lifecycle-runtime.js +50 -0
- package/lib/project-linux-access.js +22 -0
- package/lib/project-logs-canonical-clay.js +27 -0
- package/lib/project-logs-clay-query.js +16 -0
- package/lib/project-logs-schema.js +4 -2
- package/lib/project-logs-service.js +8 -7
- package/lib/project-logs.js +1 -0
- package/lib/project-loop.js +1 -0
- package/lib/project-mate-chat-control.js +55 -0
- package/lib/project-mate-creation-proposal.js +18 -3
- package/lib/project-mate-interaction.js +40 -62
- package/lib/project-mcp.js +54 -16
- package/lib/project-models.js +14 -31
- package/lib/project-notifications.js +76 -17
- package/lib/project-ownership.js +77 -0
- package/lib/project-pair-result-delivery.js +14 -3
- package/lib/project-pair-usage.js +12 -13
- package/lib/project-pending-message-queue.js +4 -1
- package/lib/project-product-control.js +89 -0
- package/lib/project-product-session-queue.js +46 -0
- package/lib/project-push-access.js +28 -0
- package/lib/project-scheduled-message-queue.js +30 -0
- package/lib/project-scheduled-messages.js +67 -68
- package/lib/project-scheduled-task-control.js +83 -0
- package/lib/project-scheduled-tasks.js +13 -2
- package/lib/project-scheduling-access.js +10 -0
- package/lib/project-session-actions.js +65 -0
- package/lib/project-session-delete.js +8 -1
- package/lib/project-session-document.js +27 -7
- package/lib/project-session-github.js +63 -19
- package/lib/project-session-history-actions.js +167 -0
- package/lib/project-session-linear.js +14 -6
- package/lib/project-session-notes.js +7 -3
- package/lib/project-session-pair.js +1 -1
- package/lib/project-session-runtime-actions.js +64 -0
- package/lib/project-session-spawn.js +2 -3
- package/lib/project-session-vendor.js +55 -0
- package/lib/project-sessions.js +103 -272
- package/lib/project-shared-browser.js +78 -17
- package/lib/project-studio-presentation.js +58 -0
- package/lib/project-user-message.js +67 -1
- package/lib/project-vendor-login.js +6 -36
- package/lib/project-workspace-operations.js +126 -0
- package/lib/project-workspace-query.js +19 -2
- package/lib/project.js +178 -45
- package/lib/public/app.js +46 -0
- package/lib/public/appearance-bootstrap.js +16 -0
- package/lib/public/css/clay-tool-activity.css +51 -0
- package/lib/public/css/clay-workspace.css +29 -0
- package/lib/public/css/command-palette.css +12 -33
- package/lib/public/css/contextual-clay.css +240 -0
- package/lib/public/css/home-debate-planning.css +2 -0
- package/lib/public/css/home-mate-creation.css +5 -0
- package/lib/public/css/input.css +6 -0
- package/lib/public/css/mate-avatar-gallery.css +12 -0
- package/lib/public/css/mate-conversation.css +10 -5
- package/lib/public/css/messages.css +6 -2
- package/lib/public/css/overlays.css +4 -2
- package/lib/public/css/project-admin-overview.css +13 -0
- package/lib/public/css/session-folders.css +11 -0
- package/lib/public/css/session-github.css +46 -1
- package/lib/public/css/shared-browser.css +35 -1
- package/lib/public/css/sticky-notes.css +87 -1
- package/lib/public/index.html +11 -5
- package/lib/public/mate-avatars/B01.png +0 -0
- package/lib/public/mate-avatars/B02.png +0 -0
- package/lib/public/mate-avatars/B03.png +0 -0
- package/lib/public/mate-avatars/B04.png +0 -0
- package/lib/public/mate-avatars/B05.png +0 -0
- package/lib/public/mate-avatars/B06.png +0 -0
- package/lib/public/mate-avatars/B07.png +0 -0
- package/lib/public/mate-avatars/B08.png +0 -0
- package/lib/public/mate-avatars/B09.png +0 -0
- package/lib/public/mate-avatars/B10.png +0 -0
- package/lib/public/mate-avatars/B11.png +0 -0
- package/lib/public/mate-avatars/B12.png +0 -0
- package/lib/public/mate-avatars/B13.png +0 -0
- package/lib/public/mate-avatars/B14.png +0 -0
- package/lib/public/mate-avatars/B15.png +0 -0
- package/lib/public/mate-avatars/B16.png +0 -0
- package/lib/public/mate-avatars/B17.png +0 -0
- package/lib/public/mate-avatars/B18.png +0 -0
- package/lib/public/mate-avatars/B19.png +0 -0
- package/lib/public/mate-avatars/B20.png +0 -0
- package/lib/public/mate-avatars/B21.png +0 -0
- package/lib/public/mate-avatars/B22.png +0 -0
- package/lib/public/mate-avatars/B23.png +0 -0
- package/lib/public/mate-avatars/B24.png +0 -0
- package/lib/public/mate-avatars/B25.png +0 -0
- package/lib/public/mate-avatars/B26.png +0 -0
- package/lib/public/mate-avatars/B27.png +0 -0
- package/lib/public/mate-avatars/B28.png +0 -0
- package/lib/public/mate-avatars/B29.png +0 -0
- package/lib/public/mate-avatars/B30.png +0 -0
- package/lib/public/mate-avatars/B31.png +0 -0
- package/lib/public/mate-avatars/B32.png +0 -0
- package/lib/public/mate-avatars/B33.png +0 -0
- package/lib/public/mate-avatars/B34.png +0 -0
- package/lib/public/mate-avatars/B35.png +0 -0
- package/lib/public/mate-avatars/B36.png +0 -0
- package/lib/public/mate-avatars/B37.png +0 -0
- package/lib/public/mate-avatars/B38.png +0 -0
- package/lib/public/mate-avatars/B39.png +0 -0
- package/lib/public/mate-avatars/B40.png +0 -0
- package/lib/public/mate-avatars/B41.png +0 -0
- package/lib/public/mate-avatars/B42.png +0 -0
- package/lib/public/mate-avatars/B43.png +0 -0
- package/lib/public/mate-avatars/B44.png +0 -0
- package/lib/public/mate-avatars/B45.png +0 -0
- package/lib/public/mate-avatars/B46.png +0 -0
- package/lib/public/mate-avatars/B47.png +0 -0
- package/lib/public/mate-avatars/B48.png +0 -0
- package/lib/public/mate-avatars/C01.png +0 -0
- package/lib/public/mate-avatars/C02.png +0 -0
- package/lib/public/mate-avatars/C03.png +0 -0
- package/lib/public/mate-avatars/C04.png +0 -0
- package/lib/public/mate-avatars/C05.png +0 -0
- package/lib/public/mate-avatars/C06.png +0 -0
- package/lib/public/mate-avatars/C07.png +0 -0
- package/lib/public/mate-avatars/C08.png +0 -0
- package/lib/public/mate-avatars/C09.png +0 -0
- package/lib/public/mate-avatars/C10.png +0 -0
- package/lib/public/mate-avatars/C11.png +0 -0
- package/lib/public/mate-avatars/C12.png +0 -0
- package/lib/public/mate-avatars/C13.png +0 -0
- package/lib/public/mate-avatars/C14.png +0 -0
- package/lib/public/mate-avatars/C15.png +0 -0
- package/lib/public/mate-avatars/C16.png +0 -0
- package/lib/public/mate-avatars/C17.png +0 -0
- package/lib/public/mate-avatars/C18.png +0 -0
- package/lib/public/mate-avatars/C19.png +0 -0
- package/lib/public/mate-avatars/C20.png +0 -0
- package/lib/public/mate-avatars/C21.png +0 -0
- package/lib/public/mate-avatars/C22.png +0 -0
- package/lib/public/mate-avatars/C23.png +0 -0
- package/lib/public/mate-avatars/C24.png +0 -0
- package/lib/public/mate-avatars/C25.png +0 -0
- package/lib/public/mate-avatars/C26.png +0 -0
- package/lib/public/mate-avatars/C27.png +0 -0
- package/lib/public/mate-avatars/C28.png +0 -0
- package/lib/public/mate-avatars/C29.png +0 -0
- package/lib/public/mate-avatars/C30.png +0 -0
- package/lib/public/mate-avatars/C31.png +0 -0
- package/lib/public/mate-avatars/C32.png +0 -0
- package/lib/public/mate-avatars/C33.png +0 -0
- package/lib/public/mate-avatars/C34.png +0 -0
- package/lib/public/mate-avatars/C35.png +0 -0
- package/lib/public/mate-avatars/C36.png +0 -0
- package/lib/public/mate-avatars/C37.png +0 -0
- package/lib/public/mate-avatars/C38.png +0 -0
- package/lib/public/mate-avatars/C39.png +0 -0
- package/lib/public/mate-avatars/C40.png +0 -0
- package/lib/public/mate-avatars/C41.png +0 -0
- package/lib/public/mate-avatars/C42.png +0 -0
- package/lib/public/mate-avatars/C43.png +0 -0
- package/lib/public/mate-avatars/C44.png +0 -0
- package/lib/public/mate-avatars/C45.png +0 -0
- package/lib/public/mate-avatars/C46.png +0 -0
- package/lib/public/mate-avatars/C47.png +0 -0
- package/lib/public/mate-avatars/C48.png +0 -0
- package/lib/public/mate-avatars/catalog.json +482 -0
- package/lib/public/mate-avatars/lead-clay.png +0 -0
- package/lib/public/modules/admin-settings-projects.js +6 -2
- package/lib/public/modules/app-connection.js +11 -1
- package/lib/public/modules/app-favicon.js +18 -9
- package/lib/public/modules/app-header.js +7 -4
- package/lib/public/modules/app-loop-ui.js +2 -0
- package/lib/public/modules/app-message-router.js +22 -1
- package/lib/public/modules/app-messages.js +115 -17
- package/lib/public/modules/app-misc.js +3 -1
- package/lib/public/modules/app-notifications.js +11 -5
- package/lib/public/modules/app-panels.js +61 -123
- package/lib/public/modules/app-projects.js +13 -0
- package/lib/public/modules/app-rate-limit.js +7 -27
- package/lib/public/modules/app-rendering.js +4 -3
- package/lib/public/modules/avatar.js +15 -41
- package/lib/public/modules/chat-render-runtime.js +20 -0
- package/lib/public/modules/clay-browser-links.js +47 -0
- package/lib/public/modules/clay-control-activity.js +214 -0
- package/lib/public/modules/clay-control-copy.js +36 -0
- package/lib/public/modules/clay-control-detail-targets.js +44 -0
- package/lib/public/modules/clay-control-object-targets.js +52 -0
- package/lib/public/modules/clay-control-target-visibility.js +12 -0
- package/lib/public/modules/clay-control-targets.js +44 -0
- package/lib/public/modules/clay-log-links.js +23 -0
- package/lib/public/modules/clay-navigation-render.js +52 -0
- package/lib/public/modules/clay-owner-navigation.js +33 -0
- package/lib/public/modules/clay-session-links.js +31 -0
- package/lib/public/modules/clay-studio-bridge.js +20 -0
- package/lib/public/modules/clay-studio-document.js +67 -0
- package/lib/public/modules/clay-studio-render.js +146 -0
- package/lib/public/modules/clay-tool-activity.js +140 -0
- package/lib/public/modules/clay-tool-presentation.js +342 -0
- package/lib/public/modules/command-palette.js +162 -40
- package/lib/public/modules/contextual-ask-session.js +26 -0
- package/lib/public/modules/contextual-clay-geometry.js +155 -0
- package/lib/public/modules/contextual-clay-session.js +130 -0
- package/lib/public/modules/contextual-clay-workspace.js +169 -0
- package/lib/public/modules/contextual-clay.js +250 -0
- package/lib/public/modules/contextual-composer.js +91 -0
- package/lib/public/modules/contextual-mate-context.js +117 -0
- package/lib/public/modules/contextual-mate-hint.js +40 -0
- package/lib/public/modules/contextual-mate-identity.js +23 -0
- package/lib/public/modules/contextual-mate-sessions.js +134 -0
- package/lib/public/modules/contextual-search.js +137 -0
- package/lib/public/modules/contextual-session-citations.js +58 -0
- package/lib/public/modules/debate.js +1 -0
- package/lib/public/modules/default-ai.js +11 -3
- package/lib/public/modules/elicitation-form.js +5 -0
- package/lib/public/modules/filebrowser.js +20 -1
- package/lib/public/modules/generation-stop.js +8 -5
- package/lib/public/modules/git-panel.js +3 -1
- package/lib/public/modules/history-replay-batch.js +13 -1
- package/lib/public/modules/home-debate-live.js +2 -0
- package/lib/public/modules/home-debate-planning.js +7 -7
- package/lib/public/modules/home-mate-avatar-editor.js +127 -208
- package/lib/public/modules/home-mate-chat.js +8 -6
- package/lib/public/modules/home-mate-creation.js +73 -1
- package/lib/public/modules/home-mate-settings.js +19 -12
- package/lib/public/modules/icon-strip-tooltip.js +2 -1
- package/lib/public/modules/input.js +88 -10
- package/lib/public/modules/issues-render.js +3 -2
- package/lib/public/modules/knowledge-db-workbench.js +4 -4
- package/lib/public/modules/markdown.js +6 -34
- package/lib/public/modules/mate-avatar-catalog.js +97 -0
- package/lib/public/modules/mate-knowledge-workbench.js +1 -1
- package/lib/public/modules/mate-management.js +40 -7
- package/lib/public/modules/mcp-connection-view.js +31 -13
- package/lib/public/modules/mcp-discovery-view.js +31 -0
- package/lib/public/modules/mcp-ui.js +23 -4
- package/lib/public/modules/mention.js +3 -0
- package/lib/public/modules/message-delivery.js +20 -2
- package/lib/public/modules/model-picker.js +2 -0
- package/lib/public/modules/pane-activation.js +214 -0
- package/lib/public/modules/pane-binding.js +82 -0
- package/lib/public/modules/pane-bridge.js +7 -4
- package/lib/public/modules/pane-browser-bridge.js +22 -0
- package/lib/public/modules/pane-file-bridge.js +4 -0
- package/lib/public/modules/pane-issue-bridge.js +4 -1
- package/lib/public/modules/pending-message-queue.js +1 -0
- package/lib/public/modules/permission-control.js +5 -4
- package/lib/public/modules/personal-settings-dialog.js +7 -1
- package/lib/public/modules/product-review.js +26 -0
- package/lib/public/modules/profile.js +1 -238
- package/lib/public/modules/project-access-recovery.js +17 -0
- package/lib/public/modules/project-admin-overview.js +21 -0
- package/lib/public/modules/project-chat-identity.js +13 -4
- package/lib/public/modules/project-logs-render.js +3 -0
- package/lib/public/modules/project-mate-navigation.js +144 -22
- package/lib/public/modules/rewind.js +5 -0
- package/lib/public/modules/scheduled-tasks.js +2 -0
- package/lib/public/modules/scheduler.js +2 -0
- package/lib/public/modules/search-clay-chat.js +5 -440
- package/lib/public/modules/session-actions.js +5 -2
- package/lib/public/modules/session-context-menu.js +5 -0
- package/lib/public/modules/session-create-form.js +10 -10
- package/lib/public/modules/session-folder-layout.js +1 -1
- package/lib/public/modules/session-folder-view-menu.js +9 -0
- package/lib/public/modules/session-github.js +85 -14
- package/lib/public/modules/session-rich-drafts.js +21 -0
- package/lib/public/modules/session-switch-defer.js +67 -0
- package/lib/public/modules/session-work-primary.js +51 -0
- package/lib/public/modules/settings-defaults.js +27 -28
- package/lib/public/modules/shared-browser-settings.js +112 -0
- package/lib/public/modules/shared-browser-tabs.js +13 -3
- package/lib/public/modules/shared-browser.js +29 -6
- package/lib/public/modules/sidebar-mobile.js +4 -3
- package/lib/public/modules/sidebar-projects.js +1 -0
- package/lib/public/modules/sidebar-session-folders-ui.js +1 -1
- package/lib/public/modules/sidebar-sessions.js +1 -0
- package/lib/public/modules/split-group-restore.js +68 -0
- package/lib/public/modules/split-pair-ui.js +1 -0
- package/lib/public/modules/split-pane-reconciler.js +15 -0
- package/lib/public/modules/split-pane-renderer.js +87 -6
- package/lib/public/modules/split-session-boundary.js +1 -1
- package/lib/public/modules/split-view.js +60 -68
- package/lib/public/modules/sticky-note-markdown.js +72 -6
- package/lib/public/modules/sticky-notes-actions.js +30 -0
- package/lib/public/modules/sticky-notes-browser.js +9 -2
- package/lib/public/modules/sticky-notes-card.js +23 -7
- package/lib/public/modules/sticky-notes-checklist.js +116 -0
- package/lib/public/modules/sticky-notes-editor.js +108 -44
- package/lib/public/modules/sticky-notes-shared.js +50 -2
- package/lib/public/modules/sticky-notes-state.js +66 -0
- package/lib/public/modules/sticky-notes.js +34 -51
- package/lib/public/modules/stt-controller.js +4 -1
- package/lib/public/modules/stt-recording.js +1 -1
- package/lib/public/modules/stt.js +7 -2
- package/lib/public/modules/terminal.js +9 -0
- package/lib/public/modules/theme.js +8 -1
- package/lib/public/modules/thinking-lifecycle.js +33 -3
- package/lib/public/modules/thinking-view.js +23 -1
- package/lib/public/modules/tools.js +60 -11
- package/lib/public/modules/tui-grab.js +1 -2
- package/lib/public/modules/user-settings-appearance.js +10 -3
- package/lib/public/modules/user-settings-editors.js +1 -1
- package/lib/public/modules/user-settings-layout.js +11 -2
- package/lib/public/modules/user-settings-preferences.js +6 -2
- package/lib/public/modules/user-settings-profile.js +12 -2
- package/lib/public/modules/user-settings.js +3 -2
- package/lib/public/modules/vendor-login-browser.js +5 -3
- package/lib/public/modules/vendor-login.js +2 -2
- package/lib/public/modules/vendor-priority.js +15 -1
- package/lib/public/modules/wireframe-workbench.js +5 -2
- package/lib/public/muse-avatar.svg +4 -0
- package/lib/public/style.css +5 -0
- package/lib/public/sw.js +3 -1
- package/lib/safe-bash-commands.js +3 -45
- package/lib/scheduled-task-records.js +3 -1
- package/lib/scheduler.js +2 -0
- package/lib/sdk-bridge.js +342 -401
- package/lib/sdk-foreground-admission.js +16 -0
- package/lib/sdk-mcp-descriptors.js +2 -37
- package/lib/sdk-message-processor.js +52 -17
- package/lib/sdk-quota-snapshot.js +1 -1
- package/lib/sdk-response-recovery.js +1 -0
- package/lib/sdk-worker.js +2 -677
- package/lib/server-admin.js +63 -16
- package/lib/server-appearance-settings.js +13 -1
- package/lib/server-contextual-clay-settings.js +40 -0
- package/lib/server-contextual-mate-sessions.js +70 -0
- package/lib/server-dm.js +2 -1
- package/lib/server-global-ws.js +10 -20
- package/lib/server-home-chat-events.js +18 -4
- package/lib/server-home-chat.js +22 -20
- package/lib/server-home-clay-entry.js +23 -4
- package/lib/server-home-clay-session-links.js +29 -9
- package/lib/server-home-mate-creation.js +1 -0
- package/lib/server-home-mcp-consent.js +14 -0
- package/lib/server-mates.js +25 -62
- package/lib/server-owner-ui.js +118 -0
- package/lib/server-path-access.js +38 -0
- package/lib/server-project-removal.js +22 -0
- package/lib/server-settings.js +6 -1
- package/lib/server.js +163 -43
- package/lib/session-config-transition.js +45 -0
- package/lib/session-folders.js +7 -2
- package/lib/session-fork-history.js +21 -0
- package/lib/session-github.js +9 -2
- package/lib/session-hygiene.js +3 -35
- package/lib/session-permission-mode.js +4 -3
- package/lib/session-skill-scope.js +11 -0
- package/lib/session-visibility.js +5 -2
- package/lib/session-work-primary.js +50 -0
- package/lib/sessions.js +64 -99
- package/lib/shared-browser-cookie-sync.js +32 -0
- package/lib/shared-browser-cookies.js +79 -0
- package/lib/shared-browser-runtime.js +25 -9
- package/lib/shared-browser-storage-sync.js +43 -0
- package/lib/shared-browser-storage.js +101 -0
- package/lib/shared-browser-tools.js +2 -1
- package/lib/shared-browser-worker.js +46 -10
- package/lib/terminal-manager.js +65 -6
- package/lib/tool-llm.js +1 -1
- package/lib/tui-transcript-index.js +1 -132
- package/lib/users-contextual-clay-preferences.js +31 -0
- package/lib/users-permissions.js +2 -8
- package/lib/users.js +7 -0
- package/lib/vendor-login-browser.js +1 -11
- package/lib/workspace-assignment-service.js +25 -0
- package/lib/workspace-query-access.js +4 -1
- package/lib/workspace-query-mcp-server.js +1 -1
- package/lib/workspace-query-service.js +13 -2
- package/lib/ws-request.js +1 -0
- package/lib/ws-schema.js +18 -2
- package/lib/yoke/acp-agent-profiles.js +7 -5
- package/lib/yoke/adapters/antigravity.js +3 -14
- package/lib/yoke/adapters/claude-query-contract.js +9 -0
- package/lib/yoke/adapters/claude.js +54 -50
- package/lib/yoke/adapters/codex-query-contract.js +24 -0
- package/lib/yoke/adapters/codex.js +53 -111
- package/lib/yoke/adapters/kiro.js +3 -1
- package/lib/yoke/adapters/muse-query-contract.js +7 -0
- package/lib/yoke/adapters/muse.js +122 -0
- package/lib/yoke/auth-events.js +17 -0
- package/lib/yoke/claude-hook-installer.js +271 -0
- package/lib/yoke/claude-jsonl-watcher.js +204 -0
- package/lib/yoke/claude-maintenance.js +55 -0
- package/lib/yoke/claude-permission-patterns.js +53 -0
- package/lib/yoke/claude-response-recovery.js +155 -0
- package/lib/yoke/claude-transcript-hygiene.js +34 -0
- package/lib/yoke/claude-worker-startup.js +28 -0
- package/lib/yoke/clay-skill-install.js +33 -0
- package/lib/yoke/cli-sessions.js +300 -0
- package/lib/yoke/codex-app-server.js +7 -12
- package/lib/yoke/codex-idle-recovery.js +81 -1
- package/lib/yoke/codex-recovery-admission.js +164 -0
- package/lib/yoke/configuration.js +13 -0
- package/lib/yoke/discovery.js +70 -0
- package/lib/yoke/errors.js +8 -0
- package/lib/yoke/host-environment.js +7 -0
- package/lib/yoke/index.js +9 -51
- package/lib/yoke/interface.js +116 -0
- package/lib/yoke/kiro-acp-server.js +5 -5
- package/lib/yoke/legacy-sessions.js +89 -0
- package/lib/yoke/login-protocol.js +25 -0
- package/lib/yoke/maintenance.js +12 -0
- package/lib/yoke/mcp-proxy.js +32 -0
- package/lib/yoke/mcp-source-adapters.js +91 -0
- package/lib/yoke/mcp-source-context.js +42 -0
- package/lib/yoke/mcp-source-discovery.js +169 -0
- package/lib/yoke/mcp-source-plugins.js +68 -0
- package/lib/yoke/mcp-source-restrictions.js +47 -0
- package/lib/yoke/mcp-tool-policy-normalize.js +28 -0
- package/lib/yoke/model-preferences.js +6 -0
- package/lib/yoke/muse-artifacts.js +36 -0
- package/lib/yoke/muse-controls.js +50 -0
- package/lib/yoke/muse-input.js +64 -0
- package/lib/yoke/muse-items.js +157 -0
- package/lib/yoke/muse-policy.js +52 -0
- package/lib/yoke/muse-query.js +428 -0
- package/lib/yoke/muse-runtime.js +211 -0
- package/lib/yoke/muse-services.js +79 -0
- package/lib/yoke/muse-skills.js +79 -0
- package/lib/yoke/muse-turns.js +71 -0
- package/lib/yoke/options/acp.js +2 -0
- package/lib/yoke/options/antigravity.js +2 -0
- package/lib/yoke/options/claude.js +21 -0
- package/lib/yoke/options/codex-defaults.js +29 -0
- package/lib/yoke/options/codex-settings.js +21 -0
- package/lib/yoke/options/codex.js +6 -0
- package/lib/yoke/options/kiro-defaults.js +22 -0
- package/lib/yoke/options/kiro.js +5 -0
- package/lib/yoke/options/muse.js +5 -0
- package/lib/yoke/provider-contract.js +5 -0
- package/lib/yoke/providers/antigravity-executable.js +8 -0
- package/lib/yoke/providers/claude-executable.js +40 -0
- package/lib/yoke/providers/claude-model-descriptions.js +14 -0
- package/lib/yoke/providers/claude-process.js +97 -0
- package/lib/yoke/providers/claude-provision.js +75 -0
- package/lib/yoke/providers/codex-errors.js +8 -0
- package/lib/yoke/providers/muse-executable.js +17 -0
- package/lib/yoke/provisioning.js +6 -0
- package/lib/yoke/query-options.js +10 -0
- package/lib/yoke/response-recovery.js +41 -0
- package/lib/yoke/sdk-mcp-descriptors.js +37 -0
- package/lib/yoke/sdk-server-factory.js +7 -0
- package/lib/yoke/session-history.js +8 -0
- package/lib/yoke/session-tool-transport.js +34 -13
- package/lib/yoke/settings.js +23 -0
- package/lib/yoke/source-locations.js +4 -0
- package/lib/yoke/title-query.js +18 -7
- package/lib/yoke/tui-transcript-index.js +132 -0
- package/lib/yoke/usage.js +48 -0
- package/lib/yoke/user-input.js +13 -0
- package/lib/yoke/vendor-registry.js +81 -1
- package/package.json +10 -4
package/lib/server.js
CHANGED
|
@@ -10,7 +10,7 @@ var dm = require("./dm");
|
|
|
10
10
|
var mates = require("./mates");
|
|
11
11
|
var serverAuth = require("./server-auth");
|
|
12
12
|
var serverSkills = require("./server-skills");
|
|
13
|
-
var claudeHookInstaller = require("./claude-hook-installer");
|
|
13
|
+
var claudeHookInstaller = require("./yoke/claude-hook-installer");
|
|
14
14
|
var serverDm = require("./server-dm");
|
|
15
15
|
var serverMates = require("./server-mates");
|
|
16
16
|
var serverHomeChat = require("./server-home-chat");
|
|
@@ -219,6 +219,14 @@ function createServer(opts) {
|
|
|
219
219
|
var isRequestAuthed = auth.isRequestAuthed;
|
|
220
220
|
var parseCookies = auth.parseCookies;
|
|
221
221
|
|
|
222
|
+
var projectAdminOverview = require("./project-admin-overview");
|
|
223
|
+
|
|
224
|
+
function administrativeMetadata(userId, slug) {
|
|
225
|
+
var user = userId && users.findUserById(userId);
|
|
226
|
+
var context = projects.get(slug);
|
|
227
|
+
return projectAdminOverview.metadataFor(user, context && context.getStatus(), onGetProjectAccess && onGetProjectAccess(slug), users);
|
|
228
|
+
}
|
|
229
|
+
|
|
222
230
|
function canUserAccessSlug(userId, slug) {
|
|
223
231
|
if (!userId || !slug) return false;
|
|
224
232
|
var project = projects && projects.get(slug);
|
|
@@ -237,6 +245,13 @@ function createServer(opts) {
|
|
|
237
245
|
return users.canAccessProject(userId, access) === true;
|
|
238
246
|
}
|
|
239
247
|
|
|
248
|
+
var projects = new Map(); // slug → projectContext
|
|
249
|
+
var lifecycleRuntime = require("./project-lifecycle-runtime").attachLifecycleRuntime({ projects: projects });
|
|
250
|
+
var canUsePath = require("./server-path-access").attachPathAccess({
|
|
251
|
+
users: users, projects: projects, canAccess: canUserAccessSlug, osUsers: osUsers,
|
|
252
|
+
resolveIdentity: require("./os-users").resolveOsUserInfo,
|
|
253
|
+
});
|
|
254
|
+
|
|
240
255
|
var realVersion = require("../package.json").version;
|
|
241
256
|
var currentVersion = debug ? "0.0.9" : realVersion;
|
|
242
257
|
|
|
@@ -341,8 +356,13 @@ function createServer(opts) {
|
|
|
341
356
|
var caContent = caPath ? (function () { try { return fs.readFileSync(caPath); } catch (e) { return null; } })() : null;
|
|
342
357
|
|
|
343
358
|
// --- Project registry ---
|
|
344
|
-
var projects = new Map(); // slug → projectContext
|
|
345
359
|
var assignmentService = attachWorkspaceAssignmentService({
|
|
360
|
+
getPresentation: function (principal) {
|
|
361
|
+
var project = projects.get(principal.sourceProjectSlug), manager = project && project.getSessionManager(), status = project && project.getStatus();
|
|
362
|
+
var session = manager && manager.sessions.get(principal.sourceSessionId);
|
|
363
|
+
var bound = clayProductControl && session && clayProductControl.bind({ projectSlug: principal.sourceProjectSlug, projectOwnerId: status.projectOwnerId, isMate: status.isMate, mateId: status.mateId, session: session });
|
|
364
|
+
return bound && bound._presentation;
|
|
365
|
+
},
|
|
346
366
|
storageDir: path.join(CONFIG_DIR, "workspace-assignments"),
|
|
347
367
|
getProjects: function () { return projects; },
|
|
348
368
|
isMultiUser: function () { return users.isMultiUser(); },
|
|
@@ -363,6 +383,36 @@ function createServer(opts) {
|
|
|
363
383
|
},
|
|
364
384
|
assignmentService: assignmentService,
|
|
365
385
|
});
|
|
386
|
+
var ownerUiService = require('./server-owner-ui').attachOwnerUi({
|
|
387
|
+
isMultiUser: users.isMultiUser, findUser: users.findUserById,
|
|
388
|
+
forEachClient: function (visit) {
|
|
389
|
+
if (globalWs) globalWs.forEachClient(function (ws) { visit(ws, null); });
|
|
390
|
+
projects.forEach(function (project, slug) { project.forEachClient(function (ws) { visit(ws, slug); }); });
|
|
391
|
+
}
|
|
392
|
+
});
|
|
393
|
+
var mateContextService = require('./mate-context-service').attachMateContextService({
|
|
394
|
+
getOwnerUi: function () { return ownerUiService; }, workspace: workspaceQueryService,
|
|
395
|
+
getProjects: function () { return projects; }, isMultiUser: users.isMultiUser,
|
|
396
|
+
findUser: users.findUserById, onGetProjectAccess: onGetProjectAccess,
|
|
397
|
+
canAccessProject: users.canAccessProject,
|
|
398
|
+
resolveMate: function (owner, id) { return mates.getMate(mates.buildMateCtx(users.isMultiUser() ? owner : null), id); }
|
|
399
|
+
});
|
|
400
|
+
var clayProductControl = require("./clay-product-control").attachClayProductControl({
|
|
401
|
+
getOwnerUi: function () { return ownerUiService; },
|
|
402
|
+
getNotifications: function () { return _globalNotifications; },
|
|
403
|
+
getRecordServices: function () { return { issues: issuesService, logs: projectLogsService }; },
|
|
404
|
+
projectLifecycle: opts.projectLifecycle || null,
|
|
405
|
+
getMateLifecycle: function () { return mateHandler && mateHandler.lifecycle; },
|
|
406
|
+
getMateDir: function (ownerId, mateId) { return mates.getMateDir(mates.buildMateCtx(users.isMultiUser() ? ownerId : null), mateId); },
|
|
407
|
+
lifecyclePermissions: function (user) { return users.getEffectivePermissions(user, osUsers); },
|
|
408
|
+
canUsePath: canUsePath,
|
|
409
|
+
getProjects: function () { return projects; },
|
|
410
|
+
isMultiUser: function () { return users.isMultiUser(); },
|
|
411
|
+
onGetProjectAccess: onGetProjectAccess,
|
|
412
|
+
canAccessProject: function (userId, access) { return users.canAccessProject(userId, access) === true; },
|
|
413
|
+
findUser: function (userId) { return users.findUserById(userId); },
|
|
414
|
+
resolveMate: function (userId, mateId) { return mates.getMate(mates.buildMateCtx(users.isMultiUser() ? userId : null), mateId); },
|
|
415
|
+
});
|
|
366
416
|
// Project access is resolved from the authoritative project record, not from
|
|
367
417
|
// getStatus(), which carries no visibility or allowedUsers fields.
|
|
368
418
|
var projectLogsService = attachProjectLogsService({
|
|
@@ -409,6 +459,7 @@ function createServer(opts) {
|
|
|
409
459
|
// Mate Knowledge reads the synchronized Knowledge records. The Mate list is
|
|
410
460
|
// derived from the owning user alone, so a binding can never span users.
|
|
411
461
|
var mateKnowledgeService = attachMateKnowledgeService({
|
|
462
|
+
findUser: function (userId) { return users.findUserById(userId); },
|
|
412
463
|
getProjects: function () { return projects; },
|
|
413
464
|
isMultiUser: function () { return users.isMultiUser(); },
|
|
414
465
|
resolveMate: function (userId, mateId) {
|
|
@@ -491,6 +542,41 @@ function createServer(opts) {
|
|
|
491
542
|
},
|
|
492
543
|
});
|
|
493
544
|
|
|
545
|
+
function injectAppearanceSeed(html, appearance) {
|
|
546
|
+
var validId = function (value) {
|
|
547
|
+
return typeof value === "string" && /^[a-zA-Z0-9_-]{1,120}$/.test(value) ? value : null;
|
|
548
|
+
};
|
|
549
|
+
var mode = appearance && ["light", "dark"].indexOf(appearance.mode) >= 0 ? appearance.mode : null;
|
|
550
|
+
var seed = appearance && appearance.configured === true ? {
|
|
551
|
+
configured: true,
|
|
552
|
+
theme: validId(appearance.theme),
|
|
553
|
+
mode: mode,
|
|
554
|
+
lightTheme: validId(appearance.lightTheme),
|
|
555
|
+
darkTheme: validId(appearance.darkTheme),
|
|
556
|
+
} : null;
|
|
557
|
+
var payload = JSON.stringify(seed).replace(/</g, "\\u003c").replace(/\u2028/g, "\\u2028").replace(/\u2029/g, "\\u2029");
|
|
558
|
+
var script = '<script>window.__clayAppearanceSeed=' + payload + ';</script>';
|
|
559
|
+
return html.replace('<script src="appearance-bootstrap.js"></script>', script + '<script src="appearance-bootstrap.js"></script>');
|
|
560
|
+
}
|
|
561
|
+
|
|
562
|
+
function sendAppShell(req, res, slug) {
|
|
563
|
+
try {
|
|
564
|
+
var shell = fs.readFileSync(path.join(publicDir, "index.html"), "utf8");
|
|
565
|
+
if (slug) shell = injectRootProjectSlug(shell, slug);
|
|
566
|
+
var appearance = null;
|
|
567
|
+
try { appearance = settings.getInitialAppearance(req); } catch (e) {}
|
|
568
|
+
shell = injectAppearanceSeed(shell, appearance);
|
|
569
|
+
res.writeHead(200, {
|
|
570
|
+
"Content-Type": "text/html; charset=utf-8",
|
|
571
|
+
"Cache-Control": "private, no-store",
|
|
572
|
+
});
|
|
573
|
+
res.end(shell);
|
|
574
|
+
} catch (e) {
|
|
575
|
+
res.writeHead(500, { "Content-Type": "text/plain" });
|
|
576
|
+
res.end("App shell missing.");
|
|
577
|
+
}
|
|
578
|
+
}
|
|
579
|
+
|
|
494
580
|
var palette = serverPalette.attachPalette({
|
|
495
581
|
users: users,
|
|
496
582
|
projects: projects,
|
|
@@ -512,7 +598,28 @@ function createServer(opts) {
|
|
|
512
598
|
broadcastAll: function (msg) { broadcastAll(msg); },
|
|
513
599
|
sendToUser: function (userId, msg) { sendToUser(userId, msg); },
|
|
514
600
|
pushModule: pushModule,
|
|
601
|
+
forEachClient: forEachAppClient,
|
|
602
|
+
getUsers: function () { return users.getAllUsers(); },
|
|
603
|
+
canView: function (ws, notification) { return canViewNotification(ws && ws._clayUser && ws._clayUser.id, notification); },
|
|
604
|
+
canViewPrincipal: function (principal, notification) { return canViewNotification(principal.userId, notification); },
|
|
515
605
|
});
|
|
606
|
+
function canViewNotification(userId, notification) {
|
|
607
|
+
if (!users.isMultiUser()) return true;
|
|
608
|
+
if (!userId || !users.findUserById(userId)) return false;
|
|
609
|
+
if (notification.targetUserId && notification.targetUserId !== userId) return false;
|
|
610
|
+
if (notification.slug) {
|
|
611
|
+
if (!canUserAccessSlug(userId, notification.slug)) return false;
|
|
612
|
+
if (notification.sessionId) {
|
|
613
|
+
var project = projects.get(notification.slug);
|
|
614
|
+
var session = project && project.getSessionManager().sessions.get(notification.sessionId);
|
|
615
|
+
var status = project && project.getStatus();
|
|
616
|
+
var access = status && status.isMate ? { isMate: true, visibility: "private", ownerId: status.projectOwnerId } : onGetProjectAccess(notification.slug);
|
|
617
|
+
if (!session || !users.canAccessSession(userId, session, access)) return false;
|
|
618
|
+
}
|
|
619
|
+
return !notification.ownerId || notification.ownerId === userId || !!notification.sessionId;
|
|
620
|
+
}
|
|
621
|
+
return notification.targetUserId === userId || notification.ownerId === userId;
|
|
622
|
+
}
|
|
516
623
|
|
|
517
624
|
// --- Security headers ---
|
|
518
625
|
var securityHeaders = {
|
|
@@ -910,15 +1017,7 @@ function createServer(opts) {
|
|
|
910
1017
|
});
|
|
911
1018
|
}
|
|
912
1019
|
if (targetSlug) {
|
|
913
|
-
|
|
914
|
-
var homeHtml = fs.readFileSync(path.join(publicDir, "index.html"), "utf8");
|
|
915
|
-
homeHtml = injectRootProjectSlug(homeHtml, targetSlug);
|
|
916
|
-
res.writeHead(200, { "Content-Type": "text/html; charset=utf-8", "Cache-Control": "no-cache" });
|
|
917
|
-
res.end(homeHtml);
|
|
918
|
-
} catch (e) {
|
|
919
|
-
res.writeHead(500, { "Content-Type": "text/plain" });
|
|
920
|
-
res.end("App shell missing.");
|
|
921
|
-
}
|
|
1020
|
+
sendAppShell(req, res, targetSlug);
|
|
922
1021
|
return;
|
|
923
1022
|
}
|
|
924
1023
|
}
|
|
@@ -936,9 +1035,7 @@ function createServer(opts) {
|
|
|
936
1035
|
return;
|
|
937
1036
|
}
|
|
938
1037
|
}
|
|
939
|
-
|
|
940
|
-
res.writeHead(500, { "Content-Type": "text/plain" });
|
|
941
|
-
res.end("App shell missing.");
|
|
1038
|
+
sendAppShell(req, res, null);
|
|
942
1039
|
return;
|
|
943
1040
|
}
|
|
944
1041
|
|
|
@@ -955,8 +1052,8 @@ function createServer(opts) {
|
|
|
955
1052
|
var projectList = [];
|
|
956
1053
|
var infoUser = users.isMultiUser() ? getMultiUserFromReq(req) : null;
|
|
957
1054
|
projects.forEach(function (ctx, slug) {
|
|
958
|
-
if (users.isMultiUser() && (!infoUser || !canUserAccessSlug(infoUser.id, slug))) return;
|
|
959
|
-
projectList.push({ slug: slug, project: ctx.project });
|
|
1055
|
+
if (users.isMultiUser() && (!infoUser || (!canUserAccessSlug(infoUser.id, slug) && !administrativeMetadata(infoUser.id, slug)))) return;
|
|
1056
|
+
projectList.push({ slug: slug, project: ctx.project, contentAccess: !users.isMultiUser() || canUserAccessSlug(infoUser.id, slug) });
|
|
960
1057
|
});
|
|
961
1058
|
res.writeHead(200, { "Content-Type": "application/json" });
|
|
962
1059
|
res.end(JSON.stringify({ projects: projectList, version: currentVersion, authenticated: true }));
|
|
@@ -965,6 +1062,10 @@ function createServer(opts) {
|
|
|
965
1062
|
|
|
966
1063
|
// Static files (favicon, manifest, icons, sw.js, mate avatars, etc.)
|
|
967
1064
|
if (!fullUrl.includes("..") && !fullUrl.startsWith("/p/") && !fullUrl.startsWith("/api/")) {
|
|
1065
|
+
if (fullUrl === "/index.html") {
|
|
1066
|
+
sendAppShell(req, res, null);
|
|
1067
|
+
return;
|
|
1068
|
+
}
|
|
968
1069
|
if (serveStatic(fullUrl, res)) return;
|
|
969
1070
|
}
|
|
970
1071
|
|
|
@@ -1028,8 +1129,14 @@ function createServer(opts) {
|
|
|
1028
1129
|
if (users.isMultiUser() && !isMcpBridgeAuthenticated) {
|
|
1029
1130
|
var httpUser = getMultiUserFromReq(req);
|
|
1030
1131
|
if (!httpUser || !canUserAccessSlug(httpUser.id, slug)) {
|
|
1031
|
-
|
|
1032
|
-
|
|
1132
|
+
var overview = httpUser && administrativeMetadata(httpUser.id, slug);
|
|
1133
|
+
if (overview && req.method === "GET" && (projectUrlForAuth === "/" || projectUrlForAuth === "/index.html")) {
|
|
1134
|
+
res.writeHead(200, { "Content-Type": "text/html; charset=utf-8", "Cache-Control": "no-store" });
|
|
1135
|
+
res.end(projectAdminOverview.page(overview, getVisibleProjects(httpUser.id)));
|
|
1136
|
+
return;
|
|
1137
|
+
}
|
|
1138
|
+
res.writeHead(403, { "Content-Type": "application/json", "Cache-Control": "no-store" });
|
|
1139
|
+
res.end(JSON.stringify({ error: "Project content access is not permitted" }));
|
|
1033
1140
|
return;
|
|
1034
1141
|
}
|
|
1035
1142
|
}
|
|
@@ -1054,6 +1161,10 @@ function createServer(opts) {
|
|
|
1054
1161
|
|
|
1055
1162
|
// Static files (same assets for all projects)
|
|
1056
1163
|
if (req.method === "GET") {
|
|
1164
|
+
if (projectUrl === "/" || projectUrl === "/index.html") {
|
|
1165
|
+
sendAppShell(req, res, slug);
|
|
1166
|
+
return;
|
|
1167
|
+
}
|
|
1057
1168
|
if (serveStatic(projectUrl, res)) return;
|
|
1058
1169
|
}
|
|
1059
1170
|
|
|
@@ -1134,6 +1245,7 @@ function createServer(opts) {
|
|
|
1134
1245
|
var globalWs = serverGlobalWs.attachGlobalWs({
|
|
1135
1246
|
osUsers: osUsers,
|
|
1136
1247
|
usersModule: users,
|
|
1248
|
+
canUsePath: canUsePath,
|
|
1137
1249
|
onAddProject: onAddProject,
|
|
1138
1250
|
onCreateProject: onCreateProject,
|
|
1139
1251
|
onCloneProject: onCloneProject,
|
|
@@ -1185,6 +1297,7 @@ function createServer(opts) {
|
|
|
1185
1297
|
if (!require('./account-auth-socket').guardSocket(ws, req, isRequestAuthed, auth.touchSession)) return;
|
|
1186
1298
|
ws._clayPane = wsRequest.pane;
|
|
1187
1299
|
ws._clayPaneSession = wsRequest.paneSession;
|
|
1300
|
+
ws._clayContextual = wsRequest.contextual;
|
|
1188
1301
|
globalWs.handleConnection(ws, globalUser);
|
|
1189
1302
|
});
|
|
1190
1303
|
return;
|
|
@@ -1230,6 +1343,7 @@ function createServer(opts) {
|
|
|
1230
1343
|
ws._clayUser = wsUser; // attach user context
|
|
1231
1344
|
ws._clayPane = wsRequest.pane;
|
|
1232
1345
|
ws._clayPaneSession = wsRequest.paneSession;
|
|
1346
|
+
ws._clayContextual = wsRequest.contextual;
|
|
1233
1347
|
var remoteAddr = req.socket.remoteAddress || "";
|
|
1234
1348
|
ws._clayLocal = (remoteAddr === "127.0.0.1" || remoteAddr === "::1" || remoteAddr === "::ffff:127.0.0.1");
|
|
1235
1349
|
// Clear cross-project unread for this project when client connects
|
|
@@ -1274,17 +1388,10 @@ function createServer(opts) {
|
|
|
1274
1388
|
if (processingUpdateTimer) clearTimeout(processingUpdateTimer);
|
|
1275
1389
|
processingUpdateTimer = setTimeout(function () {
|
|
1276
1390
|
processingUpdateTimer = null;
|
|
1277
|
-
var allProjectsList = getProjects();
|
|
1278
1391
|
// Always send per-client to include cross-project unread counts
|
|
1279
1392
|
projects.forEach(function (ctx, projSlug) {
|
|
1280
1393
|
ctx.forEachClient(function (ws) {
|
|
1281
|
-
var filtered =
|
|
1282
|
-
if (users.isMultiUser() && onGetProjectAccess) {
|
|
1283
|
-
var wsUser = ws._clayUser;
|
|
1284
|
-
filtered = wsUser ? allProjectsList.filter(function (p) {
|
|
1285
|
-
return canUserAccessSlug(wsUser.id, p.slug);
|
|
1286
|
-
}) : [];
|
|
1287
|
-
}
|
|
1394
|
+
var filtered = getVisibleProjects(ws._clayUser ? ws._clayUser.id : null);
|
|
1288
1395
|
// Attach per-project unread counts for this client
|
|
1289
1396
|
var unreadMap = getCrossProjectUnread(ws);
|
|
1290
1397
|
var projectsWithUnread = filtered.map(function (p) {
|
|
@@ -1334,6 +1441,10 @@ function createServer(opts) {
|
|
|
1334
1441
|
function addProject(cwd, slug, title, icon, projectOwnerId, worktreeMeta, extraOpts) {
|
|
1335
1442
|
if (projects.has(slug)) return false;
|
|
1336
1443
|
var extra = extraOpts || {};
|
|
1444
|
+
if (extra.isMate) {
|
|
1445
|
+
var registeredMate = mates.getMate(mates.buildMateCtx(users.isMultiUser() ? projectOwnerId : null), extra.mateId || path.basename(cwd));
|
|
1446
|
+
if (registeredMate && registeredMate.lifecycleDeletion) return false;
|
|
1447
|
+
}
|
|
1337
1448
|
var ctx = createProjectContext({
|
|
1338
1449
|
cwd: cwd,
|
|
1339
1450
|
slug: slug,
|
|
@@ -1353,6 +1464,9 @@ function createServer(opts) {
|
|
|
1353
1464
|
return mateHandler.createReadyMateFromInterview(ws, userId, definition);
|
|
1354
1465
|
},
|
|
1355
1466
|
workspaceQueryService: workspaceQueryService,
|
|
1467
|
+
clayProductControl: clayProductControl,
|
|
1468
|
+
mateContextService: mateContextService,
|
|
1469
|
+
resumeLifecycleProject: function (userId) { return opts.projectLifecycle ? opts.projectLifecycle.resumeRecovered(slug, userId) : true; },
|
|
1356
1470
|
projectLogsService: projectLogsService,
|
|
1357
1471
|
issuesService: issuesService,
|
|
1358
1472
|
linearStorage: linear.storage,
|
|
@@ -1374,13 +1488,19 @@ function createServer(opts) {
|
|
|
1374
1488
|
return !!(access && !access.error && users.canAccessProject(userId, access));
|
|
1375
1489
|
},
|
|
1376
1490
|
getProjectAccess: function () {
|
|
1377
|
-
if (extra.isMate)
|
|
1491
|
+
if (extra.isMate) {
|
|
1492
|
+
var mate = mates.getMate(mates.buildMateCtx(users.isMultiUser() ? projectOwnerId : null), extra.mateId || path.basename(cwd));
|
|
1493
|
+
return { isMate: true, visibility: "private", ownerId: projectOwnerId || null, allowedUsers: [], lifecycleExecutionPaused: !mate || !!mate.lifecycleDeletion };
|
|
1494
|
+
}
|
|
1378
1495
|
return onGetProjectAccess ? onGetProjectAccess(slug) : { visibility: "public", ownerId: projectOwnerId || null };
|
|
1379
1496
|
},
|
|
1380
1497
|
shouldSuppressResponseNotification: function (session) {
|
|
1381
1498
|
return shouldSuppressHomeResponse(projects, slug, session);
|
|
1382
1499
|
},
|
|
1383
|
-
pushModule: pushModule,
|
|
1500
|
+
pushModule: require("./project-push-access").scopedPush(pushModule, {
|
|
1501
|
+
slug: slug, users: users, getProject: function (target) { return projects.get(target); },
|
|
1502
|
+
canAccessProject: canUserAccessSlug, getAccess: onGetProjectAccess,
|
|
1503
|
+
}),
|
|
1384
1504
|
debug: debug,
|
|
1385
1505
|
dangerouslySkipPermissions: dangerouslySkipPermissions,
|
|
1386
1506
|
osUsers: osUsers,
|
|
@@ -1412,6 +1532,7 @@ function createServer(opts) {
|
|
|
1412
1532
|
var status = ctx.getStatus();
|
|
1413
1533
|
var recs = ctx.getSchedules();
|
|
1414
1534
|
for (var i = 0; i < recs.length; i++) {
|
|
1535
|
+
if (users.isMultiUser() && recs[i].ownerId !== userId) continue;
|
|
1415
1536
|
// Shallow-copy full record and augment with project metadata
|
|
1416
1537
|
var copy = {};
|
|
1417
1538
|
var keys = Object.keys(recs[i]);
|
|
@@ -1469,6 +1590,7 @@ function createServer(opts) {
|
|
|
1469
1590
|
return ctx.getSchedules().length;
|
|
1470
1591
|
},
|
|
1471
1592
|
canAccessProjectSlug: canUserAccessSlug,
|
|
1593
|
+
canUsePath: canUsePath,
|
|
1472
1594
|
onPresenceChange: broadcastPresenceChange,
|
|
1473
1595
|
onProcessingChanged: broadcastProcessingChange,
|
|
1474
1596
|
onSessionDone: function () { onSessionDone(slug); },
|
|
@@ -1622,6 +1744,8 @@ function createServer(opts) {
|
|
|
1622
1744
|
}
|
|
1623
1745
|
|
|
1624
1746
|
function handleDmMessage(ws, msg, routedProjectSlug) {
|
|
1747
|
+
if (ownerUiService.handleMessage(ws, msg)) return true;
|
|
1748
|
+
if (mateContextService.handleMessage(ws, msg)) return true;
|
|
1625
1749
|
if (cursorSharingService && cursorSharingService.handleMessage(ws, msg)) return true;
|
|
1626
1750
|
if (defaultVendorService && defaultVendorService.handleMessage(ws, msg, routedProjectSlug)) return true;
|
|
1627
1751
|
if (contextViewService && contextViewService.handleMessage(ws, msg)) return true;
|
|
@@ -1630,25 +1754,14 @@ function createServer(opts) {
|
|
|
1630
1754
|
if (dmHandler.handleMessage(ws, msg)) return true;
|
|
1631
1755
|
if (mateHandler && mateHandler.handleMessage(ws, msg)) return true;
|
|
1632
1756
|
if (emailHandler.handleMessage(ws, msg)) return true;
|
|
1633
|
-
if (homeChatHandler.handleMessage(ws, msg)) return true;
|
|
1757
|
+
if (homeChatHandler.handleMessage(ws, msg, routedProjectSlug)) return true;
|
|
1634
1758
|
if (homePreferencesHandler.handleMessage(ws, msg)) return true;
|
|
1635
1759
|
if (toolsHandler.handleMessage(ws, msg)) return true;
|
|
1636
1760
|
return false;
|
|
1637
1761
|
}
|
|
1638
1762
|
|
|
1639
|
-
function removeProject(slug) {
|
|
1640
|
-
|
|
1641
|
-
if (!ctx) return false;
|
|
1642
|
-
var wasMate = ctx.getStatus().isMate;
|
|
1643
|
-
var shutdownResult = ctx.destroy();
|
|
1644
|
-
projects.delete(slug);
|
|
1645
|
-
if (shutdownResult && typeof shutdownResult.catch === "function") {
|
|
1646
|
-
shutdownResult.catch(function(err) {
|
|
1647
|
-
console.error("[server] Project destroy failed for " + slug + ":", err && err.message ? err.message : err);
|
|
1648
|
-
});
|
|
1649
|
-
}
|
|
1650
|
-
if (!wasMate) scheduleRegistryRefresh();
|
|
1651
|
-
return true;
|
|
1763
|
+
function removeProject(slug, awaitCompletion) {
|
|
1764
|
+
return require('./server-project-removal').removeProjectRuntime(projects, slug, awaitCompletion, scheduleRegistryRefresh);
|
|
1652
1765
|
}
|
|
1653
1766
|
|
|
1654
1767
|
// Now that addProject and removeProject are defined, initialize mateHandler
|
|
@@ -1734,7 +1847,11 @@ function createServer(opts) {
|
|
|
1734
1847
|
function getVisibleProjects(userId) {
|
|
1735
1848
|
var visible = [];
|
|
1736
1849
|
projects.forEach(function (ctx, slug) {
|
|
1737
|
-
if (users.isMultiUser() && (!userId || !canUserAccessSlug(userId, slug)))
|
|
1850
|
+
if (users.isMultiUser() && (!userId || !canUserAccessSlug(userId, slug))) {
|
|
1851
|
+
var metadata = administrativeMetadata(userId, slug);
|
|
1852
|
+
if (metadata) visible.push(metadata);
|
|
1853
|
+
return;
|
|
1854
|
+
}
|
|
1738
1855
|
var status = ctx.getStatus();
|
|
1739
1856
|
if (!status.isMate && onGetProjectAccess) {
|
|
1740
1857
|
var access = onGetProjectAccess(slug);
|
|
@@ -1933,6 +2050,7 @@ function createServer(opts) {
|
|
|
1933
2050
|
speech.destroy();
|
|
1934
2051
|
var shutdowns = [];
|
|
1935
2052
|
shutdowns.push(durableSchedulerLifecycle.shutdown());
|
|
2053
|
+
shutdowns.push(lifecycleRuntime.shutdown());
|
|
1936
2054
|
projects.forEach(function (ctx, slug) {
|
|
1937
2055
|
console.log("[server] Destroying project:", slug);
|
|
1938
2056
|
var result = ctx.destroy();
|
|
@@ -2000,6 +2118,8 @@ function createServer(opts) {
|
|
|
2000
2118
|
isTLS: !!tlsOptions,
|
|
2001
2119
|
addProject: addProject,
|
|
2002
2120
|
removeProject: removeProject,
|
|
2121
|
+
getProjectLifecycleTargets: lifecycleRuntime.targets,
|
|
2122
|
+
closeProjectLifecycle: lifecycleRuntime.close,
|
|
2003
2123
|
getProjects: getProjects,
|
|
2004
2124
|
reorderProjects: reorderProjects,
|
|
2005
2125
|
setProjectTitle: setProjectTitle,
|
|
@@ -0,0 +1,45 @@
|
|
|
1
|
+
// Guarded configuration commit shared by SDK setters and permission transitions.
|
|
2
|
+
// Provider acknowledgement is distinct from local persistence. Once a request
|
|
3
|
+
// has crossed that boundary, failures never imply the provider was rolled back.
|
|
4
|
+
async function applySessionConfig(ctx) {
|
|
5
|
+
var session = ctx.session, sm = ctx.sm, handle = session.queryInstance;
|
|
6
|
+
var generation = Number(session._sdkQueryGeneration || 0), owner = session.ownerId;
|
|
7
|
+
var paused = !!session._pendingMessageDrainPaused, signal = session.abortController && session.abortController.signal;
|
|
8
|
+
var attempted = false, acknowledged = false, persisted = false, previous = {};
|
|
9
|
+
function current() {
|
|
10
|
+
ctx.revalidate();
|
|
11
|
+
if (sm.sessions.get(session.localId) !== session || session.ownerId !== owner || session.queryInstance !== handle ||
|
|
12
|
+
Number(session._sdkQueryGeneration || 0) !== generation || session.taskStopRequested ||
|
|
13
|
+
!!session._pendingMessageDrainPaused !== paused || signal && signal.aborted) throw new Error("Target ownership, runtime, or Stop state changed during the configuration request.");
|
|
14
|
+
}
|
|
15
|
+
try {
|
|
16
|
+
current();
|
|
17
|
+
if (handle) {
|
|
18
|
+
if (typeof handle[ctx.method] !== "function") throw new Error("This provider cannot apply this configuration to the active runtime.");
|
|
19
|
+
attempted = true;
|
|
20
|
+
var reply = await handle[ctx.method](ctx.nativeValue);
|
|
21
|
+
if (reply === false || reply && reply.ok === false) throw new Error(reply && reply.error || "The provider refused the configuration change.");
|
|
22
|
+
acknowledged = true;
|
|
23
|
+
current();
|
|
24
|
+
}
|
|
25
|
+
var changes = typeof ctx.changes === "function" ? ctx.changes() : ctx.changes;
|
|
26
|
+
Object.keys(changes).forEach(function (key) { previous[key] = { present: Object.prototype.hasOwnProperty.call(session, key), value: session[key] }; });
|
|
27
|
+
Object.assign(session, changes);
|
|
28
|
+
try {
|
|
29
|
+
if (sm.saveSessionFile(session) !== true) throw new Error("Could not persist the configuration change.");
|
|
30
|
+
persisted = true;
|
|
31
|
+
} catch (error) {
|
|
32
|
+
Object.keys(previous).forEach(function (key) { if (previous[key].present) session[key] = previous[key].value; else delete session[key]; });
|
|
33
|
+
throw error;
|
|
34
|
+
}
|
|
35
|
+
// There is no await between the last authorization check, disk commit and
|
|
36
|
+
// publication. Never broadcast a desired value before its save succeeds.
|
|
37
|
+
ctx.publish();
|
|
38
|
+
return Object.assign({ ok: true, status: "completed", persisted: true, runtimeEffect: acknowledged ? "applied" : "none" }, changes);
|
|
39
|
+
} catch (error) {
|
|
40
|
+
return { ok: false, status: "failed", outcome: persisted ? "partial" : attempted ? "uncertain" : "failed", persisted: persisted,
|
|
41
|
+
runtimeEffect: acknowledged ? "applied" : attempted ? "unknown" : "none", retrySafe: !attempted && !persisted,
|
|
42
|
+
error: (persisted ? "The configuration was saved, but publication did not complete. " : "") + (attempted ? "The provider may retain the requested change; no external rollback was attempted. " : "") + (error.message || String(error)) };
|
|
43
|
+
}
|
|
44
|
+
}
|
|
45
|
+
module.exports = { applySessionConfig: applySessionConfig };
|
package/lib/session-folders.js
CHANGED
|
@@ -9,7 +9,7 @@
|
|
|
9
9
|
// also keeps its folder (or Unfiled) assignment
|
|
10
10
|
// orders: { containerKey: [keys] } manual order per container ("unfiled", custom id, "all")
|
|
11
11
|
// collapsed: { containerKey: true }
|
|
12
|
-
// view: { group, sort, direction }
|
|
12
|
+
// view: { group, sort, direction, showDateHeadings }
|
|
13
13
|
// sessionKey is the session's opaque, durable sessionOriginId.
|
|
14
14
|
|
|
15
15
|
var crypto = require("crypto");
|
|
@@ -35,7 +35,7 @@ function defaultState() {
|
|
|
35
35
|
favorites: [],
|
|
36
36
|
orders: {},
|
|
37
37
|
collapsed: {},
|
|
38
|
-
view: { group: "folders", sort: "activity", direction: "desc" },
|
|
38
|
+
view: { group: "folders", sort: "activity", direction: "desc", showDateHeadings: true },
|
|
39
39
|
legacyFavoritesMigrated: false,
|
|
40
40
|
};
|
|
41
41
|
}
|
|
@@ -147,6 +147,7 @@ function normalizeState(raw) {
|
|
|
147
147
|
var view = isPlainObject(source.view) ? source.view : {};
|
|
148
148
|
if (SORTS.indexOf(view.sort) !== -1) state.view.sort = view.sort;
|
|
149
149
|
if (DIRECTIONS.indexOf(view.direction) !== -1) state.view.direction = view.direction;
|
|
150
|
+
if (typeof view.showDateHeadings === "boolean") state.view.showDateHeadings = view.showDateHeadings;
|
|
150
151
|
state.legacyFavoritesMigrated = source.legacyFavoritesMigrated === true;
|
|
151
152
|
return state;
|
|
152
153
|
}
|
|
@@ -334,6 +335,10 @@ function applyRaw(input, op, env) {
|
|
|
334
335
|
if (DIRECTIONS.indexOf(op.direction) === -1) return { error: "Invalid direction" };
|
|
335
336
|
state.view.direction = op.direction;
|
|
336
337
|
}
|
|
338
|
+
if (op.showDateHeadings !== undefined) {
|
|
339
|
+
if (typeof op.showDateHeadings !== "boolean") return { error: "Invalid date heading setting" };
|
|
340
|
+
state.view.showDateHeadings = op.showDateHeadings;
|
|
341
|
+
}
|
|
337
342
|
return { state: state };
|
|
338
343
|
}
|
|
339
344
|
|
|
@@ -0,0 +1,21 @@
|
|
|
1
|
+
// Product transcript slicing for providers that include a completed turn.
|
|
2
|
+
function endIndex(session, uuid, boundary) {
|
|
3
|
+
if (boundary === undefined) return undefined;
|
|
4
|
+
if (boundary !== "completed-turn-inclusive") throw new Error("Unsupported local fork history boundary");
|
|
5
|
+
var history = session.history || [];
|
|
6
|
+
var markers = (session.messageUUIDs || []).filter(function(marker) { return marker.uuid === uuid && marker.type === "user"; });
|
|
7
|
+
var marker = markers.length === 1 && markers[0];
|
|
8
|
+
var index = marker && marker.historyIndex;
|
|
9
|
+
var entry = Number.isInteger(index) && history[index];
|
|
10
|
+
if (!entry || entry.type !== "message_uuid" || entry.uuid !== uuid) throw new Error("Cannot safely represent this completed-turn fork boundary in local history");
|
|
11
|
+
for (var i = index + 1; i < history.length; i++) {
|
|
12
|
+
entry = history[i];
|
|
13
|
+
if (entry.type === "user_message" || entry.type === "message_uuid" && entry.messageType === "user") break;
|
|
14
|
+
if (entry.type === "done") {
|
|
15
|
+
if (entry.code === 0) return i + 1;
|
|
16
|
+
break;
|
|
17
|
+
}
|
|
18
|
+
}
|
|
19
|
+
throw new Error("Cannot safely represent this completed-turn fork boundary in local history");
|
|
20
|
+
}
|
|
21
|
+
module.exports = { endIndex: endIndex };
|
package/lib/session-github.js
CHANGED
|
@@ -33,22 +33,29 @@ function runGh(cwd, args, identity, input) {
|
|
|
33
33
|
}
|
|
34
34
|
async function readReference(cwd, url, identity, run, statusOnly) {
|
|
35
35
|
var ref = parseReference(url);
|
|
36
|
-
var fields = "title,state,url" + (ref.kind === "pr" ? (statusOnly ? ",isDraft" : ",isDraft,headRefName,reviewDecision,statusCheckRollup") : "");
|
|
36
|
+
var fields = "title,state,url" + (ref.kind === "pr" ? (statusOnly ? ",isDraft,reviewDecision,reviewRequests" : ",isDraft,headRefName,reviewDecision,statusCheckRollup") : "");
|
|
37
37
|
var data = await (run || runGh)(cwd, [ref.kind === "pr" ? "pr" : "issue", "view", String(ref.number), "--repo", ref.repository, "--json", fields], identity);
|
|
38
38
|
var verified = parseReference(data.url);
|
|
39
39
|
if (verified.url.toLowerCase() !== ref.url.toLowerCase()) throw new Error("GitHub returned a different reference.");
|
|
40
40
|
ref.title = String(data.title || "").slice(0, 200);
|
|
41
41
|
ref.state = data.state === "MERGED" ? "merged" : data.state === "CLOSED" ? "closed" : data.state === "OPEN" ? (data.isDraft ? "draft" : "open") : "unknown";
|
|
42
42
|
ref.checkedAt = Date.now();
|
|
43
|
+
if (ref.kind === "pr") {
|
|
44
|
+
ref.review = ["APPROVED", "CHANGES_REQUESTED", "REVIEW_REQUIRED"].indexOf(data.reviewDecision) >= 0 ? data.reviewDecision : "";
|
|
45
|
+
}
|
|
43
46
|
if (ref.kind === "pr" && !statusOnly) {
|
|
44
47
|
ref.branch = String(data.headRefName || "").slice(0, 200);
|
|
45
|
-
ref.review = ["APPROVED", "CHANGES_REQUESTED", "REVIEW_REQUIRED"].indexOf(data.reviewDecision) >= 0 ? data.reviewDecision : "";
|
|
46
48
|
ref.checks = (data.statusCheckRollup || []).slice(0, 30).map(function (check) {
|
|
47
49
|
var target = check.detailsUrl || check.targetUrl || "";
|
|
48
50
|
if (!/^https:\/\//i.test(target)) target = "";
|
|
49
51
|
return { name: String(check.name || check.context || "Check").slice(0, 100), state: String(check.conclusion || check.state || check.status || "PENDING").slice(0, 40), url: target };
|
|
50
52
|
});
|
|
51
53
|
}
|
|
54
|
+
if (ref.kind === "pr" && statusOnly) {
|
|
55
|
+
ref.reviewRequests = Array.isArray(data.reviewRequests) ? data.reviewRequests.slice(0, 30).map(function (request) {
|
|
56
|
+
return String(request.login || "").trim().toLowerCase().slice(0, 100);
|
|
57
|
+
}).filter(Boolean) : [];
|
|
58
|
+
}
|
|
52
59
|
return ref;
|
|
53
60
|
}
|
|
54
61
|
module.exports = { parseReference: parseReference, readReference: readReference, runGh: runGh };
|
package/lib/session-hygiene.js
CHANGED
|
@@ -5,7 +5,7 @@
|
|
|
5
5
|
var sessionProvenance = require("./session-provenance");
|
|
6
6
|
|
|
7
7
|
var BLANK_SESSION_MAX_AGE_MS = 24 * 60 * 60 * 1000;
|
|
8
|
-
var
|
|
8
|
+
var transcriptHygiene = require("./yoke/claude-transcript-hygiene");
|
|
9
9
|
|
|
10
10
|
// A session is "blank" when nothing has ever happened in it and nothing is
|
|
11
11
|
// attached to it. Adopted external sessions are never blank (their transcript
|
|
@@ -61,43 +61,11 @@ function collectStaleBlankSessions(sessions, activeSessionId, now) {
|
|
|
61
61
|
return stale;
|
|
62
62
|
}
|
|
63
63
|
|
|
64
|
-
function extractClaudeUserText(event) {
|
|
65
|
-
var content = event && event.message && event.message.content;
|
|
66
|
-
if (typeof content === "string") return content;
|
|
67
|
-
if (!Array.isArray(content)) return "";
|
|
68
|
-
var parts = [];
|
|
69
|
-
for (var i = 0; i < content.length; i++) {
|
|
70
|
-
if (content[i] && content[i].type === "text" && typeof content[i].text === "string") {
|
|
71
|
-
parts.push(content[i].text);
|
|
72
|
-
}
|
|
73
|
-
}
|
|
74
|
-
return parts.join("");
|
|
75
|
-
}
|
|
76
|
-
|
|
77
|
-
// SDK capability probes create a real Claude transcript with a single "hi"
|
|
78
|
-
// prompt. Newer Claude Code versions append an interruption record when Clay
|
|
79
|
-
// aborts the probe, so that bookkeeping record must not make the transcript
|
|
80
|
-
// look like a real two-turn conversation.
|
|
81
|
-
function isClaudeWarmupTranscript(events) {
|
|
82
|
-
var promptCount = 0;
|
|
83
|
-
for (var i = 0; i < events.length; i++) {
|
|
84
|
-
var event = events[i];
|
|
85
|
-
if (!event || typeof event !== "object") continue;
|
|
86
|
-
if (event.type === "assistant") return false;
|
|
87
|
-
if (event.type !== "user" || !event.message || event.message.role !== "user") continue;
|
|
88
|
-
var text = extractClaudeUserText(event);
|
|
89
|
-
if (text === CLAUDE_INTERRUPTED_TEXT) continue;
|
|
90
|
-
if (text !== "hi") return false;
|
|
91
|
-
promptCount++;
|
|
92
|
-
}
|
|
93
|
-
return promptCount === 1;
|
|
94
|
-
}
|
|
95
|
-
|
|
96
64
|
module.exports = {
|
|
97
65
|
isBlankSession: isBlankSession,
|
|
98
66
|
findReusableBlankSession: findReusableBlankSession,
|
|
99
67
|
collectStaleBlankSessions: collectStaleBlankSessions,
|
|
100
|
-
extractClaudeUserText: extractClaudeUserText,
|
|
101
|
-
isClaudeWarmupTranscript: isClaudeWarmupTranscript,
|
|
68
|
+
extractClaudeUserText: transcriptHygiene.extractClaudeUserText,
|
|
69
|
+
isClaudeWarmupTranscript: transcriptHygiene.isClaudeWarmupTranscript,
|
|
102
70
|
BLANK_SESSION_MAX_AGE_MS: BLANK_SESSION_MAX_AGE_MS,
|
|
103
71
|
};
|
|
@@ -7,11 +7,12 @@ function normalize(mode) {
|
|
|
7
7
|
return null;
|
|
8
8
|
}
|
|
9
9
|
|
|
10
|
-
function capabilities(session, defaultVendor) {
|
|
10
|
+
function capabilities(session, defaultVendor, provider) {
|
|
11
11
|
var vendor = session && session.vendor || defaultVendor || "claude";
|
|
12
|
+
var contract = require("./yoke/session-tool-transport").contract(provider || vendor);
|
|
12
13
|
return {
|
|
13
|
-
auto:
|
|
14
|
-
mcpOverride:
|
|
14
|
+
auto: Array.isArray(contract.permissionModes) && contract.permissionModes.indexOf("auto") !== -1,
|
|
15
|
+
mcpOverride: contract.mcpPermissionOverrides === true && !!(session && session.queryInstance &&
|
|
15
16
|
typeof session.queryInstance.setMcpPermissionModeOverride === "function"),
|
|
16
17
|
};
|
|
17
18
|
}
|
|
@@ -0,0 +1,11 @@
|
|
|
1
|
+
// Bind personal instruction reads to the existing live session/query authority.
|
|
2
|
+
function bind(session, sessions, options, valid, multiUser) {
|
|
3
|
+
var owner = session.ownerId || null;
|
|
4
|
+
return Object.assign({}, options, { isAvailable: function() {
|
|
5
|
+
if (!sessions || typeof sessions.get !== "function" || sessions.get(session.localId) !== session || !valid() || (session.ownerId || null) !== owner || session.youCurator || session.sessionVisibility === "shared" || session._mcpForeignInput) return false;
|
|
6
|
+
if (owner) return require("./mcp-session-access").canUsePersonalConnections(session, sessions);
|
|
7
|
+
return !multiUser && !session.delegated && !session._delegatedBy && !session._pairDelegation
|
|
8
|
+
&& !(session.history || []).some(function(entry) { return entry.type === "user_message" && entry.from && entry.from !== "default"; });
|
|
9
|
+
} });
|
|
10
|
+
}
|
|
11
|
+
module.exports = { bind: bind };
|
|
@@ -54,7 +54,7 @@ function handleDefaultChange(ctx, ws, msg) {
|
|
|
54
54
|
? ctx.usersModule.getEffectivePermissions(user, ctx.osUsers) : {};
|
|
55
55
|
var isOwner = !!(user && access && access.ownerId && access.ownerId === user.id);
|
|
56
56
|
var isAdmin = !!(user && user.role === "admin");
|
|
57
|
-
if (!user || !permissions.projectSettings ||
|
|
57
|
+
if (!user || !permissions.projectSettings || !isOwner) {
|
|
58
58
|
defaultChangeResult(ctx, ws, msg, { ok: false, error: "Project settings access is not permitted" });
|
|
59
59
|
return true;
|
|
60
60
|
}
|
|
@@ -98,7 +98,10 @@ function revokeViewers(ctx, session) {
|
|
|
98
98
|
// Clear the server-side selection before reconnecting so no further
|
|
99
99
|
// session events or input can cross the revoked access boundary.
|
|
100
100
|
client._clayActiveSession = null;
|
|
101
|
-
if (client.readyState === 1)
|
|
101
|
+
if (client.readyState === 1) {
|
|
102
|
+
if (ctx.sendTo) ctx.sendTo(client, { type: "access_revoked", slug: ctx.slug });
|
|
103
|
+
client.close(1008, "Session access changed");
|
|
104
|
+
}
|
|
102
105
|
});
|
|
103
106
|
}
|
|
104
107
|
}
|