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.
Files changed (189) hide show
  1. package/lib/ask-user-mcp-server.js +5 -119
  2. package/lib/builtin-mates.js +6 -6
  3. package/lib/claude-hook-installer.js +15 -0
  4. package/lib/clay-history-mcp-server.js +62 -297
  5. package/lib/daemon.js +1 -1
  6. package/lib/debate-model-selection.js +119 -0
  7. package/lib/home-debate-tool-policy.js +164 -0
  8. package/lib/home-response-notifications.js +26 -0
  9. package/lib/mate-creation-mcp-server.js +55 -0
  10. package/lib/mate-ready-creation.js +95 -0
  11. package/lib/mates.js +2 -0
  12. package/lib/notes.js +2 -1
  13. package/lib/project-ask-user.js +64 -0
  14. package/lib/project-capsule-catalog.js +101 -0
  15. package/lib/project-connection.js +4 -0
  16. package/lib/project-debate-proposal.js +133 -17
  17. package/lib/project-debate.js +214 -110
  18. package/lib/project-delegated-follow-up.js +84 -0
  19. package/lib/project-delegated-session.js +53 -0
  20. package/lib/project-filesystem.js +7 -9
  21. package/lib/project-knowledge.js +1 -0
  22. package/lib/project-mate-creation-proposal.js +120 -0
  23. package/lib/project-memory.js +14 -7
  24. package/lib/project-models.js +157 -32
  25. package/lib/project-session-notes.js +2 -2
  26. package/lib/project-session-pair.js +8 -8
  27. package/lib/project-sessions.js +66 -51
  28. package/lib/project-vendor-login.js +397 -0
  29. package/lib/project-worker-proposal.js +25 -25
  30. package/lib/project-workspace-query.js +144 -0
  31. package/lib/project.js +349 -102
  32. package/lib/public/app.js +85 -42
  33. package/lib/public/css/avatar-imprints.css +0 -1
  34. package/lib/public/css/base.css +4 -0
  35. package/lib/public/css/capsule-ui.css +389 -0
  36. package/lib/public/css/command-palette.css +306 -6
  37. package/lib/public/css/home-capsule-library.css +243 -0
  38. package/lib/public/css/home-capsule-source.css +192 -0
  39. package/lib/public/css/home-debate-live.css +146 -0
  40. package/lib/public/css/home-debate-planning.css +125 -0
  41. package/lib/public/css/home-debates-archive.css +281 -0
  42. package/lib/public/css/home-hub.css +896 -405
  43. package/lib/public/css/home-mate-creation.css +34 -0
  44. package/lib/public/css/home-mate-model-picker.css +131 -0
  45. package/lib/public/css/home-mate-settings.css +344 -0
  46. package/lib/public/css/home-session-actions.css +265 -0
  47. package/lib/public/css/home-sidebar.css +667 -0
  48. package/lib/public/css/icon-strip.css +1 -2
  49. package/lib/public/css/mates.css +7 -34
  50. package/lib/public/css/pane.css +1 -1
  51. package/lib/public/css/playbook.css +0 -80
  52. package/lib/public/css/sticky-notes.css +53 -117
  53. package/lib/public/css/tui-attention.css +0 -44
  54. package/lib/public/css/workspace-assignment.css +45 -0
  55. package/lib/public/fonts/source-serif-4/LICENSE.md +93 -0
  56. package/lib/public/fonts/source-serif-4/SourceSerif4Caption-Semibold.ttf.woff2 +0 -0
  57. package/lib/public/index.html +93 -74
  58. package/lib/public/modules/app-connection.js +10 -1
  59. package/lib/public/modules/app-dm.js +43 -160
  60. package/lib/public/modules/app-home-hub.js +328 -585
  61. package/lib/public/modules/app-message-cards.js +242 -0
  62. package/lib/public/modules/app-message-router.js +84 -0
  63. package/lib/public/modules/app-messages.js +102 -37
  64. package/lib/public/modules/app-notifications.js +8 -119
  65. package/lib/public/modules/app-projects.js +9 -1
  66. package/lib/public/modules/app-rendering.js +21 -602
  67. package/lib/public/modules/avatar-imprint.js +11 -8
  68. package/lib/public/modules/chat-bubble-renderer.js +152 -0
  69. package/lib/public/modules/chat-render-runtime.js +198 -0
  70. package/lib/public/modules/command-palette.js +225 -436
  71. package/lib/public/modules/dm-render.js +82 -0
  72. package/lib/public/modules/home-capsule-creation-intent.js +31 -0
  73. package/lib/public/modules/home-capsule-library.js +146 -0
  74. package/lib/public/modules/home-capsule-source.js +383 -0
  75. package/lib/public/modules/home-chat-identity.js +35 -0
  76. package/lib/public/modules/home-chat-scroll.js +77 -0
  77. package/lib/public/modules/home-chat-stream-state.js +34 -0
  78. package/lib/public/modules/home-composer-focus.js +25 -0
  79. package/lib/public/modules/home-conversations-sheet.js +179 -0
  80. package/lib/public/modules/home-debate-activity.js +48 -0
  81. package/lib/public/modules/home-debate-controls.js +295 -0
  82. package/lib/public/modules/home-debate-launch.js +41 -0
  83. package/lib/public/modules/home-debate-live.js +284 -0
  84. package/lib/public/modules/home-debate-models.js +73 -0
  85. package/lib/public/modules/home-debate-planning.js +335 -0
  86. package/lib/public/modules/home-debates-archive.js +279 -0
  87. package/lib/public/modules/home-dock-resize.js +74 -0
  88. package/lib/public/modules/home-dock.js +446 -0
  89. package/lib/public/modules/home-mate-chat.js +496 -0
  90. package/lib/public/modules/home-mate-creation.js +109 -0
  91. package/lib/public/modules/home-mate-model-picker.js +281 -0
  92. package/lib/public/modules/home-mate-selection.js +38 -0
  93. package/lib/public/modules/home-mate-settings-menu.js +131 -0
  94. package/lib/public/modules/home-mate-settings.js +383 -0
  95. package/lib/public/modules/home-session-actions.js +373 -0
  96. package/lib/public/modules/home-session-model-confirmation.js +13 -0
  97. package/lib/public/modules/home-shell.js +9 -0
  98. package/lib/public/modules/home-sidebar-chat-list.js +63 -0
  99. package/lib/public/modules/home-sidebar.js +158 -0
  100. package/lib/public/modules/home-sub-surface.js +19 -0
  101. package/lib/public/modules/home-surface-boot.js +68 -0
  102. package/lib/public/modules/home-surface.js +141 -0
  103. package/lib/public/modules/home-tools.js +271 -0
  104. package/lib/public/modules/markdown.js +50 -2
  105. package/lib/public/modules/mate-management.js +86 -0
  106. package/lib/public/modules/mate-wizard.js +0 -7
  107. package/lib/public/modules/mention.js +17 -19
  108. package/lib/public/modules/pane-bridge.js +9 -0
  109. package/lib/public/modules/profile.js +4 -5
  110. package/lib/public/modules/project-settings.js +34 -28
  111. package/lib/public/modules/project-switcher.js +11 -5
  112. package/lib/public/modules/project-workspace-assignment.js +23 -0
  113. package/lib/public/modules/search-clay-chat.js +402 -0
  114. package/lib/public/modules/server-settings.js +14 -12
  115. package/lib/public/modules/session-actions.js +1 -1
  116. package/lib/public/modules/sidebar-mates.js +56 -552
  117. package/lib/public/modules/sidebar-mobile.js +7 -64
  118. package/lib/public/modules/sidebar-presence.js +37 -0
  119. package/lib/public/modules/split-pair-ui.js +13 -13
  120. package/lib/public/modules/split-view.js +7 -0
  121. package/lib/public/modules/sticky-notes.js +7 -6
  122. package/lib/public/modules/tool-input-composition.js +48 -0
  123. package/lib/public/modules/tool-llm-status.js +167 -0
  124. package/lib/public/modules/tool-renderer-advanced.js +285 -0
  125. package/lib/public/modules/tool-renderer-chart.js +158 -0
  126. package/lib/public/modules/tool-renderer-semantics.js +35 -0
  127. package/lib/public/modules/tool-renderer.js +464 -0
  128. package/lib/public/modules/tool-runtime.js +309 -0
  129. package/lib/public/modules/tool-ui-evaluator.js +97 -0
  130. package/lib/public/modules/tool-ui-tree.js +21 -0
  131. package/lib/public/modules/tui-attention.js +10 -0
  132. package/lib/public/modules/user-settings.js +16 -23
  133. package/lib/public/modules/vendor-login.js +287 -0
  134. package/lib/public/modules/worker-proposal.js +2 -2
  135. package/lib/public/modules/workspace-assignment-card.js +149 -0
  136. package/lib/public/modules/workspace-assignment-routing.js +4 -0
  137. package/lib/public/style.css +13 -2
  138. package/lib/runtime-env.js +65 -0
  139. package/lib/sdk-bridge.js +120 -32
  140. package/lib/sdk-message-processor.js +10 -6
  141. package/lib/server-home-capsule-creation.js +36 -0
  142. package/lib/server-home-chat-events.js +287 -0
  143. package/lib/server-home-chat.js +518 -0
  144. package/lib/server-home-clay-entry.js +65 -0
  145. package/lib/server-home-clay-session-links.js +26 -0
  146. package/lib/server-home-debate-planning.js +214 -0
  147. package/lib/server-home-debates.js +137 -0
  148. package/lib/server-home-mate-creation.js +261 -0
  149. package/lib/server-home-models.js +241 -0
  150. package/lib/server-home-preferences.js +61 -0
  151. package/lib/server-mates.js +37 -0
  152. package/lib/server-tools.js +377 -0
  153. package/lib/server.js +111 -59
  154. package/lib/session-pair-mcp-server.js +6 -6
  155. package/lib/sessions.js +18 -3
  156. package/lib/tool-capsule-source.js +142 -0
  157. package/lib/tool-control-mcp-server.js +126 -0
  158. package/lib/tool-llm.js +48 -0
  159. package/lib/tool-storage.js +77 -0
  160. package/lib/tool-ui-spec-advanced.js +82 -0
  161. package/lib/tool-ui-spec.js +261 -0
  162. package/lib/tools-registry.js +286 -0
  163. package/lib/users-home-dock-preferences.js +77 -0
  164. package/lib/users-home-surface-preferences.js +99 -0
  165. package/lib/users-preferences.js +4 -7
  166. package/lib/users.js +12 -0
  167. package/lib/whats-new-content.js +3 -3
  168. package/lib/workspace-assignment-service.js +420 -0
  169. package/lib/workspace-query-mcp-server.js +154 -0
  170. package/lib/workspace-query-service.js +492 -0
  171. package/lib/ws-schema.js +93 -12
  172. package/lib/yoke/adapters/acp.js +2 -1
  173. package/lib/yoke/adapters/antigravity.js +2 -1
  174. package/lib/yoke/adapters/claude-worker.js +11 -4
  175. package/lib/yoke/adapters/claude.js +73 -43
  176. package/lib/yoke/adapters/codex.js +40 -10
  177. package/lib/yoke/adapters/kiro.js +2 -1
  178. package/lib/yoke/claude-user-input.js +38 -0
  179. package/lib/yoke/codex-app-server.js +20 -2
  180. package/lib/yoke/codex-user-input.js +64 -0
  181. package/lib/yoke/complete-once.js +164 -0
  182. package/lib/yoke/index.js +5 -1
  183. package/lib/yoke/interface.js +19 -0
  184. package/lib/yoke/mcp-bridge-server.js +2 -6
  185. package/lib/yoke/user-input.js +254 -0
  186. package/package.json +3 -2
  187. package/lib/public/css/home-chat.css +0 -380
  188. package/lib/public/modules/home-chat.js +0 -438
  189. package/lib/server-clay-home.js +0 -245
@@ -78,6 +78,7 @@ function attachConnection(ctx) {
78
78
  var _mcp = ctx._mcp;
79
79
  var _notifications = ctx._notifications;
80
80
  var _splitGroups = ctx._splitGroups;
81
+ var _vendorLogin = ctx._vendorLogin;
81
82
  var hydrateImageRefs = ctx.hydrateImageRefs;
82
83
  var resolveSessionForView = ctx.resolveSessionForView;
83
84
  var broadcastClientCount = ctx.broadcastClientCount;
@@ -191,6 +192,9 @@ function attachConnection(ctx) {
191
192
  sendTo(ws, { type: "last_vendor", vendor: sm.lastVendor || "" });
192
193
  sendTo(ws, Object.assign({ type: "codex_config" }, getCodexConfig(sm)));
193
194
  sendTo(ws, { type: "term_list", terminals: tm.list() });
195
+ // Any login flow already running in this project, so a reconnecting client
196
+ // re-attaches to the existing login terminal instead of starting another.
197
+ if (_vendorLogin) _vendorLogin.sendStateTo(ws);
194
198
  // Context sources sent after session is resolved (per-session storage)
195
199
  // Send email accounts list for context sources picker
196
200
  var emailUserId = (wsUser && wsUser.id) || "default";
@@ -1,28 +1,84 @@
1
1
  var path = require("path");
2
2
  var debateMcp = require("./debate-mcp-server");
3
+ var debateModels = require("./debate-model-selection");
3
4
 
4
5
  function attachDebateProposal(ctx) {
5
6
  var pendingProposals = {};
6
7
 
7
- function createMcpServer(adapter, boundSession) {
8
- var toolDefs = debateMcp.getToolDefs(function onPropose(briefData) {
8
+ function hasHomeDebateTopicAnswer(session) {
9
+ if (session && typeof session.homeDebateInitialTopic === "string" && session.homeDebateInitialTopic.trim()) return true;
10
+ var history = session && Array.isArray(session.history) ? session.history : [];
11
+ var firstQuestionId = null;
12
+ for (var i = 0; i < history.length; i++) {
13
+ var event = history[i];
14
+ if (!firstQuestionId && event && event.type === "tool_executing" && event.name === "AskUserQuestion") firstQuestionId = event.id || null;
15
+ if (firstQuestionId && event && event.type === "ask_user_answered" && event.toolId === firstQuestionId) return true;
16
+ }
17
+ return false;
18
+ }
19
+
20
+ function publicProposal(briefData) {
21
+ return {
22
+ proposalId: briefData.proposalId,
23
+ topic: briefData.topic || "Untitled debate",
24
+ format: briefData.format || "free_discussion",
25
+ context: briefData.context || "",
26
+ specialRequests: briefData.specialRequests || null,
27
+ moderatorId: briefData.moderatorId || null,
28
+ modelSelections: Array.isArray(briefData.modelSelections) ? briefData.modelSelections : [],
29
+ panelists: Array.isArray(briefData.panelists) ? briefData.panelists.map(function (panelist) {
30
+ return { mateId: panelist.mateId, role: panelist.role || "", brief: panelist.brief || "" };
31
+ }) : [],
32
+ };
33
+ }
34
+
35
+ function record(session, event) {
36
+ if (typeof ctx.recordSessionEvent === "function") ctx.recordSessionEvent(session, event);
37
+ }
38
+
39
+ function getToolDefs(boundSession) {
40
+ return debateMcp.getToolDefs(function onPropose(briefData) {
9
41
  if (!boundSession) {
10
42
  return Promise.resolve({
11
43
  action: "error",
12
44
  error: "Debate proposals require an active Clay session.",
13
45
  });
14
46
  }
15
-
47
+ var projectOwnerId = typeof ctx.getProjectOwnerId === "function" ? ctx.getProjectOwnerId() : null;
48
+ if (boundSession.homeDebatePlanning === true
49
+ && (ctx.isHostAgent !== true || ctx.isMate !== true || boundSession.debateSetupMode !== true
50
+ || !boundSession.ownerId || (projectOwnerId && boundSession.ownerId !== projectOwnerId))) {
51
+ return Promise.resolve({
52
+ action: "error",
53
+ error: "This Home debate proposal is not bound to an owned Clay planning session.",
54
+ });
55
+ }
56
+ if (boundSession.homeDebatePlanning === true && !hasHomeDebateTopicAnswer(boundSession)) {
57
+ return Promise.resolve({ action: "error", error: "Ask the user for a debate topic before proposing a debate." });
58
+ }
16
59
  return new Promise(function (resolve) {
17
60
  var proposalId = "dp_" + Date.now() + "_" + Math.random().toString(36).slice(2, 8);
18
61
  briefData.proposalId = proposalId;
19
- pendingProposals[proposalId] = {
20
- resolve: resolve,
21
- briefData: briefData,
22
- session: boundSession,
23
- };
62
+ var moderatorId = ctx.isMate ? path.basename(ctx.cwd) : briefData.moderatorId;
63
+ var userId = boundSession.ownerId || (typeof ctx.getProjectOwnerId === "function" ? ctx.getProjectOwnerId() : null);
64
+ var mateCtx = ctx.buildMateCtx(userId);
65
+ function register(selections) {
66
+ briefData.modelSelections = selections;
67
+ pendingProposals[proposalId] = {
68
+ resolve: resolve,
69
+ briefData: briefData,
70
+ session: boundSession,
71
+ };
72
+ record(boundSession, { type: "debate_proposal", proposal: publicProposal(briefData) });
73
+ }
74
+ if (typeof ctx.getVendorModelCatalog !== "function" && typeof ctx.getVendorModelCatalogForSession !== "function") register([]);
75
+ else debateModels.loadSelections(ctx, null, mateCtx, moderatorId, briefData.panelists || [], boundSession).then(register).catch(function () { register([]); });
24
76
  });
25
77
  });
78
+ }
79
+
80
+ function createMcpServer(adapter, boundSession) {
81
+ var toolDefs = getToolDefs(boundSession);
26
82
 
27
83
  return adapter.createToolServer({
28
84
  name: "clay-debate",
@@ -31,6 +87,30 @@ function attachDebateProposal(ctx) {
31
87
  });
32
88
  }
33
89
 
90
+ function getBridgeTools(boundSession, normalizeSchema) {
91
+ if (!boundSession) return [];
92
+ var toolDefs = getToolDefs(boundSession);
93
+ return toolDefs.map(function (tool) {
94
+ return {
95
+ server: "clay-debate",
96
+ name: tool.name,
97
+ description: tool.description || tool.name,
98
+ inputSchema: normalizeSchema(tool.inputSchema),
99
+ };
100
+ });
101
+ }
102
+
103
+ function callBridgeTool(boundSession, toolName, args) {
104
+ if (!boundSession) return Promise.reject(new Error("Debate proposals require a valid Clay session."));
105
+ var toolDefs = getToolDefs(boundSession);
106
+ for (var i = 0; i < toolDefs.length; i++) {
107
+ if (toolDefs[i].name === toolName && typeof toolDefs[i].handler === "function") {
108
+ return Promise.resolve(toolDefs[i].handler(args || {}));
109
+ }
110
+ }
111
+ return Promise.reject(new Error("Session tool not found: clay-debate/" + toolName));
112
+ }
113
+
34
114
  function findPendingProposal(ws, msg) {
35
115
  var keys = Object.keys(pendingProposals);
36
116
  if (keys.length === 0) return null;
@@ -47,8 +127,7 @@ function attachDebateProposal(ctx) {
47
127
  if (!key) key = keys[keys.length - 1];
48
128
  var pending = pendingProposals[key];
49
129
  if (!pending) return null;
50
- delete pendingProposals[key];
51
- return pending;
130
+ return { key: key, pending: pending };
52
131
  }
53
132
 
54
133
  function rejectProposal(ws, pending, error) {
@@ -57,6 +136,7 @@ function attachDebateProposal(ctx) {
57
136
  } catch (sendErr) {
58
137
  console.error("[debate] Failed to send proposal error:", sendErr && sendErr.message ? sendErr.message : sendErr);
59
138
  }
139
+ record(pending.session, { type: "debate_proposal_resolved", proposalId: pending.briefData.proposalId, action: "error", error: error });
60
140
  pending.resolve({ action: "error", error: error });
61
141
  }
62
142
 
@@ -98,40 +178,76 @@ function attachDebateProposal(ctx) {
98
178
  return { moderatorId: moderatorId };
99
179
  }
100
180
 
101
- function handleMessage(ws, msg) {
102
- if (msg.type !== "debate_proposal_response") return false;
103
-
104
- var pending = findPendingProposal(ws, msg);
105
- if (!pending) return true;
181
+ async function startApprovedProposal(ws, msg, found) {
182
+ var pending = found.pending;
183
+ if (pending.responding) return;
184
+ pending.responding = true;
106
185
  if (msg.action !== "start") {
186
+ delete pendingProposals[found.key];
187
+ record(pending.session, { type: "debate_proposal_resolved", proposalId: pending.briefData.proposalId, action: "cancel" });
107
188
  pending.resolve({ action: "cancel" });
108
- return true;
189
+ return;
109
190
  }
110
191
 
111
192
  var validated = validateProposal(ws, pending);
112
193
  if (validated.error) {
194
+ delete pendingProposals[found.key];
113
195
  rejectProposal(ws, pending, validated.error);
114
- return true;
196
+ return;
115
197
  }
116
198
 
199
+ var userId = ws && ws._clayUser ? ws._clayUser.id : (pending.session.ownerId || ctx.getProjectOwnerId() || null);
200
+ var mateCtx = ctx.buildMateCtx(userId);
201
+ var modelResult = await debateModels.validateSelections(ctx, ws, mateCtx, validated.moderatorId, pending.briefData.panelists, msg.modelOverrides, pending.session);
202
+ if (modelResult.error) {
203
+ delete pendingProposals[found.key];
204
+ rejectProposal(ws, pending, modelResult.error);
205
+ return;
206
+ }
207
+ pending.briefData.participantModels = modelResult.selections;
208
+ delete pendingProposals[found.key];
209
+
117
210
  try {
118
211
  var result = ctx.startDebate(pending.session, pending.briefData, validated.moderatorId, ws);
119
212
  if (result && result.error) {
120
213
  rejectProposal(ws, pending, result.error);
121
214
  return true;
122
215
  }
216
+ record(pending.session, { type: "debate_proposal_resolved", proposalId: pending.briefData.proposalId, action: "start" });
123
217
  pending.resolve({ action: "start" });
124
218
  } catch (err) {
125
219
  var detail = err && err.message ? err.message : String(err);
126
220
  console.error("[debate] Failed to start approved proposal:", detail);
127
221
  rejectProposal(ws, pending, "The debate could not be started. Check the server logs for details.");
128
222
  }
223
+ }
224
+
225
+ function handleMessage(ws, msg) {
226
+ if (msg.type !== "debate_proposal_response") return false;
227
+
228
+ var found = findPendingProposal(ws, msg);
229
+ if (!found) return true;
230
+ startApprovedProposal(ws, msg, found).catch(function (error) {
231
+ delete pendingProposals[found.key];
232
+ rejectProposal(ws, found.pending, error && error.message ? error.message : "The selected debate models could not be verified.");
233
+ });
129
234
  return true;
130
235
  }
131
236
 
237
+ function handleHomeMessage(ws, msg, expectedSession) {
238
+ var found = findPendingProposal(ws, msg);
239
+ if (!found || found.pending.session !== expectedSession) return false;
240
+ if (expectedSession.ownerId && (!ws || !ws._clayUser || ws._clayUser.id !== expectedSession.ownerId)) return false;
241
+ return handleMessage(ws, msg);
242
+ }
243
+
132
244
  return {
133
245
  createMcpServer: createMcpServer,
246
+ getToolDefs: getToolDefs,
247
+ getBridgeTools: getBridgeTools,
248
+ callBridgeTool: callBridgeTool,
134
249
  handleMessage: handleMessage,
250
+ handleHomeMessage: handleHomeMessage,
135
251
  };
136
252
  }
137
253