clay-server 2.26.0-beta.9 → 2.26.0
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/browser-mcp-server.js +4 -4
- package/lib/debate-mcp-server.js +94 -0
- package/lib/mates.js +12 -24
- package/lib/project-debate.js +304 -166
- package/lib/project-mate-interaction.js +10 -5
- package/lib/project.js +108 -39
- package/lib/public/app.js +317 -85
- package/lib/public/css/debate.css +230 -2
- package/lib/public/css/filebrowser.css +41 -4
- package/lib/public/css/icon-strip.css +10 -10
- package/lib/public/css/input.css +33 -0
- package/lib/public/css/mates.css +17 -38
- package/lib/public/css/messages.css +17 -0
- package/lib/public/css/mobile-nav.css +3 -1
- package/lib/public/css/rewind.css +17 -4
- package/lib/public/index.html +23 -15
- package/lib/public/modules/context-sources.js +21 -6
- package/lib/public/modules/debate.js +298 -97
- package/lib/public/modules/input.js +15 -0
- package/lib/public/modules/mate-knowledge.js +11 -11
- package/lib/public/modules/mate-memory.js +5 -5
- package/lib/public/modules/mate-sidebar.js +13 -9
- package/lib/public/modules/sidebar.js +105 -26
- package/lib/public/modules/terminal.js +62 -6
- package/lib/public/modules/tools.js +2 -2
- package/lib/sdk-bridge.js +123 -22
- package/lib/sessions.js +2 -2
- package/package.json +1 -1
|
@@ -111,7 +111,7 @@ function create(sendCommand, getTabList, contextOps) {
|
|
|
111
111
|
// --- browser_screenshot ---
|
|
112
112
|
tools.push(tool(
|
|
113
113
|
"browser_screenshot",
|
|
114
|
-
"Capture a screenshot of a browser tab
|
|
114
|
+
"Capture a screenshot of a browser tab. Skip if the tab is already attached as a context source (data is auto-injected).",
|
|
115
115
|
buildShape({
|
|
116
116
|
tabId: { type: "number", description: "Tab ID" },
|
|
117
117
|
selector: { type: "string", description: "CSS selector to capture a specific element (optional)" },
|
|
@@ -134,7 +134,7 @@ function create(sendCommand, getTabList, contextOps) {
|
|
|
134
134
|
// --- browser_console ---
|
|
135
135
|
tools.push(tool(
|
|
136
136
|
"browser_console",
|
|
137
|
-
"Read captured console logs from a tab (
|
|
137
|
+
"Read captured console logs from a tab. Skip if the tab is already a context source (data is auto-injected).",
|
|
138
138
|
buildShape({
|
|
139
139
|
tabId: { type: "number", description: "Tab ID" },
|
|
140
140
|
}, ["tabId"]),
|
|
@@ -157,7 +157,7 @@ function create(sendCommand, getTabList, contextOps) {
|
|
|
157
157
|
// --- browser_network ---
|
|
158
158
|
tools.push(tool(
|
|
159
159
|
"browser_network",
|
|
160
|
-
"Read captured network requests (fetch/XHR) from a tab",
|
|
160
|
+
"Read captured network requests (fetch/XHR) from a tab. Skip if the tab is already a context source.",
|
|
161
161
|
buildShape({
|
|
162
162
|
tabId: { type: "number", description: "Tab ID" },
|
|
163
163
|
}, ["tabId"]),
|
|
@@ -181,7 +181,7 @@ function create(sendCommand, getTabList, contextOps) {
|
|
|
181
181
|
// --- browser_read_page ---
|
|
182
182
|
tools.push(tool(
|
|
183
183
|
"browser_read_page",
|
|
184
|
-
"Read page text content (innerText).
|
|
184
|
+
"Read page text content (innerText). Skip if the tab is already a context source (text is auto-injected). Use for tabs NOT in context sources, or to read a specific element via selector.",
|
|
185
185
|
buildShape({
|
|
186
186
|
tabId: { type: "number", description: "Tab ID" },
|
|
187
187
|
selector: { type: "string", description: "CSS selector to read specific element (optional)" },
|
|
@@ -0,0 +1,94 @@
|
|
|
1
|
+
// Debate MCP Server for Clay (in-process SDK version)
|
|
2
|
+
// Provides the propose_debate tool so mates can propose debates
|
|
3
|
+
// via the SDK tool system instead of writing files to disk.
|
|
4
|
+
//
|
|
5
|
+
// Usage:
|
|
6
|
+
// var debateMcp = require("./debate-mcp-server");
|
|
7
|
+
// var mcpConfig = debateMcp.create(onPropose);
|
|
8
|
+
// // Pass mcpConfig to sdk-bridge opts.mcpServers
|
|
9
|
+
|
|
10
|
+
var z;
|
|
11
|
+
try { z = require("zod"); } catch (e) { z = null; }
|
|
12
|
+
|
|
13
|
+
function buildShape(props, required) {
|
|
14
|
+
if (!z) return {};
|
|
15
|
+
var shape = {};
|
|
16
|
+
var keys = Object.keys(props);
|
|
17
|
+
for (var i = 0; i < keys.length; i++) {
|
|
18
|
+
var k = keys[i];
|
|
19
|
+
var p = props[k];
|
|
20
|
+
var field;
|
|
21
|
+
if (p.type === "number") field = z.number();
|
|
22
|
+
else if (p.type === "boolean") field = z.boolean();
|
|
23
|
+
else if (p.enum) field = z.enum(p.enum);
|
|
24
|
+
else field = z.string();
|
|
25
|
+
if (p.description) field = field.describe(p.description);
|
|
26
|
+
if (!required || required.indexOf(k) === -1) field = field.optional();
|
|
27
|
+
shape[k] = field;
|
|
28
|
+
}
|
|
29
|
+
return shape;
|
|
30
|
+
}
|
|
31
|
+
|
|
32
|
+
// onPropose(briefData) -> Promise<{action: "start"|"cancel"}>
|
|
33
|
+
// The returned Promise blocks the tool until the user approves or cancels.
|
|
34
|
+
function create(onPropose) {
|
|
35
|
+
var sdk;
|
|
36
|
+
try { sdk = require("@anthropic-ai/claude-agent-sdk"); } catch (e) {
|
|
37
|
+
console.error("[debate-mcp] Failed to load SDK:", e.message);
|
|
38
|
+
return null;
|
|
39
|
+
}
|
|
40
|
+
|
|
41
|
+
var createSdkMcpServer = sdk.createSdkMcpServer;
|
|
42
|
+
var tool = sdk.tool;
|
|
43
|
+
if (!createSdkMcpServer || !tool) {
|
|
44
|
+
console.error("[debate-mcp] SDK missing createSdkMcpServer or tool helper");
|
|
45
|
+
return null;
|
|
46
|
+
}
|
|
47
|
+
|
|
48
|
+
var tools = [];
|
|
49
|
+
|
|
50
|
+
tools.push(tool(
|
|
51
|
+
"propose_debate",
|
|
52
|
+
"Propose a structured debate among Clay Mates. The user will see an inline approval card. The tool blocks until the user approves or cancels.",
|
|
53
|
+
buildShape({
|
|
54
|
+
topic: { type: "string", description: "The debate topic" },
|
|
55
|
+
format: { type: "string", description: "Debate format, e.g. free_discussion (default)" },
|
|
56
|
+
context: { type: "string", description: "Key context from the conversation that panelists should know" },
|
|
57
|
+
specialRequests: { type: "string", description: "Special instructions for the debate, or empty" },
|
|
58
|
+
panelists: { type: "string", description: "JSON array of panelist objects: [{\"mateId\": \"<UUID>\", \"role\": \"perspective\", \"brief\": \"guidance\"}]" },
|
|
59
|
+
}, ["topic", "panelists"]),
|
|
60
|
+
function (args) {
|
|
61
|
+
var panelists;
|
|
62
|
+
try {
|
|
63
|
+
panelists = JSON.parse(args.panelists);
|
|
64
|
+
} catch (e) {
|
|
65
|
+
return Promise.resolve({
|
|
66
|
+
content: [{ type: "text", text: "Error: panelists must be a valid JSON array. Got: " + (args.panelists || "").substring(0, 100) }],
|
|
67
|
+
});
|
|
68
|
+
}
|
|
69
|
+
|
|
70
|
+
var briefData = {
|
|
71
|
+
topic: args.topic || "Untitled debate",
|
|
72
|
+
format: args.format || "free_discussion",
|
|
73
|
+
context: args.context || "",
|
|
74
|
+
specialRequests: args.specialRequests || null,
|
|
75
|
+
panelists: panelists,
|
|
76
|
+
};
|
|
77
|
+
|
|
78
|
+
return onPropose(briefData).then(function (result) {
|
|
79
|
+
if (result && result.action === "start") {
|
|
80
|
+
return { content: [{ type: "text", text: "Debate approved and started. Topic: " + briefData.topic }] };
|
|
81
|
+
}
|
|
82
|
+
return { content: [{ type: "text", text: "Debate proposal was cancelled by the user." }] };
|
|
83
|
+
});
|
|
84
|
+
}
|
|
85
|
+
));
|
|
86
|
+
|
|
87
|
+
return createSdkMcpServer({
|
|
88
|
+
name: "clay-debate",
|
|
89
|
+
version: "1.0.0",
|
|
90
|
+
tools: tools,
|
|
91
|
+
});
|
|
92
|
+
}
|
|
93
|
+
|
|
94
|
+
module.exports = { create: create };
|
package/lib/mates.js
CHANGED
|
@@ -633,35 +633,23 @@ var DEBATE_AWARENESS_SECTION =
|
|
|
633
633
|
"\n\n" + DEBATE_AWARENESS_MARKER + "\n" +
|
|
634
634
|
"## Proposing Debates\n\n" +
|
|
635
635
|
"**This section is managed by the system and cannot be removed.**\n\n" +
|
|
636
|
-
"When the user suggests
|
|
637
|
-
"
|
|
638
|
-
"
|
|
636
|
+
"When the user suggests a debate, you MUST use the `propose_debate` tool. " +
|
|
637
|
+
"NEVER write debate files to disk. NEVER mkdir for debates. NEVER use Write/Bash for debate setup. " +
|
|
638
|
+
"The ONLY way to propose a debate is the `propose_debate` tool.\n\n" +
|
|
639
639
|
"**How to propose a debate:**\n" +
|
|
640
|
-
"
|
|
641
|
-
"
|
|
642
|
-
"
|
|
643
|
-
"
|
|
644
|
-
"
|
|
645
|
-
"
|
|
646
|
-
"{\n" +
|
|
647
|
-
"
|
|
648
|
-
" \"format\": \"free_discussion\",\n" +
|
|
649
|
-
" \"context\": \"Key context from the conversation that panelists should know\",\n" +
|
|
650
|
-
" \"specialRequests\": \"Any special instructions, or null\",\n" +
|
|
651
|
-
" \"panelists\": [\n" +
|
|
652
|
-
" {\n" +
|
|
653
|
-
" \"mateId\": \"<mate UUID from the team roster above>\",\n" +
|
|
654
|
-
" \"role\": \"The perspective or stance this panelist should take\",\n" +
|
|
655
|
-
" \"brief\": \"Specific guidance for this panelist\"\n" +
|
|
656
|
-
" }\n" +
|
|
657
|
-
" ]\n" +
|
|
658
|
-
"}\n" +
|
|
659
|
-
"```\n\n" +
|
|
640
|
+
"Call the `propose_debate` tool with these parameters:\n" +
|
|
641
|
+
"- `topic` (required): The refined debate topic\n" +
|
|
642
|
+
"- `format`: Debate format, default \"free_discussion\"\n" +
|
|
643
|
+
"- `context`: Key context from the conversation that panelists should know\n" +
|
|
644
|
+
"- `specialRequests`: Any special instructions\n" +
|
|
645
|
+
"- `panelists` (required): A JSON string array of panelist objects:\n" +
|
|
646
|
+
" `[{\"mateId\": \"<mate UUID from team roster>\", \"role\": \"perspective\", \"brief\": \"guidance\"}]`\n\n" +
|
|
647
|
+
"The user will see an inline approval card. The tool blocks until they approve or cancel.\n\n" +
|
|
660
648
|
"**Rules:**\n" +
|
|
661
649
|
"- Choose 2-4 panelists from the team roster. Pick mates whose expertise fits the topic.\n" +
|
|
662
650
|
"- Do NOT include yourself as a panelist. You will moderate the debate.\n" +
|
|
663
651
|
"- Only propose a debate when the user explicitly asks for one.\n" +
|
|
664
|
-
"-
|
|
652
|
+
"- Do NOT write files to disk for debate proposals. Always use the propose_debate tool.\n";
|
|
665
653
|
|
|
666
654
|
function enforceDebateAwareness(filePath) {
|
|
667
655
|
if (!fs.existsSync(filePath)) return false;
|