clay-server 3.8.1 → 4.0.0-beta.2
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/ask-user-mcp-server.js +5 -119
- package/lib/builtin-mates.js +6 -6
- package/lib/claude-hook-installer.js +15 -0
- package/lib/clay-history-mcp-server.js +62 -297
- package/lib/daemon.js +1 -1
- package/lib/debate-model-selection.js +119 -0
- package/lib/home-debate-tool-policy.js +164 -0
- package/lib/home-response-notifications.js +26 -0
- package/lib/mate-creation-mcp-server.js +55 -0
- package/lib/mate-ready-creation.js +95 -0
- package/lib/mates.js +2 -0
- package/lib/notes.js +2 -1
- package/lib/project-ask-user.js +64 -0
- package/lib/project-capsule-catalog.js +101 -0
- package/lib/project-connection.js +4 -0
- package/lib/project-debate-proposal.js +133 -17
- package/lib/project-debate.js +214 -110
- package/lib/project-delegated-follow-up.js +84 -0
- package/lib/project-delegated-session.js +53 -0
- package/lib/project-filesystem.js +7 -9
- package/lib/project-knowledge.js +1 -0
- package/lib/project-mate-creation-proposal.js +120 -0
- package/lib/project-memory.js +14 -7
- package/lib/project-models.js +157 -32
- package/lib/project-session-notes.js +2 -2
- package/lib/project-session-pair.js +8 -8
- package/lib/project-sessions.js +66 -51
- package/lib/project-vendor-login.js +397 -0
- package/lib/project-worker-proposal.js +25 -25
- package/lib/project-workspace-query.js +144 -0
- package/lib/project.js +349 -102
- package/lib/public/app.js +85 -42
- package/lib/public/css/avatar-imprints.css +0 -1
- package/lib/public/css/base.css +4 -0
- package/lib/public/css/capsule-ui.css +389 -0
- package/lib/public/css/command-palette.css +306 -6
- package/lib/public/css/home-capsule-library.css +243 -0
- package/lib/public/css/home-capsule-source.css +192 -0
- package/lib/public/css/home-debate-live.css +146 -0
- package/lib/public/css/home-debate-planning.css +125 -0
- package/lib/public/css/home-debates-archive.css +281 -0
- package/lib/public/css/home-hub.css +896 -405
- package/lib/public/css/home-mate-creation.css +34 -0
- package/lib/public/css/home-mate-model-picker.css +131 -0
- package/lib/public/css/home-mate-settings.css +344 -0
- package/lib/public/css/home-session-actions.css +265 -0
- package/lib/public/css/home-sidebar.css +667 -0
- package/lib/public/css/icon-strip.css +1 -2
- package/lib/public/css/mates.css +7 -34
- package/lib/public/css/pane.css +1 -1
- package/lib/public/css/playbook.css +0 -80
- package/lib/public/css/sticky-notes.css +53 -117
- package/lib/public/css/tui-attention.css +0 -44
- package/lib/public/css/workspace-assignment.css +45 -0
- package/lib/public/fonts/source-serif-4/LICENSE.md +93 -0
- package/lib/public/fonts/source-serif-4/SourceSerif4Caption-Semibold.ttf.woff2 +0 -0
- package/lib/public/index.html +93 -74
- package/lib/public/modules/app-connection.js +10 -1
- package/lib/public/modules/app-dm.js +43 -160
- package/lib/public/modules/app-home-hub.js +328 -585
- package/lib/public/modules/app-message-cards.js +242 -0
- package/lib/public/modules/app-message-router.js +84 -0
- package/lib/public/modules/app-messages.js +102 -37
- package/lib/public/modules/app-notifications.js +8 -119
- package/lib/public/modules/app-projects.js +9 -1
- package/lib/public/modules/app-rendering.js +21 -602
- package/lib/public/modules/avatar-imprint.js +11 -8
- package/lib/public/modules/chat-bubble-renderer.js +152 -0
- package/lib/public/modules/chat-render-runtime.js +198 -0
- package/lib/public/modules/command-palette.js +225 -436
- package/lib/public/modules/dm-render.js +82 -0
- package/lib/public/modules/home-capsule-creation-intent.js +31 -0
- package/lib/public/modules/home-capsule-library.js +146 -0
- package/lib/public/modules/home-capsule-source.js +383 -0
- package/lib/public/modules/home-chat-identity.js +35 -0
- package/lib/public/modules/home-chat-scroll.js +77 -0
- package/lib/public/modules/home-chat-stream-state.js +34 -0
- package/lib/public/modules/home-composer-focus.js +25 -0
- package/lib/public/modules/home-conversations-sheet.js +179 -0
- package/lib/public/modules/home-debate-activity.js +48 -0
- package/lib/public/modules/home-debate-controls.js +295 -0
- package/lib/public/modules/home-debate-launch.js +41 -0
- package/lib/public/modules/home-debate-live.js +284 -0
- package/lib/public/modules/home-debate-models.js +73 -0
- package/lib/public/modules/home-debate-planning.js +335 -0
- package/lib/public/modules/home-debates-archive.js +279 -0
- package/lib/public/modules/home-dock-resize.js +74 -0
- package/lib/public/modules/home-dock.js +446 -0
- package/lib/public/modules/home-mate-chat.js +496 -0
- package/lib/public/modules/home-mate-creation.js +109 -0
- package/lib/public/modules/home-mate-model-picker.js +281 -0
- package/lib/public/modules/home-mate-selection.js +38 -0
- package/lib/public/modules/home-mate-settings-menu.js +131 -0
- package/lib/public/modules/home-mate-settings.js +383 -0
- package/lib/public/modules/home-session-actions.js +373 -0
- package/lib/public/modules/home-session-model-confirmation.js +13 -0
- package/lib/public/modules/home-shell.js +9 -0
- package/lib/public/modules/home-sidebar-chat-list.js +63 -0
- package/lib/public/modules/home-sidebar.js +158 -0
- package/lib/public/modules/home-sub-surface.js +19 -0
- package/lib/public/modules/home-surface-boot.js +68 -0
- package/lib/public/modules/home-surface.js +141 -0
- package/lib/public/modules/home-tools.js +271 -0
- package/lib/public/modules/markdown.js +50 -2
- package/lib/public/modules/mate-management.js +86 -0
- package/lib/public/modules/mate-wizard.js +0 -7
- package/lib/public/modules/mention.js +17 -19
- package/lib/public/modules/pane-bridge.js +9 -0
- package/lib/public/modules/profile.js +4 -5
- package/lib/public/modules/project-settings.js +34 -28
- package/lib/public/modules/project-switcher.js +11 -5
- package/lib/public/modules/project-workspace-assignment.js +23 -0
- package/lib/public/modules/search-clay-chat.js +402 -0
- package/lib/public/modules/server-settings.js +14 -12
- package/lib/public/modules/session-actions.js +1 -1
- package/lib/public/modules/sidebar-mates.js +56 -552
- package/lib/public/modules/sidebar-mobile.js +7 -64
- package/lib/public/modules/sidebar-presence.js +37 -0
- package/lib/public/modules/split-pair-ui.js +13 -13
- package/lib/public/modules/split-view.js +7 -0
- package/lib/public/modules/sticky-notes.js +7 -6
- package/lib/public/modules/tool-input-composition.js +48 -0
- package/lib/public/modules/tool-llm-status.js +167 -0
- package/lib/public/modules/tool-renderer-advanced.js +285 -0
- package/lib/public/modules/tool-renderer-chart.js +158 -0
- package/lib/public/modules/tool-renderer-semantics.js +35 -0
- package/lib/public/modules/tool-renderer.js +464 -0
- package/lib/public/modules/tool-runtime.js +309 -0
- package/lib/public/modules/tool-ui-evaluator.js +97 -0
- package/lib/public/modules/tool-ui-tree.js +21 -0
- package/lib/public/modules/tui-attention.js +10 -0
- package/lib/public/modules/user-settings.js +16 -23
- package/lib/public/modules/vendor-login.js +287 -0
- package/lib/public/modules/worker-proposal.js +2 -2
- package/lib/public/modules/workspace-assignment-card.js +149 -0
- package/lib/public/modules/workspace-assignment-routing.js +4 -0
- package/lib/public/style.css +13 -2
- package/lib/runtime-env.js +65 -0
- package/lib/sdk-bridge.js +120 -32
- package/lib/sdk-message-processor.js +10 -6
- package/lib/server-home-capsule-creation.js +36 -0
- package/lib/server-home-chat-events.js +287 -0
- package/lib/server-home-chat.js +518 -0
- package/lib/server-home-clay-entry.js +65 -0
- package/lib/server-home-clay-session-links.js +26 -0
- package/lib/server-home-debate-planning.js +214 -0
- package/lib/server-home-debates.js +137 -0
- package/lib/server-home-mate-creation.js +261 -0
- package/lib/server-home-models.js +241 -0
- package/lib/server-home-preferences.js +61 -0
- package/lib/server-mates.js +37 -0
- package/lib/server-tools.js +377 -0
- package/lib/server.js +111 -59
- package/lib/session-pair-mcp-server.js +6 -6
- package/lib/sessions.js +18 -3
- package/lib/tool-capsule-source.js +142 -0
- package/lib/tool-control-mcp-server.js +126 -0
- package/lib/tool-llm.js +48 -0
- package/lib/tool-storage.js +77 -0
- package/lib/tool-ui-spec-advanced.js +82 -0
- package/lib/tool-ui-spec.js +261 -0
- package/lib/tools-registry.js +286 -0
- package/lib/users-home-dock-preferences.js +77 -0
- package/lib/users-home-surface-preferences.js +99 -0
- package/lib/users-preferences.js +4 -7
- package/lib/users.js +12 -0
- package/lib/whats-new-content.js +3 -3
- package/lib/workspace-assignment-service.js +420 -0
- package/lib/workspace-query-mcp-server.js +154 -0
- package/lib/workspace-query-service.js +492 -0
- package/lib/ws-schema.js +93 -12
- package/lib/yoke/adapters/acp.js +2 -1
- package/lib/yoke/adapters/antigravity.js +2 -1
- package/lib/yoke/adapters/claude-worker.js +11 -4
- package/lib/yoke/adapters/claude.js +73 -43
- package/lib/yoke/adapters/codex.js +40 -10
- package/lib/yoke/adapters/kiro.js +2 -1
- package/lib/yoke/claude-user-input.js +38 -0
- package/lib/yoke/codex-app-server.js +20 -2
- package/lib/yoke/codex-user-input.js +64 -0
- package/lib/yoke/complete-once.js +164 -0
- package/lib/yoke/index.js +5 -1
- package/lib/yoke/interface.js +19 -0
- package/lib/yoke/mcp-bridge-server.js +2 -6
- package/lib/yoke/user-input.js +254 -0
- package/package.json +3 -2
- package/lib/public/css/home-chat.css +0 -380
- package/lib/public/modules/home-chat.js +0 -438
- package/lib/server-clay-home.js +0 -245
package/lib/sdk-bridge.js
CHANGED
|
@@ -10,6 +10,7 @@ var { splitShellSegments, attachSkillDiscovery } = require("./sdk-skill-discover
|
|
|
10
10
|
var { isSafeBashSegment } = require("./safe-bash-commands");
|
|
11
11
|
var { createMessageQueue } = require("./sdk-message-queue");
|
|
12
12
|
var { attachMessageProcessor } = require("./sdk-message-processor");
|
|
13
|
+
var homeDebateToolPolicy = require("./home-debate-tool-policy");
|
|
13
14
|
var yoke = require("./yoke");
|
|
14
15
|
|
|
15
16
|
// Extract serializable tool descriptors from MCP server instances.
|
|
@@ -108,6 +109,7 @@ function createSDKBridge(opts) {
|
|
|
108
109
|
var getNotificationsModule = opts.getNotificationsModule || function () { return null; };
|
|
109
110
|
var adapter = opts.adapter;
|
|
110
111
|
var adapters = opts.adapters || {};
|
|
112
|
+
var getRuntimeEnv = opts.getRuntimeEnv || function () { return process.env; };
|
|
111
113
|
var mateDisplayName = opts.mateDisplayName || "";
|
|
112
114
|
var isMate = opts.isMate || (slug.indexOf("mate-") === 0);
|
|
113
115
|
var osUsers = !!opts.osUsers;
|
|
@@ -364,6 +366,7 @@ function createSDKBridge(opts) {
|
|
|
364
366
|
sessionAdapter.generateTitle(userMessages, {
|
|
365
367
|
cwd: cwd,
|
|
366
368
|
linuxUser: getSessionLinuxUser(session) || undefined,
|
|
369
|
+
env: getRuntimeEnv(session),
|
|
367
370
|
}).then(function(title) {
|
|
368
371
|
if (!title || title.length < 2) return;
|
|
369
372
|
title = title.substring(0, 100);
|
|
@@ -391,6 +394,7 @@ function createSDKBridge(opts) {
|
|
|
391
394
|
mateDisplayName: mateDisplayName,
|
|
392
395
|
pushModule: pushModule,
|
|
393
396
|
getNotificationsModule: getNotificationsModule,
|
|
397
|
+
shouldSuppressResponseNotification: opts.shouldSuppressResponseNotification,
|
|
394
398
|
adapter: adapter,
|
|
395
399
|
saveImageFile: opts.saveImageFile,
|
|
396
400
|
getSessionLinuxUser: getSessionLinuxUser,
|
|
@@ -573,6 +577,29 @@ function createSDKBridge(opts) {
|
|
|
573
577
|
if (toolName.indexOf("mcp__clay-debate__") === 0) {
|
|
574
578
|
return { behavior: "allow", updatedInput: input };
|
|
575
579
|
}
|
|
580
|
+
if (toolName.indexOf("mcp__clay-mate-creation__") === 0) {
|
|
581
|
+
return { behavior: "allow", updatedInput: input };
|
|
582
|
+
}
|
|
583
|
+
// Structured user input only presents a question and waits for the user's
|
|
584
|
+
// answer. Yoke may expose the same query-bound capability as a native
|
|
585
|
+
// dynamic tool, its MCP fallback, or the legacy Clay MCP name.
|
|
586
|
+
if (toolName === "ask_user_questions"
|
|
587
|
+
|| toolName === "mcp__yoke-user-input__ask_user_questions"
|
|
588
|
+
|| toolName === "mcp__clay-ask-user__ask_user_questions") {
|
|
589
|
+
return { behavior: "allow", updatedInput: input };
|
|
590
|
+
}
|
|
591
|
+
|
|
592
|
+
var safeCapsuleTools = {
|
|
593
|
+
clay_tool_list: true,
|
|
594
|
+
clay_tool_snapshot: true,
|
|
595
|
+
clay_tool_act: true,
|
|
596
|
+
clay_tool_set: true,
|
|
597
|
+
clay_tool_source: true,
|
|
598
|
+
};
|
|
599
|
+
if (toolName.indexOf("mcp__clay-tools__") === 0
|
|
600
|
+
&& safeCapsuleTools[toolName.substring(toolName.lastIndexOf("__") + 2)]) {
|
|
601
|
+
return { behavior: "allow", updatedInput: input };
|
|
602
|
+
}
|
|
576
603
|
|
|
577
604
|
// Auto-approve split-pair partner tools. The pair itself is
|
|
578
605
|
// user-constructed (the user created the split and its roles and
|
|
@@ -622,10 +649,20 @@ function createSDKBridge(opts) {
|
|
|
622
649
|
}
|
|
623
650
|
}
|
|
624
651
|
|
|
625
|
-
//
|
|
626
|
-
//
|
|
627
|
-
|
|
628
|
-
|
|
652
|
+
// Workspace inspection and proposal posting are session-bound. Keep this
|
|
653
|
+
// list exact so a future execution/mutation tool cannot inherit approval.
|
|
654
|
+
var safeWorkspaceTools = {
|
|
655
|
+
"mcp__clay-workspace__list_projects": true,
|
|
656
|
+
"mcp__clay-workspace__list_project_sessions": true,
|
|
657
|
+
"mcp__clay-workspace__search_project_history": true,
|
|
658
|
+
"mcp__clay-workspace__read_project_session": true,
|
|
659
|
+
"mcp__clay-workspace__search_workspace_history": true,
|
|
660
|
+
"mcp__clay-workspace__list_workspace_activity": true,
|
|
661
|
+
"mcp__clay-workspace__propose_project_assignment": true,
|
|
662
|
+
"mcp__clay-workspace__propose_project_follow_up": true,
|
|
663
|
+
"mcp__clay-workspace__get_assignment_status": true,
|
|
664
|
+
};
|
|
665
|
+
if (safeWorkspaceTools[toolName] || toolName.indexOf("mcp__clay-history__") === 0) {
|
|
629
666
|
return { behavior: "allow", updatedInput: input };
|
|
630
667
|
}
|
|
631
668
|
|
|
@@ -668,6 +705,18 @@ function createSDKBridge(opts) {
|
|
|
668
705
|
}
|
|
669
706
|
|
|
670
707
|
function handleCanUseTool(session, toolName, input, opts) {
|
|
708
|
+
var debateDecision = homeDebateToolPolicy.initialToolDecision(session, toolName, input);
|
|
709
|
+
if (debateDecision) return Promise.resolve(debateDecision);
|
|
710
|
+
// The dynamic proposal tool is bound to this exact query session. It only
|
|
711
|
+
// posts the inline proposal; starting the debate still requires the user.
|
|
712
|
+
if (session.homeDebatePlanning === true && toolName === "propose_debate") {
|
|
713
|
+
return Promise.resolve({ behavior: "allow", updatedInput: input });
|
|
714
|
+
}
|
|
715
|
+
// Mate creation proposals only present the exact-session approval card;
|
|
716
|
+
// creating the Mate still requires the user's explicit action there.
|
|
717
|
+
if (session.mateCreationMode === true && toolName === "propose_mate") {
|
|
718
|
+
return Promise.resolve({ behavior: "allow", updatedInput: input });
|
|
719
|
+
}
|
|
671
720
|
// Full-auto mode: auto-approve everything except AskUserQuestion
|
|
672
721
|
// (which still needs to go through the user interaction flow).
|
|
673
722
|
var clayPermissionMode = session.permissionMode || sm.currentPermissionMode;
|
|
@@ -693,23 +742,6 @@ function createSDKBridge(opts) {
|
|
|
693
742
|
return Promise.resolve(whitelisted);
|
|
694
743
|
}
|
|
695
744
|
|
|
696
|
-
// AskUserQuestion: wait for user answers via WebSocket
|
|
697
|
-
if (toolName === "AskUserQuestion") {
|
|
698
|
-
return new Promise(function(resolve) {
|
|
699
|
-
session.pendingAskUser[opts.toolUseID] = {
|
|
700
|
-
resolve: resolve,
|
|
701
|
-
input: input,
|
|
702
|
-
};
|
|
703
|
-
if (opts.signal) {
|
|
704
|
-
opts.signal.addEventListener("abort", function() {
|
|
705
|
-
delete session.pendingAskUser[opts.toolUseID];
|
|
706
|
-
sendAndRecord(session, { type: "ask_user_answered", toolId: opts.toolUseID });
|
|
707
|
-
resolve({ behavior: "deny", message: "Cancelled" });
|
|
708
|
-
});
|
|
709
|
-
}
|
|
710
|
-
});
|
|
711
|
-
}
|
|
712
|
-
|
|
713
745
|
// Auto-approve if tool was previously allowed for session
|
|
714
746
|
if (session.allowedTools && session.allowedTools[toolName]) {
|
|
715
747
|
return Promise.resolve({ behavior: "allow", updatedInput: input });
|
|
@@ -1032,19 +1064,15 @@ function createSDKBridge(opts) {
|
|
|
1032
1064
|
if (ownsRuntime) {
|
|
1033
1065
|
session.taskStopRequested = false;
|
|
1034
1066
|
session.pendingPermissions = {};
|
|
1035
|
-
// Preserve MCP
|
|
1036
|
-
//
|
|
1037
|
-
// ("card posted, end your turn") and the user's answer is expected to
|
|
1038
|
-
// arrive as a brand-new user_message on the *next* turn. That means the
|
|
1039
|
-
// pending entry MUST survive this finally block. Without it, the
|
|
1040
|
-
// ask_user_response handler can't find the toolId and silently drops
|
|
1041
|
-
// the answer. canUseTool-mode entries (Claude's native path) still hold
|
|
1042
|
-
// an open SDK permission callback that dies with the query, so those
|
|
1043
|
-
// are correctly cleared here.
|
|
1067
|
+
// Preserve only restored legacy MCP entries. Canonical Yoke requests
|
|
1068
|
+
// hold a live provider callback and must be cancelled with their query.
|
|
1044
1069
|
var keepAskUser = {};
|
|
1045
1070
|
for (var _tid in session.pendingAskUser) {
|
|
1046
1071
|
var _pending = session.pendingAskUser[_tid];
|
|
1047
1072
|
if (_pending && _pending.mode === "mcp") keepAskUser[_tid] = _pending;
|
|
1073
|
+
else if (_pending && _pending.mode === "yoke" && _pending.respond && typeof _pending.respond.cancel === "function") {
|
|
1074
|
+
_pending.respond.cancel("Query closed");
|
|
1075
|
+
}
|
|
1048
1076
|
}
|
|
1049
1077
|
session.pendingAskUser = keepAskUser;
|
|
1050
1078
|
session.pendingElicitations = {};
|
|
@@ -1093,6 +1121,7 @@ function createSDKBridge(opts) {
|
|
|
1093
1121
|
handle = await adapter.createQuery({
|
|
1094
1122
|
cwd: cwd,
|
|
1095
1123
|
resumeSessionId: session.cliSessionId,
|
|
1124
|
+
env: getRuntimeEnv(session),
|
|
1096
1125
|
adapterOptions: {
|
|
1097
1126
|
CLAUDE: {
|
|
1098
1127
|
settingSources: ["user", "project", "local"],
|
|
@@ -1209,6 +1238,7 @@ function createSDKBridge(opts) {
|
|
|
1209
1238
|
}
|
|
1210
1239
|
|
|
1211
1240
|
async function startQueryInner(session, text, images, linuxUser) {
|
|
1241
|
+
var sessionRuntimeEnv = getRuntimeEnv(session);
|
|
1212
1242
|
async function ensureVendorReady(vendor) {
|
|
1213
1243
|
if (!vendor) return null;
|
|
1214
1244
|
if (linuxUser && !supportsOsUserIsolation(vendor)) return null;
|
|
@@ -1222,6 +1252,7 @@ function createSDKBridge(opts) {
|
|
|
1222
1252
|
clayTls: clayTls,
|
|
1223
1253
|
clayAuthToken: clayAuthToken,
|
|
1224
1254
|
slug: slug,
|
|
1255
|
+
env: sessionRuntimeEnv,
|
|
1225
1256
|
});
|
|
1226
1257
|
}
|
|
1227
1258
|
var needsReadyMetadata = !sm.capabilitiesByVendor || !sm.capabilitiesByVendor[vendor]
|
|
@@ -1235,6 +1266,7 @@ function createSDKBridge(opts) {
|
|
|
1235
1266
|
clayTls: clayTls,
|
|
1236
1267
|
clayAuthToken: clayAuthToken,
|
|
1237
1268
|
slug: slug,
|
|
1269
|
+
env: sessionRuntimeEnv,
|
|
1238
1270
|
});
|
|
1239
1271
|
rememberAdapterReady(vendor, readyResult);
|
|
1240
1272
|
}
|
|
@@ -1477,8 +1509,37 @@ function createSDKBridge(opts) {
|
|
|
1477
1509
|
|
|
1478
1510
|
var codexConfig = getCodexConfig(sm);
|
|
1479
1511
|
var kiroConfig = getKiroConfig(sm);
|
|
1480
|
-
var
|
|
1512
|
+
var requestedUserInputMode = session.debateSetupMode || session.mateCreationMode ? "fallback" : "auto";
|
|
1513
|
+
var selectedUserInputMode = yoke.userInput.selectMode(sessionAdapter, requestedUserInputMode);
|
|
1514
|
+
var sessionUserInputHandler = function(request, respond) {
|
|
1515
|
+
if (request.presentation === "elicitation" && request.diagnostics && request.diagnostics.elicitation) {
|
|
1516
|
+
var elicitationController = new AbortController();
|
|
1517
|
+
if (respond && typeof respond.onSettle === "function") {
|
|
1518
|
+
respond.onSettle(function (result) {
|
|
1519
|
+
if (result.status !== "submitted") elicitationController.abort();
|
|
1520
|
+
});
|
|
1521
|
+
}
|
|
1522
|
+
return handleElicitation(session, request.diagnostics.elicitation, { signal: elicitationController.signal }).then(function(result) {
|
|
1523
|
+
if (result && result.action === "accept") return respond.submitContent(result.content || {});
|
|
1524
|
+
return respond.cancel("Elicitation rejected");
|
|
1525
|
+
});
|
|
1526
|
+
}
|
|
1527
|
+
if (typeof opts.onUserInputRequest !== "function") return respond.cancel("Structured user input is unavailable.");
|
|
1528
|
+
return opts.onUserInputRequest(session, request, respond);
|
|
1529
|
+
};
|
|
1530
|
+
var localMcpServers = getMcpServers(session);
|
|
1531
|
+
if (selectedUserInputMode === "fallback") {
|
|
1532
|
+
var userInputServer = yoke.userInput.createFallbackServer(sessionAdapter, sessionUserInputHandler, { force: true });
|
|
1533
|
+
if (userInputServer) {
|
|
1534
|
+
localMcpServers = Object.assign({}, localMcpServers || {});
|
|
1535
|
+
localMcpServers[userInputServer.name || "yoke-user-input"] = userInputServer;
|
|
1536
|
+
}
|
|
1537
|
+
}
|
|
1538
|
+
var mergedMcpServers = mergeMcpServers(localMcpServers, getRemoteMcpServers) || undefined;
|
|
1481
1539
|
var sessionToolDefs = getSessionToolDefs(session) || [];
|
|
1540
|
+
if (selectedUserInputMode === "fallback") {
|
|
1541
|
+
sessionToolDefs = sessionToolDefs.concat(yoke.userInput.fallbackToolDefs(sessionUserInputHandler));
|
|
1542
|
+
}
|
|
1482
1543
|
|
|
1483
1544
|
// Derive an explicit session title for fresh queries so the SDK records
|
|
1484
1545
|
// it at session creation and skips its own auto-generation. This also
|
|
@@ -1503,6 +1564,7 @@ function createSDKBridge(opts) {
|
|
|
1503
1564
|
var queryOpts = {
|
|
1504
1565
|
cwd: cwd,
|
|
1505
1566
|
linuxUser: linuxUser || undefined,
|
|
1567
|
+
env: sessionRuntimeEnv,
|
|
1506
1568
|
// appendSystemPrompt, NOT systemPrompt: a plain-string systemPrompt
|
|
1507
1569
|
// REPLACES the entire Claude Code system prompt (sdk.d.ts:2096), which
|
|
1508
1570
|
// would strip the driver session down to the two-sentence pair preset.
|
|
@@ -1535,8 +1597,19 @@ function createSDKBridge(opts) {
|
|
|
1535
1597
|
resumeSessionId: session.cliSessionId || undefined,
|
|
1536
1598
|
abortController: linuxUser ? undefined : session.abortController,
|
|
1537
1599
|
canUseTool: function(toolName, input, toolOpts) {
|
|
1538
|
-
|
|
1600
|
+
var permissionName = toolName;
|
|
1601
|
+
for (var pti = 0; pti < sessionToolDefs.length; pti++) {
|
|
1602
|
+
if (sessionToolDefs[pti].name === toolName && sessionToolDefs[pti].permissionName) {
|
|
1603
|
+
permissionName = sessionToolDefs[pti].permissionName;
|
|
1604
|
+
break;
|
|
1605
|
+
}
|
|
1606
|
+
}
|
|
1607
|
+
return handleCanUseTool(session, permissionName, input, toolOpts);
|
|
1539
1608
|
},
|
|
1609
|
+
onUserInputRequest: function(request, respond) {
|
|
1610
|
+
return sessionUserInputHandler(request, respond);
|
|
1611
|
+
},
|
|
1612
|
+
userInputMode: selectedUserInputMode,
|
|
1540
1613
|
onElicitation: function(request, elicitOpts) {
|
|
1541
1614
|
return handleElicitation(session, request, elicitOpts);
|
|
1542
1615
|
},
|
|
@@ -1757,6 +1830,19 @@ function createSDKBridge(opts) {
|
|
|
1757
1830
|
return true;
|
|
1758
1831
|
}
|
|
1759
1832
|
|
|
1833
|
+
function refreshEnvironmentRuntime() {
|
|
1834
|
+
if (sm && sm.sessions) {
|
|
1835
|
+
sm.sessions.forEach(function (session) { refreshSessionRuntime(session); });
|
|
1836
|
+
}
|
|
1837
|
+
var vendorNames = Object.keys(adapters);
|
|
1838
|
+
for (var i = 0; i < vendorNames.length; i++) {
|
|
1839
|
+
var runtime = adapters[vendorNames[i]];
|
|
1840
|
+
if (!runtime || typeof runtime.shutdownIfIdle !== "function") continue;
|
|
1841
|
+
Promise.resolve(runtime.shutdownIfIdle(0)).catch(function () {});
|
|
1842
|
+
}
|
|
1843
|
+
return true;
|
|
1844
|
+
}
|
|
1845
|
+
|
|
1760
1846
|
function permissionPushTitle(toolName, input) {
|
|
1761
1847
|
if (!input) return "Claude wants to use " + toolName;
|
|
1762
1848
|
var file = input.file_path ? input.file_path.split(/[/\\]/).pop() : "";
|
|
@@ -2078,6 +2164,7 @@ function createSDKBridge(opts) {
|
|
|
2078
2164
|
handle = await mentionAdapter.createQuery({
|
|
2079
2165
|
cwd: cwd,
|
|
2080
2166
|
linuxUser: opts.linuxUser || undefined,
|
|
2167
|
+
env: getRuntimeEnv(opts.session || { linuxUser: opts.linuxUser || null }),
|
|
2081
2168
|
systemPrompt: opts.claudeMd,
|
|
2082
2169
|
model: opts.model || undefined,
|
|
2083
2170
|
toolServers: opts.includeMcpServers ? (mergeMcpServers(getMcpServers(), getRemoteMcpServers) || undefined) : undefined,
|
|
@@ -2233,6 +2320,7 @@ function createSDKBridge(opts) {
|
|
|
2233
2320
|
startQuery: startQuery,
|
|
2234
2321
|
pushMessage: pushMessage,
|
|
2235
2322
|
refreshSessionRuntime: refreshSessionRuntime,
|
|
2323
|
+
refreshEnvironmentRuntime: refreshEnvironmentRuntime,
|
|
2236
2324
|
setModel: setModel,
|
|
2237
2325
|
setEffort: setEffort,
|
|
2238
2326
|
setPermissionMode: setPermissionMode,
|
|
@@ -9,6 +9,7 @@ function attachMessageProcessor(ctx) {
|
|
|
9
9
|
var mateDisplayName = ctx.mateDisplayName;
|
|
10
10
|
var pushModule = ctx.pushModule;
|
|
11
11
|
var getNotificationsModule = ctx.getNotificationsModule || function () { return null; };
|
|
12
|
+
var shouldSuppressResponseNotification = ctx.shouldSuppressResponseNotification || function () { return false; };
|
|
12
13
|
var getSDK = ctx.getSDK;
|
|
13
14
|
var adapter = ctx.adapter;
|
|
14
15
|
var cwd = ctx.cwd;
|
|
@@ -484,10 +485,8 @@ function attachMessageProcessor(ctx) {
|
|
|
484
485
|
session.pendingPermissions = {};
|
|
485
486
|
session.pendingElicitations = {};
|
|
486
487
|
// Record ask_user_answered for any leftover pending questions so replay pairs correctly.
|
|
487
|
-
//
|
|
488
|
-
//
|
|
489
|
-
// entries must survive across turns so the eventual ask_user_response can inject the
|
|
490
|
-
// answer as the next user message. Only blocking modes (Claude canUseTool) get closed.
|
|
488
|
+
// Restored legacy MCP entries survive across turns. Canonical Yoke
|
|
489
|
+
// requests own a live provider callback and are cancelled on turn end.
|
|
491
490
|
var leftoverAskIds = Object.keys(session.pendingAskUser);
|
|
492
491
|
var keptAskUser = {};
|
|
493
492
|
for (var lai = 0; lai < leftoverAskIds.length; lai++) {
|
|
@@ -497,6 +496,9 @@ function attachMessageProcessor(ctx) {
|
|
|
497
496
|
keptAskUser[lid] = lentry;
|
|
498
497
|
continue;
|
|
499
498
|
}
|
|
499
|
+
if (lentry && lentry.mode === "yoke" && lentry.respond && typeof lentry.respond.cancel === "function") {
|
|
500
|
+
lentry.respond.cancel("Turn ended");
|
|
501
|
+
}
|
|
500
502
|
sendAndRecord(session, { type: "ask_user_answered", toolId: lid });
|
|
501
503
|
}
|
|
502
504
|
session.pendingAskUser = keptAskUser;
|
|
@@ -582,8 +584,10 @@ function attachMessageProcessor(ctx) {
|
|
|
582
584
|
var _donePreviewText = (session.responsePreview || "").replace(/\s+/g, " ").trim();
|
|
583
585
|
if (_donePreviewText.length > 140) _donePreviewText = _donePreviewText.substring(0, 140) + "...";
|
|
584
586
|
var _doneTitle = mateDisplayName ? (mateDisplayName + " responded") : (session.title || "Claude");
|
|
587
|
+
var _suppressResponseNotification = false;
|
|
588
|
+
try { _suppressResponseNotification = shouldSuppressResponseNotification(session) === true; } catch (e) {}
|
|
585
589
|
|
|
586
|
-
if (pushModule && !session._delegatedBy) {
|
|
590
|
+
if (pushModule && !session._delegatedBy && !_suppressResponseNotification) {
|
|
587
591
|
pushModule.sendPush({
|
|
588
592
|
type: "done",
|
|
589
593
|
slug: slug,
|
|
@@ -594,7 +598,7 @@ function attachMessageProcessor(ctx) {
|
|
|
594
598
|
}
|
|
595
599
|
|
|
596
600
|
var _nm = getNotificationsModule();
|
|
597
|
-
if (_nm && !session.loop && !session._delegatedBy) {
|
|
601
|
+
if (_nm && !session.loop && !session._delegatedBy && !_suppressResponseNotification) {
|
|
598
602
|
_nm.notify("response_done", {
|
|
599
603
|
title: _doneTitle,
|
|
600
604
|
preview: _donePreviewText,
|
|
@@ -0,0 +1,36 @@
|
|
|
1
|
+
// Validation and bounded Mate context for a Capsule creation conversation.
|
|
2
|
+
|
|
3
|
+
function normalizeCapsuleDescription(value) {
|
|
4
|
+
if (typeof value !== "string") return "";
|
|
5
|
+
return value.replace(/[\u0000-\u0008\u000b\u000c\u000e-\u001f\u007f]/g, " ").trim().slice(0, 4000);
|
|
6
|
+
}
|
|
7
|
+
|
|
8
|
+
function readCapsuleCreationIntent(value) {
|
|
9
|
+
if (!value || value.type !== "capsule_creation") return null;
|
|
10
|
+
var description = normalizeCapsuleDescription(value.description);
|
|
11
|
+
if (!description) {
|
|
12
|
+
var error = new Error("Describe the interface you need.");
|
|
13
|
+
error.code = "capsule_description_required";
|
|
14
|
+
throw error;
|
|
15
|
+
}
|
|
16
|
+
return { type: "capsule_creation", description: description };
|
|
17
|
+
}
|
|
18
|
+
|
|
19
|
+
function buildCapsuleCreationPrompt(description) {
|
|
20
|
+
return [
|
|
21
|
+
"Help the user turn the following request into a durable Capsule interface.",
|
|
22
|
+
"First inspect the need conversationally and help refine the behavior, state, and safe declarative UI.",
|
|
23
|
+
"Do not install or update a Capsule until the user has inspected the proposal and explicitly approved it through the existing permission flow.",
|
|
24
|
+
"The Capsule remains user-owned and available to all of the user's Mates.",
|
|
25
|
+
"",
|
|
26
|
+
"<capsule_request>",
|
|
27
|
+
description,
|
|
28
|
+
"</capsule_request>",
|
|
29
|
+
].join("\n");
|
|
30
|
+
}
|
|
31
|
+
|
|
32
|
+
module.exports = {
|
|
33
|
+
normalizeCapsuleDescription: normalizeCapsuleDescription,
|
|
34
|
+
readCapsuleCreationIntent: readCapsuleCreationIntent,
|
|
35
|
+
buildCapsuleCreationPrompt: buildCapsuleCreationPrompt,
|
|
36
|
+
};
|