clay-server 5.2.0-beta.1 → 5.2.0-beta.11
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.md +0 -4
- package/lib/account-auth-socket.js +1 -0
- package/lib/builtin-mates.js +19 -16
- package/lib/bundled-skills/clay-agent-browser/SKILL.md +6 -2
- package/lib/canonical-clay-record-authority.js +15 -0
- package/lib/canonical-clay-scheduling-authority.js +19 -0
- package/lib/claude-hook-installer.js +1 -239
- package/lib/claude-jsonl-watcher.js +1 -204
- package/lib/clay-control-presentation-binding.js +96 -0
- package/lib/clay-control-presentation.js +128 -0
- package/lib/clay-control-target-projection.js +26 -0
- package/lib/clay-mate-chat-receipts.js +26 -0
- package/lib/clay-mate-chat.js +88 -0
- package/lib/clay-mate-knowledge-input.js +26 -0
- package/lib/clay-mate-knowledge.js +95 -0
- package/lib/clay-mate-lifecycle.js +95 -0
- package/lib/clay-product-control-input.js +33 -0
- package/lib/clay-product-control-tools.js +52 -0
- package/lib/clay-product-control.js +250 -0
- package/lib/clay-project-lifecycle.js +154 -0
- package/lib/clay-project-record-input.js +44 -0
- package/lib/clay-project-records.js +84 -0
- package/lib/clay-scheduling-input.js +21 -0
- package/lib/clay-scheduling-receipts.js +26 -0
- package/lib/clay-scheduling.js +119 -0
- package/lib/clay-screen-controls.js +104 -0
- package/lib/clay-skill-install.js +1 -33
- package/lib/clay-vendor-usage.js +44 -0
- package/lib/clay-workspace-controls.js +84 -0
- package/lib/clay-workspace-input.js +17 -0
- package/lib/clay-workspace-receipts.js +26 -0
- package/lib/cli-sessions.js +1 -300
- package/lib/codex-defaults.js +1 -28
- package/lib/context-usage.js +3 -2
- package/lib/contextual-screen-snapshot.js +38 -0
- package/lib/daemon-project-access.js +11 -0
- package/lib/daemon-project-lifecycle-callbacks.js +15 -0
- package/lib/daemon-project-lifecycle.js +262 -0
- package/lib/daemon-projects.js +1 -1
- package/lib/daemon.js +78 -276
- package/lib/default-ai-runtime.js +4 -8
- package/lib/dm-digest-cursor.js +120 -0
- package/lib/email-mcp-server.js +1 -1
- package/lib/github-star-count.js +147 -0
- package/lib/issues-service.js +29 -15
- package/lib/kiro-defaults.js +1 -22
- package/lib/knowledge-db-import-validation.js +46 -0
- package/lib/knowledge-db-import.js +99 -0
- package/lib/knowledge-db-service.js +24 -33
- package/lib/knowledge-db-storage-nedb-maintenance.js +99 -0
- package/lib/knowledge-db-storage-nedb.js +66 -0
- package/lib/knowledge-db-storage.js +72 -0
- package/lib/knowledge-db-validation.js +0 -0
- package/lib/knowledge-document-index.js +2 -1
- package/lib/knowledge-file-store.js +7 -1
- package/lib/knowledge-product-operations.js +46 -0
- package/lib/mate-avatar-catalog.js +12 -0
- package/lib/mate-avatar-migration.js +41 -0
- package/lib/mate-context-service.js +138 -0
- package/lib/mate-context-tools.js +21 -0
- package/lib/mate-creation-mcp-server.js +2 -0
- package/lib/mate-knowledge-canonical-access.js +10 -0
- package/lib/mate-knowledge-mate-bound.js +53 -0
- package/lib/mate-knowledge-mcp-server.js +55 -8
- package/lib/mate-knowledge-service.js +16 -34
- package/lib/mate-knowledge-text-tools.js +106 -0
- package/lib/mate-lifecycle-service.js +94 -0
- package/lib/mate-message-delivery.js +43 -0
- package/lib/mate-ready-creation.js +9 -1
- package/lib/mate-schedule-input.js +29 -0
- package/lib/mate-schedule-lifecycle.js +151 -0
- package/lib/mate-scheduling.js +103 -0
- package/lib/mates.js +18 -6
- package/lib/mcp-agent-tools.js +117 -0
- package/lib/mcp-connection-store.js +119 -15
- package/lib/mcp-import-credentials.js +31 -0
- package/lib/mcp-local-transport.js +13 -0
- package/lib/mcp-oauth.js +8 -6
- package/lib/mcp-proxy.js +2 -32
- package/lib/mcp-query-bridge.js +30 -0
- package/lib/mcp-remote-connections.js +74 -20
- package/lib/mcp-source-adapters.js +1 -0
- package/lib/mcp-source-context.js +1 -0
- package/lib/mcp-source-discovery.js +1 -0
- package/lib/mcp-source-plugins.js +1 -0
- package/lib/mcp-source-restrictions.js +1 -0
- package/lib/mcp-tool-policy.js +9 -0
- package/lib/notes-checklist.js +92 -0
- package/lib/notes.js +51 -4
- package/lib/os-user-diagnostics.js +2 -4
- package/lib/os-users.js +24 -70
- package/lib/pane-pending-interactions.js +20 -0
- package/lib/pane-session-activation.js +114 -0
- package/lib/pane-session-transport.js +26 -0
- package/lib/project-admin-overview.js +51 -0
- package/lib/project-ask-user.js +8 -4
- package/lib/project-connection.js +14 -10
- package/lib/project-control-git-view.js +12 -0
- package/lib/project-debate.js +1 -0
- package/lib/project-delegated-follow-up.js +2 -1
- package/lib/project-directory-claim.js +65 -0
- package/lib/project-file-operations.js +61 -0
- package/lib/project-filesystem.js +15 -85
- package/lib/project-full-access.js +23 -2
- package/lib/project-http.js +7 -4
- package/lib/project-knowledge.js +32 -18
- package/lib/project-lifecycle-operations.js +98 -0
- package/lib/project-lifecycle-process-witness.js +32 -0
- package/lib/project-lifecycle-runtime.js +50 -0
- package/lib/project-linux-access.js +22 -0
- package/lib/project-logs-canonical-clay.js +27 -0
- package/lib/project-logs-clay-query.js +16 -0
- package/lib/project-logs-schema.js +4 -2
- package/lib/project-logs-service.js +8 -7
- package/lib/project-logs.js +1 -0
- package/lib/project-loop.js +1 -0
- package/lib/project-mate-chat-control.js +55 -0
- package/lib/project-mate-creation-proposal.js +18 -3
- package/lib/project-mate-interaction.js +40 -62
- package/lib/project-mcp.js +54 -16
- package/lib/project-models.js +14 -31
- package/lib/project-notifications.js +76 -17
- package/lib/project-ownership.js +77 -0
- package/lib/project-pair-result-delivery.js +14 -3
- package/lib/project-pair-usage.js +12 -13
- package/lib/project-pending-message-queue.js +4 -1
- package/lib/project-product-control.js +89 -0
- package/lib/project-product-session-queue.js +46 -0
- package/lib/project-push-access.js +28 -0
- package/lib/project-scheduled-message-queue.js +30 -0
- package/lib/project-scheduled-messages.js +67 -68
- package/lib/project-scheduled-task-control.js +83 -0
- package/lib/project-scheduled-tasks.js +13 -2
- package/lib/project-scheduling-access.js +10 -0
- package/lib/project-session-actions.js +65 -0
- package/lib/project-session-delete.js +8 -1
- package/lib/project-session-document.js +27 -7
- package/lib/project-session-github.js +63 -19
- package/lib/project-session-history-actions.js +167 -0
- package/lib/project-session-linear.js +14 -6
- package/lib/project-session-notes.js +40 -11
- package/lib/project-session-pair.js +1 -1
- package/lib/project-session-runtime-actions.js +64 -0
- package/lib/project-session-spawn.js +2 -3
- package/lib/project-session-vendor.js +55 -0
- package/lib/project-sessions.js +160 -290
- package/lib/project-shared-browser.js +78 -17
- package/lib/project-start-protocol.js +29 -0
- package/lib/project-studio-presentation.js +58 -0
- package/lib/project-user-message.js +67 -1
- package/lib/project-vendor-login.js +8 -36
- package/lib/project-workspace-operations.js +126 -0
- package/lib/project-workspace-query.js +19 -2
- package/lib/project.js +181 -45
- package/lib/public/app.js +71 -17
- package/lib/public/appearance-bootstrap.js +16 -0
- package/lib/public/css/clay-tool-activity.css +51 -0
- package/lib/public/css/clay-workspace.css +29 -0
- package/lib/public/css/command-palette.css +12 -33
- package/lib/public/css/contextual-clay.css +240 -0
- package/lib/public/css/filebrowser.css +1 -1
- package/lib/public/css/home-debate-planning.css +2 -0
- package/lib/public/css/home-mate-creation.css +5 -0
- package/lib/public/css/input.css +6 -0
- package/lib/public/css/mate-avatar-gallery.css +12 -0
- package/lib/public/css/mate-conversation.css +10 -5
- package/lib/public/css/mate-loading-scene.css +21 -0
- package/lib/public/css/messages.css +6 -2
- package/lib/public/css/overlays.css +68 -258
- package/lib/public/css/project-admin-overview.css +13 -0
- package/lib/public/css/project-mate-creation.css +5 -6
- package/lib/public/css/project-start.css +108 -0
- package/lib/public/css/projects-hub.css +53 -14
- package/lib/public/css/session-folders.css +11 -0
- package/lib/public/css/session-github.css +46 -1
- package/lib/public/css/settings-shell.css +103 -0
- package/lib/public/css/shared-browser.css +35 -1
- package/lib/public/css/sidebar.css +7 -0
- package/lib/public/css/sticky-notes.css +87 -1
- package/lib/public/css/title-bar.css +79 -0
- package/lib/public/index.html +61 -68
- package/lib/public/mate-avatars/B01.png +0 -0
- package/lib/public/mate-avatars/B02.png +0 -0
- package/lib/public/mate-avatars/B03.png +0 -0
- package/lib/public/mate-avatars/B04.png +0 -0
- package/lib/public/mate-avatars/B05.png +0 -0
- package/lib/public/mate-avatars/B06.png +0 -0
- package/lib/public/mate-avatars/B07.png +0 -0
- package/lib/public/mate-avatars/B08.png +0 -0
- package/lib/public/mate-avatars/B09.png +0 -0
- package/lib/public/mate-avatars/B10.png +0 -0
- package/lib/public/mate-avatars/B11.png +0 -0
- package/lib/public/mate-avatars/B12.png +0 -0
- package/lib/public/mate-avatars/B13.png +0 -0
- package/lib/public/mate-avatars/B14.png +0 -0
- package/lib/public/mate-avatars/B15.png +0 -0
- package/lib/public/mate-avatars/B16.png +0 -0
- package/lib/public/mate-avatars/B17.png +0 -0
- package/lib/public/mate-avatars/B18.png +0 -0
- package/lib/public/mate-avatars/B19.png +0 -0
- package/lib/public/mate-avatars/B20.png +0 -0
- package/lib/public/mate-avatars/B21.png +0 -0
- package/lib/public/mate-avatars/B22.png +0 -0
- package/lib/public/mate-avatars/B23.png +0 -0
- package/lib/public/mate-avatars/B24.png +0 -0
- package/lib/public/mate-avatars/B25.png +0 -0
- package/lib/public/mate-avatars/B26.png +0 -0
- package/lib/public/mate-avatars/B27.png +0 -0
- package/lib/public/mate-avatars/B28.png +0 -0
- package/lib/public/mate-avatars/B29.png +0 -0
- package/lib/public/mate-avatars/B30.png +0 -0
- package/lib/public/mate-avatars/B31.png +0 -0
- package/lib/public/mate-avatars/B32.png +0 -0
- package/lib/public/mate-avatars/B33.png +0 -0
- package/lib/public/mate-avatars/B34.png +0 -0
- package/lib/public/mate-avatars/B35.png +0 -0
- package/lib/public/mate-avatars/B36.png +0 -0
- package/lib/public/mate-avatars/B37.png +0 -0
- package/lib/public/mate-avatars/B38.png +0 -0
- package/lib/public/mate-avatars/B39.png +0 -0
- package/lib/public/mate-avatars/B40.png +0 -0
- package/lib/public/mate-avatars/B41.png +0 -0
- package/lib/public/mate-avatars/B42.png +0 -0
- package/lib/public/mate-avatars/B43.png +0 -0
- package/lib/public/mate-avatars/B44.png +0 -0
- package/lib/public/mate-avatars/B45.png +0 -0
- package/lib/public/mate-avatars/B46.png +0 -0
- package/lib/public/mate-avatars/B47.png +0 -0
- package/lib/public/mate-avatars/B48.png +0 -0
- package/lib/public/mate-avatars/C01.png +0 -0
- package/lib/public/mate-avatars/C02.png +0 -0
- package/lib/public/mate-avatars/C03.png +0 -0
- package/lib/public/mate-avatars/C04.png +0 -0
- package/lib/public/mate-avatars/C05.png +0 -0
- package/lib/public/mate-avatars/C06.png +0 -0
- package/lib/public/mate-avatars/C07.png +0 -0
- package/lib/public/mate-avatars/C08.png +0 -0
- package/lib/public/mate-avatars/C09.png +0 -0
- package/lib/public/mate-avatars/C10.png +0 -0
- package/lib/public/mate-avatars/C11.png +0 -0
- package/lib/public/mate-avatars/C12.png +0 -0
- package/lib/public/mate-avatars/C13.png +0 -0
- package/lib/public/mate-avatars/C14.png +0 -0
- package/lib/public/mate-avatars/C15.png +0 -0
- package/lib/public/mate-avatars/C16.png +0 -0
- package/lib/public/mate-avatars/C17.png +0 -0
- package/lib/public/mate-avatars/C18.png +0 -0
- package/lib/public/mate-avatars/C19.png +0 -0
- package/lib/public/mate-avatars/C20.png +0 -0
- package/lib/public/mate-avatars/C21.png +0 -0
- package/lib/public/mate-avatars/C22.png +0 -0
- package/lib/public/mate-avatars/C23.png +0 -0
- package/lib/public/mate-avatars/C24.png +0 -0
- package/lib/public/mate-avatars/C25.png +0 -0
- package/lib/public/mate-avatars/C26.png +0 -0
- package/lib/public/mate-avatars/C27.png +0 -0
- package/lib/public/mate-avatars/C28.png +0 -0
- package/lib/public/mate-avatars/C29.png +0 -0
- package/lib/public/mate-avatars/C30.png +0 -0
- package/lib/public/mate-avatars/C31.png +0 -0
- package/lib/public/mate-avatars/C32.png +0 -0
- package/lib/public/mate-avatars/C33.png +0 -0
- package/lib/public/mate-avatars/C34.png +0 -0
- package/lib/public/mate-avatars/C35.png +0 -0
- package/lib/public/mate-avatars/C36.png +0 -0
- package/lib/public/mate-avatars/C37.png +0 -0
- package/lib/public/mate-avatars/C38.png +0 -0
- package/lib/public/mate-avatars/C39.png +0 -0
- package/lib/public/mate-avatars/C40.png +0 -0
- package/lib/public/mate-avatars/C41.png +0 -0
- package/lib/public/mate-avatars/C42.png +0 -0
- package/lib/public/mate-avatars/C43.png +0 -0
- package/lib/public/mate-avatars/C44.png +0 -0
- package/lib/public/mate-avatars/C45.png +0 -0
- package/lib/public/mate-avatars/C46.png +0 -0
- package/lib/public/mate-avatars/C47.png +0 -0
- package/lib/public/mate-avatars/C48.png +0 -0
- package/lib/public/mate-avatars/catalog.json +482 -0
- package/lib/public/mate-avatars/lead-clay.png +0 -0
- package/lib/public/modules/admin-settings-invitations.js +2 -2
- package/lib/public/modules/admin-settings-projects.js +8 -4
- package/lib/public/modules/admin-settings-ui.js +20 -4
- package/lib/public/modules/admin-settings-users.js +4 -4
- package/lib/public/modules/app-connection.js +11 -1
- package/lib/public/modules/app-favicon.js +18 -9
- package/lib/public/modules/app-header.js +7 -4
- package/lib/public/modules/app-home-hub.js +2 -1
- package/lib/public/modules/app-loop-ui.js +2 -0
- package/lib/public/modules/app-message-router.js +22 -1
- package/lib/public/modules/app-messages.js +125 -19
- package/lib/public/modules/app-misc.js +3 -1
- package/lib/public/modules/app-notifications.js +11 -5
- package/lib/public/modules/app-panels.js +61 -123
- package/lib/public/modules/app-projects.js +14 -407
- package/lib/public/modules/app-rate-limit.js +19 -28
- package/lib/public/modules/app-rendering.js +4 -3
- package/lib/public/modules/avatar.js +15 -41
- package/lib/public/modules/chat-render-runtime.js +20 -0
- package/lib/public/modules/clay-browser-links.js +47 -0
- package/lib/public/modules/clay-control-activity.js +214 -0
- package/lib/public/modules/clay-control-copy.js +36 -0
- package/lib/public/modules/clay-control-detail-targets.js +44 -0
- package/lib/public/modules/clay-control-object-targets.js +52 -0
- package/lib/public/modules/clay-control-target-visibility.js +12 -0
- package/lib/public/modules/clay-control-targets.js +44 -0
- package/lib/public/modules/clay-log-links.js +23 -0
- package/lib/public/modules/clay-navigation-render.js +52 -0
- package/lib/public/modules/clay-owner-navigation.js +33 -0
- package/lib/public/modules/clay-session-links.js +31 -0
- package/lib/public/modules/clay-studio-bridge.js +20 -0
- package/lib/public/modules/clay-studio-document.js +67 -0
- package/lib/public/modules/clay-studio-render.js +146 -0
- package/lib/public/modules/clay-tool-activity.js +140 -0
- package/lib/public/modules/clay-tool-presentation.js +343 -0
- package/lib/public/modules/command-palette.js +162 -40
- package/lib/public/modules/contextual-ask-session.js +26 -0
- package/lib/public/modules/contextual-clay-geometry.js +155 -0
- package/lib/public/modules/contextual-clay-session.js +130 -0
- package/lib/public/modules/contextual-clay-workspace.js +169 -0
- package/lib/public/modules/contextual-clay.js +252 -0
- package/lib/public/modules/contextual-composer.js +91 -0
- package/lib/public/modules/contextual-mate-context.js +117 -0
- package/lib/public/modules/contextual-mate-hint.js +40 -0
- package/lib/public/modules/contextual-mate-identity.js +23 -0
- package/lib/public/modules/contextual-mate-sessions.js +134 -0
- package/lib/public/modules/contextual-search.js +137 -0
- package/lib/public/modules/contextual-session-citations.js +58 -0
- package/lib/public/modules/debate.js +1 -0
- package/lib/public/modules/default-ai.js +11 -3
- package/lib/public/modules/elicitation-form.js +5 -0
- package/lib/public/modules/filebrowser.js +20 -1
- package/lib/public/modules/generation-stop.js +8 -5
- package/lib/public/modules/git-panel.js +3 -1
- package/lib/public/modules/github-star.js +66 -0
- package/lib/public/modules/history-replay-batch.js +13 -1
- package/lib/public/modules/home-debate-live.js +2 -0
- package/lib/public/modules/home-debate-planning.js +7 -7
- package/lib/public/modules/home-mate-avatar-editor.js +127 -208
- package/lib/public/modules/home-mate-chat.js +8 -6
- package/lib/public/modules/home-mate-creation.js +73 -1
- package/lib/public/modules/home-mate-settings.js +19 -12
- package/lib/public/modules/icon-strip-tooltip.js +2 -1
- package/lib/public/modules/input.js +88 -10
- package/lib/public/modules/issues-render.js +3 -2
- package/lib/public/modules/knowledge-db-workbench.js +4 -4
- package/lib/public/modules/markdown.js +6 -34
- package/lib/public/modules/mate-avatar-catalog.js +97 -0
- package/lib/public/modules/mate-knowledge-workbench.js +1 -1
- package/lib/public/modules/mate-loading-scene.js +17 -0
- package/lib/public/modules/mate-management.js +40 -7
- package/lib/public/modules/mcp-connection-view.js +31 -13
- package/lib/public/modules/mcp-discovery-view.js +31 -0
- package/lib/public/modules/mcp-ui.js +23 -4
- package/lib/public/modules/mention.js +3 -0
- package/lib/public/modules/message-delivery.js +20 -2
- package/lib/public/modules/model-picker.js +2 -0
- package/lib/public/modules/pane-activation.js +214 -0
- package/lib/public/modules/pane-binding.js +82 -0
- package/lib/public/modules/pane-bridge.js +7 -4
- package/lib/public/modules/pane-browser-bridge.js +22 -0
- package/lib/public/modules/pane-file-bridge.js +4 -0
- package/lib/public/modules/pane-issue-bridge.js +4 -1
- package/lib/public/modules/pending-message-queue.js +1 -0
- package/lib/public/modules/permission-control.js +5 -4
- package/lib/public/modules/personal-settings-dialog.js +7 -1
- package/lib/public/modules/product-review.js +26 -0
- package/lib/public/modules/profile.js +12 -241
- package/lib/public/modules/project-access-recovery.js +17 -0
- package/lib/public/modules/project-admin-overview.js +21 -0
- package/lib/public/modules/project-chat-identity.js +13 -4
- package/lib/public/modules/project-logs-render.js +3 -0
- package/lib/public/modules/project-mate-creation-workspace.js +13 -4
- package/lib/public/modules/project-mate-navigation.js +144 -22
- package/lib/public/modules/project-session-visibility-settings.js +19 -16
- package/lib/public/modules/project-settings.js +119 -129
- package/lib/public/modules/project-start-dialog.js +130 -0
- package/lib/public/modules/project-start-folder-state.js +78 -0
- package/lib/public/modules/project-start-folder-view.js +190 -0
- package/lib/public/modules/project-start-forms.js +66 -0
- package/lib/public/modules/project-start-path.js +60 -0
- package/lib/public/modules/project-start-state.js +54 -0
- package/lib/public/modules/project-start-submit.js +67 -0
- package/lib/public/modules/projects-hub-view.js +33 -14
- package/lib/public/modules/projects-hub.js +10 -6
- package/lib/public/modules/rewind.js +5 -0
- package/lib/public/modules/scheduled-tasks.js +2 -0
- package/lib/public/modules/scheduler.js +2 -0
- package/lib/public/modules/search-clay-chat.js +5 -440
- package/lib/public/modules/server-settings.js +36 -91
- package/lib/public/modules/session-actions.js +5 -2
- package/lib/public/modules/session-context-menu.js +5 -0
- package/lib/public/modules/session-create-form.js +10 -10
- package/lib/public/modules/session-folder-layout.js +1 -1
- package/lib/public/modules/session-folder-view-menu.js +9 -0
- package/lib/public/modules/session-github.js +85 -14
- package/lib/public/modules/session-rich-drafts.js +21 -0
- package/lib/public/modules/session-switch-defer.js +67 -0
- package/lib/public/modules/session-work-primary.js +51 -0
- package/lib/public/modules/settings-defaults.js +27 -28
- package/lib/public/modules/settings-project-target.js +56 -0
- package/lib/public/modules/settings-select.js +1 -1
- package/lib/public/modules/settings-shell-registry.js +88 -0
- package/lib/public/modules/settings-shell-view.js +104 -0
- package/lib/public/modules/settings-shell.js +342 -0
- package/lib/public/modules/shared-browser-settings.js +112 -0
- package/lib/public/modules/shared-browser-tabs.js +13 -3
- package/lib/public/modules/shared-browser.js +29 -6
- package/lib/public/modules/sidebar-mobile.js +12 -33
- package/lib/public/modules/sidebar-projects.js +3 -1
- package/lib/public/modules/sidebar-session-folders-ui.js +1 -1
- package/lib/public/modules/sidebar-sessions.js +1 -0
- package/lib/public/modules/split-group-restore.js +68 -0
- package/lib/public/modules/split-pair-ui.js +1 -0
- package/lib/public/modules/split-pane-reconciler.js +15 -0
- package/lib/public/modules/split-pane-renderer.js +87 -6
- package/lib/public/modules/split-session-boundary.js +1 -1
- package/lib/public/modules/split-view.js +60 -68
- package/lib/public/modules/sticky-note-markdown.js +72 -6
- package/lib/public/modules/sticky-notes-actions.js +30 -0
- package/lib/public/modules/sticky-notes-browser.js +9 -2
- package/lib/public/modules/sticky-notes-card.js +23 -7
- package/lib/public/modules/sticky-notes-checklist.js +116 -0
- package/lib/public/modules/sticky-notes-editor.js +108 -44
- package/lib/public/modules/sticky-notes-shared.js +50 -2
- package/lib/public/modules/sticky-notes-state.js +66 -0
- package/lib/public/modules/sticky-notes.js +34 -51
- package/lib/public/modules/stt-controller.js +4 -1
- package/lib/public/modules/stt-recording.js +1 -1
- package/lib/public/modules/stt.js +7 -2
- package/lib/public/modules/terminal.js +9 -0
- package/lib/public/modules/theme.js +18 -3
- package/lib/public/modules/thinking-lifecycle.js +33 -3
- package/lib/public/modules/thinking-view.js +23 -1
- package/lib/public/modules/tools.js +60 -11
- package/lib/public/modules/tui-grab.js +1 -2
- package/lib/public/modules/user-settings-appearance.js +10 -3
- package/lib/public/modules/user-settings-editors.js +1 -1
- package/lib/public/modules/user-settings-layout.js +14 -30
- package/lib/public/modules/user-settings-preferences.js +6 -2
- package/lib/public/modules/user-settings-profile.js +13 -3
- package/lib/public/modules/user-settings.js +18 -84
- package/lib/public/modules/vendor-login-browser.js +5 -3
- package/lib/public/modules/vendor-login.js +2 -2
- package/lib/public/modules/vendor-priority.js +15 -1
- package/lib/public/modules/vendor-usage-format.js +93 -0
- package/lib/public/modules/vendor-usage-list.js +45 -0
- package/lib/public/modules/vendor-usage-model.js +215 -0
- package/lib/public/modules/vendor-usage-overview.js +312 -0
- package/lib/public/modules/wireframe-workbench.js +5 -2
- package/lib/public/muse-avatar.svg +4 -0
- package/lib/public/style.css +14 -6
- package/lib/public/sw.js +3 -1
- package/lib/public/welcome-art/conversation-desk.png +0 -0
- package/lib/public/welcome-art/mate-clay.png +0 -0
- package/lib/public/welcome-art/project-clay.png +0 -0
- package/lib/safe-bash-commands.js +3 -45
- package/lib/scheduled-task-records.js +3 -1
- package/lib/scheduler.js +2 -0
- package/lib/sdk-bridge.js +348 -402
- package/lib/sdk-foreground-admission.js +16 -0
- package/lib/sdk-mcp-descriptors.js +2 -37
- package/lib/sdk-message-processor.js +61 -18
- package/lib/sdk-quota-snapshot.js +21 -3
- package/lib/sdk-response-recovery.js +1 -0
- package/lib/sdk-worker.js +2 -677
- package/lib/server-admin.js +63 -16
- package/lib/server-appearance-settings.js +13 -1
- package/lib/server-contextual-clay-settings.js +40 -0
- package/lib/server-contextual-mate-sessions.js +70 -0
- package/lib/server-dm.js +2 -1
- package/lib/server-github-stars.js +39 -0
- package/lib/server-global-ws.js +26 -32
- package/lib/server-home-chat-events.js +18 -4
- package/lib/server-home-chat.js +22 -20
- package/lib/server-home-clay-entry.js +23 -4
- package/lib/server-home-clay-session-links.js +29 -9
- package/lib/server-home-mate-creation.js +1 -0
- package/lib/server-home-mcp-consent.js +14 -0
- package/lib/server-mates.js +25 -62
- package/lib/server-owner-ui.js +118 -0
- package/lib/server-path-access.js +38 -0
- package/lib/server-project-removal.js +22 -0
- package/lib/server-settings.js +6 -1
- package/lib/server.js +167 -43
- package/lib/session-config-transition.js +45 -0
- package/lib/session-folders.js +7 -2
- package/lib/session-fork-history.js +21 -0
- package/lib/session-github.js +9 -2
- package/lib/session-hygiene.js +3 -35
- package/lib/session-notes-mcp-server.js +26 -4
- package/lib/session-notes-writes.js +88 -0
- package/lib/session-permission-mode.js +4 -3
- package/lib/session-skill-scope.js +11 -0
- package/lib/session-visibility.js +25 -10
- package/lib/session-work-primary.js +50 -0
- package/lib/sessions.js +66 -99
- package/lib/shared-browser-cookie-sync.js +32 -0
- package/lib/shared-browser-cookies.js +79 -0
- package/lib/shared-browser-runtime.js +25 -9
- package/lib/shared-browser-storage-sync.js +43 -0
- package/lib/shared-browser-storage.js +101 -0
- package/lib/shared-browser-tools.js +2 -1
- package/lib/shared-browser-worker.js +46 -10
- package/lib/terminal-manager.js +65 -6
- package/lib/tool-llm.js +1 -1
- package/lib/tui-transcript-index.js +1 -132
- package/lib/users-contextual-clay-preferences.js +31 -0
- package/lib/users-permissions.js +2 -8
- package/lib/users.js +7 -0
- package/lib/vendor-login-browser.js +1 -11
- package/lib/vendor-usage-acp-readers.js +97 -0
- package/lib/vendor-usage-capabilities.js +88 -0
- package/lib/vendor-usage-http-readers.js +214 -0
- package/lib/vendor-usage-metrics.js +47 -0
- package/lib/vendor-usage-native-readers.js +106 -0
- package/lib/vendor-usage-overview.js +406 -0
- package/lib/vendor-usage-service.js +281 -0
- package/lib/workspace-assignment-service.js +25 -0
- package/lib/workspace-query-access.js +4 -1
- package/lib/workspace-query-mcp-server.js +1 -1
- package/lib/workspace-query-service.js +13 -2
- package/lib/ws-request.js +1 -0
- package/lib/ws-schema.js +22 -4
- package/lib/yoke/acp-agent-profiles.js +7 -5
- package/lib/yoke/adapters/antigravity.js +3 -14
- package/lib/yoke/adapters/claude-query-contract.js +9 -0
- package/lib/yoke/adapters/claude.js +66 -50
- package/lib/yoke/adapters/codex-query-contract.js +25 -0
- package/lib/yoke/adapters/codex.js +98 -123
- package/lib/yoke/adapters/kiro.js +3 -1
- package/lib/yoke/adapters/muse-query-contract.js +7 -0
- package/lib/yoke/adapters/muse.js +122 -0
- package/lib/yoke/auth-events.js +17 -0
- package/lib/yoke/claude-hook-installer.js +272 -0
- package/lib/yoke/claude-jsonl-watcher.js +204 -0
- package/lib/yoke/claude-maintenance.js +55 -0
- package/lib/yoke/claude-permission-patterns.js +53 -0
- package/lib/yoke/claude-response-recovery.js +155 -0
- package/lib/yoke/claude-transcript-hygiene.js +34 -0
- package/lib/yoke/claude-worker-startup.js +28 -0
- package/lib/yoke/clay-skill-install.js +33 -0
- package/lib/yoke/cli-sessions.js +300 -0
- package/lib/yoke/codex-app-server.js +7 -12
- package/lib/yoke/codex-dynamic-tool-names.js +80 -0
- package/lib/yoke/codex-idle-recovery.js +81 -1
- package/lib/yoke/codex-model-catalog.js +37 -3
- package/lib/yoke/codex-recovery-admission.js +164 -0
- package/lib/yoke/configuration.js +13 -0
- package/lib/yoke/discovery.js +70 -0
- package/lib/yoke/errors.js +8 -0
- package/lib/yoke/host-environment.js +7 -0
- package/lib/yoke/index.js +9 -51
- package/lib/yoke/interface.js +116 -0
- package/lib/yoke/kiro-acp-server.js +5 -5
- package/lib/yoke/legacy-sessions.js +89 -0
- package/lib/yoke/login-protocol.js +25 -0
- package/lib/yoke/maintenance.js +12 -0
- package/lib/yoke/mcp-proxy.js +32 -0
- package/lib/yoke/mcp-source-adapters.js +91 -0
- package/lib/yoke/mcp-source-context.js +42 -0
- package/lib/yoke/mcp-source-discovery.js +169 -0
- package/lib/yoke/mcp-source-plugins.js +68 -0
- package/lib/yoke/mcp-source-restrictions.js +47 -0
- package/lib/yoke/mcp-tool-policy-normalize.js +28 -0
- package/lib/yoke/model-preferences.js +6 -0
- package/lib/yoke/muse-artifacts.js +36 -0
- package/lib/yoke/muse-controls.js +50 -0
- package/lib/yoke/muse-input.js +64 -0
- package/lib/yoke/muse-items.js +157 -0
- package/lib/yoke/muse-policy.js +52 -0
- package/lib/yoke/muse-query.js +428 -0
- package/lib/yoke/muse-runtime.js +211 -0
- package/lib/yoke/muse-services.js +92 -0
- package/lib/yoke/muse-skills.js +79 -0
- package/lib/yoke/muse-turns.js +71 -0
- package/lib/yoke/options/acp.js +2 -0
- package/lib/yoke/options/antigravity.js +2 -0
- package/lib/yoke/options/claude.js +21 -0
- package/lib/yoke/options/codex-defaults.js +29 -0
- package/lib/yoke/options/codex-settings.js +21 -0
- package/lib/yoke/options/codex.js +6 -0
- package/lib/yoke/options/kiro-defaults.js +22 -0
- package/lib/yoke/options/kiro.js +5 -0
- package/lib/yoke/options/muse.js +5 -0
- package/lib/yoke/provider-contract.js +5 -0
- package/lib/yoke/providers/antigravity-executable.js +8 -0
- package/lib/yoke/providers/claude-executable.js +40 -0
- package/lib/yoke/providers/claude-model-descriptions.js +34 -0
- package/lib/yoke/providers/claude-process.js +97 -0
- package/lib/yoke/providers/claude-provision.js +75 -0
- package/lib/yoke/providers/codex-errors.js +8 -0
- package/lib/yoke/providers/muse-executable.js +17 -0
- package/lib/yoke/provisioning.js +6 -0
- package/lib/yoke/query-options.js +10 -0
- package/lib/yoke/response-recovery.js +41 -0
- package/lib/yoke/sdk-mcp-descriptors.js +37 -0
- package/lib/yoke/sdk-server-factory.js +7 -0
- package/lib/yoke/session-history.js +8 -0
- package/lib/yoke/session-tool-transport.js +34 -13
- package/lib/yoke/settings.js +23 -0
- package/lib/yoke/source-locations.js +4 -0
- package/lib/yoke/title-query.js +18 -7
- package/lib/yoke/tui-transcript-index.js +132 -0
- package/lib/yoke/usage.js +48 -0
- package/lib/yoke/user-input.js +13 -0
- package/lib/yoke/vendor-registry.js +87 -3
- package/package.json +11 -4
- package/lib/public/modules/server-settings-navigation.js +0 -39
|
@@ -0,0 +1,169 @@
|
|
|
1
|
+
var fs = require('fs');
|
|
2
|
+
var path = require('path');
|
|
3
|
+
var os = require('os');
|
|
4
|
+
var crypto = require('crypto');
|
|
5
|
+
var adapters = require('./mcp-source-adapters');
|
|
6
|
+
var sourceContext = require('./mcp-source-context');
|
|
7
|
+
var restrictions = require('./mcp-source-restrictions');
|
|
8
|
+
var fsAsUser = require('../os-users').fsAsUser;
|
|
9
|
+
function createDiscovery(ctx) {
|
|
10
|
+
var scans = new Map(), publicScans = new Map();
|
|
11
|
+
function read(file, identity) {
|
|
12
|
+
if (identity) {
|
|
13
|
+
var stat = fsAsUser('stat', { file: file }, identity);
|
|
14
|
+
if (stat.size > 2 * 1024 * 1024 || stat.isDir) throw new Error('Source exceeds size limit.');
|
|
15
|
+
return fsAsUser('read', { file: file, readContent: true }, identity).content;
|
|
16
|
+
}
|
|
17
|
+
var info = fs.statSync(file);
|
|
18
|
+
if (!info.isFile() || info.size > 2 * 1024 * 1024) throw new Error('Source exceeds size limit.');
|
|
19
|
+
return fs.readFileSync(file, 'utf8');
|
|
20
|
+
}
|
|
21
|
+
function list(directory, identity) {
|
|
22
|
+
try { return identity ? fsAsUser('list', { dir: directory }, identity) : fs.readdirSync(directory, { withFileTypes: true }).map(function (entry) { return { name: entry.name, isDir: entry.isDirectory() }; }); }
|
|
23
|
+
catch (error) { return []; }
|
|
24
|
+
}
|
|
25
|
+
function scan(owner, ws, explicit) {
|
|
26
|
+
ctx.authorize(owner, ws);
|
|
27
|
+
var identity = ctx.identity(ws), home = identity ? identity.home : ctx.home || os.homedir();
|
|
28
|
+
var context = sourceContext.resolve(ctx, owner, ws, home, identity);
|
|
29
|
+
var rows = [], diagnostics = [], sources = context.sources, files = new Map(), directories = new Map();
|
|
30
|
+
function listing(directory) { var entries = list(directory, identity); directories.set(directory, JSON.stringify(entries.slice().sort(function (left, right) { return left.name.localeCompare(right.name); }))); return entries; }
|
|
31
|
+
function source(vendor, file, scope, pluginRoot, extra) { sources.push(Object.assign({ vendor: vendor, file: file, scope: scope, cwd: ctx.cwd, pluginRoot: pluginRoot }, extra)); }
|
|
32
|
+
Object.keys(adapters.adapters).forEach(function (vendor) {
|
|
33
|
+
var adapter = adapters.adapters[vendor];
|
|
34
|
+
if (adapter.agents) [home, ctx.cwd].forEach(function (base) {
|
|
35
|
+
var directory = path.join(base, adapter.agents);
|
|
36
|
+
listing(directory).slice(0, 100).forEach(function (entry) { if (!entry.isDir && /\.(json|md)$/.test(entry.name)) source(vendor, path.join(directory, entry.name), 'agent'); });
|
|
37
|
+
});
|
|
38
|
+
if (adapter.plugins) {
|
|
39
|
+
var directory = path.join(home, adapter.plugins);
|
|
40
|
+
listing(directory).slice(0, 100).forEach(function (entry) { if (entry.isDir) source(vendor, path.join(directory, entry.name, 'mcp_config.json'), 'plugin', path.join(directory, entry.name), { blocked: 'This plugin has no locally resolved activation registry. Review its active configuration before importing.' }); });
|
|
41
|
+
}
|
|
42
|
+
});
|
|
43
|
+
// Copilot reads nearer project definitions before ancestors up to the Git root.
|
|
44
|
+
var parents = [], repository = false;
|
|
45
|
+
var currentDirectory = ctx.cwd;
|
|
46
|
+
while (true) {
|
|
47
|
+
try { if (identity) fsAsUser('stat', { file: path.join(currentDirectory, '.git') }, identity); else fs.statSync(path.join(currentDirectory, '.git')); repository = true; break; } catch (error) {}
|
|
48
|
+
var parent = path.dirname(currentDirectory);
|
|
49
|
+
if (parent === currentDirectory) break;
|
|
50
|
+
parents.push(parent); currentDirectory = parent;
|
|
51
|
+
}
|
|
52
|
+
if (repository) parents.forEach(function (directory) {
|
|
53
|
+
source('copilot', path.join(directory, '.mcp.json'), 'project-ancestor');
|
|
54
|
+
source('copilot', path.join(directory, '.github/mcp.json'), 'project-ancestor');
|
|
55
|
+
});
|
|
56
|
+
diagnostics.push({ vendor: 'all', scope: 'plugins', message: 'Remote bundles are not downloaded. Unresolved installed plugin activation and local managed policies block import; credentials and vendor OAuth stores are never inspected.' });
|
|
57
|
+
if (explicit) {
|
|
58
|
+
if (!adapters.adapters[explicit.vendor] || typeof explicit.file !== 'string' || !path.isAbsolute(explicit.file)) throw new Error('Choose a supported format and an absolute source file path.');
|
|
59
|
+
source(explicit.vendor, explicit.file, 'configured');
|
|
60
|
+
}
|
|
61
|
+
function load(file) {
|
|
62
|
+
if (files.has(file)) { var cached = files.get(file); if (cached.error) throw cached.error; return cached.value; }
|
|
63
|
+
try {
|
|
64
|
+
var content = read(file, identity), value = adapters.parse(file, content);
|
|
65
|
+
files.set(file, { value: value, digest: crypto.createHash('sha256').update(content).digest('hex') }); return value;
|
|
66
|
+
} catch (error) { files.set(file, { error: error, digest: null }); throw error; }
|
|
67
|
+
}
|
|
68
|
+
require('./mcp-source-plugins').discover({ load: load, source: source, list: listing, roots: context.roots, cwd: ctx.cwd, diagnostics: diagnostics });
|
|
69
|
+
var blockedVendors = restrictions.inspect({ load: load, roots: context.roots, policyPaths: context.policyPaths, cwd: ctx.cwd, home: home, username: identity ? identity.username : process.env.USER });
|
|
70
|
+
var openCodeTools = {}, openCodeDefinitions = {};
|
|
71
|
+
function collect(source, definitions, root) {
|
|
72
|
+
if (!definitions || typeof definitions !== 'object') return;
|
|
73
|
+
var names = Array.isArray(definitions) ? definitions.map(function (definition) { return definition.name; }) : Object.keys(definitions);
|
|
74
|
+
names.slice(0, 100).forEach(function (name, index) {
|
|
75
|
+
if (typeof name !== 'string' || !name || name.length > 100) return;
|
|
76
|
+
try {
|
|
77
|
+
var definition = Array.isArray(definitions) ? definitions[index] : definitions[name];
|
|
78
|
+
if (source.vendor === 'opencode') {
|
|
79
|
+
definition = Object.assign({}, openCodeDefinitions[name] || {}, definition);
|
|
80
|
+
openCodeDefinitions[name] = definition;
|
|
81
|
+
}
|
|
82
|
+
if (source.overrides && source.overrides[name]) definition = Object.assign({}, definition, source.overrides[name]);
|
|
83
|
+
var provenance = Object.assign({}, source); delete provenance.inline; delete provenance.overrides;
|
|
84
|
+
var config = adapters.normalize(source.vendor, name, definition, provenance);
|
|
85
|
+
var blocked = source.blocked || blockedVendors[source.vendor];
|
|
86
|
+
if (root && Object.keys(root).some(function (key) { return restrictions.securityKey(key); })) blocked = 'This source contains runtime or agent restrictions Clay cannot resolve. Review its effective policy before importing.';
|
|
87
|
+
if (root && root.tools !== undefined && source.vendor !== 'opencode') blocked = 'This source contains runtime tool restrictions Clay cannot resolve. Review its effective policy before importing.';
|
|
88
|
+
var known = ['type', 'transport', 'command', 'args', 'env', 'environment', 'cwd', 'url', 'httpUrl', 'serverUrl', 'headers', 'http_headers', 'env_http_headers', 'bearer_token_env_var', 'bearerTokenEnvVar', 'includeTools', 'excludeTools', 'env_vars', 'enabled', 'disabled', 'autoApprove', 'disabledTools', 'disabled_tools', 'enabledTools', 'enabled_tools', 'timeout', 'startup_timeout_sec', 'tool_timeout_sec', 'oauth', 'oauthScopes', 'trust', 'name', 'description', 'tools', 'startupTimeoutMs'];
|
|
89
|
+
var unknown = Object.keys(definition).filter(function (key) { return known.indexOf(key) < 0; });
|
|
90
|
+
if (unknown.length) blocked = 'Unrecognized server fields require deliberate review in a direct Clay connection: ' + unknown.slice(0, 10).join(', ');
|
|
91
|
+
if (unknown.length) diagnostics.push({ vendor: source.vendor, scope: source.scope, name: name, message: 'Unrecognized fields are not imported: ' + unknown.slice(0, 10).join(', ') });
|
|
92
|
+
var hash = adapters.signature(config);
|
|
93
|
+
rows.push({ id: crypto.randomUUID(), name: name, config: config, signature: hash, blocked: blocked });
|
|
94
|
+
} catch (error) { diagnostics.push({ vendor: source.vendor, scope: source.scope, name: name, message: error.message }); }
|
|
95
|
+
});
|
|
96
|
+
}
|
|
97
|
+
if (sources.length > 500) diagnostics.push({ vendor: 'all', scope: 'discovery', message: 'Source limit reached; inspect additional files individually.' });
|
|
98
|
+
sources.sort(function (left, right) { return sourceContext.priority(left) - sourceContext.priority(right); });
|
|
99
|
+
sources.slice(0, 500).forEach(function (source) {
|
|
100
|
+
try {
|
|
101
|
+
var value = source.inline ? adapters.parse('inline.json', source.inline) : load(source.file), adapter = adapters.adapters[source.vendor];
|
|
102
|
+
if (Object.keys(value).some(function (key) { return restrictions.securityKey(key); })) blockedVendors[source.vendor] = 'A configuration layer contains unresolved security restrictions. Review the effective vendor policy before importing.';
|
|
103
|
+
if (source.vendor === 'opencode' && value.agent && Object.keys(value.agent).some(function (name) { return Object.keys(value.agent[name] || {}).some(function (key) { return restrictions.securityKey(key) || key === 'tools'; }); })) blockedVendors.opencode = 'OpenCode agent-specific restrictions require review. Configure a direct Clay connection with the intended restrictions.';
|
|
104
|
+
collect(source, source.scope === 'plugin-inline' ? value.mcpServers : value[adapter.key] || (source.vendor === 'codex' && !source.file.endsWith('.toml') ? value.mcpServers || value : source.vendor === 'copilot' || source.scope === 'plugin' ? value : null), value);
|
|
105
|
+
if (source.vendor === 'opencode' && value.tools !== undefined) {
|
|
106
|
+
if (!value.tools || typeof value.tools !== 'object' || Array.isArray(value.tools) || Object.values(value.tools).some(function (enabled) { return typeof enabled !== 'boolean'; })) blockedVendors.opencode = 'Invalid OpenCode tool policy. Review the runtime configuration before importing.';
|
|
107
|
+
else Object.assign(openCodeTools, value.tools);
|
|
108
|
+
}
|
|
109
|
+
if (source.vendor === 'claude' && source.scope === 'user' && value.projects && value.projects[ctx.cwd]) collect(Object.assign({}, source, { scope: 'local' }), value.projects[ctx.cwd].mcpServers, value.projects[ctx.cwd]);
|
|
110
|
+
} catch (error) {
|
|
111
|
+
if (error.code !== 'ENOENT' && !(identity && /ENOENT|no such file/i.test(error.message))) diagnostics.push({ vendor: source.vendor, scope: source.scope, message: 'Could not read or parse source; check permissions and format.' });
|
|
112
|
+
}
|
|
113
|
+
});
|
|
114
|
+
rows.forEach(function (row) {
|
|
115
|
+
var source = row.config.provenance;
|
|
116
|
+
row.blocked = row.blocked || blockedVendors[source.vendor];
|
|
117
|
+
if (source.vendor === 'opencode') {
|
|
118
|
+
row.config.toolPrefix = row.name + '_';
|
|
119
|
+
row.config.toolPatterns = Object.keys(openCodeTools).filter(function (pattern) { return openCodeTools[pattern] === false; });
|
|
120
|
+
row.signature = adapters.signature(row.config);
|
|
121
|
+
}
|
|
122
|
+
var effective = rows.filter(function (other) { return other.name === row.name && other.config.provenance.vendor === source.vendor && other.config.provenance.scope !== 'agent' && other.config.provenance.scope.indexOf('plugin') !== 0; }).pop();
|
|
123
|
+
if (source.scope !== 'agent' && source.scope.indexOf('plugin') !== 0 && effective && effective !== row) row.blocked = 'Shadowed by the effective ' + effective.config.provenance.scope + ' source. Import that definition instead.';
|
|
124
|
+
});
|
|
125
|
+
var current = ctx.snapshot(owner);
|
|
126
|
+
rows.forEach(function (row) {
|
|
127
|
+
var same = rows.filter(function (other) { return other !== row && (other.name === row.name || row.config.url && other.config.url === row.config.url); });
|
|
128
|
+
row.duplicate = rows.some(function (other) { return other !== row && other.signature === row.signature; });
|
|
129
|
+
row.conflict = same.some(function (other) { return other.signature !== row.signature; });
|
|
130
|
+
row.imported = current.records.some(function (saved) { return saved.importSignature === row.signature || row.config.url && saved.url === row.config.url; });
|
|
131
|
+
});
|
|
132
|
+
var scanId = crypto.randomUUID();
|
|
133
|
+
scans.set(owner, { id: scanId, ws: ws, rows: rows, files: files, directories: directories, identity: identity, revision: current.revision, context: context.fingerprint, home: home, created: Date.now() });
|
|
134
|
+
var publicScan = { scanId: scanId, candidates: rows.map(function (row) {
|
|
135
|
+
return { id: row.id, name: row.name, vendor: row.config.provenance.vendor, scope: row.config.provenance.scope, file: row.config.provenance.file,
|
|
136
|
+
blocked: row.blocked || null, pluginName: row.config.provenance.pluginName, pluginVersion: row.config.provenance.pluginVersion, transport: row.config.transport, dependency: row.config.command ? (/^[a-zA-Z0-9_./\\-]+$/.test(row.config.command) ? path.basename(row.config.command) : 'Configured executable') : new URL(row.config.url).hostname,
|
|
137
|
+
references: require('../mcp-import-credentials').requiredNames(row.config), environmentNames: row.config.environmentNames, sourceEnabled: row.config.sourceEnabled,
|
|
138
|
+
duplicate: row.duplicate, conflict: row.conflict, imported: row.imported };
|
|
139
|
+
}), diagnostics: diagnostics };
|
|
140
|
+
publicScans.set(owner, publicScan); return publicScan;
|
|
141
|
+
}
|
|
142
|
+
function selected(owner, ws, msg) {
|
|
143
|
+
ctx.authorize(owner, ws);
|
|
144
|
+
var scan = scans.get(owner);
|
|
145
|
+
if (!scan || scan.ws !== ws || scan.id !== msg.scanId || Date.now() - scan.created > 10 * 60 * 1000) throw new Error('Discovery expired. Scan again.');
|
|
146
|
+
if (JSON.stringify(ctx.identity(ws)) !== JSON.stringify(scan.identity)) throw new Error('OS identity changed. Scan again.');
|
|
147
|
+
if (sourceContext.resolve(ctx, owner, ws, scan.home, scan.identity).fingerprint !== scan.context) throw new Error('Runtime configuration changed. Scan again.');
|
|
148
|
+
scan.directories.forEach(function (state, directory) {
|
|
149
|
+
var entries = list(directory, scan.identity).slice().sort(function (left, right) { return left.name.localeCompare(right.name); });
|
|
150
|
+
if (JSON.stringify(entries) !== state) throw new Error('Installed source selection changed. Scan again.');
|
|
151
|
+
});
|
|
152
|
+
scan.files.forEach(function (state, file) {
|
|
153
|
+
var hash = null;
|
|
154
|
+
try { hash = crypto.createHash('sha256').update(read(file, scan.identity)).digest('hex'); } catch (error) {
|
|
155
|
+
if (!state.error || (error.code || error.message) !== (state.error.code || state.error.message)) throw new Error('Vendor configuration changed. Scan again.');
|
|
156
|
+
}
|
|
157
|
+
if (hash !== state.digest) throw new Error('Vendor configuration changed. Scan again.');
|
|
158
|
+
});
|
|
159
|
+
var row = scan.rows.find(function (candidate) { return candidate.id === msg.candidateId; });
|
|
160
|
+
if (row && row.blocked) throw new Error(row.blocked);
|
|
161
|
+
if (!row || row.imported) throw new Error('Source is unavailable or already imported.');
|
|
162
|
+
return { config: JSON.parse(JSON.stringify(row.config)), signature: row.signature, revision: scan.revision };
|
|
163
|
+
}
|
|
164
|
+
return { scan: scan, selected: selected, candidate: function (owner, subject, args) {
|
|
165
|
+
selected(owner, subject, args);
|
|
166
|
+
return publicScans.get(owner).candidates.find(function (row) { return row.id === args.candidateId; });
|
|
167
|
+
}, destroy: function () { scans.clear(); publicScans.clear(); } };
|
|
168
|
+
}
|
|
169
|
+
module.exports = { createDiscovery: createDiscovery };
|
|
@@ -0,0 +1,68 @@
|
|
|
1
|
+
var path = require('path');
|
|
2
|
+
function discover(ctx) {
|
|
3
|
+
var load = ctx.load, source = ctx.source, list = ctx.list, roots = ctx.roots;
|
|
4
|
+
function optional(file) { try { return load(file); } catch (error) { return {}; } }
|
|
5
|
+
var enabled = {};
|
|
6
|
+
var settingsFiles = [path.join(roots.claude, 'settings.json'), path.join(ctx.cwd, '.claude/settings.json'), path.join(ctx.cwd, '.claude/settings.local.json')];
|
|
7
|
+
settingsFiles.forEach(function (file) { Object.assign(enabled, optional(file).enabledPlugins || {}); });
|
|
8
|
+
var installed = optional(path.join(roots.claude, 'plugins/installed_plugins.json'));
|
|
9
|
+
Object.keys(installed.plugins || {}).slice(0, 100).forEach(function (name) {
|
|
10
|
+
var entries = (installed.plugins[name] || []).filter(function (entry) { return entry.installPath && (!entry.projectPath || path.resolve(entry.projectPath) === path.resolve(ctx.cwd)); });
|
|
11
|
+
var scoped = entries.filter(function (entry) { return entry.scope === 'local' || entry.scope === 'project'; });
|
|
12
|
+
if (scoped.length) entries = scoped;
|
|
13
|
+
var local = entries.filter(function (entry) { return entry.scope === 'local'; }); if (local.length) entries = local;
|
|
14
|
+
// The registry is authoritative only when it selects one installation.
|
|
15
|
+
entries.forEach(function (entry) {
|
|
16
|
+
var extra = { pluginName: name, pluginVersion: entry.version || null, sourceEnabled: enabled[name] === true ? true : enabled[name] === false ? false : null,
|
|
17
|
+
blocked: entries.length > 1 ? 'Claude registry selects multiple installations. Resolve the active plugin installation before importing.' : typeof enabled[name] !== 'boolean' ? 'Claude plugin enablement is unknown. Enable or disable it explicitly in vendor settings and scan again.' : null };
|
|
18
|
+
var root = entry.installPath;
|
|
19
|
+
source('claude', path.join(root, '.mcp.json'), 'plugin', root, extra);
|
|
20
|
+
var manifest = optional(path.join(root, '.claude-plugin/plugin.json'));
|
|
21
|
+
var definitions = Array.isArray(manifest.mcpServers) ? manifest.mcpServers : [manifest.mcpServers];
|
|
22
|
+
definitions.forEach(function (definition) {
|
|
23
|
+
if (typeof definition === 'string' && definition.endsWith('.json') && !definition.includes('://')) source('claude', path.resolve(root, definition), 'plugin', root, extra);
|
|
24
|
+
else if (definition && typeof definition === 'object') source('claude', path.join(root, '.claude-plugin/plugin.json'), 'plugin-inline', root, extra);
|
|
25
|
+
else if (definition) ctx.diagnostics.push({ vendor: 'claude', scope: 'plugin', message: 'Remote plugin bundles are not downloaded. Install and resolve the local plugin before scanning.' });
|
|
26
|
+
});
|
|
27
|
+
});
|
|
28
|
+
});
|
|
29
|
+
var codex = {};
|
|
30
|
+
[path.join(roots.codex, 'config.toml'), path.join(ctx.cwd, '.codex/config.toml')].forEach(function (file) {
|
|
31
|
+
var plugins = optional(file).plugins || {};
|
|
32
|
+
Object.keys(plugins).forEach(function (name) {
|
|
33
|
+
var previous = codex[name] || {}, next = plugins[name] || {};
|
|
34
|
+
codex[name] = Object.assign({}, previous, next, { mcp_servers: Object.assign({}, previous.mcp_servers || {}, next.mcp_servers || {}) });
|
|
35
|
+
});
|
|
36
|
+
});
|
|
37
|
+
var cache = path.join(roots.codex, 'plugins/cache');
|
|
38
|
+
list(cache).slice(0, 50).forEach(function (market) {
|
|
39
|
+
if (!market.isDir) return;
|
|
40
|
+
list(path.join(cache, market.name)).slice(0, 50).forEach(function (plugin) {
|
|
41
|
+
if (!plugin.isDir) return;
|
|
42
|
+
var name = plugin.name + '@' + market.name, configured = codex[name] || {};
|
|
43
|
+
var versions = list(path.join(cache, market.name, plugin.name)).filter(function (entry) { return entry.isDir; });
|
|
44
|
+
// Codex core-plugin-common/installed.rs selects local first, otherwise the greatest installed version.
|
|
45
|
+
versions = versions.filter(function (entry) { return /^[A-Za-z0-9._+-]+$/.test(entry.name); }).sort(function (left, right) {
|
|
46
|
+
var semver = require('semver');
|
|
47
|
+
return semver.valid(left.name) && semver.valid(right.name) ? semver.compareBuild(left.name, right.name) : left.name < right.name ? -1 : left.name > right.name ? 1 : 0;
|
|
48
|
+
});
|
|
49
|
+
var active = versions.find(function (entry) { return entry.name === 'local'; }) || versions[versions.length - 1];
|
|
50
|
+
versions = active ? [active] : [];
|
|
51
|
+
versions.slice(0, 50).forEach(function (version) {
|
|
52
|
+
var root = path.join(cache, market.name, plugin.name, version.name);
|
|
53
|
+
var extra = { pluginName: name, pluginVersion: version.name, overrides: configured.mcp_servers,
|
|
54
|
+
sourceEnabled: Object.prototype.hasOwnProperty.call(codex, name) ? configured.enabled !== false : false,
|
|
55
|
+
blocked: configured.enabled !== undefined && typeof configured.enabled !== 'boolean' ? 'Invalid Codex plugin enabled state. Review its vendor configuration before importing.' : null };
|
|
56
|
+
var portable = optional(path.join(root, 'plugin.json'));
|
|
57
|
+
var manifest = portable.extensions && portable.extensions['com.openai'] || optional(path.join(root, '.codex-plugin/plugin.json'));
|
|
58
|
+
if (portable.name) source('codex', path.join(root, 'mcp.json'), 'plugin', root, extra);
|
|
59
|
+
else {
|
|
60
|
+
source('codex', path.join(root, '.mcp.json'), 'plugin', root, extra);
|
|
61
|
+
source('codex', path.join(root, 'mcp.json'), 'plugin', root, extra);
|
|
62
|
+
}
|
|
63
|
+
if (typeof manifest.mcpServers === 'string' && !manifest.mcpServers.includes('://')) source('codex', path.resolve(root, manifest.mcpServers), 'plugin', root, extra);
|
|
64
|
+
});
|
|
65
|
+
});
|
|
66
|
+
});
|
|
67
|
+
}
|
|
68
|
+
module.exports = { discover: discover };
|
|
@@ -0,0 +1,47 @@
|
|
|
1
|
+
var path = require('path');
|
|
2
|
+
var SECURITY = /permission|policy|security|sandbox|registry|disabledMcp|restrict|approval|allowed|denied|managedMcp|strictPlugin|includeTools|excludeTools/i;
|
|
3
|
+
function inspect(ctx) {
|
|
4
|
+
var blocked = {}, files = [];
|
|
5
|
+
function add(vendor, file, exclusive) { files.push({ vendor: vendor, file: file, exclusive: exclusive }); }
|
|
6
|
+
var claudeManaged = process.platform === 'darwin' ? '/Library/Application Support/ClaudeCode' : process.platform === 'win32' ? path.join(process.env.ProgramFiles || 'C:\\Program Files', 'ClaudeCode') : '/etc/claude-code';
|
|
7
|
+
['managed-mcp.json', 'managed-settings.json'].forEach(function (file) { add('claude', path.join(claudeManaged, file), true); });
|
|
8
|
+
add('claude', path.join(claudeManaged, 'managed-settings.d'), true);
|
|
9
|
+
if (process.platform === 'darwin') {
|
|
10
|
+
add('claude', '/Library/Managed Preferences/com.anthropic.claudecode.plist', true);
|
|
11
|
+
if (ctx.username) add('claude', path.join('/Library/Managed Preferences', ctx.username, 'com.anthropic.claudecode.plist'), true);
|
|
12
|
+
}
|
|
13
|
+
[path.join(ctx.roots.claude, 'settings.json'), path.join(ctx.cwd, '.claude/settings.json'), path.join(ctx.cwd, '.claude/settings.local.json')].forEach(function (file) { add('claude', file); });
|
|
14
|
+
[path.join(ctx.roots.codex, 'requirements.toml'), '/etc/codex/requirements.toml', '/etc/codex/managed_config.toml', path.join(ctx.roots.codex, 'managed_config.toml')].forEach(function (file) { add('codex', file, true); });
|
|
15
|
+
var openCodeManaged = process.platform === 'darwin' ? '/Library/Application Support/opencode' : process.platform === 'win32' ? path.join(process.env.ProgramData || 'C:\\ProgramData', 'opencode') : '/etc/opencode';
|
|
16
|
+
['opencode.json', 'opencode.jsonc'].forEach(function (file) { add('opencode', path.join(openCodeManaged, file), true); });
|
|
17
|
+
if (process.platform === 'darwin') {
|
|
18
|
+
add('opencode', '/Library/Managed Preferences/ai.opencode.managed.plist', true);
|
|
19
|
+
if (ctx.username) add('opencode', path.join('/Library/Managed Preferences', ctx.username, 'ai.opencode.managed.plist'), true);
|
|
20
|
+
}
|
|
21
|
+
['settings.json', 'permissions-config.json'].forEach(function (file) { add('copilot', path.join(ctx.roots.copilot, file)); });
|
|
22
|
+
['settings.json', 'settings.local.json'].forEach(function (file) { add('copilot', path.join(ctx.cwd, '.github/copilot', file)); });
|
|
23
|
+
var copilotManaged = process.platform === 'darwin' ? '/Library/Application Support/GitHubCopilot/managed-settings.json' : process.platform === 'win32' ? path.join(process.env.ProgramFiles || 'C:\\Program Files', 'GitHubCopilot/managed-settings.json') : '/etc/github-copilot/managed-settings.json';
|
|
24
|
+
add('copilot', copilotManaged, true);
|
|
25
|
+
if (process.platform === 'darwin') {
|
|
26
|
+
add('copilot', '/Library/Managed Preferences/com.github.copilot.plist', true);
|
|
27
|
+
if (ctx.username) add('copilot', path.join('/Library/Managed Preferences', ctx.username, 'com.github.copilot.plist'), true);
|
|
28
|
+
}
|
|
29
|
+
add('kimi', path.join(ctx.roots.kimi, 'config.toml'));
|
|
30
|
+
var qwenSystem = process.platform === 'darwin' ? '/Library/Application Support/QwenCode' : process.platform === 'win32' ? 'C:\\ProgramData\\qwen-code' : '/etc/qwen-code';
|
|
31
|
+
add('qwen', ctx.policyPaths.qwenSettings || path.join(qwenSystem, 'settings.json'), true);
|
|
32
|
+
add('qwen', ctx.policyPaths.qwenDefaults || path.join(qwenSystem, 'system-defaults.json'), true);
|
|
33
|
+
add('grok', '/etc/grok/requirements.toml', true);
|
|
34
|
+
add('grok', '/etc/grok/managed_config.toml', true);
|
|
35
|
+
add('grok', path.join(ctx.roots.grok, 'requirements.toml'), true);
|
|
36
|
+
add('grok', path.join(ctx.roots.grok, 'managed_config.toml'), true);
|
|
37
|
+
files.forEach(function (entry) {
|
|
38
|
+
try {
|
|
39
|
+
var value = ctx.load(entry.file);
|
|
40
|
+
if (entry.exclusive || path.basename(entry.file) === 'permissions-config.json' && Object.keys(value).length || Object.keys(value).some(function (key) { return SECURITY.test(key); })) blocked[entry.vendor] = 'Local vendor security or managed policy is present. Clay cannot resolve its effective restrictions. Review that policy and configure an explicitly authorized Clay connection; vendor import is blocked.';
|
|
41
|
+
} catch (error) {
|
|
42
|
+
if (error.code !== 'ENOENT' && !/ENOENT|no such file/i.test(error.message)) blocked[entry.vendor] = 'Could not resolve a local vendor policy source. Check permissions and format before importing.';
|
|
43
|
+
}
|
|
44
|
+
});
|
|
45
|
+
return blocked;
|
|
46
|
+
}
|
|
47
|
+
module.exports = { inspect: inspect, securityKey: function (key) { return SECURITY.test(key); } };
|
|
@@ -0,0 +1,28 @@
|
|
|
1
|
+
// Restrictive policies are intersected; an empty allowlist means no tools.
|
|
2
|
+
var ALLOW = ['enabled_tools', 'enabledTools', 'includeTools'];
|
|
3
|
+
var DENY = ['disabled_tools', 'disabledTools', 'excludeTools'];
|
|
4
|
+
function list(value, key) {
|
|
5
|
+
if (!Array.isArray(value) || value.some(function (item) { return typeof item !== 'string' || !item || item.indexOf('\0') >= 0; })) throw new Error('Invalid tool policy: ' + key + '. Review the vendor configuration before importing.');
|
|
6
|
+
return Array.from(new Set(value));
|
|
7
|
+
}
|
|
8
|
+
function normalize(vendor, value) {
|
|
9
|
+
var allow = null, deny = [], keys = ALLOW.slice();
|
|
10
|
+
if (vendor === 'copilot') keys.push('tools');
|
|
11
|
+
keys.forEach(function (key) {
|
|
12
|
+
if (!Object.prototype.hasOwnProperty.call(value, key)) return;
|
|
13
|
+
var next = list(value[key], key);
|
|
14
|
+
if (vendor === 'copilot' && key === 'tools' && next.indexOf('*') >= 0) next = null;
|
|
15
|
+
if (next !== null) allow = allow === null ? next : allow.filter(function (name) { return next.indexOf(name) >= 0; });
|
|
16
|
+
});
|
|
17
|
+
DENY.forEach(function (key) { if (Object.prototype.hasOwnProperty.call(value, key)) deny = deny.concat(list(value[key], key)); });
|
|
18
|
+
var unsupported = Object.keys(value).filter(function (key) {
|
|
19
|
+
if (ALLOW.concat(DENY, vendor === 'copilot' ? ['tools'] : [], ['autoApprove', 'trust', 'oauth', 'oauthScopes']).indexOf(key) >= 0) return false;
|
|
20
|
+
return /tool|permission|policy|security|authProvider|allowed|denied|restrict|approval/i.test(key) && ['tool_timeout_sec'].indexOf(key) < 0;
|
|
21
|
+
});
|
|
22
|
+
if (unsupported.length) throw new Error('Unsupported restriction or security configuration: ' + unsupported.join(', ') + '. Configure and review a direct Clay connection instead.');
|
|
23
|
+
if (value.autoApprove !== undefined && (!Array.isArray(value.autoApprove) || value.autoApprove.some(function (item) { return typeof item !== 'string'; }))) throw new Error('Invalid autoApprove policy.');
|
|
24
|
+
if (value.trust !== undefined && typeof value.trust !== 'boolean') throw new Error('Invalid trust policy.');
|
|
25
|
+
return { enabledTools: allow, disabledTools: Array.from(new Set(deny)) };
|
|
26
|
+
}
|
|
27
|
+
|
|
28
|
+
module.exports = { normalize: normalize };
|
|
@@ -0,0 +1,6 @@
|
|
|
1
|
+
function families() {
|
|
2
|
+
var registry = require("./vendor-registry").VENDOR_REGISTRY, result = {};
|
|
3
|
+
Object.keys(registry).forEach(function(vendor) { if (registry[vendor].preferredModelFamilies) result[vendor] = registry[vendor].preferredModelFamilies.slice(); });
|
|
4
|
+
return result;
|
|
5
|
+
}
|
|
6
|
+
module.exports = { families: families };
|
|
@@ -0,0 +1,36 @@
|
|
|
1
|
+
// Read only explicit image output references; never open provider paths/URIs.
|
|
2
|
+
var MAX_BYTES = 6 * 1024 * 1024;
|
|
3
|
+
var MEDIA_TYPES = ["image/png", "image/jpeg", "image/webp", "image/gif"];
|
|
4
|
+
function create(getRuntime, push) {
|
|
5
|
+
var seen = new Set();
|
|
6
|
+
return async function(item) {
|
|
7
|
+
var ref = item && item.outputRef;
|
|
8
|
+
if (!item || item.status !== "completed" || !ref || MEDIA_TYPES.indexOf(ref.mediaType) < 0) return;
|
|
9
|
+
var key = JSON.stringify([item.itemId, ref.id]);
|
|
10
|
+
if (seen.has(key)) return;
|
|
11
|
+
seen.add(key);
|
|
12
|
+
var runtime = getRuntime();
|
|
13
|
+
runtime.check();
|
|
14
|
+
var event = { yokeType: "generated_image", toolId: item.itemId + ":image", blockId: item.itemId,
|
|
15
|
+
mediaType: ref.mediaType, prompt: "", savedPath: null, transparentBackground: null,
|
|
16
|
+
status: "completed", isError: false, data: "" };
|
|
17
|
+
try {
|
|
18
|
+
if (ref.availability !== "available" || typeof ref.id !== "string" || !ref.id || !Number.isSafeInteger(ref.byteLen) || ref.byteLen <= 0 || ref.byteLen > MAX_BYTES) throw new Error("Muse image artifact is unavailable or exceeds the 6 MiB output limit");
|
|
19
|
+
var result = await runtime.waitRequest(runtime.connection.request("item/readOutput", {
|
|
20
|
+
sessionId: runtime.session.sessionId, itemId: item.itemId, outputRef: ref.id, offsetBytes: 0, lengthBytes: MAX_BYTES,
|
|
21
|
+
}));
|
|
22
|
+
runtime.check();
|
|
23
|
+
if (result.encoding !== "base64" || result.mediaType !== ref.mediaType || result.offsetBytes !== 0 || result.eof !== true || result.byteLen !== ref.byteLen || typeof result.content !== "string" || result.content.length > Math.ceil(MAX_BYTES / 3) * 4 || !/^[A-Za-z0-9+/]+={0,2}$/.test(result.content)) throw new Error("Muse returned an incomplete or invalid image artifact");
|
|
24
|
+
var bytes = Buffer.from(result.content, "base64");
|
|
25
|
+
if (bytes.length !== ref.byteLen || bytes.toString("base64") !== result.content) throw new Error("Muse image artifact byte length does not match its reference");
|
|
26
|
+
event.data = result.content;
|
|
27
|
+
} catch (error) {
|
|
28
|
+
runtime.check();
|
|
29
|
+
event.isError = true;
|
|
30
|
+
event.status = "failed";
|
|
31
|
+
push({ yokeType: "informational", level: "warning", content: error.message || "Muse image artifact could not be read" });
|
|
32
|
+
}
|
|
33
|
+
push(event);
|
|
34
|
+
};
|
|
35
|
+
}
|
|
36
|
+
module.exports = { create: create };
|
|
@@ -0,0 +1,50 @@
|
|
|
1
|
+
function create(ctx) {
|
|
2
|
+
var state = ctx.state, assertLive = ctx.assertLive, selectModel = ctx.selectModel, validateEffort = ctx.validateEffort;
|
|
3
|
+
return {
|
|
4
|
+
setModel: async function(model) {
|
|
5
|
+
assertLive();
|
|
6
|
+
if (typeof model !== "string" || !model) throw new Error("Muse model selection requires a model id");
|
|
7
|
+
if (!state.session) {
|
|
8
|
+
state.model = model;
|
|
9
|
+
return;
|
|
10
|
+
}
|
|
11
|
+
var selection = await selectModel(model);
|
|
12
|
+
await ctx.runtime().waitRequest(state.connection.command("session/setModel", {
|
|
13
|
+
sessionId: state.sessionId,
|
|
14
|
+
model: selection
|
|
15
|
+
}));
|
|
16
|
+
state.model = model;
|
|
17
|
+
},
|
|
18
|
+
setEffort: async function(effort) {
|
|
19
|
+
assertLive();
|
|
20
|
+
if (state.session && !effort && state.effort) throw new Error("Muse cannot reset session effort without an explicit supported level");
|
|
21
|
+
if (effort) validateEffort(effort);
|
|
22
|
+
if (state.session && effort) await ctx.runtime().waitRequest(state.connection.command("session/setReasoningEffort", {
|
|
23
|
+
sessionId: state.sessionId,
|
|
24
|
+
reasoningEffort: effort
|
|
25
|
+
}));
|
|
26
|
+
assertLive();
|
|
27
|
+
state.effort = effort || null;
|
|
28
|
+
},
|
|
29
|
+
listTasks: async function() {
|
|
30
|
+
assertLive();
|
|
31
|
+
if (!state.session) throw new Error("Muse tasks require an opened session");
|
|
32
|
+
return ctx.runtime().waitRequest(state.connection.request("task/list", { sessionId: state.sessionId }));
|
|
33
|
+
},
|
|
34
|
+
compact: async function() {
|
|
35
|
+
assertLive();
|
|
36
|
+
if (!state.session) throw new Error("Muse compaction requires an opened session");
|
|
37
|
+
return ctx.runtime().waitRequest(state.connection.command("session/compact", { sessionId: state.sessionId }));
|
|
38
|
+
},
|
|
39
|
+
listSkills: function() { return ctx.skills.listNative(); },
|
|
40
|
+
invokeSkill: async function(selector, args) {
|
|
41
|
+
assertLive();
|
|
42
|
+
var catalog = await ctx.handle.listSkills();
|
|
43
|
+
assertLive();
|
|
44
|
+
if (!(catalog.skills || []).some(function(skill) { return skill.selector === selector; })) throw new Error("Muse skill is not in the live session catalog");
|
|
45
|
+
return ctx.handle.pushMessage("", [], { selector: selector, arguments: String(args || "") });
|
|
46
|
+
},
|
|
47
|
+
rollback: function() { return Promise.reject(new Error("Muse SDK 1.4.7 has no rollback method")); },
|
|
48
|
+
};
|
|
49
|
+
}
|
|
50
|
+
module.exports = { create: create };
|
|
@@ -0,0 +1,64 @@
|
|
|
1
|
+
var userInput = require("./user-input");
|
|
2
|
+
function createRouter(runtime, queryOpts, signal) {
|
|
3
|
+
var pending = new Map();
|
|
4
|
+
function route(request) {
|
|
5
|
+
if (pending.has(request.userInputId)) return pending.get(request.userInputId).operation;
|
|
6
|
+
if (pending.size >= 1000) return Promise.reject(new Error("Muse input request capacity exceeded"));
|
|
7
|
+
var controller = new AbortController();
|
|
8
|
+
var entry = { controller: controller, retired: false };
|
|
9
|
+
function abort() { controller.abort(); }
|
|
10
|
+
if (signal.aborted) abort(); else signal.addEventListener("abort", abort, { once: true });
|
|
11
|
+
var operation = Promise.resolve().then(async function() {
|
|
12
|
+
runtime.check();
|
|
13
|
+
var input = { id: request.userInputId, questions: (request.questions || []).map(function(question) {
|
|
14
|
+
return { id: question.id, header: question.header, question: question.question,
|
|
15
|
+
options: question.options, multiSelect: question.selection && question.selection.mode === "multiple", allowOther: true };
|
|
16
|
+
}) };
|
|
17
|
+
if (typeof queryOpts.validateUserInputRequest === "function") {
|
|
18
|
+
var reason = queryOpts.validateUserInputRequest(input);
|
|
19
|
+
if (reason) throw new Error(reason);
|
|
20
|
+
}
|
|
21
|
+
var result = await runtime.wait(userInput.dispatchUserInput(queryOpts.onUserInputRequest, input,
|
|
22
|
+
{ source: "muse", native: true, provider: "muse", signal: controller.signal }));
|
|
23
|
+
runtime.check();
|
|
24
|
+
if (entry.retired) return;
|
|
25
|
+
if (result.status !== "submitted") return runtime.waitRequest(runtime.connection.command("userInput/cancel", {
|
|
26
|
+
sessionId: request.sessionId, userInputId: request.userInputId,
|
|
27
|
+
}));
|
|
28
|
+
var answers = request.questions.map(function(question) {
|
|
29
|
+
var values = result.answers[question.id] || [];
|
|
30
|
+
var selection = question.selection || {};
|
|
31
|
+
if (values.length < (selection.minSelections || 1) || selection.maxSelections != null && values.length > selection.maxSelections) throw new Error("Muse answer violates selection bounds");
|
|
32
|
+
var known = values.every(function(value) { return (question.options || []).some(function(option) { return option.label === value; }); });
|
|
33
|
+
var answer = { questionId: question.id };
|
|
34
|
+
if (!known || !question.options.length) {
|
|
35
|
+
var text = values.join(", ");
|
|
36
|
+
if (text.length > 500) throw new Error("Muse free-text answer exceeds 500 characters");
|
|
37
|
+
answer.freeText = text;
|
|
38
|
+
} else if (selection.mode === "multiple") answer.selectedLabels = values;
|
|
39
|
+
else answer.selectedLabel = values[0];
|
|
40
|
+
return answer;
|
|
41
|
+
});
|
|
42
|
+
return runtime.waitRequest(runtime.connection.command("userInput/answer", {
|
|
43
|
+
sessionId: request.sessionId, userInputId: request.userInputId, answers: answers,
|
|
44
|
+
}));
|
|
45
|
+
});
|
|
46
|
+
entry.operation = operation.finally(function() { signal.removeEventListener("abort", abort); });
|
|
47
|
+
pending.set(request.userInputId, entry);
|
|
48
|
+
return entry.operation;
|
|
49
|
+
}
|
|
50
|
+
route.settle = function(id) {
|
|
51
|
+
var entry = pending.get(id);
|
|
52
|
+
if (entry) { entry.retired = true; entry.controller.abort(); }
|
|
53
|
+
};
|
|
54
|
+
return route;
|
|
55
|
+
}
|
|
56
|
+
function inputParts(text, images) {
|
|
57
|
+
var parts = [{ type: "text", text: text }];
|
|
58
|
+
(images || []).forEach(function(image) {
|
|
59
|
+
if (!image || typeof image.data !== "string" || !image.data || !/^image\/[a-z0-9.+-]+$/i.test(image.mediaType || "") || !/^[A-Za-z0-9+/]+={0,2}$/.test(image.data)) throw new Error("Invalid Muse image attachment");
|
|
60
|
+
parts.push({ type: "image", mediaType: image.mediaType, base64Data: image.data });
|
|
61
|
+
});
|
|
62
|
+
return parts;
|
|
63
|
+
}
|
|
64
|
+
module.exports = { createRouter: createRouter, inputParts: inputParts };
|
|
@@ -0,0 +1,157 @@
|
|
|
1
|
+
function itemInput(item) {
|
|
2
|
+
if (!item || typeof item.args !== "string") return {};
|
|
3
|
+
try {
|
|
4
|
+
return JSON.parse(item.args);
|
|
5
|
+
} catch (e) {
|
|
6
|
+
return {
|
|
7
|
+
rawArgs: item.args
|
|
8
|
+
};
|
|
9
|
+
}
|
|
10
|
+
}
|
|
11
|
+
|
|
12
|
+
function toolName(item) {
|
|
13
|
+
var name = String(item && (item.tool || item.toolName) || "Tool").toLowerCase();
|
|
14
|
+
if (name.indexOf("shell") !== -1 || name.indexOf("command") !== -1) return "Bash";
|
|
15
|
+
if (name.indexOf("read") !== -1) return "Read";
|
|
16
|
+
if (name.indexOf("write") !== -1 || name.indexOf("create") !== -1) return "Write";
|
|
17
|
+
if (name.indexOf("edit") !== -1 || name.indexOf("delete") !== -1) return "Edit";
|
|
18
|
+
if (name.indexOf("search") !== -1 || name.indexOf("grep") !== -1) return "Grep";
|
|
19
|
+
return item && (item.tool || item.toolName) || "Tool";
|
|
20
|
+
}
|
|
21
|
+
|
|
22
|
+
function createRenderer(state, push) {
|
|
23
|
+
var streamedItems = {};
|
|
24
|
+
var openBlocks = {};
|
|
25
|
+
var notices = {};
|
|
26
|
+
function closeBlocks(turnId) {
|
|
27
|
+
Object.keys(openBlocks).forEach(function(id) {
|
|
28
|
+
if (turnId && openBlocks[id] !== turnId) return;
|
|
29
|
+
push({
|
|
30
|
+
yokeType: "block_stop",
|
|
31
|
+
blockId: id
|
|
32
|
+
});
|
|
33
|
+
delete openBlocks[id];
|
|
34
|
+
});
|
|
35
|
+
if (!turnId) { state.thinkingBlocks = {}; state.textBlocks = {}; state.toolBlocks = {}; }
|
|
36
|
+
}
|
|
37
|
+
function emitNotice(item, id) {
|
|
38
|
+
if (item.status === "inProgress" || item.kind === "userMessage") return;
|
|
39
|
+
var failed = ["failed", "rejected", "timedOut"].includes(item.status)
|
|
40
|
+
|| (item.kind === "compaction" && item.outcome === "failed")
|
|
41
|
+
|| (item.kind === "hookRun" && ["failed", "blocked", "timedOut"].includes(item.runStatus))
|
|
42
|
+
|| (item.kind === "subagent" && item.result && item.result.errorKind);
|
|
43
|
+
var text = "";
|
|
44
|
+
if (failed) {
|
|
45
|
+
var labels = { reminderChild: "A background task", hookRun: "A hook", compaction: "Context maintenance", sideChat: "A side conversation", subagent: "A task", workflow: "A workflow", userShell: "A command", webSearch: "A search" };
|
|
46
|
+
var label = labels[item.kind] || "A Muse operation";
|
|
47
|
+
// Unknown kinds have no established human-facing fields. Do not dump them.
|
|
48
|
+
var detail = labels[item.kind] ? (item.failureReason || item.reason || item.message || "") : "";
|
|
49
|
+
if (item.kind === "subagent" && !detail && item.result) detail = item.result.summary || "";
|
|
50
|
+
text = label + " failed" + (detail ? ": " + detail : ".");
|
|
51
|
+
} else if (item.status === "completed") {
|
|
52
|
+
// Only documented action results belong in chat. Reminder/hook/compaction/
|
|
53
|
+
// side-chat bookkeeping and unknown protocol fallback text stay silent.
|
|
54
|
+
if (item.kind === "subagent" && item.result) text = item.result.text || item.result.summary || "";
|
|
55
|
+
else if (item.kind === "workflow") text = item.finalSummary || item.message || "";
|
|
56
|
+
else if (item.kind === "userShell") text = item.visibleOutput || "";
|
|
57
|
+
else if (item.kind === "webSearch") text = item.fallbackText || "";
|
|
58
|
+
}
|
|
59
|
+
var key = id + (failed ? ":failure" : ":summary");
|
|
60
|
+
if (typeof text !== "string" || !text.trim() || notices[key]) return;
|
|
61
|
+
notices[key] = true;
|
|
62
|
+
push({ yokeType: "informational", level: failed ? "warning" : "info", content: text });
|
|
63
|
+
}
|
|
64
|
+
function emitItem(item) {
|
|
65
|
+
if (!item || state.stopped) return;
|
|
66
|
+
var id = item.itemId || "muse-item";
|
|
67
|
+
if (item.kind === "agentMessage" || item.kind === "reasoning") {
|
|
68
|
+
var previous = state.textBlocks[id] || "";
|
|
69
|
+
var value = item.kind === "reasoning" && Array.isArray(item.summary) ? item.summary.join("\n") : item.text || "";
|
|
70
|
+
var blockId = state.thinkingBlocks[id] || id;
|
|
71
|
+
if (item.kind === "reasoning") state.thinkingBlocks[id] = blockId;
|
|
72
|
+
if (!previous && value) {
|
|
73
|
+
openBlocks[blockId] = item.turnId;
|
|
74
|
+
push({
|
|
75
|
+
yokeType: item.kind === "reasoning" ? "thinking_start" : "text_start",
|
|
76
|
+
blockId: blockId
|
|
77
|
+
});
|
|
78
|
+
}
|
|
79
|
+
if (value.length > previous.length) push({
|
|
80
|
+
yokeType: item.kind === "reasoning" ? "thinking_delta" : "text_delta",
|
|
81
|
+
blockId: blockId,
|
|
82
|
+
text: value.substring(previous.length)
|
|
83
|
+
});
|
|
84
|
+
if (value.length >= previous.length) state.textBlocks[id] = value;
|
|
85
|
+
if (item.status !== "inProgress" && openBlocks[blockId]) {
|
|
86
|
+
push({
|
|
87
|
+
yokeType: "block_stop",
|
|
88
|
+
blockId: blockId
|
|
89
|
+
});
|
|
90
|
+
delete openBlocks[blockId];
|
|
91
|
+
}
|
|
92
|
+
return;
|
|
93
|
+
}
|
|
94
|
+
if (item.kind === "toolCall") {
|
|
95
|
+
if (!state.toolBlocks[id]) {
|
|
96
|
+
state.toolBlocks[id] = true;
|
|
97
|
+
push({
|
|
98
|
+
yokeType: "tool_start",
|
|
99
|
+
blockId: id,
|
|
100
|
+
toolId: id,
|
|
101
|
+
toolName: toolName(item)
|
|
102
|
+
});
|
|
103
|
+
push({
|
|
104
|
+
yokeType: "tool_executing",
|
|
105
|
+
blockId: id,
|
|
106
|
+
toolId: id,
|
|
107
|
+
toolName: toolName(item),
|
|
108
|
+
input: itemInput(item)
|
|
109
|
+
});
|
|
110
|
+
}
|
|
111
|
+
if (item.status && item.status !== "inProgress" && state.toolBlocks[id] !== "completed") {
|
|
112
|
+
state.toolBlocks[id] = "completed";
|
|
113
|
+
push({
|
|
114
|
+
yokeType: "tool_result",
|
|
115
|
+
blockId: id,
|
|
116
|
+
toolId: id,
|
|
117
|
+
content: item.visibleOutput || item.message || item.failureReason || "",
|
|
118
|
+
isError: item.status !== "completed"
|
|
119
|
+
});
|
|
120
|
+
}
|
|
121
|
+
return;
|
|
122
|
+
}
|
|
123
|
+
emitNotice(item, id);
|
|
124
|
+
}
|
|
125
|
+
function renderFrame(frame) {
|
|
126
|
+
var params = frame.params || {};
|
|
127
|
+
var item = params.item;
|
|
128
|
+
var owner = item && item.turnId || streamedItems[params.itemId] && streamedItems[params.itemId].turnId;
|
|
129
|
+
if (!(state.liveTurnIds && state.liveTurnIds.has(owner) || state.activeTurn && owner === state.activeTurn.turnId)) return false;
|
|
130
|
+
if (item) streamedItems[item.itemId] = Object.assign({}, item); else if (frame.method === "item/delta") {
|
|
131
|
+
item = streamedItems[params.itemId];
|
|
132
|
+
if (item) {
|
|
133
|
+
var field = params.field || "text";
|
|
134
|
+
if (field.indexOf("summary.") === 0) {
|
|
135
|
+
var index = Number(field.split(".")[1]);
|
|
136
|
+
item.summary = (item.summary || []).slice();
|
|
137
|
+
item.summary[index] = (item.summary[index] || "") + params.delta;
|
|
138
|
+
} else if (field === "text") item.text = (item.text || "") + params.delta; else if (field === "output") item.visibleOutput = (item.visibleOutput || "") + params.delta;
|
|
139
|
+
}
|
|
140
|
+
}
|
|
141
|
+
if (item) emitItem(item);
|
|
142
|
+
return true;
|
|
143
|
+
}
|
|
144
|
+
return {
|
|
145
|
+
emitItem: emitItem,
|
|
146
|
+
renderFrame: renderFrame,
|
|
147
|
+
closeBlocks: closeBlocks,
|
|
148
|
+
hasItem: function(id) {
|
|
149
|
+
return !!streamedItems[id];
|
|
150
|
+
}
|
|
151
|
+
};
|
|
152
|
+
}
|
|
153
|
+
|
|
154
|
+
module.exports = {
|
|
155
|
+
createRenderer: createRenderer,
|
|
156
|
+
itemInput: itemInput
|
|
157
|
+
};
|