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.
Files changed (222) hide show
  1. package/lib/ask-user-mcp-server.js +5 -119
  2. package/lib/background-task-timing.js +105 -0
  3. package/lib/builtin-mates.js +6 -6
  4. package/lib/claude-hook-installer.js +15 -0
  5. package/lib/clay-history-mcp-server.js +62 -297
  6. package/lib/daemon.js +23 -1
  7. package/lib/debate-model-selection.js +119 -0
  8. package/lib/home-debate-tool-policy.js +164 -0
  9. package/lib/home-response-notifications.js +26 -0
  10. package/lib/knowledge-import.js +436 -0
  11. package/lib/knowledge-record-store.js +188 -0
  12. package/lib/knowledge-search.js +224 -0
  13. package/lib/mate-creation-mcp-server.js +55 -0
  14. package/lib/mate-knowledge-mcp-server.js +151 -0
  15. package/lib/mate-knowledge-migration.js +283 -0
  16. package/lib/mate-knowledge-service.js +488 -0
  17. package/lib/mate-knowledge-sync.js +482 -0
  18. package/lib/mate-ready-creation.js +95 -0
  19. package/lib/mates.js +2 -0
  20. package/lib/notes.js +2 -1
  21. package/lib/project-ask-user.js +64 -0
  22. package/lib/project-capsule-catalog.js +101 -0
  23. package/lib/project-connection.js +17 -0
  24. package/lib/project-debate-proposal.js +133 -17
  25. package/lib/project-debate.js +214 -110
  26. package/lib/project-delegated-follow-up.js +84 -0
  27. package/lib/project-delegated-session.js +53 -0
  28. package/lib/project-filesystem.js +7 -9
  29. package/lib/project-knowledge.js +23 -0
  30. package/lib/project-logs-comments.js +137 -0
  31. package/lib/project-logs-mcp-server.js +290 -0
  32. package/lib/project-logs-query.js +167 -0
  33. package/lib/project-logs-root.js +67 -0
  34. package/lib/project-logs-schema.js +259 -0
  35. package/lib/project-logs-service.js +357 -0
  36. package/lib/project-logs-snapshot.js +202 -0
  37. package/lib/project-logs-store.js +498 -0
  38. package/lib/project-logs-versioning.js +128 -0
  39. package/lib/project-logs.js +347 -0
  40. package/lib/project-mate-creation-proposal.js +120 -0
  41. package/lib/project-mate-interaction.js +14 -0
  42. package/lib/project-mate-knowledge.js +110 -0
  43. package/lib/project-memory.js +36 -7
  44. package/lib/project-models.js +157 -32
  45. package/lib/project-session-notes.js +2 -2
  46. package/lib/project-session-pair.js +8 -8
  47. package/lib/project-sessions.js +66 -51
  48. package/lib/project-vendor-login.js +414 -0
  49. package/lib/project-worker-proposal.js +25 -25
  50. package/lib/project-workspace-query.js +144 -0
  51. package/lib/project.js +433 -102
  52. package/lib/public/app.js +109 -48
  53. package/lib/public/css/avatar-imprints.css +0 -1
  54. package/lib/public/css/base.css +4 -0
  55. package/lib/public/css/capsule-ui.css +389 -0
  56. package/lib/public/css/command-palette.css +306 -6
  57. package/lib/public/css/home-capsule-library.css +243 -0
  58. package/lib/public/css/home-capsule-source.css +192 -0
  59. package/lib/public/css/home-debate-live.css +146 -0
  60. package/lib/public/css/home-debate-planning.css +125 -0
  61. package/lib/public/css/home-debates-archive.css +281 -0
  62. package/lib/public/css/home-hub.css +896 -405
  63. package/lib/public/css/home-mate-creation.css +34 -0
  64. package/lib/public/css/home-mate-model-picker.css +131 -0
  65. package/lib/public/css/home-mate-settings.css +344 -0
  66. package/lib/public/css/home-session-actions.css +265 -0
  67. package/lib/public/css/home-sidebar.css +667 -0
  68. package/lib/public/css/icon-strip.css +1 -2
  69. package/lib/public/css/input.css +79 -25
  70. package/lib/public/css/mates.css +7 -34
  71. package/lib/public/css/pane.css +1 -1
  72. package/lib/public/css/playbook.css +0 -80
  73. package/lib/public/css/project-logs.css +234 -0
  74. package/lib/public/css/scheduler.css +1 -1
  75. package/lib/public/css/sticky-notes.css +53 -117
  76. package/lib/public/css/tui-attention.css +0 -44
  77. package/lib/public/css/workspace-assignment.css +45 -0
  78. package/lib/public/fonts/source-serif-4/LICENSE.md +93 -0
  79. package/lib/public/fonts/source-serif-4/SourceSerif4Caption-Semibold.ttf.woff2 +0 -0
  80. package/lib/public/index.html +96 -74
  81. package/lib/public/modules/app-connection.js +100 -5
  82. package/lib/public/modules/app-dm.js +43 -160
  83. package/lib/public/modules/app-home-hub.js +328 -585
  84. package/lib/public/modules/app-message-cards.js +242 -0
  85. package/lib/public/modules/app-message-router.js +84 -0
  86. package/lib/public/modules/app-messages.js +124 -38
  87. package/lib/public/modules/app-notifications.js +8 -119
  88. package/lib/public/modules/app-panels.js +43 -2
  89. package/lib/public/modules/app-projects.js +9 -1
  90. package/lib/public/modules/app-rendering.js +21 -602
  91. package/lib/public/modules/avatar-imprint.js +11 -8
  92. package/lib/public/modules/background-tasks-ui.js +139 -16
  93. package/lib/public/modules/chat-bubble-renderer.js +152 -0
  94. package/lib/public/modules/chat-render-runtime.js +198 -0
  95. package/lib/public/modules/command-palette.js +225 -436
  96. package/lib/public/modules/dm-render.js +82 -0
  97. package/lib/public/modules/home-capsule-creation-intent.js +31 -0
  98. package/lib/public/modules/home-capsule-library.js +146 -0
  99. package/lib/public/modules/home-capsule-source.js +383 -0
  100. package/lib/public/modules/home-chat-identity.js +35 -0
  101. package/lib/public/modules/home-chat-scroll.js +77 -0
  102. package/lib/public/modules/home-chat-stream-state.js +34 -0
  103. package/lib/public/modules/home-composer-focus.js +25 -0
  104. package/lib/public/modules/home-conversations-sheet.js +179 -0
  105. package/lib/public/modules/home-debate-activity.js +48 -0
  106. package/lib/public/modules/home-debate-controls.js +295 -0
  107. package/lib/public/modules/home-debate-launch.js +41 -0
  108. package/lib/public/modules/home-debate-live.js +284 -0
  109. package/lib/public/modules/home-debate-models.js +73 -0
  110. package/lib/public/modules/home-debate-planning.js +335 -0
  111. package/lib/public/modules/home-debates-archive.js +279 -0
  112. package/lib/public/modules/home-dock-resize.js +74 -0
  113. package/lib/public/modules/home-dock.js +446 -0
  114. package/lib/public/modules/home-mate-chat.js +496 -0
  115. package/lib/public/modules/home-mate-creation.js +109 -0
  116. package/lib/public/modules/home-mate-model-picker.js +281 -0
  117. package/lib/public/modules/home-mate-selection.js +38 -0
  118. package/lib/public/modules/home-mate-settings-menu.js +131 -0
  119. package/lib/public/modules/home-mate-settings.js +383 -0
  120. package/lib/public/modules/home-session-actions.js +373 -0
  121. package/lib/public/modules/home-session-model-confirmation.js +13 -0
  122. package/lib/public/modules/home-shell.js +9 -0
  123. package/lib/public/modules/home-sidebar-chat-list.js +63 -0
  124. package/lib/public/modules/home-sidebar.js +165 -0
  125. package/lib/public/modules/home-sub-surface.js +19 -0
  126. package/lib/public/modules/home-surface-boot.js +68 -0
  127. package/lib/public/modules/home-surface.js +141 -0
  128. package/lib/public/modules/home-tools.js +271 -0
  129. package/lib/public/modules/markdown.js +50 -2
  130. package/lib/public/modules/mate-management.js +86 -0
  131. package/lib/public/modules/mate-sidebar.js +0 -8
  132. package/lib/public/modules/mate-wizard.js +0 -7
  133. package/lib/public/modules/mention.js +17 -19
  134. package/lib/public/modules/pane-bridge.js +9 -0
  135. package/lib/public/modules/profile.js +4 -5
  136. package/lib/public/modules/project-logs-ambient.js +238 -0
  137. package/lib/public/modules/project-logs-render.js +359 -0
  138. package/lib/public/modules/project-logs.js +328 -0
  139. package/lib/public/modules/project-settings.js +34 -28
  140. package/lib/public/modules/project-switcher.js +11 -5
  141. package/lib/public/modules/project-workspace-assignment.js +23 -0
  142. package/lib/public/modules/scheduler.js +17 -3
  143. package/lib/public/modules/search-clay-chat.js +402 -0
  144. package/lib/public/modules/server-settings.js +14 -12
  145. package/lib/public/modules/session-actions.js +1 -1
  146. package/lib/public/modules/sidebar-mates.js +56 -552
  147. package/lib/public/modules/sidebar-mobile.js +12 -73
  148. package/lib/public/modules/sidebar-presence.js +37 -0
  149. package/lib/public/modules/sidebar-sessions.js +25 -1
  150. package/lib/public/modules/split-pair-ui.js +13 -13
  151. package/lib/public/modules/split-view.js +7 -0
  152. package/lib/public/modules/sticky-notes.js +106 -53
  153. package/lib/public/modules/tool-input-composition.js +48 -0
  154. package/lib/public/modules/tool-llm-status.js +167 -0
  155. package/lib/public/modules/tool-palette.js +76 -4
  156. package/lib/public/modules/tool-renderer-advanced.js +285 -0
  157. package/lib/public/modules/tool-renderer-chart.js +158 -0
  158. package/lib/public/modules/tool-renderer-semantics.js +35 -0
  159. package/lib/public/modules/tool-renderer.js +464 -0
  160. package/lib/public/modules/tool-runtime.js +309 -0
  161. package/lib/public/modules/tool-ui-evaluator.js +97 -0
  162. package/lib/public/modules/tool-ui-tree.js +21 -0
  163. package/lib/public/modules/tui-attention.js +10 -0
  164. package/lib/public/modules/user-settings.js +16 -23
  165. package/lib/public/modules/vendor-login.js +287 -0
  166. package/lib/public/modules/worker-proposal.js +2 -2
  167. package/lib/public/modules/workspace-assignment-card.js +149 -0
  168. package/lib/public/modules/workspace-assignment-routing.js +4 -0
  169. package/lib/public/style.css +14 -2
  170. package/lib/runtime-env.js +65 -0
  171. package/lib/sdk-bridge.js +120 -32
  172. package/lib/sdk-message-processor.js +34 -13
  173. package/lib/server-home-capsule-creation.js +36 -0
  174. package/lib/server-home-chat-events.js +287 -0
  175. package/lib/server-home-chat.js +518 -0
  176. package/lib/server-home-clay-entry.js +65 -0
  177. package/lib/server-home-clay-session-links.js +26 -0
  178. package/lib/server-home-debate-planning.js +214 -0
  179. package/lib/server-home-debates.js +137 -0
  180. package/lib/server-home-mate-creation.js +261 -0
  181. package/lib/server-home-models.js +241 -0
  182. package/lib/server-home-preferences.js +61 -0
  183. package/lib/server-mates.js +37 -0
  184. package/lib/server-tools.js +377 -0
  185. package/lib/server.js +166 -59
  186. package/lib/session-pair-mcp-server.js +6 -6
  187. package/lib/sessions.js +22 -4
  188. package/lib/tool-capsule-source.js +142 -0
  189. package/lib/tool-control-mcp-server.js +126 -0
  190. package/lib/tool-llm.js +48 -0
  191. package/lib/tool-storage.js +77 -0
  192. package/lib/tool-ui-spec-advanced.js +82 -0
  193. package/lib/tool-ui-spec.js +261 -0
  194. package/lib/tools-registry.js +286 -0
  195. package/lib/users-home-dock-preferences.js +77 -0
  196. package/lib/users-home-surface-preferences.js +99 -0
  197. package/lib/users-preferences.js +4 -7
  198. package/lib/users.js +12 -0
  199. package/lib/whats-new-content.js +3 -3
  200. package/lib/workspace-assignment-service.js +420 -0
  201. package/lib/workspace-query-mcp-server.js +154 -0
  202. package/lib/workspace-query-service.js +492 -0
  203. package/lib/ws-schema.js +107 -12
  204. package/lib/yoke/adapters/acp.js +2 -1
  205. package/lib/yoke/adapters/antigravity.js +2 -1
  206. package/lib/yoke/adapters/claude-worker.js +11 -4
  207. package/lib/yoke/adapters/claude.js +141 -46
  208. package/lib/yoke/adapters/codex.js +79 -11
  209. package/lib/yoke/adapters/kiro.js +2 -1
  210. package/lib/yoke/claude-user-input.js +38 -0
  211. package/lib/yoke/codex-app-server.js +20 -2
  212. package/lib/yoke/codex-background-tasks.js +8 -2
  213. package/lib/yoke/codex-user-input.js +64 -0
  214. package/lib/yoke/complete-once.js +164 -0
  215. package/lib/yoke/index.js +5 -1
  216. package/lib/yoke/interface.js +19 -0
  217. package/lib/yoke/mcp-bridge-server.js +2 -6
  218. package/lib/yoke/user-input.js +254 -0
  219. package/package.json +4 -3
  220. package/lib/public/css/home-chat.css +0 -380
  221. package/lib/public/modules/home-chat.js +0 -438
  222. package/lib/server-clay-home.js +0 -245
@@ -0,0 +1,377 @@
1
+ var toolsRegistry = require("./tools-registry");
2
+ var toolStorage = require("./tool-storage");
3
+ var crypto = require("crypto");
4
+ var toolLlm = require("./tool-llm");
5
+
6
+ function attachTools(deps) {
7
+ var users = deps.users;
8
+ var projects = deps.projects;
9
+ var serverLogic = Object.create(null);
10
+ var controlTimeoutMs = deps.controlTimeoutMs || 15000;
11
+ var llmControlTimeoutMs = deps.llmControlTimeoutMs || 90000;
12
+ var pendingControl = Object.create(null);
13
+
14
+ function contextFor(userId) {
15
+ var multiUser = users.isMultiUser();
16
+ var linuxUser = null;
17
+ if (multiUser) {
18
+ var user = users.findUserById(userId);
19
+ if (user && user.linuxUser) linuxUser = user.linuxUser;
20
+ }
21
+ return { userId: userId, multiUser: multiUser, linuxUser: linuxUser };
22
+ }
23
+
24
+ function send(ws, payload) {
25
+ if (ws.readyState !== undefined && ws.readyState !== 1) return;
26
+ ws.send(JSON.stringify(payload));
27
+ }
28
+
29
+ function broadcastToUser(userId, payload) {
30
+ var sent = new Set();
31
+ projects.forEach(function (projectContext) {
32
+ projectContext.forEachClient(function (otherWs) {
33
+ if (sent.has(otherWs)) return;
34
+ if (users.isMultiUser() && (!otherWs._clayUser || otherWs._clayUser.id !== userId)) return;
35
+ sent.add(otherWs);
36
+ send(otherWs, payload);
37
+ });
38
+ });
39
+ }
40
+
41
+ function sendError(ws, msg, error) {
42
+ send(ws, {
43
+ type: "tools_error",
44
+ requestType: msg.type,
45
+ toolId: msg.toolId || (msg.manifest && msg.manifest.id) || null,
46
+ seq: msg.seq,
47
+ requestId: msg.requestId,
48
+ message: error && error.message ? error.message : "Tool operation failed.",
49
+ });
50
+ }
51
+
52
+ function run(ws, msg, operation) {
53
+ Promise.resolve().then(operation).catch(function (error) { sendError(ws, msg, error); });
54
+ }
55
+
56
+ function fullToolList(ctx) {
57
+ var manifests = toolsRegistry.listTools(ctx);
58
+ var tools = [];
59
+ for (var i = 0; i < manifests.length; i++) {
60
+ if (manifests[i].error) {
61
+ tools.push(manifests[i]);
62
+ continue;
63
+ }
64
+ var tool = toolsRegistry.getTool(ctx, manifests[i].id);
65
+ if (tool) tools.push(tool);
66
+ }
67
+ return tools;
68
+ }
69
+
70
+ function installedManifests(userId) {
71
+ var ctx = contextFor(userId);
72
+ return toolsRegistry.listTools(ctx).filter(function (manifest) { return !manifest.error; });
73
+ }
74
+
75
+ function refreshMateCatalogs(userId) {
76
+ projects.forEach(function (projectContext) {
77
+ try {
78
+ if (!projectContext || typeof projectContext.getStatus !== "function" || typeof projectContext.refreshCapsuleCatalog !== "function") return;
79
+ var status = projectContext.getStatus();
80
+ if (!status || status.isMate !== true) return;
81
+ if (users.isMultiUser() && status.projectOwnerId !== userId) return;
82
+ projectContext.refreshCapsuleCatalog();
83
+ } catch (error) {
84
+ console.error("[tools] Could not refresh a Mate Capsule catalog:", error && error.message ? error.message : error);
85
+ }
86
+ });
87
+ }
88
+
89
+ function socketUserId(ws) {
90
+ if (!users.isMultiUser()) return "default";
91
+ return ws._clayUser ? ws._clayUser.id : null;
92
+ }
93
+
94
+ function latestHomeSocket(userId) {
95
+ var found = null;
96
+ var foundAt = -1;
97
+ var seen = new Set();
98
+ projects.forEach(function (projectContext) {
99
+ projectContext.forEachClient(function (ws) {
100
+ if (seen.has(ws) || socketUserId(ws) !== userId || !ws._homeChatTap) return;
101
+ seen.add(ws);
102
+ if (ws.readyState !== undefined && ws.readyState !== 1) return;
103
+ var openedAt = ws._homeChatTap.openedAt || 0;
104
+ if (!found || openedAt >= foundAt) {
105
+ found = ws;
106
+ foundAt = openedAt;
107
+ }
108
+ });
109
+ });
110
+ return found;
111
+ }
112
+
113
+ function requestBrowserControl(userId, mateId, toolId, kind, payload, timeoutMs) {
114
+ var ws = latestHomeSocket(userId);
115
+ if (!ws) return Promise.reject(new Error("The user's home screen is not open."));
116
+ var requestId = "toolctl_" + crypto.randomUUID();
117
+ return new Promise(function (resolve, reject) {
118
+ var timer = setTimeout(function () {
119
+ delete pendingControl[requestId];
120
+ reject(new Error("The tool control request timed out because the home screen did not respond."));
121
+ }, timeoutMs || controlTimeoutMs);
122
+ pendingControl[requestId] = {
123
+ ws: ws,
124
+ userId: userId,
125
+ resolve: resolve,
126
+ reject: reject,
127
+ timer: timer,
128
+ };
129
+ send(ws, {
130
+ type: "tool_control_request",
131
+ requestId: requestId,
132
+ toolId: toolId,
133
+ kind: kind,
134
+ payload: payload || {},
135
+ callerId: mateId,
136
+ });
137
+ });
138
+ }
139
+
140
+ function controlForMate(userId, mateId, toolId, kind, payload) {
141
+ payload = payload || {};
142
+ var ctx = contextFor(userId);
143
+ toolsRegistry.listTools(ctx);
144
+ var installed = toolsRegistry.getTool(ctx, toolId);
145
+ if (!installed) return Promise.reject(new Error("Tool is not installed."));
146
+ if (installed.manifest.runtime === "server") {
147
+ var adapter = serverLogic[toolId];
148
+ if (!adapter) return Promise.reject(new Error("No trusted server runtime is registered for this capsule."));
149
+ var context = { userId: userId, callerId: mateId };
150
+ if (kind === "snapshot") return Promise.resolve(adapter.snapshot(context));
151
+ if (kind === "act") return Promise.resolve(adapter.act(context, payload.actionId, payload.args || {}));
152
+ if (kind === "set" && adapter.set) return Promise.resolve(adapter.set(context, payload.controlId, payload.value));
153
+ return Promise.reject(new Error("The server-runtime capsule does not support '" + kind + "'."));
154
+ }
155
+ var permissions = installed.manifest.permissions || [];
156
+ var timeoutMs = kind === "act" && permissions.indexOf("llm") !== -1 ? llmControlTimeoutMs : controlTimeoutMs;
157
+ return requestBrowserControl(userId, mateId, toolId, kind, payload || {}, timeoutMs);
158
+ }
159
+
160
+ function handleControlResponse(ws, msg, userId) {
161
+ var pending = pendingControl[msg.requestId];
162
+ if (!pending || pending.ws !== ws || pending.userId !== userId) return;
163
+ clearTimeout(pending.timer);
164
+ delete pendingControl[msg.requestId];
165
+ if (msg.error) pending.reject(new Error(msg.error));
166
+ else pending.resolve(msg.data || {});
167
+ }
168
+
169
+ function storageOperation(ctx, msg) {
170
+ if (!toolsRegistry.getTool(ctx, msg.toolId)) throw new Error("Tool is not installed.");
171
+ var storage = toolStorage.createToolStorage(ctx, msg.toolId);
172
+ var args = msg.args || {};
173
+ if (msg.op === "list") return storage.list();
174
+ if (msg.op === "get") return storage.get(args.id);
175
+ if (msg.op === "put") return storage.put(args.doc);
176
+ if (msg.op === "delete") return storage.delete(args.id);
177
+ if (msg.op === "query") return storage.query(args.query || {});
178
+ throw new Error("Unknown storage operation '" + msg.op + "'.");
179
+ }
180
+
181
+ function projectForSocket(ws) {
182
+ var found = null;
183
+ projects.forEach(function (projectContext) {
184
+ if (!found && projectContext.clients && projectContext.clients.has(ws)) found = projectContext;
185
+ });
186
+ return found;
187
+ }
188
+
189
+ async function llmOperation(ws, ctx, userId, msg) {
190
+ var tool = toolsRegistry.getTool(ctx, msg.toolId);
191
+ if (!tool) throw new Error("Tool is not installed.");
192
+ var permissions = tool.manifest.permissions || [];
193
+ if (permissions.indexOf("llm") === -1) throw new Error("This capsule does not have the llm permission.");
194
+ var args = toolLlm.validateArgs(msg.args);
195
+ var projectContext = projectForSocket(ws);
196
+ if (!projectContext || typeof projectContext.completeToolLlm !== "function") throw new Error("No project LLM runtime is available.");
197
+ console.debug("[tool-llm] toolId=" + msg.toolId + " callerId=" + (msg.callerId || "user"));
198
+ return projectContext.completeToolLlm(ws, args);
199
+ }
200
+
201
+ async function llmConfiguration(ws, alias) {
202
+ var projectContext = projectForSocket(ws);
203
+ if (!projectContext || typeof projectContext.getToolLlmConfig !== "function") {
204
+ return { status: "error", vendor: "", vendorName: "", model: "", modelName: "", error: "No project model configuration is available." };
205
+ }
206
+ try {
207
+ return await projectContext.getToolLlmConfig(ws, alias);
208
+ } catch (error) {
209
+ return { status: "error", vendor: "", vendorName: "", model: "", modelName: "", error: error && error.message ? error.message : "Could not load the model configuration." };
210
+ }
211
+ }
212
+
213
+ function installForMate(userId, input) {
214
+ var installed = toolsRegistry.installTool(contextFor(userId), input);
215
+ refreshMateCatalogs(userId);
216
+ broadcastToUser(userId, { type: "tool_installed", tool: installed });
217
+ return installed;
218
+ }
219
+
220
+ function sourceForMate(userId, toolId) {
221
+ var ctx = contextFor(userId);
222
+ var installed = toolsRegistry.getTool(ctx, toolId);
223
+ if (!installed) throw new Error("Tool not found.");
224
+ if (installed.manifest.runtime !== "worker") throw new Error("Server-managed Capsule source is not available to Mates.");
225
+ if (!installed.metadata || installed.metadata.mateEditingAllowed !== true) {
226
+ throw new Error("The user has not allowed Mate source access for this Capsule.");
227
+ }
228
+ return toolsRegistry.getToolSource(ctx, toolId);
229
+ }
230
+
231
+ function updateForMate(userId, toolId, input) {
232
+ var ctx = contextFor(userId);
233
+ var installed = toolsRegistry.getTool(ctx, toolId);
234
+ if (!installed) throw new Error("Tool not found.");
235
+ if (!installed.metadata || installed.metadata.mateEditingAllowed !== true) {
236
+ throw new Error("The user has not allowed Mate editing for this Capsule.");
237
+ }
238
+ var updated = toolsRegistry.updateTool(ctx, toolId, input);
239
+ refreshMateCatalogs(userId);
240
+ broadcastToUser(userId, { type: "tool_installed", tool: updated });
241
+ var source = toolsRegistry.getToolSource(ctx, toolId);
242
+ return Object.assign({}, updated, { revision: source.revision });
243
+ }
244
+
245
+ function setMateAccess(userId, toolId, allowed, requestId) {
246
+ var ctx = contextFor(userId);
247
+ var tool = toolsRegistry.getTool(ctx, toolId);
248
+ if (!tool) throw new Error("Tool not found.");
249
+ if (tool.manifest.runtime !== "worker" && allowed === true) {
250
+ throw new Error("Server-managed Capsules cannot be edited by Mates.");
251
+ }
252
+ var metadata = toolsRegistry.setMateEditingAllowed(ctx, toolId, allowed);
253
+ broadcastToUser(userId, { type: "tool_mate_access_state", toolId: toolId, requestId: requestId || null, ok: true, metadata: metadata });
254
+ return metadata;
255
+ }
256
+
257
+ function removeForMate(userId, toolId) {
258
+ var removed = toolsRegistry.removeTool(contextFor(userId), toolId);
259
+ if (!removed) throw new Error("Tool not found.");
260
+ refreshMateCatalogs(userId);
261
+ broadcastToUser(userId, { type: "tool_removed", toolId: toolId });
262
+ return { removed: true, toolId: toolId };
263
+ }
264
+
265
+ function handleMessage(ws, msg) {
266
+ var messageTypes = ["tools_list", "tool_get", "tool_install", "tool_remove", "tool_storage_op", "tool_llm_op", "tool_llm_config_get", "tool_control_response", "tool_source_get", "tool_mate_access_set"];
267
+ if (!msg || messageTypes.indexOf(msg.type) === -1) return false;
268
+ var userId;
269
+ if (users.isMultiUser()) {
270
+ if (!ws._clayUser) return false;
271
+ userId = ws._clayUser.id;
272
+ } else {
273
+ userId = "default";
274
+ }
275
+ var ctx = contextFor(userId);
276
+
277
+ if (msg.type === "tool_control_response") {
278
+ handleControlResponse(ws, msg, userId);
279
+ return true;
280
+ }
281
+
282
+ if (msg.type === "tools_list") {
283
+ run(ws, msg, function () {
284
+ send(ws, { type: "tools_state", tools: fullToolList(ctx) });
285
+ });
286
+ return true;
287
+ }
288
+ if (msg.type === "tool_get") {
289
+ run(ws, msg, function () {
290
+ var tool = toolsRegistry.getTool(ctx, msg.toolId);
291
+ if (!tool) throw new Error("Tool not found.");
292
+ send(ws, { type: "tools_state", tools: [tool], requestedToolId: msg.toolId });
293
+ });
294
+ return true;
295
+ }
296
+ if (msg.type === "tool_source_get") {
297
+ Promise.resolve().then(function () {
298
+ return toolsRegistry.getToolSource(ctx, msg.toolId);
299
+ }).then(function (source) {
300
+ send(ws, Object.assign({ type: "tool_source_state", toolId: msg.toolId, requestId: msg.requestId, ok: true }, source));
301
+ }).catch(function (error) {
302
+ send(ws, { type: "tool_source_state", toolId: msg.toolId, requestId: msg.requestId, ok: false, error: error && error.message ? error.message : "Could not read Capsule source." });
303
+ });
304
+ return true;
305
+ }
306
+ if (msg.type === "tool_mate_access_set") {
307
+ Promise.resolve().then(function () {
308
+ if (typeof msg.allowed !== "boolean") throw new Error("Mate editing permission must be true or false.");
309
+ return setMateAccess(userId, msg.toolId, msg.allowed, msg.requestId);
310
+ }).catch(function (error) {
311
+ send(ws, { type: "tool_mate_access_state", toolId: msg.toolId, requestId: msg.requestId, ok: false, error: error && error.message ? error.message : "Could not update Mate editing permission." });
312
+ });
313
+ return true;
314
+ }
315
+ if (msg.type === "tool_install") {
316
+ run(ws, msg, function () {
317
+ installForMate(userId, {
318
+ manifest: msg.manifest,
319
+ logicSource: msg.logicSource,
320
+ uiTree: msg.uiTree,
321
+ });
322
+ });
323
+ return true;
324
+ }
325
+ if (msg.type === "tool_remove") {
326
+ run(ws, msg, function () {
327
+ removeForMate(userId, msg.toolId);
328
+ });
329
+ return true;
330
+ }
331
+ if (msg.type === "tool_storage_op") {
332
+ Promise.resolve().then(function () {
333
+ return storageOperation(ctx, msg);
334
+ }).then(function (data) {
335
+ send(ws, { type: "tool_storage_result", toolId: msg.toolId, op: msg.op, seq: msg.seq, data: data });
336
+ }).catch(function (error) {
337
+ send(ws, {
338
+ type: "tool_storage_result",
339
+ toolId: msg.toolId,
340
+ op: msg.op,
341
+ seq: msg.seq,
342
+ error: error && error.message ? error.message : "Tool storage operation failed.",
343
+ });
344
+ });
345
+ return true;
346
+ }
347
+ if (msg.type === "tool_llm_op") {
348
+ run(ws, msg, async function () {
349
+ var data = await llmOperation(ws, ctx, userId, msg);
350
+ send(ws, { type: "tool_llm_result", toolId: msg.toolId, requestId: msg.requestId, data: data });
351
+ });
352
+ return true;
353
+ }
354
+ if (msg.type === "tool_llm_config_get") {
355
+ run(ws, msg, async function () {
356
+ var alias = toolLlm.MODEL_ALIASES.indexOf(msg.alias) !== -1 ? msg.alias : "standard";
357
+ var state = await llmConfiguration(ws, alias);
358
+ send(ws, Object.assign({ type: "tool_llm_config_state", requestId: msg.requestId || null, alias: alias }, state));
359
+ });
360
+ return true;
361
+ }
362
+ return false;
363
+ }
364
+
365
+ return {
366
+ handleMessage: handleMessage,
367
+ installedManifests: installedManifests,
368
+ controlForMate: controlForMate,
369
+ installForMate: installForMate,
370
+ sourceForMate: sourceForMate,
371
+ updateForMate: updateForMate,
372
+ setMateAccess: setMateAccess,
373
+ removeForMate: removeForMate,
374
+ };
375
+ }
376
+
377
+ module.exports = { attachTools: attachTools };