clay-server 5.1.1-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-policy.js +21 -0
- package/lib/account-auth-socket.js +30 -0
- package/lib/account-auth-throttle.js +44 -0
- package/lib/account-auth-transport.js +48 -0
- package/lib/account-login-page.js +28 -0
- package/lib/account-passkey-challenges.js +31 -0
- package/lib/account-passkey-page.js +89 -0
- package/lib/account-passkey-policy.js +39 -0
- package/lib/account-password-page.js +69 -0
- package/lib/account-passwords.js +36 -0
- package/lib/account-remembered.js +77 -0
- package/lib/account-session-page.js +51 -0
- package/lib/account-session-store.js +82 -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 +80 -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/migrate-single-user.js +3 -23
- 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-server-settings.js +1 -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-knowledge.js +2 -1
- 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/auth/account-login.css +98 -0
- package/lib/public/auth/account-login.js +104 -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/css/user-settings-sessions.css +42 -0
- package/lib/public/index.html +28 -10
- 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/account-auth-settings.js +71 -0
- package/lib/public/modules/account-transport-settings.js +51 -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 +119 -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/passkey-browser.js +69 -0
- package/lib/public/modules/passkey-server-settings.js +57 -0
- 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 +6 -2
- 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/server-settings-controls.js +10 -0
- package/lib/public/modules/server-settings.js +7 -2
- 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-account.js +14 -1
- 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-sessions.js +120 -0
- package/lib/public/modules/user-settings.js +6 -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/modules/you-activity.js +3 -1
- package/lib/public/modules/you.js +91 -6
- package/lib/public/muse-avatar.svg +4 -0
- package/lib/public/style.css +6 -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-account-passkeys.js +186 -0
- package/lib/server-account-passwords.js +127 -0
- package/lib/server-account-security.js +53 -0
- package/lib/server-admin.js +63 -16
- package/lib/server-appearance-settings.js +13 -1
- package/lib/server-auth.js +107 -79
- 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 +8 -2
- package/lib/server.js +165 -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/user-knowledge-service.js +23 -1
- package/lib/users-auth.js +38 -3
- package/lib/users-contextual-clay-preferences.js +31 -0
- package/lib/users-create.js +97 -0
- package/lib/users-permissions.js +2 -8
- package/lib/users-server-pin.js +37 -0
- package/lib/users.js +18 -84
- 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 +11 -4
package/lib/server-auth.js
CHANGED
|
@@ -66,71 +66,54 @@ function attachAuth(ctx) {
|
|
|
66
66
|
// --- Multi-user auth tokens (persisted to disk) ---
|
|
67
67
|
var TOKENS_FILE = path.join(CONFIG_DIR, _isDevMode ? "auth-tokens-dev.json" : "auth-tokens.json");
|
|
68
68
|
var MULTI_USER_COOKIE = _isDevMode ? "relay_auth_user_dev" : "relay_auth_user";
|
|
69
|
-
var
|
|
70
|
-
|
|
71
|
-
|
|
72
|
-
|
|
73
|
-
|
|
74
|
-
|
|
75
|
-
|
|
76
|
-
|
|
77
|
-
|
|
78
|
-
|
|
79
|
-
|
|
80
|
-
|
|
69
|
+
var accountPolicy = require('./account-auth-policy').attachPolicy(users);
|
|
70
|
+
var transport = require('./account-auth-transport').attachTransport({ users: users, tlsOptions: tlsOptions });
|
|
71
|
+
var sessionStore = require('./account-session-store').attachSessionStore({
|
|
72
|
+
file: TOKENS_FILE, managed: accountPolicy.available, clientAddress: transport.clientAddress,
|
|
73
|
+
});
|
|
74
|
+
var throttle = require('./account-auth-throttle').attachThrottle({
|
|
75
|
+
file: path.join(CONFIG_DIR, _isDevMode ? 'auth-attempts-dev.json' : 'auth-attempts.json'), clientAddress: transport.clientAddress,
|
|
76
|
+
});
|
|
77
|
+
function sessionToken(req) { return parseCookies(req)[MULTI_USER_COOKIE]; }
|
|
78
|
+
function createMultiUserSession(userId, credential, passkeyId, secure, req) {
|
|
79
|
+
var created = sessionStore.create(userId, credential, passkeyId, req, req && sessionToken(req));
|
|
80
|
+
var age = created.entry.expiresAt ? Math.max(0, Math.floor((created.entry.expiresAt - Date.now()) / 1000)) : 31536000;
|
|
81
|
+
var cookie = MULTI_USER_COOKIE + '=' + created.token + '; Path=/; HttpOnly; SameSite=Strict; Max-Age=' + age +
|
|
82
|
+
(tlsOptions || secure || req && transport.info(req).secure ? '; Secure' : '');
|
|
83
|
+
var rememberedCookie = rememberedAccounts.remember(userId, req);
|
|
84
|
+
return { token: created.token, cookie: cookie, cookies: rememberedCookie ? [cookie, rememberedCookie] : [cookie] };
|
|
81
85
|
}
|
|
82
|
-
|
|
83
|
-
|
|
84
|
-
|
|
85
|
-
|
|
86
|
-
|
|
87
|
-
|
|
88
|
-
|
|
89
|
-
|
|
86
|
+
function validSessionUser(record) {
|
|
87
|
+
var user = record && users.findUserById(record.userId);
|
|
88
|
+
if (!user) return null;
|
|
89
|
+
if (record.passkeyId && (!require('./account-passkey-policy').configured(users.loadUsers()) ||
|
|
90
|
+
!(user.passkeys || []).some(function (key) { return key.id === record.passkeyId; }))) return null;
|
|
91
|
+
if (accountPolicy.requiresPassword(user) && (!user.passwordHash || user.mustChangePin ||
|
|
92
|
+
record.credentialVersion !== require('./account-session-store').digest(user.passwordHash))) return null;
|
|
93
|
+
return user;
|
|
90
94
|
}
|
|
91
|
-
|
|
92
|
-
loadTokens();
|
|
93
|
-
|
|
94
|
-
function createMultiUserSession(userId) {
|
|
95
|
-
var token = users.generateUserAuthToken(userId);
|
|
96
|
-
multiUserTokens[token] = userId;
|
|
97
|
-
saveTokens();
|
|
98
|
-
var cookie = MULTI_USER_COOKIE + "=" + token + "; Path=/; HttpOnly; SameSite=Strict; Max-Age=31536000" + (tlsOptions ? "; Secure" : "");
|
|
99
|
-
return { token: token, cookie: cookie };
|
|
100
|
-
}
|
|
101
|
-
|
|
102
95
|
function getMultiUserFromReq(req) {
|
|
103
|
-
|
|
104
|
-
var token =
|
|
105
|
-
|
|
106
|
-
|
|
107
|
-
|
|
108
|
-
|
|
109
|
-
|
|
110
|
-
}
|
|
96
|
+
if (accountPolicy.enabled() && !transport.allows(req, false)) return null;
|
|
97
|
+
var token = sessionToken(req);
|
|
98
|
+
var record = sessionStore.get(token, false);
|
|
99
|
+
var user = validSessionUser(record);
|
|
100
|
+
if (user) {
|
|
101
|
+
if (!req.claySessionPassive) sessionStore.get(token, true, req);
|
|
102
|
+
return user;
|
|
111
103
|
}
|
|
112
|
-
|
|
113
|
-
// login wall. Mirrors the old single-user onramp once single-user mode is
|
|
114
|
-
// absorbed into multi-user. Disabled the moment a PIN is set or a second
|
|
115
|
-
// user is added (then the normal token/login flow applies).
|
|
116
|
-
var solo = users.getSoloNoPinUser();
|
|
117
|
-
if (solo) return solo;
|
|
118
|
-
return null;
|
|
104
|
+
return users.getSoloNoPinUser() || null;
|
|
119
105
|
}
|
|
120
|
-
|
|
121
|
-
|
|
122
|
-
return !!getMultiUserFromReq(req);
|
|
106
|
+
function touchSession(req) {
|
|
107
|
+
if (getMultiUserFromReq(req)) sessionStore.get(sessionToken(req), true, req);
|
|
123
108
|
}
|
|
124
|
-
|
|
125
|
-
function revokeUserTokens(userId) {
|
|
126
|
-
|
|
127
|
-
|
|
128
|
-
|
|
129
|
-
|
|
130
|
-
|
|
131
|
-
}
|
|
109
|
+
function isMultiUserAuthed(req) { return !!getMultiUserFromReq(req); }
|
|
110
|
+
function revokeUserTokens(userId) { sessionStore.revokeUser(userId); }
|
|
111
|
+
function allowAttempt(req, res, username) {
|
|
112
|
+
try { throttle.consume(req, username); return true; }
|
|
113
|
+
catch (error) {
|
|
114
|
+
res.writeHead(error.status || 503, { 'Content-Type': 'application/json', 'Cache-Control': 'no-store' });
|
|
115
|
+
res.end(JSON.stringify({ error: error.message })); return false;
|
|
132
116
|
}
|
|
133
|
-
if (changed) saveTokens();
|
|
134
117
|
}
|
|
135
118
|
|
|
136
119
|
// --- PIN rate limiting (per-instance state) ---
|
|
@@ -163,7 +146,7 @@ function attachAuth(ctx) {
|
|
|
163
146
|
var recovery = null;
|
|
164
147
|
|
|
165
148
|
function setRecovery(urlPath, password) {
|
|
166
|
-
recovery = { urlPath: urlPath, password: password };
|
|
149
|
+
recovery = { urlPath: urlPath, password: password, until: Date.now() + 15 * 60000 };
|
|
167
150
|
}
|
|
168
151
|
|
|
169
152
|
function clearRecovery() {
|
|
@@ -246,14 +229,11 @@ function attachAuth(ctx) {
|
|
|
246
229
|
// --- Auth page selection ---
|
|
247
230
|
var pinPage = pages.pinPageHtml();
|
|
248
231
|
var adminSetupPage = pages.adminSetupPageHtml();
|
|
249
|
-
var loginPage = pages.multiUserLoginPageHtml();
|
|
250
|
-
var smtpLoginPage = pages.smtpLoginPageHtml();
|
|
251
232
|
|
|
252
233
|
function getAuthPage() {
|
|
253
234
|
if (!users.isMultiUser()) return pinPage;
|
|
254
235
|
if (!users.hasAdmin()) return adminSetupPage;
|
|
255
|
-
|
|
256
|
-
return loginPage;
|
|
236
|
+
return require('./account-login-page').render({ password: accountPolicy.enabled(), email: !accountPolicy.enabled() && smtp.isEmailLoginEnabled() });
|
|
257
237
|
}
|
|
258
238
|
|
|
259
239
|
function isRequestAuthed(req) {
|
|
@@ -268,8 +248,22 @@ function attachAuth(ctx) {
|
|
|
268
248
|
// --- Route handler ---
|
|
269
249
|
|
|
270
250
|
function handleRequest(req, res, fullUrl) {
|
|
251
|
+
if (require('./account-login-page').handleAsset(req, res, fullUrl)) return true;
|
|
252
|
+
if (accountPolicy.enabled() && transport.info(req).secure && typeof res.setHeader === 'function') res.setHeader('Strict-Transport-Security', 'max-age=31536000');
|
|
253
|
+
if ((accountPolicy.enabled() || fullUrl === '/api/account-auth-policy' && req.method === 'PUT') && /^(?:\/auth\/(?!passkey-browser\.js)|\/api\/(?:account-auth-policy|passkey-policy|passkeys|account-sessions|account-transport|user\/pin|admin\/users|profile)|\/recover\/)/.test(fullUrl) &&
|
|
254
|
+
!transport.allows(req, ['GET', 'HEAD', 'OPTIONS'].indexOf(req.method) === -1)) {
|
|
255
|
+
res.writeHead(403, { 'Content-Type': 'application/json', 'Cache-Control': 'no-store' });
|
|
256
|
+
res.end(JSON.stringify({ error: 'Use HTTPS and the same Clay address for account requests. Reverse proxies must be explicitly configured.' })); return true;
|
|
257
|
+
}
|
|
258
|
+
if (rememberedAccounts.handleRequest(req, res, fullUrl)) return true;
|
|
259
|
+
if (accountSecurity.handleRequest(req, res, fullUrl)) return true;
|
|
260
|
+
if (accountPasskeys.handleRequest(req, res, fullUrl)) return true;
|
|
261
|
+
if (accountPasswords.handleRequest(req, res, fullUrl)) return true;
|
|
271
262
|
// Admin password recovery
|
|
272
263
|
if (recovery && fullUrl === "/recover/" + recovery.urlPath) {
|
|
264
|
+
if (recovery.until <= Date.now()) {
|
|
265
|
+
recovery = null; res.writeHead(410, { 'Content-Type': 'application/json' }); res.end('{"error":"Recovery expired. Enable a new recovery link from the server terminal."}'); return true;
|
|
266
|
+
}
|
|
273
267
|
if (req.method === "GET") {
|
|
274
268
|
res.writeHead(200, { "Content-Type": "text/html; charset=utf-8" });
|
|
275
269
|
res.end(recoveryPageHtml());
|
|
@@ -288,6 +282,8 @@ function attachAuth(ctx) {
|
|
|
288
282
|
req.on("end", function () {
|
|
289
283
|
try {
|
|
290
284
|
var data = JSON.parse(body);
|
|
285
|
+
if (!allowAttempt(req, res, 'admin-recovery')) return;
|
|
286
|
+
if (!recovery || recovery.until <= Date.now()) throw new Error('Recovery expired.');
|
|
291
287
|
if (data.step === "verify") {
|
|
292
288
|
if (!data.password || data.password !== recovery.password) {
|
|
293
289
|
recordPinFailure(ip);
|
|
@@ -315,7 +311,9 @@ function attachAuth(ctx) {
|
|
|
315
311
|
res.end('{"error":"No admin account found"}');
|
|
316
312
|
return;
|
|
317
313
|
}
|
|
318
|
-
users.updateUserPin(admin.id, data.pin);
|
|
314
|
+
var reset = users.updateUserPin(admin.id, data.pin);
|
|
315
|
+
if (!reset.ok) throw new Error('Could not reset the administrator account.');
|
|
316
|
+
revokeUserTokens(admin.id);
|
|
319
317
|
recovery = null;
|
|
320
318
|
res.writeHead(200, { "Content-Type": "application/json" });
|
|
321
319
|
res.end('{"ok":true}');
|
|
@@ -334,6 +332,11 @@ function attachAuth(ctx) {
|
|
|
334
332
|
|
|
335
333
|
// Global auth endpoint (single-user PIN)
|
|
336
334
|
if (req.method === "POST" && req.url === "/auth") {
|
|
335
|
+
if (users.isMultiUser()) {
|
|
336
|
+
res.writeHead(403, { 'Content-Type': 'application/json', 'Cache-Control': 'no-store' });
|
|
337
|
+
res.end(JSON.stringify({ ok: false, error: 'Server PIN sign-in is unavailable. Sign in with your account.' }));
|
|
338
|
+
return true;
|
|
339
|
+
}
|
|
337
340
|
var ip = req.socket.remoteAddress || "";
|
|
338
341
|
var remaining = checkPinRateLimit(ip);
|
|
339
342
|
if (remaining !== null) {
|
|
@@ -439,9 +442,9 @@ function attachAuth(ctx) {
|
|
|
439
442
|
}
|
|
440
443
|
}
|
|
441
444
|
users.clearSetupCode();
|
|
442
|
-
var session = createMultiUserSession(result.user.id);
|
|
445
|
+
var session = createMultiUserSession(result.user.id, null, null, false, req);
|
|
443
446
|
res.writeHead(200, {
|
|
444
|
-
"Set-Cookie": session.
|
|
447
|
+
"Set-Cookie": session.cookies,
|
|
445
448
|
"Content-Type": "application/json",
|
|
446
449
|
});
|
|
447
450
|
res.end(JSON.stringify({ ok: true, user: { id: result.user.id, username: result.user.username, role: result.user.role } }));
|
|
@@ -472,6 +475,7 @@ function attachAuth(ctx) {
|
|
|
472
475
|
req.on("end", function () {
|
|
473
476
|
try {
|
|
474
477
|
var data = JSON.parse(body);
|
|
478
|
+
if (!allowAttempt(req, res, data.username)) return;
|
|
475
479
|
var user = users.authenticateUser(data.username, data.pin);
|
|
476
480
|
if (!user) {
|
|
477
481
|
recordPinFailure(ip);
|
|
@@ -481,11 +485,12 @@ function attachAuth(ctx) {
|
|
|
481
485
|
return;
|
|
482
486
|
}
|
|
483
487
|
clearPinFailures(ip);
|
|
484
|
-
|
|
488
|
+
throttle.success(req, data.username);
|
|
489
|
+
var session = createMultiUserSession(user.id, null, null, false, req);
|
|
485
490
|
var loginResp = { ok: true, user: { id: user.id, username: user.username, role: user.role } };
|
|
486
491
|
if (user.mustChangePin) loginResp.mustChangePin = true;
|
|
487
492
|
res.writeHead(200, {
|
|
488
|
-
"Set-Cookie": session.
|
|
493
|
+
"Set-Cookie": session.cookies,
|
|
489
494
|
"Content-Type": "application/json",
|
|
490
495
|
});
|
|
491
496
|
res.end(JSON.stringify(loginResp));
|
|
@@ -528,6 +533,7 @@ function attachAuth(ctx) {
|
|
|
528
533
|
res.end('{"ok":true}');
|
|
529
534
|
return;
|
|
530
535
|
}
|
|
536
|
+
if (!allowAttempt(req, res, 'email:' + String(data.email).toLowerCase())) return;
|
|
531
537
|
var result = smtp.requestOtp(data.email);
|
|
532
538
|
if (result.error) {
|
|
533
539
|
res.writeHead(429, { "Content-Type": "application/json" });
|
|
@@ -573,6 +579,7 @@ function attachAuth(ctx) {
|
|
|
573
579
|
res.end('{"error":"Email and code are required"}');
|
|
574
580
|
return;
|
|
575
581
|
}
|
|
582
|
+
if (!allowAttempt(req, res, 'email:' + String(data.email).toLowerCase())) return;
|
|
576
583
|
var otpResult = smtp.verifyOtp(data.email, data.code);
|
|
577
584
|
if (!otpResult.valid) {
|
|
578
585
|
recordPinFailure(ip);
|
|
@@ -587,9 +594,9 @@ function attachAuth(ctx) {
|
|
|
587
594
|
return;
|
|
588
595
|
}
|
|
589
596
|
clearPinFailures(ip);
|
|
590
|
-
var session = createMultiUserSession(user.id);
|
|
597
|
+
var session = createMultiUserSession(user.id, null, null, false, req);
|
|
591
598
|
res.writeHead(200, {
|
|
592
|
-
"Set-Cookie": session.
|
|
599
|
+
"Set-Cookie": session.cookies,
|
|
593
600
|
"Content-Type": "application/json",
|
|
594
601
|
});
|
|
595
602
|
res.end(JSON.stringify({ ok: true, user: { id: user.id, username: user.username, role: user.role } }));
|
|
@@ -625,7 +632,7 @@ function attachAuth(ctx) {
|
|
|
625
632
|
return;
|
|
626
633
|
}
|
|
627
634
|
var result;
|
|
628
|
-
if (smtp.isEmailLoginEnabled() && !data.pin) {
|
|
635
|
+
if (smtp.isEmailLoginEnabled() && !data.pin && !accountPasswords.policy.enabled()) {
|
|
629
636
|
// SMTP mode: username + email required, no PIN
|
|
630
637
|
if (!data.email || !/^[^\s@]+@[^\s@]+\.[^\s@]+$/.test(data.email)) {
|
|
631
638
|
res.writeHead(400, { "Content-Type": "application/json" });
|
|
@@ -667,9 +674,9 @@ function attachAuth(ctx) {
|
|
|
667
674
|
}
|
|
668
675
|
}
|
|
669
676
|
users.markInviteUsed(data.inviteCode);
|
|
670
|
-
var session = createMultiUserSession(result.user.id);
|
|
677
|
+
var session = createMultiUserSession(result.user.id, null, null, false, req);
|
|
671
678
|
res.writeHead(200, {
|
|
672
|
-
"Set-Cookie": session.
|
|
679
|
+
"Set-Cookie": session.cookies,
|
|
673
680
|
"Content-Type": "application/json",
|
|
674
681
|
});
|
|
675
682
|
res.end(JSON.stringify({ ok: true, user: { id: result.user.id, username: result.user.username, role: result.user.role } }));
|
|
@@ -686,17 +693,16 @@ function attachAuth(ctx) {
|
|
|
686
693
|
if (users.isMultiUser()) {
|
|
687
694
|
var cookies = parseCookies(req);
|
|
688
695
|
var token = cookies[MULTI_USER_COOKIE];
|
|
689
|
-
|
|
690
|
-
|
|
691
|
-
saveTokens();
|
|
696
|
+
try { sessionStore.revokeToken(token); } catch (error) {
|
|
697
|
+
res.writeHead(503, { 'Content-Type': 'application/json' }); res.end('{"error":"Could not persist sign-out. Please retry."}'); return true;
|
|
692
698
|
}
|
|
693
699
|
res.writeHead(200, {
|
|
694
|
-
"Set-Cookie": MULTI_USER_COOKIE + "=; Path=/; HttpOnly; SameSite=Strict; Max-Age=0" + (tlsOptions ? "; Secure" : ""),
|
|
700
|
+
"Set-Cookie": MULTI_USER_COOKIE + "=; Path=/; HttpOnly; SameSite=Strict; Max-Age=0" + (tlsOptions || transport.info(req).secure ? "; Secure" : ""),
|
|
695
701
|
"Content-Type": "application/json",
|
|
696
702
|
});
|
|
697
703
|
} else {
|
|
698
704
|
res.writeHead(200, {
|
|
699
|
-
"Set-Cookie": "relay_auth=; Path=/; HttpOnly; SameSite=Strict; Max-Age=0" + (tlsOptions ? "; Secure" : ""),
|
|
705
|
+
"Set-Cookie": "relay_auth=; Path=/; HttpOnly; SameSite=Strict; Max-Age=0" + (tlsOptions || transport.info(req).secure ? "; Secure" : ""),
|
|
700
706
|
"Content-Type": "application/json",
|
|
701
707
|
});
|
|
702
708
|
}
|
|
@@ -722,14 +728,36 @@ function attachAuth(ctx) {
|
|
|
722
728
|
return true;
|
|
723
729
|
}
|
|
724
730
|
res.writeHead(200, { "Content-Type": "text/html; charset=utf-8" });
|
|
725
|
-
res.end(smtp.isEmailLoginEnabled() ? pages.smtpInvitePageHtml(inviteCode) : pages.invitePageHtml(inviteCode));
|
|
731
|
+
res.end(smtp.isEmailLoginEnabled() && !accountPasswords.policy.enabled() ? pages.smtpInvitePageHtml(inviteCode) : pages.invitePageHtml(inviteCode));
|
|
726
732
|
return true;
|
|
727
733
|
}
|
|
728
734
|
|
|
729
735
|
return false;
|
|
730
736
|
}
|
|
731
737
|
|
|
738
|
+
var accountPasswords = require('./server-account-passwords').attachAccountPasswords({
|
|
739
|
+
users: users, devMode: _isDevMode, tlsOptions: tlsOptions, parseCookies: parseCookies,
|
|
740
|
+
getUser: getMultiUserFromReq, createSession: createMultiUserSession, revokeSessions: revokeUserTokens,
|
|
741
|
+
onPolicyChanged: ctx.onAccountPolicyChanged, throttle: throttle, transport: transport,
|
|
742
|
+
});
|
|
743
|
+
var accountPasskeys = require('./server-account-passkeys').attachAccountPasskeys({
|
|
744
|
+
users: users, devMode: _isDevMode, parseCookies: parseCookies, http: accountPasswords.http,
|
|
745
|
+
getUser: getMultiUserFromReq, createSession: createMultiUserSession,
|
|
746
|
+
sessionToken: sessionToken, clientAddress: transport.clientAddress,
|
|
747
|
+
});
|
|
748
|
+
|
|
749
|
+
var rememberedAccounts = require('./account-remembered').attachRemembered({
|
|
750
|
+
users: users, devMode: _isDevMode, parseCookies: parseCookies, transport: transport,
|
|
751
|
+
file: path.join(CONFIG_DIR, _isDevMode ? 'remembered-accounts-dev.json' : 'remembered-accounts.json'), read: accountPasswords.http.read,
|
|
752
|
+
});
|
|
753
|
+
|
|
754
|
+
var accountSecurity = require('./server-account-security').attachAccountSecurity({
|
|
755
|
+
users: users, getUser: getMultiUserFromReq, sessionToken: sessionToken, sessions: sessionStore,
|
|
756
|
+
validSessionUser: validSessionUser, http: accountPasswords.http, transport: transport,
|
|
757
|
+
});
|
|
758
|
+
|
|
732
759
|
return {
|
|
760
|
+
touchSession: touchSession,
|
|
733
761
|
handleRequest: handleRequest,
|
|
734
762
|
getMultiUserFromReq: getMultiUserFromReq,
|
|
735
763
|
isRequestAuthed: isRequestAuthed,
|
|
@@ -0,0 +1,40 @@
|
|
|
1
|
+
// Authenticated personal preferences, using the shared users/config persistence.
|
|
2
|
+
function attachContextualClaySettings(ctx) {
|
|
3
|
+
function reply(res, status, data) {
|
|
4
|
+
res.writeHead(status, { 'Content-Type': 'application/json', 'Cache-Control': 'no-store' });
|
|
5
|
+
res.end(JSON.stringify(data));
|
|
6
|
+
}
|
|
7
|
+
function identity(req) {
|
|
8
|
+
if (!ctx.isRequestAuthed(req)) return null;
|
|
9
|
+
return ctx.users.isMultiUser() ? ctx.getMultiUserFromReq(req) : { id: 'default' };
|
|
10
|
+
}
|
|
11
|
+
function handleRequest(req, res, url) {
|
|
12
|
+
if (url !== '/api/user/contextual-clay-geometry') return false;
|
|
13
|
+
var user = identity(req);
|
|
14
|
+
if (!user) { reply(res, 401, { error: 'Sign in to manage popover preferences.' }); return true; }
|
|
15
|
+
if (req.method === 'GET') {
|
|
16
|
+
try { reply(res, 200, { geometry: ctx.users.getContextualClayGeometry(user.id) }); }
|
|
17
|
+
catch (error) { reply(res, 500, { error: 'Could not read popover preference.' }); }
|
|
18
|
+
return true;
|
|
19
|
+
}
|
|
20
|
+
if (req.method !== 'PUT') { reply(res, 405, { error: 'Method not allowed.' }); return true; }
|
|
21
|
+
if (req.headers['x-clay-settings'] !== '1' || (req.headers['sec-fetch-site'] && ['same-origin', 'none'].indexOf(req.headers['sec-fetch-site']) < 0)) {
|
|
22
|
+
reply(res, 403, { error: 'Save preferences from Clay.' }); return true;
|
|
23
|
+
}
|
|
24
|
+
var body = ''; var tooLarge = false;
|
|
25
|
+
req.setEncoding('utf8');
|
|
26
|
+
req.on('data', function (chunk) { body += chunk; if (body.length > 1024 && !tooLarge) { tooLarge = true; reply(res, 413, { error: 'Request too large.' }); } });
|
|
27
|
+
req.on('end', function () {
|
|
28
|
+
if (tooLarge) return;
|
|
29
|
+
var live = identity(req);
|
|
30
|
+
if (!live || live.id !== user.id) { reply(res, 401, { error: 'Sign in again.' }); return; }
|
|
31
|
+
try {
|
|
32
|
+
var result = ctx.users.setContextualClayGeometry(live.id, JSON.parse(body));
|
|
33
|
+
reply(res, result.error ? 400 : 200, result);
|
|
34
|
+
} catch (error) { reply(res, 400, { error: 'Could not save popover preference.' }); }
|
|
35
|
+
});
|
|
36
|
+
return true;
|
|
37
|
+
}
|
|
38
|
+
return { handleRequest: handleRequest };
|
|
39
|
+
}
|
|
40
|
+
module.exports = { attachContextualClaySettings: attachContextualClaySettings };
|
|
@@ -0,0 +1,70 @@
|
|
|
1
|
+
// Presentation-only session operations share Home's authoritative permissions,
|
|
2
|
+
// model policy, saved-session projection and session manager. No transcript tap.
|
|
3
|
+
function attachContextualMateSessions(ctx) {
|
|
4
|
+
var receipts = new Map();
|
|
5
|
+
var lifetime = 30 * 60 * 1000;
|
|
6
|
+
function stamp(mate) { return JSON.stringify([mate.id, mate.createdBy || null, mate.createdAt || null, mate.builtinKey || null]); }
|
|
7
|
+
function live(ws, userId, msg, original) {
|
|
8
|
+
if (!ctx.isActorLive(ws, userId)) throw new Error('Your account is no longer available.');
|
|
9
|
+
var found = ctx.findMateProject(userId, msg.mateId, true);
|
|
10
|
+
if (!found || found.mate.archived || found.mate.lifecycleDeletion || found.mate.createdBy && found.mate.createdBy !== userId || stamp(found.mate) !== msg.mateStamp) throw new Error('This Mate is no longer available.');
|
|
11
|
+
var status = found.ctx.getStatus();
|
|
12
|
+
if (!status || !status.isMate || status.mateId !== found.mate.id || userId && status.projectOwnerId !== userId) throw new Error('This private Mate workspace is unavailable.');
|
|
13
|
+
found.contextualManager = found.ctx.getSessionManager();
|
|
14
|
+
found.contextualRevision = JSON.stringify([status.path, status.projectOwnerId, status.mateId, stamp(found.mate)]);
|
|
15
|
+
if (original && (found.ctx !== original.ctx || found.contextualRevision !== original.contextualRevision || found.contextualManager !== original.contextualManager)) throw new Error('This Mate conversation changed.');
|
|
16
|
+
return found;
|
|
17
|
+
}
|
|
18
|
+
function reply(ws, msg, data) { ctx.sendMessage(ws, Object.assign({ type: 'contextual_mate_sessions_result', requestId: msg.requestId, mateId: msg.mateId, mateStamp: msg.mateStamp }, data)); }
|
|
19
|
+
async function perform(ws, userId, msg) {
|
|
20
|
+
try {
|
|
21
|
+
if (typeof msg.requestId !== 'string' || !/^mate-conversations-[a-z0-9-]{36}$/.test(msg.requestId)) throw new Error('Invalid conversation request.');
|
|
22
|
+
var found = live(ws, userId, msg), manager = found.ctx.getSessionManager();
|
|
23
|
+
if (!manager) throw new Error('Conversation history is unavailable.');
|
|
24
|
+
if (msg.type === 'home_mate_sessions_list') {
|
|
25
|
+
var list = ctx.listHomeSessions(found, userId);
|
|
26
|
+
reply(ws, msg, { ok: true, sessions: list.slice(0, 500), truncated: list.length > 500 }); return;
|
|
27
|
+
}
|
|
28
|
+
var session;
|
|
29
|
+
if (msg.type === 'home_mate_session_open') {
|
|
30
|
+
session = ctx.resolveHomeSession(found, userId, msg.sessionId);
|
|
31
|
+
if (!session || typeof msg.sessionOriginId !== 'string' || msg.sessionOriginId !== session.sessionOriginId) throw new Error('This conversation is no longer available.');
|
|
32
|
+
} else {
|
|
33
|
+
var now = Date.now();
|
|
34
|
+
receipts.forEach(function (entry, key) { if (now - entry.at > lifetime) receipts.delete(key); });
|
|
35
|
+
var key = JSON.stringify([userId, msg.mateId, msg.requestId]);
|
|
36
|
+
var receipt = receipts.get(key);
|
|
37
|
+
manager.sessions.forEach(function (candidate) { if (candidate.contextualCreationRequestId === msg.requestId && ctx.ownsSession(candidate, userId)) session = candidate; });
|
|
38
|
+
if (session && session.contextualCreationMateStamp !== msg.mateStamp) throw new Error('This request belongs to a replaced Mate.');
|
|
39
|
+
if (receipt && (!session || receipt.origin !== session.sessionOriginId || receipt.stamp !== msg.mateStamp)) throw new Error('The previously created conversation is no longer available.');
|
|
40
|
+
if (!session && msg.lookupOnly) throw new Error('Creation was not confirmed. Start a new chat explicitly if you still want one.');
|
|
41
|
+
if (!session) {
|
|
42
|
+
if (receipts.size >= 1024) throw new Error('Please try starting a conversation later.');
|
|
43
|
+
var resolved = await ctx.homeModels.resolveMateModel(ws, found, userId);
|
|
44
|
+
found = live(ws, userId, msg, found);
|
|
45
|
+
// Recheck after model resolution: concurrent retries select one exact session.
|
|
46
|
+
manager.sessions.forEach(function (candidate) { if (candidate.contextualCreationRequestId === msg.requestId && ctx.ownsSession(candidate, userId)) session = candidate; });
|
|
47
|
+
receipt = receipts.get(key);
|
|
48
|
+
if (receipt && (!session || receipt.origin !== session.sessionOriginId || receipt.stamp !== msg.mateStamp)) throw new Error('The previously created conversation is no longer available.');
|
|
49
|
+
if (session && session.contextualCreationMateStamp !== msg.mateStamp) throw new Error('This request belongs to a replaced Mate.');
|
|
50
|
+
if (!session) {
|
|
51
|
+
if (receipts.size >= 1024) throw new Error('Please try starting a conversation later.');
|
|
52
|
+
session = manager.createSessionRaw({ ownerId: userId, vendor: resolved.vendor, model: resolved.model, effort: resolved.effort || null });
|
|
53
|
+
session.contextualCreationRequestId = msg.requestId;
|
|
54
|
+
session.contextualCreationMateStamp = msg.mateStamp;
|
|
55
|
+
manager.saveSessionFile(session);
|
|
56
|
+
}
|
|
57
|
+
}
|
|
58
|
+
if (!ctx.ownsSession(session, userId)) throw new Error('This conversation is no longer available.');
|
|
59
|
+
receipts.set(key, { at: now, origin: session.sessionOriginId, stamp: msg.mateStamp });
|
|
60
|
+
}
|
|
61
|
+
live(ws, userId, msg, found);
|
|
62
|
+
reply(ws, msg, { ok: true, sessionId: session.localId, sessionOriginId: session.sessionOriginId });
|
|
63
|
+
} catch (error) { reply(ws, msg, { ok: false, error: error.message || 'Conversation unavailable.' }); }
|
|
64
|
+
}
|
|
65
|
+
return { handle: function (ws, userId, msg) {
|
|
66
|
+
if (msg.presentation !== 'contextual' || !/^home_mate_(sessions_list|session_open|new_session)$/.test(msg.type)) return false;
|
|
67
|
+
perform(ws, userId, msg); return true;
|
|
68
|
+
} };
|
|
69
|
+
}
|
|
70
|
+
module.exports = { attachContextualMateSessions: attachContextualMateSessions };
|
package/lib/server-dm.js
CHANGED
|
@@ -49,7 +49,7 @@ function attachDm(ctx) {
|
|
|
49
49
|
var mateCtx2 = mates.buildMateCtx(userId);
|
|
50
50
|
if (mates.isMate(mateCtx2, msg.targetUserId)) {
|
|
51
51
|
var mate = mates.getMate(mateCtx2, msg.targetUserId);
|
|
52
|
-
if (!mate) return true;
|
|
52
|
+
if (!mate || mate.lifecycleDeletion) return true;
|
|
53
53
|
// Ensure mate project is registered (survives server restarts)
|
|
54
54
|
var mateSlug2 = "mate-" + mate.id;
|
|
55
55
|
if (!projects.has(mateSlug2)) {
|
|
@@ -69,6 +69,7 @@ function attachDm(ctx) {
|
|
|
69
69
|
id: mate.id,
|
|
70
70
|
displayName: mp.displayName || mate.name || "New Mate",
|
|
71
71
|
username: mate.id,
|
|
72
|
+
avatarCatalogId: mp.avatarCatalogId || "",
|
|
72
73
|
avatarStyle: mp.avatarStyle || "imprint",
|
|
73
74
|
avatarSeed: mp.avatarSeed || mate.id,
|
|
74
75
|
avatarColor: mp.avatarColor || "#5857fc",
|
package/lib/server-global-ws.js
CHANGED
|
@@ -63,14 +63,6 @@ function attachGlobalWs(opts) {
|
|
|
63
63
|
if (msg.type === "browse_dir") {
|
|
64
64
|
var rawPath = (msg.path || "").replace(/^~/, config.REAL_HOME);
|
|
65
65
|
var absTarget = path.resolve(rawPath);
|
|
66
|
-
// Multi-user mode: non-admins can only browse their home directory.
|
|
67
|
-
if (osUsers && ws._clayUser && ws._clayUser.role !== "admin") {
|
|
68
|
-
var browseHome = ws._clayUser.linuxUser ? "/home/" + ws._clayUser.linuxUser : null;
|
|
69
|
-
if (!browseHome || (absTarget !== browseHome && (absTarget + "/").indexOf(browseHome + "/") !== 0)) {
|
|
70
|
-
sendTo(ws, { type: "browse_dir_result", path: msg.path, entries: [], error: "Access restricted to your home directory" });
|
|
71
|
-
return;
|
|
72
|
-
}
|
|
73
|
-
}
|
|
74
66
|
var parentDir, prefix;
|
|
75
67
|
try {
|
|
76
68
|
var stat = fs.statSync(absTarget);
|
|
@@ -87,12 +79,17 @@ function attachGlobalWs(opts) {
|
|
|
87
79
|
parentDir = path.dirname(absTarget);
|
|
88
80
|
prefix = path.basename(absTarget).toLowerCase();
|
|
89
81
|
}
|
|
82
|
+
if (opts.canUsePath && !opts.canUsePath(ws._clayUser && ws._clayUser.id, parentDir)) {
|
|
83
|
+
sendTo(ws, { type: "browse_dir_result", entries: [], error: "Directory access is not permitted" });
|
|
84
|
+
return;
|
|
85
|
+
}
|
|
90
86
|
try {
|
|
91
87
|
var dirItems = fs.readdirSync(parentDir, { withFileTypes: true });
|
|
92
88
|
var dirEntries = [];
|
|
93
89
|
for (var di = 0; di < dirItems.length; di++) {
|
|
94
90
|
var d = dirItems[di];
|
|
95
91
|
if (!d.isDirectory()) continue;
|
|
92
|
+
if (opts.canUsePath && !opts.canUsePath(ws._clayUser && ws._clayUser.id, path.join(parentDir, d.name))) continue;
|
|
96
93
|
if (d.name.charAt(0) === ".") continue;
|
|
97
94
|
if (IGNORED_DIRS.has(d.name)) continue;
|
|
98
95
|
if (prefix && !d.name.toLowerCase().startsWith(prefix)) continue;
|
|
@@ -110,16 +107,9 @@ function attachGlobalWs(opts) {
|
|
|
110
107
|
if (msg.type === "add_project") {
|
|
111
108
|
var addPath = (msg.path || "").replace(/^~/, config.REAL_HOME);
|
|
112
109
|
var addAbs = path.resolve(addPath);
|
|
113
|
-
if (
|
|
114
|
-
|
|
115
|
-
|
|
116
|
-
return;
|
|
117
|
-
}
|
|
118
|
-
var userHome = "/home/" + ws._clayUser.linuxUser;
|
|
119
|
-
if (addAbs !== userHome && (addAbs + "/").indexOf(userHome + "/") !== 0) {
|
|
120
|
-
sendTo(ws, { type: "add_project_result", ok: false, error: "Path not allowed. You can only add directories under " + userHome });
|
|
121
|
-
return;
|
|
122
|
-
}
|
|
110
|
+
if (opts.canUsePath && !opts.canUsePath(ws._clayUser && ws._clayUser.id, addAbs)) {
|
|
111
|
+
sendTo(ws, { type: "add_project_result", ok: false, error: "Directory access is not permitted" });
|
|
112
|
+
return;
|
|
123
113
|
}
|
|
124
114
|
try {
|
|
125
115
|
var addStat = fs.statSync(addAbs);
|
|
@@ -133,7 +123,7 @@ function attachGlobalWs(opts) {
|
|
|
133
123
|
}
|
|
134
124
|
if (typeof onAddProject === "function") {
|
|
135
125
|
var result = onAddProject(addAbs, ws._clayUser);
|
|
136
|
-
sendTo(ws, {
|
|
126
|
+
sendTo(ws, Object.assign({}, result, { type: "add_project_result" }));
|
|
137
127
|
} else {
|
|
138
128
|
sendTo(ws, { type: "add_project_result", ok: false, error: "Not supported" });
|
|
139
129
|
}
|
|
@@ -159,7 +149,7 @@ function attachGlobalWs(opts) {
|
|
|
159
149
|
}
|
|
160
150
|
if (typeof onCreateProject === "function") {
|
|
161
151
|
var createResult = onCreateProject(createName, ws._clayUser);
|
|
162
|
-
sendTo(ws, {
|
|
152
|
+
sendTo(ws, Object.assign({}, createResult, { type: "add_project_result" }));
|
|
163
153
|
} else {
|
|
164
154
|
sendTo(ws, { type: "add_project_result", ok: false, error: "Not supported" });
|
|
165
155
|
}
|
|
@@ -3,7 +3,7 @@
|
|
|
3
3
|
function homeDebateQuestions(input) {
|
|
4
4
|
var source = input && Array.isArray(input.questions) && input.questions[0] ? input.questions[0] : null;
|
|
5
5
|
if (!source) return [];
|
|
6
|
-
var question = { header: source.header || "", question: source.question || "", multiSelect: false, options: [] };
|
|
6
|
+
var question = { header: source.header || "", question: source.question || "", multiSelect: false, allowOther: source.allowOther !== false, options: [] };
|
|
7
7
|
var options = Array.isArray(source.options) ? source.options.slice(0, 6) : [];
|
|
8
8
|
for (var i = 0; i < options.length; i++) question.options.push({ label: options[i].label || "Option", description: options[i].description || "" });
|
|
9
9
|
return [question];
|
|
@@ -36,6 +36,7 @@ function findDebateTurn(messages, event) {
|
|
|
36
36
|
function debateIdentity(source, fallback) {
|
|
37
37
|
var prior = fallback || {};
|
|
38
38
|
return {
|
|
39
|
+
avatarCatalogId: source.avatarCatalogId || prior.avatarCatalogId || "",
|
|
39
40
|
avatarStyle: source.avatarStyle || prior.avatarStyle || "imprint",
|
|
40
41
|
avatarSeed: source.avatarSeed || prior.avatarSeed || source.mateId || "mate",
|
|
41
42
|
avatarColor: source.avatarColor || prior.avatarColor || "",
|
|
@@ -112,7 +113,7 @@ function applyAssignmentHistoryEvent(messages, event) {
|
|
|
112
113
|
messages.push({ role: "assignment", assignment: assignment });
|
|
113
114
|
}
|
|
114
115
|
|
|
115
|
-
function historyToHomeChat(history, debateSetupMode, mateCreationMode) {
|
|
116
|
+
function historyToHomeChat(history, debateSetupMode, mateCreationMode, pendingAskUser) {
|
|
116
117
|
var messages = [];
|
|
117
118
|
var pending = "";
|
|
118
119
|
var interviewMode = debateSetupMode === true || mateCreationMode === true;
|
|
@@ -124,6 +125,12 @@ function historyToHomeChat(history, debateSetupMode, mateCreationMode) {
|
|
|
124
125
|
for (var i = 0; i < history.length; i++) {
|
|
125
126
|
var event = history[i];
|
|
126
127
|
if (!event) continue;
|
|
128
|
+
if (event.type === 'tool_executing' && event.name === 'AskUserQuestion' && ['mcp-import', 'mate-schedule', 'mcp_fallback', 'product-control'].indexOf(event.source) >= 0) {
|
|
129
|
+
flushAssistant();
|
|
130
|
+
var activeConsent = pendingAskUser === undefined || !!(pendingAskUser && pendingAskUser[event.id]);
|
|
131
|
+
messages.push({ role: 'question', flow: event.source === 'mcp-import' ? 'mcp_import' : 'mate_question', toolId: event.id, questions: homeDebateQuestions(event.input), status: activeConsent ? 'pending' : 'expired', error: activeConsent ? '' : 'This question is no longer active. Ask for a new review.' });
|
|
132
|
+
continue;
|
|
133
|
+
}
|
|
127
134
|
if (event.type === "project_assignment_proposal" || event.type === "project_assignment_status") {
|
|
128
135
|
flushAssistant();
|
|
129
136
|
applyAssignmentHistoryEvent(messages, event);
|
|
@@ -185,7 +192,7 @@ function historyToHomeChat(history, debateSetupMode, mateCreationMode) {
|
|
|
185
192
|
} else if (interviewMode && event.type === "tool_executing" && event.name === "AskUserQuestion" && event.id && event.input) {
|
|
186
193
|
flushAssistant();
|
|
187
194
|
messages.push({ role: "question", flow: mateCreationMode === true ? "mate_creation" : "debate", toolId: event.id, questions: homeDebateQuestions(event.input), status: "pending", error: "" });
|
|
188
|
-
} else if ((event.type === "ask_user_answered" || event.type === "home_debate_question_expired" || event.type === "home_mate_creation_question_expired") && event.toolId) {
|
|
195
|
+
} else if ((event.type === "ask_user_answered" || event.type === "home_debate_question_expired" || event.type === "home_mate_creation_question_expired" || event.type === "mcp_import_consent_expired" || event.type === "mate_schedule_question_expired") && event.toolId) {
|
|
189
196
|
for (var k = messages.length - 1; k >= 0; k--) {
|
|
190
197
|
if (messages[k].role === "question" && messages[k].toolId === event.toolId) {
|
|
191
198
|
messages[k].status = event.type === "ask_user_answered" ? "answered" : "expired";
|
|
@@ -273,7 +280,7 @@ function transformEvent(event, mateId, session, requestId, stableSessionId) {
|
|
|
273
280
|
}
|
|
274
281
|
if (session && session.homeDebatePlanning === true && HOME_DEBATE_EVENT_TYPES[event.type]) {
|
|
275
282
|
var live = { type: "home_debate_event", eventType: event.type };
|
|
276
|
-
var fields = ["turnId", "decisionId", "decision", "toolName", "command", "commandTruncated", "topic", "format", "moderatorId", "moderatorName", "panelists", "mateName", "role", "round", "activity", "delta", "text", "reason", "action", "avatarStyle", "avatarSeed", "avatarColor", "avatarCustom"];
|
|
283
|
+
var fields = ["turnId", "decisionId", "decision", "toolName", "command", "commandTruncated", "topic", "format", "moderatorId", "moderatorName", "panelists", "mateName", "role", "round", "activity", "delta", "text", "reason", "action", "avatarCatalogId", "avatarStyle", "avatarSeed", "avatarColor", "avatarCustom"];
|
|
277
284
|
for (var fi = 0; fi < fields.length; fi++) if (Object.prototype.hasOwnProperty.call(event, fields[fi])) live[fields[fi]] = event[fields[fi]];
|
|
278
285
|
if (event.mateId) live.speakerMateId = event.mateId;
|
|
279
286
|
return Object.assign(live, metadata);
|
|
@@ -298,6 +305,13 @@ function transformEvent(event, mateId, session, requestId, stableSessionId) {
|
|
|
298
305
|
if (event.type === "debate_proposal_resolved" && event.proposalId) return Object.assign({ type: "home_debate_proposal_resolved", proposalId: event.proposalId, action: event.action || "cancel", error: event.error || "" }, metadata);
|
|
299
306
|
if (session && session.mateCreationMode === true && event.type === "mate_creation_proposal" && event.proposal) return Object.assign({ type: "home_mate_creation_proposal", proposal: event.proposal }, metadata);
|
|
300
307
|
if (session && session.mateCreationMode === true && event.type === "mate_creation_proposal_resolved" && event.proposalId) return Object.assign({ type: "home_mate_creation_proposal_resolved", proposalId: event.proposalId, action: event.action || "cancel", createdMateId: event.mateId || null, mateName: event.mateName || null, error: event.error || "" }, metadata);
|
|
308
|
+
if (!(session && (session.debateSetupMode === true || session.mateCreationMode === true)) && event.type === 'tool_executing' && event.name === 'AskUserQuestion' && ['mate-schedule', 'mcp_fallback', 'product-control'].indexOf(event.source) >= 0) return Object.assign({ type: 'home_mate_question', toolId: event.id, questions: homeDebateQuestions(event.input) }, metadata);
|
|
309
|
+
if (session && session.debateSetupMode !== true && session.mateCreationMode !== true && event.type === 'ask_user_answered' && event.toolId && (session.history || []).some(function (item) { return item.id === event.toolId && ['mate-schedule', 'mcp_fallback', 'product-control'].indexOf(item.source) >= 0; })) return Object.assign({ type: 'home_mate_question_resolved', toolId: event.toolId, status: 'answered', answers: event.answers }, metadata);
|
|
310
|
+
if (event.type === 'tool_executing' && event.name === 'AskUserQuestion' && event.source === 'mcp-import') return Object.assign({ type: 'home_mcp_import_question', toolId: event.id, questions: homeDebateQuestions(event.input) }, metadata);
|
|
311
|
+
if (event.type === 'product_control_question_expired') return Object.assign({ type: 'home_mate_question_resolved', toolId: event.toolId, status: 'expired', error: event.error }, metadata);
|
|
312
|
+
if (event.type === 'mate_schedule_question_expired') return Object.assign({ type: 'home_mate_question_resolved', toolId: event.toolId, status: 'expired', error: event.error }, metadata);
|
|
313
|
+
if (event.type === 'mcp_import_consent_expired') return Object.assign({ type: 'home_mcp_import_question_resolved', toolId: event.toolId, status: 'expired', error: event.error }, metadata);
|
|
314
|
+
if (session && event.type === 'ask_user_answered' && event.toolId && (session.history || []).some(function (item) { return item.id === event.toolId && item.source === 'mcp-import'; })) return Object.assign({ type: 'home_mcp_import_question_resolved', toolId: event.toolId, status: 'answered', answers: event.answers }, metadata);
|
|
301
315
|
if (session && session.debateSetupMode === true && event.type === "tool_executing" && event.name === "AskUserQuestion" && event.id && event.input) {
|
|
302
316
|
return Object.assign({ type: "home_debate_question", toolId: event.id, questions: homeDebateQuestions(event.input) }, metadata);
|
|
303
317
|
}
|