clay-server 5.2.0-beta.1 → 5.2.0-beta.10
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/lib/account-auth-socket.js +1 -0
- package/lib/builtin-mates.js +19 -16
- package/lib/bundled-skills/clay-agent-browser/SKILL.md +6 -2
- package/lib/canonical-clay-record-authority.js +15 -0
- package/lib/canonical-clay-scheduling-authority.js +19 -0
- package/lib/claude-hook-installer.js +1 -239
- package/lib/claude-jsonl-watcher.js +1 -204
- package/lib/clay-control-presentation-binding.js +96 -0
- package/lib/clay-control-presentation.js +128 -0
- package/lib/clay-control-target-projection.js +26 -0
- package/lib/clay-mate-chat-receipts.js +26 -0
- package/lib/clay-mate-chat.js +88 -0
- package/lib/clay-mate-knowledge-input.js +26 -0
- package/lib/clay-mate-knowledge.js +95 -0
- package/lib/clay-mate-lifecycle.js +95 -0
- package/lib/clay-product-control-input.js +33 -0
- package/lib/clay-product-control-tools.js +51 -0
- package/lib/clay-product-control.js +247 -0
- package/lib/clay-project-lifecycle.js +154 -0
- package/lib/clay-project-record-input.js +44 -0
- package/lib/clay-project-records.js +84 -0
- package/lib/clay-scheduling-input.js +21 -0
- package/lib/clay-scheduling-receipts.js +26 -0
- package/lib/clay-scheduling.js +119 -0
- package/lib/clay-screen-controls.js +104 -0
- package/lib/clay-skill-install.js +1 -33
- package/lib/clay-workspace-controls.js +84 -0
- package/lib/clay-workspace-input.js +17 -0
- package/lib/clay-workspace-receipts.js +26 -0
- package/lib/cli-sessions.js +1 -300
- package/lib/codex-defaults.js +1 -28
- package/lib/context-usage.js +3 -2
- package/lib/contextual-screen-snapshot.js +38 -0
- package/lib/daemon-project-access.js +11 -0
- package/lib/daemon-project-lifecycle-callbacks.js +15 -0
- package/lib/daemon-project-lifecycle.js +262 -0
- package/lib/daemon-projects.js +1 -1
- package/lib/daemon.js +78 -276
- package/lib/default-ai-runtime.js +4 -8
- package/lib/dm-digest-cursor.js +120 -0
- package/lib/email-mcp-server.js +1 -1
- package/lib/issues-service.js +29 -15
- package/lib/kiro-defaults.js +1 -22
- package/lib/knowledge-db-import-validation.js +46 -0
- package/lib/knowledge-db-import.js +99 -0
- package/lib/knowledge-db-service.js +24 -33
- package/lib/knowledge-db-storage-nedb-maintenance.js +99 -0
- package/lib/knowledge-db-storage-nedb.js +66 -0
- package/lib/knowledge-db-storage.js +72 -0
- package/lib/knowledge-db-validation.js +0 -0
- package/lib/knowledge-document-index.js +2 -1
- package/lib/knowledge-file-store.js +7 -1
- package/lib/knowledge-product-operations.js +46 -0
- package/lib/mate-avatar-catalog.js +12 -0
- package/lib/mate-avatar-migration.js +41 -0
- package/lib/mate-context-service.js +138 -0
- package/lib/mate-context-tools.js +21 -0
- package/lib/mate-creation-mcp-server.js +2 -0
- package/lib/mate-knowledge-canonical-access.js +10 -0
- package/lib/mate-knowledge-mate-bound.js +53 -0
- package/lib/mate-knowledge-mcp-server.js +55 -8
- package/lib/mate-knowledge-service.js +16 -34
- package/lib/mate-knowledge-text-tools.js +106 -0
- package/lib/mate-lifecycle-service.js +94 -0
- package/lib/mate-message-delivery.js +43 -0
- package/lib/mate-ready-creation.js +9 -1
- package/lib/mate-schedule-input.js +29 -0
- package/lib/mate-schedule-lifecycle.js +151 -0
- package/lib/mate-scheduling.js +103 -0
- package/lib/mates.js +18 -6
- package/lib/mcp-agent-tools.js +117 -0
- package/lib/mcp-connection-store.js +119 -15
- package/lib/mcp-import-credentials.js +31 -0
- package/lib/mcp-local-transport.js +13 -0
- package/lib/mcp-oauth.js +8 -6
- package/lib/mcp-proxy.js +2 -32
- package/lib/mcp-query-bridge.js +30 -0
- package/lib/mcp-remote-connections.js +74 -20
- package/lib/mcp-source-adapters.js +1 -0
- package/lib/mcp-source-context.js +1 -0
- package/lib/mcp-source-discovery.js +1 -0
- package/lib/mcp-source-plugins.js +1 -0
- package/lib/mcp-source-restrictions.js +1 -0
- package/lib/mcp-tool-policy.js +9 -0
- package/lib/notes-checklist.js +50 -0
- package/lib/notes.js +49 -3
- package/lib/os-user-diagnostics.js +2 -4
- package/lib/os-users.js +24 -70
- package/lib/pane-pending-interactions.js +20 -0
- package/lib/pane-session-activation.js +114 -0
- package/lib/pane-session-transport.js +26 -0
- package/lib/project-admin-overview.js +51 -0
- package/lib/project-ask-user.js +8 -4
- package/lib/project-connection.js +14 -10
- package/lib/project-control-git-view.js +12 -0
- package/lib/project-debate.js +1 -0
- package/lib/project-delegated-follow-up.js +2 -1
- package/lib/project-directory-claim.js +65 -0
- package/lib/project-file-operations.js +61 -0
- package/lib/project-filesystem.js +15 -85
- package/lib/project-full-access.js +23 -2
- package/lib/project-http.js +7 -4
- package/lib/project-knowledge.js +32 -18
- package/lib/project-lifecycle-operations.js +98 -0
- package/lib/project-lifecycle-process-witness.js +32 -0
- package/lib/project-lifecycle-runtime.js +50 -0
- package/lib/project-linux-access.js +22 -0
- package/lib/project-logs-canonical-clay.js +27 -0
- package/lib/project-logs-clay-query.js +16 -0
- package/lib/project-logs-schema.js +4 -2
- package/lib/project-logs-service.js +8 -7
- package/lib/project-logs.js +1 -0
- package/lib/project-loop.js +1 -0
- package/lib/project-mate-chat-control.js +55 -0
- package/lib/project-mate-creation-proposal.js +18 -3
- package/lib/project-mate-interaction.js +40 -62
- package/lib/project-mcp.js +54 -16
- package/lib/project-models.js +14 -31
- package/lib/project-notifications.js +76 -17
- package/lib/project-ownership.js +77 -0
- package/lib/project-pair-result-delivery.js +14 -3
- package/lib/project-pair-usage.js +12 -13
- package/lib/project-pending-message-queue.js +4 -1
- package/lib/project-product-control.js +89 -0
- package/lib/project-product-session-queue.js +46 -0
- package/lib/project-push-access.js +28 -0
- package/lib/project-scheduled-message-queue.js +30 -0
- package/lib/project-scheduled-messages.js +67 -68
- package/lib/project-scheduled-task-control.js +83 -0
- package/lib/project-scheduled-tasks.js +13 -2
- package/lib/project-scheduling-access.js +10 -0
- package/lib/project-session-actions.js +65 -0
- package/lib/project-session-delete.js +8 -1
- package/lib/project-session-document.js +27 -7
- package/lib/project-session-github.js +63 -19
- package/lib/project-session-history-actions.js +167 -0
- package/lib/project-session-linear.js +14 -6
- package/lib/project-session-notes.js +7 -3
- package/lib/project-session-pair.js +1 -1
- package/lib/project-session-runtime-actions.js +64 -0
- package/lib/project-session-spawn.js +2 -3
- package/lib/project-session-vendor.js +55 -0
- package/lib/project-sessions.js +103 -272
- package/lib/project-shared-browser.js +78 -17
- package/lib/project-studio-presentation.js +58 -0
- package/lib/project-user-message.js +67 -1
- package/lib/project-vendor-login.js +6 -36
- package/lib/project-workspace-operations.js +126 -0
- package/lib/project-workspace-query.js +19 -2
- package/lib/project.js +178 -45
- package/lib/public/app.js +46 -0
- package/lib/public/appearance-bootstrap.js +16 -0
- package/lib/public/css/clay-tool-activity.css +51 -0
- package/lib/public/css/clay-workspace.css +29 -0
- package/lib/public/css/command-palette.css +12 -33
- package/lib/public/css/contextual-clay.css +240 -0
- package/lib/public/css/home-debate-planning.css +2 -0
- package/lib/public/css/home-mate-creation.css +5 -0
- package/lib/public/css/input.css +6 -0
- package/lib/public/css/mate-avatar-gallery.css +12 -0
- package/lib/public/css/mate-conversation.css +10 -5
- package/lib/public/css/messages.css +6 -2
- package/lib/public/css/overlays.css +4 -2
- package/lib/public/css/project-admin-overview.css +13 -0
- package/lib/public/css/session-folders.css +11 -0
- package/lib/public/css/session-github.css +46 -1
- package/lib/public/css/shared-browser.css +35 -1
- package/lib/public/css/sticky-notes.css +87 -1
- package/lib/public/index.html +11 -5
- package/lib/public/mate-avatars/B01.png +0 -0
- package/lib/public/mate-avatars/B02.png +0 -0
- package/lib/public/mate-avatars/B03.png +0 -0
- package/lib/public/mate-avatars/B04.png +0 -0
- package/lib/public/mate-avatars/B05.png +0 -0
- package/lib/public/mate-avatars/B06.png +0 -0
- package/lib/public/mate-avatars/B07.png +0 -0
- package/lib/public/mate-avatars/B08.png +0 -0
- package/lib/public/mate-avatars/B09.png +0 -0
- package/lib/public/mate-avatars/B10.png +0 -0
- package/lib/public/mate-avatars/B11.png +0 -0
- package/lib/public/mate-avatars/B12.png +0 -0
- package/lib/public/mate-avatars/B13.png +0 -0
- package/lib/public/mate-avatars/B14.png +0 -0
- package/lib/public/mate-avatars/B15.png +0 -0
- package/lib/public/mate-avatars/B16.png +0 -0
- package/lib/public/mate-avatars/B17.png +0 -0
- package/lib/public/mate-avatars/B18.png +0 -0
- package/lib/public/mate-avatars/B19.png +0 -0
- package/lib/public/mate-avatars/B20.png +0 -0
- package/lib/public/mate-avatars/B21.png +0 -0
- package/lib/public/mate-avatars/B22.png +0 -0
- package/lib/public/mate-avatars/B23.png +0 -0
- package/lib/public/mate-avatars/B24.png +0 -0
- package/lib/public/mate-avatars/B25.png +0 -0
- package/lib/public/mate-avatars/B26.png +0 -0
- package/lib/public/mate-avatars/B27.png +0 -0
- package/lib/public/mate-avatars/B28.png +0 -0
- package/lib/public/mate-avatars/B29.png +0 -0
- package/lib/public/mate-avatars/B30.png +0 -0
- package/lib/public/mate-avatars/B31.png +0 -0
- package/lib/public/mate-avatars/B32.png +0 -0
- package/lib/public/mate-avatars/B33.png +0 -0
- package/lib/public/mate-avatars/B34.png +0 -0
- package/lib/public/mate-avatars/B35.png +0 -0
- package/lib/public/mate-avatars/B36.png +0 -0
- package/lib/public/mate-avatars/B37.png +0 -0
- package/lib/public/mate-avatars/B38.png +0 -0
- package/lib/public/mate-avatars/B39.png +0 -0
- package/lib/public/mate-avatars/B40.png +0 -0
- package/lib/public/mate-avatars/B41.png +0 -0
- package/lib/public/mate-avatars/B42.png +0 -0
- package/lib/public/mate-avatars/B43.png +0 -0
- package/lib/public/mate-avatars/B44.png +0 -0
- package/lib/public/mate-avatars/B45.png +0 -0
- package/lib/public/mate-avatars/B46.png +0 -0
- package/lib/public/mate-avatars/B47.png +0 -0
- package/lib/public/mate-avatars/B48.png +0 -0
- package/lib/public/mate-avatars/C01.png +0 -0
- package/lib/public/mate-avatars/C02.png +0 -0
- package/lib/public/mate-avatars/C03.png +0 -0
- package/lib/public/mate-avatars/C04.png +0 -0
- package/lib/public/mate-avatars/C05.png +0 -0
- package/lib/public/mate-avatars/C06.png +0 -0
- package/lib/public/mate-avatars/C07.png +0 -0
- package/lib/public/mate-avatars/C08.png +0 -0
- package/lib/public/mate-avatars/C09.png +0 -0
- package/lib/public/mate-avatars/C10.png +0 -0
- package/lib/public/mate-avatars/C11.png +0 -0
- package/lib/public/mate-avatars/C12.png +0 -0
- package/lib/public/mate-avatars/C13.png +0 -0
- package/lib/public/mate-avatars/C14.png +0 -0
- package/lib/public/mate-avatars/C15.png +0 -0
- package/lib/public/mate-avatars/C16.png +0 -0
- package/lib/public/mate-avatars/C17.png +0 -0
- package/lib/public/mate-avatars/C18.png +0 -0
- package/lib/public/mate-avatars/C19.png +0 -0
- package/lib/public/mate-avatars/C20.png +0 -0
- package/lib/public/mate-avatars/C21.png +0 -0
- package/lib/public/mate-avatars/C22.png +0 -0
- package/lib/public/mate-avatars/C23.png +0 -0
- package/lib/public/mate-avatars/C24.png +0 -0
- package/lib/public/mate-avatars/C25.png +0 -0
- package/lib/public/mate-avatars/C26.png +0 -0
- package/lib/public/mate-avatars/C27.png +0 -0
- package/lib/public/mate-avatars/C28.png +0 -0
- package/lib/public/mate-avatars/C29.png +0 -0
- package/lib/public/mate-avatars/C30.png +0 -0
- package/lib/public/mate-avatars/C31.png +0 -0
- package/lib/public/mate-avatars/C32.png +0 -0
- package/lib/public/mate-avatars/C33.png +0 -0
- package/lib/public/mate-avatars/C34.png +0 -0
- package/lib/public/mate-avatars/C35.png +0 -0
- package/lib/public/mate-avatars/C36.png +0 -0
- package/lib/public/mate-avatars/C37.png +0 -0
- package/lib/public/mate-avatars/C38.png +0 -0
- package/lib/public/mate-avatars/C39.png +0 -0
- package/lib/public/mate-avatars/C40.png +0 -0
- package/lib/public/mate-avatars/C41.png +0 -0
- package/lib/public/mate-avatars/C42.png +0 -0
- package/lib/public/mate-avatars/C43.png +0 -0
- package/lib/public/mate-avatars/C44.png +0 -0
- package/lib/public/mate-avatars/C45.png +0 -0
- package/lib/public/mate-avatars/C46.png +0 -0
- package/lib/public/mate-avatars/C47.png +0 -0
- package/lib/public/mate-avatars/C48.png +0 -0
- package/lib/public/mate-avatars/catalog.json +482 -0
- package/lib/public/mate-avatars/lead-clay.png +0 -0
- package/lib/public/modules/admin-settings-projects.js +6 -2
- package/lib/public/modules/app-connection.js +11 -1
- package/lib/public/modules/app-favicon.js +18 -9
- package/lib/public/modules/app-header.js +7 -4
- package/lib/public/modules/app-loop-ui.js +2 -0
- package/lib/public/modules/app-message-router.js +22 -1
- package/lib/public/modules/app-messages.js +115 -17
- package/lib/public/modules/app-misc.js +3 -1
- package/lib/public/modules/app-notifications.js +11 -5
- package/lib/public/modules/app-panels.js +61 -123
- package/lib/public/modules/app-projects.js +13 -0
- package/lib/public/modules/app-rate-limit.js +7 -27
- package/lib/public/modules/app-rendering.js +4 -3
- package/lib/public/modules/avatar.js +15 -41
- package/lib/public/modules/chat-render-runtime.js +20 -0
- package/lib/public/modules/clay-browser-links.js +47 -0
- package/lib/public/modules/clay-control-activity.js +214 -0
- package/lib/public/modules/clay-control-copy.js +36 -0
- package/lib/public/modules/clay-control-detail-targets.js +44 -0
- package/lib/public/modules/clay-control-object-targets.js +52 -0
- package/lib/public/modules/clay-control-target-visibility.js +12 -0
- package/lib/public/modules/clay-control-targets.js +44 -0
- package/lib/public/modules/clay-log-links.js +23 -0
- package/lib/public/modules/clay-navigation-render.js +52 -0
- package/lib/public/modules/clay-owner-navigation.js +33 -0
- package/lib/public/modules/clay-session-links.js +31 -0
- package/lib/public/modules/clay-studio-bridge.js +20 -0
- package/lib/public/modules/clay-studio-document.js +67 -0
- package/lib/public/modules/clay-studio-render.js +146 -0
- package/lib/public/modules/clay-tool-activity.js +140 -0
- package/lib/public/modules/clay-tool-presentation.js +342 -0
- package/lib/public/modules/command-palette.js +162 -40
- package/lib/public/modules/contextual-ask-session.js +26 -0
- package/lib/public/modules/contextual-clay-geometry.js +155 -0
- package/lib/public/modules/contextual-clay-session.js +130 -0
- package/lib/public/modules/contextual-clay-workspace.js +169 -0
- package/lib/public/modules/contextual-clay.js +250 -0
- package/lib/public/modules/contextual-composer.js +91 -0
- package/lib/public/modules/contextual-mate-context.js +117 -0
- package/lib/public/modules/contextual-mate-hint.js +40 -0
- package/lib/public/modules/contextual-mate-identity.js +23 -0
- package/lib/public/modules/contextual-mate-sessions.js +134 -0
- package/lib/public/modules/contextual-search.js +137 -0
- package/lib/public/modules/contextual-session-citations.js +58 -0
- package/lib/public/modules/debate.js +1 -0
- package/lib/public/modules/default-ai.js +11 -3
- package/lib/public/modules/elicitation-form.js +5 -0
- package/lib/public/modules/filebrowser.js +20 -1
- package/lib/public/modules/generation-stop.js +8 -5
- package/lib/public/modules/git-panel.js +3 -1
- package/lib/public/modules/history-replay-batch.js +13 -1
- package/lib/public/modules/home-debate-live.js +2 -0
- package/lib/public/modules/home-debate-planning.js +7 -7
- package/lib/public/modules/home-mate-avatar-editor.js +127 -208
- package/lib/public/modules/home-mate-chat.js +8 -6
- package/lib/public/modules/home-mate-creation.js +73 -1
- package/lib/public/modules/home-mate-settings.js +19 -12
- package/lib/public/modules/icon-strip-tooltip.js +2 -1
- package/lib/public/modules/input.js +88 -10
- package/lib/public/modules/issues-render.js +3 -2
- package/lib/public/modules/knowledge-db-workbench.js +4 -4
- package/lib/public/modules/markdown.js +6 -34
- package/lib/public/modules/mate-avatar-catalog.js +97 -0
- package/lib/public/modules/mate-knowledge-workbench.js +1 -1
- package/lib/public/modules/mate-management.js +40 -7
- package/lib/public/modules/mcp-connection-view.js +31 -13
- package/lib/public/modules/mcp-discovery-view.js +31 -0
- package/lib/public/modules/mcp-ui.js +23 -4
- package/lib/public/modules/mention.js +3 -0
- package/lib/public/modules/message-delivery.js +20 -2
- package/lib/public/modules/model-picker.js +2 -0
- package/lib/public/modules/pane-activation.js +214 -0
- package/lib/public/modules/pane-binding.js +82 -0
- package/lib/public/modules/pane-bridge.js +7 -4
- package/lib/public/modules/pane-browser-bridge.js +22 -0
- package/lib/public/modules/pane-file-bridge.js +4 -0
- package/lib/public/modules/pane-issue-bridge.js +4 -1
- package/lib/public/modules/pending-message-queue.js +1 -0
- package/lib/public/modules/permission-control.js +5 -4
- package/lib/public/modules/personal-settings-dialog.js +7 -1
- package/lib/public/modules/product-review.js +26 -0
- package/lib/public/modules/profile.js +1 -238
- package/lib/public/modules/project-access-recovery.js +17 -0
- package/lib/public/modules/project-admin-overview.js +21 -0
- package/lib/public/modules/project-chat-identity.js +13 -4
- package/lib/public/modules/project-logs-render.js +3 -0
- package/lib/public/modules/project-mate-navigation.js +144 -22
- package/lib/public/modules/rewind.js +5 -0
- package/lib/public/modules/scheduled-tasks.js +2 -0
- package/lib/public/modules/scheduler.js +2 -0
- package/lib/public/modules/search-clay-chat.js +5 -440
- package/lib/public/modules/session-actions.js +5 -2
- package/lib/public/modules/session-context-menu.js +5 -0
- package/lib/public/modules/session-create-form.js +10 -10
- package/lib/public/modules/session-folder-layout.js +1 -1
- package/lib/public/modules/session-folder-view-menu.js +9 -0
- package/lib/public/modules/session-github.js +85 -14
- package/lib/public/modules/session-rich-drafts.js +21 -0
- package/lib/public/modules/session-switch-defer.js +67 -0
- package/lib/public/modules/session-work-primary.js +51 -0
- package/lib/public/modules/settings-defaults.js +27 -28
- package/lib/public/modules/shared-browser-settings.js +112 -0
- package/lib/public/modules/shared-browser-tabs.js +13 -3
- package/lib/public/modules/shared-browser.js +29 -6
- package/lib/public/modules/sidebar-mobile.js +4 -3
- package/lib/public/modules/sidebar-projects.js +1 -0
- package/lib/public/modules/sidebar-session-folders-ui.js +1 -1
- package/lib/public/modules/sidebar-sessions.js +1 -0
- package/lib/public/modules/split-group-restore.js +68 -0
- package/lib/public/modules/split-pair-ui.js +1 -0
- package/lib/public/modules/split-pane-reconciler.js +15 -0
- package/lib/public/modules/split-pane-renderer.js +87 -6
- package/lib/public/modules/split-session-boundary.js +1 -1
- package/lib/public/modules/split-view.js +60 -68
- package/lib/public/modules/sticky-note-markdown.js +72 -6
- package/lib/public/modules/sticky-notes-actions.js +30 -0
- package/lib/public/modules/sticky-notes-browser.js +9 -2
- package/lib/public/modules/sticky-notes-card.js +23 -7
- package/lib/public/modules/sticky-notes-checklist.js +116 -0
- package/lib/public/modules/sticky-notes-editor.js +108 -44
- package/lib/public/modules/sticky-notes-shared.js +50 -2
- package/lib/public/modules/sticky-notes-state.js +66 -0
- package/lib/public/modules/sticky-notes.js +34 -51
- package/lib/public/modules/stt-controller.js +4 -1
- package/lib/public/modules/stt-recording.js +1 -1
- package/lib/public/modules/stt.js +7 -2
- package/lib/public/modules/terminal.js +9 -0
- package/lib/public/modules/theme.js +8 -1
- package/lib/public/modules/thinking-lifecycle.js +33 -3
- package/lib/public/modules/thinking-view.js +23 -1
- package/lib/public/modules/tools.js +60 -11
- package/lib/public/modules/tui-grab.js +1 -2
- package/lib/public/modules/user-settings-appearance.js +10 -3
- package/lib/public/modules/user-settings-editors.js +1 -1
- package/lib/public/modules/user-settings-layout.js +11 -2
- package/lib/public/modules/user-settings-preferences.js +6 -2
- package/lib/public/modules/user-settings-profile.js +12 -2
- package/lib/public/modules/user-settings.js +3 -2
- package/lib/public/modules/vendor-login-browser.js +5 -3
- package/lib/public/modules/vendor-login.js +2 -2
- package/lib/public/modules/vendor-priority.js +15 -1
- package/lib/public/modules/wireframe-workbench.js +5 -2
- package/lib/public/muse-avatar.svg +4 -0
- package/lib/public/style.css +5 -0
- package/lib/public/sw.js +3 -1
- package/lib/safe-bash-commands.js +3 -45
- package/lib/scheduled-task-records.js +3 -1
- package/lib/scheduler.js +2 -0
- package/lib/sdk-bridge.js +342 -401
- package/lib/sdk-foreground-admission.js +16 -0
- package/lib/sdk-mcp-descriptors.js +2 -37
- package/lib/sdk-message-processor.js +52 -17
- package/lib/sdk-quota-snapshot.js +1 -1
- package/lib/sdk-response-recovery.js +1 -0
- package/lib/sdk-worker.js +2 -677
- package/lib/server-admin.js +63 -16
- package/lib/server-appearance-settings.js +13 -1
- package/lib/server-contextual-clay-settings.js +40 -0
- package/lib/server-contextual-mate-sessions.js +70 -0
- package/lib/server-dm.js +2 -1
- package/lib/server-global-ws.js +10 -20
- package/lib/server-home-chat-events.js +18 -4
- package/lib/server-home-chat.js +22 -20
- package/lib/server-home-clay-entry.js +23 -4
- package/lib/server-home-clay-session-links.js +29 -9
- package/lib/server-home-mate-creation.js +1 -0
- package/lib/server-home-mcp-consent.js +14 -0
- package/lib/server-mates.js +25 -62
- package/lib/server-owner-ui.js +118 -0
- package/lib/server-path-access.js +38 -0
- package/lib/server-project-removal.js +22 -0
- package/lib/server-settings.js +6 -1
- package/lib/server.js +163 -43
- package/lib/session-config-transition.js +45 -0
- package/lib/session-folders.js +7 -2
- package/lib/session-fork-history.js +21 -0
- package/lib/session-github.js +9 -2
- package/lib/session-hygiene.js +3 -35
- package/lib/session-permission-mode.js +4 -3
- package/lib/session-skill-scope.js +11 -0
- package/lib/session-visibility.js +5 -2
- package/lib/session-work-primary.js +50 -0
- package/lib/sessions.js +64 -99
- package/lib/shared-browser-cookie-sync.js +32 -0
- package/lib/shared-browser-cookies.js +79 -0
- package/lib/shared-browser-runtime.js +25 -9
- package/lib/shared-browser-storage-sync.js +43 -0
- package/lib/shared-browser-storage.js +101 -0
- package/lib/shared-browser-tools.js +2 -1
- package/lib/shared-browser-worker.js +46 -10
- package/lib/terminal-manager.js +65 -6
- package/lib/tool-llm.js +1 -1
- package/lib/tui-transcript-index.js +1 -132
- package/lib/users-contextual-clay-preferences.js +31 -0
- package/lib/users-permissions.js +2 -8
- package/lib/users.js +7 -0
- package/lib/vendor-login-browser.js +1 -11
- package/lib/workspace-assignment-service.js +25 -0
- package/lib/workspace-query-access.js +4 -1
- package/lib/workspace-query-mcp-server.js +1 -1
- package/lib/workspace-query-service.js +13 -2
- package/lib/ws-request.js +1 -0
- package/lib/ws-schema.js +18 -2
- package/lib/yoke/acp-agent-profiles.js +7 -5
- package/lib/yoke/adapters/antigravity.js +3 -14
- package/lib/yoke/adapters/claude-query-contract.js +9 -0
- package/lib/yoke/adapters/claude.js +54 -50
- package/lib/yoke/adapters/codex-query-contract.js +24 -0
- package/lib/yoke/adapters/codex.js +53 -111
- package/lib/yoke/adapters/kiro.js +3 -1
- package/lib/yoke/adapters/muse-query-contract.js +7 -0
- package/lib/yoke/adapters/muse.js +122 -0
- package/lib/yoke/auth-events.js +17 -0
- package/lib/yoke/claude-hook-installer.js +271 -0
- package/lib/yoke/claude-jsonl-watcher.js +204 -0
- package/lib/yoke/claude-maintenance.js +55 -0
- package/lib/yoke/claude-permission-patterns.js +53 -0
- package/lib/yoke/claude-response-recovery.js +155 -0
- package/lib/yoke/claude-transcript-hygiene.js +34 -0
- package/lib/yoke/claude-worker-startup.js +28 -0
- package/lib/yoke/clay-skill-install.js +33 -0
- package/lib/yoke/cli-sessions.js +300 -0
- package/lib/yoke/codex-app-server.js +7 -12
- package/lib/yoke/codex-idle-recovery.js +81 -1
- package/lib/yoke/codex-recovery-admission.js +164 -0
- package/lib/yoke/configuration.js +13 -0
- package/lib/yoke/discovery.js +70 -0
- package/lib/yoke/errors.js +8 -0
- package/lib/yoke/host-environment.js +7 -0
- package/lib/yoke/index.js +9 -51
- package/lib/yoke/interface.js +116 -0
- package/lib/yoke/kiro-acp-server.js +5 -5
- package/lib/yoke/legacy-sessions.js +89 -0
- package/lib/yoke/login-protocol.js +25 -0
- package/lib/yoke/maintenance.js +12 -0
- package/lib/yoke/mcp-proxy.js +32 -0
- package/lib/yoke/mcp-source-adapters.js +91 -0
- package/lib/yoke/mcp-source-context.js +42 -0
- package/lib/yoke/mcp-source-discovery.js +169 -0
- package/lib/yoke/mcp-source-plugins.js +68 -0
- package/lib/yoke/mcp-source-restrictions.js +47 -0
- package/lib/yoke/mcp-tool-policy-normalize.js +28 -0
- package/lib/yoke/model-preferences.js +6 -0
- package/lib/yoke/muse-artifacts.js +36 -0
- package/lib/yoke/muse-controls.js +50 -0
- package/lib/yoke/muse-input.js +64 -0
- package/lib/yoke/muse-items.js +157 -0
- package/lib/yoke/muse-policy.js +52 -0
- package/lib/yoke/muse-query.js +428 -0
- package/lib/yoke/muse-runtime.js +211 -0
- package/lib/yoke/muse-services.js +79 -0
- package/lib/yoke/muse-skills.js +79 -0
- package/lib/yoke/muse-turns.js +71 -0
- package/lib/yoke/options/acp.js +2 -0
- package/lib/yoke/options/antigravity.js +2 -0
- package/lib/yoke/options/claude.js +21 -0
- package/lib/yoke/options/codex-defaults.js +29 -0
- package/lib/yoke/options/codex-settings.js +21 -0
- package/lib/yoke/options/codex.js +6 -0
- package/lib/yoke/options/kiro-defaults.js +22 -0
- package/lib/yoke/options/kiro.js +5 -0
- package/lib/yoke/options/muse.js +5 -0
- package/lib/yoke/provider-contract.js +5 -0
- package/lib/yoke/providers/antigravity-executable.js +8 -0
- package/lib/yoke/providers/claude-executable.js +40 -0
- package/lib/yoke/providers/claude-model-descriptions.js +14 -0
- package/lib/yoke/providers/claude-process.js +97 -0
- package/lib/yoke/providers/claude-provision.js +75 -0
- package/lib/yoke/providers/codex-errors.js +8 -0
- package/lib/yoke/providers/muse-executable.js +17 -0
- package/lib/yoke/provisioning.js +6 -0
- package/lib/yoke/query-options.js +10 -0
- package/lib/yoke/response-recovery.js +41 -0
- package/lib/yoke/sdk-mcp-descriptors.js +37 -0
- package/lib/yoke/sdk-server-factory.js +7 -0
- package/lib/yoke/session-history.js +8 -0
- package/lib/yoke/session-tool-transport.js +34 -13
- package/lib/yoke/settings.js +23 -0
- package/lib/yoke/source-locations.js +4 -0
- package/lib/yoke/title-query.js +18 -7
- package/lib/yoke/tui-transcript-index.js +132 -0
- package/lib/yoke/usage.js +48 -0
- package/lib/yoke/user-input.js +13 -0
- package/lib/yoke/vendor-registry.js +81 -1
- package/package.json +10 -4
package/lib/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,38 @@ 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_project_records": true,
|
|
735
|
+
"mcp__clay-workspace__inspect_project_record_change": true,
|
|
736
|
+
"mcp__clay-workspace__control_project_records": true,
|
|
737
|
+
"mcp__clay-workspace__read_mate_knowledge_control": true,
|
|
738
|
+
"mcp__clay-workspace__inspect_mate_knowledge_change": true,
|
|
739
|
+
"mcp__clay-workspace__control_mate_knowledge": true,
|
|
740
|
+
"mcp__clay-workspace__inspect_mate_control": true,
|
|
741
|
+
"mcp__clay-workspace__control_mate_lifecycle": true,
|
|
742
|
+
"mcp__clay-workspace__inspect_project_control": true,
|
|
743
|
+
"mcp__clay-workspace__control_project_lifecycle": true,
|
|
744
|
+
"mcp__clay-workspace__inspect_session_control": true,
|
|
745
|
+
"mcp__clay-workspace__control_project_session": true,
|
|
748
746
|
"mcp__clay-workspace__list_projects": true,
|
|
749
747
|
"mcp__clay-workspace__list_project_sessions": true,
|
|
750
748
|
"mcp__clay-workspace__search_project_history": true,
|
|
@@ -902,6 +900,7 @@ function createSDKBridge(opts) {
|
|
|
902
900
|
|
|
903
901
|
if (pushModule) {
|
|
904
902
|
pushModule.sendPush({
|
|
903
|
+
sessionId: session.localId,
|
|
905
904
|
type: "permission_request",
|
|
906
905
|
slug: slug,
|
|
907
906
|
requestId: requestId,
|
|
@@ -943,58 +942,13 @@ function createSDKBridge(opts) {
|
|
|
943
942
|
* Only returns processes whose cwd matches our project directory.
|
|
944
943
|
* Returns an array of { pid, command } for each conflicting process found.
|
|
945
944
|
*/
|
|
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
|
-
}
|
|
945
|
+
function findConflictingProcesses(session, error) {
|
|
946
|
+
var service = require("./yoke/provider-contract").resolve(getAdapterForSession(session)).processControl;
|
|
947
|
+
return service && typeof service.shouldInspect === "function" && service.shouldInspect(error) && typeof service.findConflicts === "function" ? service.findConflicts(cwd) : [];
|
|
986
948
|
}
|
|
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
|
-
}
|
|
949
|
+
function isProviderProcess(pid, session) {
|
|
950
|
+
var service = require("./yoke/provider-contract").resolve(session ? getAdapterForSession(session) : adapter).processControl;
|
|
951
|
+
return !!(service && typeof service.verifyProcess === "function" && service.verifyProcess(pid));
|
|
998
952
|
}
|
|
999
953
|
|
|
1000
954
|
function ownsQueryRuntime(session, queryInstance, queryGeneration) {
|
|
@@ -1006,6 +960,7 @@ function createSDKBridge(opts) {
|
|
|
1006
960
|
function recordRuntimeEffectivePermissionMode(session, queryInstance, queryGeneration, message) {
|
|
1007
961
|
if (!message || (message.yokeType !== "init" && message.yokeType !== "status") || !message.permissionMode) return false;
|
|
1008
962
|
if (!ownsQueryRuntime(session, queryInstance, queryGeneration)) return false;
|
|
963
|
+
session._permissionObservationRevision = Number(session._permissionObservationRevision || 0) + 1;
|
|
1009
964
|
session.effectivePermissionMode = message.permissionMode;
|
|
1010
965
|
session.permissionModeFallbackReason = null;
|
|
1011
966
|
sm.saveSessionFile(session);
|
|
@@ -1036,7 +991,8 @@ function createSDKBridge(opts) {
|
|
|
1036
991
|
return true;
|
|
1037
992
|
}
|
|
1038
993
|
|
|
1039
|
-
async function processQueryStream(session,
|
|
994
|
+
async function processQueryStream(session, catalogCandidate, queryContract) {
|
|
995
|
+
queryContract = queryContract || yoke.sessionTools.contract(getAdapterForSession(session));
|
|
1040
996
|
// Capture references at start so we only clean up OUR resources in finally,
|
|
1041
997
|
// not resources from a newer query that may have been created after an abort.
|
|
1042
998
|
var myQueryInstance = session.queryInstance;
|
|
@@ -1047,7 +1003,7 @@ function createSDKBridge(opts) {
|
|
|
1047
1003
|
try {
|
|
1048
1004
|
for await (var msg of myQueryInstance) {
|
|
1049
1005
|
// An old iterator may drain after Stop or after a replacement query starts.
|
|
1050
|
-
if (!ownsQueryRuntime(session, myQueryInstance, myQueryGeneration)) continue;
|
|
1006
|
+
if (!ownsQueryRuntime(session, myQueryInstance, myQueryGeneration) || responseRecovery.stopping(session)) continue;
|
|
1051
1007
|
if ((session.taskStopRequested || (myAbortController && myAbortController.signal.aborted))
|
|
1052
1008
|
&& msg && msg.yokeType !== "error" && msg.yokeType !== "interrupted") continue;
|
|
1053
1009
|
if (msg && msg.yokeType !== "text_delta" && msg.yokeType !== "thinking_delta" && msg.yokeType !== "tool_input_delta") {
|
|
@@ -1091,6 +1047,7 @@ function createSDKBridge(opts) {
|
|
|
1091
1047
|
if (continuationIdentity && !ownsQueryRuntime(session, myQueryInstance, myQueryGeneration)) {
|
|
1092
1048
|
continue;
|
|
1093
1049
|
}
|
|
1050
|
+
responseRecovery.event(session, msg);
|
|
1094
1051
|
processSDKMessage(session, msg);
|
|
1095
1052
|
if (continuationIdentity) {
|
|
1096
1053
|
settleContinuationStartup(session, myQueryInstance, myQueryGeneration, true, null);
|
|
@@ -1101,26 +1058,21 @@ function createSDKBridge(opts) {
|
|
|
1101
1058
|
// permission state. Setter acknowledgement deliberately does not
|
|
1102
1059
|
// change this field.
|
|
1103
1060
|
recordRuntimeEffectivePermissionMode(session, myQueryInstance, myQueryGeneration, msg);
|
|
1104
|
-
if (
|
|
1061
|
+
if (catalogCandidate && msg && msg.yokeType === "session_started" && msg.sessionId
|
|
1105
1062
|
&& session.queryInstance === myQueryInstance
|
|
1106
|
-
&& Number(session._sdkQueryGeneration || 0) ===
|
|
1063
|
+
&& Number(session._sdkQueryGeneration || 0) === catalogCandidate.generation
|
|
1107
1064
|
&& session.cliSessionId === msg.sessionId
|
|
1108
1065
|
&& (!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;
|
|
1066
|
+
queryContract.recordCatalog(session, catalogCandidate.versions);
|
|
1115
1067
|
sm.saveSessionFile(session);
|
|
1116
|
-
|
|
1068
|
+
catalogCandidate = null;
|
|
1117
1069
|
}
|
|
1118
1070
|
}
|
|
1119
1071
|
// (getContextUsage moved to processSDKMessage result handler -- fire-and-forget)
|
|
1120
1072
|
// Stream ended normally after a task stop — no "result" message was sent,
|
|
1121
1073
|
// so the session is still marked as processing. Send interrupted feedback.
|
|
1122
1074
|
console.log("[sdk-bridge] processQueryStream ended: isProcessing=" + session.isProcessing + " taskStopRequested=" + session.taskStopRequested);
|
|
1123
|
-
var stillOwnsRuntime = session.queryInstance === myQueryInstance;
|
|
1075
|
+
var stillOwnsRuntime = session.queryInstance === myQueryInstance && !responseRecovery.stopping(session);
|
|
1124
1076
|
settleContinuationStartup(session, myQueryInstance, myQueryGeneration, false, "The successor query ended before initialization.");
|
|
1125
1077
|
if (session.isProcessing && session.taskStopRequested && stillOwnsRuntime) {
|
|
1126
1078
|
session._lastTurnInterrupted = true;
|
|
@@ -1131,9 +1083,7 @@ function createSDKBridge(opts) {
|
|
|
1131
1083
|
onProcessingChanged();
|
|
1132
1084
|
send({ type: "status", processing: false });
|
|
1133
1085
|
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?";
|
|
1086
|
+
var interruptMsg = (queryContract && queryContract.interruptionMessage) || "■ Conversation interrupted - tell the model what to do differently.";
|
|
1137
1087
|
sendAndRecord(session, { type: "info", text: interruptMsg });
|
|
1138
1088
|
sendAndRecord(session, { type: "done", code: 0 });
|
|
1139
1089
|
sm.broadcastSessionList();
|
|
@@ -1158,7 +1108,7 @@ function createSDKBridge(opts) {
|
|
|
1158
1108
|
}
|
|
1159
1109
|
} catch (err) {
|
|
1160
1110
|
settleContinuationStartup(session, myQueryInstance, myQueryGeneration, false, err.message || "The successor query failed before initialization.");
|
|
1161
|
-
if (session.isProcessing && session.queryInstance === myQueryInstance) {
|
|
1111
|
+
if (session.isProcessing && session.queryInstance === myQueryInstance && !responseRecovery.stopping(session)) {
|
|
1162
1112
|
session.isProcessing = false;
|
|
1163
1113
|
session._awaitingTurnResult = false;
|
|
1164
1114
|
session._queuedTurnCount = 0;
|
|
@@ -1168,9 +1118,7 @@ function createSDKBridge(opts) {
|
|
|
1168
1118
|
session._lastTurnInterrupted = true;
|
|
1169
1119
|
if (!session.destroying) {
|
|
1170
1120
|
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?";
|
|
1121
|
+
var interruptMsg2 = (queryContract && queryContract.interruptionMessage) || "■ Conversation interrupted - tell the model what to do differently.";
|
|
1174
1122
|
sendAndRecord(session, { type: "info", text: interruptMsg2 });
|
|
1175
1123
|
sendAndRecord(session, { type: "done", code: 0 });
|
|
1176
1124
|
}
|
|
@@ -1186,21 +1134,17 @@ function createSDKBridge(opts) {
|
|
|
1186
1134
|
console.error("[sdk-bridge] Query stream error for session " + session.localId + ":", errDetail);
|
|
1187
1135
|
console.error("[sdk-bridge] Stack:", err.stack || "(no stack)");
|
|
1188
1136
|
|
|
1189
|
-
|
|
1190
|
-
var isExitCode1 = err.exitCode === 1 || (err.message && err.message.indexOf("exited with code 1") !== -1);
|
|
1191
|
-
var conflicts = isExitCode1 ? findConflictingClaude() : [];
|
|
1137
|
+
var conflicts = findConflictingProcesses(session, err);
|
|
1192
1138
|
if (conflicts.length > 0) {
|
|
1193
|
-
console.error("[sdk-bridge] Found " + conflicts.length + " conflicting
|
|
1139
|
+
console.error("[sdk-bridge] Found " + conflicts.length + " conflicting provider process(es):", conflicts.map(function(c) { return "PID " + c.pid; }).join(", "));
|
|
1194
1140
|
sendAndRecord(session, {
|
|
1195
1141
|
type: "process_conflict",
|
|
1196
|
-
text: "Another
|
|
1142
|
+
text: "Another provider process is already running in this project.",
|
|
1197
1143
|
processes: conflicts,
|
|
1198
1144
|
});
|
|
1199
1145
|
} else {
|
|
1200
1146
|
var errLower = errDetail.toLowerCase();
|
|
1201
|
-
var isContextOverflow =
|
|
1202
|
-
|| errLower.indexOf("context_length") !== -1
|
|
1203
|
-
|| errLower.indexOf("maximum context length") !== -1;
|
|
1147
|
+
var isContextOverflow = require("./yoke/errors").contextOverflow(errDetail);
|
|
1204
1148
|
var isAuthError = isAuthErrorMessage(errDetail);
|
|
1205
1149
|
if (isContextOverflow) {
|
|
1206
1150
|
sendAndRecord(session, {
|
|
@@ -1247,7 +1191,7 @@ function createSDKBridge(opts) {
|
|
|
1247
1191
|
// chat message already sent above
|
|
1248
1192
|
}
|
|
1249
1193
|
} else {
|
|
1250
|
-
sendAndRecord(session, { type: "error", text: "
|
|
1194
|
+
sendAndRecord(session, { type: "error", text: "Provider process error: " + err.message });
|
|
1251
1195
|
}
|
|
1252
1196
|
}
|
|
1253
1197
|
sendAndRecord(session, { type: "done", code: 1 });
|
|
@@ -1272,7 +1216,8 @@ function createSDKBridge(opts) {
|
|
|
1272
1216
|
}
|
|
1273
1217
|
if (session.messageQueue === myMessageQueue) session.messageQueue = null;
|
|
1274
1218
|
if (session.abortController === myAbortController) session.abortController = null;
|
|
1275
|
-
if (ownsRuntime) {
|
|
1219
|
+
if (ownsRuntime && !responseRecovery.stopping(session)) {
|
|
1220
|
+
responseRecovery.cancel(session);
|
|
1276
1221
|
session.taskStopRequested = false;
|
|
1277
1222
|
session.pendingPermissions = {};
|
|
1278
1223
|
// Preserve only restored legacy MCP entries. Canonical Yoke requests
|
|
@@ -1321,7 +1266,7 @@ function createSDKBridge(opts) {
|
|
|
1321
1266
|
}
|
|
1322
1267
|
}
|
|
1323
1268
|
}
|
|
1324
|
-
if (!session.isProcessing && typeof opts.onSessionAvailable === "function") opts.onSessionAvailable(session);
|
|
1269
|
+
if (!responseRecovery.stopping(session) && !session.isProcessing && typeof opts.onSessionAvailable === "function") opts.onSessionAvailable(session);
|
|
1325
1270
|
}
|
|
1326
1271
|
}
|
|
1327
1272
|
|
|
@@ -1329,20 +1274,16 @@ function createSDKBridge(opts) {
|
|
|
1329
1274
|
if (session.queryInstance) return { query: session.queryInstance, isTemp: false, cleanup: function() {} };
|
|
1330
1275
|
|
|
1331
1276
|
var handle;
|
|
1277
|
+
var selectedAdapter = getAdapterForSession(session);
|
|
1332
1278
|
try {
|
|
1333
|
-
handle = await
|
|
1279
|
+
handle = await selectedAdapter.createQuery({
|
|
1334
1280
|
cwd: cwd,
|
|
1335
1281
|
resumeSessionId: session.cliSessionId,
|
|
1336
1282
|
env: getRuntimeEnv(session),
|
|
1337
|
-
adapterOptions: {
|
|
1338
|
-
CLAUDE: {
|
|
1339
|
-
settingSources: ["user", "project", "local"],
|
|
1340
|
-
enableFileCheckpointing: true,
|
|
1341
|
-
},
|
|
1342
|
-
},
|
|
1283
|
+
adapterOptions: require("./yoke/query-options").map(getAdapterForSession(session), { nativePermissionMode: "default" }),
|
|
1343
1284
|
});
|
|
1344
1285
|
} catch (e) {
|
|
1345
|
-
sendAndRecord(session, { type: "error", text: "Failed to load
|
|
1286
|
+
sendAndRecord(session, { type: "error", text: "Failed to load provider session: " + (e.message || e) });
|
|
1346
1287
|
throw e;
|
|
1347
1288
|
}
|
|
1348
1289
|
|
|
@@ -1409,7 +1350,7 @@ function createSDKBridge(opts) {
|
|
|
1409
1350
|
// abort the whole rewind instead of leaving local history trimmed
|
|
1410
1351
|
// ahead of the real, un-rolled-back provider thread.
|
|
1411
1352
|
if (!turnId) {
|
|
1412
|
-
throw new Error("No turn id recorded for this turn; cannot roll back the
|
|
1353
|
+
throw new Error("No turn id recorded for this turn; cannot roll back the provider thread.");
|
|
1413
1354
|
}
|
|
1414
1355
|
await sessionAdapter.rollbackThread(session.cliSessionId, turnId, {
|
|
1415
1356
|
linuxUser: getSessionLinuxUser(session) || undefined,
|
|
@@ -1425,6 +1366,8 @@ function createSDKBridge(opts) {
|
|
|
1425
1366
|
|
|
1426
1367
|
async function forkSessionUnified(session, uuid) {
|
|
1427
1368
|
var sessionAdapter = getAdapterForSession(session);
|
|
1369
|
+
var localHistoryEndIndex = require("./session-fork-history").endIndex(session, uuid,
|
|
1370
|
+
require("./yoke/provider-contract").resolve(sessionAdapter).forkHistoryBoundary);
|
|
1428
1371
|
var result = await sessionAdapter.forkSession(session.cliSessionId, {
|
|
1429
1372
|
upToMessageId: uuid,
|
|
1430
1373
|
dir: cwd,
|
|
@@ -1433,8 +1376,10 @@ function createSDKBridge(opts) {
|
|
|
1433
1376
|
if (!result || !result.sessionId) throw new Error("Fork returned no session id");
|
|
1434
1377
|
|
|
1435
1378
|
// Adapters with rollbackThread (e.g. Codex) use local history copy
|
|
1436
|
-
if (typeof sessionAdapter.rollbackThread === "function") {
|
|
1437
|
-
|
|
1379
|
+
if (result.useLocalHistory === true || typeof sessionAdapter.rollbackThread === "function") {
|
|
1380
|
+
var localFork = { sessionId: result.sessionId, useLocalHistory: true };
|
|
1381
|
+
if (localHistoryEndIndex !== undefined) localFork.localHistoryEndIndex = localHistoryEndIndex;
|
|
1382
|
+
return localFork;
|
|
1438
1383
|
}
|
|
1439
1384
|
// Claude: read history from CLI session files
|
|
1440
1385
|
return { sessionId: result.sessionId, useLocalHistory: false };
|
|
@@ -1442,22 +1387,69 @@ function createSDKBridge(opts) {
|
|
|
1442
1387
|
|
|
1443
1388
|
// Wrapper: marks the boot window so pushMessage can buffer instead of
|
|
1444
1389
|
// dropping messages that arrive while createQuery is still awaiting.
|
|
1445
|
-
async function startQuery(session, text, images, linuxUser, beforePush, onAccepted) {
|
|
1390
|
+
async function startQuery(session, text, images, linuxUser, beforePush, onAccepted, retryState) {
|
|
1391
|
+
if (opts.isLifecycleExecutionPaused && opts.isLifecycleExecutionPaused()) {
|
|
1392
|
+
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." });
|
|
1393
|
+
session.isProcessing = false; onProcessingChanged(); sendAndRecord(session, { type: "done", code: 1 }); return false;
|
|
1394
|
+
}
|
|
1395
|
+
if (session._responseRecoveryStopPending && !retryState) {
|
|
1396
|
+
session.isProcessing = false;
|
|
1397
|
+
onProcessingChanged();
|
|
1398
|
+
sendAndRecord(session, { type: "error", text: "The previous Claude attempt has not confirmed stopped. Check the connection before sending this message again." });
|
|
1399
|
+
sendAndRecord(session, { type: "done", code: 1 });
|
|
1400
|
+
return false;
|
|
1401
|
+
}
|
|
1402
|
+
if (responseRecovery.stopping(session) && !retryState) return false;
|
|
1446
1403
|
delete session._lastTurnInterrupted;
|
|
1404
|
+
var payload = { text: text, images: images, linuxUser: linuxUser, beforePush: beforePush };
|
|
1405
|
+
var recoveryState = responseRecovery.begin(session, payload, retryState);
|
|
1406
|
+
if (recoveryState) recoveryState.handle = null;
|
|
1407
|
+
var guardedPush = function() {
|
|
1408
|
+
return !session.destroying && !session.taskStopRequested
|
|
1409
|
+
&& (!recoveryState || responseRecovery.valid(session, recoveryState) && !recoveryState.stopping)
|
|
1410
|
+
&& (typeof beforePush !== "function" || beforePush() === true);
|
|
1411
|
+
};
|
|
1412
|
+
guardedPush.exactProductDelivery = !!(beforePush && beforePush.exactProductDelivery);
|
|
1447
1413
|
session._queryGeneration = (session._queryGeneration || 0) + 1;
|
|
1448
1414
|
session._queryStarting = true;
|
|
1415
|
+
var starting = startQueryInner(session, text, images, linuxUser, guardedPush, onAccepted, recoveryState);
|
|
1416
|
+
if (recoveryState) recoveryState.starting = starting;
|
|
1449
1417
|
try {
|
|
1450
|
-
|
|
1418
|
+
var accepted = await starting;
|
|
1419
|
+
if (accepted === false && (!recoveryState || !recoveryState.stopping)) {
|
|
1420
|
+
responseRecovery.cancel(session);
|
|
1421
|
+
session.isProcessing = false;
|
|
1422
|
+
onProcessingChanged();
|
|
1423
|
+
}
|
|
1424
|
+
return accepted;
|
|
1425
|
+
} catch (error) {
|
|
1426
|
+
// Includes synchronous input queue failures, before stream consumption.
|
|
1427
|
+
var failedHandle = session.queryInstance;
|
|
1428
|
+
if (failedHandle) {
|
|
1429
|
+
try { if (typeof failedHandle.abort === "function") failedHandle.abort(); } catch (e) {}
|
|
1430
|
+
try { if (typeof failedHandle.close === "function") failedHandle.close(); } catch (e) {}
|
|
1431
|
+
}
|
|
1432
|
+
session.queryInstance = null;
|
|
1433
|
+
session.abortController = null;
|
|
1434
|
+
session.messageQueue = null;
|
|
1435
|
+
session.isProcessing = false;
|
|
1436
|
+
session._awaitingTurnResult = false;
|
|
1437
|
+
session._queuedTurnCount = 0;
|
|
1438
|
+
taskLifecycle.clearAll(session);
|
|
1439
|
+
if (!recoveryState || !recoveryState.stopping) {
|
|
1440
|
+
responseRecovery.cancel(session);
|
|
1441
|
+
sendAndRecord(session, { type: "error", text: "The agent connection failed while delivering your message. Please retry or check the connection." });
|
|
1442
|
+
sendAndRecord(session, { type: "done", code: 1 });
|
|
1443
|
+
onProcessingChanged();
|
|
1444
|
+
sm.broadcastSessionList();
|
|
1445
|
+
}
|
|
1446
|
+
return false;
|
|
1451
1447
|
} finally {
|
|
1452
1448
|
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);
|
|
1449
|
+
delete session._providerRecoveryWaiting;
|
|
1450
|
+
if (!session.queryInstance && session.pendingPush && session.pendingPush.length) session.pendingPush = [];
|
|
1451
|
+
if (!session.queryInstance && !session.isProcessing && !session._pendingMessageDrainPaused && !responseRecovery.stopping(session)) session.taskStopRequested = false;
|
|
1452
|
+
if (!responseRecovery.stopping(session) && !session.isProcessing && typeof opts.onSessionAvailable === "function") opts.onSessionAvailable(session);
|
|
1461
1453
|
}
|
|
1462
1454
|
}
|
|
1463
1455
|
|
|
@@ -1501,7 +1493,7 @@ function createSDKBridge(opts) {
|
|
|
1501
1493
|
};
|
|
1502
1494
|
}
|
|
1503
1495
|
|
|
1504
|
-
async function startQueryInner(session, text, images, linuxUser, beforePush, onAccepted) {
|
|
1496
|
+
async function startQueryInner(session, text, images, linuxUser, beforePush, onAccepted, recoveryState) {
|
|
1505
1497
|
var sessionRuntimeEnv = getRuntimeEnv(session);
|
|
1506
1498
|
var resumedAtQueryStart = !!session.cliSessionId;
|
|
1507
1499
|
async function ensureVendorReady(vendor) {
|
|
@@ -1653,7 +1645,8 @@ function createSDKBridge(opts) {
|
|
|
1653
1645
|
|
|
1654
1646
|
// Ensure Linux user project directory exists (runs in parallel with worker boot)
|
|
1655
1647
|
if (linuxUser) {
|
|
1656
|
-
|
|
1648
|
+
var preparation = require("./yoke/provider-contract").resolve(sessionAdapter).prepareIsolation;
|
|
1649
|
+
if (typeof preparation === "function") preparation(linuxUser, session, cwd);
|
|
1657
1650
|
}
|
|
1658
1651
|
|
|
1659
1652
|
session.blocks = {};
|
|
@@ -1670,100 +1663,27 @@ function createSDKBridge(opts) {
|
|
|
1670
1663
|
session.abortController = new AbortController();
|
|
1671
1664
|
}
|
|
1672
1665
|
|
|
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
1666
|
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
|
|
1667
|
+
if (ls.permissionMode) session._loopPermissionMode = ls.permissionMode;
|
|
1668
|
+
var permissionMode = session.permissionMode || sm.currentPermissionMode || "default";
|
|
1669
|
+
var nativeMode = permissionMode === "bypassPermissions" ? "default" : session.acceptEditsAfterStart ? "acceptEdits" : permissionMode;
|
|
1670
|
+
var isolationHome = null;
|
|
1751
1671
|
if (linuxUser) {
|
|
1752
|
-
|
|
1753
|
-
|
|
1754
|
-
|
|
1755
|
-
|
|
1756
|
-
|
|
1757
|
-
|
|
1758
|
-
}
|
|
1759
|
-
|
|
1760
|
-
|
|
1761
|
-
|
|
1762
|
-
|
|
1763
|
-
|
|
1764
|
-
|
|
1765
|
-
|
|
1766
|
-
|
|
1672
|
+
try { isolationHome = require("./os-users").resolveOsUserInfo(linuxUser).home; } catch (error) {}
|
|
1673
|
+
}
|
|
1674
|
+
var executionIntent = {
|
|
1675
|
+
settings: sm, permissionMode: permissionMode, nativePermissionMode: session._loopPermissionMode || nativeMode,
|
|
1676
|
+
nativeBypass: dangerouslySkipPermissions || session.mode === "tui" && session.dangerouslySkipPermissions,
|
|
1677
|
+
readOnly: !!session.youCurator, betas: sm.currentBetas,
|
|
1678
|
+
thinking: { mode: ls.thinking || sm.currentThinking, budget: ls.thinkingBudget || sm.currentThinkingBudget },
|
|
1679
|
+
disableHooks: ls.disableAllHooks, resumeAt: session.cliSessionId && session.lastRewindUuid || undefined,
|
|
1680
|
+
singleTurn: !!session.singleTurn, startedAt: t0,
|
|
1681
|
+
isolation: { user: linuxUser, home: isolationHome, projectPath: session.cwd || null, workerState: session._adapterWorkerState },
|
|
1682
|
+
sessionBridge: null,
|
|
1683
|
+
};
|
|
1684
|
+
if (session.acceptEditsAfterStart) delete session.acceptEditsAfterStart;
|
|
1685
|
+
if (executionIntent.resumeAt) { delete session.lastRewindUuid; sm.saveSessionFile(session); }
|
|
1686
|
+
if (linuxUser && session._adapterWorkerState) session._adapterWorkerState = null;
|
|
1767
1687
|
|
|
1768
1688
|
// Pick a model from the session or its vendor-specific default, then
|
|
1769
1689
|
// validate it against the session vendor's known model list.
|
|
@@ -1789,20 +1709,21 @@ function createSDKBridge(opts) {
|
|
|
1789
1709
|
sm.saveSessionFile(session);
|
|
1790
1710
|
}
|
|
1791
1711
|
|
|
1792
|
-
var codexConfig = getCodexConfig(sm);
|
|
1793
|
-
var kiroConfig = getKiroConfig(sm);
|
|
1794
1712
|
session._sdkQueryGeneration = Number(session._sdkQueryGeneration || 0) + 1;
|
|
1795
1713
|
// Individual feature modules own their transport capability checks. Do not
|
|
1796
1714
|
// suppress unrelated session tools merely because one feature cannot be
|
|
1797
1715
|
// delivered by this provider.
|
|
1798
1716
|
var sessionToolDefs = getSessionToolDefs(session) || [];
|
|
1799
1717
|
var queryGeneration = Number(session._sdkQueryGeneration || 0);
|
|
1718
|
+
executionIntent.sessionBridge = getAcpMcpServers(session);
|
|
1719
|
+
var queryContract = yoke.sessionTools.contract(sessionAdapter);
|
|
1720
|
+
function needsCatalogRecovery(family, version) {
|
|
1721
|
+
return yoke.sessionTools.needsRecovery(sessionAdapter, session, family, version);
|
|
1722
|
+
}
|
|
1800
1723
|
var hasYouCatalog = sessionToolDefs.some(function (tool) { return tool.name === "search_user_knowledge"; });
|
|
1801
|
-
var
|
|
1802
|
-
&& hasYouCatalog && Number(session.codexYouToolCatalogVersion || 0) < 1;
|
|
1724
|
+
var recoverYouTools = needsCatalogRecovery("knowledge", 1) && hasYouCatalog;
|
|
1803
1725
|
var hasLinearCatalog = sessionToolDefs.some(function (tool) { return tool.name === "link_session_linear"; });
|
|
1804
|
-
var
|
|
1805
|
-
&& hasLinearCatalog && Number(session.codexLinearToolCatalogVersion || 0) < 1 && canUseSessionTools(session) === true;
|
|
1726
|
+
var recoverLinearTools = needsCatalogRecovery("linear", 1) && hasLinearCatalog && canUseSessionTools(session) === true;
|
|
1806
1727
|
var hasIssueCatalog = false;
|
|
1807
1728
|
for (var issueToolIndex = 0; issueToolIndex < sessionToolDefs.length; issueToolIndex++) {
|
|
1808
1729
|
if (sessionToolDefs[issueToolIndex].name === "create_issue") {
|
|
@@ -1811,24 +1732,23 @@ function createSDKBridge(opts) {
|
|
|
1811
1732
|
}
|
|
1812
1733
|
}
|
|
1813
1734
|
var hasSharedBrowserCatalog = sessionToolDefs.some(function (definition) { return definition.name === "shared_browser"; });
|
|
1814
|
-
var
|
|
1815
|
-
|
|
1816
|
-
var recoverCodexIssueTools = sessionAdapter.vendor === "codex"
|
|
1817
|
-
&& !!session.cliSessionId
|
|
1818
|
-
&& hasIssueCatalog
|
|
1819
|
-
&& Number(session.codexIssuesToolCatalogVersion || 0) < 1;
|
|
1735
|
+
var recoverBrowserTools = needsCatalogRecovery("browser", 6) && hasSharedBrowserCatalog;
|
|
1736
|
+
var recoverIssueTools = needsCatalogRecovery("issues", 1) && hasIssueCatalog;
|
|
1820
1737
|
function queryContextAvailable() {
|
|
1738
|
+
if (queryRetired()) return false;
|
|
1821
1739
|
if (Number(session._sdkQueryGeneration || 0) !== queryGeneration) return false;
|
|
1822
1740
|
if (sm && sm.sessions && typeof sm.sessions.get === "function" && sm.sessions.get(session.localId) !== session) return false;
|
|
1823
1741
|
return canUseSessionTools(session) === true;
|
|
1824
1742
|
}
|
|
1743
|
+
var hasMateScheduleTool = sessionToolDefs.some(function (tool) { return yoke.sessionTools.MATE_SCHEDULE_TOOLS.indexOf(tool.name) !== -1; });
|
|
1744
|
+
var recoverMateSchedules = needsCatalogRecovery() && hasMateScheduleTool && queryContextAvailable();
|
|
1825
1745
|
var hasScheduleTool = false;
|
|
1826
1746
|
var hasScheduleInterviewTool = false;
|
|
1827
1747
|
var scheduleInterviewActive = null;
|
|
1828
1748
|
var scheduleQuestionLimit = null;
|
|
1829
1749
|
for (var sessionToolIndex = 0; sessionToolIndex < sessionToolDefs.length; sessionToolIndex++) {
|
|
1830
1750
|
if (yoke.sessionTools.SCHEDULE_TOOLS.indexOf(sessionToolDefs[sessionToolIndex].name) !== -1) hasScheduleTool = true;
|
|
1831
|
-
if (sessionToolDefs[sessionToolIndex].name
|
|
1751
|
+
if (["begin_scheduled_task_interview", "begin_mate_schedule_interview", "begin_schedule_control_interview"].indexOf(sessionToolDefs[sessionToolIndex].name) >= 0) {
|
|
1832
1752
|
hasScheduleInterviewTool = true;
|
|
1833
1753
|
scheduleInterviewActive = sessionToolDefs[sessionToolIndex].scheduleInterviewActive || null;
|
|
1834
1754
|
scheduleQuestionLimit = sessionToolDefs[sessionToolIndex].structuredQuestionLimit || null;
|
|
@@ -1838,10 +1758,10 @@ function createSDKBridge(opts) {
|
|
|
1838
1758
|
var activeLoopInterview = !isDriverOperatedSession(session) && !session.loopInterviewHandoff && !activeRun && !!loopInterview.activeInterviewId(session);
|
|
1839
1759
|
var structuredInputSession = hasScheduleInterviewTool || activeLoopInterview || (!isDriverOperatedSession(session) && session.ralphCraftingMode === true && session.loop && session.loop.role === "crafting");
|
|
1840
1760
|
var requestedUserInputMode = session.debateSetupMode || session.mateCreationMode ? "fallback" : "auto";
|
|
1841
|
-
if (structuredInputSession
|
|
1761
|
+
if (structuredInputSession) requestedUserInputMode = "fallback";
|
|
1762
|
+
if (requestedUserInputMode === "auto" && queryContract.defaultUserInputMode) requestedUserInputMode = queryContract.defaultUserInputMode;
|
|
1842
1763
|
var selectedUserInputMode = yoke.userInput.selectMode(sessionAdapter, requestedUserInputMode);
|
|
1843
|
-
var
|
|
1844
|
-
&& Number(session.codexUserInputToolCatalogVersion || 0) < 1 && queryContextAvailable();
|
|
1764
|
+
var recoverQuestionTools = needsCatalogRecovery("questions", 1) && queryContextAvailable();
|
|
1845
1765
|
function structuredInputContextAvailable() {
|
|
1846
1766
|
if (!queryContextAvailable()) return false;
|
|
1847
1767
|
// A schedule-triggered fallback shares the schedule feature's live
|
|
@@ -1860,9 +1780,10 @@ function createSDKBridge(opts) {
|
|
|
1860
1780
|
return "Ask exactly one question at a time, wait for the answer, then ask the next question.";
|
|
1861
1781
|
}
|
|
1862
1782
|
var sessionUserInputHandler = function(request, respond) {
|
|
1863
|
-
if (!structuredInputContextAvailable()) {
|
|
1783
|
+
if (queryRetired() || !structuredInputContextAvailable()) {
|
|
1864
1784
|
return respond.cancel("This structured-input request belongs to an unavailable or older query.");
|
|
1865
1785
|
}
|
|
1786
|
+
responseRecovery.progress(session);
|
|
1866
1787
|
var questionError = scheduleQuestionError(request);
|
|
1867
1788
|
if (questionError) return respond.cancel(questionError);
|
|
1868
1789
|
if (request.presentation === "elicitation" && request.diagnostics && request.diagnostics.elicitation) {
|
|
@@ -1882,21 +1803,33 @@ function createSDKBridge(opts) {
|
|
|
1882
1803
|
return opts.onUserInputRequest(session, request, respond);
|
|
1883
1804
|
};
|
|
1884
1805
|
var localMcpServers = getMcpServers(session);
|
|
1885
|
-
if (
|
|
1806
|
+
if (queryContract.toolTransport === "sdk-mcp" && (hasScheduleTool || hasMateScheduleTool)
|
|
1807
|
+
&& typeof sessionAdapter.createToolServer !== "function") {
|
|
1808
|
+
throw new Error("The adapter cannot mount native schedule tools without createToolServer.");
|
|
1809
|
+
}
|
|
1810
|
+
if (queryContract.toolTransport === "sdk-mcp" && hasScheduleTool) {
|
|
1886
1811
|
var scheduledTaskToolDefs = [];
|
|
1887
1812
|
for (var scheduledToolIndex = 0; scheduledToolIndex < sessionToolDefs.length; scheduledToolIndex++) {
|
|
1888
1813
|
if (yoke.sessionTools.SCHEDULE_TOOLS.indexOf(sessionToolDefs[scheduledToolIndex].name) !== -1) scheduledTaskToolDefs.push(sessionToolDefs[scheduledToolIndex]);
|
|
1889
1814
|
}
|
|
1890
1815
|
if (scheduledTaskToolDefs.length) {
|
|
1891
1816
|
var scheduledTaskServer = sessionAdapter.createToolServer({ name: "clay-scheduled-tasks", version: "1.0.0", tools: scheduledTaskToolDefs });
|
|
1892
|
-
if (scheduledTaskServer)
|
|
1893
|
-
|
|
1894
|
-
|
|
1895
|
-
}
|
|
1817
|
+
if (!scheduledTaskServer) throw new Error("The adapter could not mount scheduled-task tools.");
|
|
1818
|
+
localMcpServers = Object.assign({}, localMcpServers || {});
|
|
1819
|
+
localMcpServers["clay-scheduled-tasks"] = scheduledTaskServer;
|
|
1896
1820
|
}
|
|
1897
1821
|
}
|
|
1822
|
+
if (queryContract.toolTransport === "sdk-mcp" && hasMateScheduleTool) {
|
|
1823
|
+
localMcpServers = Object.assign({}, localMcpServers || {});
|
|
1824
|
+
localMcpServers["clay-mate-schedules"] = sessionAdapter.createToolServer({ name: "clay-mate-schedules", version: "1.0.0",
|
|
1825
|
+
tools: sessionToolDefs.filter(function (tool) { return yoke.sessionTools.MATE_SCHEDULE_TOOLS.indexOf(tool.name) !== -1; }) });
|
|
1826
|
+
if (!localMcpServers["clay-mate-schedules"]) throw new Error("The adapter could not mount Mate schedule tools.");
|
|
1827
|
+
}
|
|
1898
1828
|
if (selectedUserInputMode === "fallback") {
|
|
1899
1829
|
var userInputServer = yoke.userInput.createFallbackServer(sessionAdapter, sessionUserInputHandler, { force: true, maxQuestions: scheduleQuestionLimit });
|
|
1830
|
+
if (queryContract.toolTransport === "sdk-mcp" && !userInputServer) {
|
|
1831
|
+
throw new Error("The adapter could not mount structured-input tools.");
|
|
1832
|
+
}
|
|
1900
1833
|
if (userInputServer) {
|
|
1901
1834
|
localMcpServers = Object.assign({}, localMcpServers || {});
|
|
1902
1835
|
localMcpServers[userInputServer.name || "yoke-user-input"] = userInputServer;
|
|
@@ -1931,6 +1864,12 @@ function createSDKBridge(opts) {
|
|
|
1931
1864
|
return snapshotDef;
|
|
1932
1865
|
}
|
|
1933
1866
|
|
|
1867
|
+
var externalQueryBridge = require('./mcp-query-bridge').createQueryBridge({ valid: queryContextAvailable,
|
|
1868
|
+
getServers: function () { return getRemoteMcpServers ? getRemoteMcpServers(session) || {} : {}; } });
|
|
1869
|
+
var externalToolDefs = queryContract.externalToolTransport === "dynamic" ? externalQueryBridge.dynamicDefs() : [];
|
|
1870
|
+
if (externalToolDefs.length) { sessionToolDefs = sessionToolDefs.concat(externalToolDefs); queryToolSnapshots.set(session, { generation: queryGeneration, defs: sessionToolDefs.slice() }); }
|
|
1871
|
+
var recoverExternalTools = needsCatalogRecovery() && (externalToolDefs.length > 0 || isMate);
|
|
1872
|
+
|
|
1934
1873
|
// Give fresh queries an immediate provisional label. The visible user
|
|
1935
1874
|
// message in history wins over `text`, which may contain an internal
|
|
1936
1875
|
// provider wrapper rather than what the person typed.
|
|
@@ -1945,6 +1884,10 @@ function createSDKBridge(opts) {
|
|
|
1945
1884
|
}
|
|
1946
1885
|
|
|
1947
1886
|
var modelSwitchGeneration = session._queryGeneration;
|
|
1887
|
+
function queryRetired() {
|
|
1888
|
+
return Number(session._sdkQueryGeneration || 0) !== queryGeneration || session.taskStopRequested
|
|
1889
|
+
|| session.destroying || responseRecovery.stopping(session) || (handle && session.queryInstance !== handle);
|
|
1890
|
+
}
|
|
1948
1891
|
var queryOpts = {
|
|
1949
1892
|
onModelSwitch: function(change) {
|
|
1950
1893
|
if (session._queryGeneration !== modelSwitchGeneration || session.taskStopRequested) return;
|
|
@@ -1959,7 +1902,7 @@ function createSDKBridge(opts) {
|
|
|
1959
1902
|
clayBridgeToken: clayBridgeToken,
|
|
1960
1903
|
linuxUser: linuxUser || undefined,
|
|
1961
1904
|
env: sessionRuntimeEnv,
|
|
1962
|
-
skillOptions: getSessionSkillOptions(session),
|
|
1905
|
+
skillOptions: require("./session-skill-scope").bind(session, sm.sessions, getSessionSkillOptions(session), queryContextAvailable, usersModule.isMultiUser()),
|
|
1963
1906
|
// appendSystemPrompt, NOT systemPrompt: a plain-string systemPrompt
|
|
1964
1907
|
// REPLACES the entire Claude Code system prompt (sdk.d.ts:2096), which
|
|
1965
1908
|
// would strip the driver session down to the two-sentence pair preset.
|
|
@@ -1967,7 +1910,7 @@ function createSDKBridge(opts) {
|
|
|
1967
1910
|
// codex/kiro: prepend to the first message).
|
|
1968
1911
|
appendSystemPrompt: [
|
|
1969
1912
|
typeof opts.getSessionSystemPrompt === "function" ? opts.getSessionSystemPrompt(session) : "",
|
|
1970
|
-
|
|
1913
|
+
typeof queryContract.questionGuidance === "function" && queryContextAvailable() ? queryContract.questionGuidance() : "",
|
|
1971
1914
|
].filter(Boolean).join("\n\n") || undefined,
|
|
1972
1915
|
model: queryModel,
|
|
1973
1916
|
// Effort is remembered per vendor and clamped to the session vendor's
|
|
@@ -1984,10 +1927,22 @@ function createSDKBridge(opts) {
|
|
|
1984
1927
|
toolServers: mergedMcpServers,
|
|
1985
1928
|
toolServerDescriptors: extractMcpDescriptors(mergedMcpServers) || undefined,
|
|
1986
1929
|
dynamicTools: sessionToolDefs,
|
|
1987
|
-
//
|
|
1930
|
+
// Conversation-scoped catalogs persist definitions. A stale authorized Driver
|
|
1988
1931
|
// gets this exact-query bridge; its handlers still reauthorize live.
|
|
1989
|
-
sessionMcpServer: (
|
|
1932
|
+
sessionMcpServer: (recoverMateSchedules || recoverIssueTools || recoverQuestionTools || recoverBrowserTools || recoverLinearTools || recoverYouTools || recoverExternalTools) ? getSessionMcpServer(session, queryGeneration) : undefined,
|
|
1933
|
+
onRecoveryAdmission: function(waiting) {
|
|
1934
|
+
if (!queryContextAvailable()) return;
|
|
1935
|
+
if (waiting) session._providerRecoveryWaiting = queryGeneration;
|
|
1936
|
+
else delete session._providerRecoveryWaiting;
|
|
1937
|
+
},
|
|
1938
|
+
onRecoveryWaiting: function(waiting) {
|
|
1939
|
+
if (!queryContextAvailable()) return;
|
|
1940
|
+
sendAndRecord(session, { type: 'informational', level: 'info', content: waiting
|
|
1941
|
+
? 'Tool recovery is waiting for this conversation’s runtime to become safely available. Your message is retained; Stop cancels the wait.'
|
|
1942
|
+
: 'Tool recovery is ready. Continuing your retained message.' });
|
|
1943
|
+
},
|
|
1990
1944
|
callDynamicTool: function (toolName, args) {
|
|
1945
|
+
if (queryRetired() || !queryContextAvailable()) return Promise.reject(new Error("This session tool query is no longer available."));
|
|
1991
1946
|
var toolDef = findSessionToolDef(toolName);
|
|
1992
1947
|
if (toolDef && typeof toolDef.handler === "function") {
|
|
1993
1948
|
return toolDef.handler(args || {});
|
|
@@ -1997,7 +1952,10 @@ function createSDKBridge(opts) {
|
|
|
1997
1952
|
resumeSessionId: session.cliSessionId || undefined,
|
|
1998
1953
|
abortController: linuxUser ? undefined : session.abortController,
|
|
1999
1954
|
canUseTool: function(toolName, input, toolOpts) {
|
|
2000
|
-
|
|
1955
|
+
if (queryRetired()) return { behavior: "deny", message: "This attempt has stopped." };
|
|
1956
|
+
responseRecovery.progress(session);
|
|
1957
|
+
var questionInput = yoke.userInput.toolQuestions(sessionAdapter, toolName, input);
|
|
1958
|
+
var nativeQuestionError = questionInput ? scheduleQuestionError(questionInput) : null;
|
|
2001
1959
|
if (nativeQuestionError) return { behavior: "deny", message: nativeQuestionError };
|
|
2002
1960
|
var permissionName = toolName;
|
|
2003
1961
|
var permissionToolDef = findSessionToolDef(toolName);
|
|
@@ -2005,7 +1963,10 @@ function createSDKBridge(opts) {
|
|
|
2005
1963
|
return handleCanUseTool(session, permissionName, input, toolOpts);
|
|
2006
1964
|
},
|
|
2007
1965
|
preToolUsePolicy: function(toolName, input) {
|
|
2008
|
-
|
|
1966
|
+
if (queryRetired()) return Promise.resolve({ behavior: "deny", message: "This attempt has stopped." });
|
|
1967
|
+
responseRecovery.progress(session);
|
|
1968
|
+
var questionInput = yoke.userInput.toolQuestions(sessionAdapter, toolName, input);
|
|
1969
|
+
var nativeQuestionError = questionInput ? scheduleQuestionError(questionInput) : null;
|
|
2009
1970
|
if (nativeQuestionError) return Promise.resolve({ behavior: "deny", message: nativeQuestionError });
|
|
2010
1971
|
var permissionName = toolName;
|
|
2011
1972
|
var permissionToolDef = findSessionToolDef(toolName);
|
|
@@ -2018,47 +1979,45 @@ function createSDKBridge(opts) {
|
|
|
2018
1979
|
validateUserInputRequest: scheduleQuestionError,
|
|
2019
1980
|
userInputMode: selectedUserInputMode,
|
|
2020
1981
|
onElicitation: function(request, elicitOpts) {
|
|
1982
|
+
if (queryRetired()) return Promise.resolve({ action: "cancel" });
|
|
1983
|
+
responseRecovery.progress(session);
|
|
2021
1984
|
return handleElicitation(session, request, elicitOpts);
|
|
2022
1985
|
},
|
|
2023
1986
|
onUserDialog: function(dialogRequest, dialogOpts) {
|
|
1987
|
+
if (queryRetired()) return Promise.resolve({ behavior: "cancelled" });
|
|
1988
|
+
responseRecovery.progress(session);
|
|
2024
1989
|
return handleUserDialog(session, dialogRequest, dialogOpts);
|
|
2025
1990
|
},
|
|
2026
1991
|
callMcpTool: function(serverName, toolName, args) {
|
|
1992
|
+
if (queryRetired()) return Promise.reject(new Error("This attempt has stopped."));
|
|
1993
|
+
responseRecovery.progress(session);
|
|
2027
1994
|
return callMcpToolHandler(mergedMcpServers, serverName, toolName, args);
|
|
2028
1995
|
},
|
|
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
|
-
},
|
|
1996
|
+
adapterOptions: require("./yoke/query-options").map(sessionAdapter, executionIntent),
|
|
2056
1997
|
};
|
|
2057
1998
|
|
|
1999
|
+
if (recoveryState) {
|
|
2000
|
+
if (!recoveryState.context) recoveryState.context = { appendSystemPrompt: queryOpts.appendSystemPrompt, model: queryOpts.model, effort: queryOpts.effort };
|
|
2001
|
+
Object.assign(queryOpts, recoveryState.context);
|
|
2002
|
+
}
|
|
2058
2003
|
var handle;
|
|
2004
|
+
var startupHandle = session.queryInstance;
|
|
2059
2005
|
console.log("[sdk-bridge] calling adapter.createQuery... vendor=" + sessionAdapter.vendor);
|
|
2060
2006
|
try {
|
|
2061
2007
|
handle = await sessionAdapter.createQuery(queryOpts);
|
|
2008
|
+
// A guarded delivery must still own the exact startup after provider
|
|
2009
|
+
// creation. Never replace a newer handle or publish to a deleted target.
|
|
2010
|
+
if (beforePush && beforePush.exactProductDelivery) {
|
|
2011
|
+
var startupCurrent = false;
|
|
2012
|
+
try { startupCurrent = sm.sessions.get(session.localId) === session && session.queryInstance === startupHandle && Number(session._sdkQueryGeneration || 0) === queryGeneration && beforePush() === true; } catch (guardError) {}
|
|
2013
|
+
if (!startupCurrent) {
|
|
2014
|
+
try { if (handle.abort) handle.abort(); } catch (abortError) {}
|
|
2015
|
+
try { if (handle.close) handle.close(); } catch (closeError) {}
|
|
2016
|
+
if (session.queryInstance === startupHandle) session.isProcessing = false;
|
|
2017
|
+
return false;
|
|
2018
|
+
}
|
|
2019
|
+
}
|
|
2020
|
+
if (recoveryState) recoveryState.handle = handle;
|
|
2062
2021
|
console.log("[sdk-bridge] createQuery returned handle, vendor=" + sessionAdapter.vendor);
|
|
2063
2022
|
// SDK accepted the explicit title. Provisional labels remain eligible
|
|
2064
2023
|
// for semantic generation after the first Home exchange (or the normal
|
|
@@ -2078,6 +2037,7 @@ function createSDKBridge(opts) {
|
|
|
2078
2037
|
console.error("[sdk-bridge] Failed to create query for session " + session.localId + ":", e.message || e);
|
|
2079
2038
|
console.error("[sdk-bridge] cliSessionId:", session.cliSessionId, "resume:", !!session.cliSessionId);
|
|
2080
2039
|
console.error("[sdk-bridge] Stack:", e.stack || "(no stack)");
|
|
2040
|
+
if (beforePush && beforePush.exactProductDelivery && (sm.sessions.get(session.localId) !== session || session.queryInstance !== startupHandle || Number(session._sdkQueryGeneration || 0) !== queryGeneration)) return false;
|
|
2081
2041
|
session.isProcessing = false;
|
|
2082
2042
|
session._awaitingTurnResult = false;
|
|
2083
2043
|
session._queuedTurnCount = 0;
|
|
@@ -2112,11 +2072,9 @@ function createSDKBridge(opts) {
|
|
|
2112
2072
|
|
|
2113
2073
|
// Store QueryHandle on session for iteration and control.
|
|
2114
2074
|
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";
|
|
2075
|
+
// An installed setter and the adapter's explicit protocol contract are
|
|
2076
|
+
// both required; generic handle stubs do not establish runtime support.
|
|
2077
|
+
session.permissionCapabilities = require("./session-permission-mode").capabilities(session, sm.defaultVendor, sessionAdapter);
|
|
2120
2078
|
session.effectivePermissionMode = null;
|
|
2121
2079
|
sm.saveSessionFile(session);
|
|
2122
2080
|
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 +2090,7 @@ function createSDKBridge(opts) {
|
|
|
2132
2090
|
}
|
|
2133
2091
|
|
|
2134
2092
|
if (typeof beforePush === "function" && beforePush() !== true) {
|
|
2093
|
+
try { if (typeof handle.abort === "function") handle.abort(); } catch (e) {}
|
|
2135
2094
|
try { handle.close(); } catch (e) {}
|
|
2136
2095
|
if (session.queryInstance === handle) session.queryInstance = null;
|
|
2137
2096
|
session.messageQueue = null;
|
|
@@ -2141,6 +2100,13 @@ function createSDKBridge(opts) {
|
|
|
2141
2100
|
session._queuedTurnCount = 0;
|
|
2142
2101
|
taskLifecycle.clearAll(session);
|
|
2143
2102
|
onProcessingChanged();
|
|
2103
|
+
if (recoveryState && !responseRecovery.stopping(session)) {
|
|
2104
|
+
sendAndRecord(session, { type: "thinking_stop" });
|
|
2105
|
+
sendAndRecord(session, { type: session.taskStopRequested ? "info" : "error", text: session.taskStopRequested
|
|
2106
|
+
? "Stopped before sending your message."
|
|
2107
|
+
: "This request is no longer eligible for delivery. Please review it and send it again." });
|
|
2108
|
+
sendAndRecord(session, { type: "done", code: session.taskStopRequested ? 0 : 1 });
|
|
2109
|
+
}
|
|
2144
2110
|
sm.broadcastSessionList();
|
|
2145
2111
|
return false;
|
|
2146
2112
|
}
|
|
@@ -2192,32 +2158,27 @@ function createSDKBridge(opts) {
|
|
|
2192
2158
|
}
|
|
2193
2159
|
|
|
2194
2160
|
session.lastActivityAt = Date.now();
|
|
2195
|
-
var
|
|
2196
|
-
if (
|
|
2161
|
+
var catalogCandidate = null;
|
|
2162
|
+
if (queryContract.catalogLifetime === "conversation" && typeof queryContract.recordCatalog === "function" && !resumedAtQueryStart) {
|
|
2197
2163
|
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
2164
|
for (var catalogToolIndex = 0; catalogToolIndex < sessionToolDefs.length; catalogToolIndex++) {
|
|
2199
2165
|
if (Object.prototype.hasOwnProperty.call(requiredCatalogTools, sessionToolDefs[catalogToolIndex].name)) requiredCatalogTools[sessionToolDefs[catalogToolIndex].name] = true;
|
|
2200
2166
|
}
|
|
2201
2167
|
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
2168
|
if (completeInterviewCatalog || requiredCatalogTools.report_scheduled_task_outcome) {
|
|
2203
|
-
|
|
2169
|
+
catalogCandidate = { generation: queryGeneration, versions: { schedules: yoke.sessionTools.SCHEDULE_CATALOG_VERSION } };
|
|
2204
2170
|
}
|
|
2205
|
-
|
|
2206
|
-
|
|
2207
|
-
|
|
2208
|
-
if (hasYouCatalog) codexCatalogCandidate = Object.assign({}, codexCatalogCandidate || {}, { generation: queryGeneration, youVersion: 1 });
|
|
2209
|
-
if (hasLinearCatalog) codexCatalogCandidate = Object.assign({}, codexCatalogCandidate || {}, { generation: queryGeneration, linearVersion: 1 });
|
|
2210
|
-
if (hasSharedBrowserCatalog) {
|
|
2211
|
-
codexCatalogCandidate = Object.assign({}, codexCatalogCandidate || {}, { generation: queryGeneration, sharedBrowserVersion: 5 });
|
|
2212
|
-
}
|
|
2213
|
-
if (hasIssueCatalog) {
|
|
2214
|
-
codexCatalogCandidate = Object.assign({}, codexCatalogCandidate || {}, {
|
|
2215
|
-
generation: queryGeneration,
|
|
2216
|
-
issuesVersion: 1,
|
|
2217
|
-
});
|
|
2171
|
+
function markCatalog(family, version) {
|
|
2172
|
+
if (!catalogCandidate) catalogCandidate = { generation: queryGeneration, versions: {} };
|
|
2173
|
+
catalogCandidate.versions[family] = version;
|
|
2218
2174
|
}
|
|
2175
|
+
if (requiredCatalogTools.ask_user_questions) markCatalog("questions", 1);
|
|
2176
|
+
if (hasYouCatalog) markCatalog("knowledge", 1);
|
|
2177
|
+
if (hasLinearCatalog) markCatalog("linear", 1);
|
|
2178
|
+
if (hasSharedBrowserCatalog) markCatalog("browser", 6);
|
|
2179
|
+
if (hasIssueCatalog) markCatalog("issues", 1);
|
|
2219
2180
|
}
|
|
2220
|
-
session.streamPromise = processQueryStream(session,
|
|
2181
|
+
session.streamPromise = processQueryStream(session, catalogCandidate, queryContract).catch(function(err) {
|
|
2221
2182
|
});
|
|
2222
2183
|
return true;
|
|
2223
2184
|
}
|
|
@@ -2229,6 +2190,19 @@ function createSDKBridge(opts) {
|
|
|
2229
2190
|
// dropped messages in both gap windows, which is what made a session show
|
|
2230
2191
|
// the processing indicator without ever answering until a second send.
|
|
2231
2192
|
function pushMessage(session, text, images, deliveryMeta) {
|
|
2193
|
+
if (session._responseRecoveryStopPending && !responseRecovery.stopping(session)) return false;
|
|
2194
|
+
function trackDelivery() {
|
|
2195
|
+
responseRecovery.enqueue(session, {
|
|
2196
|
+
text: text, images: images, linuxUser: session.lastLinuxUser || null,
|
|
2197
|
+
});
|
|
2198
|
+
}
|
|
2199
|
+
if (responseRecovery.stopping(session)) {
|
|
2200
|
+
// Keep admission serialized while the old execution is terminating.
|
|
2201
|
+
session.pendingPush = session.pendingPush || [];
|
|
2202
|
+
session.pendingPush.push(Object.assign({ text: text, images: images || null }, deliveryMeta || {}));
|
|
2203
|
+
trackDelivery();
|
|
2204
|
+
return true;
|
|
2205
|
+
}
|
|
2232
2206
|
session.lastActivityAt = Date.now();
|
|
2233
2207
|
if (session._runtimeRefreshRequested && !session._queryStarting) {
|
|
2234
2208
|
session._runtimeRefreshRequested = false;
|
|
@@ -2255,6 +2229,8 @@ function createSDKBridge(opts) {
|
|
|
2255
2229
|
console.error("[sdk-bridge] QueryHandle rejected message for session " + session.localId + ":", e.message || e);
|
|
2256
2230
|
}
|
|
2257
2231
|
if (delivered) {
|
|
2232
|
+
require('./sdk-foreground-admission').take(session);
|
|
2233
|
+
trackDelivery();
|
|
2258
2234
|
delete session._lastTurnInterrupted;
|
|
2259
2235
|
if (session._awaitingTurnResult) {
|
|
2260
2236
|
session._queuedTurnCount = (session._queuedTurnCount || 0) + 1;
|
|
@@ -2279,6 +2255,7 @@ function createSDKBridge(opts) {
|
|
|
2279
2255
|
if (session._queryStarting) {
|
|
2280
2256
|
session.pendingPush = session.pendingPush || [];
|
|
2281
2257
|
session.pendingPush.push(Object.assign({ text: text, images: images || null }, deliveryMeta || {}));
|
|
2258
|
+
trackDelivery();
|
|
2282
2259
|
return true;
|
|
2283
2260
|
}
|
|
2284
2261
|
return false;
|
|
@@ -2359,65 +2336,8 @@ function createSDKBridge(opts) {
|
|
|
2359
2336
|
// Detect which vendor binaries are installed for this user.
|
|
2360
2337
|
// In multi-user mode, runs checks as the specific Linux user.
|
|
2361
2338
|
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;
|
|
2339
|
+
var installed = require("./yoke/discovery").installed({ user: linuxUser });
|
|
2340
|
+
return Object.keys(installed).filter(function(vendor) { return installed[vendor]; });
|
|
2421
2341
|
}
|
|
2422
2342
|
|
|
2423
2343
|
function getAvailableVendors(linuxUser) {
|
|
@@ -2489,7 +2409,20 @@ function createSDKBridge(opts) {
|
|
|
2489
2409
|
sendModelInfoForVendor(null, defaultVendor, defaultModelForVendor(defaultVendor));
|
|
2490
2410
|
}
|
|
2491
2411
|
|
|
2492
|
-
async function setModel(session, model) {
|
|
2412
|
+
async function setModel(session, model, options) {
|
|
2413
|
+
if (options && typeof options.revalidate === "function") {
|
|
2414
|
+
var vendor = session.vendor || sm.defaultVendor || "claude";
|
|
2415
|
+
return require("./session-config-transition").applySessionConfig({
|
|
2416
|
+
sm: sm, session: session, revalidate: options.revalidate, method: "setModel", nativeValue: model, changes: { model: model },
|
|
2417
|
+
publish: function () {
|
|
2418
|
+
sm.defaultModelByVendor = sm.defaultModelByVendor || {};
|
|
2419
|
+
sm.defaultModelByVendor[vendor] = model;
|
|
2420
|
+
sm.broadcastSessionList();
|
|
2421
|
+
sendModelInfoForVendor(session, vendor, model);
|
|
2422
|
+
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 || [] });
|
|
2423
|
+
},
|
|
2424
|
+
});
|
|
2425
|
+
}
|
|
2493
2426
|
// Normalize to string id in case a { value, displayName } object slips in
|
|
2494
2427
|
if (model && typeof model !== "string") {
|
|
2495
2428
|
model = modelEntryValue(model);
|
|
@@ -2525,7 +2458,22 @@ function createSDKBridge(opts) {
|
|
|
2525
2458
|
}
|
|
2526
2459
|
}
|
|
2527
2460
|
|
|
2528
|
-
async function setEffort(session, effort) {
|
|
2461
|
+
async function setEffort(session, effort, options) {
|
|
2462
|
+
if (options && typeof options.revalidate === "function") {
|
|
2463
|
+
var vendor = session.vendor || sm.defaultVendor || "claude";
|
|
2464
|
+
var value = yoke.clampEffort(vendor, effort);
|
|
2465
|
+
if (!value || value !== effort) throw new Error("Unsupported reasoning effort.");
|
|
2466
|
+
return require("./session-config-transition").applySessionConfig({
|
|
2467
|
+
sm: sm, session: session, revalidate: options.revalidate, method: "setEffort", nativeValue: value, changes: { effort: value },
|
|
2468
|
+
publish: function () {
|
|
2469
|
+
sm.currentEffortByVendor = sm.currentEffortByVendor || {};
|
|
2470
|
+
sm.currentEffortByVendor[vendor] = value;
|
|
2471
|
+
sm.currentEffort = value;
|
|
2472
|
+
sm.broadcastSessionList();
|
|
2473
|
+
sendToSession(session, { type: "config_state", sessionId: session.localId, vendor: vendor, effort: value, model: session.model || "", mode: session.permissionMode || sm.currentPermissionMode || "default", betas: sm.currentBetas || [] });
|
|
2474
|
+
},
|
|
2475
|
+
});
|
|
2476
|
+
}
|
|
2529
2477
|
// Remember the pick per vendor (clamped) so vendor switches don't leak
|
|
2530
2478
|
// unsupported levels across sessions; sm.currentEffort stays as the
|
|
2531
2479
|
// display value for the session the user just configured.
|
|
@@ -2646,16 +2594,7 @@ function createSDKBridge(opts) {
|
|
|
2646
2594
|
message: "Read-only access. You cannot make changes via @mention.",
|
|
2647
2595
|
});
|
|
2648
2596
|
},
|
|
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
|
-
},
|
|
2597
|
+
adapterOptions: require("./yoke/query-options").map(mentionAdapter, { instructionSources: ["user"], readOnly: true }),
|
|
2659
2598
|
});
|
|
2660
2599
|
} catch (e) {
|
|
2661
2600
|
opts.onError("Failed to create mention query: " + (e.message || e));
|
|
@@ -2794,12 +2733,14 @@ function createSDKBridge(opts) {
|
|
|
2794
2733
|
startQuery: startQuery,
|
|
2795
2734
|
startQueryWithAcceptance: startQueryWithAcceptance,
|
|
2796
2735
|
pushMessage: pushMessage,
|
|
2736
|
+
cancelResponseRecovery: responseRecovery.cancel,
|
|
2797
2737
|
refreshSessionRuntime: refreshSessionRuntime,
|
|
2798
2738
|
refreshEnvironmentRuntime: refreshEnvironmentRuntime,
|
|
2799
2739
|
setModel: setModel,
|
|
2800
2740
|
setEffort: setEffort,
|
|
2801
2741
|
setPermissionMode: setPermissionMode,
|
|
2802
|
-
|
|
2742
|
+
isProviderProcess: isProviderProcess,
|
|
2743
|
+
isClaudeProcess: isProviderProcess, // Compatibility export; production uses the provider contract.
|
|
2803
2744
|
permissionPushTitle: permissionPushTitle,
|
|
2804
2745
|
permissionPushBody: permissionPushBody,
|
|
2805
2746
|
warmup: warmup,
|