clay-server 5.2.0-beta.5 → 5.2.0-beta.7
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/claude-hook-installer.js +1 -267
- 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.js +1 -0
- package/lib/clay-mate-knowledge.js +1 -1
- package/lib/clay-product-control-tools.js +1 -1
- package/lib/clay-product-control.js +22 -12
- package/lib/clay-project-records.js +2 -1
- package/lib/clay-scheduling.js +1 -1
- package/lib/clay-screen-controls.js +13 -5
- package/lib/clay-skill-install.js +1 -33
- package/lib/clay-workspace-controls.js +2 -1
- 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.js +5 -55
- package/lib/default-ai-runtime.js +4 -8
- package/lib/email-mcp-server.js +1 -1
- package/lib/kiro-defaults.js +1 -22
- package/lib/mate-context-service.js +138 -0
- package/lib/mate-context-tools.js +21 -0
- package/lib/mcp-proxy.js +2 -32
- package/lib/mcp-query-bridge.js +1 -1
- package/lib/mcp-source-adapters.js +1 -91
- package/lib/mcp-source-context.js +1 -42
- package/lib/mcp-source-discovery.js +1 -169
- package/lib/mcp-source-plugins.js +1 -68
- package/lib/mcp-source-restrictions.js +1 -47
- package/lib/mcp-tool-policy.js +1 -26
- package/lib/os-user-diagnostics.js +2 -4
- package/lib/os-users.js +4 -65
- package/lib/project-connection.js +14 -10
- package/lib/project-control-git-view.js +12 -0
- package/lib/project-filesystem.js +5 -1
- package/lib/project-http.js +7 -4
- package/lib/project-mcp.js +2 -2
- package/lib/project-notifications.js +5 -4
- package/lib/project-pair-result-delivery.js +2 -2
- package/lib/project-pair-usage.js +12 -13
- package/lib/project-pending-message-queue.js +3 -1
- package/lib/project-product-control.js +3 -1
- package/lib/project-scheduled-messages.js +4 -4
- package/lib/project-scheduled-task-control.js +1 -1
- package/lib/project-session-document.js +20 -5
- package/lib/project-session-history-actions.js +5 -3
- package/lib/project-session-pair.js +1 -1
- package/lib/project-session-runtime-actions.js +2 -1
- package/lib/project-session-spawn.js +2 -3
- package/lib/project-session-vendor.js +2 -1
- package/lib/project-sessions.js +18 -26
- package/lib/project-shared-browser.js +22 -5
- package/lib/project-studio-presentation.js +58 -0
- package/lib/project-user-message.js +37 -0
- package/lib/project-vendor-login.js +6 -36
- package/lib/project-workspace-query.js +11 -1
- package/lib/project.js +24 -7
- package/lib/public/app.js +25 -0
- package/lib/public/appearance-bootstrap.js +2 -0
- package/lib/public/css/contextual-clay.css +240 -0
- package/lib/public/css/messages.css +6 -2
- package/lib/public/modules/app-favicon.js +18 -9
- package/lib/public/modules/app-header.js +4 -2
- package/lib/public/modules/app-loop-ui.js +2 -0
- package/lib/public/modules/app-message-router.js +5 -1
- package/lib/public/modules/app-messages.js +50 -6
- 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 +3 -0
- package/lib/public/modules/app-rate-limit.js +7 -27
- package/lib/public/modules/chat-render-runtime.js +3 -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-navigation-render.js +52 -0
- package/lib/public/modules/clay-owner-navigation.js +11 -2
- 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 +144 -0
- package/lib/public/modules/clay-tool-presentation.js +4 -0
- package/lib/public/modules/command-palette.js +26 -31
- 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 +157 -0
- package/lib/public/modules/contextual-clay.js +237 -0
- package/lib/public/modules/contextual-composer.js +91 -0
- package/lib/public/modules/contextual-mate-context.js +115 -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/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/icon-strip-tooltip.js +2 -1
- package/lib/public/modules/input.js +35 -1
- 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 +2 -34
- package/lib/public/modules/mate-knowledge-workbench.js +1 -1
- package/lib/public/modules/mcp-connection-view.js +1 -1
- package/lib/public/modules/message-delivery.js +10 -0
- package/lib/public/modules/pane-bridge.js +2 -2
- package/lib/public/modules/pending-message-queue.js +1 -0
- package/lib/public/modules/permission-control.js +5 -4
- package/lib/public/modules/product-review.js +26 -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 +58 -21
- 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 -454
- package/lib/public/modules/session-create-form.js +10 -10
- package/lib/public/modules/settings-defaults.js +27 -28
- package/lib/public/modules/shared-browser.js +2 -0
- package/lib/public/modules/sidebar-mobile.js +4 -3
- package/lib/public/modules/sidebar-projects.js +1 -0
- package/lib/public/modules/sidebar-sessions.js +1 -0
- package/lib/public/modules/split-view.js +7 -16
- package/lib/public/modules/terminal.js +9 -0
- package/lib/public/modules/tools.js +6 -2
- package/lib/public/modules/tui-grab.js +1 -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 +2 -0
- package/lib/safe-bash-commands.js +3 -45
- package/lib/sdk-bridge.js +131 -395
- package/lib/sdk-foreground-admission.js +16 -0
- package/lib/sdk-mcp-descriptors.js +2 -37
- package/lib/sdk-message-processor.js +50 -17
- package/lib/sdk-quota-snapshot.js +1 -1
- package/lib/sdk-response-recovery.js +1 -155
- package/lib/sdk-worker.js +2 -677
- package/lib/server-contextual-clay-settings.js +40 -0
- package/lib/server-contextual-mate-sessions.js +70 -0
- package/lib/server-home-chat.js +7 -1
- package/lib/server-home-clay-entry.js +23 -4
- package/lib/server-home-clay-session-links.js +12 -0
- package/lib/server-owner-ui.js +49 -8
- package/lib/server-settings.js +2 -0
- package/lib/server.js +18 -1
- package/lib/session-fork-history.js +21 -0
- 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/sessions.js +24 -89
- package/lib/terminal-manager.js +18 -11
- 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.js +3 -0
- package/lib/vendor-login-browser.js +1 -11
- package/lib/workspace-assignment-service.js +25 -0
- package/lib/workspace-query-mcp-server.js +1 -1
- package/lib/ws-request.js +1 -0
- package/lib/ws-schema.js +10 -0
- package/lib/yoke/acp-agent-profiles.js +5 -3
- package/lib/yoke/adapters/antigravity.js +3 -14
- package/lib/yoke/adapters/claude-query-contract.js +9 -0
- package/lib/yoke/adapters/claude.js +7 -42
- package/lib/yoke/adapters/codex-query-contract.js +24 -0
- package/lib/yoke/adapters/codex.js +1 -0
- 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/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/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 +31 -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 +3 -2
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) {
|
|
@@ -390,7 +378,8 @@ function createSDKBridge(opts) {
|
|
|
390
378
|
var sendAndRecord = msgProcessor.sendAndRecord;
|
|
391
379
|
var sendToSession = msgProcessor.sendToSession;
|
|
392
380
|
|
|
393
|
-
var responseRecovery = require("./
|
|
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; },
|
|
394
383
|
sessions: sm.sessions,
|
|
395
384
|
changed: onProcessingChanged,
|
|
396
385
|
record: sendAndRecord,
|
|
@@ -503,44 +492,7 @@ function createSDKBridge(opts) {
|
|
|
503
492
|
// Ensures the linux user's .claude project directory exists and is writable,
|
|
504
493
|
// then pre-copies CLI session file if needed. Called before starting a query
|
|
505
494
|
// so the worker can resume from the correct session file.
|
|
506
|
-
|
|
507
|
-
try {
|
|
508
|
-
var configMod = require("./config");
|
|
509
|
-
var osUsersMod = require("./os-users");
|
|
510
|
-
var originalHome = configMod.REAL_HOME || require("os").homedir();
|
|
511
|
-
var linuxUserHome = osUsersMod.getLinuxUserHome(linuxUser);
|
|
512
|
-
var uid = osUsersMod.getLinuxUserUid(linuxUser);
|
|
513
|
-
if (originalHome !== linuxUserHome && uid != null) {
|
|
514
|
-
var projectSlug = (cwd || "").replace(/\//g, "-");
|
|
515
|
-
var dstDir = path.join(linuxUserHome, ".claude", "projects", projectSlug);
|
|
516
|
-
// Create and chown the project directory once
|
|
517
|
-
if (!fs.existsSync(dstDir)) {
|
|
518
|
-
fs.mkdirSync(dstDir, { recursive: true });
|
|
519
|
-
try { execFileSync("chown", ["-R", String(uid), path.join(linuxUserHome, ".claude")]); } catch (e2) {}
|
|
520
|
-
} else {
|
|
521
|
-
try {
|
|
522
|
-
var dirStat = fs.statSync(dstDir);
|
|
523
|
-
if (dirStat.uid !== uid) {
|
|
524
|
-
execFileSync("chown", [String(uid), dstDir]);
|
|
525
|
-
}
|
|
526
|
-
} catch (e2) {}
|
|
527
|
-
}
|
|
528
|
-
// Pre-copy CLI session file so the worker can resume the conversation
|
|
529
|
-
if (session.cliSessionId) {
|
|
530
|
-
var sessionFileName = session.cliSessionId + ".jsonl";
|
|
531
|
-
var srcFile = path.join(originalHome, ".claude", "projects", projectSlug, sessionFileName);
|
|
532
|
-
var dstFile = path.join(dstDir, sessionFileName);
|
|
533
|
-
if (fs.existsSync(srcFile) && !fs.existsSync(dstFile)) {
|
|
534
|
-
fs.copyFileSync(srcFile, dstFile);
|
|
535
|
-
try { execFileSync("chown", [String(uid), dstFile]); } catch (e2) {}
|
|
536
|
-
console.log("[sdk-bridge] Pre-copied CLI session " + session.cliSessionId + " to " + linuxUser);
|
|
537
|
-
}
|
|
538
|
-
}
|
|
539
|
-
}
|
|
540
|
-
} catch (copyErr) {
|
|
541
|
-
console.log("[sdk-bridge] Dir setup / session pre-copy skipped:", copyErr.message);
|
|
542
|
-
}
|
|
543
|
-
}
|
|
495
|
+
|
|
544
496
|
|
|
545
497
|
// --- SDK query lifecycle ---
|
|
546
498
|
|
|
@@ -759,6 +711,10 @@ function createSDKBridge(opts) {
|
|
|
759
711
|
// Workspace inspection and proposal posting are session-bound. Keep this
|
|
760
712
|
// list exact so a future execution/mutation tool cannot inherit approval.
|
|
761
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,
|
|
762
718
|
"mcp__clay-workspace__read_owner_screen": true,
|
|
763
719
|
"mcp__clay-workspace__inspect_owner_screen_change": true,
|
|
764
720
|
"mcp__clay-workspace__control_owner_screen": true,
|
|
@@ -986,58 +942,13 @@ function createSDKBridge(opts) {
|
|
|
986
942
|
* Only returns processes whose cwd matches our project directory.
|
|
987
943
|
* Returns an array of { pid, command } for each conflicting process found.
|
|
988
944
|
*/
|
|
989
|
-
function
|
|
990
|
-
|
|
991
|
-
|
|
992
|
-
var lines = output.trim().split("\n");
|
|
993
|
-
var candidates = [];
|
|
994
|
-
for (var i = 1; i < lines.length; i++) { // skip header
|
|
995
|
-
var line = lines[i].trim();
|
|
996
|
-
var m = line.match(/^(\d+)\s+(.+)/);
|
|
997
|
-
if (!m) continue;
|
|
998
|
-
var pid = parseInt(m[1], 10);
|
|
999
|
-
var cmd = m[2];
|
|
1000
|
-
// Skip our own process
|
|
1001
|
-
if (pid === process.pid) continue;
|
|
1002
|
-
// Skip node processes (our daemon, dev watchers, etc.)
|
|
1003
|
-
if (/\bnode\b/.test(cmd.split(/\s/)[0])) continue;
|
|
1004
|
-
// Match actual claude binary (e.g. /Users/x/.claude/local/claude, /usr/local/bin/claude)
|
|
1005
|
-
if (/\/claude(\s|$)/.test(cmd) || /^claude(\s|$)/.test(cmd)) {
|
|
1006
|
-
candidates.push({ pid: pid, command: cmd.substring(0, 200) });
|
|
1007
|
-
}
|
|
1008
|
-
}
|
|
1009
|
-
|
|
1010
|
-
// Filter to only processes whose cwd matches our project
|
|
1011
|
-
var results = [];
|
|
1012
|
-
for (var j = 0; j < candidates.length; j++) {
|
|
1013
|
-
var c = candidates[j];
|
|
1014
|
-
try {
|
|
1015
|
-
// Use /proc/<pid>/cwd symlink (always available on Linux, no lsof dependency)
|
|
1016
|
-
var procCwd = fs.readlinkSync("/proc/" + c.pid + "/cwd");
|
|
1017
|
-
if (procCwd === cwd) {
|
|
1018
|
-
results.push(c);
|
|
1019
|
-
}
|
|
1020
|
-
} catch (e) {
|
|
1021
|
-
// /proc read failed — include as candidate anyway (conservative)
|
|
1022
|
-
results.push(c);
|
|
1023
|
-
}
|
|
1024
|
-
}
|
|
1025
|
-
return results;
|
|
1026
|
-
} catch (e) {
|
|
1027
|
-
return [];
|
|
1028
|
-
}
|
|
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) : [];
|
|
1029
948
|
}
|
|
1030
|
-
|
|
1031
|
-
|
|
1032
|
-
|
|
1033
|
-
*/
|
|
1034
|
-
function isClaudeProcess(pid) {
|
|
1035
|
-
try {
|
|
1036
|
-
var output = execFileSync("ps", ["-p", String(pid), "-o", "command="], { encoding: "utf8", timeout: 3000, stdio: ["pipe", "pipe", "pipe"] }).trim();
|
|
1037
|
-
return /\/claude(\s|$)/.test(output) || /^claude(\s|$)/.test(output);
|
|
1038
|
-
} catch (e) {
|
|
1039
|
-
return false;
|
|
1040
|
-
}
|
|
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));
|
|
1041
952
|
}
|
|
1042
953
|
|
|
1043
954
|
function ownsQueryRuntime(session, queryInstance, queryGeneration) {
|
|
@@ -1080,7 +991,8 @@ function createSDKBridge(opts) {
|
|
|
1080
991
|
return true;
|
|
1081
992
|
}
|
|
1082
993
|
|
|
1083
|
-
async function processQueryStream(session,
|
|
994
|
+
async function processQueryStream(session, catalogCandidate, queryContract) {
|
|
995
|
+
queryContract = queryContract || yoke.sessionTools.contract(getAdapterForSession(session));
|
|
1084
996
|
// Capture references at start so we only clean up OUR resources in finally,
|
|
1085
997
|
// not resources from a newer query that may have been created after an abort.
|
|
1086
998
|
var myQueryInstance = session.queryInstance;
|
|
@@ -1146,19 +1058,14 @@ function createSDKBridge(opts) {
|
|
|
1146
1058
|
// permission state. Setter acknowledgement deliberately does not
|
|
1147
1059
|
// change this field.
|
|
1148
1060
|
recordRuntimeEffectivePermissionMode(session, myQueryInstance, myQueryGeneration, msg);
|
|
1149
|
-
if (
|
|
1061
|
+
if (catalogCandidate && msg && msg.yokeType === "session_started" && msg.sessionId
|
|
1150
1062
|
&& session.queryInstance === myQueryInstance
|
|
1151
|
-
&& Number(session._sdkQueryGeneration || 0) ===
|
|
1063
|
+
&& Number(session._sdkQueryGeneration || 0) === catalogCandidate.generation
|
|
1152
1064
|
&& session.cliSessionId === msg.sessionId
|
|
1153
1065
|
&& (!sm.sessions || typeof sm.sessions.get !== "function" || sm.sessions.get(session.localId) === session)) {
|
|
1154
|
-
|
|
1155
|
-
if (codexCatalogCandidate.userInputVersion) session.codexUserInputToolCatalogVersion = codexCatalogCandidate.userInputVersion;
|
|
1156
|
-
if (codexCatalogCandidate.sharedBrowserVersion) session.codexSharedBrowserToolCatalogVersion = codexCatalogCandidate.sharedBrowserVersion;
|
|
1157
|
-
if (codexCatalogCandidate.issuesVersion) session.codexIssuesToolCatalogVersion = codexCatalogCandidate.issuesVersion;
|
|
1158
|
-
if (codexCatalogCandidate.youVersion) session.codexYouToolCatalogVersion = codexCatalogCandidate.youVersion;
|
|
1159
|
-
if (codexCatalogCandidate.linearVersion) session.codexLinearToolCatalogVersion = codexCatalogCandidate.linearVersion;
|
|
1066
|
+
queryContract.recordCatalog(session, catalogCandidate.versions);
|
|
1160
1067
|
sm.saveSessionFile(session);
|
|
1161
|
-
|
|
1068
|
+
catalogCandidate = null;
|
|
1162
1069
|
}
|
|
1163
1070
|
}
|
|
1164
1071
|
// (getContextUsage moved to processSDKMessage result handler -- fire-and-forget)
|
|
@@ -1176,9 +1083,7 @@ function createSDKBridge(opts) {
|
|
|
1176
1083
|
onProcessingChanged();
|
|
1177
1084
|
send({ type: "status", processing: false });
|
|
1178
1085
|
sendAndRecord(session, { type: "thinking_stop" });
|
|
1179
|
-
var interruptMsg = (
|
|
1180
|
-
? "\u25a0 Conversation interrupted - tell the model what to do differently."
|
|
1181
|
-
: "Interrupted \u00b7 What should Claude do instead?";
|
|
1086
|
+
var interruptMsg = (queryContract && queryContract.interruptionMessage) || "■ Conversation interrupted - tell the model what to do differently.";
|
|
1182
1087
|
sendAndRecord(session, { type: "info", text: interruptMsg });
|
|
1183
1088
|
sendAndRecord(session, { type: "done", code: 0 });
|
|
1184
1089
|
sm.broadcastSessionList();
|
|
@@ -1213,9 +1118,7 @@ function createSDKBridge(opts) {
|
|
|
1213
1118
|
session._lastTurnInterrupted = true;
|
|
1214
1119
|
if (!session.destroying) {
|
|
1215
1120
|
sendAndRecord(session, { type: "thinking_stop" });
|
|
1216
|
-
var interruptMsg2 = (
|
|
1217
|
-
? "\u25a0 Conversation interrupted - tell the model what to do differently."
|
|
1218
|
-
: "Interrupted \u00b7 What should Claude do instead?";
|
|
1121
|
+
var interruptMsg2 = (queryContract && queryContract.interruptionMessage) || "■ Conversation interrupted - tell the model what to do differently.";
|
|
1219
1122
|
sendAndRecord(session, { type: "info", text: interruptMsg2 });
|
|
1220
1123
|
sendAndRecord(session, { type: "done", code: 0 });
|
|
1221
1124
|
}
|
|
@@ -1231,21 +1134,17 @@ function createSDKBridge(opts) {
|
|
|
1231
1134
|
console.error("[sdk-bridge] Query stream error for session " + session.localId + ":", errDetail);
|
|
1232
1135
|
console.error("[sdk-bridge] Stack:", err.stack || "(no stack)");
|
|
1233
1136
|
|
|
1234
|
-
|
|
1235
|
-
var isExitCode1 = err.exitCode === 1 || (err.message && err.message.indexOf("exited with code 1") !== -1);
|
|
1236
|
-
var conflicts = isExitCode1 ? findConflictingClaude() : [];
|
|
1137
|
+
var conflicts = findConflictingProcesses(session, err);
|
|
1237
1138
|
if (conflicts.length > 0) {
|
|
1238
|
-
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(", "));
|
|
1239
1140
|
sendAndRecord(session, {
|
|
1240
1141
|
type: "process_conflict",
|
|
1241
|
-
text: "Another
|
|
1142
|
+
text: "Another provider process is already running in this project.",
|
|
1242
1143
|
processes: conflicts,
|
|
1243
1144
|
});
|
|
1244
1145
|
} else {
|
|
1245
1146
|
var errLower = errDetail.toLowerCase();
|
|
1246
|
-
var isContextOverflow =
|
|
1247
|
-
|| errLower.indexOf("context_length") !== -1
|
|
1248
|
-
|| errLower.indexOf("maximum context length") !== -1;
|
|
1147
|
+
var isContextOverflow = require("./yoke/errors").contextOverflow(errDetail);
|
|
1249
1148
|
var isAuthError = isAuthErrorMessage(errDetail);
|
|
1250
1149
|
if (isContextOverflow) {
|
|
1251
1150
|
sendAndRecord(session, {
|
|
@@ -1292,7 +1191,7 @@ function createSDKBridge(opts) {
|
|
|
1292
1191
|
// chat message already sent above
|
|
1293
1192
|
}
|
|
1294
1193
|
} else {
|
|
1295
|
-
sendAndRecord(session, { type: "error", text: "
|
|
1194
|
+
sendAndRecord(session, { type: "error", text: "Provider process error: " + err.message });
|
|
1296
1195
|
}
|
|
1297
1196
|
}
|
|
1298
1197
|
sendAndRecord(session, { type: "done", code: 1 });
|
|
@@ -1375,20 +1274,16 @@ function createSDKBridge(opts) {
|
|
|
1375
1274
|
if (session.queryInstance) return { query: session.queryInstance, isTemp: false, cleanup: function() {} };
|
|
1376
1275
|
|
|
1377
1276
|
var handle;
|
|
1277
|
+
var selectedAdapter = getAdapterForSession(session);
|
|
1378
1278
|
try {
|
|
1379
|
-
handle = await
|
|
1279
|
+
handle = await selectedAdapter.createQuery({
|
|
1380
1280
|
cwd: cwd,
|
|
1381
1281
|
resumeSessionId: session.cliSessionId,
|
|
1382
1282
|
env: getRuntimeEnv(session),
|
|
1383
|
-
adapterOptions: {
|
|
1384
|
-
CLAUDE: {
|
|
1385
|
-
settingSources: ["user", "project", "local"],
|
|
1386
|
-
enableFileCheckpointing: true,
|
|
1387
|
-
},
|
|
1388
|
-
},
|
|
1283
|
+
adapterOptions: require("./yoke/query-options").map(getAdapterForSession(session), { nativePermissionMode: "default" }),
|
|
1389
1284
|
});
|
|
1390
1285
|
} catch (e) {
|
|
1391
|
-
sendAndRecord(session, { type: "error", text: "Failed to load
|
|
1286
|
+
sendAndRecord(session, { type: "error", text: "Failed to load provider session: " + (e.message || e) });
|
|
1392
1287
|
throw e;
|
|
1393
1288
|
}
|
|
1394
1289
|
|
|
@@ -1455,7 +1350,7 @@ function createSDKBridge(opts) {
|
|
|
1455
1350
|
// abort the whole rewind instead of leaving local history trimmed
|
|
1456
1351
|
// ahead of the real, un-rolled-back provider thread.
|
|
1457
1352
|
if (!turnId) {
|
|
1458
|
-
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.");
|
|
1459
1354
|
}
|
|
1460
1355
|
await sessionAdapter.rollbackThread(session.cliSessionId, turnId, {
|
|
1461
1356
|
linuxUser: getSessionLinuxUser(session) || undefined,
|
|
@@ -1471,6 +1366,8 @@ function createSDKBridge(opts) {
|
|
|
1471
1366
|
|
|
1472
1367
|
async function forkSessionUnified(session, uuid) {
|
|
1473
1368
|
var sessionAdapter = getAdapterForSession(session);
|
|
1369
|
+
var localHistoryEndIndex = require("./session-fork-history").endIndex(session, uuid,
|
|
1370
|
+
require("./yoke/provider-contract").resolve(sessionAdapter).forkHistoryBoundary);
|
|
1474
1371
|
var result = await sessionAdapter.forkSession(session.cliSessionId, {
|
|
1475
1372
|
upToMessageId: uuid,
|
|
1476
1373
|
dir: cwd,
|
|
@@ -1479,8 +1376,10 @@ function createSDKBridge(opts) {
|
|
|
1479
1376
|
if (!result || !result.sessionId) throw new Error("Fork returned no session id");
|
|
1480
1377
|
|
|
1481
1378
|
// Adapters with rollbackThread (e.g. Codex) use local history copy
|
|
1482
|
-
if (typeof sessionAdapter.rollbackThread === "function") {
|
|
1483
|
-
|
|
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;
|
|
1484
1383
|
}
|
|
1485
1384
|
// Claude: read history from CLI session files
|
|
1486
1385
|
return { sessionId: result.sessionId, useLocalHistory: false };
|
|
@@ -1502,9 +1401,8 @@ function createSDKBridge(opts) {
|
|
|
1502
1401
|
}
|
|
1503
1402
|
if (responseRecovery.stopping(session) && !retryState) return false;
|
|
1504
1403
|
delete session._lastTurnInterrupted;
|
|
1505
|
-
var claude = (session.vendor || adapter.vendor) === "claude";
|
|
1506
1404
|
var payload = { text: text, images: images, linuxUser: linuxUser, beforePush: beforePush };
|
|
1507
|
-
var recoveryState =
|
|
1405
|
+
var recoveryState = responseRecovery.begin(session, payload, retryState);
|
|
1508
1406
|
if (recoveryState) recoveryState.handle = null;
|
|
1509
1407
|
var guardedPush = function() {
|
|
1510
1408
|
return !session.destroying && !session.taskStopRequested
|
|
@@ -1548,7 +1446,7 @@ function createSDKBridge(opts) {
|
|
|
1548
1446
|
return false;
|
|
1549
1447
|
} finally {
|
|
1550
1448
|
session._queryStarting = false;
|
|
1551
|
-
delete session.
|
|
1449
|
+
delete session._providerRecoveryWaiting;
|
|
1552
1450
|
if (!session.queryInstance && session.pendingPush && session.pendingPush.length) session.pendingPush = [];
|
|
1553
1451
|
if (!session.queryInstance && !session.isProcessing && !session._pendingMessageDrainPaused && !responseRecovery.stopping(session)) session.taskStopRequested = false;
|
|
1554
1452
|
if (!responseRecovery.stopping(session) && !session.isProcessing && typeof opts.onSessionAvailable === "function") opts.onSessionAvailable(session);
|
|
@@ -1747,7 +1645,8 @@ function createSDKBridge(opts) {
|
|
|
1747
1645
|
|
|
1748
1646
|
// Ensure Linux user project directory exists (runs in parallel with worker boot)
|
|
1749
1647
|
if (linuxUser) {
|
|
1750
|
-
|
|
1648
|
+
var preparation = require("./yoke/provider-contract").resolve(sessionAdapter).prepareIsolation;
|
|
1649
|
+
if (typeof preparation === "function") preparation(linuxUser, session, cwd);
|
|
1751
1650
|
}
|
|
1752
1651
|
|
|
1753
1652
|
session.blocks = {};
|
|
@@ -1764,100 +1663,27 @@ function createSDKBridge(opts) {
|
|
|
1764
1663
|
session.abortController = new AbortController();
|
|
1765
1664
|
}
|
|
1766
1665
|
|
|
1767
|
-
// Build Claude-specific adapter options
|
|
1768
|
-
var claudeOpts = {
|
|
1769
|
-
settingSources: ["user", "project", "local"],
|
|
1770
|
-
includePartialMessages: true,
|
|
1771
|
-
enableFileCheckpointing: true,
|
|
1772
|
-
extraArgs: { "replay-user-messages": null },
|
|
1773
|
-
promptSuggestions: true,
|
|
1774
|
-
agentProgressSummaries: true,
|
|
1775
|
-
};
|
|
1776
|
-
|
|
1777
|
-
// Per-loop settings override global defaults when present
|
|
1778
1666
|
var ls = session.loopSettings || {};
|
|
1779
|
-
|
|
1780
|
-
|
|
1781
|
-
|
|
1782
|
-
|
|
1783
|
-
var thinkingMode = ls.thinking || sm.currentThinking;
|
|
1784
|
-
if (thinkingMode === "disabled") {
|
|
1785
|
-
claudeOpts.thinking = { type: "disabled" };
|
|
1786
|
-
} else if (thinkingMode === "budget") {
|
|
1787
|
-
var budgetTokens = ls.thinkingBudget || sm.currentThinkingBudget;
|
|
1788
|
-
if (budgetTokens) claudeOpts.thinking = { type: "enabled", budgetTokens: budgetTokens };
|
|
1789
|
-
} else {
|
|
1790
|
-
// Adaptive (the default). Request summarized display explicitly:
|
|
1791
|
-
// current models default thinking.display to "omitted", which streams
|
|
1792
|
-
// thinking blocks whose text is an EMPTY string -- the UI's thinking
|
|
1793
|
-
// section stays blank even though thinking happens and is billed.
|
|
1794
|
-
// (SDK ThinkingAdaptive: { type: "adaptive", display?: "summarized" | "omitted" })
|
|
1795
|
-
claudeOpts.thinking = { type: "adaptive", display: "summarized" };
|
|
1796
|
-
}
|
|
1797
|
-
|
|
1798
|
-
if (ls.permissionMode) {
|
|
1799
|
-
session._loopPermissionMode = ls.permissionMode;
|
|
1800
|
-
}
|
|
1801
|
-
|
|
1802
|
-
// Pass through any extra SDK settings from LOOP.json
|
|
1803
|
-
if (ls.disableAllHooks !== undefined) {
|
|
1804
|
-
claudeOpts.settings = Object.assign({}, claudeOpts.settings || {}, { disableAllHooks: ls.disableAllHooks });
|
|
1805
|
-
}
|
|
1806
|
-
|
|
1807
|
-
if (dangerouslySkipPermissions || (session.mode === "tui" && session.dangerouslySkipPermissions)) {
|
|
1808
|
-
claudeOpts.allowDangerouslySkipPermissions = true;
|
|
1809
|
-
claudeOpts.permissionMode = "bypassPermissions";
|
|
1810
|
-
} else {
|
|
1811
|
-
var globalMode = session.permissionMode || sm.currentPermissionMode || "default";
|
|
1812
|
-
var effectiveDefault;
|
|
1813
|
-
// GUI full access stays inside Clay's canUseTool callback. Passing the
|
|
1814
|
-
// SDK bypass mode would require its process-level dangerous escape hatch
|
|
1815
|
-
// and would skip Clay's permission policy entirely.
|
|
1816
|
-
if (globalMode === "bypassPermissions") effectiveDefault = "default";
|
|
1817
|
-
else if (session.acceptEditsAfterStart) effectiveDefault = "acceptEdits";
|
|
1818
|
-
else effectiveDefault = globalMode;
|
|
1819
|
-
var modeToApply = session._loopPermissionMode || effectiveDefault;
|
|
1820
|
-
// Always set permissionMode explicitly, including "default". SDK
|
|
1821
|
-
// 0.3.286+ leaves an omitted permissionMode to Claude Code itself,
|
|
1822
|
-
// which can apply a settings defaultMode or start in auto mode on
|
|
1823
|
-
// third-party providers / with telemetry off -- silently widening
|
|
1824
|
-
// past Clay's Ask policy. Sending "default" keeps the SDK's own
|
|
1825
|
-
// decision point at the same "default" behavior Clay has always run
|
|
1826
|
-
// under: a tool the SDK's own allowed/denied rules or allowedTools
|
|
1827
|
-
// list already settles is not re-asked, but anything left undecided
|
|
1828
|
-
// still reaches Clay's canUseTool callback, as before.
|
|
1829
|
-
claudeOpts.permissionMode = modeToApply || "default";
|
|
1830
|
-
}
|
|
1831
|
-
if (session.youCurator) {
|
|
1832
|
-
claudeOpts.permissionMode = "default";
|
|
1833
|
-
claudeOpts.allowDangerouslySkipPermissions = false;
|
|
1834
|
-
}
|
|
1835
|
-
// Clear one-shot acceptEditsAfterStart regardless of which branch ran above,
|
|
1836
|
-
// so the flag does not linger into subsequent turns.
|
|
1837
|
-
if (session.acceptEditsAfterStart) delete session.acceptEditsAfterStart;
|
|
1838
|
-
if (session.cliSessionId && session.lastRewindUuid) {
|
|
1839
|
-
claudeOpts.resumeSessionAt = session.lastRewindUuid;
|
|
1840
|
-
delete session.lastRewindUuid;
|
|
1841
|
-
sm.saveSessionFile(session);
|
|
1842
|
-
}
|
|
1843
|
-
|
|
1844
|
-
// 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;
|
|
1845
1671
|
if (linuxUser) {
|
|
1846
|
-
|
|
1847
|
-
|
|
1848
|
-
|
|
1849
|
-
|
|
1850
|
-
|
|
1851
|
-
|
|
1852
|
-
}
|
|
1853
|
-
|
|
1854
|
-
|
|
1855
|
-
|
|
1856
|
-
|
|
1857
|
-
|
|
1858
|
-
|
|
1859
|
-
|
|
1860
|
-
|
|
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;
|
|
1861
1687
|
|
|
1862
1688
|
// Pick a model from the session or its vendor-specific default, then
|
|
1863
1689
|
// validate it against the session vendor's known model list.
|
|
@@ -1883,20 +1709,21 @@ function createSDKBridge(opts) {
|
|
|
1883
1709
|
sm.saveSessionFile(session);
|
|
1884
1710
|
}
|
|
1885
1711
|
|
|
1886
|
-
var codexConfig = getCodexConfig(sm);
|
|
1887
|
-
var kiroConfig = getKiroConfig(sm);
|
|
1888
1712
|
session._sdkQueryGeneration = Number(session._sdkQueryGeneration || 0) + 1;
|
|
1889
1713
|
// Individual feature modules own their transport capability checks. Do not
|
|
1890
1714
|
// suppress unrelated session tools merely because one feature cannot be
|
|
1891
1715
|
// delivered by this provider.
|
|
1892
1716
|
var sessionToolDefs = getSessionToolDefs(session) || [];
|
|
1893
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
|
+
}
|
|
1894
1723
|
var hasYouCatalog = sessionToolDefs.some(function (tool) { return tool.name === "search_user_knowledge"; });
|
|
1895
|
-
var
|
|
1896
|
-
&& hasYouCatalog && Number(session.codexYouToolCatalogVersion || 0) < 1;
|
|
1724
|
+
var recoverYouTools = needsCatalogRecovery("knowledge", 1) && hasYouCatalog;
|
|
1897
1725
|
var hasLinearCatalog = sessionToolDefs.some(function (tool) { return tool.name === "link_session_linear"; });
|
|
1898
|
-
var
|
|
1899
|
-
&& hasLinearCatalog && Number(session.codexLinearToolCatalogVersion || 0) < 1 && canUseSessionTools(session) === true;
|
|
1726
|
+
var recoverLinearTools = needsCatalogRecovery("linear", 1) && hasLinearCatalog && canUseSessionTools(session) === true;
|
|
1900
1727
|
var hasIssueCatalog = false;
|
|
1901
1728
|
for (var issueToolIndex = 0; issueToolIndex < sessionToolDefs.length; issueToolIndex++) {
|
|
1902
1729
|
if (sessionToolDefs[issueToolIndex].name === "create_issue") {
|
|
@@ -1905,19 +1732,16 @@ function createSDKBridge(opts) {
|
|
|
1905
1732
|
}
|
|
1906
1733
|
}
|
|
1907
1734
|
var hasSharedBrowserCatalog = sessionToolDefs.some(function (definition) { return definition.name === "shared_browser"; });
|
|
1908
|
-
var
|
|
1909
|
-
|
|
1910
|
-
var recoverCodexIssueTools = sessionAdapter.vendor === "codex"
|
|
1911
|
-
&& !!session.cliSessionId
|
|
1912
|
-
&& hasIssueCatalog
|
|
1913
|
-
&& Number(session.codexIssuesToolCatalogVersion || 0) < 1;
|
|
1735
|
+
var recoverBrowserTools = needsCatalogRecovery("browser", 6) && hasSharedBrowserCatalog;
|
|
1736
|
+
var recoverIssueTools = needsCatalogRecovery("issues", 1) && hasIssueCatalog;
|
|
1914
1737
|
function queryContextAvailable() {
|
|
1738
|
+
if (queryRetired()) return false;
|
|
1915
1739
|
if (Number(session._sdkQueryGeneration || 0) !== queryGeneration) return false;
|
|
1916
1740
|
if (sm && sm.sessions && typeof sm.sessions.get === "function" && sm.sessions.get(session.localId) !== session) return false;
|
|
1917
1741
|
return canUseSessionTools(session) === true;
|
|
1918
1742
|
}
|
|
1919
1743
|
var hasMateScheduleTool = sessionToolDefs.some(function (tool) { return yoke.sessionTools.MATE_SCHEDULE_TOOLS.indexOf(tool.name) !== -1; });
|
|
1920
|
-
var
|
|
1744
|
+
var recoverMateSchedules = needsCatalogRecovery() && hasMateScheduleTool && queryContextAvailable();
|
|
1921
1745
|
var hasScheduleTool = false;
|
|
1922
1746
|
var hasScheduleInterviewTool = false;
|
|
1923
1747
|
var scheduleInterviewActive = null;
|
|
@@ -1934,10 +1758,10 @@ function createSDKBridge(opts) {
|
|
|
1934
1758
|
var activeLoopInterview = !isDriverOperatedSession(session) && !session.loopInterviewHandoff && !activeRun && !!loopInterview.activeInterviewId(session);
|
|
1935
1759
|
var structuredInputSession = hasScheduleInterviewTool || activeLoopInterview || (!isDriverOperatedSession(session) && session.ralphCraftingMode === true && session.loop && session.loop.role === "crafting");
|
|
1936
1760
|
var requestedUserInputMode = session.debateSetupMode || session.mateCreationMode ? "fallback" : "auto";
|
|
1937
|
-
if (structuredInputSession
|
|
1761
|
+
if (structuredInputSession) requestedUserInputMode = "fallback";
|
|
1762
|
+
if (requestedUserInputMode === "auto" && queryContract.defaultUserInputMode) requestedUserInputMode = queryContract.defaultUserInputMode;
|
|
1938
1763
|
var selectedUserInputMode = yoke.userInput.selectMode(sessionAdapter, requestedUserInputMode);
|
|
1939
|
-
var
|
|
1940
|
-
&& Number(session.codexUserInputToolCatalogVersion || 0) < 1 && queryContextAvailable();
|
|
1764
|
+
var recoverQuestionTools = needsCatalogRecovery("questions", 1) && queryContextAvailable();
|
|
1941
1765
|
function structuredInputContextAvailable() {
|
|
1942
1766
|
if (!queryContextAvailable()) return false;
|
|
1943
1767
|
// A schedule-triggered fallback shares the schedule feature's live
|
|
@@ -1979,26 +1803,33 @@ function createSDKBridge(opts) {
|
|
|
1979
1803
|
return opts.onUserInputRequest(session, request, respond);
|
|
1980
1804
|
};
|
|
1981
1805
|
var localMcpServers = getMcpServers(session);
|
|
1982
|
-
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) {
|
|
1983
1811
|
var scheduledTaskToolDefs = [];
|
|
1984
1812
|
for (var scheduledToolIndex = 0; scheduledToolIndex < sessionToolDefs.length; scheduledToolIndex++) {
|
|
1985
1813
|
if (yoke.sessionTools.SCHEDULE_TOOLS.indexOf(sessionToolDefs[scheduledToolIndex].name) !== -1) scheduledTaskToolDefs.push(sessionToolDefs[scheduledToolIndex]);
|
|
1986
1814
|
}
|
|
1987
1815
|
if (scheduledTaskToolDefs.length) {
|
|
1988
1816
|
var scheduledTaskServer = sessionAdapter.createToolServer({ name: "clay-scheduled-tasks", version: "1.0.0", tools: scheduledTaskToolDefs });
|
|
1989
|
-
if (scheduledTaskServer)
|
|
1990
|
-
|
|
1991
|
-
|
|
1992
|
-
}
|
|
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;
|
|
1993
1820
|
}
|
|
1994
1821
|
}
|
|
1995
|
-
if (
|
|
1822
|
+
if (queryContract.toolTransport === "sdk-mcp" && hasMateScheduleTool) {
|
|
1996
1823
|
localMcpServers = Object.assign({}, localMcpServers || {});
|
|
1997
1824
|
localMcpServers["clay-mate-schedules"] = sessionAdapter.createToolServer({ name: "clay-mate-schedules", version: "1.0.0",
|
|
1998
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.");
|
|
1999
1827
|
}
|
|
2000
1828
|
if (selectedUserInputMode === "fallback") {
|
|
2001
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
|
+
}
|
|
2002
1833
|
if (userInputServer) {
|
|
2003
1834
|
localMcpServers = Object.assign({}, localMcpServers || {});
|
|
2004
1835
|
localMcpServers[userInputServer.name || "yoke-user-input"] = userInputServer;
|
|
@@ -2035,9 +1866,9 @@ function createSDKBridge(opts) {
|
|
|
2035
1866
|
|
|
2036
1867
|
var externalQueryBridge = require('./mcp-query-bridge').createQueryBridge({ valid: queryContextAvailable,
|
|
2037
1868
|
getServers: function () { return getRemoteMcpServers ? getRemoteMcpServers(session) || {} : {}; } });
|
|
2038
|
-
var externalToolDefs =
|
|
1869
|
+
var externalToolDefs = queryContract.externalToolTransport === "dynamic" ? externalQueryBridge.dynamicDefs() : [];
|
|
2039
1870
|
if (externalToolDefs.length) { sessionToolDefs = sessionToolDefs.concat(externalToolDefs); queryToolSnapshots.set(session, { generation: queryGeneration, defs: sessionToolDefs.slice() }); }
|
|
2040
|
-
var
|
|
1871
|
+
var recoverExternalTools = needsCatalogRecovery() && (externalToolDefs.length > 0 || isMate);
|
|
2041
1872
|
|
|
2042
1873
|
// Give fresh queries an immediate provisional label. The visible user
|
|
2043
1874
|
// message in history wins over `text`, which may contain an internal
|
|
@@ -2054,7 +1885,6 @@ function createSDKBridge(opts) {
|
|
|
2054
1885
|
|
|
2055
1886
|
var modelSwitchGeneration = session._queryGeneration;
|
|
2056
1887
|
function queryRetired() {
|
|
2057
|
-
if (sessionAdapter.vendor !== "claude") return false;
|
|
2058
1888
|
return Number(session._sdkQueryGeneration || 0) !== queryGeneration || session.taskStopRequested
|
|
2059
1889
|
|| session.destroying || responseRecovery.stopping(session) || (handle && session.queryInstance !== handle);
|
|
2060
1890
|
}
|
|
@@ -2072,7 +1902,7 @@ function createSDKBridge(opts) {
|
|
|
2072
1902
|
clayBridgeToken: clayBridgeToken,
|
|
2073
1903
|
linuxUser: linuxUser || undefined,
|
|
2074
1904
|
env: sessionRuntimeEnv,
|
|
2075
|
-
skillOptions: getSessionSkillOptions(session),
|
|
1905
|
+
skillOptions: require("./session-skill-scope").bind(session, sm.sessions, getSessionSkillOptions(session), queryContextAvailable, usersModule.isMultiUser()),
|
|
2076
1906
|
// appendSystemPrompt, NOT systemPrompt: a plain-string systemPrompt
|
|
2077
1907
|
// REPLACES the entire Claude Code system prompt (sdk.d.ts:2096), which
|
|
2078
1908
|
// would strip the driver session down to the two-sentence pair preset.
|
|
@@ -2080,7 +1910,7 @@ function createSDKBridge(opts) {
|
|
|
2080
1910
|
// codex/kiro: prepend to the first message).
|
|
2081
1911
|
appendSystemPrompt: [
|
|
2082
1912
|
typeof opts.getSessionSystemPrompt === "function" ? opts.getSessionSystemPrompt(session) : "",
|
|
2083
|
-
|
|
1913
|
+
typeof queryContract.questionGuidance === "function" && queryContextAvailable() ? queryContract.questionGuidance() : "",
|
|
2084
1914
|
].filter(Boolean).join("\n\n") || undefined,
|
|
2085
1915
|
model: queryModel,
|
|
2086
1916
|
// Effort is remembered per vendor and clamped to the session vendor's
|
|
@@ -2097,21 +1927,22 @@ function createSDKBridge(opts) {
|
|
|
2097
1927
|
toolServers: mergedMcpServers,
|
|
2098
1928
|
toolServerDescriptors: extractMcpDescriptors(mergedMcpServers) || undefined,
|
|
2099
1929
|
dynamicTools: sessionToolDefs,
|
|
2100
|
-
//
|
|
1930
|
+
// Conversation-scoped catalogs persist definitions. A stale authorized Driver
|
|
2101
1931
|
// gets this exact-query bridge; its handlers still reauthorize live.
|
|
2102
|
-
sessionMcpServer: (
|
|
1932
|
+
sessionMcpServer: (recoverMateSchedules || recoverIssueTools || recoverQuestionTools || recoverBrowserTools || recoverLinearTools || recoverYouTools || recoverExternalTools) ? getSessionMcpServer(session, queryGeneration) : undefined,
|
|
2103
1933
|
onRecoveryAdmission: function(waiting) {
|
|
2104
1934
|
if (!queryContextAvailable()) return;
|
|
2105
|
-
if (waiting) session.
|
|
2106
|
-
else delete session.
|
|
1935
|
+
if (waiting) session._providerRecoveryWaiting = queryGeneration;
|
|
1936
|
+
else delete session._providerRecoveryWaiting;
|
|
2107
1937
|
},
|
|
2108
1938
|
onRecoveryWaiting: function(waiting) {
|
|
2109
1939
|
if (!queryContextAvailable()) return;
|
|
2110
1940
|
sendAndRecord(session, { type: 'informational', level: 'info', content: waiting
|
|
2111
|
-
? '
|
|
2112
|
-
: '
|
|
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.' });
|
|
2113
1943
|
},
|
|
2114
1944
|
callDynamicTool: function (toolName, args) {
|
|
1945
|
+
if (queryRetired() || !queryContextAvailable()) return Promise.reject(new Error("This session tool query is no longer available."));
|
|
2115
1946
|
var toolDef = findSessionToolDef(toolName);
|
|
2116
1947
|
if (toolDef && typeof toolDef.handler === "function") {
|
|
2117
1948
|
return toolDef.handler(args || {});
|
|
@@ -2123,7 +1954,8 @@ function createSDKBridge(opts) {
|
|
|
2123
1954
|
canUseTool: function(toolName, input, toolOpts) {
|
|
2124
1955
|
if (queryRetired()) return { behavior: "deny", message: "This attempt has stopped." };
|
|
2125
1956
|
responseRecovery.progress(session);
|
|
2126
|
-
var
|
|
1957
|
+
var questionInput = yoke.userInput.toolQuestions(sessionAdapter, toolName, input);
|
|
1958
|
+
var nativeQuestionError = questionInput ? scheduleQuestionError(questionInput) : null;
|
|
2127
1959
|
if (nativeQuestionError) return { behavior: "deny", message: nativeQuestionError };
|
|
2128
1960
|
var permissionName = toolName;
|
|
2129
1961
|
var permissionToolDef = findSessionToolDef(toolName);
|
|
@@ -2133,7 +1965,8 @@ function createSDKBridge(opts) {
|
|
|
2133
1965
|
preToolUsePolicy: function(toolName, input) {
|
|
2134
1966
|
if (queryRetired()) return Promise.resolve({ behavior: "deny", message: "This attempt has stopped." });
|
|
2135
1967
|
responseRecovery.progress(session);
|
|
2136
|
-
var
|
|
1968
|
+
var questionInput = yoke.userInput.toolQuestions(sessionAdapter, toolName, input);
|
|
1969
|
+
var nativeQuestionError = questionInput ? scheduleQuestionError(questionInput) : null;
|
|
2137
1970
|
if (nativeQuestionError) return Promise.resolve({ behavior: "deny", message: nativeQuestionError });
|
|
2138
1971
|
var permissionName = toolName;
|
|
2139
1972
|
var permissionToolDef = findSessionToolDef(toolName);
|
|
@@ -2160,33 +1993,7 @@ function createSDKBridge(opts) {
|
|
|
2160
1993
|
responseRecovery.progress(session);
|
|
2161
1994
|
return callMcpToolHandler(mergedMcpServers, serverName, toolName, args);
|
|
2162
1995
|
},
|
|
2163
|
-
adapterOptions:
|
|
2164
|
-
CLAUDE: claudeOpts,
|
|
2165
|
-
CODEX: {
|
|
2166
|
-
// Always use "never" (auto-approve) because Clay handles tool
|
|
2167
|
-
// permissions via its own UI (checkToolWhitelist + handleCanUseTool).
|
|
2168
|
-
// Codex's native approval prompts are terminal-based and cannot be
|
|
2169
|
-
// relayed through Clay's web UI, causing MCP tool calls to hang.
|
|
2170
|
-
approvalPolicy: "never",
|
|
2171
|
-
sandboxMode: session.youCurator ? "read-only" : codexConfig.sandbox,
|
|
2172
|
-
webSearchMode: session.youCurator ? "disabled" : codexConfig.webSearch,
|
|
2173
|
-
},
|
|
2174
|
-
ACP: {
|
|
2175
|
-
mcpServers: getAcpMcpServers(session),
|
|
2176
|
-
},
|
|
2177
|
-
ANTIGRAVITY: {
|
|
2178
|
-
dangerouslySkipPermissions: dangerouslySkipPermissions
|
|
2179
|
-
|| session.permissionMode === "bypassPermissions",
|
|
2180
|
-
},
|
|
2181
|
-
KIRO: {
|
|
2182
|
-
engine: kiroConfig.engine,
|
|
2183
|
-
mode: kiroConfig.mode,
|
|
2184
|
-
// ACP accepts additional stdio MCP servers per session. The bridge is
|
|
2185
|
-
// bound to this Clay session so partner calls cannot leak across
|
|
2186
|
-
// concurrent Kiro sessions or users.
|
|
2187
|
-
mcpServers: getAcpMcpServers(session),
|
|
2188
|
-
},
|
|
2189
|
-
},
|
|
1996
|
+
adapterOptions: require("./yoke/query-options").map(sessionAdapter, executionIntent),
|
|
2190
1997
|
};
|
|
2191
1998
|
|
|
2192
1999
|
if (recoveryState) {
|
|
@@ -2265,11 +2072,9 @@ function createSDKBridge(opts) {
|
|
|
2265
2072
|
|
|
2266
2073
|
// Store QueryHandle on session for iteration and control.
|
|
2267
2074
|
session.queryInstance = handle;
|
|
2268
|
-
//
|
|
2269
|
-
//
|
|
2270
|
-
|
|
2271
|
-
session.permissionCapabilities = require("./session-permission-mode").capabilities(session, sm.defaultVendor);
|
|
2272
|
-
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);
|
|
2273
2078
|
session.effectivePermissionMode = null;
|
|
2274
2079
|
sm.saveSessionFile(session);
|
|
2275
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 || [] });
|
|
@@ -2353,32 +2158,27 @@ function createSDKBridge(opts) {
|
|
|
2353
2158
|
}
|
|
2354
2159
|
|
|
2355
2160
|
session.lastActivityAt = Date.now();
|
|
2356
|
-
var
|
|
2357
|
-
if (
|
|
2161
|
+
var catalogCandidate = null;
|
|
2162
|
+
if (queryContract.catalogLifetime === "conversation" && typeof queryContract.recordCatalog === "function" && !resumedAtQueryStart) {
|
|
2358
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 };
|
|
2359
2164
|
for (var catalogToolIndex = 0; catalogToolIndex < sessionToolDefs.length; catalogToolIndex++) {
|
|
2360
2165
|
if (Object.prototype.hasOwnProperty.call(requiredCatalogTools, sessionToolDefs[catalogToolIndex].name)) requiredCatalogTools[sessionToolDefs[catalogToolIndex].name] = true;
|
|
2361
2166
|
}
|
|
2362
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;
|
|
2363
2168
|
if (completeInterviewCatalog || requiredCatalogTools.report_scheduled_task_outcome) {
|
|
2364
|
-
|
|
2365
|
-
}
|
|
2366
|
-
if (requiredCatalogTools.ask_user_questions) {
|
|
2367
|
-
codexCatalogCandidate = Object.assign({}, codexCatalogCandidate || {}, { generation: queryGeneration, userInputVersion: 1 });
|
|
2169
|
+
catalogCandidate = { generation: queryGeneration, versions: { schedules: yoke.sessionTools.SCHEDULE_CATALOG_VERSION } };
|
|
2368
2170
|
}
|
|
2369
|
-
|
|
2370
|
-
|
|
2371
|
-
|
|
2372
|
-
codexCatalogCandidate = Object.assign({}, codexCatalogCandidate || {}, { generation: queryGeneration, sharedBrowserVersion: 6 });
|
|
2373
|
-
}
|
|
2374
|
-
if (hasIssueCatalog) {
|
|
2375
|
-
codexCatalogCandidate = Object.assign({}, codexCatalogCandidate || {}, {
|
|
2376
|
-
generation: queryGeneration,
|
|
2377
|
-
issuesVersion: 1,
|
|
2378
|
-
});
|
|
2171
|
+
function markCatalog(family, version) {
|
|
2172
|
+
if (!catalogCandidate) catalogCandidate = { generation: queryGeneration, versions: {} };
|
|
2173
|
+
catalogCandidate.versions[family] = version;
|
|
2379
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);
|
|
2380
2180
|
}
|
|
2381
|
-
session.streamPromise = processQueryStream(session,
|
|
2181
|
+
session.streamPromise = processQueryStream(session, catalogCandidate, queryContract).catch(function(err) {
|
|
2382
2182
|
});
|
|
2383
2183
|
return true;
|
|
2384
2184
|
}
|
|
@@ -2392,7 +2192,7 @@ function createSDKBridge(opts) {
|
|
|
2392
2192
|
function pushMessage(session, text, images, deliveryMeta) {
|
|
2393
2193
|
if (session._responseRecoveryStopPending && !responseRecovery.stopping(session)) return false;
|
|
2394
2194
|
function trackDelivery() {
|
|
2395
|
-
|
|
2195
|
+
responseRecovery.enqueue(session, {
|
|
2396
2196
|
text: text, images: images, linuxUser: session.lastLinuxUser || null,
|
|
2397
2197
|
});
|
|
2398
2198
|
}
|
|
@@ -2429,6 +2229,7 @@ function createSDKBridge(opts) {
|
|
|
2429
2229
|
console.error("[sdk-bridge] QueryHandle rejected message for session " + session.localId + ":", e.message || e);
|
|
2430
2230
|
}
|
|
2431
2231
|
if (delivered) {
|
|
2232
|
+
require('./sdk-foreground-admission').take(session);
|
|
2432
2233
|
trackDelivery();
|
|
2433
2234
|
delete session._lastTurnInterrupted;
|
|
2434
2235
|
if (session._awaitingTurnResult) {
|
|
@@ -2535,65 +2336,8 @@ function createSDKBridge(opts) {
|
|
|
2535
2336
|
// Detect which vendor binaries are installed for this user.
|
|
2536
2337
|
// In multi-user mode, runs checks as the specific Linux user.
|
|
2537
2338
|
function detectInstalledVendors(linuxUser) {
|
|
2538
|
-
var
|
|
2539
|
-
|
|
2540
|
-
var result = [];
|
|
2541
|
-
|
|
2542
|
-
function tryLookup(name) {
|
|
2543
|
-
try {
|
|
2544
|
-
if (linuxUser) {
|
|
2545
|
-
execFileSync("su", ["-", linuxUser, "-c", "which " + name], { timeout: 3000, stdio: ["pipe", "pipe", "pipe"] });
|
|
2546
|
-
} else {
|
|
2547
|
-
if (process.platform === "win32") execFileSync("where", [name], { timeout: 3000, stdio: ["pipe", "pipe", "pipe"] });
|
|
2548
|
-
else execFileSync("which", [name], { timeout: 3000, stdio: ["pipe", "pipe", "pipe"] });
|
|
2549
|
-
}
|
|
2550
|
-
return true;
|
|
2551
|
-
} catch (e) {
|
|
2552
|
-
return false;
|
|
2553
|
-
}
|
|
2554
|
-
}
|
|
2555
|
-
|
|
2556
|
-
// Claude: check if binary is in PATH
|
|
2557
|
-
if (tryLookup(yoke.getVendorInfo("claude").binaryName)) result.push("claude");
|
|
2558
|
-
|
|
2559
|
-
// Codex: check bundled binary or PATH
|
|
2560
|
-
var codexBin = null;
|
|
2561
|
-
try {
|
|
2562
|
-
codexBin = require("./yoke/codex-app-server").findCodexPath();
|
|
2563
|
-
} catch (e) {}
|
|
2564
|
-
if ((codexBin && fs.existsSync(codexBin)) || tryLookup(yoke.getVendorInfo("codex").binaryName)) result.push("codex");
|
|
2565
|
-
|
|
2566
|
-
var subprocessVendorKeys = ["antigravity", "opencode", "kimi", "grok", "copilot", "qwen", "junie"];
|
|
2567
|
-
var acpProfiles = require("./yoke/acp-agent-profiles");
|
|
2568
|
-
for (var subprocessVendorIndex = 0; subprocessVendorIndex < subprocessVendorKeys.length; subprocessVendorIndex++) {
|
|
2569
|
-
var subprocessVendor = subprocessVendorKeys[subprocessVendorIndex];
|
|
2570
|
-
var subprocessInfo = yoke.getVendorInfo(subprocessVendor);
|
|
2571
|
-
if (!linuxUser || subprocessInfo.osUserIsolation) {
|
|
2572
|
-
if (subprocessVendor === "antigravity") {
|
|
2573
|
-
if (tryLookup(subprocessInfo.binaryName)) result.push(subprocessVendor);
|
|
2574
|
-
} else {
|
|
2575
|
-
var acpProfile = acpProfiles.getAcpAgentProfile(subprocessVendor);
|
|
2576
|
-
if (acpProfiles.findAcpAgentPath(acpProfile)) result.push(subprocessVendor);
|
|
2577
|
-
}
|
|
2578
|
-
} else {
|
|
2579
|
-
console.log("[sdk-bridge] " + subprocessInfo.displayName + " hidden for OS-isolated user " + linuxUser + ": per-user spawning is not implemented");
|
|
2580
|
-
}
|
|
2581
|
-
}
|
|
2582
|
-
|
|
2583
|
-
// Kiro has no per-user ACP spawn path yet. Do not advertise the daemon's
|
|
2584
|
-
// binary to an OS-isolated user, even if that user also has Kiro installed.
|
|
2585
|
-
var kiroInfo = yoke.getVendorInfo("kiro");
|
|
2586
|
-
if (!linuxUser || kiroInfo.osUserIsolation) {
|
|
2587
|
-
var kiroBin = null;
|
|
2588
|
-
try {
|
|
2589
|
-
kiroBin = require("./yoke/kiro-acp-server").findKiroPath();
|
|
2590
|
-
} catch (e) {}
|
|
2591
|
-
if ((kiroBin && fs.existsSync(kiroBin)) || tryLookup(kiroInfo.binaryName)) result.push("kiro");
|
|
2592
|
-
} else {
|
|
2593
|
-
console.log("[sdk-bridge] " + kiroInfo.displayName + " hidden for OS-isolated user " + linuxUser + ": per-user spawning is not implemented");
|
|
2594
|
-
}
|
|
2595
|
-
|
|
2596
|
-
return result;
|
|
2339
|
+
var installed = require("./yoke/discovery").installed({ user: linuxUser });
|
|
2340
|
+
return Object.keys(installed).filter(function(vendor) { return installed[vendor]; });
|
|
2597
2341
|
}
|
|
2598
2342
|
|
|
2599
2343
|
function getAvailableVendors(linuxUser) {
|
|
@@ -2850,16 +2594,7 @@ function createSDKBridge(opts) {
|
|
|
2850
2594
|
message: "Read-only access. You cannot make changes via @mention.",
|
|
2851
2595
|
});
|
|
2852
2596
|
},
|
|
2853
|
-
adapterOptions: {
|
|
2854
|
-
CLAUDE: {
|
|
2855
|
-
settingSources: ["user"],
|
|
2856
|
-
includePartialMessages: true,
|
|
2857
|
-
// Explicit, not omitted: SDK 0.3.286+ leaves an omitted
|
|
2858
|
-
// permissionMode to Claude Code's own default/auto behavior,
|
|
2859
|
-
// which could bypass the deny-by-default canUseTool above.
|
|
2860
|
-
permissionMode: "default",
|
|
2861
|
-
},
|
|
2862
|
-
},
|
|
2597
|
+
adapterOptions: require("./yoke/query-options").map(mentionAdapter, { instructionSources: ["user"], readOnly: true }),
|
|
2863
2598
|
});
|
|
2864
2599
|
} catch (e) {
|
|
2865
2600
|
opts.onError("Failed to create mention query: " + (e.message || e));
|
|
@@ -3004,7 +2739,8 @@ function createSDKBridge(opts) {
|
|
|
3004
2739
|
setModel: setModel,
|
|
3005
2740
|
setEffort: setEffort,
|
|
3006
2741
|
setPermissionMode: setPermissionMode,
|
|
3007
|
-
|
|
2742
|
+
isProviderProcess: isProviderProcess,
|
|
2743
|
+
isClaudeProcess: isProviderProcess, // Compatibility export; production uses the provider contract.
|
|
3008
2744
|
permissionPushTitle: permissionPushTitle,
|
|
3009
2745
|
permissionPushBody: permissionPushBody,
|
|
3010
2746
|
warmup: warmup,
|