clay-server 3.8.1 → 4.0.0-beta.10
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/lib/ask-user-mcp-server.js +5 -119
- package/lib/background-task-timing.js +105 -0
- 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 +23 -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/knowledge-import.js +436 -0
- package/lib/knowledge-record-store.js +188 -0
- package/lib/knowledge-search.js +224 -0
- package/lib/mate-creation-mcp-server.js +55 -0
- package/lib/mate-knowledge-mcp-server.js +151 -0
- package/lib/mate-knowledge-migration.js +283 -0
- package/lib/mate-knowledge-service.js +488 -0
- package/lib/mate-knowledge-sync.js +482 -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 +17 -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 +23 -0
- package/lib/project-logs-comments.js +137 -0
- package/lib/project-logs-mcp-server.js +290 -0
- package/lib/project-logs-query.js +167 -0
- package/lib/project-logs-root.js +67 -0
- package/lib/project-logs-schema.js +259 -0
- package/lib/project-logs-service.js +357 -0
- package/lib/project-logs-snapshot.js +202 -0
- package/lib/project-logs-store.js +498 -0
- package/lib/project-logs-versioning.js +128 -0
- package/lib/project-logs.js +347 -0
- package/lib/project-mate-creation-proposal.js +120 -0
- package/lib/project-mate-interaction.js +14 -0
- package/lib/project-mate-knowledge.js +110 -0
- package/lib/project-memory.js +36 -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 +414 -0
- package/lib/project-worker-proposal.js +25 -25
- package/lib/project-workspace-query.js +144 -0
- package/lib/project.js +433 -102
- package/lib/public/app.js +109 -48
- 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/input.css +79 -25
- 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/project-logs.css +234 -0
- package/lib/public/css/scheduler.css +1 -1
- 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 +96 -74
- package/lib/public/modules/app-connection.js +100 -5
- 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 +124 -38
- package/lib/public/modules/app-notifications.js +8 -119
- package/lib/public/modules/app-panels.js +43 -2
- 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/background-tasks-ui.js +139 -16
- 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 +165 -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-sidebar.js +0 -8
- 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-logs-ambient.js +238 -0
- package/lib/public/modules/project-logs-render.js +359 -0
- package/lib/public/modules/project-logs.js +328 -0
- 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/scheduler.js +17 -3
- 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 +12 -73
- package/lib/public/modules/sidebar-presence.js +37 -0
- package/lib/public/modules/sidebar-sessions.js +25 -1
- 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 +106 -53
- 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-palette.js +76 -4
- 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 +14 -2
- package/lib/runtime-env.js +65 -0
- package/lib/sdk-bridge.js +120 -32
- package/lib/sdk-message-processor.js +34 -13
- 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 +166 -59
- package/lib/session-pair-mcp-server.js +6 -6
- package/lib/sessions.js +22 -4
- 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 +107 -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 +141 -46
- package/lib/yoke/adapters/codex.js +79 -11
- 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-background-tasks.js +8 -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 +4 -3
- 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/project.js
CHANGED
|
@@ -5,18 +5,22 @@ var crypto = require("crypto");
|
|
|
5
5
|
var { createSessionManager } = require("./sessions");
|
|
6
6
|
var { attachGitSessionAttribution } = require("./git-session-attribution");
|
|
7
7
|
var { createSDKBridge, createMessageQueue } = require("./sdk-bridge");
|
|
8
|
+
var runtimeEnv = require("./runtime-env");
|
|
8
9
|
var { createTerminalManager } = require("./terminal-manager");
|
|
9
10
|
var { createNotesManager } = require("./notes");
|
|
10
11
|
var { fetchLatestVersion, fetchVersion, isNewer } = require("./updater");
|
|
11
12
|
var { execFileSync, spawn } = require("child_process");
|
|
12
13
|
var usersModule = require("./users");
|
|
13
14
|
var { resolveOsUserInfo, fsAsUser, grantProjectAccess } = require("./os-users");
|
|
15
|
+
var { buildUserEnv } = require("./build-user-env");
|
|
14
16
|
var crisisSafety = require("./crisis-safety");
|
|
15
17
|
var matesModule = require("./mates");
|
|
16
18
|
var sessionSearch = require("./session-search");
|
|
17
19
|
var userPresence = require("./user-presence");
|
|
18
20
|
var { attachDebate } = require("./project-debate");
|
|
19
21
|
var { attachDebateProposal } = require("./project-debate-proposal");
|
|
22
|
+
var { attachMateCreationProposal } = require("./project-mate-creation-proposal");
|
|
23
|
+
var { attachAskUser } = require("./project-ask-user");
|
|
20
24
|
var { attachMemory } = require("./project-memory");
|
|
21
25
|
var { attachMateInteraction } = require("./project-mate-interaction");
|
|
22
26
|
var { attachUserMention } = require("./project-user-mention");
|
|
@@ -30,18 +34,76 @@ var { attachSessions } = require("./project-sessions");
|
|
|
30
34
|
var { attachModels } = require("./project-models");
|
|
31
35
|
var { attachUserMessage } = require("./project-user-message");
|
|
32
36
|
var { attachShellCommand } = require("./project-shell-command");
|
|
37
|
+
var { attachVendorLogin } = require("./project-vendor-login");
|
|
33
38
|
var { attachConnection } = require("./project-connection");
|
|
34
39
|
var { attachMcp } = require("./project-mcp");
|
|
35
40
|
var { createLocalMcp } = require("./mcp-local");
|
|
36
41
|
var { attachEmail: attachEmailModule } = require("./project-email");
|
|
37
42
|
var { attachSessionSpawn } = require("./project-session-spawn");
|
|
43
|
+
var { attachDelegatedSession } = require("./project-delegated-session");
|
|
44
|
+
var { attachDelegatedFollowUp } = require("./project-delegated-follow-up");
|
|
45
|
+
var workspaceSessionRef = require("./workspace-query-service").sessionRef;
|
|
38
46
|
var { attachSessionPair } = require("./project-session-pair");
|
|
39
47
|
var { attachSessionHandoff } = require("./project-session-handoff");
|
|
40
48
|
var { attachSessionNotes, composeSystemPrompts } = require("./project-session-notes");
|
|
41
49
|
var { attachSessionDocument } = require("./project-session-document");
|
|
50
|
+
var { attachCapsuleCatalog } = require("./project-capsule-catalog");
|
|
51
|
+
var { attachProjectWorkspaceQuery } = require("./project-workspace-query");
|
|
52
|
+
var { attachProjectLogs } = require("./project-logs");
|
|
53
|
+
var { attachProjectMateKnowledge } = require("./project-mate-knowledge");
|
|
42
54
|
var { attachSplitGroups } = require("./session-split-groups");
|
|
55
|
+
var toolControlMcp = require("./tool-control-mcp-server");
|
|
56
|
+
var toolLlm = require("./tool-llm");
|
|
43
57
|
// project-notifications is attached globally in server.js, passed via opts.notificationsModule
|
|
44
58
|
|
|
59
|
+
function createMateToolControlMcp(adapter, config) {
|
|
60
|
+
if (!adapter || typeof adapter.createToolServer !== "function") return null;
|
|
61
|
+
var handlers = {
|
|
62
|
+
list: function () {
|
|
63
|
+
var manifests = config.list(config.userId) || [];
|
|
64
|
+
var tools = [];
|
|
65
|
+
for (var i = 0; i < manifests.length; i++) {
|
|
66
|
+
tools.push({
|
|
67
|
+
id: manifests[i].id,
|
|
68
|
+
name: manifests[i].name,
|
|
69
|
+
description: manifests[i].description || "",
|
|
70
|
+
useWhen: manifests[i].useWhen || "",
|
|
71
|
+
runtime: manifests[i].runtime || "worker",
|
|
72
|
+
permissions: manifests[i].permissions || [],
|
|
73
|
+
skills: manifests[i].skills || "",
|
|
74
|
+
});
|
|
75
|
+
}
|
|
76
|
+
return tools;
|
|
77
|
+
},
|
|
78
|
+
snapshot: function (toolId) {
|
|
79
|
+
return config.control(config.userId, config.mateId, toolId, "snapshot", {});
|
|
80
|
+
},
|
|
81
|
+
act: function (toolId, actionId, args) {
|
|
82
|
+
return config.control(config.userId, config.mateId, toolId, "act", { actionId: actionId, args: args });
|
|
83
|
+
},
|
|
84
|
+
set: function (toolId, controlId, value) {
|
|
85
|
+
return config.control(config.userId, config.mateId, toolId, "set", { controlId: controlId, value: value });
|
|
86
|
+
},
|
|
87
|
+
source: function (toolId) {
|
|
88
|
+
return config.source(config.userId, toolId);
|
|
89
|
+
},
|
|
90
|
+
install: function (input) {
|
|
91
|
+
return config.install(config.userId, input);
|
|
92
|
+
},
|
|
93
|
+
update: function (toolId, input) {
|
|
94
|
+
return config.update(config.userId, toolId, input);
|
|
95
|
+
},
|
|
96
|
+
uninstall: function (toolId) {
|
|
97
|
+
return config.remove(config.userId, toolId);
|
|
98
|
+
},
|
|
99
|
+
};
|
|
100
|
+
return adapter.createToolServer({
|
|
101
|
+
name: "clay-tools",
|
|
102
|
+
version: "1.0.0",
|
|
103
|
+
tools: toolControlMcp.getToolDefs(handlers),
|
|
104
|
+
});
|
|
105
|
+
}
|
|
106
|
+
|
|
45
107
|
// --- Context Sources persistence ---
|
|
46
108
|
var _ctxSrcConfig = require("./config");
|
|
47
109
|
var _ctxSrcDir = path.join(_ctxSrcConfig.CONFIG_DIR, "context-sources");
|
|
@@ -73,26 +135,7 @@ function saveContextSources(slug, sessionId, activeIds) {
|
|
|
73
135
|
// Validate environment variable string (KEY=VALUE per line)
|
|
74
136
|
// Returns null if valid, or an error string if invalid
|
|
75
137
|
function validateEnvString(str) {
|
|
76
|
-
|
|
77
|
-
var lines = str.split("\n");
|
|
78
|
-
for (var i = 0; i < lines.length; i++) {
|
|
79
|
-
var line = lines[i].trim();
|
|
80
|
-
if (!line || line.charAt(0) === "#") continue;
|
|
81
|
-
// Must be KEY=VALUE format
|
|
82
|
-
var eqIdx = line.indexOf("=");
|
|
83
|
-
if (eqIdx < 1) return "Invalid format at line " + (i + 1) + ": expected KEY=VALUE";
|
|
84
|
-
var key = line.substring(0, eqIdx);
|
|
85
|
-
// Key must be valid env var name (no shell metacharacters)
|
|
86
|
-
if (!/^[a-zA-Z_][a-zA-Z0-9_]*$/.test(key)) {
|
|
87
|
-
return "Invalid variable name at line " + (i + 1) + ": " + key;
|
|
88
|
-
}
|
|
89
|
-
// Value must not contain shell injection characters
|
|
90
|
-
var value = line.substring(eqIdx + 1);
|
|
91
|
-
if (/[`$\\;|&><(){}\n]/.test(value) && !/^["'].*["']$/.test(value)) {
|
|
92
|
-
return "Potentially unsafe value at line " + (i + 1) + ": shell metacharacters detected";
|
|
93
|
-
}
|
|
94
|
-
}
|
|
95
|
-
return null;
|
|
138
|
+
return runtimeEnv.validateEnvString(str);
|
|
96
139
|
}
|
|
97
140
|
|
|
98
141
|
// YOKE adapter (replaces direct SDK access)
|
|
@@ -153,8 +196,6 @@ function createProjectContext(opts) {
|
|
|
153
196
|
var lanHost = opts.lanHost || null;
|
|
154
197
|
var getProjectCount = opts.getProjectCount || function () { return 1; };
|
|
155
198
|
var getProjectList = opts.getProjectList || function () { return []; };
|
|
156
|
-
var getAllProjectSessions = opts.getAllProjectSessions || function () { return []; };
|
|
157
|
-
var getAllProjectsWithSessions = opts.getAllProjectsWithSessions || function () { return []; };
|
|
158
199
|
var isHostAgent = !!opts.isHostAgent;
|
|
159
200
|
var getHubSchedules = opts.getHubSchedules || function () { return []; };
|
|
160
201
|
var moveScheduleToProject = opts.moveScheduleToProject || function () { return { ok: false, error: "Not supported" }; };
|
|
@@ -168,6 +209,23 @@ function createProjectContext(opts) {
|
|
|
168
209
|
var projectOwnerId = opts.projectOwnerId || null;
|
|
169
210
|
var worktreeMeta = opts.worktreeMeta || null; // { parentSlug, branch, external }
|
|
170
211
|
var isMate = opts.isMate || false;
|
|
212
|
+
var mateId = opts.mateId || (isMate ? path.basename(cwd) : null);
|
|
213
|
+
var listControllableTools = opts.listControllableTools || function () { return []; };
|
|
214
|
+
var controlToolForMate = opts.controlToolForMate || function () {
|
|
215
|
+
return Promise.reject(new Error("Tool control is unavailable."));
|
|
216
|
+
};
|
|
217
|
+
var installToolForMate = opts.installToolForMate || function () {
|
|
218
|
+
return Promise.reject(new Error("Tool installation is unavailable."));
|
|
219
|
+
};
|
|
220
|
+
var sourceToolForMate = opts.sourceToolForMate || function () {
|
|
221
|
+
return Promise.reject(new Error("Capsule source access is unavailable."));
|
|
222
|
+
};
|
|
223
|
+
var updateToolForMate = opts.updateToolForMate || function () {
|
|
224
|
+
return Promise.reject(new Error("Capsule source updates are unavailable."));
|
|
225
|
+
};
|
|
226
|
+
var removeToolForMate = opts.removeToolForMate || function () {
|
|
227
|
+
return Promise.reject(new Error("Tool removal is unavailable."));
|
|
228
|
+
};
|
|
171
229
|
var onCreateWorktree = opts.onCreateWorktree || null;
|
|
172
230
|
var serverPort = opts.port || 2633;
|
|
173
231
|
var serverTls = opts.tls || false;
|
|
@@ -219,8 +277,7 @@ function createProjectContext(opts) {
|
|
|
219
277
|
|
|
220
278
|
// Cache resolved OS user info to avoid repeated getent calls
|
|
221
279
|
var osUserInfoCache = {};
|
|
222
|
-
function
|
|
223
|
-
var linuxUser = getLinuxUserForWs(ws);
|
|
280
|
+
function getOsUserInfoForLinuxUser(linuxUser) {
|
|
224
281
|
if (!linuxUser) return null;
|
|
225
282
|
if (osUserInfoCache[linuxUser]) return osUserInfoCache[linuxUser];
|
|
226
283
|
try {
|
|
@@ -233,23 +290,34 @@ function createProjectContext(opts) {
|
|
|
233
290
|
}
|
|
234
291
|
}
|
|
235
292
|
|
|
293
|
+
function getOsUserInfoForWs(ws) {
|
|
294
|
+
var linuxUser = getLinuxUserForWs(ws);
|
|
295
|
+
return getOsUserInfoForLinuxUser(linuxUser);
|
|
296
|
+
}
|
|
297
|
+
|
|
236
298
|
function getOsUserInfoForReq(req) {
|
|
237
299
|
if (!osUsers) return null;
|
|
238
300
|
if (!req._clayUser || !req._clayUser.linuxUser) return null;
|
|
239
301
|
var linuxUser = req._clayUser.linuxUser;
|
|
240
|
-
|
|
241
|
-
|
|
242
|
-
|
|
243
|
-
|
|
244
|
-
|
|
245
|
-
|
|
246
|
-
|
|
247
|
-
|
|
248
|
-
|
|
302
|
+
return getOsUserInfoForLinuxUser(linuxUser);
|
|
303
|
+
}
|
|
304
|
+
|
|
305
|
+
function getRuntimeEnvForSession(session) {
|
|
306
|
+
var linuxUser = (session && session.linuxUser) || getLinuxUserForSession(session);
|
|
307
|
+
var osUserInfo = getOsUserInfoForLinuxUser(linuxUser);
|
|
308
|
+
var baseEnv = osUserInfo ? buildUserEnv(osUserInfo) : process.env;
|
|
309
|
+
var shared = typeof opts.onGetSharedEnv === "function" ? opts.onGetSharedEnv() : null;
|
|
310
|
+
var projectEnv = typeof opts.onGetProjectEnv === "function" ? opts.onGetProjectEnv(slug) : null;
|
|
311
|
+
return runtimeEnv.resolveRuntimeEnv({
|
|
312
|
+
baseEnv: baseEnv,
|
|
313
|
+
sharedEnvrc: shared && shared.envrc,
|
|
314
|
+
projectEnvrc: projectEnv && projectEnv.envrc,
|
|
315
|
+
});
|
|
249
316
|
}
|
|
250
317
|
|
|
251
318
|
// --- Per-project clients ---
|
|
252
319
|
var clients = new Set();
|
|
320
|
+
var homeDebateClients = new Set();
|
|
253
321
|
|
|
254
322
|
// --- Browser extension state (shared mutable object) ---
|
|
255
323
|
var _extToken = crypto.randomUUID(); // Auth token for MCP server bridge
|
|
@@ -369,6 +437,10 @@ function createProjectContext(opts) {
|
|
|
369
437
|
ws.send(data);
|
|
370
438
|
}
|
|
371
439
|
}
|
|
440
|
+
homeDebateClients.forEach(function (ws) {
|
|
441
|
+
if (ws.readyState !== 1) { homeDebateClients.delete(ws); return; }
|
|
442
|
+
if (!clients.has(ws) && ws._clayHomeDebateSlug === slug && ws._clayActiveSession === sessionId) ws.send(data);
|
|
443
|
+
});
|
|
372
444
|
}
|
|
373
445
|
|
|
374
446
|
function sendToSessionOthers(sender, sessionId, obj) {
|
|
@@ -537,6 +609,41 @@ function createProjectContext(opts) {
|
|
|
537
609
|
},
|
|
538
610
|
fsAsUser: fsAsUser,
|
|
539
611
|
});
|
|
612
|
+
var _capsuleCatalog = attachCapsuleCatalog({
|
|
613
|
+
isMate: isMate,
|
|
614
|
+
listManifests: listControllableTools,
|
|
615
|
+
getUserId: function (session) {
|
|
616
|
+
return (session && session.ownerId) || projectOwnerId || "default";
|
|
617
|
+
},
|
|
618
|
+
getSdk: function () { return sdk; },
|
|
619
|
+
getSessions: function () { return sm.sessions; },
|
|
620
|
+
});
|
|
621
|
+
var _workspaceQuery = attachProjectWorkspaceQuery({
|
|
622
|
+
service: opts.workspaceQueryService || null,
|
|
623
|
+
sm: sm,
|
|
624
|
+
projectSlug: slug,
|
|
625
|
+
getProjectOwnerId: function () { return projectOwnerId; },
|
|
626
|
+
isMate: isMate,
|
|
627
|
+
mateId: mateId,
|
|
628
|
+
});
|
|
629
|
+
var _projectLogs = attachProjectLogs({
|
|
630
|
+
service: opts.projectLogsService || null,
|
|
631
|
+
sm: sm,
|
|
632
|
+
projectSlug: slug,
|
|
633
|
+
getProjectOwnerId: function () { return projectOwnerId; },
|
|
634
|
+
isMate: isMate,
|
|
635
|
+
mateId: mateId,
|
|
636
|
+
sendTo: sendTo,
|
|
637
|
+
getClients: function () { return clients; },
|
|
638
|
+
});
|
|
639
|
+
var _mateKnowledge = attachProjectMateKnowledge({
|
|
640
|
+
service: opts.mateKnowledgeService || null,
|
|
641
|
+
sm: sm,
|
|
642
|
+
projectSlug: slug,
|
|
643
|
+
getProjectOwnerId: function () { return projectOwnerId; },
|
|
644
|
+
isMate: isMate,
|
|
645
|
+
mateId: mateId,
|
|
646
|
+
});
|
|
540
647
|
|
|
541
648
|
// The SDK bridge is created after local MCP servers. Session spawning uses
|
|
542
649
|
// a getter so tool handlers see the initialized bridge when they run.
|
|
@@ -587,15 +694,46 @@ function createProjectContext(opts) {
|
|
|
587
694
|
var _debateProposal = attachDebateProposal({
|
|
588
695
|
cwd: cwd,
|
|
589
696
|
isMate: isMate,
|
|
697
|
+
isHostAgent: isHostAgent,
|
|
590
698
|
sendTo: sendTo,
|
|
591
699
|
buildMateCtx: matesModule.buildMateCtx,
|
|
592
700
|
getMate: matesModule.getMate,
|
|
593
701
|
getProjectOwnerId: function () { return projectOwnerId; },
|
|
702
|
+
getVendorModelCatalog: function (ws, vendor) { return _models.getVendorCatalog(ws, vendor); },
|
|
703
|
+
getVendorModelCatalogForSession: function (session, vendor) {
|
|
704
|
+
var user = session && session.ownerId ? usersModule.findUserById(session.ownerId) : null;
|
|
705
|
+
return _models.getVendorCatalog({ _clayUser: user || null }, vendor);
|
|
706
|
+
},
|
|
594
707
|
startDebate: function (session, briefData, moderatorId, ws) {
|
|
595
708
|
if (!_debate) return { error: "The debate engine is unavailable." };
|
|
596
709
|
return _debate.handleMcpDebateApproval(session, briefData, moderatorId, ws);
|
|
597
710
|
},
|
|
711
|
+
recordSessionEvent: function (session, event) { sm.sendAndRecord(session, event); },
|
|
598
712
|
});
|
|
713
|
+
var _mateCreationProposal = attachMateCreationProposal({
|
|
714
|
+
isMate: isMate,
|
|
715
|
+
isHostAgent: isHostAgent,
|
|
716
|
+
isMultiUser: usersModule.isMultiUser,
|
|
717
|
+
getProjectOwnerId: function () { return projectOwnerId; },
|
|
718
|
+
recordSessionEvent: function (session, event) { sm.sendAndRecord(session, event); },
|
|
719
|
+
getVendorModelCatalog: function (ws, vendor) { return _models.getVendorCatalog(ws, vendor); },
|
|
720
|
+
createReadyMate: opts.createReadyMate,
|
|
721
|
+
});
|
|
722
|
+
var _askUser = attachAskUser({ record: function (session, event) { sm.sendAndRecord(session, event); } });
|
|
723
|
+
|
|
724
|
+
function createToolControlMcpServer() {
|
|
725
|
+
if (!isMate || !adapter || typeof adapter.createToolServer !== "function") return null;
|
|
726
|
+
return createMateToolControlMcp(adapter, {
|
|
727
|
+
userId: projectOwnerId || "default",
|
|
728
|
+
mateId: path.basename(cwd),
|
|
729
|
+
list: listControllableTools,
|
|
730
|
+
control: controlToolForMate,
|
|
731
|
+
source: sourceToolForMate,
|
|
732
|
+
install: installToolForMate,
|
|
733
|
+
update: updateToolForMate,
|
|
734
|
+
remove: removeToolForMate,
|
|
735
|
+
});
|
|
736
|
+
}
|
|
599
737
|
|
|
600
738
|
// --- MCP tool servers (created via YOKE adapter) ---
|
|
601
739
|
var mcpServers = (function () {
|
|
@@ -621,6 +759,27 @@ function createProjectContext(opts) {
|
|
|
621
759
|
}
|
|
622
760
|
}
|
|
623
761
|
|
|
762
|
+
// Project Logs. Project sessions get the project-scoped set; Mate projects
|
|
763
|
+
// get the read-only cross-project set only when the Mate registry confirms
|
|
764
|
+
// authoritative builtin Clay.
|
|
765
|
+
try {
|
|
766
|
+
var projectLogsMcpConfig = _projectLogs.createMcpServer(adapter, null);
|
|
767
|
+
if (projectLogsMcpConfig) servers[projectLogsMcpConfig.name || "clay-logs"] = projectLogsMcpConfig;
|
|
768
|
+
} catch (e) {
|
|
769
|
+
console.error("[project] Failed to create clay-logs MCP server:", e.message);
|
|
770
|
+
}
|
|
771
|
+
|
|
772
|
+
// Mate Knowledge. Mate projects only; the registry decides whether this is
|
|
773
|
+
// one Mate's own scope or authoritative Clay's cross-Mate read view.
|
|
774
|
+
if (isMate) {
|
|
775
|
+
try {
|
|
776
|
+
var mateKnowledgeMcpConfig = _mateKnowledge.createMcpServer(adapter, null);
|
|
777
|
+
if (mateKnowledgeMcpConfig) servers[mateKnowledgeMcpConfig.name || "clay-knowledge"] = mateKnowledgeMcpConfig;
|
|
778
|
+
} catch (e) {
|
|
779
|
+
console.error("[project] Failed to create clay-knowledge MCP server:", e.message);
|
|
780
|
+
}
|
|
781
|
+
}
|
|
782
|
+
|
|
624
783
|
// Session-bound access to the source of a handoff (main projects only).
|
|
625
784
|
if (!isMate) {
|
|
626
785
|
try {
|
|
@@ -649,77 +808,39 @@ function createProjectContext(opts) {
|
|
|
649
808
|
console.error("[project] Failed to create debate MCP server:", e.message);
|
|
650
809
|
}
|
|
651
810
|
|
|
652
|
-
|
|
653
|
-
// Gives Clay BM25 search + targeted reads across the user's full
|
|
654
|
-
// workspace. Read-only. Other Mates and project sessions never see
|
|
655
|
-
// these tools because the gate is the isHostAgent project flag.
|
|
656
|
-
if (isHostAgent) {
|
|
811
|
+
if (isMate && isHostAgent) {
|
|
657
812
|
try {
|
|
658
|
-
var
|
|
659
|
-
|
|
660
|
-
getAllProjectsWithSessions: getAllProjectsWithSessions,
|
|
661
|
-
});
|
|
662
|
-
var clayHistoryMcpConfig = adapter.createToolServer({ name: "clay-history", version: "1.0.0", tools: clayHistoryToolDefs });
|
|
663
|
-
if (clayHistoryMcpConfig) servers[clayHistoryMcpConfig.name || "clay-history"] = clayHistoryMcpConfig;
|
|
813
|
+
var mateCreationMcpConfig = _mateCreationProposal.createMcpServer(adapter, null);
|
|
814
|
+
if (mateCreationMcpConfig) servers[mateCreationMcpConfig.name || "clay-mate-creation"] = mateCreationMcpConfig;
|
|
664
815
|
} catch (e) {
|
|
665
|
-
console.error("[project] Failed to create
|
|
816
|
+
console.error("[project] Failed to create Mate creation MCP server:", e.message);
|
|
666
817
|
}
|
|
667
818
|
}
|
|
668
819
|
|
|
669
|
-
//
|
|
820
|
+
// Owner-bound workspace inspection is available only inside Mate
|
|
821
|
+
// projects. The server-side Mate registry decides whether the wider
|
|
822
|
+
// builtin Clay tools are present; project flags and tool arguments do not.
|
|
670
823
|
if (isMate) {
|
|
671
824
|
try {
|
|
672
|
-
var
|
|
673
|
-
|
|
674
|
-
|
|
675
|
-
|
|
676
|
-
|
|
677
|
-
|
|
678
|
-
|
|
679
|
-
|
|
680
|
-
|
|
681
|
-
|
|
682
|
-
|
|
683
|
-
|
|
684
|
-
return Promise.resolve({
|
|
685
|
-
content: [{ type: "text", text: "Error: no active session in " + slug + "; cannot display question card." }],
|
|
686
|
-
isError: true,
|
|
687
|
-
});
|
|
688
|
-
}
|
|
689
|
-
if (session.loop && session.loop.active && session.loop.role !== "crafting") {
|
|
690
|
-
return Promise.resolve({
|
|
691
|
-
content: [{ type: "text", text: "Error: Autonomous mode. Make your own decision." }],
|
|
692
|
-
isError: true,
|
|
693
|
-
});
|
|
694
|
-
}
|
|
825
|
+
var workspaceMcpConfig = _workspaceQuery.createMcpServer(adapter, null);
|
|
826
|
+
if (workspaceMcpConfig) servers[workspaceMcpConfig.name || "clay-workspace"] = workspaceMcpConfig;
|
|
827
|
+
} catch (e) {
|
|
828
|
+
console.error("[project] Failed to create clay-workspace MCP server:", e.message);
|
|
829
|
+
}
|
|
830
|
+
try {
|
|
831
|
+
var clayHistoryMcpConfig = _workspaceQuery.createHistoryMcpServer(adapter, null);
|
|
832
|
+
if (clayHistoryMcpConfig) servers[clayHistoryMcpConfig.name || "clay-history"] = clayHistoryMcpConfig;
|
|
833
|
+
} catch (e) {
|
|
834
|
+
console.error("[project] Failed to create Clay history compatibility server:", e.message);
|
|
835
|
+
}
|
|
836
|
+
}
|
|
695
837
|
|
|
696
|
-
|
|
697
|
-
|
|
698
|
-
|
|
699
|
-
|
|
700
|
-
mode: "mcp",
|
|
701
|
-
sessionId: session.localId,
|
|
702
|
-
postedAt: Date.now(),
|
|
703
|
-
};
|
|
704
|
-
|
|
705
|
-
sm.sendAndRecord(session, {
|
|
706
|
-
type: "tool_executing",
|
|
707
|
-
id: toolId,
|
|
708
|
-
name: "AskUserQuestion",
|
|
709
|
-
input: input,
|
|
710
|
-
});
|
|
711
|
-
|
|
712
|
-
return Promise.resolve({
|
|
713
|
-
content: [{
|
|
714
|
-
type: "text",
|
|
715
|
-
text: "The question card has been posted to the user. End this turn now without further commentary; the user's answer will arrive as the next user message, prefixed with \"[Answer to your AskUserQuestion]\" so you can recognize it.",
|
|
716
|
-
}],
|
|
717
|
-
});
|
|
718
|
-
});
|
|
719
|
-
var askUserMcpConfig = adapter.createToolServer({ name: "clay-ask-user", version: "1.0.0", tools: askUserToolDefs });
|
|
720
|
-
if (askUserMcpConfig) servers[askUserMcpConfig.name || "clay-ask-user"] = askUserMcpConfig;
|
|
838
|
+
if (isMate) {
|
|
839
|
+
try {
|
|
840
|
+
var toolControlMcpConfig = createToolControlMcpServer();
|
|
841
|
+
if (toolControlMcpConfig) servers[toolControlMcpConfig.name || "clay-tools"] = toolControlMcpConfig;
|
|
721
842
|
} catch (e) {
|
|
722
|
-
console.error("[project] Failed to create
|
|
843
|
+
console.error("[project] Failed to create clay-tools MCP server:", e.message);
|
|
723
844
|
}
|
|
724
845
|
}
|
|
725
846
|
|
|
@@ -805,6 +926,51 @@ function createProjectContext(opts) {
|
|
|
805
926
|
var name = keys[i];
|
|
806
927
|
if (name === "clay-browser" && !extConnected) continue;
|
|
807
928
|
if (name === "clay-email" && !emailAvailable) continue;
|
|
929
|
+
if (name === "clay-workspace" && forSession) {
|
|
930
|
+
try {
|
|
931
|
+
var boundWorkspace = _workspaceQuery.createMcpServer(adapter, forSession);
|
|
932
|
+
if (boundWorkspace) { filtered[name] = boundWorkspace; hasAny = true; }
|
|
933
|
+
} catch (e) {
|
|
934
|
+
console.error("[project] Failed to bind clay-workspace MCP server:", e.message);
|
|
935
|
+
}
|
|
936
|
+
continue;
|
|
937
|
+
}
|
|
938
|
+
if (name === "clay-history" && forSession) {
|
|
939
|
+
try {
|
|
940
|
+
var boundHistory = _workspaceQuery.createHistoryMcpServer(adapter, forSession);
|
|
941
|
+
if (boundHistory) { filtered[name] = boundHistory; hasAny = true; }
|
|
942
|
+
} catch (e) {
|
|
943
|
+
console.error("[project] Failed to bind Clay history compatibility server:", e.message);
|
|
944
|
+
}
|
|
945
|
+
continue;
|
|
946
|
+
}
|
|
947
|
+
if (name === "clay-logs" && forSession) {
|
|
948
|
+
try {
|
|
949
|
+
var boundLogs = _projectLogs.createMcpServer(adapter, forSession);
|
|
950
|
+
if (boundLogs) { filtered[name] = boundLogs; hasAny = true; }
|
|
951
|
+
} catch (e) {
|
|
952
|
+
console.error("[project] Failed to bind clay-logs MCP server:", e.message);
|
|
953
|
+
}
|
|
954
|
+
continue;
|
|
955
|
+
}
|
|
956
|
+
if (name === "clay-knowledge" && forSession) {
|
|
957
|
+
try {
|
|
958
|
+
var boundKnowledge = _mateKnowledge.createMcpServer(adapter, forSession);
|
|
959
|
+
if (boundKnowledge) { filtered[name] = boundKnowledge; hasAny = true; }
|
|
960
|
+
} catch (e) {
|
|
961
|
+
console.error("[project] Failed to bind clay-knowledge MCP server:", e.message);
|
|
962
|
+
}
|
|
963
|
+
continue;
|
|
964
|
+
}
|
|
965
|
+
if (name === "clay-tools" && forSession) {
|
|
966
|
+
try {
|
|
967
|
+
var boundToolControl = createToolControlMcpServer();
|
|
968
|
+
if (boundToolControl) { filtered[name] = boundToolControl; hasAny = true; }
|
|
969
|
+
} catch (e) {
|
|
970
|
+
console.error("[project] Failed to bind clay-tools MCP server:", e.message);
|
|
971
|
+
}
|
|
972
|
+
continue;
|
|
973
|
+
}
|
|
808
974
|
if (name === "clay-sessions" && forSession) {
|
|
809
975
|
try {
|
|
810
976
|
var boundSpawn = _sessionSpawn.createMcpServer(adapter, forSession);
|
|
@@ -850,6 +1016,15 @@ function createProjectContext(opts) {
|
|
|
850
1016
|
}
|
|
851
1017
|
continue;
|
|
852
1018
|
}
|
|
1019
|
+
if (name === "clay-mate-creation" && forSession) {
|
|
1020
|
+
try {
|
|
1021
|
+
var boundMateCreation = _mateCreationProposal.createMcpServer(adapter, forSession);
|
|
1022
|
+
if (boundMateCreation) { filtered[name] = boundMateCreation; hasAny = true; }
|
|
1023
|
+
} catch (e) {
|
|
1024
|
+
console.error("[project] Failed to bind Mate creation MCP server:", e.message);
|
|
1025
|
+
}
|
|
1026
|
+
continue;
|
|
1027
|
+
}
|
|
853
1028
|
filtered[name] = mcpServers[name];
|
|
854
1029
|
hasAny = true;
|
|
855
1030
|
}
|
|
@@ -866,6 +1041,7 @@ function createProjectContext(opts) {
|
|
|
866
1041
|
adapter: adapter,
|
|
867
1042
|
adapters: adapters,
|
|
868
1043
|
getNotificationsModule: function () { return _notifications; },
|
|
1044
|
+
shouldSuppressResponseNotification: opts.shouldSuppressResponseNotification,
|
|
869
1045
|
mateDisplayName: opts.mateDisplayName || "",
|
|
870
1046
|
isMate: isMate,
|
|
871
1047
|
osUsers: osUsers,
|
|
@@ -879,6 +1055,7 @@ function createProjectContext(opts) {
|
|
|
879
1055
|
onTurnDone: function (session, preview) {
|
|
880
1056
|
if (isMate) digestDmTurn(session, preview);
|
|
881
1057
|
else _sessionPair.handleTurnDone(session);
|
|
1058
|
+
if (session && typeof session.onTurnDone === "function") session.onTurnDone(session, preview);
|
|
882
1059
|
},
|
|
883
1060
|
scheduleMessage: function (session, text, resetsAt) {
|
|
884
1061
|
scheduleMessage(session, text, resetsAt);
|
|
@@ -902,13 +1079,26 @@ function createProjectContext(opts) {
|
|
|
902
1079
|
_sessionNotes.getSystemPrompt(session),
|
|
903
1080
|
_sessionHandoff.getSystemPrompt(session),
|
|
904
1081
|
_sessionDocument.getSystemPrompt(session),
|
|
1082
|
+
_capsuleCatalog.getSystemPrompt(session),
|
|
1083
|
+
_projectLogs.getSystemPrompt(session),
|
|
1084
|
+
_mateKnowledge.getSystemPrompt(session),
|
|
905
1085
|
]);
|
|
906
1086
|
},
|
|
1087
|
+
getRuntimeEnv: getRuntimeEnvForSession,
|
|
1088
|
+
onUserInputRequest: function (session, request, respond) {
|
|
1089
|
+
return _askUser.createHandler(session)(request, respond);
|
|
1090
|
+
},
|
|
907
1091
|
getSessionToolDefs: function (session) {
|
|
908
1092
|
return _sessionPair.getToolDefs(session)
|
|
909
1093
|
.concat(_sessionNotes.getToolDefs(session))
|
|
910
1094
|
.concat(_sessionHandoff.getToolDefs(session))
|
|
911
|
-
.concat(_sessionDocument.getToolDefs(session))
|
|
1095
|
+
.concat(_sessionDocument.getToolDefs(session))
|
|
1096
|
+
.concat(_debateProposal.getToolDefs(session))
|
|
1097
|
+
.concat(_mateCreationProposal.getToolDefs(session))
|
|
1098
|
+
.concat(_workspaceQuery.getDynamicToolDefs(session))
|
|
1099
|
+
.concat(_workspaceQuery.getHistoryDynamicToolDefs(session))
|
|
1100
|
+
.concat(_projectLogs.getDynamicToolDefs(session))
|
|
1101
|
+
.concat(_mateKnowledge.getDynamicToolDefs(session));
|
|
912
1102
|
},
|
|
913
1103
|
});
|
|
914
1104
|
|
|
@@ -1042,6 +1232,17 @@ function createProjectContext(opts) {
|
|
|
1042
1232
|
}
|
|
1043
1233
|
|
|
1044
1234
|
function handleMessage(ws, msg) {
|
|
1235
|
+
// --- Keep-alive (delegated to project-connection.js) ---
|
|
1236
|
+
// Answered before any routing so a ping can never be forwarded elsewhere.
|
|
1237
|
+
// _connection is assigned later in this factory than the other modules, so
|
|
1238
|
+
// the reference is guarded rather than assumed.
|
|
1239
|
+
if (_connection && _connection.handleKeepaliveMessage(ws, msg)) return;
|
|
1240
|
+
|
|
1241
|
+
if (ws._clayHomeDebateSlug && ws._clayHomeDebateSlug !== slug && /^debate_(hand_raise|comment|stop|conclude_response|user_floor_response)$/.test(msg.type || "") && opts.getProject) {
|
|
1242
|
+
var homeDebateCtx = opts.getProject(ws._clayHomeDebateSlug);
|
|
1243
|
+
if (homeDebateCtx) homeDebateCtx.handleMessage(ws, msg);
|
|
1244
|
+
return;
|
|
1245
|
+
}
|
|
1045
1246
|
// --- Cross-project routing (e.g. permission_response from notification banner) ---
|
|
1046
1247
|
if (msg.targetSlug && msg.targetSlug !== slug && opts.getProject) {
|
|
1047
1248
|
var targetCtx = opts.getProject(msg.targetSlug);
|
|
@@ -1052,9 +1253,17 @@ function createProjectContext(opts) {
|
|
|
1052
1253
|
}
|
|
1053
1254
|
|
|
1054
1255
|
// --- DM messages (delegated to server-level handler) ---
|
|
1055
|
-
if (msg.type === "
|
|
1256
|
+
if (msg.type === "home_debate_question_response" || msg.type === "home_debate_control" || msg.type === "home_mate_creation_question_response") {
|
|
1257
|
+
if (typeof opts.onDmMessage === "function") opts.onDmMessage(ws, msg);
|
|
1258
|
+
return;
|
|
1259
|
+
}
|
|
1260
|
+
if (msg.type === "home_clay_ask" || msg.type === "home_clay_session_resolve") {
|
|
1261
|
+
if (typeof opts.onDmMessage === "function") opts.onDmMessage(ws, msg, slug);
|
|
1262
|
+
return;
|
|
1263
|
+
}
|
|
1264
|
+
if (msg.type === "project_assignment_response" || msg.type === "dm_open" || msg.type === "dm_send" || msg.type === "dm_list" || msg.type === "dm_typing" || msg.type === "dm_add_favorite" || msg.type === "dm_remove_favorite" || msg.type === "mate_create" || msg.type === "mate_list" || msg.type === "mate_delete" || msg.type === "mate_update" || msg.type === "mate_readd_builtin" || msg.type === "mate_list_available_builtins" || msg.type === "email_accounts_list" || msg.type === "email_account_add" || msg.type === "email_account_remove" || msg.type === "email_account_test" || msg.type === "home_debates_list" || msg.type === "home_mate_present" || msg.type === "home_mate_open" || msg.type === "home_mate_sessions_list" || msg.type === "home_mate_session_open" || msg.type === "home_mate_send" || msg.type === "home_mate_new_session" || msg.type === "home_mate_debate_plan" || msg.type === "home_debate_proposal_response" || msg.type === "home_mate_creation_plan" || msg.type === "home_mate_creation_proposal_response" || msg.type === "home_mate_close" || msg.type === "home_mate_memory_list" || msg.type === "home_mate_knowledge_list" || msg.type === "home_mate_models_get" || msg.type === "home_mate_model_set" || msg.type === "home_dock_get" || msg.type === "home_dock_set" || msg.type === "home_surface_get" || msg.type === "home_surface_set" || msg.type === "tools_list" || msg.type === "tool_get" || msg.type === "tool_install" || msg.type === "tool_remove" || msg.type === "tool_storage_op" || msg.type === "tool_llm_op" || msg.type === "tool_llm_config_get" || msg.type === "tool_control_response" || msg.type === "tool_source_get" || msg.type === "tool_mate_access_set") {
|
|
1056
1265
|
if (typeof opts.onDmMessage === "function") {
|
|
1057
|
-
opts.onDmMessage(ws, msg);
|
|
1266
|
+
opts.onDmMessage(ws, msg, slug);
|
|
1058
1267
|
}
|
|
1059
1268
|
return;
|
|
1060
1269
|
}
|
|
@@ -1126,6 +1335,9 @@ function createProjectContext(opts) {
|
|
|
1126
1335
|
// --- Knowledge file management (delegated to project-knowledge.js) ---
|
|
1127
1336
|
if (_knowledge.handleKnowledgeMessage(ws, msg)) return;
|
|
1128
1337
|
|
|
1338
|
+
// --- Project Logs (delegated to project-logs.js) ---
|
|
1339
|
+
if (_projectLogs.handleLogsMessage(ws, msg)) return;
|
|
1340
|
+
|
|
1129
1341
|
// --- Notifications (delegated to project-notifications.js) ---
|
|
1130
1342
|
if (_notifications.handleNotificationMessage(ws, msg)) return;
|
|
1131
1343
|
|
|
@@ -1147,6 +1359,9 @@ function createProjectContext(opts) {
|
|
|
1147
1359
|
// --- Shell command context ---
|
|
1148
1360
|
if (_shellCommand.handleShellCommand(ws, msg)) return;
|
|
1149
1361
|
|
|
1362
|
+
// --- Vendor login flow (delegated to project-vendor-login.js) ---
|
|
1363
|
+
if (_vendorLogin.handleVendorLoginMessage(ws, msg)) return;
|
|
1364
|
+
|
|
1150
1365
|
// --- Notes, terminals, context, user message (delegated to project-user-message.js) ---
|
|
1151
1366
|
if (_userMessage.handleUserMessage(ws, msg)) return;
|
|
1152
1367
|
}
|
|
@@ -1165,7 +1380,12 @@ function createProjectContext(opts) {
|
|
|
1165
1380
|
sendTo: sendTo,
|
|
1166
1381
|
matesModule: matesModule,
|
|
1167
1382
|
sessionSearch: sessionSearch,
|
|
1168
|
-
|
|
1383
|
+
getWorkspaceMemorySessions: function () { return _workspaceQuery.getMemorySessions(true); },
|
|
1384
|
+
getOwnedCurrentSessions: function () {
|
|
1385
|
+
return _workspaceQuery.getMemorySessions(false).filter(function (session) {
|
|
1386
|
+
return session._projectSlug === slug;
|
|
1387
|
+
});
|
|
1388
|
+
},
|
|
1169
1389
|
projectOwnerId: projectOwnerId,
|
|
1170
1390
|
handleMessage: handleMessage,
|
|
1171
1391
|
});
|
|
@@ -1246,6 +1466,8 @@ function createProjectContext(opts) {
|
|
|
1246
1466
|
getSessionForWs: getSessionForWs,
|
|
1247
1467
|
updateMemorySummary: updateMemorySummary,
|
|
1248
1468
|
initMemorySummary: initMemorySummary,
|
|
1469
|
+
registerHomeDebateClient: function (ws) { if (ws) homeDebateClients.add(ws); },
|
|
1470
|
+
unregisterHomeDebateClient: function (ws) { homeDebateClients.delete(ws); },
|
|
1249
1471
|
});
|
|
1250
1472
|
var handleDebateStart = _debate.handleDebateStart;
|
|
1251
1473
|
var handleDebateHandRaise = _debate.handleDebateHandRaise;
|
|
@@ -1294,6 +1516,11 @@ function createProjectContext(opts) {
|
|
|
1294
1516
|
browserState._extensionId = null;
|
|
1295
1517
|
if (_mcp) _mcp.handleExtensionDisconnect();
|
|
1296
1518
|
}
|
|
1519
|
+
homeDebateClients.delete(ws);
|
|
1520
|
+
if (ws._clayHomeDebateSlug && ws._clayHomeDebateSlug !== slug && opts.getProject) {
|
|
1521
|
+
var debateProject = opts.getProject(ws._clayHomeDebateSlug);
|
|
1522
|
+
if (debateProject && typeof debateProject.unregisterHomeDebateClient === "function") debateProject.unregisterHomeDebateClient(ws);
|
|
1523
|
+
}
|
|
1297
1524
|
_connection.handleDisconnection(ws);
|
|
1298
1525
|
}
|
|
1299
1526
|
|
|
@@ -1317,6 +1544,7 @@ function createProjectContext(opts) {
|
|
|
1317
1544
|
sendToSessionOthers: sendToSessionOthers,
|
|
1318
1545
|
opts: opts,
|
|
1319
1546
|
usersModule: usersModule,
|
|
1547
|
+
getProjectAccess: opts.getProjectAccess || function () { return { visibility: "public", ownerId: projectOwnerId || null }; },
|
|
1320
1548
|
userPresence: userPresence,
|
|
1321
1549
|
matesModule: matesModule,
|
|
1322
1550
|
pushModule: pushModule,
|
|
@@ -1365,6 +1593,28 @@ function createProjectContext(opts) {
|
|
|
1365
1593
|
serverTls: serverTls,
|
|
1366
1594
|
serverAuthToken: serverAuthToken,
|
|
1367
1595
|
});
|
|
1596
|
+
var _delegatedSession = attachDelegatedSession({
|
|
1597
|
+
sm: sm,
|
|
1598
|
+
getSdk: function () { return sdk; },
|
|
1599
|
+
getLinuxUserForSession: getLinuxUserForSession,
|
|
1600
|
+
resolveModel: function (principal) {
|
|
1601
|
+
var user = principal && principal.userId ? usersModule.findUserById(principal.userId) : null;
|
|
1602
|
+
return _models.resolveConfiguredModel({ _clayUser: user || null }, "standard");
|
|
1603
|
+
},
|
|
1604
|
+
});
|
|
1605
|
+
var _delegatedFollowUp = attachDelegatedFollowUp({
|
|
1606
|
+
sm: sm,
|
|
1607
|
+
getSdk: function () { return sdk; },
|
|
1608
|
+
getLinuxUserForSession: getLinuxUserForSession,
|
|
1609
|
+
onProcessingChanged: onProcessingChanged,
|
|
1610
|
+
isMultiUser: function () { return usersModule.isMultiUser(); },
|
|
1611
|
+
sessionRef: function (session) { return workspaceSessionRef(slug, session); },
|
|
1612
|
+
isPairedSession: function (session) { return !!_splitGroups.store.groupForMember(session.localId); },
|
|
1613
|
+
canResumeVendor: function (vendor) {
|
|
1614
|
+
var capabilities = sm.capabilitiesByVendor && sm.capabilitiesByVendor[vendor];
|
|
1615
|
+
return !!(capabilities && capabilities.sessionResume === true);
|
|
1616
|
+
},
|
|
1617
|
+
});
|
|
1368
1618
|
|
|
1369
1619
|
// --- User message handler (delegated to project-user-message.js) ---
|
|
1370
1620
|
var _userMessage = attachUserMessage({
|
|
@@ -1419,6 +1669,22 @@ function createProjectContext(opts) {
|
|
|
1419
1669
|
getOsUserInfoForWs: getOsUserInfoForWs,
|
|
1420
1670
|
});
|
|
1421
1671
|
|
|
1672
|
+
// --- Vendor login flow (delegated to project-vendor-login.js) ---
|
|
1673
|
+
var _vendorLogin = attachVendorLogin({
|
|
1674
|
+
slug: slug,
|
|
1675
|
+
osUsers: osUsers,
|
|
1676
|
+
sm: sm,
|
|
1677
|
+
tm: tm,
|
|
1678
|
+
adapters: adapters,
|
|
1679
|
+
send: send,
|
|
1680
|
+
sendTo: sendTo,
|
|
1681
|
+
usersModule: usersModule,
|
|
1682
|
+
getOsUserInfoForWs: getOsUserInfoForWs,
|
|
1683
|
+
getOsUserInfoForLinuxUser: getOsUserInfoForLinuxUser,
|
|
1684
|
+
getLinuxUserForSession: getLinuxUserForSession,
|
|
1685
|
+
refreshVendorAuthEverywhere: opts.refreshVendorAuthEverywhere,
|
|
1686
|
+
});
|
|
1687
|
+
|
|
1422
1688
|
// --- Filesystem handler (delegated to project-filesystem.js) ---
|
|
1423
1689
|
var _filesystem = attachFilesystem({
|
|
1424
1690
|
cwd: cwd,
|
|
@@ -1436,6 +1702,7 @@ function createProjectContext(opts) {
|
|
|
1436
1702
|
usersModule: usersModule,
|
|
1437
1703
|
fsAsUser: fsAsUser,
|
|
1438
1704
|
validateEnvString: validateEnvString,
|
|
1705
|
+
onEnvironmentChanged: function () { return sdk.refreshEnvironmentRuntime(); },
|
|
1439
1706
|
opts: opts,
|
|
1440
1707
|
IGNORED_DIRS: IGNORED_DIRS,
|
|
1441
1708
|
BINARY_EXTS: BINARY_EXTS,
|
|
@@ -1531,6 +1798,18 @@ function createProjectContext(opts) {
|
|
|
1531
1798
|
inputSchema: normalizeToolSchema(documentTools[dti].inputSchema),
|
|
1532
1799
|
});
|
|
1533
1800
|
}
|
|
1801
|
+
var debateTools = _debateProposal.getBridgeTools(boundSession, normalizeToolSchema);
|
|
1802
|
+
for (var dbti = 0; dbti < debateTools.length; dbti++) tools.push(debateTools[dbti]);
|
|
1803
|
+
var mateCreationTools = _mateCreationProposal.getBridgeTools(boundSession, normalizeToolSchema);
|
|
1804
|
+
for (var mcti = 0; mcti < mateCreationTools.length; mcti++) tools.push(mateCreationTools[mcti]);
|
|
1805
|
+
var workspaceTools = _workspaceQuery.getBridgeTools(boundSession, normalizeToolSchema);
|
|
1806
|
+
for (var wqti = 0; wqti < workspaceTools.length; wqti++) tools.push(workspaceTools[wqti]);
|
|
1807
|
+
var historyTools = _workspaceQuery.getHistoryBridgeTools(boundSession, normalizeToolSchema);
|
|
1808
|
+
for (var cht = 0; cht < historyTools.length; cht++) tools.push(historyTools[cht]);
|
|
1809
|
+
var logsTools = _projectLogs.getBridgeTools(boundSession, normalizeToolSchema);
|
|
1810
|
+
for (var plti = 0; plti < logsTools.length; plti++) tools.push(logsTools[plti]);
|
|
1811
|
+
var knowledgeTools = _mateKnowledge.getBridgeTools(boundSession, normalizeToolSchema);
|
|
1812
|
+
for (var mkti = 0; mkti < knowledgeTools.length; mkti++) tools.push(knowledgeTools[mkti]);
|
|
1534
1813
|
}
|
|
1535
1814
|
|
|
1536
1815
|
if (sessionOnly) return Promise.resolve(tools);
|
|
@@ -1543,6 +1822,10 @@ function createProjectContext(opts) {
|
|
|
1543
1822
|
var inAppNames = Object.keys(localMcp);
|
|
1544
1823
|
for (var i = 0; i < inAppNames.length; i++) {
|
|
1545
1824
|
if (inAppNames[i] === "clay-sessions" || inAppNames[i] === "clay-notes" || inAppNames[i] === "clay-handoff" || inAppNames[i] === "clay-documents") continue;
|
|
1825
|
+
// Debate tools were added above only when this request had an
|
|
1826
|
+
// exact session. Never duplicate them or advertise the static,
|
|
1827
|
+
// intentionally unbound proposal server.
|
|
1828
|
+
if (inAppNames[i] === "clay-debate" || inAppNames[i] === "clay-mate-creation" || inAppNames[i] === "clay-workspace" || inAppNames[i] === "clay-history" || inAppNames[i] === "clay-logs" || inAppNames[i] === "clay-knowledge") continue;
|
|
1546
1829
|
extractServerTools(inAppNames[i], localMcp[inAppNames[i]]);
|
|
1547
1830
|
}
|
|
1548
1831
|
}
|
|
@@ -1593,7 +1876,25 @@ function createProjectContext(opts) {
|
|
|
1593
1876
|
}
|
|
1594
1877
|
}
|
|
1595
1878
|
}
|
|
1596
|
-
if (
|
|
1879
|
+
if (boundSession && serverName === "clay-debate") {
|
|
1880
|
+
return _debateProposal.callBridgeTool(boundSession, toolName, args);
|
|
1881
|
+
}
|
|
1882
|
+
if (boundSession && serverName === "clay-mate-creation") {
|
|
1883
|
+
return _mateCreationProposal.callBridgeTool(boundSession, toolName, args);
|
|
1884
|
+
}
|
|
1885
|
+
if (boundSession && serverName === "clay-workspace") {
|
|
1886
|
+
return _workspaceQuery.callBridgeTool(boundSession, toolName, args);
|
|
1887
|
+
}
|
|
1888
|
+
if (boundSession && serverName === "clay-history") {
|
|
1889
|
+
return _workspaceQuery.callHistoryBridgeTool(boundSession, toolName, args);
|
|
1890
|
+
}
|
|
1891
|
+
if (boundSession && serverName === "clay-logs") {
|
|
1892
|
+
return _projectLogs.callBridgeTool(boundSession, toolName, args);
|
|
1893
|
+
}
|
|
1894
|
+
if (boundSession && serverName === "clay-knowledge") {
|
|
1895
|
+
return _mateKnowledge.callBridgeTool(boundSession, toolName, args);
|
|
1896
|
+
}
|
|
1897
|
+
if (serverName === "clay-sessions" || serverName === "clay-notes" || serverName === "clay-handoff" || serverName === "clay-documents" || serverName === "clay-debate" || serverName === "clay-mate-creation" || serverName === "clay-workspace" || serverName === "clay-history" || serverName === "clay-logs" || serverName === "clay-knowledge") {
|
|
1597
1898
|
return Promise.reject(new Error("Session-bound tool requires a valid Clay session: " + serverName + "/" + toolName));
|
|
1598
1899
|
}
|
|
1599
1900
|
if (sessionOnly) return Promise.reject(new Error("Session tool not found: " + serverName + "/" + toolName));
|
|
@@ -1667,6 +1968,7 @@ function createProjectContext(opts) {
|
|
|
1667
1968
|
_mcp: _mcp,
|
|
1668
1969
|
_notifications: _notifications,
|
|
1669
1970
|
_splitGroups: _splitGroups,
|
|
1971
|
+
_vendorLogin: _vendorLogin,
|
|
1670
1972
|
resolveSessionForView: _sessions.resolveSessionForView,
|
|
1671
1973
|
hydrateImageRefs: hydrateImageRefs,
|
|
1672
1974
|
broadcastClientCount: broadcastClientCount,
|
|
@@ -1807,7 +2109,7 @@ function createProjectContext(opts) {
|
|
|
1807
2109
|
};
|
|
1808
2110
|
if (isMate) {
|
|
1809
2111
|
status.isMate = true;
|
|
1810
|
-
status.mateId =
|
|
2112
|
+
status.mateId = mateId;
|
|
1811
2113
|
}
|
|
1812
2114
|
if (worktreeMeta) {
|
|
1813
2115
|
status.isWorktree = true;
|
|
@@ -1908,7 +2210,21 @@ function createProjectContext(opts) {
|
|
|
1908
2210
|
getMcpBridgeHandler: getMcpBridgeHandler,
|
|
1909
2211
|
getStatus: getStatus,
|
|
1910
2212
|
getSessionManager: function () { return sm; },
|
|
2213
|
+
createDelegatedSession: _delegatedSession.createDelegatedSession,
|
|
2214
|
+
inspectDelegatedFollowUp: _delegatedFollowUp.inspectDelegatedFollowUp,
|
|
2215
|
+
dispatchDelegatedFollowUp: _delegatedFollowUp.dispatchDelegatedFollowUp,
|
|
2216
|
+
unregisterHomeDebateClient: function (ws) { homeDebateClients.delete(ws); },
|
|
2217
|
+
handleHomeDebateProposalResponse: function (ws, msg, session) { return _debateProposal.handleHomeMessage(ws, msg, session); },
|
|
2218
|
+
handleHomeMateCreationProposalResponse: function (ws, msg, session) { return _mateCreationProposal.handleHomeMessage(ws, msg, session); },
|
|
2219
|
+
handleHomeAskUserResponse: function (msg, session) { return _sessions.respondToAskUser(session, msg); },
|
|
2220
|
+
handleHomeDebateControl: function (ws, msg, session) { return _debate.handleHomeControl(ws, msg, session); },
|
|
2221
|
+
getVendorModelCatalog: _models.getVendorCatalog,
|
|
2222
|
+
getVendorModelAvailability: _models.getVendorAvailability,
|
|
2223
|
+
getMemoryState: _memory.readMemoryState,
|
|
2224
|
+
listKnowledgeFiles: _knowledge.listKnowledgeFiles,
|
|
2225
|
+
refreshCapsuleCatalog: _capsuleCatalog.refreshSessions,
|
|
1911
2226
|
getNotificationsModule: function () { return _notifications; },
|
|
2227
|
+
refreshVendorAuth: _vendorLogin.refreshVendorAuth,
|
|
1912
2228
|
getSchedules: _loop.getSchedules,
|
|
1913
2229
|
importSchedule: _loop.importSchedule,
|
|
1914
2230
|
removeSchedule: _loop.removeSchedule,
|
|
@@ -1916,6 +2232,21 @@ function createProjectContext(opts) {
|
|
|
1916
2232
|
setIcon: setIcon,
|
|
1917
2233
|
setProjectOwner: function (ownerId) { projectOwnerId = ownerId; },
|
|
1918
2234
|
getProjectOwner: function () { return projectOwnerId; },
|
|
2235
|
+
getToolLlmConfig: function (ws, alias) {
|
|
2236
|
+
return _models.resolveConfiguredModel(ws, alias);
|
|
2237
|
+
},
|
|
2238
|
+
completeToolLlm: async function (ws, args) {
|
|
2239
|
+
var owner = projectOwnerId ? usersModule.findUserById(projectOwnerId) : null;
|
|
2240
|
+
var selection = await _models.resolveConfiguredModel(ws, args.model);
|
|
2241
|
+
return toolLlm.complete({
|
|
2242
|
+
adapters: adapters,
|
|
2243
|
+
cwd: cwd,
|
|
2244
|
+
linuxUser: owner && owner.linuxUser ? owner.linuxUser : null,
|
|
2245
|
+
args: args,
|
|
2246
|
+
selection: selection,
|
|
2247
|
+
timeoutMs: 60000,
|
|
2248
|
+
});
|
|
2249
|
+
},
|
|
1919
2250
|
refreshUserProfile: function (userId) {
|
|
1920
2251
|
var user = usersModule.findUserById(userId);
|
|
1921
2252
|
if (!user) return;
|
|
@@ -1934,4 +2265,4 @@ function createProjectContext(opts) {
|
|
|
1934
2265
|
};
|
|
1935
2266
|
}
|
|
1936
2267
|
|
|
1937
|
-
module.exports = { createProjectContext: createProjectContext, safePath: safePath, validateEnvString: validateEnvString };
|
|
2268
|
+
module.exports = { createProjectContext: createProjectContext, createMateToolControlMcp: createMateToolControlMcp, safePath: safePath, validateEnvString: validateEnvString };
|