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.
Files changed (76) hide show
  1. package/README.md +22 -4
  2. package/bin/merlin-ask.cjs +111 -0
  3. package/bin/merlin-cli.cjs +22 -0
  4. package/bin/runtime-adapters.cjs +678 -28
  5. package/dist/server/api/client.d.ts +2 -0
  6. package/dist/server/api/client.d.ts.map +1 -1
  7. package/dist/server/api/client.js +4 -0
  8. package/dist/server/api/client.js.map +1 -1
  9. package/dist/server/server.d.ts.map +1 -1
  10. package/dist/server/server.js +45 -4
  11. package/dist/server/server.js.map +1 -1
  12. package/dist/server/tools/auto-mode.d.ts +9 -0
  13. package/dist/server/tools/auto-mode.d.ts.map +1 -0
  14. package/dist/server/tools/auto-mode.js +231 -0
  15. package/dist/server/tools/auto-mode.js.map +1 -0
  16. package/dist/server/tools/computer-use.d.ts +8 -0
  17. package/dist/server/tools/computer-use.d.ts.map +1 -0
  18. package/dist/server/tools/computer-use.js +355 -0
  19. package/dist/server/tools/computer-use.js.map +1 -0
  20. package/dist/server/tools/dream.d.ts +9 -0
  21. package/dist/server/tools/dream.d.ts.map +1 -0
  22. package/dist/server/tools/dream.js +246 -0
  23. package/dist/server/tools/dream.js.map +1 -0
  24. package/dist/server/tools/hud.d.ts +13 -0
  25. package/dist/server/tools/hud.d.ts.map +1 -0
  26. package/dist/server/tools/hud.js +295 -0
  27. package/dist/server/tools/hud.js.map +1 -0
  28. package/dist/server/tools/index.d.ts +4 -0
  29. package/dist/server/tools/index.d.ts.map +1 -1
  30. package/dist/server/tools/index.js +4 -0
  31. package/dist/server/tools/index.js.map +1 -1
  32. package/dist/server/tools/provider-ask.d.ts +10 -0
  33. package/dist/server/tools/provider-ask.d.ts.map +1 -0
  34. package/dist/server/tools/provider-ask.js +234 -0
  35. package/dist/server/tools/provider-ask.js.map +1 -0
  36. package/dist/server/tools/rate-limit.d.ts +8 -0
  37. package/dist/server/tools/rate-limit.d.ts.map +1 -0
  38. package/dist/server/tools/rate-limit.js +184 -0
  39. package/dist/server/tools/rate-limit.js.map +1 -0
  40. package/dist/server/tools/skills.d.ts +16 -0
  41. package/dist/server/tools/skills.d.ts.map +1 -0
  42. package/dist/server/tools/skills.js +326 -0
  43. package/dist/server/tools/skills.js.map +1 -0
  44. package/dist/server/tools/team-workers.d.ts +7 -0
  45. package/dist/server/tools/team-workers.d.ts.map +1 -0
  46. package/dist/server/tools/team-workers.js +271 -0
  47. package/dist/server/tools/team-workers.js.map +1 -0
  48. package/dist/server/utils/merlin-manifest.d.ts +6 -1
  49. package/dist/server/utils/merlin-manifest.d.ts.map +1 -1
  50. package/dist/server/utils/merlin-manifest.js +34 -1
  51. package/dist/server/utils/merlin-manifest.js.map +1 -1
  52. package/files/CLAUDE.md +22 -0
  53. package/files/hooks/rate-limit-watch.sh +120 -0
  54. package/files/hooks/statusline.sh +148 -0
  55. package/files/merlin/skills/SKILLS-INDEX.md +82 -0
  56. package/files/merlin/skills/automation/payments.md +14 -0
  57. package/files/merlin/skills/automation/webhooks.md +14 -0
  58. package/files/merlin/skills/coding/accessibility.md +14 -0
  59. package/files/merlin/skills/coding/api-design.md +14 -0
  60. package/files/merlin/skills/coding/debug-mode.md +14 -0
  61. package/files/merlin/skills/coding/focus-mode.md +14 -0
  62. package/files/merlin/skills/coding/loop.md +14 -0
  63. package/files/merlin/skills/coding/performance.md +14 -0
  64. package/files/merlin/skills/coding/react-patterns.md +51 -0
  65. package/files/merlin/skills/coding/security-hardening.md +56 -0
  66. package/files/merlin/skills/coding/verify.md +14 -0
  67. package/files/merlin/skills/communication/dispatcher.md +40 -0
  68. package/files/merlin/skills/communication/email-gmail.md +31 -0
  69. package/files/merlin/skills/communication/telegram.md +50 -0
  70. package/files/merlin/skills/communication/whatsapp.md +47 -0
  71. package/files/merlin/skills/data/google-sheets.md +14 -0
  72. package/files/merlin/skills/design/animation.md +14 -0
  73. package/files/merlin/skills/devops/docker-containers.md +14 -0
  74. package/files/merlin/skills/research/brainstorm.md +14 -0
  75. package/files/merlin/skills/testing/tdd-workflow.md +58 -0
  76. package/package.json +4 -2
@@ -0,0 +1,10 @@
1
+ /**
2
+ * Multi-Provider CLI Orchestration Tools
3
+ *
4
+ * Delegate tasks to external AI CLI tools (claude, codex, gemini) and
5
+ * capture their output as artifacts. Supports parallel synthesis across
6
+ * multiple providers for second opinions and architectural decisions.
7
+ */
8
+ import type { ToolContext } from './types.js';
9
+ export declare function registerProviderTools(ctx: ToolContext): void;
10
+ //# sourceMappingURL=provider-ask.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"provider-ask.d.ts","sourceRoot":"","sources":["../../../src/server/tools/provider-ask.ts"],"names":[],"mappings":"AAAA;;;;;;GAMG;AAOH,OAAO,KAAK,EAAE,WAAW,EAAE,MAAM,YAAY,CAAC;AAsN9C,wBAAgB,qBAAqB,CAAC,GAAG,EAAE,WAAW,GAAG,IAAI,CA0F5D"}
@@ -0,0 +1,234 @@
1
+ /**
2
+ * Multi-Provider CLI Orchestration Tools
3
+ *
4
+ * Delegate tasks to external AI CLI tools (claude, codex, gemini) and
5
+ * capture their output as artifacts. Supports parallel synthesis across
6
+ * multiple providers for second opinions and architectural decisions.
7
+ */
8
+ import { z } from 'zod';
9
+ import { spawn } from 'child_process';
10
+ import { existsSync, mkdirSync, writeFileSync } from 'fs';
11
+ import { join } from 'path';
12
+ import { homedir } from 'os';
13
+ // ── Constants ─────────────────────────────────────────────────────────────────
14
+ const ARTIFACTS_DIR = join(homedir(), '.merlin', 'artifacts', 'ask');
15
+ // ── Helpers ───────────────────────────────────────────────────────────────────
16
+ /** Build the shell command array for a given provider. */
17
+ function buildCommand(provider, prompt) {
18
+ switch (provider) {
19
+ case 'claude':
20
+ return ['claude', '-p', prompt, '--output-format', 'text'];
21
+ case 'codex':
22
+ return ['codex', 'exec', prompt];
23
+ case 'gemini':
24
+ return ['gemini', '-p', prompt];
25
+ }
26
+ }
27
+ /** Check whether a CLI binary exists on PATH. */
28
+ async function isBinaryAvailable(bin) {
29
+ return new Promise((resolve) => {
30
+ const proc = spawn('which', [bin], { stdio: 'pipe' });
31
+ proc.on('close', (code) => resolve(code === 0));
32
+ proc.on('error', () => resolve(false));
33
+ });
34
+ }
35
+ /** Build a URL-friendly slug from a prompt string. */
36
+ function slugify(text) {
37
+ return text
38
+ .toLowerCase()
39
+ .replace(/[^a-z0-9\s-]/g, '')
40
+ .trim()
41
+ .replace(/\s+/g, '-')
42
+ .slice(0, 40);
43
+ }
44
+ /** Ensure the artifacts directory exists. */
45
+ function ensureArtifactsDir() {
46
+ if (!existsSync(ARTIFACTS_DIR)) {
47
+ mkdirSync(ARTIFACTS_DIR, { recursive: true });
48
+ }
49
+ }
50
+ /** Save the result to a markdown artifact file. Returns the path. */
51
+ function saveArtifact(provider, prompt, output, exitCode, timestamp) {
52
+ ensureArtifactsDir();
53
+ const slug = slugify(prompt);
54
+ const filename = `${provider}-${slug}-${timestamp}.md`;
55
+ const filePath = join(ARTIFACTS_DIR, filename);
56
+ const content = [
57
+ `# Provider Ask — ${provider}`,
58
+ '',
59
+ `**Timestamp:** ${timestamp}`,
60
+ `**Exit Code:** ${exitCode}`,
61
+ '',
62
+ '## Prompt',
63
+ '',
64
+ prompt,
65
+ '',
66
+ '## Output',
67
+ '',
68
+ output || '_(no output)_',
69
+ ].join('\n');
70
+ writeFileSync(filePath, content, 'utf-8');
71
+ return filePath;
72
+ }
73
+ /** Spawn one provider CLI and return its result. */
74
+ async function runProvider(provider, prompt, agentPrompt, timeoutMs, timestamp) {
75
+ const startTime = Date.now();
76
+ const available = await isBinaryAvailable(provider === 'claude' ? 'claude' : provider);
77
+ if (!available) {
78
+ return {
79
+ provider,
80
+ output: '',
81
+ exitCode: -1,
82
+ durationMs: 0,
83
+ artifactPath: null,
84
+ error: `CLI not found: '${provider}' is not installed or not on PATH. Install it and try again.`,
85
+ };
86
+ }
87
+ const fullPrompt = agentPrompt ? `${agentPrompt}\n\n${prompt}` : prompt;
88
+ const cmdArgs = buildCommand(provider, fullPrompt);
89
+ const [cmd, ...args] = cmdArgs;
90
+ // Strip env vars known to interfere with Codex
91
+ const env = { ...process.env };
92
+ if (provider === 'codex') {
93
+ delete env['RUST_LOG'];
94
+ delete env['RUST_BACKTRACE'];
95
+ }
96
+ return new Promise((resolve) => {
97
+ const stdoutChunks = [];
98
+ const stderrChunks = [];
99
+ const proc = spawn(cmd, args, {
100
+ stdio: ['ignore', 'pipe', 'pipe'],
101
+ env,
102
+ });
103
+ proc.stdout.on('data', (chunk) => stdoutChunks.push(chunk));
104
+ proc.stderr.on('data', (chunk) => stderrChunks.push(chunk));
105
+ let timedOut = false;
106
+ const timer = setTimeout(() => {
107
+ timedOut = true;
108
+ proc.kill('SIGTERM');
109
+ }, timeoutMs);
110
+ proc.on('close', (code) => {
111
+ clearTimeout(timer);
112
+ const durationMs = Date.now() - startTime;
113
+ const output = Buffer.concat(stdoutChunks).toString('utf-8').trim();
114
+ const stderr = Buffer.concat(stderrChunks).toString('utf-8').trim();
115
+ const exitCode = timedOut ? 124 : (code ?? -1);
116
+ let error = null;
117
+ if (timedOut) {
118
+ error = `Timed out after ${timeoutMs / 1000}s`;
119
+ }
120
+ else if (exitCode !== 0 && !output) {
121
+ error = stderr || `Process exited with code ${exitCode}`;
122
+ }
123
+ const artifactPath = saveArtifact(provider, prompt, output || stderr, exitCode, timestamp);
124
+ resolve({ provider, output: output || stderr, exitCode, durationMs, artifactPath, error });
125
+ });
126
+ proc.on('error', (err) => {
127
+ clearTimeout(timer);
128
+ resolve({
129
+ provider,
130
+ output: '',
131
+ exitCode: -1,
132
+ durationMs: Date.now() - startTime,
133
+ artifactPath: null,
134
+ error: `Failed to spawn process: ${err.message}`,
135
+ });
136
+ });
137
+ });
138
+ }
139
+ /** Format a single provider result for display. */
140
+ function formatResult(result) {
141
+ const statusLine = result.error
142
+ ? `Status: ERROR — ${result.error}`
143
+ : `Status: OK (exit ${result.exitCode}, ${result.durationMs}ms)`;
144
+ const artifactLine = result.artifactPath ? `Artifact: ${result.artifactPath}` : '';
145
+ const lines = [
146
+ `## ${result.provider.toUpperCase()}`,
147
+ statusLine,
148
+ artifactLine,
149
+ '',
150
+ result.error && !result.output ? '_No output._' : result.output,
151
+ ].filter((l) => l !== undefined);
152
+ return lines.join('\n');
153
+ }
154
+ /** Build a comparison table from multiple results. */
155
+ function buildSynthesis(results, prompt) {
156
+ const rows = results.map((r) => {
157
+ const status = r.error ? 'ERROR' : 'OK';
158
+ const preview = (r.output || '').slice(0, 120).replace(/\n/g, ' ');
159
+ return `| ${r.provider} | ${status} | ${r.durationMs}ms | ${preview}... |`;
160
+ });
161
+ return [
162
+ '## Synthesis Comparison',
163
+ '',
164
+ `**Prompt:** ${prompt}`,
165
+ '',
166
+ '| Provider | Status | Duration | Output Preview |',
167
+ '|----------|--------|----------|----------------|',
168
+ ...rows,
169
+ '',
170
+ '### Full Outputs',
171
+ '',
172
+ ...results.map(formatResult),
173
+ ].join('\n');
174
+ }
175
+ // ── Tool Registration ─────────────────────────────────────────────────────────
176
+ export function registerProviderTools(ctx) {
177
+ const { server } = ctx;
178
+ // ── merlin_ask_provider ───────────────────────────────────────────────────
179
+ server.tool('merlin_ask_provider', 'Delegate a task to an external AI CLI provider (claude, codex, or gemini) and capture the result. ' +
180
+ 'Use for multi-model synthesis, second opinions, or leveraging provider-specific strengths. ' +
181
+ 'Automatically detects if the CLI is installed and saves an artifact to ~/.merlin/artifacts/ask/. ' +
182
+ 'Returns the full output text so Merlin can incorporate it into orchestration decisions.', {
183
+ provider: z.enum(['claude', 'codex', 'gemini']).describe('Which AI CLI to invoke: claude (Claude Code), codex (OpenAI Codex CLI), or gemini (Google Gemini CLI)'),
184
+ prompt: z.string().describe('The task or question to send to the provider'),
185
+ agentPrompt: z.string().optional().describe('Optional role/persona template to prepend before the main prompt (e.g., "You are a senior security engineer.")'),
186
+ timeoutSeconds: z.number().optional().default(120).describe('Maximum seconds to wait for the provider to respond (default: 120)'),
187
+ }, async ({ provider, prompt, agentPrompt, timeoutSeconds }) => {
188
+ const timeoutMs = (timeoutSeconds ?? 120) * 1000;
189
+ const timestamp = new Date().toISOString().replace(/[:.]/g, '-');
190
+ const result = await runProvider(provider, prompt, agentPrompt, timeoutMs, timestamp);
191
+ if (result.error && !result.output) {
192
+ return {
193
+ content: [
194
+ {
195
+ type: 'text',
196
+ text: `Provider ask failed — ${provider}: ${result.error}`,
197
+ },
198
+ ],
199
+ isError: true,
200
+ };
201
+ }
202
+ const text = [
203
+ formatResult(result),
204
+ result.artifactPath ? `\nArtifact saved to: ${result.artifactPath}` : '',
205
+ ]
206
+ .join('\n')
207
+ .trim();
208
+ return { content: [{ type: 'text', text }] };
209
+ });
210
+ // ── merlin_ask_synthesis ──────────────────────────────────────────────────
211
+ server.tool('merlin_ask_synthesis', 'Run the same prompt through multiple AI CLI providers in parallel and synthesize the results. ' +
212
+ 'Ideal for architecture decisions, code review, security analysis, or any task where multiple perspectives add value. ' +
213
+ 'Returns a comparison table plus each provider\'s full output. ' +
214
+ 'Artifacts for each provider are saved to ~/.merlin/artifacts/ask/.', {
215
+ providers: z.array(z.enum(['claude', 'codex', 'gemini'])).describe('Which AI CLIs to query in parallel — all must be installed locally'),
216
+ prompt: z.string().describe('The task or question to send to all providers'),
217
+ synthesize: z.boolean().optional().default(true).describe('When true (default), includes a comparison table at the top of the response'),
218
+ }, async ({ providers, prompt, synthesize }) => {
219
+ if (providers.length === 0) {
220
+ return {
221
+ content: [{ type: 'text', text: 'No providers specified. Pass at least one of: claude, codex, gemini.' }],
222
+ isError: true,
223
+ };
224
+ }
225
+ const timeoutMs = 180 * 1000; // synthesis allows longer per-provider timeout
226
+ const timestamp = new Date().toISOString().replace(/[:.]/g, '-');
227
+ const results = await Promise.all(providers.map((p) => runProvider(p, prompt, undefined, timeoutMs, timestamp)));
228
+ const text = synthesize !== false
229
+ ? buildSynthesis(results, prompt)
230
+ : results.map(formatResult).join('\n\n---\n\n');
231
+ return { content: [{ type: 'text', text }] };
232
+ });
233
+ }
234
+ //# sourceMappingURL=provider-ask.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"provider-ask.js","sourceRoot":"","sources":["../../../src/server/tools/provider-ask.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,8 @@
1
+ /**
2
+ * Rate Limit Tools
3
+ * Monitor Claude/provider rate-limit state and configure auto-resume behavior.
4
+ * State is written by the rate-limit-watch.sh PostToolUse hook.
5
+ */
6
+ import type { ToolContext } from './types.js';
7
+ export declare function registerRateLimitTools(ctx: ToolContext): void;
8
+ //# sourceMappingURL=rate-limit.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"rate-limit.d.ts","sourceRoot":"","sources":["../../../src/server/tools/rate-limit.ts"],"names":[],"mappings":"AAAA;;;;GAIG;AAMH,OAAO,KAAK,EAAE,WAAW,EAAE,MAAM,YAAY,CAAC;AA0G9C,wBAAgB,sBAAsB,CAAC,GAAG,EAAE,WAAW,GAAG,IAAI,CA8H7D"}
@@ -0,0 +1,184 @@
1
+ /**
2
+ * Rate Limit Tools
3
+ * Monitor Claude/provider rate-limit state and configure auto-resume behavior.
4
+ * State is written by the rate-limit-watch.sh PostToolUse hook.
5
+ */
6
+ import { z } from 'zod';
7
+ import { existsSync, readFileSync, writeFileSync, mkdirSync } from 'fs';
8
+ import { join } from 'path';
9
+ import { homedir } from 'os';
10
+ import { coachWrap } from '../session-coach.js';
11
+ const STATE_DIR = join(homedir(), '.merlin', 'state');
12
+ const RATE_LIMIT_STATE_FILE = join(STATE_DIR, 'rate-limit.json');
13
+ const SESSION_COST_FILE = join(STATE_DIR, 'session-cost.json');
14
+ const CONFIG_FILE = join(STATE_DIR, 'rate-limit-config.json');
15
+ /** Default config values */
16
+ const DEFAULTS = {
17
+ warningThreshold: 80,
18
+ autoResume: true,
19
+ cooldownMinutes: 2,
20
+ notifyDesktop: true,
21
+ };
22
+ // ── Helpers ──────────────────────────────────────────────────────────────────
23
+ function readJson(filePath) {
24
+ try {
25
+ if (!existsSync(filePath))
26
+ return null;
27
+ return JSON.parse(readFileSync(filePath, 'utf-8'));
28
+ }
29
+ catch {
30
+ return null;
31
+ }
32
+ }
33
+ function ensureStateDir() {
34
+ if (!existsSync(STATE_DIR)) {
35
+ mkdirSync(STATE_DIR, { recursive: true });
36
+ }
37
+ }
38
+ function readConfig() {
39
+ const saved = readJson(CONFIG_FILE);
40
+ return {
41
+ warningThreshold: saved?.warningThreshold ?? DEFAULTS.warningThreshold,
42
+ autoResume: saved?.autoResume ?? DEFAULTS.autoResume,
43
+ cooldownMinutes: saved?.cooldownMinutes ?? DEFAULTS.cooldownMinutes,
44
+ notifyDesktop: saved?.notifyDesktop ?? DEFAULTS.notifyDesktop,
45
+ };
46
+ }
47
+ /** Seconds until the estimated reset time (negative = already passed) */
48
+ function secondsUntilReset(estimatedResetAt) {
49
+ try {
50
+ const resetMs = new Date(estimatedResetAt).getTime();
51
+ return Math.round((resetMs - Date.now()) / 1000);
52
+ }
53
+ catch {
54
+ return 0;
55
+ }
56
+ }
57
+ /** Seconds since a given ISO timestamp */
58
+ function secondsSince(isoTs) {
59
+ try {
60
+ return Math.round((Date.now() - new Date(isoTs).getTime()) / 1000);
61
+ }
62
+ catch {
63
+ return 0;
64
+ }
65
+ }
66
+ /** Determine effective status including cooldown transition */
67
+ function effectiveStatus(state, config, usagePercent) {
68
+ if (state?.status === 'blocked')
69
+ return 'blocked';
70
+ // Cooldown: recently cleared within cooldownMinutes window
71
+ if (state?.status === 'ok' && state.clearedAt) {
72
+ const elapsed = secondsSince(state.clearedAt);
73
+ if (elapsed < config.cooldownMinutes * 60)
74
+ return 'cooldown';
75
+ }
76
+ if (usagePercent >= config.warningThreshold)
77
+ return 'warning';
78
+ return 'ok';
79
+ }
80
+ // ── Tool registration ─────────────────────────────────────────────────────────
81
+ export function registerRateLimitTools(ctx) {
82
+ const { server } = ctx;
83
+ // ── merlin_rate_limit_status ────────────────────────────────────────────────
84
+ server.tool('merlin_rate_limit_status', 'Check current rate limit status across providers. Returns current state (ok/warning/blocked/cooldown), time until reset, and session usage metrics. Use before spawning agents to decide whether to throttle. Blocked = stop spawning. Warning = spawn cautiously. Cooldown = recently unblocked, proceed slowly.', {}, async () => {
85
+ try {
86
+ const state = readJson(RATE_LIMIT_STATE_FILE);
87
+ const cost = readJson(SESSION_COST_FILE);
88
+ const config = readConfig();
89
+ const usagePercent = cost?.usagePercent ?? 0;
90
+ const status = effectiveStatus(state, config, usagePercent);
91
+ let statusLine = '';
92
+ let recommendation = '';
93
+ let resetInfo = '';
94
+ if (status === 'blocked') {
95
+ const secsLeft = state?.estimatedResetAt ? secondsUntilReset(state.estimatedResetAt) : 0;
96
+ const minsLeft = secsLeft > 0 ? Math.ceil(secsLeft / 60) : 0;
97
+ resetInfo = secsLeft > 0
98
+ ? `Estimated reset: ~${minsLeft} min (${state.estimatedResetAt})`
99
+ : `Reset time has passed — state may clear on next tool call`;
100
+ statusLine = `**Status: BLOCKED** (trigger: ${state?.trigger ?? 'unknown'})`;
101
+ recommendation = config.autoResume
102
+ ? `Auto-resume is enabled. Do not spawn new agents. Wait ${minsLeft > 0 ? `~${minsLeft} min` : 'for the next tool call to clear state'}.`
103
+ : 'Auto-resume is disabled. Manually call merlin_rate_limit_status again after waiting.';
104
+ }
105
+ else if (status === 'cooldown') {
106
+ const elapsed = state?.clearedAt ? secondsSince(state.clearedAt) : 0;
107
+ const remaining = Math.max(0, config.cooldownMinutes * 60 - elapsed);
108
+ statusLine = `**Status: COOLDOWN** (${Math.ceil(remaining / 60)} min remaining)`;
109
+ recommendation = 'Recently unblocked. Proceed cautiously — spawn agents at reduced rate.';
110
+ }
111
+ else if (status === 'warning') {
112
+ statusLine = `**Status: WARNING** (${usagePercent}% usage — threshold: ${config.warningThreshold}%)`;
113
+ recommendation = 'Approaching rate limits. Avoid spawning multiple parallel agents.';
114
+ }
115
+ else {
116
+ statusLine = `**Status: OK** (${usagePercent}% usage)`;
117
+ recommendation = 'Normal operations. No restrictions.';
118
+ }
119
+ const text = `
120
+ ${statusLine}
121
+
122
+ ${resetInfo ? `${resetInfo}\n` : ''}**Recommendation:** ${recommendation}
123
+
124
+ **Config:** warning at ${config.warningThreshold}% · auto-resume: ${config.autoResume} · cooldown: ${config.cooldownMinutes}min
125
+
126
+ To update these settings, call \`merlin_rate_limit_configure\`.
127
+ `.trim();
128
+ return {
129
+ content: [{ type: 'text', text: coachWrap('merlin_rate_limit_status', text) }],
130
+ };
131
+ }
132
+ catch (error) {
133
+ return {
134
+ content: [{
135
+ type: 'text',
136
+ text: `**Error reading rate limit state:** ${error instanceof Error ? error.message : 'Unknown error'}`,
137
+ }],
138
+ isError: true,
139
+ };
140
+ }
141
+ });
142
+ // ── merlin_rate_limit_configure ─────────────────────────────────────────────
143
+ server.tool('merlin_rate_limit_configure', 'Configure rate limit thresholds and auto-resume behavior for Merlin. Sets the warning percentage, whether blocked sessions auto-resume, cooldown duration after unblocking, and desktop notifications. Config is persisted to ~/.merlin/state/rate-limit-config.json.', {
144
+ warningThreshold: z.number().min(1).max(100).optional().describe('Usage percentage at which to warn (default: 80)'),
145
+ autoResume: z.boolean().optional().describe('Whether to auto-resume blocked sessions when the rate limit clears (default: true)'),
146
+ cooldownMinutes: z.number().min(0).max(60).optional().describe('Minutes to stay in cooldown after unblocking (default: 2)'),
147
+ notifyDesktop: z.boolean().optional().describe('Send macOS desktop notification when rate limit is detected (default: true)'),
148
+ }, async ({ warningThreshold, autoResume, cooldownMinutes, notifyDesktop }) => {
149
+ try {
150
+ ensureStateDir();
151
+ const current = readConfig();
152
+ const updated = {
153
+ warningThreshold: warningThreshold ?? current.warningThreshold,
154
+ autoResume: autoResume ?? current.autoResume,
155
+ cooldownMinutes: cooldownMinutes ?? current.cooldownMinutes,
156
+ notifyDesktop: notifyDesktop ?? current.notifyDesktop,
157
+ };
158
+ writeFileSync(CONFIG_FILE, JSON.stringify(updated, null, 2), 'utf-8');
159
+ const text = `
160
+ **Rate limit config updated**
161
+
162
+ - Warning threshold: ${updated.warningThreshold}%
163
+ - Auto-resume: ${updated.autoResume}
164
+ - Cooldown after unblock: ${updated.cooldownMinutes} min
165
+ - Desktop notifications: ${updated.notifyDesktop}
166
+
167
+ Saved to \`~/.merlin/state/rate-limit-config.json\`
168
+ `.trim();
169
+ return {
170
+ content: [{ type: 'text', text: coachWrap('merlin_rate_limit_configure', text) }],
171
+ };
172
+ }
173
+ catch (error) {
174
+ return {
175
+ content: [{
176
+ type: 'text',
177
+ text: `**Error saving rate limit config:** ${error instanceof Error ? error.message : 'Unknown error'}`,
178
+ }],
179
+ isError: true,
180
+ };
181
+ }
182
+ });
183
+ }
184
+ //# sourceMappingURL=rate-limit.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"rate-limit.js","sourceRoot":"","sources":["../../../src/server/tools/rate-limit.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,16 @@
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 type { ToolContext } from './types.js';
15
+ export declare function registerSkillsTools(ctx: ToolContext): void;
16
+ //# sourceMappingURL=skills.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"skills.d.ts","sourceRoot":"","sources":["../../../src/server/tools/skills.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;GAYG;AAMH,OAAO,KAAK,EAAE,WAAW,EAAE,MAAM,YAAY,CAAC;AA4H9C,wBAAgB,mBAAmB,CAAC,GAAG,EAAE,WAAW,GAAG,IAAI,CA0M1D"}