@desplega.ai/agent-swarm 1.2.0 → 1.9.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/.claude/settings.local.json +20 -1
- package/.dockerignore +3 -0
- package/.env.docker.example +22 -1
- package/.env.example +17 -0
- package/.github/workflows/docker-publish.yml +92 -0
- package/CONTRIBUTING.md +270 -0
- package/DEPLOYMENT.md +391 -0
- package/Dockerfile.worker +29 -1
- package/FAQ.md +19 -0
- package/LICENSE +21 -0
- package/MCP.md +249 -0
- package/README.md +105 -185
- package/assets/agent-swarm-logo-orange.png +0 -0
- package/assets/agent-swarm-logo.png +0 -0
- package/assets/agent-swarm.png +0 -0
- package/deploy/docker-push.ts +30 -0
- package/docker-compose.example.yml +137 -0
- package/docker-entrypoint.sh +223 -7
- package/package.json +13 -4
- package/{cc-plugin → plugin}/.claude-plugin/plugin.json +1 -1
- package/plugin/README.md +1 -0
- package/plugin/agents/.gitkeep +0 -0
- package/plugin/agents/codebase-analyzer.md +143 -0
- package/plugin/agents/codebase-locator.md +122 -0
- package/plugin/agents/codebase-pattern-finder.md +227 -0
- package/plugin/agents/web-search-researcher.md +109 -0
- package/plugin/commands/create-plan.md +415 -0
- package/plugin/commands/implement-plan.md +89 -0
- package/plugin/commands/research.md +200 -0
- package/plugin/commands/start-leader.md +101 -0
- package/plugin/commands/start-worker.md +56 -0
- package/plugin/commands/swarm-chat.md +78 -0
- package/plugin/commands/todos.md +66 -0
- package/plugin/commands/work-on-task.md +44 -0
- package/plugin/skills/.gitkeep +0 -0
- package/scripts/generate-mcp-docs.ts +415 -0
- package/slack-manifest.json +69 -0
- package/src/be/db.ts +1431 -25
- package/src/cli.tsx +135 -11
- package/src/commands/lead.ts +13 -0
- package/src/commands/runner.ts +255 -0
- package/src/commands/setup.tsx +5 -5
- package/src/commands/worker.ts +8 -220
- package/src/hooks/hook.ts +108 -14
- package/src/http.ts +361 -5
- package/src/prompts/base-prompt.ts +131 -0
- package/src/server.ts +56 -0
- package/src/slack/app.ts +73 -0
- package/src/slack/commands.ts +88 -0
- package/src/slack/handlers.ts +281 -0
- package/src/slack/index.ts +3 -0
- package/src/slack/responses.ts +175 -0
- package/src/slack/router.ts +170 -0
- package/src/slack/types.ts +20 -0
- package/src/slack/watcher.ts +119 -0
- package/src/tools/create-channel.ts +80 -0
- package/src/tools/get-tasks.ts +54 -21
- package/src/tools/join-swarm.ts +28 -4
- package/src/tools/list-channels.ts +37 -0
- package/src/tools/list-services.ts +110 -0
- package/src/tools/poll-task.ts +47 -3
- package/src/tools/post-message.ts +87 -0
- package/src/tools/read-messages.ts +192 -0
- package/src/tools/register-service.ts +118 -0
- package/src/tools/send-task.ts +80 -7
- package/src/tools/store-progress.ts +9 -3
- package/src/tools/task-action.ts +211 -0
- package/src/tools/unregister-service.ts +110 -0
- package/src/tools/update-profile.ts +105 -0
- package/src/tools/update-service-status.ts +118 -0
- package/src/types.ts +110 -3
- package/src/utils/pretty-print.ts +224 -0
- package/thoughts/shared/plans/.gitkeep +0 -0
- package/thoughts/shared/plans/2025-12-18-inverse-teleport.md +1142 -0
- package/thoughts/shared/plans/2025-12-18-slack-integration.md +1195 -0
- package/thoughts/shared/plans/2025-12-19-agent-log-streaming.md +732 -0
- package/thoughts/shared/plans/2025-12-19-role-based-swarm-plugin.md +361 -0
- package/thoughts/shared/plans/2025-12-20-mobile-responsive-ui.md +501 -0
- package/thoughts/shared/plans/2025-12-20-startup-team-swarm.md +560 -0
- package/thoughts/shared/research/.gitkeep +0 -0
- package/thoughts/shared/research/2025-12-18-slack-integration.md +442 -0
- package/thoughts/shared/research/2025-12-19-agent-log-streaming.md +339 -0
- package/thoughts/shared/research/2025-12-19-agent-secrets-cli-research.md +390 -0
- package/thoughts/shared/research/2025-12-21-gemini-cli-integration.md +376 -0
- package/thoughts/shared/research/2025-12-22-setup-experience-improvements.md +264 -0
- package/tsconfig.json +3 -1
- package/ui/bun.lock +692 -0
- package/ui/index.html +22 -0
- package/ui/package.json +32 -0
- package/ui/pnpm-lock.yaml +3034 -0
- package/ui/postcss.config.js +6 -0
- package/ui/public/logo.png +0 -0
- package/ui/src/App.tsx +43 -0
- package/ui/src/components/ActivityFeed.tsx +415 -0
- package/ui/src/components/AgentDetailPanel.tsx +534 -0
- package/ui/src/components/AgentsPanel.tsx +549 -0
- package/ui/src/components/ChatPanel.tsx +1820 -0
- package/ui/src/components/ConfigModal.tsx +232 -0
- package/ui/src/components/Dashboard.tsx +534 -0
- package/ui/src/components/Header.tsx +168 -0
- package/ui/src/components/ServicesPanel.tsx +612 -0
- package/ui/src/components/StatsBar.tsx +288 -0
- package/ui/src/components/StatusBadge.tsx +124 -0
- package/ui/src/components/TaskDetailPanel.tsx +807 -0
- package/ui/src/components/TasksPanel.tsx +575 -0
- package/ui/src/hooks/queries.ts +170 -0
- package/ui/src/index.css +235 -0
- package/ui/src/lib/api.ts +161 -0
- package/ui/src/lib/config.ts +35 -0
- package/ui/src/lib/theme.ts +214 -0
- package/ui/src/lib/utils.ts +48 -0
- package/ui/src/main.tsx +32 -0
- package/ui/src/types/api.ts +164 -0
- package/ui/src/vite-env.d.ts +1 -0
- package/ui/tailwind.config.js +35 -0
- package/ui/tsconfig.json +31 -0
- package/ui/vite.config.ts +22 -0
- package/cc-plugin/README.md +0 -49
- package/cc-plugin/commands/setup-leader.md +0 -73
- package/cc-plugin/commands/start-worker.md +0 -64
- package/docker-compose.worker.yml +0 -35
- package/example-req-meta.json +0 -24
- /package/{cc-plugin → plugin}/hooks/hooks.json +0 -0
|
@@ -0,0 +1,415 @@
|
|
|
1
|
+
#!/usr/bin/env bun
|
|
2
|
+
/**
|
|
3
|
+
* MCP Tools Documentation Generator
|
|
4
|
+
*
|
|
5
|
+
* This script dynamically discovers and parses tool files in src/tools/
|
|
6
|
+
* and generates MCP.md documentation.
|
|
7
|
+
*
|
|
8
|
+
* Run with: bun run docs:mcp
|
|
9
|
+
*/
|
|
10
|
+
|
|
11
|
+
import { Glob } from "bun";
|
|
12
|
+
import path from "node:path";
|
|
13
|
+
|
|
14
|
+
const TOOLS_DIR = path.join(import.meta.dir, "../src/tools");
|
|
15
|
+
const SERVER_FILE = path.join(import.meta.dir, "../src/server.ts");
|
|
16
|
+
const OUTPUT_FILE = path.join(import.meta.dir, "../MCP.md");
|
|
17
|
+
|
|
18
|
+
interface ToolCategory {
|
|
19
|
+
name: string;
|
|
20
|
+
title: string;
|
|
21
|
+
description: string;
|
|
22
|
+
tools: string[];
|
|
23
|
+
}
|
|
24
|
+
|
|
25
|
+
interface ToolInfo {
|
|
26
|
+
name: string;
|
|
27
|
+
title: string;
|
|
28
|
+
description: string;
|
|
29
|
+
fields: FieldInfo[];
|
|
30
|
+
}
|
|
31
|
+
|
|
32
|
+
interface FieldInfo {
|
|
33
|
+
name: string;
|
|
34
|
+
type: string;
|
|
35
|
+
required: boolean;
|
|
36
|
+
default?: string;
|
|
37
|
+
description: string;
|
|
38
|
+
}
|
|
39
|
+
|
|
40
|
+
/**
|
|
41
|
+
* Dynamically discover tool categories from server.ts
|
|
42
|
+
*/
|
|
43
|
+
async function discoverCategories(): Promise<ToolCategory[]> {
|
|
44
|
+
const serverContent = await Bun.file(SERVER_FILE).text();
|
|
45
|
+
const categories: ToolCategory[] = [];
|
|
46
|
+
|
|
47
|
+
// Extract core tools (always registered, no capability check)
|
|
48
|
+
const coreTools: string[] = [];
|
|
49
|
+
const coreMatch = serverContent.match(
|
|
50
|
+
/\/\/ Core tools[\s\S]*?(?=\/\/.*capability|if \(hasCapability)/
|
|
51
|
+
);
|
|
52
|
+
if (coreMatch) {
|
|
53
|
+
const registerCalls = coreMatch[0].matchAll(/register(\w+)Tool\(server\)/g);
|
|
54
|
+
for (const match of registerCalls) {
|
|
55
|
+
const funcName = match[1];
|
|
56
|
+
const toolName = camelToKebab(funcName);
|
|
57
|
+
coreTools.push(toolName);
|
|
58
|
+
}
|
|
59
|
+
}
|
|
60
|
+
categories.push({
|
|
61
|
+
name: "core",
|
|
62
|
+
title: "Core Tools",
|
|
63
|
+
description: "Always available tools for basic swarm operations.",
|
|
64
|
+
tools: coreTools,
|
|
65
|
+
});
|
|
66
|
+
|
|
67
|
+
// Extract capability-based tools
|
|
68
|
+
const capabilityBlocks = serverContent.matchAll(
|
|
69
|
+
/\/\/\s*([\w\s]+)\s*capability[\s\S]*?if\s*\(hasCapability\(["'](\w+(?:-\w+)*)["']\)\)\s*\{([\s\S]*?)\}/g
|
|
70
|
+
);
|
|
71
|
+
|
|
72
|
+
for (const match of capabilityBlocks) {
|
|
73
|
+
const [, commentDesc, capName, block] = match;
|
|
74
|
+
const tools: string[] = [];
|
|
75
|
+
|
|
76
|
+
const registerCalls = block.matchAll(/register(\w+)Tool\(server\)/g);
|
|
77
|
+
for (const call of registerCalls) {
|
|
78
|
+
const funcName = call[1];
|
|
79
|
+
const toolName = camelToKebab(funcName);
|
|
80
|
+
tools.push(toolName);
|
|
81
|
+
}
|
|
82
|
+
|
|
83
|
+
if (tools.length > 0) {
|
|
84
|
+
categories.push({
|
|
85
|
+
name: capName,
|
|
86
|
+
title: formatCategoryTitle(capName),
|
|
87
|
+
description: commentDesc.trim(),
|
|
88
|
+
tools,
|
|
89
|
+
});
|
|
90
|
+
}
|
|
91
|
+
}
|
|
92
|
+
|
|
93
|
+
return categories;
|
|
94
|
+
}
|
|
95
|
+
|
|
96
|
+
/**
|
|
97
|
+
* Discover all tool files in the tools directory
|
|
98
|
+
*/
|
|
99
|
+
async function discoverToolFiles(): Promise<string[]> {
|
|
100
|
+
const glob = new Glob("*.ts");
|
|
101
|
+
const files: string[] = [];
|
|
102
|
+
|
|
103
|
+
for await (const file of glob.scan(TOOLS_DIR)) {
|
|
104
|
+
// Skip utility files
|
|
105
|
+
if (file === "utils.ts" || file === "index.ts") continue;
|
|
106
|
+
files.push(file.replace(".ts", ""));
|
|
107
|
+
}
|
|
108
|
+
|
|
109
|
+
return files;
|
|
110
|
+
}
|
|
111
|
+
|
|
112
|
+
/**
|
|
113
|
+
* Parse a tool file to extract metadata
|
|
114
|
+
*/
|
|
115
|
+
async function parseToolFile(toolFileName: string): Promise<ToolInfo | null> {
|
|
116
|
+
const filePath = path.join(TOOLS_DIR, `${toolFileName}.ts`);
|
|
117
|
+
const content = await Bun.file(filePath).text();
|
|
118
|
+
|
|
119
|
+
// Extract tool name from createToolRegistrar call
|
|
120
|
+
const nameMatch = content.match(/createToolRegistrar\(server\)\(\s*["']([^"']+)["']/);
|
|
121
|
+
if (!nameMatch) return null;
|
|
122
|
+
|
|
123
|
+
const name = nameMatch[1];
|
|
124
|
+
|
|
125
|
+
// Extract title
|
|
126
|
+
const titleMatch = content.match(/title:\s*["']([^"']+)["']/);
|
|
127
|
+
const title = titleMatch ? titleMatch[1] : formatTitle(name);
|
|
128
|
+
|
|
129
|
+
// Extract description - handle multiline and various quote types
|
|
130
|
+
let description = "";
|
|
131
|
+
// Try to find description that ends before inputSchema, outputSchema, or annotations
|
|
132
|
+
const descPatterns = [
|
|
133
|
+
/description:\s*["'`]([\s\S]*?)["'`]\s*,\s*(?:inputSchema|outputSchema|annotations|_meta)/,
|
|
134
|
+
/description:\s*["']([^"']+)["']/,
|
|
135
|
+
/description:\s*`([^`]+)`/,
|
|
136
|
+
];
|
|
137
|
+
|
|
138
|
+
for (const pattern of descPatterns) {
|
|
139
|
+
const match = content.match(pattern);
|
|
140
|
+
if (match) {
|
|
141
|
+
description = match[1].replace(/\s+/g, " ").trim();
|
|
142
|
+
break;
|
|
143
|
+
}
|
|
144
|
+
}
|
|
145
|
+
|
|
146
|
+
// Parse schema fields
|
|
147
|
+
const fields = parseSchemaFields(content);
|
|
148
|
+
|
|
149
|
+
return { name, title, description, fields };
|
|
150
|
+
}
|
|
151
|
+
|
|
152
|
+
/**
|
|
153
|
+
* Parse input schema fields from file content
|
|
154
|
+
*/
|
|
155
|
+
function parseSchemaFields(content: string): FieldInfo[] {
|
|
156
|
+
const fields: FieldInfo[] = [];
|
|
157
|
+
|
|
158
|
+
// Find inputSchema block
|
|
159
|
+
const schemaStart = content.indexOf("inputSchema:");
|
|
160
|
+
if (schemaStart === -1) return fields;
|
|
161
|
+
|
|
162
|
+
// Find the z.object({ ... }) block
|
|
163
|
+
const objectStart = content.indexOf("z.object({", schemaStart);
|
|
164
|
+
if (objectStart === -1) return fields;
|
|
165
|
+
|
|
166
|
+
// Extract the object content by counting braces
|
|
167
|
+
let braceCount = 0;
|
|
168
|
+
let inObject = false;
|
|
169
|
+
let objectContent = "";
|
|
170
|
+
let i = objectStart + "z.object(".length;
|
|
171
|
+
|
|
172
|
+
while (i < content.length) {
|
|
173
|
+
const char = content[i];
|
|
174
|
+
if (char === "{") {
|
|
175
|
+
braceCount++;
|
|
176
|
+
inObject = true;
|
|
177
|
+
}
|
|
178
|
+
if (inObject) objectContent += char;
|
|
179
|
+
if (char === "}") {
|
|
180
|
+
braceCount--;
|
|
181
|
+
if (braceCount === 0 && inObject) break;
|
|
182
|
+
}
|
|
183
|
+
i++;
|
|
184
|
+
}
|
|
185
|
+
|
|
186
|
+
if (!objectContent) return fields;
|
|
187
|
+
|
|
188
|
+
// Remove outer braces and parse fields
|
|
189
|
+
objectContent = objectContent.slice(1, -1);
|
|
190
|
+
|
|
191
|
+
// Parse each field by tracking brace/paren depth
|
|
192
|
+
let currentField = "";
|
|
193
|
+
let depth = 0;
|
|
194
|
+
|
|
195
|
+
for (let j = 0; j < objectContent.length; j++) {
|
|
196
|
+
const char = objectContent[j];
|
|
197
|
+
if (char === "(" || char === "{" || char === "[") depth++;
|
|
198
|
+
if (char === ")" || char === "}" || char === "]") depth--;
|
|
199
|
+
|
|
200
|
+
currentField += char;
|
|
201
|
+
|
|
202
|
+
// Field ends when we hit a comma at depth 0, or end of content
|
|
203
|
+
const isEndOfField =
|
|
204
|
+
(char === "," && depth === 0) || j === objectContent.length - 1;
|
|
205
|
+
|
|
206
|
+
if (isEndOfField && currentField.trim()) {
|
|
207
|
+
const field = parseField(currentField);
|
|
208
|
+
if (field) fields.push(field);
|
|
209
|
+
currentField = "";
|
|
210
|
+
}
|
|
211
|
+
}
|
|
212
|
+
|
|
213
|
+
return fields;
|
|
214
|
+
}
|
|
215
|
+
|
|
216
|
+
/**
|
|
217
|
+
* Parse a single field definition
|
|
218
|
+
*/
|
|
219
|
+
function parseField(fieldStr: string): FieldInfo | null {
|
|
220
|
+
// Match field name and type chain
|
|
221
|
+
const fieldMatch = fieldStr.match(/^\s*(\w+):\s*z\.([\s\S]+)/);
|
|
222
|
+
if (!fieldMatch) return null;
|
|
223
|
+
|
|
224
|
+
const [, name, typeChain] = fieldMatch;
|
|
225
|
+
|
|
226
|
+
// Determine type
|
|
227
|
+
let type = "unknown";
|
|
228
|
+
if (typeChain.startsWith("string")) type = "string";
|
|
229
|
+
else if (typeChain.startsWith("number")) type = "number";
|
|
230
|
+
else if (typeChain.startsWith("boolean")) type = "boolean";
|
|
231
|
+
else if (typeChain.startsWith("array")) type = "array";
|
|
232
|
+
else if (typeChain.startsWith("uuid")) type = "uuid";
|
|
233
|
+
else if (typeChain.startsWith("object")) type = "object";
|
|
234
|
+
else if (typeChain.startsWith("record")) type = "object";
|
|
235
|
+
else if (typeChain.startsWith("enum")) {
|
|
236
|
+
const enumMatch = typeChain.match(/enum\(\[([\s\S]*?)\]/);
|
|
237
|
+
if (enumMatch) {
|
|
238
|
+
const values = enumMatch[1]
|
|
239
|
+
.replace(/["']/g, "")
|
|
240
|
+
.split(",")
|
|
241
|
+
.map((s) => s.trim())
|
|
242
|
+
.filter(Boolean);
|
|
243
|
+
type = values.join(" \\| ");
|
|
244
|
+
}
|
|
245
|
+
}
|
|
246
|
+
|
|
247
|
+
// Check if optional or has default
|
|
248
|
+
let required = true;
|
|
249
|
+
let defaultValue: string | undefined;
|
|
250
|
+
|
|
251
|
+
if (typeChain.includes(".optional()")) required = false;
|
|
252
|
+
if (typeChain.includes(".default(")) {
|
|
253
|
+
required = false;
|
|
254
|
+
const defaultMatch = typeChain.match(/\.default\(([^)]+)\)/);
|
|
255
|
+
if (defaultMatch) {
|
|
256
|
+
defaultValue = defaultMatch[1].trim();
|
|
257
|
+
}
|
|
258
|
+
}
|
|
259
|
+
|
|
260
|
+
// Extract description
|
|
261
|
+
let description = "";
|
|
262
|
+
const descMatch = typeChain.match(/\.describe\(["'`]([\s\S]*?)["'`]\)/);
|
|
263
|
+
if (descMatch) {
|
|
264
|
+
description = descMatch[1].replace(/\s+/g, " ").trim();
|
|
265
|
+
}
|
|
266
|
+
|
|
267
|
+
return { name, type, required, default: defaultValue, description };
|
|
268
|
+
}
|
|
269
|
+
|
|
270
|
+
/**
|
|
271
|
+
* Convert CamelCase to kebab-case
|
|
272
|
+
*/
|
|
273
|
+
function camelToKebab(str: string): string {
|
|
274
|
+
return str
|
|
275
|
+
.replace(/([a-z])([A-Z])/g, "$1-$2")
|
|
276
|
+
.replace(/([A-Z]+)([A-Z][a-z])/g, "$1-$2")
|
|
277
|
+
.toLowerCase();
|
|
278
|
+
}
|
|
279
|
+
|
|
280
|
+
/**
|
|
281
|
+
* Format category name to title
|
|
282
|
+
*/
|
|
283
|
+
function formatCategoryTitle(name: string): string {
|
|
284
|
+
return name
|
|
285
|
+
.split("-")
|
|
286
|
+
.map((word) => word.charAt(0).toUpperCase() + word.slice(1))
|
|
287
|
+
.join(" ") + " Tools";
|
|
288
|
+
}
|
|
289
|
+
|
|
290
|
+
/**
|
|
291
|
+
* Format tool name to title
|
|
292
|
+
*/
|
|
293
|
+
function formatTitle(name: string): string {
|
|
294
|
+
return name
|
|
295
|
+
.split("-")
|
|
296
|
+
.map((word) => word.charAt(0).toUpperCase() + word.slice(1))
|
|
297
|
+
.join(" ");
|
|
298
|
+
}
|
|
299
|
+
|
|
300
|
+
/**
|
|
301
|
+
* Generate markdown for a single tool
|
|
302
|
+
*/
|
|
303
|
+
function generateToolMarkdown(tool: ToolInfo): string {
|
|
304
|
+
let md = `### ${tool.name}\n\n`;
|
|
305
|
+
md += `**${tool.title}**\n\n`;
|
|
306
|
+
|
|
307
|
+
if (tool.description) {
|
|
308
|
+
md += `${tool.description}\n\n`;
|
|
309
|
+
}
|
|
310
|
+
|
|
311
|
+
if (tool.fields.length > 0) {
|
|
312
|
+
md += `| Parameter | Type | Required | Default | Description |\n`;
|
|
313
|
+
md += `|-----------|------|----------|---------|-------------|\n`;
|
|
314
|
+
for (const field of tool.fields) {
|
|
315
|
+
const req = field.required ? "Yes" : "No";
|
|
316
|
+
const def = field.default ?? "-";
|
|
317
|
+
const desc = field.description || "-";
|
|
318
|
+
md += `| \`${field.name}\` | \`${field.type}\` | ${req} | ${def} | ${desc} |\n`;
|
|
319
|
+
}
|
|
320
|
+
md += "\n";
|
|
321
|
+
} else {
|
|
322
|
+
md += "*No parameters*\n\n";
|
|
323
|
+
}
|
|
324
|
+
|
|
325
|
+
return md;
|
|
326
|
+
}
|
|
327
|
+
|
|
328
|
+
/**
|
|
329
|
+
* Main generation function
|
|
330
|
+
*/
|
|
331
|
+
async function generateDocs() {
|
|
332
|
+
console.log("Discovering tool categories from server.ts...");
|
|
333
|
+
const categories = await discoverCategories();
|
|
334
|
+
|
|
335
|
+
console.log("Discovering tool files...");
|
|
336
|
+
const allToolFiles = await discoverToolFiles();
|
|
337
|
+
|
|
338
|
+
console.log(`Found ${allToolFiles.length} tool files`);
|
|
339
|
+
console.log(`Found ${categories.length} categories:`);
|
|
340
|
+
for (const cat of categories) {
|
|
341
|
+
console.log(` - ${cat.name}: ${cat.tools.length} tools`);
|
|
342
|
+
}
|
|
343
|
+
|
|
344
|
+
// Parse all tool files
|
|
345
|
+
const toolInfoMap = new Map<string, ToolInfo>();
|
|
346
|
+
for (const fileName of allToolFiles) {
|
|
347
|
+
const info = await parseToolFile(fileName);
|
|
348
|
+
if (info) {
|
|
349
|
+
toolInfoMap.set(info.name, info);
|
|
350
|
+
}
|
|
351
|
+
}
|
|
352
|
+
|
|
353
|
+
console.log(`Parsed ${toolInfoMap.size} tools`);
|
|
354
|
+
|
|
355
|
+
// Generate markdown
|
|
356
|
+
let markdown = `# MCP Tools Reference
|
|
357
|
+
|
|
358
|
+
> Auto-generated from source. Do not edit manually.
|
|
359
|
+
> Run \`bun run docs:mcp\` to regenerate.
|
|
360
|
+
|
|
361
|
+
## Table of Contents
|
|
362
|
+
|
|
363
|
+
`;
|
|
364
|
+
|
|
365
|
+
// Generate TOC
|
|
366
|
+
for (const category of categories) {
|
|
367
|
+
const anchor = category.title.toLowerCase().replace(/\s+/g, "-");
|
|
368
|
+
markdown += `- [${category.title}](#${anchor})\n`;
|
|
369
|
+
for (const toolName of category.tools) {
|
|
370
|
+
markdown += ` - [${toolName}](#${toolName})\n`;
|
|
371
|
+
}
|
|
372
|
+
}
|
|
373
|
+
|
|
374
|
+
markdown += "\n---\n\n";
|
|
375
|
+
|
|
376
|
+
// Generate tool documentation by category
|
|
377
|
+
for (const category of categories) {
|
|
378
|
+
markdown += `## ${category.title}\n\n`;
|
|
379
|
+
markdown += `*${category.description}*\n\n`;
|
|
380
|
+
|
|
381
|
+
for (const toolName of category.tools) {
|
|
382
|
+
const tool = toolInfoMap.get(toolName);
|
|
383
|
+
if (tool) {
|
|
384
|
+
markdown += generateToolMarkdown(tool);
|
|
385
|
+
} else {
|
|
386
|
+
console.warn(`Warning: No info found for tool "${toolName}"`);
|
|
387
|
+
markdown += `### ${toolName}\n\n*Documentation not available*\n\n`;
|
|
388
|
+
}
|
|
389
|
+
}
|
|
390
|
+
}
|
|
391
|
+
|
|
392
|
+
// Check for uncategorized tools
|
|
393
|
+
const categorizedTools = new Set(categories.flatMap((c) => c.tools));
|
|
394
|
+
const uncategorized = [...toolInfoMap.keys()].filter(
|
|
395
|
+
(name) => !categorizedTools.has(name)
|
|
396
|
+
);
|
|
397
|
+
|
|
398
|
+
if (uncategorized.length > 0) {
|
|
399
|
+
markdown += `## Other Tools\n\n`;
|
|
400
|
+
markdown += `*Tools not assigned to a capability group*\n\n`;
|
|
401
|
+
for (const toolName of uncategorized) {
|
|
402
|
+
const tool = toolInfoMap.get(toolName);
|
|
403
|
+
if (tool) {
|
|
404
|
+
markdown += generateToolMarkdown(tool);
|
|
405
|
+
}
|
|
406
|
+
}
|
|
407
|
+
}
|
|
408
|
+
|
|
409
|
+
// Write to file
|
|
410
|
+
await Bun.write(OUTPUT_FILE, markdown);
|
|
411
|
+
console.log(`\nGenerated ${OUTPUT_FILE}`);
|
|
412
|
+
}
|
|
413
|
+
|
|
414
|
+
// Run
|
|
415
|
+
generateDocs().catch(console.error);
|
|
@@ -0,0 +1,69 @@
|
|
|
1
|
+
{
|
|
2
|
+
"display_information": {
|
|
3
|
+
"name": "agent-swarm",
|
|
4
|
+
"description": "Your Agent Swarm",
|
|
5
|
+
"background_color": "#000000"
|
|
6
|
+
},
|
|
7
|
+
"features": {
|
|
8
|
+
"app_home": {
|
|
9
|
+
"home_tab_enabled": false,
|
|
10
|
+
"messages_tab_enabled": true,
|
|
11
|
+
"messages_tab_read_only_enabled": false
|
|
12
|
+
},
|
|
13
|
+
"bot_user": {
|
|
14
|
+
"display_name": "agent-swarm",
|
|
15
|
+
"always_online": true
|
|
16
|
+
},
|
|
17
|
+
"slash_commands": [
|
|
18
|
+
{
|
|
19
|
+
"command": "/agent-swarm-status",
|
|
20
|
+
"description": "Check status of available agents",
|
|
21
|
+
"should_escape": false
|
|
22
|
+
},
|
|
23
|
+
{
|
|
24
|
+
"command": "/agent-swarm-help",
|
|
25
|
+
"description": "Show help for using the Agent Swarm bot",
|
|
26
|
+
"should_escape": false
|
|
27
|
+
}
|
|
28
|
+
]
|
|
29
|
+
},
|
|
30
|
+
"oauth_config": {
|
|
31
|
+
"scopes": {
|
|
32
|
+
"bot": [
|
|
33
|
+
"app_mentions:read",
|
|
34
|
+
"channels:history",
|
|
35
|
+
"channels:read",
|
|
36
|
+
"chat:write",
|
|
37
|
+
"chat:write.customize",
|
|
38
|
+
"chat:write.public",
|
|
39
|
+
"commands",
|
|
40
|
+
"groups:history",
|
|
41
|
+
"groups:read",
|
|
42
|
+
"im:history",
|
|
43
|
+
"im:read",
|
|
44
|
+
"im:write",
|
|
45
|
+
"mpim:history",
|
|
46
|
+
"mpim:read",
|
|
47
|
+
"mpim:write",
|
|
48
|
+
"users:read"
|
|
49
|
+
]
|
|
50
|
+
}
|
|
51
|
+
},
|
|
52
|
+
"settings": {
|
|
53
|
+
"event_subscriptions": {
|
|
54
|
+
"bot_events": [
|
|
55
|
+
"app_mention",
|
|
56
|
+
"message.channels",
|
|
57
|
+
"message.groups",
|
|
58
|
+
"message.im",
|
|
59
|
+
"message.mpim"
|
|
60
|
+
]
|
|
61
|
+
},
|
|
62
|
+
"interactivity": {
|
|
63
|
+
"is_enabled": true
|
|
64
|
+
},
|
|
65
|
+
"org_deploy_enabled": false,
|
|
66
|
+
"socket_mode_enabled": true,
|
|
67
|
+
"token_rotation_enabled": false
|
|
68
|
+
}
|
|
69
|
+
}
|