clay-server 5.2.0-beta.1 → 5.2.0-beta.11
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.md +0 -4
- package/lib/account-auth-socket.js +1 -0
- package/lib/builtin-mates.js +19 -16
- package/lib/bundled-skills/clay-agent-browser/SKILL.md +6 -2
- package/lib/canonical-clay-record-authority.js +15 -0
- package/lib/canonical-clay-scheduling-authority.js +19 -0
- package/lib/claude-hook-installer.js +1 -239
- package/lib/claude-jsonl-watcher.js +1 -204
- package/lib/clay-control-presentation-binding.js +96 -0
- package/lib/clay-control-presentation.js +128 -0
- package/lib/clay-control-target-projection.js +26 -0
- package/lib/clay-mate-chat-receipts.js +26 -0
- package/lib/clay-mate-chat.js +88 -0
- package/lib/clay-mate-knowledge-input.js +26 -0
- package/lib/clay-mate-knowledge.js +95 -0
- package/lib/clay-mate-lifecycle.js +95 -0
- package/lib/clay-product-control-input.js +33 -0
- package/lib/clay-product-control-tools.js +52 -0
- package/lib/clay-product-control.js +250 -0
- package/lib/clay-project-lifecycle.js +154 -0
- package/lib/clay-project-record-input.js +44 -0
- package/lib/clay-project-records.js +84 -0
- package/lib/clay-scheduling-input.js +21 -0
- package/lib/clay-scheduling-receipts.js +26 -0
- package/lib/clay-scheduling.js +119 -0
- package/lib/clay-screen-controls.js +104 -0
- package/lib/clay-skill-install.js +1 -33
- package/lib/clay-vendor-usage.js +44 -0
- package/lib/clay-workspace-controls.js +84 -0
- package/lib/clay-workspace-input.js +17 -0
- package/lib/clay-workspace-receipts.js +26 -0
- package/lib/cli-sessions.js +1 -300
- package/lib/codex-defaults.js +1 -28
- package/lib/context-usage.js +3 -2
- package/lib/contextual-screen-snapshot.js +38 -0
- package/lib/daemon-project-access.js +11 -0
- package/lib/daemon-project-lifecycle-callbacks.js +15 -0
- package/lib/daemon-project-lifecycle.js +262 -0
- package/lib/daemon-projects.js +1 -1
- package/lib/daemon.js +78 -276
- package/lib/default-ai-runtime.js +4 -8
- package/lib/dm-digest-cursor.js +120 -0
- package/lib/email-mcp-server.js +1 -1
- package/lib/github-star-count.js +147 -0
- package/lib/issues-service.js +29 -15
- package/lib/kiro-defaults.js +1 -22
- package/lib/knowledge-db-import-validation.js +46 -0
- package/lib/knowledge-db-import.js +99 -0
- package/lib/knowledge-db-service.js +24 -33
- package/lib/knowledge-db-storage-nedb-maintenance.js +99 -0
- package/lib/knowledge-db-storage-nedb.js +66 -0
- package/lib/knowledge-db-storage.js +72 -0
- package/lib/knowledge-db-validation.js +0 -0
- package/lib/knowledge-document-index.js +2 -1
- package/lib/knowledge-file-store.js +7 -1
- package/lib/knowledge-product-operations.js +46 -0
- package/lib/mate-avatar-catalog.js +12 -0
- package/lib/mate-avatar-migration.js +41 -0
- package/lib/mate-context-service.js +138 -0
- package/lib/mate-context-tools.js +21 -0
- package/lib/mate-creation-mcp-server.js +2 -0
- package/lib/mate-knowledge-canonical-access.js +10 -0
- package/lib/mate-knowledge-mate-bound.js +53 -0
- package/lib/mate-knowledge-mcp-server.js +55 -8
- package/lib/mate-knowledge-service.js +16 -34
- package/lib/mate-knowledge-text-tools.js +106 -0
- package/lib/mate-lifecycle-service.js +94 -0
- package/lib/mate-message-delivery.js +43 -0
- package/lib/mate-ready-creation.js +9 -1
- package/lib/mate-schedule-input.js +29 -0
- package/lib/mate-schedule-lifecycle.js +151 -0
- package/lib/mate-scheduling.js +103 -0
- package/lib/mates.js +18 -6
- package/lib/mcp-agent-tools.js +117 -0
- package/lib/mcp-connection-store.js +119 -15
- package/lib/mcp-import-credentials.js +31 -0
- package/lib/mcp-local-transport.js +13 -0
- package/lib/mcp-oauth.js +8 -6
- package/lib/mcp-proxy.js +2 -32
- package/lib/mcp-query-bridge.js +30 -0
- package/lib/mcp-remote-connections.js +74 -20
- package/lib/mcp-source-adapters.js +1 -0
- package/lib/mcp-source-context.js +1 -0
- package/lib/mcp-source-discovery.js +1 -0
- package/lib/mcp-source-plugins.js +1 -0
- package/lib/mcp-source-restrictions.js +1 -0
- package/lib/mcp-tool-policy.js +9 -0
- package/lib/notes-checklist.js +92 -0
- package/lib/notes.js +51 -4
- package/lib/os-user-diagnostics.js +2 -4
- package/lib/os-users.js +24 -70
- package/lib/pane-pending-interactions.js +20 -0
- package/lib/pane-session-activation.js +114 -0
- package/lib/pane-session-transport.js +26 -0
- package/lib/project-admin-overview.js +51 -0
- package/lib/project-ask-user.js +8 -4
- package/lib/project-connection.js +14 -10
- package/lib/project-control-git-view.js +12 -0
- package/lib/project-debate.js +1 -0
- package/lib/project-delegated-follow-up.js +2 -1
- package/lib/project-directory-claim.js +65 -0
- package/lib/project-file-operations.js +61 -0
- package/lib/project-filesystem.js +15 -85
- package/lib/project-full-access.js +23 -2
- package/lib/project-http.js +7 -4
- package/lib/project-knowledge.js +32 -18
- package/lib/project-lifecycle-operations.js +98 -0
- package/lib/project-lifecycle-process-witness.js +32 -0
- package/lib/project-lifecycle-runtime.js +50 -0
- package/lib/project-linux-access.js +22 -0
- package/lib/project-logs-canonical-clay.js +27 -0
- package/lib/project-logs-clay-query.js +16 -0
- package/lib/project-logs-schema.js +4 -2
- package/lib/project-logs-service.js +8 -7
- package/lib/project-logs.js +1 -0
- package/lib/project-loop.js +1 -0
- package/lib/project-mate-chat-control.js +55 -0
- package/lib/project-mate-creation-proposal.js +18 -3
- package/lib/project-mate-interaction.js +40 -62
- package/lib/project-mcp.js +54 -16
- package/lib/project-models.js +14 -31
- package/lib/project-notifications.js +76 -17
- package/lib/project-ownership.js +77 -0
- package/lib/project-pair-result-delivery.js +14 -3
- package/lib/project-pair-usage.js +12 -13
- package/lib/project-pending-message-queue.js +4 -1
- package/lib/project-product-control.js +89 -0
- package/lib/project-product-session-queue.js +46 -0
- package/lib/project-push-access.js +28 -0
- package/lib/project-scheduled-message-queue.js +30 -0
- package/lib/project-scheduled-messages.js +67 -68
- package/lib/project-scheduled-task-control.js +83 -0
- package/lib/project-scheduled-tasks.js +13 -2
- package/lib/project-scheduling-access.js +10 -0
- package/lib/project-session-actions.js +65 -0
- package/lib/project-session-delete.js +8 -1
- package/lib/project-session-document.js +27 -7
- package/lib/project-session-github.js +63 -19
- package/lib/project-session-history-actions.js +167 -0
- package/lib/project-session-linear.js +14 -6
- package/lib/project-session-notes.js +40 -11
- package/lib/project-session-pair.js +1 -1
- package/lib/project-session-runtime-actions.js +64 -0
- package/lib/project-session-spawn.js +2 -3
- package/lib/project-session-vendor.js +55 -0
- package/lib/project-sessions.js +160 -290
- package/lib/project-shared-browser.js +78 -17
- package/lib/project-start-protocol.js +29 -0
- package/lib/project-studio-presentation.js +58 -0
- package/lib/project-user-message.js +67 -1
- package/lib/project-vendor-login.js +8 -36
- package/lib/project-workspace-operations.js +126 -0
- package/lib/project-workspace-query.js +19 -2
- package/lib/project.js +181 -45
- package/lib/public/app.js +71 -17
- package/lib/public/appearance-bootstrap.js +16 -0
- package/lib/public/css/clay-tool-activity.css +51 -0
- package/lib/public/css/clay-workspace.css +29 -0
- package/lib/public/css/command-palette.css +12 -33
- package/lib/public/css/contextual-clay.css +240 -0
- package/lib/public/css/filebrowser.css +1 -1
- package/lib/public/css/home-debate-planning.css +2 -0
- package/lib/public/css/home-mate-creation.css +5 -0
- package/lib/public/css/input.css +6 -0
- package/lib/public/css/mate-avatar-gallery.css +12 -0
- package/lib/public/css/mate-conversation.css +10 -5
- package/lib/public/css/mate-loading-scene.css +21 -0
- package/lib/public/css/messages.css +6 -2
- package/lib/public/css/overlays.css +68 -258
- package/lib/public/css/project-admin-overview.css +13 -0
- package/lib/public/css/project-mate-creation.css +5 -6
- package/lib/public/css/project-start.css +108 -0
- package/lib/public/css/projects-hub.css +53 -14
- package/lib/public/css/session-folders.css +11 -0
- package/lib/public/css/session-github.css +46 -1
- package/lib/public/css/settings-shell.css +103 -0
- package/lib/public/css/shared-browser.css +35 -1
- package/lib/public/css/sidebar.css +7 -0
- package/lib/public/css/sticky-notes.css +87 -1
- package/lib/public/css/title-bar.css +79 -0
- package/lib/public/index.html +61 -68
- package/lib/public/mate-avatars/B01.png +0 -0
- package/lib/public/mate-avatars/B02.png +0 -0
- package/lib/public/mate-avatars/B03.png +0 -0
- package/lib/public/mate-avatars/B04.png +0 -0
- package/lib/public/mate-avatars/B05.png +0 -0
- package/lib/public/mate-avatars/B06.png +0 -0
- package/lib/public/mate-avatars/B07.png +0 -0
- package/lib/public/mate-avatars/B08.png +0 -0
- package/lib/public/mate-avatars/B09.png +0 -0
- package/lib/public/mate-avatars/B10.png +0 -0
- package/lib/public/mate-avatars/B11.png +0 -0
- package/lib/public/mate-avatars/B12.png +0 -0
- package/lib/public/mate-avatars/B13.png +0 -0
- package/lib/public/mate-avatars/B14.png +0 -0
- package/lib/public/mate-avatars/B15.png +0 -0
- package/lib/public/mate-avatars/B16.png +0 -0
- package/lib/public/mate-avatars/B17.png +0 -0
- package/lib/public/mate-avatars/B18.png +0 -0
- package/lib/public/mate-avatars/B19.png +0 -0
- package/lib/public/mate-avatars/B20.png +0 -0
- package/lib/public/mate-avatars/B21.png +0 -0
- package/lib/public/mate-avatars/B22.png +0 -0
- package/lib/public/mate-avatars/B23.png +0 -0
- package/lib/public/mate-avatars/B24.png +0 -0
- package/lib/public/mate-avatars/B25.png +0 -0
- package/lib/public/mate-avatars/B26.png +0 -0
- package/lib/public/mate-avatars/B27.png +0 -0
- package/lib/public/mate-avatars/B28.png +0 -0
- package/lib/public/mate-avatars/B29.png +0 -0
- package/lib/public/mate-avatars/B30.png +0 -0
- package/lib/public/mate-avatars/B31.png +0 -0
- package/lib/public/mate-avatars/B32.png +0 -0
- package/lib/public/mate-avatars/B33.png +0 -0
- package/lib/public/mate-avatars/B34.png +0 -0
- package/lib/public/mate-avatars/B35.png +0 -0
- package/lib/public/mate-avatars/B36.png +0 -0
- package/lib/public/mate-avatars/B37.png +0 -0
- package/lib/public/mate-avatars/B38.png +0 -0
- package/lib/public/mate-avatars/B39.png +0 -0
- package/lib/public/mate-avatars/B40.png +0 -0
- package/lib/public/mate-avatars/B41.png +0 -0
- package/lib/public/mate-avatars/B42.png +0 -0
- package/lib/public/mate-avatars/B43.png +0 -0
- package/lib/public/mate-avatars/B44.png +0 -0
- package/lib/public/mate-avatars/B45.png +0 -0
- package/lib/public/mate-avatars/B46.png +0 -0
- package/lib/public/mate-avatars/B47.png +0 -0
- package/lib/public/mate-avatars/B48.png +0 -0
- package/lib/public/mate-avatars/C01.png +0 -0
- package/lib/public/mate-avatars/C02.png +0 -0
- package/lib/public/mate-avatars/C03.png +0 -0
- package/lib/public/mate-avatars/C04.png +0 -0
- package/lib/public/mate-avatars/C05.png +0 -0
- package/lib/public/mate-avatars/C06.png +0 -0
- package/lib/public/mate-avatars/C07.png +0 -0
- package/lib/public/mate-avatars/C08.png +0 -0
- package/lib/public/mate-avatars/C09.png +0 -0
- package/lib/public/mate-avatars/C10.png +0 -0
- package/lib/public/mate-avatars/C11.png +0 -0
- package/lib/public/mate-avatars/C12.png +0 -0
- package/lib/public/mate-avatars/C13.png +0 -0
- package/lib/public/mate-avatars/C14.png +0 -0
- package/lib/public/mate-avatars/C15.png +0 -0
- package/lib/public/mate-avatars/C16.png +0 -0
- package/lib/public/mate-avatars/C17.png +0 -0
- package/lib/public/mate-avatars/C18.png +0 -0
- package/lib/public/mate-avatars/C19.png +0 -0
- package/lib/public/mate-avatars/C20.png +0 -0
- package/lib/public/mate-avatars/C21.png +0 -0
- package/lib/public/mate-avatars/C22.png +0 -0
- package/lib/public/mate-avatars/C23.png +0 -0
- package/lib/public/mate-avatars/C24.png +0 -0
- package/lib/public/mate-avatars/C25.png +0 -0
- package/lib/public/mate-avatars/C26.png +0 -0
- package/lib/public/mate-avatars/C27.png +0 -0
- package/lib/public/mate-avatars/C28.png +0 -0
- package/lib/public/mate-avatars/C29.png +0 -0
- package/lib/public/mate-avatars/C30.png +0 -0
- package/lib/public/mate-avatars/C31.png +0 -0
- package/lib/public/mate-avatars/C32.png +0 -0
- package/lib/public/mate-avatars/C33.png +0 -0
- package/lib/public/mate-avatars/C34.png +0 -0
- package/lib/public/mate-avatars/C35.png +0 -0
- package/lib/public/mate-avatars/C36.png +0 -0
- package/lib/public/mate-avatars/C37.png +0 -0
- package/lib/public/mate-avatars/C38.png +0 -0
- package/lib/public/mate-avatars/C39.png +0 -0
- package/lib/public/mate-avatars/C40.png +0 -0
- package/lib/public/mate-avatars/C41.png +0 -0
- package/lib/public/mate-avatars/C42.png +0 -0
- package/lib/public/mate-avatars/C43.png +0 -0
- package/lib/public/mate-avatars/C44.png +0 -0
- package/lib/public/mate-avatars/C45.png +0 -0
- package/lib/public/mate-avatars/C46.png +0 -0
- package/lib/public/mate-avatars/C47.png +0 -0
- package/lib/public/mate-avatars/C48.png +0 -0
- package/lib/public/mate-avatars/catalog.json +482 -0
- package/lib/public/mate-avatars/lead-clay.png +0 -0
- package/lib/public/modules/admin-settings-invitations.js +2 -2
- package/lib/public/modules/admin-settings-projects.js +8 -4
- package/lib/public/modules/admin-settings-ui.js +20 -4
- package/lib/public/modules/admin-settings-users.js +4 -4
- package/lib/public/modules/app-connection.js +11 -1
- package/lib/public/modules/app-favicon.js +18 -9
- package/lib/public/modules/app-header.js +7 -4
- package/lib/public/modules/app-home-hub.js +2 -1
- package/lib/public/modules/app-loop-ui.js +2 -0
- package/lib/public/modules/app-message-router.js +22 -1
- package/lib/public/modules/app-messages.js +125 -19
- package/lib/public/modules/app-misc.js +3 -1
- package/lib/public/modules/app-notifications.js +11 -5
- package/lib/public/modules/app-panels.js +61 -123
- package/lib/public/modules/app-projects.js +14 -407
- package/lib/public/modules/app-rate-limit.js +19 -28
- package/lib/public/modules/app-rendering.js +4 -3
- package/lib/public/modules/avatar.js +15 -41
- package/lib/public/modules/chat-render-runtime.js +20 -0
- package/lib/public/modules/clay-browser-links.js +47 -0
- package/lib/public/modules/clay-control-activity.js +214 -0
- package/lib/public/modules/clay-control-copy.js +36 -0
- package/lib/public/modules/clay-control-detail-targets.js +44 -0
- package/lib/public/modules/clay-control-object-targets.js +52 -0
- package/lib/public/modules/clay-control-target-visibility.js +12 -0
- package/lib/public/modules/clay-control-targets.js +44 -0
- package/lib/public/modules/clay-log-links.js +23 -0
- package/lib/public/modules/clay-navigation-render.js +52 -0
- package/lib/public/modules/clay-owner-navigation.js +33 -0
- package/lib/public/modules/clay-session-links.js +31 -0
- package/lib/public/modules/clay-studio-bridge.js +20 -0
- package/lib/public/modules/clay-studio-document.js +67 -0
- package/lib/public/modules/clay-studio-render.js +146 -0
- package/lib/public/modules/clay-tool-activity.js +140 -0
- package/lib/public/modules/clay-tool-presentation.js +343 -0
- package/lib/public/modules/command-palette.js +162 -40
- package/lib/public/modules/contextual-ask-session.js +26 -0
- package/lib/public/modules/contextual-clay-geometry.js +155 -0
- package/lib/public/modules/contextual-clay-session.js +130 -0
- package/lib/public/modules/contextual-clay-workspace.js +169 -0
- package/lib/public/modules/contextual-clay.js +252 -0
- package/lib/public/modules/contextual-composer.js +91 -0
- package/lib/public/modules/contextual-mate-context.js +117 -0
- package/lib/public/modules/contextual-mate-hint.js +40 -0
- package/lib/public/modules/contextual-mate-identity.js +23 -0
- package/lib/public/modules/contextual-mate-sessions.js +134 -0
- package/lib/public/modules/contextual-search.js +137 -0
- package/lib/public/modules/contextual-session-citations.js +58 -0
- package/lib/public/modules/debate.js +1 -0
- package/lib/public/modules/default-ai.js +11 -3
- package/lib/public/modules/elicitation-form.js +5 -0
- package/lib/public/modules/filebrowser.js +20 -1
- package/lib/public/modules/generation-stop.js +8 -5
- package/lib/public/modules/git-panel.js +3 -1
- package/lib/public/modules/github-star.js +66 -0
- package/lib/public/modules/history-replay-batch.js +13 -1
- package/lib/public/modules/home-debate-live.js +2 -0
- package/lib/public/modules/home-debate-planning.js +7 -7
- package/lib/public/modules/home-mate-avatar-editor.js +127 -208
- package/lib/public/modules/home-mate-chat.js +8 -6
- package/lib/public/modules/home-mate-creation.js +73 -1
- package/lib/public/modules/home-mate-settings.js +19 -12
- package/lib/public/modules/icon-strip-tooltip.js +2 -1
- package/lib/public/modules/input.js +88 -10
- package/lib/public/modules/issues-render.js +3 -2
- package/lib/public/modules/knowledge-db-workbench.js +4 -4
- package/lib/public/modules/markdown.js +6 -34
- package/lib/public/modules/mate-avatar-catalog.js +97 -0
- package/lib/public/modules/mate-knowledge-workbench.js +1 -1
- package/lib/public/modules/mate-loading-scene.js +17 -0
- package/lib/public/modules/mate-management.js +40 -7
- package/lib/public/modules/mcp-connection-view.js +31 -13
- package/lib/public/modules/mcp-discovery-view.js +31 -0
- package/lib/public/modules/mcp-ui.js +23 -4
- package/lib/public/modules/mention.js +3 -0
- package/lib/public/modules/message-delivery.js +20 -2
- package/lib/public/modules/model-picker.js +2 -0
- package/lib/public/modules/pane-activation.js +214 -0
- package/lib/public/modules/pane-binding.js +82 -0
- package/lib/public/modules/pane-bridge.js +7 -4
- package/lib/public/modules/pane-browser-bridge.js +22 -0
- package/lib/public/modules/pane-file-bridge.js +4 -0
- package/lib/public/modules/pane-issue-bridge.js +4 -1
- package/lib/public/modules/pending-message-queue.js +1 -0
- package/lib/public/modules/permission-control.js +5 -4
- package/lib/public/modules/personal-settings-dialog.js +7 -1
- package/lib/public/modules/product-review.js +26 -0
- package/lib/public/modules/profile.js +12 -241
- package/lib/public/modules/project-access-recovery.js +17 -0
- package/lib/public/modules/project-admin-overview.js +21 -0
- package/lib/public/modules/project-chat-identity.js +13 -4
- package/lib/public/modules/project-logs-render.js +3 -0
- package/lib/public/modules/project-mate-creation-workspace.js +13 -4
- package/lib/public/modules/project-mate-navigation.js +144 -22
- package/lib/public/modules/project-session-visibility-settings.js +19 -16
- package/lib/public/modules/project-settings.js +119 -129
- package/lib/public/modules/project-start-dialog.js +130 -0
- package/lib/public/modules/project-start-folder-state.js +78 -0
- package/lib/public/modules/project-start-folder-view.js +190 -0
- package/lib/public/modules/project-start-forms.js +66 -0
- package/lib/public/modules/project-start-path.js +60 -0
- package/lib/public/modules/project-start-state.js +54 -0
- package/lib/public/modules/project-start-submit.js +67 -0
- package/lib/public/modules/projects-hub-view.js +33 -14
- package/lib/public/modules/projects-hub.js +10 -6
- package/lib/public/modules/rewind.js +5 -0
- package/lib/public/modules/scheduled-tasks.js +2 -0
- package/lib/public/modules/scheduler.js +2 -0
- package/lib/public/modules/search-clay-chat.js +5 -440
- package/lib/public/modules/server-settings.js +36 -91
- package/lib/public/modules/session-actions.js +5 -2
- package/lib/public/modules/session-context-menu.js +5 -0
- package/lib/public/modules/session-create-form.js +10 -10
- package/lib/public/modules/session-folder-layout.js +1 -1
- package/lib/public/modules/session-folder-view-menu.js +9 -0
- package/lib/public/modules/session-github.js +85 -14
- package/lib/public/modules/session-rich-drafts.js +21 -0
- package/lib/public/modules/session-switch-defer.js +67 -0
- package/lib/public/modules/session-work-primary.js +51 -0
- package/lib/public/modules/settings-defaults.js +27 -28
- package/lib/public/modules/settings-project-target.js +56 -0
- package/lib/public/modules/settings-select.js +1 -1
- package/lib/public/modules/settings-shell-registry.js +88 -0
- package/lib/public/modules/settings-shell-view.js +104 -0
- package/lib/public/modules/settings-shell.js +342 -0
- package/lib/public/modules/shared-browser-settings.js +112 -0
- package/lib/public/modules/shared-browser-tabs.js +13 -3
- package/lib/public/modules/shared-browser.js +29 -6
- package/lib/public/modules/sidebar-mobile.js +12 -33
- package/lib/public/modules/sidebar-projects.js +3 -1
- package/lib/public/modules/sidebar-session-folders-ui.js +1 -1
- package/lib/public/modules/sidebar-sessions.js +1 -0
- package/lib/public/modules/split-group-restore.js +68 -0
- package/lib/public/modules/split-pair-ui.js +1 -0
- package/lib/public/modules/split-pane-reconciler.js +15 -0
- package/lib/public/modules/split-pane-renderer.js +87 -6
- package/lib/public/modules/split-session-boundary.js +1 -1
- package/lib/public/modules/split-view.js +60 -68
- package/lib/public/modules/sticky-note-markdown.js +72 -6
- package/lib/public/modules/sticky-notes-actions.js +30 -0
- package/lib/public/modules/sticky-notes-browser.js +9 -2
- package/lib/public/modules/sticky-notes-card.js +23 -7
- package/lib/public/modules/sticky-notes-checklist.js +116 -0
- package/lib/public/modules/sticky-notes-editor.js +108 -44
- package/lib/public/modules/sticky-notes-shared.js +50 -2
- package/lib/public/modules/sticky-notes-state.js +66 -0
- package/lib/public/modules/sticky-notes.js +34 -51
- package/lib/public/modules/stt-controller.js +4 -1
- package/lib/public/modules/stt-recording.js +1 -1
- package/lib/public/modules/stt.js +7 -2
- package/lib/public/modules/terminal.js +9 -0
- package/lib/public/modules/theme.js +18 -3
- package/lib/public/modules/thinking-lifecycle.js +33 -3
- package/lib/public/modules/thinking-view.js +23 -1
- package/lib/public/modules/tools.js +60 -11
- package/lib/public/modules/tui-grab.js +1 -2
- package/lib/public/modules/user-settings-appearance.js +10 -3
- package/lib/public/modules/user-settings-editors.js +1 -1
- package/lib/public/modules/user-settings-layout.js +14 -30
- package/lib/public/modules/user-settings-preferences.js +6 -2
- package/lib/public/modules/user-settings-profile.js +13 -3
- package/lib/public/modules/user-settings.js +18 -84
- package/lib/public/modules/vendor-login-browser.js +5 -3
- package/lib/public/modules/vendor-login.js +2 -2
- package/lib/public/modules/vendor-priority.js +15 -1
- package/lib/public/modules/vendor-usage-format.js +93 -0
- package/lib/public/modules/vendor-usage-list.js +45 -0
- package/lib/public/modules/vendor-usage-model.js +215 -0
- package/lib/public/modules/vendor-usage-overview.js +312 -0
- package/lib/public/modules/wireframe-workbench.js +5 -2
- package/lib/public/muse-avatar.svg +4 -0
- package/lib/public/style.css +14 -6
- package/lib/public/sw.js +3 -1
- package/lib/public/welcome-art/conversation-desk.png +0 -0
- package/lib/public/welcome-art/mate-clay.png +0 -0
- package/lib/public/welcome-art/project-clay.png +0 -0
- package/lib/safe-bash-commands.js +3 -45
- package/lib/scheduled-task-records.js +3 -1
- package/lib/scheduler.js +2 -0
- package/lib/sdk-bridge.js +348 -402
- package/lib/sdk-foreground-admission.js +16 -0
- package/lib/sdk-mcp-descriptors.js +2 -37
- package/lib/sdk-message-processor.js +61 -18
- package/lib/sdk-quota-snapshot.js +21 -3
- package/lib/sdk-response-recovery.js +1 -0
- package/lib/sdk-worker.js +2 -677
- package/lib/server-admin.js +63 -16
- package/lib/server-appearance-settings.js +13 -1
- package/lib/server-contextual-clay-settings.js +40 -0
- package/lib/server-contextual-mate-sessions.js +70 -0
- package/lib/server-dm.js +2 -1
- package/lib/server-github-stars.js +39 -0
- package/lib/server-global-ws.js +26 -32
- package/lib/server-home-chat-events.js +18 -4
- package/lib/server-home-chat.js +22 -20
- package/lib/server-home-clay-entry.js +23 -4
- package/lib/server-home-clay-session-links.js +29 -9
- package/lib/server-home-mate-creation.js +1 -0
- package/lib/server-home-mcp-consent.js +14 -0
- package/lib/server-mates.js +25 -62
- package/lib/server-owner-ui.js +118 -0
- package/lib/server-path-access.js +38 -0
- package/lib/server-project-removal.js +22 -0
- package/lib/server-settings.js +6 -1
- package/lib/server.js +167 -43
- package/lib/session-config-transition.js +45 -0
- package/lib/session-folders.js +7 -2
- package/lib/session-fork-history.js +21 -0
- package/lib/session-github.js +9 -2
- package/lib/session-hygiene.js +3 -35
- package/lib/session-notes-mcp-server.js +26 -4
- package/lib/session-notes-writes.js +88 -0
- package/lib/session-permission-mode.js +4 -3
- package/lib/session-skill-scope.js +11 -0
- package/lib/session-visibility.js +25 -10
- package/lib/session-work-primary.js +50 -0
- package/lib/sessions.js +66 -99
- package/lib/shared-browser-cookie-sync.js +32 -0
- package/lib/shared-browser-cookies.js +79 -0
- package/lib/shared-browser-runtime.js +25 -9
- package/lib/shared-browser-storage-sync.js +43 -0
- package/lib/shared-browser-storage.js +101 -0
- package/lib/shared-browser-tools.js +2 -1
- package/lib/shared-browser-worker.js +46 -10
- package/lib/terminal-manager.js +65 -6
- package/lib/tool-llm.js +1 -1
- package/lib/tui-transcript-index.js +1 -132
- package/lib/users-contextual-clay-preferences.js +31 -0
- package/lib/users-permissions.js +2 -8
- package/lib/users.js +7 -0
- package/lib/vendor-login-browser.js +1 -11
- package/lib/vendor-usage-acp-readers.js +97 -0
- package/lib/vendor-usage-capabilities.js +88 -0
- package/lib/vendor-usage-http-readers.js +214 -0
- package/lib/vendor-usage-metrics.js +47 -0
- package/lib/vendor-usage-native-readers.js +106 -0
- package/lib/vendor-usage-overview.js +406 -0
- package/lib/vendor-usage-service.js +281 -0
- package/lib/workspace-assignment-service.js +25 -0
- package/lib/workspace-query-access.js +4 -1
- package/lib/workspace-query-mcp-server.js +1 -1
- package/lib/workspace-query-service.js +13 -2
- package/lib/ws-request.js +1 -0
- package/lib/ws-schema.js +22 -4
- package/lib/yoke/acp-agent-profiles.js +7 -5
- package/lib/yoke/adapters/antigravity.js +3 -14
- package/lib/yoke/adapters/claude-query-contract.js +9 -0
- package/lib/yoke/adapters/claude.js +66 -50
- package/lib/yoke/adapters/codex-query-contract.js +25 -0
- package/lib/yoke/adapters/codex.js +98 -123
- package/lib/yoke/adapters/kiro.js +3 -1
- package/lib/yoke/adapters/muse-query-contract.js +7 -0
- package/lib/yoke/adapters/muse.js +122 -0
- package/lib/yoke/auth-events.js +17 -0
- package/lib/yoke/claude-hook-installer.js +272 -0
- package/lib/yoke/claude-jsonl-watcher.js +204 -0
- package/lib/yoke/claude-maintenance.js +55 -0
- package/lib/yoke/claude-permission-patterns.js +53 -0
- package/lib/yoke/claude-response-recovery.js +155 -0
- package/lib/yoke/claude-transcript-hygiene.js +34 -0
- package/lib/yoke/claude-worker-startup.js +28 -0
- package/lib/yoke/clay-skill-install.js +33 -0
- package/lib/yoke/cli-sessions.js +300 -0
- package/lib/yoke/codex-app-server.js +7 -12
- package/lib/yoke/codex-dynamic-tool-names.js +80 -0
- package/lib/yoke/codex-idle-recovery.js +81 -1
- package/lib/yoke/codex-model-catalog.js +37 -3
- package/lib/yoke/codex-recovery-admission.js +164 -0
- package/lib/yoke/configuration.js +13 -0
- package/lib/yoke/discovery.js +70 -0
- package/lib/yoke/errors.js +8 -0
- package/lib/yoke/host-environment.js +7 -0
- package/lib/yoke/index.js +9 -51
- package/lib/yoke/interface.js +116 -0
- package/lib/yoke/kiro-acp-server.js +5 -5
- package/lib/yoke/legacy-sessions.js +89 -0
- package/lib/yoke/login-protocol.js +25 -0
- package/lib/yoke/maintenance.js +12 -0
- package/lib/yoke/mcp-proxy.js +32 -0
- package/lib/yoke/mcp-source-adapters.js +91 -0
- package/lib/yoke/mcp-source-context.js +42 -0
- package/lib/yoke/mcp-source-discovery.js +169 -0
- package/lib/yoke/mcp-source-plugins.js +68 -0
- package/lib/yoke/mcp-source-restrictions.js +47 -0
- package/lib/yoke/mcp-tool-policy-normalize.js +28 -0
- package/lib/yoke/model-preferences.js +6 -0
- package/lib/yoke/muse-artifacts.js +36 -0
- package/lib/yoke/muse-controls.js +50 -0
- package/lib/yoke/muse-input.js +64 -0
- package/lib/yoke/muse-items.js +157 -0
- package/lib/yoke/muse-policy.js +52 -0
- package/lib/yoke/muse-query.js +428 -0
- package/lib/yoke/muse-runtime.js +211 -0
- package/lib/yoke/muse-services.js +92 -0
- package/lib/yoke/muse-skills.js +79 -0
- package/lib/yoke/muse-turns.js +71 -0
- package/lib/yoke/options/acp.js +2 -0
- package/lib/yoke/options/antigravity.js +2 -0
- package/lib/yoke/options/claude.js +21 -0
- package/lib/yoke/options/codex-defaults.js +29 -0
- package/lib/yoke/options/codex-settings.js +21 -0
- package/lib/yoke/options/codex.js +6 -0
- package/lib/yoke/options/kiro-defaults.js +22 -0
- package/lib/yoke/options/kiro.js +5 -0
- package/lib/yoke/options/muse.js +5 -0
- package/lib/yoke/provider-contract.js +5 -0
- package/lib/yoke/providers/antigravity-executable.js +8 -0
- package/lib/yoke/providers/claude-executable.js +40 -0
- package/lib/yoke/providers/claude-model-descriptions.js +34 -0
- package/lib/yoke/providers/claude-process.js +97 -0
- package/lib/yoke/providers/claude-provision.js +75 -0
- package/lib/yoke/providers/codex-errors.js +8 -0
- package/lib/yoke/providers/muse-executable.js +17 -0
- package/lib/yoke/provisioning.js +6 -0
- package/lib/yoke/query-options.js +10 -0
- package/lib/yoke/response-recovery.js +41 -0
- package/lib/yoke/sdk-mcp-descriptors.js +37 -0
- package/lib/yoke/sdk-server-factory.js +7 -0
- package/lib/yoke/session-history.js +8 -0
- package/lib/yoke/session-tool-transport.js +34 -13
- package/lib/yoke/settings.js +23 -0
- package/lib/yoke/source-locations.js +4 -0
- package/lib/yoke/title-query.js +18 -7
- package/lib/yoke/tui-transcript-index.js +132 -0
- package/lib/yoke/usage.js +48 -0
- package/lib/yoke/user-input.js +13 -0
- package/lib/yoke/vendor-registry.js +87 -3
- package/package.json +11 -4
- package/lib/public/modules/server-settings-navigation.js +0 -39
package/lib/sdk-bridge.js
CHANGED
|
@@ -1,12 +1,9 @@
|
|
|
1
|
-
|
|
2
|
-
var codexQuestionGuidance = require("./yoke/user-input-guidance").codexQuestionGuidance;
|
|
1
|
+
var crypto = require("crypto");
|
|
3
2
|
var fs = require("fs");
|
|
4
3
|
var path = require("path");
|
|
5
4
|
var execSync = require("child_process").execSync;
|
|
6
5
|
var execFileSync = require("child_process").execFileSync;
|
|
7
6
|
var usersModule = require("./users");
|
|
8
|
-
var { getCodexConfig } = require("./codex-defaults");
|
|
9
|
-
var { getKiroConfig } = require("./kiro-defaults");
|
|
10
7
|
var { splitShellSegments, attachSkillDiscovery } = require("./sdk-skill-discovery");
|
|
11
8
|
var skillDiscovery = require("./yoke/skill-discovery");
|
|
12
9
|
var { isSafeBashSegment } = require("./safe-bash-commands");
|
|
@@ -19,7 +16,7 @@ var sessionTitlePolicy = require("./session-title-policy");
|
|
|
19
16
|
var sessionTitleGenerator = require("./session-title-generator");
|
|
20
17
|
var loopInterview = require("./project-loop-interview");
|
|
21
18
|
|
|
22
|
-
var extractMcpDescriptors = require("./sdk-mcp-descriptors").extractMcpDescriptors;
|
|
19
|
+
var extractMcpDescriptors = require("./yoke/sdk-mcp-descriptors").extractMcpDescriptors;
|
|
23
20
|
|
|
24
21
|
// Call an MCP tool handler by server name and tool name.
|
|
25
22
|
// Returns a promise that resolves with the tool result.
|
|
@@ -137,7 +134,7 @@ function createSDKBridge(opts) {
|
|
|
137
134
|
}];
|
|
138
135
|
}
|
|
139
136
|
|
|
140
|
-
function
|
|
137
|
+
function getSessionMcpServer(session, queryGeneration) {
|
|
141
138
|
if (!session || !Number.isInteger(queryGeneration)) return null;
|
|
142
139
|
var bridgeArgs = [
|
|
143
140
|
path.join(__dirname, "yoke", "mcp-bridge-server.js"),
|
|
@@ -165,25 +162,16 @@ function createSDKBridge(opts) {
|
|
|
165
162
|
return _cachedFreshAuthState;
|
|
166
163
|
}
|
|
167
164
|
|
|
168
|
-
|
|
169
|
-
if (!errDetail) return false;
|
|
170
|
-
var errLower = String(errDetail).toLowerCase();
|
|
171
|
-
return errLower.indexOf("not logged in") !== -1
|
|
172
|
-
|| errLower.indexOf("unauthenticated") !== -1
|
|
173
|
-
|| errLower.indexOf("authentication") !== -1
|
|
174
|
-
|| errLower.indexOf("sign in") !== -1
|
|
175
|
-
|| errLower.indexOf("log in") !== -1
|
|
176
|
-
|| errLower.indexOf("please login") !== -1;
|
|
177
|
-
}
|
|
165
|
+
var isAuthErrorMessage = require("./yoke/auth-events").isAuthenticationError;
|
|
178
166
|
|
|
179
167
|
function getLoginCommand(vendor) {
|
|
180
168
|
var info = yoke.getVendorInfo(vendor);
|
|
181
|
-
return (info && info.loginCommand) || "
|
|
169
|
+
return (info && info.loginCommand) || "";
|
|
182
170
|
}
|
|
183
171
|
|
|
184
172
|
function supportsOsUserIsolation(vendor) {
|
|
185
173
|
var info = yoke.getVendorInfo(vendor);
|
|
186
|
-
return
|
|
174
|
+
return !!info && info.osUserIsolation === true;
|
|
187
175
|
}
|
|
188
176
|
|
|
189
177
|
function notifyAuthRequired(session, title, body, authLinuxUser, canAutoLogin, loginCommand) {
|
|
@@ -323,6 +311,7 @@ function createSDKBridge(opts) {
|
|
|
323
311
|
}
|
|
324
312
|
|
|
325
313
|
function stopIdleReaper() {
|
|
314
|
+
responseRecovery.dispose();
|
|
326
315
|
if (_idleReaperTimer) {
|
|
327
316
|
clearInterval(_idleReaperTimer);
|
|
328
317
|
_idleReaperTimer = null;
|
|
@@ -389,6 +378,18 @@ function createSDKBridge(opts) {
|
|
|
389
378
|
var sendAndRecord = msgProcessor.sendAndRecord;
|
|
390
379
|
var sendToSession = msgProcessor.sendToSession;
|
|
391
380
|
|
|
381
|
+
var responseRecovery = require("./yoke/response-recovery").attachResponseRecovery(Object.assign({
|
|
382
|
+
getProvider: function(session) { var vendor = session.vendor || sm.defaultVendor || adapter && adapter.vendor; return adapters[vendor] || vendor || adapter; },
|
|
383
|
+
sessions: sm.sessions,
|
|
384
|
+
changed: onProcessingChanged,
|
|
385
|
+
record: sendAndRecord,
|
|
386
|
+
send: sendToSession,
|
|
387
|
+
broadcast: function() { if (sm.broadcastSessionList) sm.broadcastSessionList(); },
|
|
388
|
+
restart: function(session, payload, state) {
|
|
389
|
+
return startQuery(session, payload.text, payload.images, payload.linuxUser, payload.beforePush, null, state);
|
|
390
|
+
},
|
|
391
|
+
}, opts.responseRecovery || {}));
|
|
392
|
+
|
|
392
393
|
// --- MCP elicitation ---
|
|
393
394
|
|
|
394
395
|
function handleElicitation(session, request, opts) {
|
|
@@ -417,6 +418,7 @@ function createSDKBridge(opts) {
|
|
|
417
418
|
|
|
418
419
|
if (pushModule) {
|
|
419
420
|
pushModule.sendPush({
|
|
421
|
+
sessionId: session.localId,
|
|
420
422
|
type: "elicitation",
|
|
421
423
|
slug: slug,
|
|
422
424
|
title: (request.serverName || "MCP Server") + " needs input",
|
|
@@ -467,6 +469,7 @@ function createSDKBridge(opts) {
|
|
|
467
469
|
|
|
468
470
|
if (pushModule) {
|
|
469
471
|
pushModule.sendPush({
|
|
472
|
+
sessionId: session.localId,
|
|
470
473
|
type: "user_dialog",
|
|
471
474
|
slug: slug,
|
|
472
475
|
title: "Claude needs a decision",
|
|
@@ -489,44 +492,7 @@ function createSDKBridge(opts) {
|
|
|
489
492
|
// Ensures the linux user's .claude project directory exists and is writable,
|
|
490
493
|
// then pre-copies CLI session file if needed. Called before starting a query
|
|
491
494
|
// so the worker can resume from the correct session file.
|
|
492
|
-
|
|
493
|
-
try {
|
|
494
|
-
var configMod = require("./config");
|
|
495
|
-
var osUsersMod = require("./os-users");
|
|
496
|
-
var originalHome = configMod.REAL_HOME || require("os").homedir();
|
|
497
|
-
var linuxUserHome = osUsersMod.getLinuxUserHome(linuxUser);
|
|
498
|
-
var uid = osUsersMod.getLinuxUserUid(linuxUser);
|
|
499
|
-
if (originalHome !== linuxUserHome && uid != null) {
|
|
500
|
-
var projectSlug = (cwd || "").replace(/\//g, "-");
|
|
501
|
-
var dstDir = path.join(linuxUserHome, ".claude", "projects", projectSlug);
|
|
502
|
-
// Create and chown the project directory once
|
|
503
|
-
if (!fs.existsSync(dstDir)) {
|
|
504
|
-
fs.mkdirSync(dstDir, { recursive: true });
|
|
505
|
-
try { execFileSync("chown", ["-R", String(uid), path.join(linuxUserHome, ".claude")]); } catch (e2) {}
|
|
506
|
-
} else {
|
|
507
|
-
try {
|
|
508
|
-
var dirStat = fs.statSync(dstDir);
|
|
509
|
-
if (dirStat.uid !== uid) {
|
|
510
|
-
execFileSync("chown", [String(uid), dstDir]);
|
|
511
|
-
}
|
|
512
|
-
} catch (e2) {}
|
|
513
|
-
}
|
|
514
|
-
// Pre-copy CLI session file so the worker can resume the conversation
|
|
515
|
-
if (session.cliSessionId) {
|
|
516
|
-
var sessionFileName = session.cliSessionId + ".jsonl";
|
|
517
|
-
var srcFile = path.join(originalHome, ".claude", "projects", projectSlug, sessionFileName);
|
|
518
|
-
var dstFile = path.join(dstDir, sessionFileName);
|
|
519
|
-
if (fs.existsSync(srcFile) && !fs.existsSync(dstFile)) {
|
|
520
|
-
fs.copyFileSync(srcFile, dstFile);
|
|
521
|
-
try { execFileSync("chown", [String(uid), dstFile]); } catch (e2) {}
|
|
522
|
-
console.log("[sdk-bridge] Pre-copied CLI session " + session.cliSessionId + " to " + linuxUser);
|
|
523
|
-
}
|
|
524
|
-
}
|
|
525
|
-
}
|
|
526
|
-
} catch (copyErr) {
|
|
527
|
-
console.log("[sdk-bridge] Dir setup / session pre-copy skipped:", copyErr.message);
|
|
528
|
-
}
|
|
529
|
-
}
|
|
495
|
+
|
|
530
496
|
|
|
531
497
|
// --- SDK query lifecycle ---
|
|
532
498
|
|
|
@@ -745,6 +711,39 @@ function createSDKBridge(opts) {
|
|
|
745
711
|
// Workspace inspection and proposal posting are session-bound. Keep this
|
|
746
712
|
// list exact so a future execution/mutation tool cannot inherit approval.
|
|
747
713
|
var safeWorkspaceTools = {
|
|
714
|
+
"mcp__clay-workspace__read_current_context": true,
|
|
715
|
+
"mcp__clay-workspace__read_selected_context": true,
|
|
716
|
+
"mcp__clay-workspace__open_context_conversation": true,
|
|
717
|
+
"mcp__clay-workspace__read_context_navigation_receipt": true,
|
|
718
|
+
"mcp__clay-workspace__read_owner_screen": true,
|
|
719
|
+
"mcp__clay-workspace__inspect_owner_screen_change": true,
|
|
720
|
+
"mcp__clay-workspace__control_owner_screen": true,
|
|
721
|
+
"mcp__clay-workspace__discover_product_controls": true,
|
|
722
|
+
"mcp__clay-workspace__list_owned_mates": true,
|
|
723
|
+
"mcp__clay-workspace__begin_schedule_control_interview": true,
|
|
724
|
+
"mcp__clay-workspace__read_schedule_controls": true,
|
|
725
|
+
"mcp__clay-workspace__inspect_schedule_change": true,
|
|
726
|
+
"mcp__clay-workspace__control_schedules": true,
|
|
727
|
+
"mcp__clay-workspace__read_mate_chat_control": true,
|
|
728
|
+
"mcp__clay-workspace__inspect_mate_chat_change": true,
|
|
729
|
+
"mcp__clay-workspace__control_mate_chat": true,
|
|
730
|
+
"mcp__clay-workspace__read_project_workspace": true,
|
|
731
|
+
"mcp__clay-workspace__read_workspace_receipt": true,
|
|
732
|
+
"mcp__clay-workspace__inspect_workspace_change": true,
|
|
733
|
+
"mcp__clay-workspace__control_project_workspace": true,
|
|
734
|
+
"mcp__clay-workspace__read_vendor_usage": true,
|
|
735
|
+
"mcp__clay-workspace__read_project_records": true,
|
|
736
|
+
"mcp__clay-workspace__inspect_project_record_change": true,
|
|
737
|
+
"mcp__clay-workspace__control_project_records": true,
|
|
738
|
+
"mcp__clay-workspace__read_mate_knowledge_control": true,
|
|
739
|
+
"mcp__clay-workspace__inspect_mate_knowledge_change": true,
|
|
740
|
+
"mcp__clay-workspace__control_mate_knowledge": true,
|
|
741
|
+
"mcp__clay-workspace__inspect_mate_control": true,
|
|
742
|
+
"mcp__clay-workspace__control_mate_lifecycle": true,
|
|
743
|
+
"mcp__clay-workspace__inspect_project_control": true,
|
|
744
|
+
"mcp__clay-workspace__control_project_lifecycle": true,
|
|
745
|
+
"mcp__clay-workspace__inspect_session_control": true,
|
|
746
|
+
"mcp__clay-workspace__control_project_session": true,
|
|
748
747
|
"mcp__clay-workspace__list_projects": true,
|
|
749
748
|
"mcp__clay-workspace__list_project_sessions": true,
|
|
750
749
|
"mcp__clay-workspace__search_project_history": true,
|
|
@@ -902,6 +901,7 @@ function createSDKBridge(opts) {
|
|
|
902
901
|
|
|
903
902
|
if (pushModule) {
|
|
904
903
|
pushModule.sendPush({
|
|
904
|
+
sessionId: session.localId,
|
|
905
905
|
type: "permission_request",
|
|
906
906
|
slug: slug,
|
|
907
907
|
requestId: requestId,
|
|
@@ -943,58 +943,13 @@ function createSDKBridge(opts) {
|
|
|
943
943
|
* Only returns processes whose cwd matches our project directory.
|
|
944
944
|
* Returns an array of { pid, command } for each conflicting process found.
|
|
945
945
|
*/
|
|
946
|
-
function
|
|
947
|
-
|
|
948
|
-
|
|
949
|
-
var lines = output.trim().split("\n");
|
|
950
|
-
var candidates = [];
|
|
951
|
-
for (var i = 1; i < lines.length; i++) { // skip header
|
|
952
|
-
var line = lines[i].trim();
|
|
953
|
-
var m = line.match(/^(\d+)\s+(.+)/);
|
|
954
|
-
if (!m) continue;
|
|
955
|
-
var pid = parseInt(m[1], 10);
|
|
956
|
-
var cmd = m[2];
|
|
957
|
-
// Skip our own process
|
|
958
|
-
if (pid === process.pid) continue;
|
|
959
|
-
// Skip node processes (our daemon, dev watchers, etc.)
|
|
960
|
-
if (/\bnode\b/.test(cmd.split(/\s/)[0])) continue;
|
|
961
|
-
// Match actual claude binary (e.g. /Users/x/.claude/local/claude, /usr/local/bin/claude)
|
|
962
|
-
if (/\/claude(\s|$)/.test(cmd) || /^claude(\s|$)/.test(cmd)) {
|
|
963
|
-
candidates.push({ pid: pid, command: cmd.substring(0, 200) });
|
|
964
|
-
}
|
|
965
|
-
}
|
|
966
|
-
|
|
967
|
-
// Filter to only processes whose cwd matches our project
|
|
968
|
-
var results = [];
|
|
969
|
-
for (var j = 0; j < candidates.length; j++) {
|
|
970
|
-
var c = candidates[j];
|
|
971
|
-
try {
|
|
972
|
-
// Use /proc/<pid>/cwd symlink (always available on Linux, no lsof dependency)
|
|
973
|
-
var procCwd = fs.readlinkSync("/proc/" + c.pid + "/cwd");
|
|
974
|
-
if (procCwd === cwd) {
|
|
975
|
-
results.push(c);
|
|
976
|
-
}
|
|
977
|
-
} catch (e) {
|
|
978
|
-
// /proc read failed — include as candidate anyway (conservative)
|
|
979
|
-
results.push(c);
|
|
980
|
-
}
|
|
981
|
-
}
|
|
982
|
-
return results;
|
|
983
|
-
} catch (e) {
|
|
984
|
-
return [];
|
|
985
|
-
}
|
|
946
|
+
function findConflictingProcesses(session, error) {
|
|
947
|
+
var service = require("./yoke/provider-contract").resolve(getAdapterForSession(session)).processControl;
|
|
948
|
+
return service && typeof service.shouldInspect === "function" && service.shouldInspect(error) && typeof service.findConflicts === "function" ? service.findConflicts(cwd) : [];
|
|
986
949
|
}
|
|
987
|
-
|
|
988
|
-
|
|
989
|
-
|
|
990
|
-
*/
|
|
991
|
-
function isClaudeProcess(pid) {
|
|
992
|
-
try {
|
|
993
|
-
var output = execFileSync("ps", ["-p", String(pid), "-o", "command="], { encoding: "utf8", timeout: 3000, stdio: ["pipe", "pipe", "pipe"] }).trim();
|
|
994
|
-
return /\/claude(\s|$)/.test(output) || /^claude(\s|$)/.test(output);
|
|
995
|
-
} catch (e) {
|
|
996
|
-
return false;
|
|
997
|
-
}
|
|
950
|
+
function isProviderProcess(pid, session) {
|
|
951
|
+
var service = require("./yoke/provider-contract").resolve(session ? getAdapterForSession(session) : adapter).processControl;
|
|
952
|
+
return !!(service && typeof service.verifyProcess === "function" && service.verifyProcess(pid));
|
|
998
953
|
}
|
|
999
954
|
|
|
1000
955
|
function ownsQueryRuntime(session, queryInstance, queryGeneration) {
|
|
@@ -1006,6 +961,7 @@ function createSDKBridge(opts) {
|
|
|
1006
961
|
function recordRuntimeEffectivePermissionMode(session, queryInstance, queryGeneration, message) {
|
|
1007
962
|
if (!message || (message.yokeType !== "init" && message.yokeType !== "status") || !message.permissionMode) return false;
|
|
1008
963
|
if (!ownsQueryRuntime(session, queryInstance, queryGeneration)) return false;
|
|
964
|
+
session._permissionObservationRevision = Number(session._permissionObservationRevision || 0) + 1;
|
|
1009
965
|
session.effectivePermissionMode = message.permissionMode;
|
|
1010
966
|
session.permissionModeFallbackReason = null;
|
|
1011
967
|
sm.saveSessionFile(session);
|
|
@@ -1036,7 +992,8 @@ function createSDKBridge(opts) {
|
|
|
1036
992
|
return true;
|
|
1037
993
|
}
|
|
1038
994
|
|
|
1039
|
-
async function processQueryStream(session,
|
|
995
|
+
async function processQueryStream(session, catalogCandidate, queryContract) {
|
|
996
|
+
queryContract = queryContract || yoke.sessionTools.contract(getAdapterForSession(session));
|
|
1040
997
|
// Capture references at start so we only clean up OUR resources in finally,
|
|
1041
998
|
// not resources from a newer query that may have been created after an abort.
|
|
1042
999
|
var myQueryInstance = session.queryInstance;
|
|
@@ -1047,7 +1004,7 @@ function createSDKBridge(opts) {
|
|
|
1047
1004
|
try {
|
|
1048
1005
|
for await (var msg of myQueryInstance) {
|
|
1049
1006
|
// An old iterator may drain after Stop or after a replacement query starts.
|
|
1050
|
-
if (!ownsQueryRuntime(session, myQueryInstance, myQueryGeneration)) continue;
|
|
1007
|
+
if (!ownsQueryRuntime(session, myQueryInstance, myQueryGeneration) || responseRecovery.stopping(session)) continue;
|
|
1051
1008
|
if ((session.taskStopRequested || (myAbortController && myAbortController.signal.aborted))
|
|
1052
1009
|
&& msg && msg.yokeType !== "error" && msg.yokeType !== "interrupted") continue;
|
|
1053
1010
|
if (msg && msg.yokeType !== "text_delta" && msg.yokeType !== "thinking_delta" && msg.yokeType !== "tool_input_delta") {
|
|
@@ -1091,6 +1048,7 @@ function createSDKBridge(opts) {
|
|
|
1091
1048
|
if (continuationIdentity && !ownsQueryRuntime(session, myQueryInstance, myQueryGeneration)) {
|
|
1092
1049
|
continue;
|
|
1093
1050
|
}
|
|
1051
|
+
responseRecovery.event(session, msg);
|
|
1094
1052
|
processSDKMessage(session, msg);
|
|
1095
1053
|
if (continuationIdentity) {
|
|
1096
1054
|
settleContinuationStartup(session, myQueryInstance, myQueryGeneration, true, null);
|
|
@@ -1101,26 +1059,21 @@ function createSDKBridge(opts) {
|
|
|
1101
1059
|
// permission state. Setter acknowledgement deliberately does not
|
|
1102
1060
|
// change this field.
|
|
1103
1061
|
recordRuntimeEffectivePermissionMode(session, myQueryInstance, myQueryGeneration, msg);
|
|
1104
|
-
if (
|
|
1062
|
+
if (catalogCandidate && msg && msg.yokeType === "session_started" && msg.sessionId
|
|
1105
1063
|
&& session.queryInstance === myQueryInstance
|
|
1106
|
-
&& Number(session._sdkQueryGeneration || 0) ===
|
|
1064
|
+
&& Number(session._sdkQueryGeneration || 0) === catalogCandidate.generation
|
|
1107
1065
|
&& session.cliSessionId === msg.sessionId
|
|
1108
1066
|
&& (!sm.sessions || typeof sm.sessions.get !== "function" || sm.sessions.get(session.localId) === session)) {
|
|
1109
|
-
|
|
1110
|
-
if (codexCatalogCandidate.userInputVersion) session.codexUserInputToolCatalogVersion = codexCatalogCandidate.userInputVersion;
|
|
1111
|
-
if (codexCatalogCandidate.sharedBrowserVersion) session.codexSharedBrowserToolCatalogVersion = codexCatalogCandidate.sharedBrowserVersion;
|
|
1112
|
-
if (codexCatalogCandidate.issuesVersion) session.codexIssuesToolCatalogVersion = codexCatalogCandidate.issuesVersion;
|
|
1113
|
-
if (codexCatalogCandidate.youVersion) session.codexYouToolCatalogVersion = codexCatalogCandidate.youVersion;
|
|
1114
|
-
if (codexCatalogCandidate.linearVersion) session.codexLinearToolCatalogVersion = codexCatalogCandidate.linearVersion;
|
|
1067
|
+
queryContract.recordCatalog(session, catalogCandidate.versions);
|
|
1115
1068
|
sm.saveSessionFile(session);
|
|
1116
|
-
|
|
1069
|
+
catalogCandidate = null;
|
|
1117
1070
|
}
|
|
1118
1071
|
}
|
|
1119
1072
|
// (getContextUsage moved to processSDKMessage result handler -- fire-and-forget)
|
|
1120
1073
|
// Stream ended normally after a task stop — no "result" message was sent,
|
|
1121
1074
|
// so the session is still marked as processing. Send interrupted feedback.
|
|
1122
1075
|
console.log("[sdk-bridge] processQueryStream ended: isProcessing=" + session.isProcessing + " taskStopRequested=" + session.taskStopRequested);
|
|
1123
|
-
var stillOwnsRuntime = session.queryInstance === myQueryInstance;
|
|
1076
|
+
var stillOwnsRuntime = session.queryInstance === myQueryInstance && !responseRecovery.stopping(session);
|
|
1124
1077
|
settleContinuationStartup(session, myQueryInstance, myQueryGeneration, false, "The successor query ended before initialization.");
|
|
1125
1078
|
if (session.isProcessing && session.taskStopRequested && stillOwnsRuntime) {
|
|
1126
1079
|
session._lastTurnInterrupted = true;
|
|
@@ -1131,9 +1084,7 @@ function createSDKBridge(opts) {
|
|
|
1131
1084
|
onProcessingChanged();
|
|
1132
1085
|
send({ type: "status", processing: false });
|
|
1133
1086
|
sendAndRecord(session, { type: "thinking_stop" });
|
|
1134
|
-
var interruptMsg = (
|
|
1135
|
-
? "\u25a0 Conversation interrupted - tell the model what to do differently."
|
|
1136
|
-
: "Interrupted \u00b7 What should Claude do instead?";
|
|
1087
|
+
var interruptMsg = (queryContract && queryContract.interruptionMessage) || "■ Conversation interrupted - tell the model what to do differently.";
|
|
1137
1088
|
sendAndRecord(session, { type: "info", text: interruptMsg });
|
|
1138
1089
|
sendAndRecord(session, { type: "done", code: 0 });
|
|
1139
1090
|
sm.broadcastSessionList();
|
|
@@ -1158,7 +1109,7 @@ function createSDKBridge(opts) {
|
|
|
1158
1109
|
}
|
|
1159
1110
|
} catch (err) {
|
|
1160
1111
|
settleContinuationStartup(session, myQueryInstance, myQueryGeneration, false, err.message || "The successor query failed before initialization.");
|
|
1161
|
-
if (session.isProcessing && session.queryInstance === myQueryInstance) {
|
|
1112
|
+
if (session.isProcessing && session.queryInstance === myQueryInstance && !responseRecovery.stopping(session)) {
|
|
1162
1113
|
session.isProcessing = false;
|
|
1163
1114
|
session._awaitingTurnResult = false;
|
|
1164
1115
|
session._queuedTurnCount = 0;
|
|
@@ -1168,9 +1119,7 @@ function createSDKBridge(opts) {
|
|
|
1168
1119
|
session._lastTurnInterrupted = true;
|
|
1169
1120
|
if (!session.destroying) {
|
|
1170
1121
|
sendAndRecord(session, { type: "thinking_stop" });
|
|
1171
|
-
var interruptMsg2 = (
|
|
1172
|
-
? "\u25a0 Conversation interrupted - tell the model what to do differently."
|
|
1173
|
-
: "Interrupted \u00b7 What should Claude do instead?";
|
|
1122
|
+
var interruptMsg2 = (queryContract && queryContract.interruptionMessage) || "■ Conversation interrupted - tell the model what to do differently.";
|
|
1174
1123
|
sendAndRecord(session, { type: "info", text: interruptMsg2 });
|
|
1175
1124
|
sendAndRecord(session, { type: "done", code: 0 });
|
|
1176
1125
|
}
|
|
@@ -1186,21 +1135,17 @@ function createSDKBridge(opts) {
|
|
|
1186
1135
|
console.error("[sdk-bridge] Query stream error for session " + session.localId + ":", errDetail);
|
|
1187
1136
|
console.error("[sdk-bridge] Stack:", err.stack || "(no stack)");
|
|
1188
1137
|
|
|
1189
|
-
|
|
1190
|
-
var isExitCode1 = err.exitCode === 1 || (err.message && err.message.indexOf("exited with code 1") !== -1);
|
|
1191
|
-
var conflicts = isExitCode1 ? findConflictingClaude() : [];
|
|
1138
|
+
var conflicts = findConflictingProcesses(session, err);
|
|
1192
1139
|
if (conflicts.length > 0) {
|
|
1193
|
-
console.error("[sdk-bridge] Found " + conflicts.length + " conflicting
|
|
1140
|
+
console.error("[sdk-bridge] Found " + conflicts.length + " conflicting provider process(es):", conflicts.map(function(c) { return "PID " + c.pid; }).join(", "));
|
|
1194
1141
|
sendAndRecord(session, {
|
|
1195
1142
|
type: "process_conflict",
|
|
1196
|
-
text: "Another
|
|
1143
|
+
text: "Another provider process is already running in this project.",
|
|
1197
1144
|
processes: conflicts,
|
|
1198
1145
|
});
|
|
1199
1146
|
} else {
|
|
1200
1147
|
var errLower = errDetail.toLowerCase();
|
|
1201
|
-
var isContextOverflow =
|
|
1202
|
-
|| errLower.indexOf("context_length") !== -1
|
|
1203
|
-
|| errLower.indexOf("maximum context length") !== -1;
|
|
1148
|
+
var isContextOverflow = require("./yoke/errors").contextOverflow(errDetail);
|
|
1204
1149
|
var isAuthError = isAuthErrorMessage(errDetail);
|
|
1205
1150
|
if (isContextOverflow) {
|
|
1206
1151
|
sendAndRecord(session, {
|
|
@@ -1247,7 +1192,7 @@ function createSDKBridge(opts) {
|
|
|
1247
1192
|
// chat message already sent above
|
|
1248
1193
|
}
|
|
1249
1194
|
} else {
|
|
1250
|
-
sendAndRecord(session, { type: "error", text: "
|
|
1195
|
+
sendAndRecord(session, { type: "error", text: "Provider process error: " + err.message });
|
|
1251
1196
|
}
|
|
1252
1197
|
}
|
|
1253
1198
|
sendAndRecord(session, { type: "done", code: 1 });
|
|
@@ -1272,7 +1217,8 @@ function createSDKBridge(opts) {
|
|
|
1272
1217
|
}
|
|
1273
1218
|
if (session.messageQueue === myMessageQueue) session.messageQueue = null;
|
|
1274
1219
|
if (session.abortController === myAbortController) session.abortController = null;
|
|
1275
|
-
if (ownsRuntime) {
|
|
1220
|
+
if (ownsRuntime && !responseRecovery.stopping(session)) {
|
|
1221
|
+
responseRecovery.cancel(session);
|
|
1276
1222
|
session.taskStopRequested = false;
|
|
1277
1223
|
session.pendingPermissions = {};
|
|
1278
1224
|
// Preserve only restored legacy MCP entries. Canonical Yoke requests
|
|
@@ -1321,7 +1267,7 @@ function createSDKBridge(opts) {
|
|
|
1321
1267
|
}
|
|
1322
1268
|
}
|
|
1323
1269
|
}
|
|
1324
|
-
if (!session.isProcessing && typeof opts.onSessionAvailable === "function") opts.onSessionAvailable(session);
|
|
1270
|
+
if (!responseRecovery.stopping(session) && !session.isProcessing && typeof opts.onSessionAvailable === "function") opts.onSessionAvailable(session);
|
|
1325
1271
|
}
|
|
1326
1272
|
}
|
|
1327
1273
|
|
|
@@ -1329,20 +1275,16 @@ function createSDKBridge(opts) {
|
|
|
1329
1275
|
if (session.queryInstance) return { query: session.queryInstance, isTemp: false, cleanup: function() {} };
|
|
1330
1276
|
|
|
1331
1277
|
var handle;
|
|
1278
|
+
var selectedAdapter = getAdapterForSession(session);
|
|
1332
1279
|
try {
|
|
1333
|
-
handle = await
|
|
1280
|
+
handle = await selectedAdapter.createQuery({
|
|
1334
1281
|
cwd: cwd,
|
|
1335
1282
|
resumeSessionId: session.cliSessionId,
|
|
1336
1283
|
env: getRuntimeEnv(session),
|
|
1337
|
-
adapterOptions: {
|
|
1338
|
-
CLAUDE: {
|
|
1339
|
-
settingSources: ["user", "project", "local"],
|
|
1340
|
-
enableFileCheckpointing: true,
|
|
1341
|
-
},
|
|
1342
|
-
},
|
|
1284
|
+
adapterOptions: require("./yoke/query-options").map(getAdapterForSession(session), { nativePermissionMode: "default" }),
|
|
1343
1285
|
});
|
|
1344
1286
|
} catch (e) {
|
|
1345
|
-
sendAndRecord(session, { type: "error", text: "Failed to load
|
|
1287
|
+
sendAndRecord(session, { type: "error", text: "Failed to load provider session: " + (e.message || e) });
|
|
1346
1288
|
throw e;
|
|
1347
1289
|
}
|
|
1348
1290
|
|
|
@@ -1409,7 +1351,7 @@ function createSDKBridge(opts) {
|
|
|
1409
1351
|
// abort the whole rewind instead of leaving local history trimmed
|
|
1410
1352
|
// ahead of the real, un-rolled-back provider thread.
|
|
1411
1353
|
if (!turnId) {
|
|
1412
|
-
throw new Error("No turn id recorded for this turn; cannot roll back the
|
|
1354
|
+
throw new Error("No turn id recorded for this turn; cannot roll back the provider thread.");
|
|
1413
1355
|
}
|
|
1414
1356
|
await sessionAdapter.rollbackThread(session.cliSessionId, turnId, {
|
|
1415
1357
|
linuxUser: getSessionLinuxUser(session) || undefined,
|
|
@@ -1425,6 +1367,8 @@ function createSDKBridge(opts) {
|
|
|
1425
1367
|
|
|
1426
1368
|
async function forkSessionUnified(session, uuid) {
|
|
1427
1369
|
var sessionAdapter = getAdapterForSession(session);
|
|
1370
|
+
var localHistoryEndIndex = require("./session-fork-history").endIndex(session, uuid,
|
|
1371
|
+
require("./yoke/provider-contract").resolve(sessionAdapter).forkHistoryBoundary);
|
|
1428
1372
|
var result = await sessionAdapter.forkSession(session.cliSessionId, {
|
|
1429
1373
|
upToMessageId: uuid,
|
|
1430
1374
|
dir: cwd,
|
|
@@ -1433,8 +1377,10 @@ function createSDKBridge(opts) {
|
|
|
1433
1377
|
if (!result || !result.sessionId) throw new Error("Fork returned no session id");
|
|
1434
1378
|
|
|
1435
1379
|
// Adapters with rollbackThread (e.g. Codex) use local history copy
|
|
1436
|
-
if (typeof sessionAdapter.rollbackThread === "function") {
|
|
1437
|
-
|
|
1380
|
+
if (result.useLocalHistory === true || typeof sessionAdapter.rollbackThread === "function") {
|
|
1381
|
+
var localFork = { sessionId: result.sessionId, useLocalHistory: true };
|
|
1382
|
+
if (localHistoryEndIndex !== undefined) localFork.localHistoryEndIndex = localHistoryEndIndex;
|
|
1383
|
+
return localFork;
|
|
1438
1384
|
}
|
|
1439
1385
|
// Claude: read history from CLI session files
|
|
1440
1386
|
return { sessionId: result.sessionId, useLocalHistory: false };
|
|
@@ -1442,22 +1388,69 @@ function createSDKBridge(opts) {
|
|
|
1442
1388
|
|
|
1443
1389
|
// Wrapper: marks the boot window so pushMessage can buffer instead of
|
|
1444
1390
|
// dropping messages that arrive while createQuery is still awaiting.
|
|
1445
|
-
async function startQuery(session, text, images, linuxUser, beforePush, onAccepted) {
|
|
1391
|
+
async function startQuery(session, text, images, linuxUser, beforePush, onAccepted, retryState) {
|
|
1392
|
+
if (opts.isLifecycleExecutionPaused && opts.isLifecycleExecutionPaused()) {
|
|
1393
|
+
sendAndRecord(session, { type: "error", text: "Project execution is paused for lifecycle recovery. Reconcile the saved operation, or send a new owner message after restoring the registration." });
|
|
1394
|
+
session.isProcessing = false; onProcessingChanged(); sendAndRecord(session, { type: "done", code: 1 }); return false;
|
|
1395
|
+
}
|
|
1396
|
+
if (session._responseRecoveryStopPending && !retryState) {
|
|
1397
|
+
session.isProcessing = false;
|
|
1398
|
+
onProcessingChanged();
|
|
1399
|
+
sendAndRecord(session, { type: "error", text: "The previous Claude attempt has not confirmed stopped. Check the connection before sending this message again." });
|
|
1400
|
+
sendAndRecord(session, { type: "done", code: 1 });
|
|
1401
|
+
return false;
|
|
1402
|
+
}
|
|
1403
|
+
if (responseRecovery.stopping(session) && !retryState) return false;
|
|
1446
1404
|
delete session._lastTurnInterrupted;
|
|
1405
|
+
var payload = { text: text, images: images, linuxUser: linuxUser, beforePush: beforePush };
|
|
1406
|
+
var recoveryState = responseRecovery.begin(session, payload, retryState);
|
|
1407
|
+
if (recoveryState) recoveryState.handle = null;
|
|
1408
|
+
var guardedPush = function() {
|
|
1409
|
+
return !session.destroying && !session.taskStopRequested
|
|
1410
|
+
&& (!recoveryState || responseRecovery.valid(session, recoveryState) && !recoveryState.stopping)
|
|
1411
|
+
&& (typeof beforePush !== "function" || beforePush() === true);
|
|
1412
|
+
};
|
|
1413
|
+
guardedPush.exactProductDelivery = !!(beforePush && beforePush.exactProductDelivery);
|
|
1447
1414
|
session._queryGeneration = (session._queryGeneration || 0) + 1;
|
|
1448
1415
|
session._queryStarting = true;
|
|
1416
|
+
var starting = startQueryInner(session, text, images, linuxUser, guardedPush, onAccepted, recoveryState);
|
|
1417
|
+
if (recoveryState) recoveryState.starting = starting;
|
|
1449
1418
|
try {
|
|
1450
|
-
|
|
1419
|
+
var accepted = await starting;
|
|
1420
|
+
if (accepted === false && (!recoveryState || !recoveryState.stopping)) {
|
|
1421
|
+
responseRecovery.cancel(session);
|
|
1422
|
+
session.isProcessing = false;
|
|
1423
|
+
onProcessingChanged();
|
|
1424
|
+
}
|
|
1425
|
+
return accepted;
|
|
1426
|
+
} catch (error) {
|
|
1427
|
+
// Includes synchronous input queue failures, before stream consumption.
|
|
1428
|
+
var failedHandle = session.queryInstance;
|
|
1429
|
+
if (failedHandle) {
|
|
1430
|
+
try { if (typeof failedHandle.abort === "function") failedHandle.abort(); } catch (e) {}
|
|
1431
|
+
try { if (typeof failedHandle.close === "function") failedHandle.close(); } catch (e) {}
|
|
1432
|
+
}
|
|
1433
|
+
session.queryInstance = null;
|
|
1434
|
+
session.abortController = null;
|
|
1435
|
+
session.messageQueue = null;
|
|
1436
|
+
session.isProcessing = false;
|
|
1437
|
+
session._awaitingTurnResult = false;
|
|
1438
|
+
session._queuedTurnCount = 0;
|
|
1439
|
+
taskLifecycle.clearAll(session);
|
|
1440
|
+
if (!recoveryState || !recoveryState.stopping) {
|
|
1441
|
+
responseRecovery.cancel(session);
|
|
1442
|
+
sendAndRecord(session, { type: "error", text: "The agent connection failed while delivering your message. Please retry or check the connection." });
|
|
1443
|
+
sendAndRecord(session, { type: "done", code: 1 });
|
|
1444
|
+
onProcessingChanged();
|
|
1445
|
+
sm.broadcastSessionList();
|
|
1446
|
+
}
|
|
1447
|
+
return false;
|
|
1451
1448
|
} finally {
|
|
1452
1449
|
session._queryStarting = false;
|
|
1453
|
-
|
|
1454
|
-
|
|
1455
|
-
|
|
1456
|
-
|
|
1457
|
-
session.pendingPush = [];
|
|
1458
|
-
}
|
|
1459
|
-
if (!session.queryInstance && !session.isProcessing) session.taskStopRequested = false;
|
|
1460
|
-
if (!session.isProcessing && typeof opts.onSessionAvailable === "function") opts.onSessionAvailable(session);
|
|
1450
|
+
delete session._providerRecoveryWaiting;
|
|
1451
|
+
if (!session.queryInstance && session.pendingPush && session.pendingPush.length) session.pendingPush = [];
|
|
1452
|
+
if (!session.queryInstance && !session.isProcessing && !session._pendingMessageDrainPaused && !responseRecovery.stopping(session)) session.taskStopRequested = false;
|
|
1453
|
+
if (!responseRecovery.stopping(session) && !session.isProcessing && typeof opts.onSessionAvailable === "function") opts.onSessionAvailable(session);
|
|
1461
1454
|
}
|
|
1462
1455
|
}
|
|
1463
1456
|
|
|
@@ -1501,7 +1494,7 @@ function createSDKBridge(opts) {
|
|
|
1501
1494
|
};
|
|
1502
1495
|
}
|
|
1503
1496
|
|
|
1504
|
-
async function startQueryInner(session, text, images, linuxUser, beforePush, onAccepted) {
|
|
1497
|
+
async function startQueryInner(session, text, images, linuxUser, beforePush, onAccepted, recoveryState) {
|
|
1505
1498
|
var sessionRuntimeEnv = getRuntimeEnv(session);
|
|
1506
1499
|
var resumedAtQueryStart = !!session.cliSessionId;
|
|
1507
1500
|
async function ensureVendorReady(vendor) {
|
|
@@ -1653,7 +1646,8 @@ function createSDKBridge(opts) {
|
|
|
1653
1646
|
|
|
1654
1647
|
// Ensure Linux user project directory exists (runs in parallel with worker boot)
|
|
1655
1648
|
if (linuxUser) {
|
|
1656
|
-
|
|
1649
|
+
var preparation = require("./yoke/provider-contract").resolve(sessionAdapter).prepareIsolation;
|
|
1650
|
+
if (typeof preparation === "function") preparation(linuxUser, session, cwd);
|
|
1657
1651
|
}
|
|
1658
1652
|
|
|
1659
1653
|
session.blocks = {};
|
|
@@ -1670,100 +1664,27 @@ function createSDKBridge(opts) {
|
|
|
1670
1664
|
session.abortController = new AbortController();
|
|
1671
1665
|
}
|
|
1672
1666
|
|
|
1673
|
-
// Build Claude-specific adapter options
|
|
1674
|
-
var claudeOpts = {
|
|
1675
|
-
settingSources: ["user", "project", "local"],
|
|
1676
|
-
includePartialMessages: true,
|
|
1677
|
-
enableFileCheckpointing: true,
|
|
1678
|
-
extraArgs: { "replay-user-messages": null },
|
|
1679
|
-
promptSuggestions: true,
|
|
1680
|
-
agentProgressSummaries: true,
|
|
1681
|
-
};
|
|
1682
|
-
|
|
1683
|
-
// Per-loop settings override global defaults when present
|
|
1684
1667
|
var ls = session.loopSettings || {};
|
|
1685
|
-
|
|
1686
|
-
|
|
1687
|
-
|
|
1688
|
-
|
|
1689
|
-
var thinkingMode = ls.thinking || sm.currentThinking;
|
|
1690
|
-
if (thinkingMode === "disabled") {
|
|
1691
|
-
claudeOpts.thinking = { type: "disabled" };
|
|
1692
|
-
} else if (thinkingMode === "budget") {
|
|
1693
|
-
var budgetTokens = ls.thinkingBudget || sm.currentThinkingBudget;
|
|
1694
|
-
if (budgetTokens) claudeOpts.thinking = { type: "enabled", budgetTokens: budgetTokens };
|
|
1695
|
-
} else {
|
|
1696
|
-
// Adaptive (the default). Request summarized display explicitly:
|
|
1697
|
-
// current models default thinking.display to "omitted", which streams
|
|
1698
|
-
// thinking blocks whose text is an EMPTY string -- the UI's thinking
|
|
1699
|
-
// section stays blank even though thinking happens and is billed.
|
|
1700
|
-
// (SDK ThinkingAdaptive: { type: "adaptive", display?: "summarized" | "omitted" })
|
|
1701
|
-
claudeOpts.thinking = { type: "adaptive", display: "summarized" };
|
|
1702
|
-
}
|
|
1703
|
-
|
|
1704
|
-
if (ls.permissionMode) {
|
|
1705
|
-
session._loopPermissionMode = ls.permissionMode;
|
|
1706
|
-
}
|
|
1707
|
-
|
|
1708
|
-
// Pass through any extra SDK settings from LOOP.json
|
|
1709
|
-
if (ls.disableAllHooks !== undefined) {
|
|
1710
|
-
claudeOpts.settings = Object.assign({}, claudeOpts.settings || {}, { disableAllHooks: ls.disableAllHooks });
|
|
1711
|
-
}
|
|
1712
|
-
|
|
1713
|
-
if (dangerouslySkipPermissions || (session.mode === "tui" && session.dangerouslySkipPermissions)) {
|
|
1714
|
-
claudeOpts.allowDangerouslySkipPermissions = true;
|
|
1715
|
-
claudeOpts.permissionMode = "bypassPermissions";
|
|
1716
|
-
} else {
|
|
1717
|
-
var globalMode = session.permissionMode || sm.currentPermissionMode || "default";
|
|
1718
|
-
var effectiveDefault;
|
|
1719
|
-
// GUI full access stays inside Clay's canUseTool callback. Passing the
|
|
1720
|
-
// SDK bypass mode would require its process-level dangerous escape hatch
|
|
1721
|
-
// and would skip Clay's permission policy entirely.
|
|
1722
|
-
if (globalMode === "bypassPermissions") effectiveDefault = "default";
|
|
1723
|
-
else if (session.acceptEditsAfterStart) effectiveDefault = "acceptEdits";
|
|
1724
|
-
else effectiveDefault = globalMode;
|
|
1725
|
-
var modeToApply = session._loopPermissionMode || effectiveDefault;
|
|
1726
|
-
// Always set permissionMode explicitly, including "default". SDK
|
|
1727
|
-
// 0.3.286+ leaves an omitted permissionMode to Claude Code itself,
|
|
1728
|
-
// which can apply a settings defaultMode or start in auto mode on
|
|
1729
|
-
// third-party providers / with telemetry off -- silently widening
|
|
1730
|
-
// past Clay's Ask policy. Sending "default" keeps the SDK's own
|
|
1731
|
-
// decision point at the same "default" behavior Clay has always run
|
|
1732
|
-
// under: a tool the SDK's own allowed/denied rules or allowedTools
|
|
1733
|
-
// list already settles is not re-asked, but anything left undecided
|
|
1734
|
-
// still reaches Clay's canUseTool callback, as before.
|
|
1735
|
-
claudeOpts.permissionMode = modeToApply || "default";
|
|
1736
|
-
}
|
|
1737
|
-
if (session.youCurator) {
|
|
1738
|
-
claudeOpts.permissionMode = "default";
|
|
1739
|
-
claudeOpts.allowDangerouslySkipPermissions = false;
|
|
1740
|
-
}
|
|
1741
|
-
// Clear one-shot acceptEditsAfterStart regardless of which branch ran above,
|
|
1742
|
-
// so the flag does not linger into subsequent turns.
|
|
1743
|
-
if (session.acceptEditsAfterStart) delete session.acceptEditsAfterStart;
|
|
1744
|
-
if (session.cliSessionId && session.lastRewindUuid) {
|
|
1745
|
-
claudeOpts.resumeSessionAt = session.lastRewindUuid;
|
|
1746
|
-
delete session.lastRewindUuid;
|
|
1747
|
-
sm.saveSessionFile(session);
|
|
1748
|
-
}
|
|
1749
|
-
|
|
1750
|
-
// Pass linuxUser to adapter for worker-based queries
|
|
1668
|
+
if (ls.permissionMode) session._loopPermissionMode = ls.permissionMode;
|
|
1669
|
+
var permissionMode = session.permissionMode || sm.currentPermissionMode || "default";
|
|
1670
|
+
var nativeMode = permissionMode === "bypassPermissions" ? "default" : session.acceptEditsAfterStart ? "acceptEdits" : permissionMode;
|
|
1671
|
+
var isolationHome = null;
|
|
1751
1672
|
if (linuxUser) {
|
|
1752
|
-
|
|
1753
|
-
|
|
1754
|
-
|
|
1755
|
-
|
|
1756
|
-
|
|
1757
|
-
|
|
1758
|
-
}
|
|
1759
|
-
|
|
1760
|
-
|
|
1761
|
-
|
|
1762
|
-
|
|
1763
|
-
|
|
1764
|
-
|
|
1765
|
-
|
|
1766
|
-
|
|
1673
|
+
try { isolationHome = require("./os-users").resolveOsUserInfo(linuxUser).home; } catch (error) {}
|
|
1674
|
+
}
|
|
1675
|
+
var executionIntent = {
|
|
1676
|
+
settings: sm, permissionMode: permissionMode, nativePermissionMode: session._loopPermissionMode || nativeMode,
|
|
1677
|
+
nativeBypass: dangerouslySkipPermissions || session.mode === "tui" && session.dangerouslySkipPermissions,
|
|
1678
|
+
readOnly: !!session.youCurator, betas: sm.currentBetas,
|
|
1679
|
+
thinking: { mode: ls.thinking || sm.currentThinking, budget: ls.thinkingBudget || sm.currentThinkingBudget },
|
|
1680
|
+
disableHooks: ls.disableAllHooks, resumeAt: session.cliSessionId && session.lastRewindUuid || undefined,
|
|
1681
|
+
singleTurn: !!session.singleTurn, startedAt: t0,
|
|
1682
|
+
isolation: { user: linuxUser, home: isolationHome, projectPath: session.cwd || null, workerState: session._adapterWorkerState },
|
|
1683
|
+
sessionBridge: null,
|
|
1684
|
+
};
|
|
1685
|
+
if (session.acceptEditsAfterStart) delete session.acceptEditsAfterStart;
|
|
1686
|
+
if (executionIntent.resumeAt) { delete session.lastRewindUuid; sm.saveSessionFile(session); }
|
|
1687
|
+
if (linuxUser && session._adapterWorkerState) session._adapterWorkerState = null;
|
|
1767
1688
|
|
|
1768
1689
|
// Pick a model from the session or its vendor-specific default, then
|
|
1769
1690
|
// validate it against the session vendor's known model list.
|
|
@@ -1789,20 +1710,21 @@ function createSDKBridge(opts) {
|
|
|
1789
1710
|
sm.saveSessionFile(session);
|
|
1790
1711
|
}
|
|
1791
1712
|
|
|
1792
|
-
var codexConfig = getCodexConfig(sm);
|
|
1793
|
-
var kiroConfig = getKiroConfig(sm);
|
|
1794
1713
|
session._sdkQueryGeneration = Number(session._sdkQueryGeneration || 0) + 1;
|
|
1795
1714
|
// Individual feature modules own their transport capability checks. Do not
|
|
1796
1715
|
// suppress unrelated session tools merely because one feature cannot be
|
|
1797
1716
|
// delivered by this provider.
|
|
1798
1717
|
var sessionToolDefs = getSessionToolDefs(session) || [];
|
|
1799
1718
|
var queryGeneration = Number(session._sdkQueryGeneration || 0);
|
|
1719
|
+
executionIntent.sessionBridge = getAcpMcpServers(session);
|
|
1720
|
+
var queryContract = yoke.sessionTools.contract(sessionAdapter);
|
|
1721
|
+
function needsCatalogRecovery(family, version) {
|
|
1722
|
+
return yoke.sessionTools.needsRecovery(sessionAdapter, session, family, version);
|
|
1723
|
+
}
|
|
1800
1724
|
var hasYouCatalog = sessionToolDefs.some(function (tool) { return tool.name === "search_user_knowledge"; });
|
|
1801
|
-
var
|
|
1802
|
-
&& hasYouCatalog && Number(session.codexYouToolCatalogVersion || 0) < 1;
|
|
1725
|
+
var recoverYouTools = needsCatalogRecovery("knowledge", 1) && hasYouCatalog;
|
|
1803
1726
|
var hasLinearCatalog = sessionToolDefs.some(function (tool) { return tool.name === "link_session_linear"; });
|
|
1804
|
-
var
|
|
1805
|
-
&& hasLinearCatalog && Number(session.codexLinearToolCatalogVersion || 0) < 1 && canUseSessionTools(session) === true;
|
|
1727
|
+
var recoverLinearTools = needsCatalogRecovery("linear", 1) && hasLinearCatalog && canUseSessionTools(session) === true;
|
|
1806
1728
|
var hasIssueCatalog = false;
|
|
1807
1729
|
for (var issueToolIndex = 0; issueToolIndex < sessionToolDefs.length; issueToolIndex++) {
|
|
1808
1730
|
if (sessionToolDefs[issueToolIndex].name === "create_issue") {
|
|
@@ -1811,24 +1733,26 @@ function createSDKBridge(opts) {
|
|
|
1811
1733
|
}
|
|
1812
1734
|
}
|
|
1813
1735
|
var hasSharedBrowserCatalog = sessionToolDefs.some(function (definition) { return definition.name === "shared_browser"; });
|
|
1814
|
-
var
|
|
1815
|
-
|
|
1816
|
-
var
|
|
1817
|
-
|
|
1818
|
-
|
|
1819
|
-
&& Number(session.codexIssuesToolCatalogVersion || 0) < 1;
|
|
1736
|
+
var recoverBrowserTools = needsCatalogRecovery("browser", 6) && hasSharedBrowserCatalog;
|
|
1737
|
+
var recoverIssueTools = needsCatalogRecovery("issues", 1) && hasIssueCatalog;
|
|
1738
|
+
var notesCatalogVersion = require("./session-notes-mcp-server").CATALOG_VERSION;
|
|
1739
|
+
var hasNotesCatalog = sessionToolDefs.some(function (definition) { return definition.name === "write_note"; });
|
|
1740
|
+
var recoverNoteTools = needsCatalogRecovery("notes", notesCatalogVersion) && hasNotesCatalog;
|
|
1820
1741
|
function queryContextAvailable() {
|
|
1742
|
+
if (queryRetired()) return false;
|
|
1821
1743
|
if (Number(session._sdkQueryGeneration || 0) !== queryGeneration) return false;
|
|
1822
1744
|
if (sm && sm.sessions && typeof sm.sessions.get === "function" && sm.sessions.get(session.localId) !== session) return false;
|
|
1823
1745
|
return canUseSessionTools(session) === true;
|
|
1824
1746
|
}
|
|
1747
|
+
var hasMateScheduleTool = sessionToolDefs.some(function (tool) { return yoke.sessionTools.MATE_SCHEDULE_TOOLS.indexOf(tool.name) !== -1; });
|
|
1748
|
+
var recoverMateSchedules = needsCatalogRecovery() && hasMateScheduleTool && queryContextAvailable();
|
|
1825
1749
|
var hasScheduleTool = false;
|
|
1826
1750
|
var hasScheduleInterviewTool = false;
|
|
1827
1751
|
var scheduleInterviewActive = null;
|
|
1828
1752
|
var scheduleQuestionLimit = null;
|
|
1829
1753
|
for (var sessionToolIndex = 0; sessionToolIndex < sessionToolDefs.length; sessionToolIndex++) {
|
|
1830
1754
|
if (yoke.sessionTools.SCHEDULE_TOOLS.indexOf(sessionToolDefs[sessionToolIndex].name) !== -1) hasScheduleTool = true;
|
|
1831
|
-
if (sessionToolDefs[sessionToolIndex].name
|
|
1755
|
+
if (["begin_scheduled_task_interview", "begin_mate_schedule_interview", "begin_schedule_control_interview"].indexOf(sessionToolDefs[sessionToolIndex].name) >= 0) {
|
|
1832
1756
|
hasScheduleInterviewTool = true;
|
|
1833
1757
|
scheduleInterviewActive = sessionToolDefs[sessionToolIndex].scheduleInterviewActive || null;
|
|
1834
1758
|
scheduleQuestionLimit = sessionToolDefs[sessionToolIndex].structuredQuestionLimit || null;
|
|
@@ -1838,10 +1762,10 @@ function createSDKBridge(opts) {
|
|
|
1838
1762
|
var activeLoopInterview = !isDriverOperatedSession(session) && !session.loopInterviewHandoff && !activeRun && !!loopInterview.activeInterviewId(session);
|
|
1839
1763
|
var structuredInputSession = hasScheduleInterviewTool || activeLoopInterview || (!isDriverOperatedSession(session) && session.ralphCraftingMode === true && session.loop && session.loop.role === "crafting");
|
|
1840
1764
|
var requestedUserInputMode = session.debateSetupMode || session.mateCreationMode ? "fallback" : "auto";
|
|
1841
|
-
if (structuredInputSession
|
|
1765
|
+
if (structuredInputSession) requestedUserInputMode = "fallback";
|
|
1766
|
+
if (requestedUserInputMode === "auto" && queryContract.defaultUserInputMode) requestedUserInputMode = queryContract.defaultUserInputMode;
|
|
1842
1767
|
var selectedUserInputMode = yoke.userInput.selectMode(sessionAdapter, requestedUserInputMode);
|
|
1843
|
-
var
|
|
1844
|
-
&& Number(session.codexUserInputToolCatalogVersion || 0) < 1 && queryContextAvailable();
|
|
1768
|
+
var recoverQuestionTools = needsCatalogRecovery("questions", 1) && queryContextAvailable();
|
|
1845
1769
|
function structuredInputContextAvailable() {
|
|
1846
1770
|
if (!queryContextAvailable()) return false;
|
|
1847
1771
|
// A schedule-triggered fallback shares the schedule feature's live
|
|
@@ -1860,9 +1784,10 @@ function createSDKBridge(opts) {
|
|
|
1860
1784
|
return "Ask exactly one question at a time, wait for the answer, then ask the next question.";
|
|
1861
1785
|
}
|
|
1862
1786
|
var sessionUserInputHandler = function(request, respond) {
|
|
1863
|
-
if (!structuredInputContextAvailable()) {
|
|
1787
|
+
if (queryRetired() || !structuredInputContextAvailable()) {
|
|
1864
1788
|
return respond.cancel("This structured-input request belongs to an unavailable or older query.");
|
|
1865
1789
|
}
|
|
1790
|
+
responseRecovery.progress(session);
|
|
1866
1791
|
var questionError = scheduleQuestionError(request);
|
|
1867
1792
|
if (questionError) return respond.cancel(questionError);
|
|
1868
1793
|
if (request.presentation === "elicitation" && request.diagnostics && request.diagnostics.elicitation) {
|
|
@@ -1882,21 +1807,33 @@ function createSDKBridge(opts) {
|
|
|
1882
1807
|
return opts.onUserInputRequest(session, request, respond);
|
|
1883
1808
|
};
|
|
1884
1809
|
var localMcpServers = getMcpServers(session);
|
|
1885
|
-
if (
|
|
1810
|
+
if (queryContract.toolTransport === "sdk-mcp" && (hasScheduleTool || hasMateScheduleTool)
|
|
1811
|
+
&& typeof sessionAdapter.createToolServer !== "function") {
|
|
1812
|
+
throw new Error("The adapter cannot mount native schedule tools without createToolServer.");
|
|
1813
|
+
}
|
|
1814
|
+
if (queryContract.toolTransport === "sdk-mcp" && hasScheduleTool) {
|
|
1886
1815
|
var scheduledTaskToolDefs = [];
|
|
1887
1816
|
for (var scheduledToolIndex = 0; scheduledToolIndex < sessionToolDefs.length; scheduledToolIndex++) {
|
|
1888
1817
|
if (yoke.sessionTools.SCHEDULE_TOOLS.indexOf(sessionToolDefs[scheduledToolIndex].name) !== -1) scheduledTaskToolDefs.push(sessionToolDefs[scheduledToolIndex]);
|
|
1889
1818
|
}
|
|
1890
1819
|
if (scheduledTaskToolDefs.length) {
|
|
1891
1820
|
var scheduledTaskServer = sessionAdapter.createToolServer({ name: "clay-scheduled-tasks", version: "1.0.0", tools: scheduledTaskToolDefs });
|
|
1892
|
-
if (scheduledTaskServer)
|
|
1893
|
-
|
|
1894
|
-
|
|
1895
|
-
}
|
|
1821
|
+
if (!scheduledTaskServer) throw new Error("The adapter could not mount scheduled-task tools.");
|
|
1822
|
+
localMcpServers = Object.assign({}, localMcpServers || {});
|
|
1823
|
+
localMcpServers["clay-scheduled-tasks"] = scheduledTaskServer;
|
|
1896
1824
|
}
|
|
1897
1825
|
}
|
|
1826
|
+
if (queryContract.toolTransport === "sdk-mcp" && hasMateScheduleTool) {
|
|
1827
|
+
localMcpServers = Object.assign({}, localMcpServers || {});
|
|
1828
|
+
localMcpServers["clay-mate-schedules"] = sessionAdapter.createToolServer({ name: "clay-mate-schedules", version: "1.0.0",
|
|
1829
|
+
tools: sessionToolDefs.filter(function (tool) { return yoke.sessionTools.MATE_SCHEDULE_TOOLS.indexOf(tool.name) !== -1; }) });
|
|
1830
|
+
if (!localMcpServers["clay-mate-schedules"]) throw new Error("The adapter could not mount Mate schedule tools.");
|
|
1831
|
+
}
|
|
1898
1832
|
if (selectedUserInputMode === "fallback") {
|
|
1899
1833
|
var userInputServer = yoke.userInput.createFallbackServer(sessionAdapter, sessionUserInputHandler, { force: true, maxQuestions: scheduleQuestionLimit });
|
|
1834
|
+
if (queryContract.toolTransport === "sdk-mcp" && !userInputServer) {
|
|
1835
|
+
throw new Error("The adapter could not mount structured-input tools.");
|
|
1836
|
+
}
|
|
1900
1837
|
if (userInputServer) {
|
|
1901
1838
|
localMcpServers = Object.assign({}, localMcpServers || {});
|
|
1902
1839
|
localMcpServers[userInputServer.name || "yoke-user-input"] = userInputServer;
|
|
@@ -1931,6 +1868,12 @@ function createSDKBridge(opts) {
|
|
|
1931
1868
|
return snapshotDef;
|
|
1932
1869
|
}
|
|
1933
1870
|
|
|
1871
|
+
var externalQueryBridge = require('./mcp-query-bridge').createQueryBridge({ valid: queryContextAvailable,
|
|
1872
|
+
getServers: function () { return getRemoteMcpServers ? getRemoteMcpServers(session) || {} : {}; } });
|
|
1873
|
+
var externalToolDefs = queryContract.externalToolTransport === "dynamic" ? externalQueryBridge.dynamicDefs() : [];
|
|
1874
|
+
if (externalToolDefs.length) { sessionToolDefs = sessionToolDefs.concat(externalToolDefs); queryToolSnapshots.set(session, { generation: queryGeneration, defs: sessionToolDefs.slice() }); }
|
|
1875
|
+
var recoverExternalTools = needsCatalogRecovery() && (externalToolDefs.length > 0 || isMate);
|
|
1876
|
+
|
|
1934
1877
|
// Give fresh queries an immediate provisional label. The visible user
|
|
1935
1878
|
// message in history wins over `text`, which may contain an internal
|
|
1936
1879
|
// provider wrapper rather than what the person typed.
|
|
@@ -1945,6 +1888,10 @@ function createSDKBridge(opts) {
|
|
|
1945
1888
|
}
|
|
1946
1889
|
|
|
1947
1890
|
var modelSwitchGeneration = session._queryGeneration;
|
|
1891
|
+
function queryRetired() {
|
|
1892
|
+
return Number(session._sdkQueryGeneration || 0) !== queryGeneration || session.taskStopRequested
|
|
1893
|
+
|| session.destroying || responseRecovery.stopping(session) || (handle && session.queryInstance !== handle);
|
|
1894
|
+
}
|
|
1948
1895
|
var queryOpts = {
|
|
1949
1896
|
onModelSwitch: function(change) {
|
|
1950
1897
|
if (session._queryGeneration !== modelSwitchGeneration || session.taskStopRequested) return;
|
|
@@ -1959,7 +1906,7 @@ function createSDKBridge(opts) {
|
|
|
1959
1906
|
clayBridgeToken: clayBridgeToken,
|
|
1960
1907
|
linuxUser: linuxUser || undefined,
|
|
1961
1908
|
env: sessionRuntimeEnv,
|
|
1962
|
-
skillOptions: getSessionSkillOptions(session),
|
|
1909
|
+
skillOptions: require("./session-skill-scope").bind(session, sm.sessions, getSessionSkillOptions(session), queryContextAvailable, usersModule.isMultiUser()),
|
|
1963
1910
|
// appendSystemPrompt, NOT systemPrompt: a plain-string systemPrompt
|
|
1964
1911
|
// REPLACES the entire Claude Code system prompt (sdk.d.ts:2096), which
|
|
1965
1912
|
// would strip the driver session down to the two-sentence pair preset.
|
|
@@ -1967,7 +1914,7 @@ function createSDKBridge(opts) {
|
|
|
1967
1914
|
// codex/kiro: prepend to the first message).
|
|
1968
1915
|
appendSystemPrompt: [
|
|
1969
1916
|
typeof opts.getSessionSystemPrompt === "function" ? opts.getSessionSystemPrompt(session) : "",
|
|
1970
|
-
|
|
1917
|
+
typeof queryContract.questionGuidance === "function" && queryContextAvailable() ? queryContract.questionGuidance() : "",
|
|
1971
1918
|
].filter(Boolean).join("\n\n") || undefined,
|
|
1972
1919
|
model: queryModel,
|
|
1973
1920
|
// Effort is remembered per vendor and clamped to the session vendor's
|
|
@@ -1984,10 +1931,22 @@ function createSDKBridge(opts) {
|
|
|
1984
1931
|
toolServers: mergedMcpServers,
|
|
1985
1932
|
toolServerDescriptors: extractMcpDescriptors(mergedMcpServers) || undefined,
|
|
1986
1933
|
dynamicTools: sessionToolDefs,
|
|
1987
|
-
//
|
|
1934
|
+
// Conversation-scoped catalogs persist definitions. A stale authorized Driver
|
|
1988
1935
|
// gets this exact-query bridge; its handlers still reauthorize live.
|
|
1989
|
-
sessionMcpServer: (
|
|
1936
|
+
sessionMcpServer: (recoverMateSchedules || recoverIssueTools || recoverQuestionTools || recoverBrowserTools || recoverLinearTools || recoverYouTools || recoverExternalTools || recoverNoteTools) ? getSessionMcpServer(session, queryGeneration) : undefined,
|
|
1937
|
+
onRecoveryAdmission: function(waiting) {
|
|
1938
|
+
if (!queryContextAvailable()) return;
|
|
1939
|
+
if (waiting) session._providerRecoveryWaiting = queryGeneration;
|
|
1940
|
+
else delete session._providerRecoveryWaiting;
|
|
1941
|
+
},
|
|
1942
|
+
onRecoveryWaiting: function(waiting) {
|
|
1943
|
+
if (!queryContextAvailable()) return;
|
|
1944
|
+
sendAndRecord(session, { type: 'informational', level: 'info', content: waiting
|
|
1945
|
+
? 'Tool recovery is waiting for this conversation’s runtime to become safely available. Your message is retained; Stop cancels the wait.'
|
|
1946
|
+
: 'Tool recovery is ready. Continuing your retained message.' });
|
|
1947
|
+
},
|
|
1990
1948
|
callDynamicTool: function (toolName, args) {
|
|
1949
|
+
if (queryRetired() || !queryContextAvailable()) return Promise.reject(new Error("This session tool query is no longer available."));
|
|
1991
1950
|
var toolDef = findSessionToolDef(toolName);
|
|
1992
1951
|
if (toolDef && typeof toolDef.handler === "function") {
|
|
1993
1952
|
return toolDef.handler(args || {});
|
|
@@ -1997,7 +1956,10 @@ function createSDKBridge(opts) {
|
|
|
1997
1956
|
resumeSessionId: session.cliSessionId || undefined,
|
|
1998
1957
|
abortController: linuxUser ? undefined : session.abortController,
|
|
1999
1958
|
canUseTool: function(toolName, input, toolOpts) {
|
|
2000
|
-
|
|
1959
|
+
if (queryRetired()) return { behavior: "deny", message: "This attempt has stopped." };
|
|
1960
|
+
responseRecovery.progress(session);
|
|
1961
|
+
var questionInput = yoke.userInput.toolQuestions(sessionAdapter, toolName, input);
|
|
1962
|
+
var nativeQuestionError = questionInput ? scheduleQuestionError(questionInput) : null;
|
|
2001
1963
|
if (nativeQuestionError) return { behavior: "deny", message: nativeQuestionError };
|
|
2002
1964
|
var permissionName = toolName;
|
|
2003
1965
|
var permissionToolDef = findSessionToolDef(toolName);
|
|
@@ -2005,7 +1967,10 @@ function createSDKBridge(opts) {
|
|
|
2005
1967
|
return handleCanUseTool(session, permissionName, input, toolOpts);
|
|
2006
1968
|
},
|
|
2007
1969
|
preToolUsePolicy: function(toolName, input) {
|
|
2008
|
-
|
|
1970
|
+
if (queryRetired()) return Promise.resolve({ behavior: "deny", message: "This attempt has stopped." });
|
|
1971
|
+
responseRecovery.progress(session);
|
|
1972
|
+
var questionInput = yoke.userInput.toolQuestions(sessionAdapter, toolName, input);
|
|
1973
|
+
var nativeQuestionError = questionInput ? scheduleQuestionError(questionInput) : null;
|
|
2009
1974
|
if (nativeQuestionError) return Promise.resolve({ behavior: "deny", message: nativeQuestionError });
|
|
2010
1975
|
var permissionName = toolName;
|
|
2011
1976
|
var permissionToolDef = findSessionToolDef(toolName);
|
|
@@ -2018,47 +1983,45 @@ function createSDKBridge(opts) {
|
|
|
2018
1983
|
validateUserInputRequest: scheduleQuestionError,
|
|
2019
1984
|
userInputMode: selectedUserInputMode,
|
|
2020
1985
|
onElicitation: function(request, elicitOpts) {
|
|
1986
|
+
if (queryRetired()) return Promise.resolve({ action: "cancel" });
|
|
1987
|
+
responseRecovery.progress(session);
|
|
2021
1988
|
return handleElicitation(session, request, elicitOpts);
|
|
2022
1989
|
},
|
|
2023
1990
|
onUserDialog: function(dialogRequest, dialogOpts) {
|
|
1991
|
+
if (queryRetired()) return Promise.resolve({ behavior: "cancelled" });
|
|
1992
|
+
responseRecovery.progress(session);
|
|
2024
1993
|
return handleUserDialog(session, dialogRequest, dialogOpts);
|
|
2025
1994
|
},
|
|
2026
1995
|
callMcpTool: function(serverName, toolName, args) {
|
|
1996
|
+
if (queryRetired()) return Promise.reject(new Error("This attempt has stopped."));
|
|
1997
|
+
responseRecovery.progress(session);
|
|
2027
1998
|
return callMcpToolHandler(mergedMcpServers, serverName, toolName, args);
|
|
2028
1999
|
},
|
|
2029
|
-
adapterOptions:
|
|
2030
|
-
CLAUDE: claudeOpts,
|
|
2031
|
-
CODEX: {
|
|
2032
|
-
// Always use "never" (auto-approve) because Clay handles tool
|
|
2033
|
-
// permissions via its own UI (checkToolWhitelist + handleCanUseTool).
|
|
2034
|
-
// Codex's native approval prompts are terminal-based and cannot be
|
|
2035
|
-
// relayed through Clay's web UI, causing MCP tool calls to hang.
|
|
2036
|
-
approvalPolicy: "never",
|
|
2037
|
-
sandboxMode: session.youCurator ? "read-only" : codexConfig.sandbox,
|
|
2038
|
-
webSearchMode: session.youCurator ? "disabled" : codexConfig.webSearch,
|
|
2039
|
-
},
|
|
2040
|
-
ACP: {
|
|
2041
|
-
mcpServers: getAcpMcpServers(session),
|
|
2042
|
-
},
|
|
2043
|
-
ANTIGRAVITY: {
|
|
2044
|
-
dangerouslySkipPermissions: dangerouslySkipPermissions
|
|
2045
|
-
|| session.permissionMode === "bypassPermissions",
|
|
2046
|
-
},
|
|
2047
|
-
KIRO: {
|
|
2048
|
-
engine: kiroConfig.engine,
|
|
2049
|
-
mode: kiroConfig.mode,
|
|
2050
|
-
// ACP accepts additional stdio MCP servers per session. The bridge is
|
|
2051
|
-
// bound to this Clay session so partner calls cannot leak across
|
|
2052
|
-
// concurrent Kiro sessions or users.
|
|
2053
|
-
mcpServers: getAcpMcpServers(session),
|
|
2054
|
-
},
|
|
2055
|
-
},
|
|
2000
|
+
adapterOptions: require("./yoke/query-options").map(sessionAdapter, executionIntent),
|
|
2056
2001
|
};
|
|
2057
2002
|
|
|
2003
|
+
if (recoveryState) {
|
|
2004
|
+
if (!recoveryState.context) recoveryState.context = { appendSystemPrompt: queryOpts.appendSystemPrompt, model: queryOpts.model, effort: queryOpts.effort };
|
|
2005
|
+
Object.assign(queryOpts, recoveryState.context);
|
|
2006
|
+
}
|
|
2058
2007
|
var handle;
|
|
2008
|
+
var startupHandle = session.queryInstance;
|
|
2059
2009
|
console.log("[sdk-bridge] calling adapter.createQuery... vendor=" + sessionAdapter.vendor);
|
|
2060
2010
|
try {
|
|
2061
2011
|
handle = await sessionAdapter.createQuery(queryOpts);
|
|
2012
|
+
// A guarded delivery must still own the exact startup after provider
|
|
2013
|
+
// creation. Never replace a newer handle or publish to a deleted target.
|
|
2014
|
+
if (beforePush && beforePush.exactProductDelivery) {
|
|
2015
|
+
var startupCurrent = false;
|
|
2016
|
+
try { startupCurrent = sm.sessions.get(session.localId) === session && session.queryInstance === startupHandle && Number(session._sdkQueryGeneration || 0) === queryGeneration && beforePush() === true; } catch (guardError) {}
|
|
2017
|
+
if (!startupCurrent) {
|
|
2018
|
+
try { if (handle.abort) handle.abort(); } catch (abortError) {}
|
|
2019
|
+
try { if (handle.close) handle.close(); } catch (closeError) {}
|
|
2020
|
+
if (session.queryInstance === startupHandle) session.isProcessing = false;
|
|
2021
|
+
return false;
|
|
2022
|
+
}
|
|
2023
|
+
}
|
|
2024
|
+
if (recoveryState) recoveryState.handle = handle;
|
|
2062
2025
|
console.log("[sdk-bridge] createQuery returned handle, vendor=" + sessionAdapter.vendor);
|
|
2063
2026
|
// SDK accepted the explicit title. Provisional labels remain eligible
|
|
2064
2027
|
// for semantic generation after the first Home exchange (or the normal
|
|
@@ -2078,6 +2041,7 @@ function createSDKBridge(opts) {
|
|
|
2078
2041
|
console.error("[sdk-bridge] Failed to create query for session " + session.localId + ":", e.message || e);
|
|
2079
2042
|
console.error("[sdk-bridge] cliSessionId:", session.cliSessionId, "resume:", !!session.cliSessionId);
|
|
2080
2043
|
console.error("[sdk-bridge] Stack:", e.stack || "(no stack)");
|
|
2044
|
+
if (beforePush && beforePush.exactProductDelivery && (sm.sessions.get(session.localId) !== session || session.queryInstance !== startupHandle || Number(session._sdkQueryGeneration || 0) !== queryGeneration)) return false;
|
|
2081
2045
|
session.isProcessing = false;
|
|
2082
2046
|
session._awaitingTurnResult = false;
|
|
2083
2047
|
session._queuedTurnCount = 0;
|
|
@@ -2112,11 +2076,9 @@ function createSDKBridge(opts) {
|
|
|
2112
2076
|
|
|
2113
2077
|
// Store QueryHandle on session for iteration and control.
|
|
2114
2078
|
session.queryInstance = handle;
|
|
2115
|
-
//
|
|
2116
|
-
//
|
|
2117
|
-
|
|
2118
|
-
session.permissionCapabilities = require("./session-permission-mode").capabilities(session, sm.defaultVendor);
|
|
2119
|
-
session.permissionCapabilities.mcpOverride = sessionAdapter.vendor === "claude" && typeof handle.setMcpPermissionModeOverride === "function";
|
|
2079
|
+
// An installed setter and the adapter's explicit protocol contract are
|
|
2080
|
+
// both required; generic handle stubs do not establish runtime support.
|
|
2081
|
+
session.permissionCapabilities = require("./session-permission-mode").capabilities(session, sm.defaultVendor, sessionAdapter);
|
|
2120
2082
|
session.effectivePermissionMode = null;
|
|
2121
2083
|
sm.saveSessionFile(session);
|
|
2122
2084
|
sendToSession(session, { type: "config_state", model: session.model || defaultModelForVendor(session.vendor || "claude"), vendor: session.vendor || "claude", sessionId: session.localId, mode: session.permissionMode || sm.currentPermissionMode || "default", effectivePermissionMode: null, permissionCapabilities: session.permissionCapabilities, mcpPermissionModeOverrides: session.mcpPermissionModeOverrides || {}, effort: session.effort || sm.currentEffort || "medium", betas: sm.currentBetas || [] });
|
|
@@ -2132,6 +2094,7 @@ function createSDKBridge(opts) {
|
|
|
2132
2094
|
}
|
|
2133
2095
|
|
|
2134
2096
|
if (typeof beforePush === "function" && beforePush() !== true) {
|
|
2097
|
+
try { if (typeof handle.abort === "function") handle.abort(); } catch (e) {}
|
|
2135
2098
|
try { handle.close(); } catch (e) {}
|
|
2136
2099
|
if (session.queryInstance === handle) session.queryInstance = null;
|
|
2137
2100
|
session.messageQueue = null;
|
|
@@ -2141,6 +2104,13 @@ function createSDKBridge(opts) {
|
|
|
2141
2104
|
session._queuedTurnCount = 0;
|
|
2142
2105
|
taskLifecycle.clearAll(session);
|
|
2143
2106
|
onProcessingChanged();
|
|
2107
|
+
if (recoveryState && !responseRecovery.stopping(session)) {
|
|
2108
|
+
sendAndRecord(session, { type: "thinking_stop" });
|
|
2109
|
+
sendAndRecord(session, { type: session.taskStopRequested ? "info" : "error", text: session.taskStopRequested
|
|
2110
|
+
? "Stopped before sending your message."
|
|
2111
|
+
: "This request is no longer eligible for delivery. Please review it and send it again." });
|
|
2112
|
+
sendAndRecord(session, { type: "done", code: session.taskStopRequested ? 0 : 1 });
|
|
2113
|
+
}
|
|
2144
2114
|
sm.broadcastSessionList();
|
|
2145
2115
|
return false;
|
|
2146
2116
|
}
|
|
@@ -2192,32 +2162,28 @@ function createSDKBridge(opts) {
|
|
|
2192
2162
|
}
|
|
2193
2163
|
|
|
2194
2164
|
session.lastActivityAt = Date.now();
|
|
2195
|
-
var
|
|
2196
|
-
if (
|
|
2165
|
+
var catalogCandidate = null;
|
|
2166
|
+
if (queryContract.catalogLifetime === "conversation" && typeof queryContract.recordCatalog === "function" && !resumedAtQueryStart) {
|
|
2197
2167
|
var requiredCatalogTools = { begin_scheduled_task_interview: false, propose_scheduled_task: false, list_scheduled_tasks: false, read_scheduled_task: false, update_scheduled_task: false, report_scheduled_task_outcome: false, ask_user_questions: false };
|
|
2198
2168
|
for (var catalogToolIndex = 0; catalogToolIndex < sessionToolDefs.length; catalogToolIndex++) {
|
|
2199
2169
|
if (Object.prototype.hasOwnProperty.call(requiredCatalogTools, sessionToolDefs[catalogToolIndex].name)) requiredCatalogTools[sessionToolDefs[catalogToolIndex].name] = true;
|
|
2200
2170
|
}
|
|
2201
2171
|
var completeInterviewCatalog = requiredCatalogTools.begin_scheduled_task_interview && requiredCatalogTools.propose_scheduled_task && requiredCatalogTools.list_scheduled_tasks && requiredCatalogTools.read_scheduled_task && requiredCatalogTools.update_scheduled_task && requiredCatalogTools.ask_user_questions;
|
|
2202
2172
|
if (completeInterviewCatalog || requiredCatalogTools.report_scheduled_task_outcome) {
|
|
2203
|
-
|
|
2204
|
-
}
|
|
2205
|
-
if (requiredCatalogTools.ask_user_questions) {
|
|
2206
|
-
codexCatalogCandidate = Object.assign({}, codexCatalogCandidate || {}, { generation: queryGeneration, userInputVersion: 1 });
|
|
2173
|
+
catalogCandidate = { generation: queryGeneration, versions: { schedules: yoke.sessionTools.SCHEDULE_CATALOG_VERSION } };
|
|
2207
2174
|
}
|
|
2208
|
-
|
|
2209
|
-
|
|
2210
|
-
|
|
2211
|
-
codexCatalogCandidate = Object.assign({}, codexCatalogCandidate || {}, { generation: queryGeneration, sharedBrowserVersion: 5 });
|
|
2175
|
+
function markCatalog(family, version) {
|
|
2176
|
+
if (!catalogCandidate) catalogCandidate = { generation: queryGeneration, versions: {} };
|
|
2177
|
+
catalogCandidate.versions[family] = version;
|
|
2212
2178
|
}
|
|
2213
|
-
if (
|
|
2214
|
-
|
|
2215
|
-
|
|
2216
|
-
|
|
2217
|
-
|
|
2218
|
-
|
|
2219
|
-
}
|
|
2220
|
-
session.streamPromise = processQueryStream(session,
|
|
2179
|
+
if (requiredCatalogTools.ask_user_questions) markCatalog("questions", 1);
|
|
2180
|
+
if (hasYouCatalog) markCatalog("knowledge", 1);
|
|
2181
|
+
if (hasLinearCatalog) markCatalog("linear", 1);
|
|
2182
|
+
if (hasSharedBrowserCatalog) markCatalog("browser", 6);
|
|
2183
|
+
if (hasIssueCatalog) markCatalog("issues", 1);
|
|
2184
|
+
if (hasNotesCatalog) markCatalog("notes", notesCatalogVersion);
|
|
2185
|
+
}
|
|
2186
|
+
session.streamPromise = processQueryStream(session, catalogCandidate, queryContract).catch(function(err) {
|
|
2221
2187
|
});
|
|
2222
2188
|
return true;
|
|
2223
2189
|
}
|
|
@@ -2229,6 +2195,19 @@ function createSDKBridge(opts) {
|
|
|
2229
2195
|
// dropped messages in both gap windows, which is what made a session show
|
|
2230
2196
|
// the processing indicator without ever answering until a second send.
|
|
2231
2197
|
function pushMessage(session, text, images, deliveryMeta) {
|
|
2198
|
+
if (session._responseRecoveryStopPending && !responseRecovery.stopping(session)) return false;
|
|
2199
|
+
function trackDelivery() {
|
|
2200
|
+
responseRecovery.enqueue(session, {
|
|
2201
|
+
text: text, images: images, linuxUser: session.lastLinuxUser || null,
|
|
2202
|
+
});
|
|
2203
|
+
}
|
|
2204
|
+
if (responseRecovery.stopping(session)) {
|
|
2205
|
+
// Keep admission serialized while the old execution is terminating.
|
|
2206
|
+
session.pendingPush = session.pendingPush || [];
|
|
2207
|
+
session.pendingPush.push(Object.assign({ text: text, images: images || null }, deliveryMeta || {}));
|
|
2208
|
+
trackDelivery();
|
|
2209
|
+
return true;
|
|
2210
|
+
}
|
|
2232
2211
|
session.lastActivityAt = Date.now();
|
|
2233
2212
|
if (session._runtimeRefreshRequested && !session._queryStarting) {
|
|
2234
2213
|
session._runtimeRefreshRequested = false;
|
|
@@ -2255,6 +2234,8 @@ function createSDKBridge(opts) {
|
|
|
2255
2234
|
console.error("[sdk-bridge] QueryHandle rejected message for session " + session.localId + ":", e.message || e);
|
|
2256
2235
|
}
|
|
2257
2236
|
if (delivered) {
|
|
2237
|
+
require('./sdk-foreground-admission').take(session);
|
|
2238
|
+
trackDelivery();
|
|
2258
2239
|
delete session._lastTurnInterrupted;
|
|
2259
2240
|
if (session._awaitingTurnResult) {
|
|
2260
2241
|
session._queuedTurnCount = (session._queuedTurnCount || 0) + 1;
|
|
@@ -2279,6 +2260,7 @@ function createSDKBridge(opts) {
|
|
|
2279
2260
|
if (session._queryStarting) {
|
|
2280
2261
|
session.pendingPush = session.pendingPush || [];
|
|
2281
2262
|
session.pendingPush.push(Object.assign({ text: text, images: images || null }, deliveryMeta || {}));
|
|
2263
|
+
trackDelivery();
|
|
2282
2264
|
return true;
|
|
2283
2265
|
}
|
|
2284
2266
|
return false;
|
|
@@ -2359,65 +2341,8 @@ function createSDKBridge(opts) {
|
|
|
2359
2341
|
// Detect which vendor binaries are installed for this user.
|
|
2360
2342
|
// In multi-user mode, runs checks as the specific Linux user.
|
|
2361
2343
|
function detectInstalledVendors(linuxUser) {
|
|
2362
|
-
var
|
|
2363
|
-
|
|
2364
|
-
var result = [];
|
|
2365
|
-
|
|
2366
|
-
function tryLookup(name) {
|
|
2367
|
-
try {
|
|
2368
|
-
if (linuxUser) {
|
|
2369
|
-
execFileSync("su", ["-", linuxUser, "-c", "which " + name], { timeout: 3000, stdio: ["pipe", "pipe", "pipe"] });
|
|
2370
|
-
} else {
|
|
2371
|
-
if (process.platform === "win32") execFileSync("where", [name], { timeout: 3000, stdio: ["pipe", "pipe", "pipe"] });
|
|
2372
|
-
else execFileSync("which", [name], { timeout: 3000, stdio: ["pipe", "pipe", "pipe"] });
|
|
2373
|
-
}
|
|
2374
|
-
return true;
|
|
2375
|
-
} catch (e) {
|
|
2376
|
-
return false;
|
|
2377
|
-
}
|
|
2378
|
-
}
|
|
2379
|
-
|
|
2380
|
-
// Claude: check if binary is in PATH
|
|
2381
|
-
if (tryLookup(yoke.getVendorInfo("claude").binaryName)) result.push("claude");
|
|
2382
|
-
|
|
2383
|
-
// Codex: check bundled binary or PATH
|
|
2384
|
-
var codexBin = null;
|
|
2385
|
-
try {
|
|
2386
|
-
codexBin = require("./yoke/codex-app-server").findCodexPath();
|
|
2387
|
-
} catch (e) {}
|
|
2388
|
-
if ((codexBin && fs.existsSync(codexBin)) || tryLookup(yoke.getVendorInfo("codex").binaryName)) result.push("codex");
|
|
2389
|
-
|
|
2390
|
-
var subprocessVendorKeys = ["antigravity", "opencode", "kimi", "grok", "copilot", "qwen", "junie"];
|
|
2391
|
-
var acpProfiles = require("./yoke/acp-agent-profiles");
|
|
2392
|
-
for (var subprocessVendorIndex = 0; subprocessVendorIndex < subprocessVendorKeys.length; subprocessVendorIndex++) {
|
|
2393
|
-
var subprocessVendor = subprocessVendorKeys[subprocessVendorIndex];
|
|
2394
|
-
var subprocessInfo = yoke.getVendorInfo(subprocessVendor);
|
|
2395
|
-
if (!linuxUser || subprocessInfo.osUserIsolation) {
|
|
2396
|
-
if (subprocessVendor === "antigravity") {
|
|
2397
|
-
if (tryLookup(subprocessInfo.binaryName)) result.push(subprocessVendor);
|
|
2398
|
-
} else {
|
|
2399
|
-
var acpProfile = acpProfiles.getAcpAgentProfile(subprocessVendor);
|
|
2400
|
-
if (acpProfiles.findAcpAgentPath(acpProfile)) result.push(subprocessVendor);
|
|
2401
|
-
}
|
|
2402
|
-
} else {
|
|
2403
|
-
console.log("[sdk-bridge] " + subprocessInfo.displayName + " hidden for OS-isolated user " + linuxUser + ": per-user spawning is not implemented");
|
|
2404
|
-
}
|
|
2405
|
-
}
|
|
2406
|
-
|
|
2407
|
-
// Kiro has no per-user ACP spawn path yet. Do not advertise the daemon's
|
|
2408
|
-
// binary to an OS-isolated user, even if that user also has Kiro installed.
|
|
2409
|
-
var kiroInfo = yoke.getVendorInfo("kiro");
|
|
2410
|
-
if (!linuxUser || kiroInfo.osUserIsolation) {
|
|
2411
|
-
var kiroBin = null;
|
|
2412
|
-
try {
|
|
2413
|
-
kiroBin = require("./yoke/kiro-acp-server").findKiroPath();
|
|
2414
|
-
} catch (e) {}
|
|
2415
|
-
if ((kiroBin && fs.existsSync(kiroBin)) || tryLookup(kiroInfo.binaryName)) result.push("kiro");
|
|
2416
|
-
} else {
|
|
2417
|
-
console.log("[sdk-bridge] " + kiroInfo.displayName + " hidden for OS-isolated user " + linuxUser + ": per-user spawning is not implemented");
|
|
2418
|
-
}
|
|
2419
|
-
|
|
2420
|
-
return result;
|
|
2344
|
+
var installed = require("./yoke/discovery").installed({ user: linuxUser });
|
|
2345
|
+
return Object.keys(installed).filter(function(vendor) { return installed[vendor]; });
|
|
2421
2346
|
}
|
|
2422
2347
|
|
|
2423
2348
|
function getAvailableVendors(linuxUser) {
|
|
@@ -2489,7 +2414,20 @@ function createSDKBridge(opts) {
|
|
|
2489
2414
|
sendModelInfoForVendor(null, defaultVendor, defaultModelForVendor(defaultVendor));
|
|
2490
2415
|
}
|
|
2491
2416
|
|
|
2492
|
-
async function setModel(session, model) {
|
|
2417
|
+
async function setModel(session, model, options) {
|
|
2418
|
+
if (options && typeof options.revalidate === "function") {
|
|
2419
|
+
var vendor = session.vendor || sm.defaultVendor || "claude";
|
|
2420
|
+
return require("./session-config-transition").applySessionConfig({
|
|
2421
|
+
sm: sm, session: session, revalidate: options.revalidate, method: "setModel", nativeValue: model, changes: { model: model },
|
|
2422
|
+
publish: function () {
|
|
2423
|
+
sm.defaultModelByVendor = sm.defaultModelByVendor || {};
|
|
2424
|
+
sm.defaultModelByVendor[vendor] = model;
|
|
2425
|
+
sm.broadcastSessionList();
|
|
2426
|
+
sendModelInfoForVendor(session, vendor, model);
|
|
2427
|
+
sendToSession(session, { type: "config_state", sessionId: session.localId, vendor: vendor, model: model, effort: session.effort || sm.currentEffort || "medium", mode: session.permissionMode || sm.currentPermissionMode || "default", betas: sm.currentBetas || [] });
|
|
2428
|
+
},
|
|
2429
|
+
});
|
|
2430
|
+
}
|
|
2493
2431
|
// Normalize to string id in case a { value, displayName } object slips in
|
|
2494
2432
|
if (model && typeof model !== "string") {
|
|
2495
2433
|
model = modelEntryValue(model);
|
|
@@ -2525,7 +2463,22 @@ function createSDKBridge(opts) {
|
|
|
2525
2463
|
}
|
|
2526
2464
|
}
|
|
2527
2465
|
|
|
2528
|
-
async function setEffort(session, effort) {
|
|
2466
|
+
async function setEffort(session, effort, options) {
|
|
2467
|
+
if (options && typeof options.revalidate === "function") {
|
|
2468
|
+
var vendor = session.vendor || sm.defaultVendor || "claude";
|
|
2469
|
+
var value = yoke.clampEffort(vendor, effort);
|
|
2470
|
+
if (!value || value !== effort) throw new Error("Unsupported reasoning effort.");
|
|
2471
|
+
return require("./session-config-transition").applySessionConfig({
|
|
2472
|
+
sm: sm, session: session, revalidate: options.revalidate, method: "setEffort", nativeValue: value, changes: { effort: value },
|
|
2473
|
+
publish: function () {
|
|
2474
|
+
sm.currentEffortByVendor = sm.currentEffortByVendor || {};
|
|
2475
|
+
sm.currentEffortByVendor[vendor] = value;
|
|
2476
|
+
sm.currentEffort = value;
|
|
2477
|
+
sm.broadcastSessionList();
|
|
2478
|
+
sendToSession(session, { type: "config_state", sessionId: session.localId, vendor: vendor, effort: value, model: session.model || "", mode: session.permissionMode || sm.currentPermissionMode || "default", betas: sm.currentBetas || [] });
|
|
2479
|
+
},
|
|
2480
|
+
});
|
|
2481
|
+
}
|
|
2529
2482
|
// Remember the pick per vendor (clamped) so vendor switches don't leak
|
|
2530
2483
|
// unsupported levels across sessions; sm.currentEffort stays as the
|
|
2531
2484
|
// display value for the session the user just configured.
|
|
@@ -2646,16 +2599,7 @@ function createSDKBridge(opts) {
|
|
|
2646
2599
|
message: "Read-only access. You cannot make changes via @mention.",
|
|
2647
2600
|
});
|
|
2648
2601
|
},
|
|
2649
|
-
adapterOptions: {
|
|
2650
|
-
CLAUDE: {
|
|
2651
|
-
settingSources: ["user"],
|
|
2652
|
-
includePartialMessages: true,
|
|
2653
|
-
// Explicit, not omitted: SDK 0.3.286+ leaves an omitted
|
|
2654
|
-
// permissionMode to Claude Code's own default/auto behavior,
|
|
2655
|
-
// which could bypass the deny-by-default canUseTool above.
|
|
2656
|
-
permissionMode: "default",
|
|
2657
|
-
},
|
|
2658
|
-
},
|
|
2602
|
+
adapterOptions: require("./yoke/query-options").map(mentionAdapter, { instructionSources: ["user"], readOnly: true }),
|
|
2659
2603
|
});
|
|
2660
2604
|
} catch (e) {
|
|
2661
2605
|
opts.onError("Failed to create mention query: " + (e.message || e));
|
|
@@ -2794,12 +2738,14 @@ function createSDKBridge(opts) {
|
|
|
2794
2738
|
startQuery: startQuery,
|
|
2795
2739
|
startQueryWithAcceptance: startQueryWithAcceptance,
|
|
2796
2740
|
pushMessage: pushMessage,
|
|
2741
|
+
cancelResponseRecovery: responseRecovery.cancel,
|
|
2797
2742
|
refreshSessionRuntime: refreshSessionRuntime,
|
|
2798
2743
|
refreshEnvironmentRuntime: refreshEnvironmentRuntime,
|
|
2799
2744
|
setModel: setModel,
|
|
2800
2745
|
setEffort: setEffort,
|
|
2801
2746
|
setPermissionMode: setPermissionMode,
|
|
2802
|
-
|
|
2747
|
+
isProviderProcess: isProviderProcess,
|
|
2748
|
+
isClaudeProcess: isProviderProcess, // Compatibility export; production uses the provider contract.
|
|
2803
2749
|
permissionPushTitle: permissionPushTitle,
|
|
2804
2750
|
permissionPushBody: permissionPushBody,
|
|
2805
2751
|
warmup: warmup,
|