clay-server 3.8.1 → 4.0.0-beta.2
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/lib/ask-user-mcp-server.js +5 -119
- package/lib/builtin-mates.js +6 -6
- package/lib/claude-hook-installer.js +15 -0
- package/lib/clay-history-mcp-server.js +62 -297
- package/lib/daemon.js +1 -1
- package/lib/debate-model-selection.js +119 -0
- package/lib/home-debate-tool-policy.js +164 -0
- package/lib/home-response-notifications.js +26 -0
- package/lib/mate-creation-mcp-server.js +55 -0
- package/lib/mate-ready-creation.js +95 -0
- package/lib/mates.js +2 -0
- package/lib/notes.js +2 -1
- package/lib/project-ask-user.js +64 -0
- package/lib/project-capsule-catalog.js +101 -0
- package/lib/project-connection.js +4 -0
- package/lib/project-debate-proposal.js +133 -17
- package/lib/project-debate.js +214 -110
- package/lib/project-delegated-follow-up.js +84 -0
- package/lib/project-delegated-session.js +53 -0
- package/lib/project-filesystem.js +7 -9
- package/lib/project-knowledge.js +1 -0
- package/lib/project-mate-creation-proposal.js +120 -0
- package/lib/project-memory.js +14 -7
- package/lib/project-models.js +157 -32
- package/lib/project-session-notes.js +2 -2
- package/lib/project-session-pair.js +8 -8
- package/lib/project-sessions.js +66 -51
- package/lib/project-vendor-login.js +397 -0
- package/lib/project-worker-proposal.js +25 -25
- package/lib/project-workspace-query.js +144 -0
- package/lib/project.js +349 -102
- package/lib/public/app.js +85 -42
- package/lib/public/css/avatar-imprints.css +0 -1
- package/lib/public/css/base.css +4 -0
- package/lib/public/css/capsule-ui.css +389 -0
- package/lib/public/css/command-palette.css +306 -6
- package/lib/public/css/home-capsule-library.css +243 -0
- package/lib/public/css/home-capsule-source.css +192 -0
- package/lib/public/css/home-debate-live.css +146 -0
- package/lib/public/css/home-debate-planning.css +125 -0
- package/lib/public/css/home-debates-archive.css +281 -0
- package/lib/public/css/home-hub.css +896 -405
- package/lib/public/css/home-mate-creation.css +34 -0
- package/lib/public/css/home-mate-model-picker.css +131 -0
- package/lib/public/css/home-mate-settings.css +344 -0
- package/lib/public/css/home-session-actions.css +265 -0
- package/lib/public/css/home-sidebar.css +667 -0
- package/lib/public/css/icon-strip.css +1 -2
- package/lib/public/css/mates.css +7 -34
- package/lib/public/css/pane.css +1 -1
- package/lib/public/css/playbook.css +0 -80
- package/lib/public/css/sticky-notes.css +53 -117
- package/lib/public/css/tui-attention.css +0 -44
- package/lib/public/css/workspace-assignment.css +45 -0
- package/lib/public/fonts/source-serif-4/LICENSE.md +93 -0
- package/lib/public/fonts/source-serif-4/SourceSerif4Caption-Semibold.ttf.woff2 +0 -0
- package/lib/public/index.html +93 -74
- package/lib/public/modules/app-connection.js +10 -1
- package/lib/public/modules/app-dm.js +43 -160
- package/lib/public/modules/app-home-hub.js +328 -585
- package/lib/public/modules/app-message-cards.js +242 -0
- package/lib/public/modules/app-message-router.js +84 -0
- package/lib/public/modules/app-messages.js +102 -37
- package/lib/public/modules/app-notifications.js +8 -119
- package/lib/public/modules/app-projects.js +9 -1
- package/lib/public/modules/app-rendering.js +21 -602
- package/lib/public/modules/avatar-imprint.js +11 -8
- package/lib/public/modules/chat-bubble-renderer.js +152 -0
- package/lib/public/modules/chat-render-runtime.js +198 -0
- package/lib/public/modules/command-palette.js +225 -436
- package/lib/public/modules/dm-render.js +82 -0
- package/lib/public/modules/home-capsule-creation-intent.js +31 -0
- package/lib/public/modules/home-capsule-library.js +146 -0
- package/lib/public/modules/home-capsule-source.js +383 -0
- package/lib/public/modules/home-chat-identity.js +35 -0
- package/lib/public/modules/home-chat-scroll.js +77 -0
- package/lib/public/modules/home-chat-stream-state.js +34 -0
- package/lib/public/modules/home-composer-focus.js +25 -0
- package/lib/public/modules/home-conversations-sheet.js +179 -0
- package/lib/public/modules/home-debate-activity.js +48 -0
- package/lib/public/modules/home-debate-controls.js +295 -0
- package/lib/public/modules/home-debate-launch.js +41 -0
- package/lib/public/modules/home-debate-live.js +284 -0
- package/lib/public/modules/home-debate-models.js +73 -0
- package/lib/public/modules/home-debate-planning.js +335 -0
- package/lib/public/modules/home-debates-archive.js +279 -0
- package/lib/public/modules/home-dock-resize.js +74 -0
- package/lib/public/modules/home-dock.js +446 -0
- package/lib/public/modules/home-mate-chat.js +496 -0
- package/lib/public/modules/home-mate-creation.js +109 -0
- package/lib/public/modules/home-mate-model-picker.js +281 -0
- package/lib/public/modules/home-mate-selection.js +38 -0
- package/lib/public/modules/home-mate-settings-menu.js +131 -0
- package/lib/public/modules/home-mate-settings.js +383 -0
- package/lib/public/modules/home-session-actions.js +373 -0
- package/lib/public/modules/home-session-model-confirmation.js +13 -0
- package/lib/public/modules/home-shell.js +9 -0
- package/lib/public/modules/home-sidebar-chat-list.js +63 -0
- package/lib/public/modules/home-sidebar.js +158 -0
- package/lib/public/modules/home-sub-surface.js +19 -0
- package/lib/public/modules/home-surface-boot.js +68 -0
- package/lib/public/modules/home-surface.js +141 -0
- package/lib/public/modules/home-tools.js +271 -0
- package/lib/public/modules/markdown.js +50 -2
- package/lib/public/modules/mate-management.js +86 -0
- package/lib/public/modules/mate-wizard.js +0 -7
- package/lib/public/modules/mention.js +17 -19
- package/lib/public/modules/pane-bridge.js +9 -0
- package/lib/public/modules/profile.js +4 -5
- package/lib/public/modules/project-settings.js +34 -28
- package/lib/public/modules/project-switcher.js +11 -5
- package/lib/public/modules/project-workspace-assignment.js +23 -0
- package/lib/public/modules/search-clay-chat.js +402 -0
- package/lib/public/modules/server-settings.js +14 -12
- package/lib/public/modules/session-actions.js +1 -1
- package/lib/public/modules/sidebar-mates.js +56 -552
- package/lib/public/modules/sidebar-mobile.js +7 -64
- package/lib/public/modules/sidebar-presence.js +37 -0
- package/lib/public/modules/split-pair-ui.js +13 -13
- package/lib/public/modules/split-view.js +7 -0
- package/lib/public/modules/sticky-notes.js +7 -6
- package/lib/public/modules/tool-input-composition.js +48 -0
- package/lib/public/modules/tool-llm-status.js +167 -0
- package/lib/public/modules/tool-renderer-advanced.js +285 -0
- package/lib/public/modules/tool-renderer-chart.js +158 -0
- package/lib/public/modules/tool-renderer-semantics.js +35 -0
- package/lib/public/modules/tool-renderer.js +464 -0
- package/lib/public/modules/tool-runtime.js +309 -0
- package/lib/public/modules/tool-ui-evaluator.js +97 -0
- package/lib/public/modules/tool-ui-tree.js +21 -0
- package/lib/public/modules/tui-attention.js +10 -0
- package/lib/public/modules/user-settings.js +16 -23
- package/lib/public/modules/vendor-login.js +287 -0
- package/lib/public/modules/worker-proposal.js +2 -2
- package/lib/public/modules/workspace-assignment-card.js +149 -0
- package/lib/public/modules/workspace-assignment-routing.js +4 -0
- package/lib/public/style.css +13 -2
- package/lib/runtime-env.js +65 -0
- package/lib/sdk-bridge.js +120 -32
- package/lib/sdk-message-processor.js +10 -6
- package/lib/server-home-capsule-creation.js +36 -0
- package/lib/server-home-chat-events.js +287 -0
- package/lib/server-home-chat.js +518 -0
- package/lib/server-home-clay-entry.js +65 -0
- package/lib/server-home-clay-session-links.js +26 -0
- package/lib/server-home-debate-planning.js +214 -0
- package/lib/server-home-debates.js +137 -0
- package/lib/server-home-mate-creation.js +261 -0
- package/lib/server-home-models.js +241 -0
- package/lib/server-home-preferences.js +61 -0
- package/lib/server-mates.js +37 -0
- package/lib/server-tools.js +377 -0
- package/lib/server.js +111 -59
- package/lib/session-pair-mcp-server.js +6 -6
- package/lib/sessions.js +18 -3
- package/lib/tool-capsule-source.js +142 -0
- package/lib/tool-control-mcp-server.js +126 -0
- package/lib/tool-llm.js +48 -0
- package/lib/tool-storage.js +77 -0
- package/lib/tool-ui-spec-advanced.js +82 -0
- package/lib/tool-ui-spec.js +261 -0
- package/lib/tools-registry.js +286 -0
- package/lib/users-home-dock-preferences.js +77 -0
- package/lib/users-home-surface-preferences.js +99 -0
- package/lib/users-preferences.js +4 -7
- package/lib/users.js +12 -0
- package/lib/whats-new-content.js +3 -3
- package/lib/workspace-assignment-service.js +420 -0
- package/lib/workspace-query-mcp-server.js +154 -0
- package/lib/workspace-query-service.js +492 -0
- package/lib/ws-schema.js +93 -12
- package/lib/yoke/adapters/acp.js +2 -1
- package/lib/yoke/adapters/antigravity.js +2 -1
- package/lib/yoke/adapters/claude-worker.js +11 -4
- package/lib/yoke/adapters/claude.js +73 -43
- package/lib/yoke/adapters/codex.js +40 -10
- package/lib/yoke/adapters/kiro.js +2 -1
- package/lib/yoke/claude-user-input.js +38 -0
- package/lib/yoke/codex-app-server.js +20 -2
- package/lib/yoke/codex-user-input.js +64 -0
- package/lib/yoke/complete-once.js +164 -0
- package/lib/yoke/index.js +5 -1
- package/lib/yoke/interface.js +19 -0
- package/lib/yoke/mcp-bridge-server.js +2 -6
- package/lib/yoke/user-input.js +254 -0
- package/package.json +3 -2
- package/lib/public/css/home-chat.css +0 -380
- package/lib/public/modules/home-chat.js +0 -438
- package/lib/server-clay-home.js +0 -245
|
@@ -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
|
|
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 };
|