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
@@ -167,16 +167,16 @@ function attachWorkerProposal(ctx) {
167
167
  }
168
168
 
169
169
  async function propose(args, session) {
170
- if (!isEligible(session)) return toolResult({ error: "Worker suggestions are only available in an unpaired Fable session." });
171
- if (hasPendingProposal(session)) return toolResult({ error: "A Worker suggestion is already awaiting a decision." });
170
+ if (!isEligible(session)) return toolResult({ error: "Split Worker suggestions are only available in an unpaired Fable session." });
171
+ if (hasPendingProposal(session)) return toolResult({ error: "A Split Worker suggestion is already awaiting a decision." });
172
172
  var summary = typeof args.summary === "string" ? args.summary.trim() : "";
173
173
  var plan = typeof args.plan === "string" ? args.plan.trim() : "";
174
174
  var task = typeof args.message === "string" ? args.message.trim() : "";
175
175
  if (!summary || !plan || !task) return toolResult({ error: "summary, plan, and message are required." });
176
- if (task.length > MAX_TASK_CHARS) return toolResult({ error: "The Worker task is too long." });
176
+ if (task.length > MAX_TASK_CHARS) return toolResult({ error: "The Split Worker task is too long." });
177
177
  await ensureModelCatalogs();
178
178
  var options = proposalOptions();
179
- if (options.installedVendors.length === 0) return toolResult({ error: "No coding agent is installed for a Worker session." });
179
+ if (options.installedVendors.length === 0) return toolResult({ error: "No coding agent is installed for a Split Worker session." });
180
180
  var recommendation = chooseRecommendation(args, session, options);
181
181
  var autoApprove = skipPermissionsEnabled(session);
182
182
  var proposal = {
@@ -200,17 +200,17 @@ function attachWorkerProposal(ctx) {
200
200
  effort: recommendation.effort,
201
201
  autoApproved: true,
202
202
  }, autoApprovalWs(session));
203
- if (!accepted.ok) return toolResult({ error: accepted.error || "Could not start the Worker." });
203
+ if (!accepted.ok) return toolResult({ error: accepted.error || "Could not start the Split Worker." });
204
204
  return toolResult({
205
205
  status: "running",
206
206
  proposalId: proposal.proposalId,
207
- instruction: "The Worker was auto-approved and started because skip permissions is enabled. Its result will return for review.",
207
+ instruction: "The Split Worker was auto-approved and started because skip permissions is enabled. Its result will return for review.",
208
208
  });
209
209
  }
210
210
  return toolResult({
211
211
  status: "posted",
212
212
  proposalId: proposal.proposalId,
213
- instruction: "The Worker suggestion is visible in the chat. End this turn now and wait for the user's decision.",
213
+ instruction: "The Split Worker suggestion is visible in the chat. End this turn now and wait for the user's decision.",
214
214
  });
215
215
  }
216
216
 
@@ -231,10 +231,10 @@ function attachWorkerProposal(ctx) {
231
231
 
232
232
  function parsePartnerResult(result) {
233
233
  if (!result || result.isError || !result.content || !result.content[0]) {
234
- return { status: "error", error: "Worker execution failed." };
234
+ return { status: "error", error: "Split Worker execution failed." };
235
235
  }
236
236
  try { return JSON.parse(result.content[0].text); }
237
- catch (e) { return { status: "error", error: result.content[0].text || "Worker execution failed." }; }
237
+ catch (e) { return { status: "error", error: result.content[0].text || "Split Worker execution failed." }; }
238
238
  }
239
239
 
240
240
  async function runWorker(session, proposal) {
@@ -247,13 +247,13 @@ function attachWorkerProposal(ctx) {
247
247
  });
248
248
  var followup;
249
249
  if (result.status === "complete") {
250
- followup = "[Worker execution completed]\nReview and verify the Worker's result. The Worker session remains available: if the implementation needs corrections or additional edits, send a follow-up with send_to_partner instead of taking over the Worker-owned files yourself. If that Worker is no longer available, keep the work in the visible Worker flow and use send_to_partner again after the stale pair is removed; never substitute a background session.\n\n" + (result.response || "The Worker completed without a text summary.");
250
+ followup = "[Split Worker execution completed]\nReview and verify the Split Worker's result. The Split Worker session remains available: if the implementation needs corrections or additional edits, send a follow-up with send_to_partner instead of taking over the Split Worker-owned files yourself. If that Split Worker is no longer available, keep the work in the visible Split Worker flow and use send_to_partner again after the stale pair is removed; never substitute a background Sub-agent.\n\n" + (result.response || "The Split Worker completed without a text summary.");
251
251
  } else if (result.status === "interrupted") {
252
- followup = "[Worker execution interrupted]\nThe user interrupted the Worker mid-turn. Its work is PARTIAL and unverified — do not treat it as finished. Review what was done and decide next steps with the user.";
252
+ followup = "[Split Worker execution interrupted]\nThe user interrupted the Split Worker mid-turn. Its work is PARTIAL and unverified — do not treat it as finished. Review what was done and decide next steps with the user.";
253
253
  } else if (result.status === "running") {
254
- followup = "[Worker execution is still running]\nUse read_partner to inspect progress before completing the task.";
254
+ followup = "[Split Worker execution is still running]\nUse read_partner to inspect progress before completing the task.";
255
255
  } else {
256
- followup = "[Worker execution failed]\nInspect the failure and delegate a narrower follow-up to the Worker when implementation work remains.\n\n" + (result.error || result.response || "Unknown Worker error.");
256
+ followup = "[Split Worker execution failed]\nInspect the failure and delegate a narrower follow-up to the Split Worker when implementation work remains.\n\n" + (result.error || result.response || "Unknown Split Worker error.");
257
257
  }
258
258
  await resumeDriver(session, followup);
259
259
  }
@@ -272,8 +272,8 @@ function attachWorkerProposal(ctx) {
272
272
  var options = proposal.options || proposalOptions();
273
273
  var vendor = msg.vendor || proposal.recommendedVendor;
274
274
  var model = msg.model || "";
275
- if (options.installedVendors.indexOf(vendor) === -1) throw new Error("Selected Worker vendor is not installed");
276
- if (!modelIsAvailable(options, vendor, model)) throw new Error("Selected Worker model is unavailable");
275
+ if (options.installedVendors.indexOf(vendor) === -1) throw new Error("Selected Split Worker vendor is not installed");
276
+ if (!modelIsAvailable(options, vendor, model)) throw new Error("Selected Split Worker model is unavailable");
277
277
  var effort = yoke.clampEffort(vendor, msg.effort || proposal.recommendedEffort || "medium") || "";
278
278
  var startingPatch = { status: "starting", selectedVendor: vendor, selectedModel: model, selectedEffort: effort };
279
279
  if (msg.autoApproved) startingPatch.autoApproved = true;
@@ -288,7 +288,7 @@ function attachWorkerProposal(ctx) {
288
288
  else ctx.sendTo(ws, { type: "pair_session_created", ok: true, group: created.group });
289
289
  runWorker(session, proposal).catch(function (err) {
290
290
  updateProposal(session, proposal, { status: "error", error: err.message || String(err) });
291
- resumeDriver(session, "[Worker execution failed]\n" + (err.message || String(err))).catch(function () {});
291
+ resumeDriver(session, "[Split Worker execution failed]\n" + (err.message || String(err))).catch(function () {});
292
292
  });
293
293
  return { ok: true, status: "running", group: created.group };
294
294
  } catch (err) {
@@ -300,11 +300,11 @@ function attachWorkerProposal(ctx) {
300
300
  async function respondToProposal(ws, msg) {
301
301
  var session = sessionForResponse(ws);
302
302
  var proposal = findProposal(session, msg.proposalId);
303
- if (!proposal) throw new Error("Worker suggestion not found");
304
- if (proposal.status !== "pending") throw new Error("Worker suggestion has already been resolved");
303
+ if (!proposal) throw new Error("Split Worker suggestion not found");
304
+ if (proposal.status !== "pending") throw new Error("Split Worker suggestion has already been resolved");
305
305
  if (!msg.accepted) {
306
306
  updateProposal(session, proposal, { status: "declined" });
307
- await resumeDriver(session, "[Worker suggestion declined]\nContinue this task in the current session using the plan you already prepared.");
307
+ await resumeDriver(session, "[Split Worker suggestion declined]\nContinue this task in the current session using the plan you already prepared.");
308
308
  return { ok: true, status: "declined" };
309
309
  }
310
310
  return acceptProposal(session, proposal, msg, ws);
@@ -322,13 +322,13 @@ function attachWorkerProposal(ctx) {
322
322
  if (!isEligible(session)) return [];
323
323
  return [{
324
324
  name: "propose_worker",
325
- description: "After making a concise plan for an implementation-heavy task, suggest that the user run the execution with another model in a visible Worker session. Use this only before substantial execution begins, never for small edits, explanations, or tasks the user asked you to keep in this session.",
325
+ description: "After making a concise plan for an implementation-heavy task, suggest that the user run the execution with another model in a visible Split Worker session. Use this only before substantial execution begins, never for small edits, explanations, or tasks the user asked you to keep in this session.",
326
326
  inputSchema: buildShape({
327
- summary: { type: "string", description: "One short sentence explaining why a Worker is useful for this task." },
327
+ summary: { type: "string", description: "One short sentence explaining why a Split Worker is useful for this task." },
328
328
  plan: { type: "string", description: "A concise numbered implementation plan to show in the approval card." },
329
- message: { type: "string", description: "Complete execution instructions for the Worker, including scope, constraints, validation, and expected result." },
330
- recommendedVendor: { type: "string", description: "Optional installed vendor id for the Worker." },
331
- recommendedModel: { type: "string", description: "Optional exact Worker model id. Omit when uncertain." },
329
+ message: { type: "string", description: "Complete execution instructions for the Split Worker, including scope, constraints, validation, and expected result." },
330
+ recommendedVendor: { type: "string", description: "Optional installed vendor id for the Split Worker." },
331
+ recommendedModel: { type: "string", description: "Optional exact Split Worker model id. Omit when uncertain." },
332
332
  recommendedEffort: { type: "string", description: "Optional reasoning effort: minimal, low, medium, high, xhigh, or max." },
333
333
  }, ["summary", "plan", "message"]),
334
334
  handler: function (args) { return propose(args || {}, session); },
@@ -337,7 +337,7 @@ function attachWorkerProposal(ctx) {
337
337
 
338
338
  function getSystemPrompt(session) {
339
339
  if (!isEligible(session)) return "";
340
- return "You can introduce Clay's Driver/Worker workflow with propose_worker. For an implementation-heavy task that is likely to consume substantial execution time, first reason about the work and form a concise plan. Before editing files or running substantial execution, call propose_worker once with that plan and a complete Worker instruction, recommending another suitable execution model. Use it conservatively: do not suggest a Worker for questions, investigations, tiny fixes, or when the user explicitly wants you to execute here. After posting a proposal, end the turn and wait. If accepted, the Worker runs visibly and its result returns to you for review.";
340
+ return "You can introduce Clay's Driver/Split Worker workflow with propose_worker. For an implementation-heavy task that is likely to consume substantial execution time, first reason about the work and form a concise plan. Before editing files or running substantial execution, call propose_worker once with that plan and a complete Split Worker instruction, recommending another suitable execution model. Use it conservatively: do not suggest a Split Worker for questions, investigations, tiny fixes, or when the user explicitly wants you to execute here. After posting a proposal, end the turn and wait. If accepted, the Split Worker runs visibly and its result returns to you for review.";
341
341
  }
342
342
 
343
343
  return {
@@ -0,0 +1,144 @@
1
+ var workspaceMcp = require("./workspace-query-mcp-server");
2
+ var clayHistoryMcp = require("./clay-history-mcp-server");
3
+
4
+ function attachProjectWorkspaceQuery(ctx) {
5
+ var service = ctx.service;
6
+ var sm = ctx.sm;
7
+ var projectSlug = ctx.projectSlug;
8
+ var getProjectOwnerId = ctx.getProjectOwnerId || function () { return null; };
9
+ var isMate = ctx.isMate;
10
+ var mateId = ctx.mateId;
11
+
12
+ function binding(session) {
13
+ if (!service || isMate !== true || !mateId) return null;
14
+ if (session && (!sm || !sm.sessions || sm.sessions.get(session.localId) !== session)) return null;
15
+ if (session && (session.homeDebatePlanning === true || session.debateSetupMode === true || session._mentionInProgress === true || session.spawn)) return null;
16
+ return service.bindSource({
17
+ projectSlug: projectSlug,
18
+ projectOwnerId: getProjectOwnerId(),
19
+ isMate: true,
20
+ mateId: mateId,
21
+ session: session || null,
22
+ });
23
+ }
24
+
25
+ function getToolDefs(session) {
26
+ var bound = session ? binding(session) : null;
27
+ if (session && !bound) return [];
28
+ return workspaceMcp.getToolDefs(bound, !!(bound && bound.isClay));
29
+ }
30
+
31
+ function createMcpServer(adapter, session) {
32
+ if (!service || isMate !== true) return null;
33
+ var bound = session ? binding(session) : null;
34
+ var projectBound = binding(null);
35
+ if (!projectBound) return null;
36
+ return workspaceMcp.createMcpServer(adapter, bound, projectBound.isClay);
37
+ }
38
+
39
+ function createHistoryMcpServer(adapter, session) {
40
+ if (!adapter || typeof adapter.createToolServer !== "function") return null;
41
+ var bound = session ? binding(session) : null;
42
+ var projectBound = binding(null);
43
+ if (!projectBound || projectBound.isClay !== true) return null;
44
+ return adapter.createToolServer({
45
+ name: "clay-history",
46
+ version: "2.0.0",
47
+ tools: clayHistoryMcp.getToolDefs({ workspace: bound }),
48
+ });
49
+ }
50
+
51
+ function isAuthoritativeClay() {
52
+ var bound = binding(null);
53
+ return !!(bound && bound.isClay === true);
54
+ }
55
+
56
+ function getBridgeTools(session, normalizeSchema) {
57
+ if (!session) return [];
58
+ var defs = getToolDefs(session);
59
+ var tools = [];
60
+ for (var i = 0; i < defs.length; i++) {
61
+ tools.push({
62
+ server: "clay-workspace",
63
+ name: defs[i].name,
64
+ description: defs[i].description || defs[i].name,
65
+ inputSchema: normalizeSchema(defs[i].inputSchema),
66
+ });
67
+ }
68
+ return tools;
69
+ }
70
+
71
+ function getDynamicToolDefs(session) {
72
+ return getToolDefs(session).map(function (tool) {
73
+ tool.permissionName = "mcp__clay-workspace__" + tool.name;
74
+ return tool;
75
+ });
76
+ }
77
+
78
+ function getHistoryDynamicToolDefs(session) {
79
+ var bound = session ? binding(session) : null;
80
+ if (!bound || bound.isClay !== true) return [];
81
+ return clayHistoryMcp.getToolDefs({ workspace: bound }).map(function (tool) {
82
+ tool.permissionName = "mcp__clay-history__" + tool.name;
83
+ return tool;
84
+ });
85
+ }
86
+
87
+ function getHistoryBridgeTools(session, normalizeSchema) {
88
+ if (!session) return [];
89
+ var bound = binding(session);
90
+ if (!bound || bound.isClay !== true) return [];
91
+ var defs = clayHistoryMcp.getToolDefs({ workspace: bound });
92
+ var tools = [];
93
+ for (var i = 0; i < defs.length; i++) {
94
+ tools.push({
95
+ server: "clay-history",
96
+ name: defs[i].name,
97
+ description: defs[i].description || defs[i].name,
98
+ inputSchema: normalizeSchema(defs[i].inputSchema),
99
+ });
100
+ }
101
+ return tools;
102
+ }
103
+
104
+ function callBridgeTool(session, toolName, args) {
105
+ if (!session) return Promise.reject(new Error("Workspace tools require a valid Clay session."));
106
+ var defs = getToolDefs(session);
107
+ for (var i = 0; i < defs.length; i++) {
108
+ if (defs[i].name === toolName) return Promise.resolve(defs[i].handler(args || {}));
109
+ }
110
+ return Promise.reject(new Error("Workspace tool not found: " + toolName));
111
+ }
112
+
113
+ function callHistoryBridgeTool(session, toolName, args) {
114
+ var bound = session ? binding(session) : null;
115
+ if (!bound || bound.isClay !== true) return Promise.reject(new Error("Clay history requires a valid builtin Clay session."));
116
+ var defs = clayHistoryMcp.getToolDefs({ workspace: bound });
117
+ for (var i = 0; i < defs.length; i++) {
118
+ if (defs[i].name === toolName) return Promise.resolve(defs[i].handler(args || {}));
119
+ }
120
+ return Promise.reject(new Error("Clay history tool not found: " + toolName));
121
+ }
122
+
123
+ function getMemorySessions(session, excludeSource) {
124
+ var bound = session && service && typeof service.bindProjectSession === "function"
125
+ ? service.bindProjectSession({ projectSlug: projectSlug, session: session })
126
+ : binding(null);
127
+ return bound ? bound.getMemorySessions(excludeSource) : [];
128
+ }
129
+
130
+ return {
131
+ createMcpServer: createMcpServer,
132
+ createHistoryMcpServer: createHistoryMcpServer,
133
+ isAuthoritativeClay: isAuthoritativeClay,
134
+ getBridgeTools: getBridgeTools,
135
+ getHistoryBridgeTools: getHistoryBridgeTools,
136
+ getDynamicToolDefs: getDynamicToolDefs,
137
+ getHistoryDynamicToolDefs: getHistoryDynamicToolDefs,
138
+ callBridgeTool: callBridgeTool,
139
+ callHistoryBridgeTool: callHistoryBridgeTool,
140
+ getMemorySessions: getMemorySessions,
141
+ };
142
+ }
143
+
144
+ module.exports = { attachProjectWorkspaceQuery: attachProjectWorkspaceQuery };