create-merlin-brain 3.22.0 → 3.23.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/README.md +22 -4
- package/bin/merlin-ask.cjs +111 -0
- package/bin/merlin-cli.cjs +22 -0
- package/bin/runtime-adapters.cjs +678 -28
- package/dist/server/api/client.d.ts +2 -0
- package/dist/server/api/client.d.ts.map +1 -1
- package/dist/server/api/client.js +4 -0
- package/dist/server/api/client.js.map +1 -1
- package/dist/server/server.d.ts.map +1 -1
- package/dist/server/server.js +45 -4
- package/dist/server/server.js.map +1 -1
- package/dist/server/tools/auto-mode.d.ts +9 -0
- package/dist/server/tools/auto-mode.d.ts.map +1 -0
- package/dist/server/tools/auto-mode.js +231 -0
- package/dist/server/tools/auto-mode.js.map +1 -0
- package/dist/server/tools/computer-use.d.ts +8 -0
- package/dist/server/tools/computer-use.d.ts.map +1 -0
- package/dist/server/tools/computer-use.js +355 -0
- package/dist/server/tools/computer-use.js.map +1 -0
- package/dist/server/tools/dream.d.ts +9 -0
- package/dist/server/tools/dream.d.ts.map +1 -0
- package/dist/server/tools/dream.js +246 -0
- package/dist/server/tools/dream.js.map +1 -0
- package/dist/server/tools/hud.d.ts +13 -0
- package/dist/server/tools/hud.d.ts.map +1 -0
- package/dist/server/tools/hud.js +295 -0
- package/dist/server/tools/hud.js.map +1 -0
- package/dist/server/tools/index.d.ts +4 -0
- package/dist/server/tools/index.d.ts.map +1 -1
- package/dist/server/tools/index.js +4 -0
- package/dist/server/tools/index.js.map +1 -1
- package/dist/server/tools/provider-ask.d.ts +10 -0
- package/dist/server/tools/provider-ask.d.ts.map +1 -0
- package/dist/server/tools/provider-ask.js +234 -0
- package/dist/server/tools/provider-ask.js.map +1 -0
- package/dist/server/tools/rate-limit.d.ts +8 -0
- package/dist/server/tools/rate-limit.d.ts.map +1 -0
- package/dist/server/tools/rate-limit.js +184 -0
- package/dist/server/tools/rate-limit.js.map +1 -0
- package/dist/server/tools/skills.d.ts +16 -0
- package/dist/server/tools/skills.d.ts.map +1 -0
- package/dist/server/tools/skills.js +326 -0
- package/dist/server/tools/skills.js.map +1 -0
- package/dist/server/tools/team-workers.d.ts +7 -0
- package/dist/server/tools/team-workers.d.ts.map +1 -0
- package/dist/server/tools/team-workers.js +271 -0
- package/dist/server/tools/team-workers.js.map +1 -0
- package/dist/server/utils/merlin-manifest.d.ts +6 -1
- package/dist/server/utils/merlin-manifest.d.ts.map +1 -1
- package/dist/server/utils/merlin-manifest.js +34 -1
- package/dist/server/utils/merlin-manifest.js.map +1 -1
- package/files/CLAUDE.md +22 -0
- package/files/hooks/rate-limit-watch.sh +120 -0
- package/files/hooks/statusline.sh +148 -0
- package/files/merlin/skills/SKILLS-INDEX.md +82 -0
- package/files/merlin/skills/automation/payments.md +14 -0
- package/files/merlin/skills/automation/webhooks.md +14 -0
- package/files/merlin/skills/coding/accessibility.md +14 -0
- package/files/merlin/skills/coding/api-design.md +14 -0
- package/files/merlin/skills/coding/debug-mode.md +14 -0
- package/files/merlin/skills/coding/focus-mode.md +14 -0
- package/files/merlin/skills/coding/loop.md +14 -0
- package/files/merlin/skills/coding/performance.md +14 -0
- package/files/merlin/skills/coding/react-patterns.md +51 -0
- package/files/merlin/skills/coding/security-hardening.md +56 -0
- package/files/merlin/skills/coding/verify.md +14 -0
- package/files/merlin/skills/communication/dispatcher.md +40 -0
- package/files/merlin/skills/communication/email-gmail.md +31 -0
- package/files/merlin/skills/communication/telegram.md +50 -0
- package/files/merlin/skills/communication/whatsapp.md +47 -0
- package/files/merlin/skills/data/google-sheets.md +14 -0
- package/files/merlin/skills/design/animation.md +14 -0
- package/files/merlin/skills/devops/docker-containers.md +14 -0
- package/files/merlin/skills/research/brainstorm.md +14 -0
- package/files/merlin/skills/testing/tdd-workflow.md +58 -0
- package/package.json +4 -2
|
@@ -0,0 +1,326 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Skills Tools — Discover, load, evolve, and track skills
|
|
3
|
+
*
|
|
4
|
+
* Skills are prompt injections stored as .md files in ~/.claude/merlin/skills/.
|
|
5
|
+
* Claude reads SKILLS-INDEX.md to find relevant skills, then loads the full .md.
|
|
6
|
+
*
|
|
7
|
+
* Inspired by OpenSpace's self-evolving skill system:
|
|
8
|
+
* - Skills track usage and success rates
|
|
9
|
+
* - Skills can be improved after use (auto-evolution)
|
|
10
|
+
* - Improvements push to the server for collective intelligence
|
|
11
|
+
*
|
|
12
|
+
* Works identically in CLI (via MCP) and Studio (same file paths).
|
|
13
|
+
*/
|
|
14
|
+
import { z } from 'zod';
|
|
15
|
+
import { existsSync, readFileSync, writeFileSync, readdirSync, statSync, mkdirSync } from 'fs';
|
|
16
|
+
import { join, relative, basename } from 'path';
|
|
17
|
+
import { homedir } from 'os';
|
|
18
|
+
import { coachWrap } from '../session-coach.js';
|
|
19
|
+
// ─── Paths ────────────────────────────────────────────────────────────────────
|
|
20
|
+
const SKILLS_DIR = join(homedir(), '.claude', 'merlin', 'skills');
|
|
21
|
+
const SKILLS_INDEX = join(SKILLS_DIR, 'SKILLS-INDEX.md');
|
|
22
|
+
const SKILL_STATS_FILE = join(homedir(), '.claude', 'merlin', 'skill-stats.json');
|
|
23
|
+
// ─── Helpers ──────────────────────────────────────────────────────────────────
|
|
24
|
+
function loadStats() {
|
|
25
|
+
try {
|
|
26
|
+
if (existsSync(SKILL_STATS_FILE)) {
|
|
27
|
+
return JSON.parse(readFileSync(SKILL_STATS_FILE, 'utf-8'));
|
|
28
|
+
}
|
|
29
|
+
}
|
|
30
|
+
catch { /* ignore */ }
|
|
31
|
+
return {};
|
|
32
|
+
}
|
|
33
|
+
function saveStats(stats) {
|
|
34
|
+
try {
|
|
35
|
+
mkdirSync(join(homedir(), '.claude', 'merlin'), { recursive: true });
|
|
36
|
+
writeFileSync(SKILL_STATS_FILE, JSON.stringify(stats, null, 2), 'utf-8');
|
|
37
|
+
}
|
|
38
|
+
catch { /* non-critical */ }
|
|
39
|
+
}
|
|
40
|
+
/** Find all .md files recursively in a directory */
|
|
41
|
+
function findSkillFiles(dir) {
|
|
42
|
+
const results = [];
|
|
43
|
+
if (!existsSync(dir))
|
|
44
|
+
return results;
|
|
45
|
+
for (const entry of readdirSync(dir)) {
|
|
46
|
+
const fullPath = join(dir, entry);
|
|
47
|
+
try {
|
|
48
|
+
const stat = statSync(fullPath);
|
|
49
|
+
if (stat.isDirectory()) {
|
|
50
|
+
results.push(...findSkillFiles(fullPath));
|
|
51
|
+
}
|
|
52
|
+
else if (entry.endsWith('.md') && entry !== 'SKILLS-INDEX.md') {
|
|
53
|
+
results.push(fullPath);
|
|
54
|
+
}
|
|
55
|
+
}
|
|
56
|
+
catch { /* skip unreadable */ }
|
|
57
|
+
}
|
|
58
|
+
return results;
|
|
59
|
+
}
|
|
60
|
+
/** Parse frontmatter from a skill .md file */
|
|
61
|
+
function parseFrontmatter(content) {
|
|
62
|
+
const match = content.match(/^---\n([\s\S]*?)\n---/);
|
|
63
|
+
if (!match)
|
|
64
|
+
return {};
|
|
65
|
+
const result = {};
|
|
66
|
+
for (const line of match[1].split('\n')) {
|
|
67
|
+
const colonIdx = line.indexOf(':');
|
|
68
|
+
if (colonIdx > 0) {
|
|
69
|
+
const key = line.slice(0, colonIdx).trim();
|
|
70
|
+
let value = line.slice(colonIdx + 1).trim();
|
|
71
|
+
// Parse arrays
|
|
72
|
+
if (typeof value === 'string' && value.startsWith('[')) {
|
|
73
|
+
try {
|
|
74
|
+
value = JSON.parse(value.replace(/'/g, '"'));
|
|
75
|
+
}
|
|
76
|
+
catch { /* keep as string */ }
|
|
77
|
+
}
|
|
78
|
+
// Parse numbers
|
|
79
|
+
if (typeof value === 'string' && /^\d+$/.test(value)) {
|
|
80
|
+
value = parseInt(value, 10);
|
|
81
|
+
}
|
|
82
|
+
result[key] = value;
|
|
83
|
+
}
|
|
84
|
+
}
|
|
85
|
+
return result;
|
|
86
|
+
}
|
|
87
|
+
/** Search skills by keyword matching against tags and name */
|
|
88
|
+
function searchSkills(query) {
|
|
89
|
+
const files = findSkillFiles(SKILLS_DIR);
|
|
90
|
+
const queryWords = query.toLowerCase().split(/\s+/);
|
|
91
|
+
const results = [];
|
|
92
|
+
for (const filePath of files) {
|
|
93
|
+
try {
|
|
94
|
+
const content = readFileSync(filePath, 'utf-8');
|
|
95
|
+
const fm = parseFrontmatter(content);
|
|
96
|
+
const id = fm.id || basename(filePath, '.md');
|
|
97
|
+
const name = fm.name || id;
|
|
98
|
+
const tags = fm.tags || [];
|
|
99
|
+
const domain = fm.domain || '';
|
|
100
|
+
const category = fm.category || '';
|
|
101
|
+
// Score: exact tag match = 3, partial tag match = 2, name match = 2, domain/category = 1
|
|
102
|
+
let score = 0;
|
|
103
|
+
const allSearchable = [...tags, name.toLowerCase(), domain, category];
|
|
104
|
+
for (const word of queryWords) {
|
|
105
|
+
for (const term of allSearchable) {
|
|
106
|
+
if (term === word)
|
|
107
|
+
score += 3;
|
|
108
|
+
else if (term.includes(word) || word.includes(term))
|
|
109
|
+
score += 1;
|
|
110
|
+
}
|
|
111
|
+
}
|
|
112
|
+
if (score > 0) {
|
|
113
|
+
const relPath = relative(SKILLS_DIR, filePath).replace(/\.md$/, '');
|
|
114
|
+
results.push({ id, name, path: relPath, score, tags });
|
|
115
|
+
}
|
|
116
|
+
}
|
|
117
|
+
catch { /* skip unreadable */ }
|
|
118
|
+
}
|
|
119
|
+
return results.sort((a, b) => b.score - a.score);
|
|
120
|
+
}
|
|
121
|
+
// ─── Register Tools ───────────────────────────────────────────────────────────
|
|
122
|
+
export function registerSkillsTools(ctx) {
|
|
123
|
+
const { server } = ctx;
|
|
124
|
+
// ── merlin_find_skill — search the skills index ──────────────────────────
|
|
125
|
+
server.tool('merlin_find_skill', 'Search the Merlin Skills Index for relevant skills to load. ' +
|
|
126
|
+
'Describe what you need (e.g., "react performance", "stripe payments", "telegram bot") ' +
|
|
127
|
+
'and get back the best matching skills with their file paths. ' +
|
|
128
|
+
'Load the top 1-3 skills by reading their .md files.', {
|
|
129
|
+
query: z.string().describe('What kind of skill you need (e.g., "react hooks", "security audit", "whatsapp messaging")'),
|
|
130
|
+
limit: z.number().optional().describe('Max results to return (default 5)'),
|
|
131
|
+
}, async ({ query, limit }) => {
|
|
132
|
+
const maxResults = Math.min(limit || 5, 20);
|
|
133
|
+
// First try local file search
|
|
134
|
+
const localResults = searchSkills(query);
|
|
135
|
+
// Also try server index if available
|
|
136
|
+
let serverResults = [];
|
|
137
|
+
try {
|
|
138
|
+
const skills = await ctx.client.request(`/api/skills/search?q=${encodeURIComponent(query)}&limit=${maxResults}`);
|
|
139
|
+
serverResults = skills.skills || [];
|
|
140
|
+
}
|
|
141
|
+
catch { /* server unavailable — local-only is fine */ }
|
|
142
|
+
// Merge results (local first, deduplicated)
|
|
143
|
+
const seen = new Set();
|
|
144
|
+
const merged = [];
|
|
145
|
+
for (const r of localResults.slice(0, maxResults)) {
|
|
146
|
+
seen.add(r.id);
|
|
147
|
+
const stats = loadStats()[r.id];
|
|
148
|
+
const successRate = stats && stats.usageCount > 0
|
|
149
|
+
? `${Math.round((stats.successCount / stats.usageCount) * 100)}%`
|
|
150
|
+
: 'new';
|
|
151
|
+
merged.push(`**${r.name}** (${r.path})\n` +
|
|
152
|
+
` Tags: ${r.tags.join(', ')}\n` +
|
|
153
|
+
` Score: ${r.score} | Success: ${successRate} | Uses: ${stats?.usageCount || 0}\n` +
|
|
154
|
+
` Load: Read ~/.claude/merlin/skills/${r.path}.md`);
|
|
155
|
+
}
|
|
156
|
+
for (const r of serverResults) {
|
|
157
|
+
if (!seen.has(r.id) && merged.length < maxResults) {
|
|
158
|
+
seen.add(r.id);
|
|
159
|
+
merged.push(`**${r.name}** (server)\n` +
|
|
160
|
+
` ${r.description}\n` +
|
|
161
|
+
` Install: merlin_install_skill("${r.id}")`);
|
|
162
|
+
}
|
|
163
|
+
}
|
|
164
|
+
const response = merged.length > 0
|
|
165
|
+
? `Found ${merged.length} skill(s) for "${query}":\n\n${merged.join('\n\n')}`
|
|
166
|
+
: `No skills found for "${query}". You can create one with merlin_evolve_skill after completing the task.`;
|
|
167
|
+
return {
|
|
168
|
+
content: [{ type: 'text', text: coachWrap('merlin_find_skill', response) }],
|
|
169
|
+
};
|
|
170
|
+
});
|
|
171
|
+
// ── merlin_track_skill — record skill usage outcome ──────────────────────
|
|
172
|
+
server.tool('merlin_track_skill', 'Record that a skill was used and whether it helped. ' +
|
|
173
|
+
'Call this after using a skill to track quality. ' +
|
|
174
|
+
'Skills with high success rates get recommended more often.', {
|
|
175
|
+
skillId: z.string().describe('The skill ID (from frontmatter)'),
|
|
176
|
+
success: z.boolean().describe('Did the skill help accomplish the task?'),
|
|
177
|
+
feedback: z.string().optional().describe('What worked or didn\'t work'),
|
|
178
|
+
}, async ({ skillId, success, feedback }) => {
|
|
179
|
+
const stats = loadStats();
|
|
180
|
+
if (!stats[skillId]) {
|
|
181
|
+
stats[skillId] = { usageCount: 0, successCount: 0, failCount: 0, lastUsed: '', version: 1 };
|
|
182
|
+
}
|
|
183
|
+
stats[skillId].usageCount++;
|
|
184
|
+
if (success)
|
|
185
|
+
stats[skillId].successCount++;
|
|
186
|
+
else
|
|
187
|
+
stats[skillId].failCount++;
|
|
188
|
+
stats[skillId].lastUsed = new Date().toISOString();
|
|
189
|
+
saveStats(stats);
|
|
190
|
+
// Push stats to server (background, non-blocking)
|
|
191
|
+
try {
|
|
192
|
+
void ctx.client.request('/api/skills/usage', {
|
|
193
|
+
method: 'POST',
|
|
194
|
+
headers: { 'Content-Type': 'application/json' },
|
|
195
|
+
body: JSON.stringify({ skillId, success, feedback }),
|
|
196
|
+
});
|
|
197
|
+
}
|
|
198
|
+
catch { /* non-critical */ }
|
|
199
|
+
const rate = Math.round((stats[skillId].successCount / stats[skillId].usageCount) * 100);
|
|
200
|
+
const response = success
|
|
201
|
+
? `Tracked: ${skillId} succeeded (${rate}% success rate, ${stats[skillId].usageCount} uses)`
|
|
202
|
+
: `Tracked: ${skillId} failed (${rate}% success rate). ${feedback ? `Feedback: ${feedback}` : 'Consider evolving this skill.'}`;
|
|
203
|
+
return {
|
|
204
|
+
content: [{ type: 'text', text: coachWrap('merlin_track_skill', response) }],
|
|
205
|
+
};
|
|
206
|
+
});
|
|
207
|
+
// ── merlin_evolve_skill — improve or create a skill ──────────────────────
|
|
208
|
+
server.tool('merlin_evolve_skill', 'Improve an existing skill or create a new one based on what you learned during a task. ' +
|
|
209
|
+
'This is how skills self-evolve: after using a skill, if you found it lacking or wrong, ' +
|
|
210
|
+
'update it with better instructions. New skills are created from successful task patterns.', {
|
|
211
|
+
skillId: z.string().describe('Skill ID to evolve (or new ID for a new skill)'),
|
|
212
|
+
name: z.string().describe('Human-readable skill name'),
|
|
213
|
+
domain: z.enum(['coding', 'non-coding']).describe('Top-level domain'),
|
|
214
|
+
category: z.string().describe('Sub-category (e.g., frontend, security, communication, automation)'),
|
|
215
|
+
tags: z.array(z.string()).describe('Search tags for discovery'),
|
|
216
|
+
content: z.string().describe('The full skill instructions (markdown)'),
|
|
217
|
+
reason: z.string().describe('Why this skill was created or what changed'),
|
|
218
|
+
}, async ({ skillId, name, domain, category, tags, content, reason }) => {
|
|
219
|
+
// Determine file path
|
|
220
|
+
const categoryDir = join(SKILLS_DIR, domain === 'non-coding' ? category : `coding`);
|
|
221
|
+
// For non-coding, use the category directly; for coding, check if the category subdir makes more sense
|
|
222
|
+
const targetDir = existsSync(join(SKILLS_DIR, category)) ? join(SKILLS_DIR, category) : categoryDir;
|
|
223
|
+
mkdirSync(targetDir, { recursive: true });
|
|
224
|
+
const filePath = join(targetDir, `${skillId}.md`);
|
|
225
|
+
// Check if evolving an existing skill
|
|
226
|
+
let version = 1;
|
|
227
|
+
const evolutionLog = [];
|
|
228
|
+
if (existsSync(filePath)) {
|
|
229
|
+
const existing = readFileSync(filePath, 'utf-8');
|
|
230
|
+
const fm = parseFrontmatter(existing);
|
|
231
|
+
version = (fm.version || 0) + 1;
|
|
232
|
+
const existingEvolution = fm.evolution || [];
|
|
233
|
+
evolutionLog.push(...existingEvolution);
|
|
234
|
+
}
|
|
235
|
+
evolutionLog.push(`v${version}: ${reason}`);
|
|
236
|
+
// Write the skill file
|
|
237
|
+
const frontmatter = [
|
|
238
|
+
'---',
|
|
239
|
+
`id: ${skillId}`,
|
|
240
|
+
`name: ${name}`,
|
|
241
|
+
`domain: ${domain}`,
|
|
242
|
+
`category: ${category}`,
|
|
243
|
+
`tags: [${tags.join(', ')}]`,
|
|
244
|
+
`version: ${version}`,
|
|
245
|
+
`source: ${version === 1 ? 'evolved' : 'evolved'}`,
|
|
246
|
+
`successRate: 0`,
|
|
247
|
+
`usageCount: 0`,
|
|
248
|
+
`evolution:`,
|
|
249
|
+
...evolutionLog.map(e => ` - "${e}"`),
|
|
250
|
+
'---',
|
|
251
|
+
'',
|
|
252
|
+
].join('\n');
|
|
253
|
+
writeFileSync(filePath, frontmatter + content, 'utf-8');
|
|
254
|
+
// Update stats
|
|
255
|
+
const stats = loadStats();
|
|
256
|
+
if (stats[skillId]) {
|
|
257
|
+
stats[skillId].lastEvolved = new Date().toISOString();
|
|
258
|
+
stats[skillId].version = version;
|
|
259
|
+
}
|
|
260
|
+
saveStats(stats);
|
|
261
|
+
// Push to server (background)
|
|
262
|
+
try {
|
|
263
|
+
void ctx.client.request('/api/skills', {
|
|
264
|
+
method: 'POST',
|
|
265
|
+
headers: { 'Content-Type': 'application/json' },
|
|
266
|
+
body: JSON.stringify({
|
|
267
|
+
id: skillId, name, domain, category, tags,
|
|
268
|
+
content, version, reason,
|
|
269
|
+
}),
|
|
270
|
+
});
|
|
271
|
+
}
|
|
272
|
+
catch { /* non-critical */ }
|
|
273
|
+
// Update the index file
|
|
274
|
+
updateSkillsIndex();
|
|
275
|
+
const action = version === 1 ? 'Created' : `Evolved to v${version}`;
|
|
276
|
+
const response = `${action}: **${name}** (${skillId})\n` +
|
|
277
|
+
`Path: ${relative(join(homedir(), '.claude', 'merlin'), filePath)}\n` +
|
|
278
|
+
`Reason: ${reason}\n` +
|
|
279
|
+
`Tags: ${tags.join(', ')}`;
|
|
280
|
+
return {
|
|
281
|
+
content: [{ type: 'text', text: coachWrap('merlin_evolve_skill', response) }],
|
|
282
|
+
};
|
|
283
|
+
});
|
|
284
|
+
}
|
|
285
|
+
// ─── Index Regeneration ───────────────────────────────────────────────────────
|
|
286
|
+
/** Rebuild SKILLS-INDEX.md from all skill files on disk */
|
|
287
|
+
function updateSkillsIndex() {
|
|
288
|
+
const files = findSkillFiles(SKILLS_DIR);
|
|
289
|
+
const byCategory = new Map();
|
|
290
|
+
for (const filePath of files) {
|
|
291
|
+
try {
|
|
292
|
+
const content = readFileSync(filePath, 'utf-8');
|
|
293
|
+
const fm = parseFrontmatter(content);
|
|
294
|
+
const id = fm.id || basename(filePath, '.md');
|
|
295
|
+
const name = fm.name || id;
|
|
296
|
+
const tags = fm.tags || [];
|
|
297
|
+
const domain = fm.domain || 'coding';
|
|
298
|
+
const category = fm.category || 'other';
|
|
299
|
+
const key = `${domain} > ${category}`;
|
|
300
|
+
const relPath = relative(SKILLS_DIR, filePath).replace(/\.md$/, '');
|
|
301
|
+
if (!byCategory.has(key))
|
|
302
|
+
byCategory.set(key, []);
|
|
303
|
+
byCategory.get(key).push({ id, name, tags, relPath });
|
|
304
|
+
}
|
|
305
|
+
catch { /* skip */ }
|
|
306
|
+
}
|
|
307
|
+
const lines = [
|
|
308
|
+
'# Merlin Skills Index',
|
|
309
|
+
'',
|
|
310
|
+
'Search this index to find skills. Load by reading the .md file.',
|
|
311
|
+
'Only load 1-3 per task. After use, track with merlin_track_skill.',
|
|
312
|
+
'',
|
|
313
|
+
];
|
|
314
|
+
for (const [category, skills] of [...byCategory.entries()].sort()) {
|
|
315
|
+
lines.push(`## ${category}`);
|
|
316
|
+
for (const s of skills) {
|
|
317
|
+
lines.push(`- \`${s.relPath}\` — ${s.name} — [${s.tags.join(', ')}]`);
|
|
318
|
+
}
|
|
319
|
+
lines.push('');
|
|
320
|
+
}
|
|
321
|
+
try {
|
|
322
|
+
writeFileSync(SKILLS_INDEX, lines.join('\n'), 'utf-8');
|
|
323
|
+
}
|
|
324
|
+
catch { /* non-critical */ }
|
|
325
|
+
}
|
|
326
|
+
//# sourceMappingURL=skills.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"skills.js","sourceRoot":"","sources":["../../../src/server/tools/skills.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1,7 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Team Workers Tools — Spawn parallel AI CLI workers in tmux panes.
|
|
3
|
+
* Job state persisted to ~/.merlin/state/team/ for status/cleanup queries.
|
|
4
|
+
*/
|
|
5
|
+
import type { ToolContext } from './types.js';
|
|
6
|
+
export declare function registerTeamWorkerTools(ctx: ToolContext): void;
|
|
7
|
+
//# sourceMappingURL=team-workers.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"team-workers.d.ts","sourceRoot":"","sources":["../../../src/server/tools/team-workers.ts"],"names":[],"mappings":"AAAA;;;GAGG;AAQH,OAAO,KAAK,EAAE,WAAW,EAAE,MAAM,YAAY,CAAC;AA0H9C,wBAAgB,uBAAuB,CAAC,GAAG,EAAE,WAAW,GAAG,IAAI,CA4J9D"}
|
|
@@ -0,0 +1,271 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Team Workers Tools — Spawn parallel AI CLI workers in tmux panes.
|
|
3
|
+
* Job state persisted to ~/.merlin/state/team/ for status/cleanup queries.
|
|
4
|
+
*/
|
|
5
|
+
import { z } from 'zod';
|
|
6
|
+
import { execFile } from 'child_process';
|
|
7
|
+
import { existsSync, readFileSync, writeFileSync, mkdirSync, readdirSync, unlinkSync } from 'fs';
|
|
8
|
+
import { homedir } from 'os';
|
|
9
|
+
import { join } from 'path';
|
|
10
|
+
import { promisify } from 'util';
|
|
11
|
+
const execFileAsync = promisify(execFile);
|
|
12
|
+
const TEAM_STATE_DIR = join(homedir(), '.merlin', 'state', 'team');
|
|
13
|
+
// ── Internal helpers ──────────────────────────────────────────────────────
|
|
14
|
+
async function isTmuxAvailable() {
|
|
15
|
+
try {
|
|
16
|
+
await execFileAsync('which', ['tmux']);
|
|
17
|
+
return true;
|
|
18
|
+
}
|
|
19
|
+
catch {
|
|
20
|
+
return false;
|
|
21
|
+
}
|
|
22
|
+
}
|
|
23
|
+
function generateJobId() {
|
|
24
|
+
return `merlin-${Date.now()}-${Math.random().toString(36).slice(2, 8)}`;
|
|
25
|
+
}
|
|
26
|
+
async function ensureTmuxSession(session) {
|
|
27
|
+
try {
|
|
28
|
+
await execFileAsync('tmux', ['has-session', '-t', session]);
|
|
29
|
+
return true;
|
|
30
|
+
}
|
|
31
|
+
catch {
|
|
32
|
+
try {
|
|
33
|
+
await execFileAsync('tmux', ['new-session', '-d', '-s', session]);
|
|
34
|
+
return true;
|
|
35
|
+
}
|
|
36
|
+
catch {
|
|
37
|
+
return false;
|
|
38
|
+
}
|
|
39
|
+
}
|
|
40
|
+
}
|
|
41
|
+
/** Split a new pane in the session, send command, return pane ID. */
|
|
42
|
+
async function createTmuxPane(session, command) {
|
|
43
|
+
await execFileAsync('tmux', ['split-window', '-d', '-t', session]);
|
|
44
|
+
const { stdout } = await execFileAsync('tmux', [
|
|
45
|
+
'list-panes', '-t', session, '-F', '#{session_name}:#{window_index}.#{pane_index}',
|
|
46
|
+
]);
|
|
47
|
+
const panes = stdout.trim().split('\n').filter(Boolean);
|
|
48
|
+
if (panes.length === 0)
|
|
49
|
+
throw new Error('No panes found after split-window');
|
|
50
|
+
const paneId = panes[panes.length - 1];
|
|
51
|
+
await execFileAsync('tmux', ['send-keys', '-t', paneId, command, 'Enter']);
|
|
52
|
+
return paneId;
|
|
53
|
+
}
|
|
54
|
+
async function capturePaneOutput(paneId, lines = 50) {
|
|
55
|
+
try {
|
|
56
|
+
const { stdout } = await execFileAsync('tmux', [
|
|
57
|
+
'capture-pane', '-t', paneId, '-p', '-J', '-S', String(-lines),
|
|
58
|
+
]);
|
|
59
|
+
return stdout;
|
|
60
|
+
}
|
|
61
|
+
catch {
|
|
62
|
+
return '(pane output unavailable)';
|
|
63
|
+
}
|
|
64
|
+
}
|
|
65
|
+
async function isPaneAlive(paneId) {
|
|
66
|
+
try {
|
|
67
|
+
await execFileAsync('tmux', ['list-panes', '-t', paneId]);
|
|
68
|
+
return true;
|
|
69
|
+
}
|
|
70
|
+
catch {
|
|
71
|
+
return false;
|
|
72
|
+
}
|
|
73
|
+
}
|
|
74
|
+
/** Build provider CLI command. Escapes task string for send-keys shell boundary. */
|
|
75
|
+
function buildProviderCommand(provider, task, agent) {
|
|
76
|
+
const t = task.replace(/\\/g, '\\\\').replace(/"/g, '\\"');
|
|
77
|
+
switch (provider) {
|
|
78
|
+
case 'claude': return `claude ${agent ? `--agent ${agent} ` : ''}-p "${t}" --output-format text`;
|
|
79
|
+
case 'codex': return `codex exec "${t}"`;
|
|
80
|
+
case 'gemini': return `gemini -p "${t}"`;
|
|
81
|
+
}
|
|
82
|
+
}
|
|
83
|
+
// ── State helpers ─────────────────────────────────────────────────────────
|
|
84
|
+
function ensureStateDir() {
|
|
85
|
+
if (!existsSync(TEAM_STATE_DIR))
|
|
86
|
+
mkdirSync(TEAM_STATE_DIR, { recursive: true });
|
|
87
|
+
}
|
|
88
|
+
function stateFilePath(teamName) {
|
|
89
|
+
return join(TEAM_STATE_DIR, `${teamName}.json`);
|
|
90
|
+
}
|
|
91
|
+
function saveJobState(state) {
|
|
92
|
+
ensureStateDir();
|
|
93
|
+
writeFileSync(stateFilePath(state.teamName), JSON.stringify(state, null, 2), 'utf-8');
|
|
94
|
+
}
|
|
95
|
+
function loadJobState(teamName) {
|
|
96
|
+
try {
|
|
97
|
+
const p = stateFilePath(teamName);
|
|
98
|
+
if (!existsSync(p))
|
|
99
|
+
return null;
|
|
100
|
+
return JSON.parse(readFileSync(p, 'utf-8'));
|
|
101
|
+
}
|
|
102
|
+
catch {
|
|
103
|
+
return null;
|
|
104
|
+
}
|
|
105
|
+
}
|
|
106
|
+
function listAllJobs() {
|
|
107
|
+
try {
|
|
108
|
+
ensureStateDir();
|
|
109
|
+
return readdirSync(TEAM_STATE_DIR)
|
|
110
|
+
.filter(f => f.endsWith('.json'))
|
|
111
|
+
.flatMap(f => {
|
|
112
|
+
try {
|
|
113
|
+
return [JSON.parse(readFileSync(join(TEAM_STATE_DIR, f), 'utf-8'))];
|
|
114
|
+
}
|
|
115
|
+
catch {
|
|
116
|
+
return [];
|
|
117
|
+
}
|
|
118
|
+
});
|
|
119
|
+
}
|
|
120
|
+
catch {
|
|
121
|
+
return [];
|
|
122
|
+
}
|
|
123
|
+
}
|
|
124
|
+
function resolveJobs(teamName, jobId) {
|
|
125
|
+
if (teamName) {
|
|
126
|
+
const j = loadJobState(teamName);
|
|
127
|
+
return j ? [j] : [];
|
|
128
|
+
}
|
|
129
|
+
if (jobId) {
|
|
130
|
+
const j = listAllJobs().find(x => x.jobId === jobId);
|
|
131
|
+
return j ? [j] : [];
|
|
132
|
+
}
|
|
133
|
+
return listAllJobs();
|
|
134
|
+
}
|
|
135
|
+
// ── Tool registration ─────────────────────────────────────────────────────
|
|
136
|
+
export function registerTeamWorkerTools(ctx) {
|
|
137
|
+
const { server } = ctx;
|
|
138
|
+
server.tool('merlin_spawn_workers', 'Spawn parallel AI CLI workers in tmux panes for burst execution. Each worker gets its own ' +
|
|
139
|
+
'tmux pane running a claude/codex/gemini CLI instance. Use for maximum parallelism on ' +
|
|
140
|
+
'independent tasks. Persists job state for status queries and cleanup. ' +
|
|
141
|
+
'Requires tmux. Returns jobId and per-worker pane assignments.', {
|
|
142
|
+
workers: z.array(z.object({
|
|
143
|
+
provider: z.enum(['claude', 'codex', 'gemini']).default('claude'),
|
|
144
|
+
task: z.string().describe('Task or prompt for this worker'),
|
|
145
|
+
agent: z.string().optional().describe('For claude: agent name (e.g. implementation-dev)'),
|
|
146
|
+
})).min(1).describe('Workers to spawn'),
|
|
147
|
+
teamName: z.string().optional().default('merlin-team').describe('Logical team name for state tracking'),
|
|
148
|
+
sessionName: z.string().optional().describe('tmux session name — defaults to teamName'),
|
|
149
|
+
}, async ({ workers, teamName, sessionName }) => {
|
|
150
|
+
const resolvedTeam = teamName ?? 'merlin-team';
|
|
151
|
+
const tmuxSession = sessionName ?? resolvedTeam;
|
|
152
|
+
if (!(await isTmuxAvailable())) {
|
|
153
|
+
return {
|
|
154
|
+
content: [{ type: 'text',
|
|
155
|
+
text: 'tmux not found. Install: macOS `brew install tmux` / Linux `apt install tmux`' }],
|
|
156
|
+
isError: true,
|
|
157
|
+
};
|
|
158
|
+
}
|
|
159
|
+
if (!(await ensureTmuxSession(tmuxSession))) {
|
|
160
|
+
return {
|
|
161
|
+
content: [{ type: 'text', text: `Failed to create tmux session "${tmuxSession}".` }],
|
|
162
|
+
isError: true,
|
|
163
|
+
};
|
|
164
|
+
}
|
|
165
|
+
const jobId = generateJobId();
|
|
166
|
+
const workerStates = [];
|
|
167
|
+
const errors = [];
|
|
168
|
+
for (const w of workers) {
|
|
169
|
+
try {
|
|
170
|
+
const paneId = await createTmuxPane(tmuxSession, buildProviderCommand(w.provider, w.task, w.agent));
|
|
171
|
+
workerStates.push({ paneId, provider: w.provider, task: w.task, agent: w.agent, status: 'running' });
|
|
172
|
+
}
|
|
173
|
+
catch (err) {
|
|
174
|
+
errors.push(`${w.provider} / ${w.task.slice(0, 40)}: ${err instanceof Error ? err.message : String(err)}`);
|
|
175
|
+
}
|
|
176
|
+
}
|
|
177
|
+
saveJobState({ jobId, teamName: resolvedTeam, tmuxSession, workers: workerStates, startedAt: new Date().toISOString() });
|
|
178
|
+
const lines = [
|
|
179
|
+
`Team spawned — jobId: ${jobId}`,
|
|
180
|
+
`tmux session: ${tmuxSession}`,
|
|
181
|
+
`workers started: ${workerStates.length} / ${workers.length}`,
|
|
182
|
+
'',
|
|
183
|
+
'Workers:',
|
|
184
|
+
...workerStates.map((w, i) => ` [${i + 1}] pane=${w.paneId} provider=${w.provider}${w.agent ? ` agent=${w.agent}` : ''} task="${w.task.slice(0, 60)}"`),
|
|
185
|
+
...(errors.length ? ['', 'Errors:', ...errors.map(e => ` ! ${e}`)] : []),
|
|
186
|
+
'',
|
|
187
|
+
`Status: merlin_team_status(teamName="${resolvedTeam}")`,
|
|
188
|
+
`Attach: tmux attach-session -t ${tmuxSession}`,
|
|
189
|
+
`Cleanup: merlin_team_cleanup(teamName="${resolvedTeam}")`,
|
|
190
|
+
];
|
|
191
|
+
return { content: [{ type: 'text', text: lines.join('\n') }] };
|
|
192
|
+
});
|
|
193
|
+
server.tool('merlin_team_status', 'Check status of running tmux team workers. Shows pane liveness and captures recent terminal ' +
|
|
194
|
+
'output per worker. Provide teamName or jobId to target a specific job; omit both for all jobs.', {
|
|
195
|
+
teamName: z.string().optional().describe('Team name used at spawn time'),
|
|
196
|
+
jobId: z.string().optional().describe('Specific job ID'),
|
|
197
|
+
}, async ({ teamName, jobId }) => {
|
|
198
|
+
const jobs = resolveJobs(teamName, jobId);
|
|
199
|
+
if (jobs.length === 0) {
|
|
200
|
+
return { content: [{ type: 'text', text: 'No team jobs found. Use merlin_spawn_workers first.' }] };
|
|
201
|
+
}
|
|
202
|
+
const sections = [];
|
|
203
|
+
for (const job of jobs) {
|
|
204
|
+
sections.push(`Job: ${job.jobId} team: ${job.teamName} session: ${job.tmuxSession}`);
|
|
205
|
+
sections.push(`Started: ${job.startedAt}`, '');
|
|
206
|
+
for (const [i, worker] of job.workers.entries()) {
|
|
207
|
+
const alive = await isPaneAlive(worker.paneId);
|
|
208
|
+
sections.push(`Worker ${i + 1}: pane=${worker.paneId} status=${alive ? 'running' : 'completed/dead'}`);
|
|
209
|
+
sections.push(` provider=${worker.provider}${worker.agent ? ` agent=${worker.agent}` : ''}`);
|
|
210
|
+
sections.push(` task="${worker.task.slice(0, 80)}"`);
|
|
211
|
+
const out = (await capturePaneOutput(worker.paneId, 50)).trim();
|
|
212
|
+
if (out) {
|
|
213
|
+
sections.push(' --- recent output ---');
|
|
214
|
+
out.split('\n').slice(-20).forEach(l => sections.push(` ${l}`));
|
|
215
|
+
sections.push(' ---');
|
|
216
|
+
}
|
|
217
|
+
sections.push('');
|
|
218
|
+
}
|
|
219
|
+
}
|
|
220
|
+
return { content: [{ type: 'text', text: sections.join('\n') }] };
|
|
221
|
+
});
|
|
222
|
+
server.tool('merlin_team_cleanup', 'Clean up tmux team workers — kills panes and removes persisted job state. ' +
|
|
223
|
+
'Optionally kills the entire tmux session. Omit teamName/jobId to clean up all jobs.', {
|
|
224
|
+
teamName: z.string().optional().describe('Team name used at spawn time'),
|
|
225
|
+
jobId: z.string().optional().describe('Specific job ID'),
|
|
226
|
+
killSession: z.boolean().optional().default(false).describe('Kill the entire tmux session instead of individual panes'),
|
|
227
|
+
}, async ({ teamName, jobId, killSession }) => {
|
|
228
|
+
const jobs = resolveJobs(teamName, jobId);
|
|
229
|
+
if (jobs.length === 0) {
|
|
230
|
+
return { content: [{ type: 'text', text: 'No team jobs found. Nothing to clean up.' }] };
|
|
231
|
+
}
|
|
232
|
+
const report = [];
|
|
233
|
+
for (const job of jobs) {
|
|
234
|
+
report.push(`Cleaning job: ${job.jobId} team: ${job.teamName}`);
|
|
235
|
+
if (killSession) {
|
|
236
|
+
try {
|
|
237
|
+
await execFileAsync('tmux', ['kill-session', '-t', job.tmuxSession]);
|
|
238
|
+
report.push(` session "${job.tmuxSession}" killed`);
|
|
239
|
+
}
|
|
240
|
+
catch {
|
|
241
|
+
report.push(` session "${job.tmuxSession}" already gone`);
|
|
242
|
+
}
|
|
243
|
+
}
|
|
244
|
+
else {
|
|
245
|
+
for (const w of job.workers) {
|
|
246
|
+
try {
|
|
247
|
+
await execFileAsync('tmux', ['kill-pane', '-t', w.paneId]);
|
|
248
|
+
report.push(` pane ${w.paneId} killed`);
|
|
249
|
+
}
|
|
250
|
+
catch {
|
|
251
|
+
report.push(` pane ${w.paneId} already gone`);
|
|
252
|
+
}
|
|
253
|
+
}
|
|
254
|
+
}
|
|
255
|
+
try {
|
|
256
|
+
const p = stateFilePath(job.teamName);
|
|
257
|
+
if (existsSync(p)) {
|
|
258
|
+
unlinkSync(p);
|
|
259
|
+
report.push(' state file removed');
|
|
260
|
+
}
|
|
261
|
+
}
|
|
262
|
+
catch {
|
|
263
|
+
report.push(' warning: could not remove state file');
|
|
264
|
+
}
|
|
265
|
+
report.push('');
|
|
266
|
+
}
|
|
267
|
+
report.push('Cleanup complete.');
|
|
268
|
+
return { content: [{ type: 'text', text: report.join('\n') }] };
|
|
269
|
+
});
|
|
270
|
+
}
|
|
271
|
+
//# sourceMappingURL=team-workers.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"team-workers.js","sourceRoot":"","sources":["../../../src/server/tools/team-workers.ts"],"names":[],"mappings":"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"}
|