claude-code-workflow 6.0.4 → 6.1.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/agents/action-planning-agent.md +1 -1
- package/.claude/agents/cli-execution-agent.md +269 -269
- package/.claude/agents/cli-explore-agent.md +182 -182
- package/.claude/agents/context-search-agent.md +582 -582
- package/.claude/agents/memory-bridge.md +93 -93
- package/.claude/commands/cli/cli-init.md +1 -1
- package/.claude/commands/memory/docs-full-cli.md +471 -471
- package/.claude/commands/memory/docs-related-cli.md +386 -386
- package/.claude/commands/memory/docs.md +615 -615
- package/.claude/commands/memory/load.md +1 -1
- package/.claude/commands/memory/update-full.md +332 -332
- package/.claude/commands/memory/update-related.md +5 -5
- package/.claude/commands/workflow/init.md +1 -1
- package/.claude/commands/workflow/lite-fix.md +621 -621
- package/.claude/commands/workflow/lite-plan.md +592 -592
- package/.claude/commands/workflow/tools/context-gather.md +434 -434
- package/.claude/commands/workflow/ui-design/generate.md +504 -504
- package/.claude/commands/workflow/ui-design/import-from-code.md +537 -537
- package/.claude/scripts/classify-folders.sh +4 -0
- package/.claude/scripts/convert_tokens_to_css.sh +4 -0
- package/.claude/scripts/detect_changed_modules.sh +5 -1
- package/.claude/scripts/discover-design-files.sh +87 -83
- package/.claude/scripts/generate_module_docs.sh +717 -713
- package/.claude/scripts/get_modules_by_depth.sh +5 -1
- package/.claude/scripts/ui-generate-preview.sh +4 -0
- package/.claude/scripts/ui-instantiate-prototypes.sh +4 -0
- package/.claude/scripts/update_module_claude.sh +4 -0
- package/.claude/skills/command-guide/index/all-commands.json +1 -12
- package/.claude/skills/command-guide/index/by-category.json +1 -12
- package/.claude/skills/command-guide/index/by-use-case.json +1 -12
- package/.claude/skills/command-guide/index/essential-commands.json +1 -12
- package/.claude/skills/command-guide/reference/agents/action-planning-agent.md +127 -71
- package/.claude/skills/command-guide/reference/agents/cli-execution-agent.md +269 -269
- package/.claude/skills/command-guide/reference/agents/cli-explore-agent.md +182 -182
- package/.claude/skills/command-guide/reference/agents/conceptual-planning-agent.md +18 -38
- package/.claude/skills/command-guide/reference/agents/context-search-agent.md +582 -577
- package/.claude/skills/command-guide/reference/agents/memory-bridge.md +93 -93
- package/.claude/skills/command-guide/reference/commands/cli/cli-init.md +1 -1
- package/.claude/skills/command-guide/reference/commands/memory/docs-full-cli.md +471 -471
- package/.claude/skills/command-guide/reference/commands/memory/docs-related-cli.md +386 -386
- package/.claude/skills/command-guide/reference/commands/memory/docs.md +615 -610
- package/.claude/skills/command-guide/reference/commands/memory/load.md +1 -1
- package/.claude/skills/command-guide/reference/commands/memory/update-full.md +332 -332
- package/.claude/skills/command-guide/reference/commands/memory/update-related.md +5 -5
- package/.claude/skills/command-guide/reference/commands/workflow/brainstorm/artifacts.md +299 -451
- package/.claude/skills/command-guide/reference/commands/workflow/brainstorm/auto-parallel.md +14 -37
- package/.claude/skills/command-guide/reference/commands/workflow/brainstorm/synthesis.md +252 -350
- package/.claude/skills/command-guide/reference/commands/workflow/init.md +2 -2
- package/.claude/skills/command-guide/reference/commands/workflow/lite-execute.md +52 -0
- package/.claude/skills/command-guide/reference/commands/workflow/lite-fix.md +621 -602
- package/.claude/skills/command-guide/reference/commands/workflow/lite-plan.md +46 -36
- package/.claude/skills/command-guide/reference/commands/workflow/review-fix.md +18 -58
- package/.claude/skills/command-guide/reference/commands/workflow/review-module-cycle.md +22 -52
- package/.claude/skills/command-guide/reference/commands/workflow/review-session-cycle.md +19 -48
- package/.claude/skills/command-guide/reference/commands/workflow/session/start.md +25 -5
- package/.claude/skills/command-guide/reference/commands/workflow/tdd-plan.md +1 -1
- package/.claude/skills/command-guide/reference/commands/workflow/test-fix-gen.md +7 -7
- package/.claude/skills/command-guide/reference/commands/workflow/tools/context-gather.md +434 -434
- package/.claude/skills/command-guide/reference/commands/workflow/tools/task-generate-agent.md +151 -11
- package/.claude/skills/command-guide/reference/commands/workflow/tools/task-generate-tdd.md +4 -4
- package/.claude/skills/command-guide/reference/commands/workflow/tools/test-task-generate.md +1 -1
- package/.claude/skills/command-guide/reference/commands/workflow/ui-design/generate.md +504 -504
- package/.claude/skills/command-guide/reference/commands/workflow/ui-design/import-from-code.md +537 -537
- package/.claude/workflows/context-search-strategy.md +77 -77
- package/.claude/workflows/tool-strategy.md +90 -71
- package/.claude/workflows/workflow-architecture.md +1 -1
- package/ccw/package.json +6 -6
- package/ccw/src/cli.js +16 -0
- package/ccw/src/commands/stop.js +101 -0
- package/ccw/src/commands/tool.js +181 -0
- package/ccw/src/core/dashboard-generator.js +18 -3
- package/ccw/src/core/lite-scanner.js +35 -11
- package/ccw/src/core/server.js +583 -17
- package/ccw/src/templates/dashboard-css/01-base.css +161 -0
- package/ccw/src/templates/dashboard-css/02-session.css +726 -0
- package/ccw/src/templates/dashboard-css/03-tasks.css +512 -0
- package/ccw/src/templates/dashboard-css/04-lite-tasks.css +843 -0
- package/ccw/src/templates/dashboard-css/05-context.css +2206 -0
- package/ccw/src/templates/dashboard-css/06-cards.css +1570 -0
- package/ccw/src/templates/dashboard-css/07-managers.css +936 -0
- package/ccw/src/templates/dashboard-css/08-review.css +1266 -0
- package/ccw/src/templates/dashboard-css/09-explorer.css +1397 -0
- package/ccw/src/templates/dashboard-js/components/global-notifications.js +219 -0
- package/ccw/src/templates/dashboard-js/components/hook-manager.js +10 -0
- package/ccw/src/templates/dashboard-js/components/mcp-manager.js +24 -2
- package/ccw/src/templates/dashboard-js/components/navigation.js +11 -5
- package/ccw/src/templates/dashboard-js/components/tabs-context.js +20 -20
- package/ccw/src/templates/dashboard-js/components/tabs-other.js +11 -11
- package/ccw/src/templates/dashboard-js/components/theme.js +29 -1
- package/ccw/src/templates/dashboard-js/main.js +4 -0
- package/ccw/src/templates/dashboard-js/state.js +5 -0
- package/ccw/src/templates/dashboard-js/views/explorer.js +852 -0
- package/ccw/src/templates/dashboard-js/views/home.js +13 -9
- package/ccw/src/templates/dashboard-js/views/hook-manager.js +8 -5
- package/ccw/src/templates/dashboard-js/views/lite-tasks.js +21 -16
- package/ccw/src/templates/dashboard-js/views/mcp-manager.js +148 -8
- package/ccw/src/templates/dashboard-js/views/project-overview.js +15 -11
- package/ccw/src/templates/dashboard-js/views/review-session.js +3 -3
- package/ccw/src/templates/dashboard-js/views/session-detail.js +38 -28
- package/ccw/src/templates/dashboard.html +129 -28
- package/ccw/src/tools/classify-folders.js +204 -0
- package/ccw/src/tools/convert-tokens-to-css.js +250 -0
- package/ccw/src/tools/detect-changed-modules.js +288 -0
- package/ccw/src/tools/discover-design-files.js +134 -0
- package/ccw/src/tools/edit-file.js +266 -0
- package/ccw/src/tools/generate-module-docs.js +416 -0
- package/ccw/src/tools/get-modules-by-depth.js +308 -0
- package/ccw/src/tools/index.js +176 -0
- package/ccw/src/tools/ui-generate-preview.js +327 -0
- package/ccw/src/tools/ui-instantiate-prototypes.js +301 -0
- package/ccw/src/tools/update-module-claude.js +380 -0
- package/ccw/src/utils/browser-launcher.js +15 -4
- package/package.json +1 -1
- package/.claude/skills/command-guide/reference/commands/workflow/status.md +0 -352
- package/ccw/src/core/server.js.bak +0 -385
- package/ccw/src/core/server_original.bak +0 -385
- package/ccw/src/templates/dashboard.css +0 -8114
- package/ccw/src/templates/dashboard_tailwind.html +0 -42
- package/ccw/src/templates/dashboard_test.html +0 -37
- package/ccw/src/templates/tailwind-base.css +0 -212
|
@@ -0,0 +1,308 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Get Modules by Depth Tool
|
|
3
|
+
* Scan project structure and organize modules by directory depth (deepest first)
|
|
4
|
+
*/
|
|
5
|
+
|
|
6
|
+
import { readdirSync, statSync, existsSync, readFileSync } from 'fs';
|
|
7
|
+
import { join, resolve, relative, extname } from 'path';
|
|
8
|
+
|
|
9
|
+
// System/cache directories to always exclude
|
|
10
|
+
const SYSTEM_EXCLUDES = [
|
|
11
|
+
// Version control and IDE
|
|
12
|
+
'.git', '.gitignore', '.gitmodules', '.gitattributes',
|
|
13
|
+
'.svn', '.hg', '.bzr',
|
|
14
|
+
'.history', '.vscode', '.idea', '.vs', '.vscode-test',
|
|
15
|
+
'.sublime-text', '.atom',
|
|
16
|
+
// Python
|
|
17
|
+
'__pycache__', '.pytest_cache', '.mypy_cache', '.tox',
|
|
18
|
+
'.coverage', 'htmlcov', '.nox', '.venv', 'venv', 'env',
|
|
19
|
+
'.egg-info', '.eggs', '.wheel',
|
|
20
|
+
'site-packages', '.python-version',
|
|
21
|
+
// Node.js/JavaScript
|
|
22
|
+
'node_modules', '.npm', '.yarn', '.pnpm', 'yarn-error.log',
|
|
23
|
+
'.nyc_output', 'coverage', '.next', '.nuxt',
|
|
24
|
+
'.cache', '.parcel-cache', '.vite', 'dist', 'build',
|
|
25
|
+
'.turbo', '.vercel', '.netlify',
|
|
26
|
+
// Build/compile outputs
|
|
27
|
+
'out', 'output', '_site', 'public',
|
|
28
|
+
'.output', '.generated', 'generated', 'gen',
|
|
29
|
+
'bin', 'obj', 'Debug', 'Release',
|
|
30
|
+
// Testing
|
|
31
|
+
'test-results', 'junit.xml', 'test_results',
|
|
32
|
+
'cypress', 'playwright-report', '.playwright',
|
|
33
|
+
// Logs and temp files
|
|
34
|
+
'logs', 'log', 'tmp', 'temp', '.tmp', '.temp',
|
|
35
|
+
// Documentation build outputs
|
|
36
|
+
'_book', 'docs/_build', 'site', 'gh-pages',
|
|
37
|
+
'.docusaurus', '.vuepress', '.gitbook',
|
|
38
|
+
// Cloud and deployment
|
|
39
|
+
'.serverless', '.terraform',
|
|
40
|
+
'.aws', '.azure', '.gcp',
|
|
41
|
+
// Mobile development
|
|
42
|
+
'.gradle', '.expo', '.metro',
|
|
43
|
+
'DerivedData',
|
|
44
|
+
// Game development
|
|
45
|
+
'Library', 'Temp', 'ProjectSettings',
|
|
46
|
+
'MemoryCaptures', 'UserSettings'
|
|
47
|
+
];
|
|
48
|
+
|
|
49
|
+
/**
|
|
50
|
+
* Parse .gitignore file and return patterns
|
|
51
|
+
*/
|
|
52
|
+
function parseGitignore(basePath) {
|
|
53
|
+
const gitignorePath = join(basePath, '.gitignore');
|
|
54
|
+
const patterns = [];
|
|
55
|
+
|
|
56
|
+
if (existsSync(gitignorePath)) {
|
|
57
|
+
const content = readFileSync(gitignorePath, 'utf8');
|
|
58
|
+
content.split('\n').forEach(line => {
|
|
59
|
+
line = line.trim();
|
|
60
|
+
// Skip empty lines and comments
|
|
61
|
+
if (!line || line.startsWith('#')) return;
|
|
62
|
+
// Remove trailing slash
|
|
63
|
+
line = line.replace(/\/$/, '');
|
|
64
|
+
patterns.push(line);
|
|
65
|
+
});
|
|
66
|
+
}
|
|
67
|
+
|
|
68
|
+
return patterns;
|
|
69
|
+
}
|
|
70
|
+
|
|
71
|
+
/**
|
|
72
|
+
* Check if a path should be excluded
|
|
73
|
+
*/
|
|
74
|
+
function shouldExclude(name, gitignorePatterns) {
|
|
75
|
+
// Check system excludes
|
|
76
|
+
if (SYSTEM_EXCLUDES.includes(name)) return true;
|
|
77
|
+
|
|
78
|
+
// Check gitignore patterns (simple matching)
|
|
79
|
+
for (const pattern of gitignorePatterns) {
|
|
80
|
+
if (name === pattern) return true;
|
|
81
|
+
// Simple wildcard matching
|
|
82
|
+
if (pattern.includes('*')) {
|
|
83
|
+
const regex = new RegExp('^' + pattern.replace(/\*/g, '.*') + '$');
|
|
84
|
+
if (regex.test(name)) return true;
|
|
85
|
+
}
|
|
86
|
+
}
|
|
87
|
+
|
|
88
|
+
return false;
|
|
89
|
+
}
|
|
90
|
+
|
|
91
|
+
/**
|
|
92
|
+
* Get file types in a directory
|
|
93
|
+
*/
|
|
94
|
+
function getFileTypes(dirPath) {
|
|
95
|
+
const types = new Set();
|
|
96
|
+
try {
|
|
97
|
+
const entries = readdirSync(dirPath, { withFileTypes: true });
|
|
98
|
+
entries.forEach(entry => {
|
|
99
|
+
if (entry.isFile()) {
|
|
100
|
+
const ext = extname(entry.name).slice(1);
|
|
101
|
+
if (ext) types.add(ext);
|
|
102
|
+
}
|
|
103
|
+
});
|
|
104
|
+
} catch (e) {
|
|
105
|
+
// Ignore errors
|
|
106
|
+
}
|
|
107
|
+
return Array.from(types);
|
|
108
|
+
}
|
|
109
|
+
|
|
110
|
+
/**
|
|
111
|
+
* Count files in a directory (non-recursive)
|
|
112
|
+
*/
|
|
113
|
+
function countFiles(dirPath) {
|
|
114
|
+
try {
|
|
115
|
+
const entries = readdirSync(dirPath, { withFileTypes: true });
|
|
116
|
+
return entries.filter(e => e.isFile()).length;
|
|
117
|
+
} catch (e) {
|
|
118
|
+
return 0;
|
|
119
|
+
}
|
|
120
|
+
}
|
|
121
|
+
|
|
122
|
+
/**
|
|
123
|
+
* Recursively scan directories and collect info
|
|
124
|
+
*/
|
|
125
|
+
function scanDirectories(basePath, currentPath, depth, gitignorePatterns, results) {
|
|
126
|
+
try {
|
|
127
|
+
const entries = readdirSync(currentPath, { withFileTypes: true });
|
|
128
|
+
|
|
129
|
+
for (const entry of entries) {
|
|
130
|
+
if (!entry.isDirectory()) continue;
|
|
131
|
+
if (shouldExclude(entry.name, gitignorePatterns)) continue;
|
|
132
|
+
|
|
133
|
+
const fullPath = join(currentPath, entry.name);
|
|
134
|
+
const relPath = './' + relative(basePath, fullPath).replace(/\\/g, '/');
|
|
135
|
+
const fileCount = countFiles(fullPath);
|
|
136
|
+
|
|
137
|
+
// Only include directories with files
|
|
138
|
+
if (fileCount > 0) {
|
|
139
|
+
const types = getFileTypes(fullPath);
|
|
140
|
+
const hasClaude = existsSync(join(fullPath, 'CLAUDE.md'));
|
|
141
|
+
|
|
142
|
+
results.push({
|
|
143
|
+
depth: depth + 1,
|
|
144
|
+
path: relPath,
|
|
145
|
+
files: fileCount,
|
|
146
|
+
types,
|
|
147
|
+
has_claude: hasClaude
|
|
148
|
+
});
|
|
149
|
+
}
|
|
150
|
+
|
|
151
|
+
// Recurse into subdirectories
|
|
152
|
+
scanDirectories(basePath, fullPath, depth + 1, gitignorePatterns, results);
|
|
153
|
+
}
|
|
154
|
+
} catch (e) {
|
|
155
|
+
// Ignore permission errors, etc.
|
|
156
|
+
}
|
|
157
|
+
}
|
|
158
|
+
|
|
159
|
+
/**
|
|
160
|
+
* Format output as list (default)
|
|
161
|
+
*/
|
|
162
|
+
function formatList(results) {
|
|
163
|
+
// Sort by depth descending (deepest first)
|
|
164
|
+
results.sort((a, b) => b.depth - a.depth);
|
|
165
|
+
|
|
166
|
+
return results.map(r =>
|
|
167
|
+
`depth:${r.depth}|path:${r.path}|files:${r.files}|types:[${r.types.join(',')}]|has_claude:${r.has_claude ? 'yes' : 'no'}`
|
|
168
|
+
).join('\n');
|
|
169
|
+
}
|
|
170
|
+
|
|
171
|
+
/**
|
|
172
|
+
* Format output as grouped
|
|
173
|
+
*/
|
|
174
|
+
function formatGrouped(results) {
|
|
175
|
+
// Sort by depth descending
|
|
176
|
+
results.sort((a, b) => b.depth - a.depth);
|
|
177
|
+
|
|
178
|
+
const maxDepth = results.length > 0 ? Math.max(...results.map(r => r.depth)) : 0;
|
|
179
|
+
const lines = ['Modules by depth (deepest first):'];
|
|
180
|
+
|
|
181
|
+
for (let d = maxDepth; d >= 0; d--) {
|
|
182
|
+
const atDepth = results.filter(r => r.depth === d);
|
|
183
|
+
if (atDepth.length > 0) {
|
|
184
|
+
lines.push(` Depth ${d}:`);
|
|
185
|
+
atDepth.forEach(r => {
|
|
186
|
+
const claudeIndicator = r.has_claude ? ' [OK]' : '';
|
|
187
|
+
lines.push(` - ${r.path}${claudeIndicator}`);
|
|
188
|
+
});
|
|
189
|
+
}
|
|
190
|
+
}
|
|
191
|
+
|
|
192
|
+
return lines.join('\n');
|
|
193
|
+
}
|
|
194
|
+
|
|
195
|
+
/**
|
|
196
|
+
* Format output as JSON
|
|
197
|
+
*/
|
|
198
|
+
function formatJson(results) {
|
|
199
|
+
// Sort by depth descending
|
|
200
|
+
results.sort((a, b) => b.depth - a.depth);
|
|
201
|
+
|
|
202
|
+
const maxDepth = results.length > 0 ? Math.max(...results.map(r => r.depth)) : 0;
|
|
203
|
+
const modules = {};
|
|
204
|
+
|
|
205
|
+
for (let d = maxDepth; d >= 0; d--) {
|
|
206
|
+
const atDepth = results.filter(r => r.depth === d);
|
|
207
|
+
if (atDepth.length > 0) {
|
|
208
|
+
modules[d] = atDepth.map(r => ({
|
|
209
|
+
path: r.path,
|
|
210
|
+
has_claude: r.has_claude
|
|
211
|
+
}));
|
|
212
|
+
}
|
|
213
|
+
}
|
|
214
|
+
|
|
215
|
+
return JSON.stringify({
|
|
216
|
+
max_depth: maxDepth,
|
|
217
|
+
modules
|
|
218
|
+
}, null, 2);
|
|
219
|
+
}
|
|
220
|
+
|
|
221
|
+
/**
|
|
222
|
+
* Main execute function
|
|
223
|
+
*/
|
|
224
|
+
async function execute(params) {
|
|
225
|
+
const { format = 'list', path: targetPath = '.' } = params;
|
|
226
|
+
|
|
227
|
+
const basePath = resolve(process.cwd(), targetPath);
|
|
228
|
+
|
|
229
|
+
if (!existsSync(basePath)) {
|
|
230
|
+
throw new Error(`Directory not found: ${basePath}`);
|
|
231
|
+
}
|
|
232
|
+
|
|
233
|
+
const stat = statSync(basePath);
|
|
234
|
+
if (!stat.isDirectory()) {
|
|
235
|
+
throw new Error(`Not a directory: ${basePath}`);
|
|
236
|
+
}
|
|
237
|
+
|
|
238
|
+
// Parse gitignore
|
|
239
|
+
const gitignorePatterns = parseGitignore(basePath);
|
|
240
|
+
|
|
241
|
+
// Collect results
|
|
242
|
+
const results = [];
|
|
243
|
+
|
|
244
|
+
// Check root directory
|
|
245
|
+
const rootFileCount = countFiles(basePath);
|
|
246
|
+
if (rootFileCount > 0) {
|
|
247
|
+
results.push({
|
|
248
|
+
depth: 0,
|
|
249
|
+
path: '.',
|
|
250
|
+
files: rootFileCount,
|
|
251
|
+
types: getFileTypes(basePath),
|
|
252
|
+
has_claude: existsSync(join(basePath, 'CLAUDE.md'))
|
|
253
|
+
});
|
|
254
|
+
}
|
|
255
|
+
|
|
256
|
+
// Scan subdirectories
|
|
257
|
+
scanDirectories(basePath, basePath, 0, gitignorePatterns, results);
|
|
258
|
+
|
|
259
|
+
// Format output
|
|
260
|
+
let output;
|
|
261
|
+
switch (format) {
|
|
262
|
+
case 'grouped':
|
|
263
|
+
output = formatGrouped(results);
|
|
264
|
+
break;
|
|
265
|
+
case 'json':
|
|
266
|
+
output = formatJson(results);
|
|
267
|
+
break;
|
|
268
|
+
case 'list':
|
|
269
|
+
default:
|
|
270
|
+
output = formatList(results);
|
|
271
|
+
break;
|
|
272
|
+
}
|
|
273
|
+
|
|
274
|
+
return {
|
|
275
|
+
format,
|
|
276
|
+
total_modules: results.length,
|
|
277
|
+
max_depth: results.length > 0 ? Math.max(...results.map(r => r.depth)) : 0,
|
|
278
|
+
output
|
|
279
|
+
};
|
|
280
|
+
}
|
|
281
|
+
|
|
282
|
+
/**
|
|
283
|
+
* Tool Definition
|
|
284
|
+
*/
|
|
285
|
+
export const getModulesByDepthTool = {
|
|
286
|
+
name: 'get_modules_by_depth',
|
|
287
|
+
description: `Scan project structure and organize modules by directory depth (deepest first).
|
|
288
|
+
Respects .gitignore patterns and excludes common system directories.
|
|
289
|
+
Output formats: list (pipe-delimited), grouped (human-readable), json.`,
|
|
290
|
+
parameters: {
|
|
291
|
+
type: 'object',
|
|
292
|
+
properties: {
|
|
293
|
+
format: {
|
|
294
|
+
type: 'string',
|
|
295
|
+
enum: ['list', 'grouped', 'json'],
|
|
296
|
+
description: 'Output format (default: list)',
|
|
297
|
+
default: 'list'
|
|
298
|
+
},
|
|
299
|
+
path: {
|
|
300
|
+
type: 'string',
|
|
301
|
+
description: 'Target directory path (default: current directory)',
|
|
302
|
+
default: '.'
|
|
303
|
+
}
|
|
304
|
+
},
|
|
305
|
+
required: []
|
|
306
|
+
},
|
|
307
|
+
execute
|
|
308
|
+
};
|
|
@@ -0,0 +1,176 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Tool Registry - MCP-like tool system for CCW
|
|
3
|
+
* Provides tool discovery, validation, and execution
|
|
4
|
+
*/
|
|
5
|
+
|
|
6
|
+
import { editFileTool } from './edit-file.js';
|
|
7
|
+
import { getModulesByDepthTool } from './get-modules-by-depth.js';
|
|
8
|
+
import { classifyFoldersTool } from './classify-folders.js';
|
|
9
|
+
import { detectChangedModulesTool } from './detect-changed-modules.js';
|
|
10
|
+
import { discoverDesignFilesTool } from './discover-design-files.js';
|
|
11
|
+
import { generateModuleDocsTool } from './generate-module-docs.js';
|
|
12
|
+
import { uiGeneratePreviewTool } from './ui-generate-preview.js';
|
|
13
|
+
import { uiInstantiatePrototypesTool } from './ui-instantiate-prototypes.js';
|
|
14
|
+
import { updateModuleClaudeTool } from './update-module-claude.js';
|
|
15
|
+
import { convertTokensToCssTool } from './convert-tokens-to-css.js';
|
|
16
|
+
|
|
17
|
+
// Tool registry - add new tools here
|
|
18
|
+
const tools = new Map();
|
|
19
|
+
|
|
20
|
+
/**
|
|
21
|
+
* Register a tool in the registry
|
|
22
|
+
* @param {Object} tool - Tool definition
|
|
23
|
+
*/
|
|
24
|
+
function registerTool(tool) {
|
|
25
|
+
if (!tool.name || !tool.execute) {
|
|
26
|
+
throw new Error('Tool must have name and execute function');
|
|
27
|
+
}
|
|
28
|
+
tools.set(tool.name, tool);
|
|
29
|
+
}
|
|
30
|
+
|
|
31
|
+
/**
|
|
32
|
+
* Get all registered tools
|
|
33
|
+
* @returns {Array<Object>} - Array of tool definitions (without execute function)
|
|
34
|
+
*/
|
|
35
|
+
export function listTools() {
|
|
36
|
+
return Array.from(tools.values()).map(tool => ({
|
|
37
|
+
name: tool.name,
|
|
38
|
+
description: tool.description,
|
|
39
|
+
parameters: tool.parameters
|
|
40
|
+
}));
|
|
41
|
+
}
|
|
42
|
+
|
|
43
|
+
/**
|
|
44
|
+
* Get a specific tool by name
|
|
45
|
+
* @param {string} name - Tool name
|
|
46
|
+
* @returns {Object|null} - Tool definition or null
|
|
47
|
+
*/
|
|
48
|
+
export function getTool(name) {
|
|
49
|
+
return tools.get(name) || null;
|
|
50
|
+
}
|
|
51
|
+
|
|
52
|
+
/**
|
|
53
|
+
* Validate parameters against tool schema
|
|
54
|
+
* @param {Object} tool - Tool definition
|
|
55
|
+
* @param {Object} params - Parameters to validate
|
|
56
|
+
* @returns {{valid: boolean, errors: string[]}}
|
|
57
|
+
*/
|
|
58
|
+
function validateParams(tool, params) {
|
|
59
|
+
const errors = [];
|
|
60
|
+
const schema = tool.parameters;
|
|
61
|
+
|
|
62
|
+
if (!schema || !schema.properties) {
|
|
63
|
+
return { valid: true, errors: [] };
|
|
64
|
+
}
|
|
65
|
+
|
|
66
|
+
// Check required parameters
|
|
67
|
+
const required = schema.required || [];
|
|
68
|
+
for (const req of required) {
|
|
69
|
+
if (params[req] === undefined || params[req] === null) {
|
|
70
|
+
errors.push(`Missing required parameter: ${req}`);
|
|
71
|
+
}
|
|
72
|
+
}
|
|
73
|
+
|
|
74
|
+
// Type validation
|
|
75
|
+
for (const [key, value] of Object.entries(params)) {
|
|
76
|
+
const propSchema = schema.properties[key];
|
|
77
|
+
if (!propSchema) {
|
|
78
|
+
continue; // Allow extra params
|
|
79
|
+
}
|
|
80
|
+
|
|
81
|
+
if (propSchema.type === 'string' && typeof value !== 'string') {
|
|
82
|
+
errors.push(`Parameter '${key}' must be a string`);
|
|
83
|
+
}
|
|
84
|
+
if (propSchema.type === 'boolean' && typeof value !== 'boolean') {
|
|
85
|
+
errors.push(`Parameter '${key}' must be a boolean`);
|
|
86
|
+
}
|
|
87
|
+
if (propSchema.type === 'number' && typeof value !== 'number') {
|
|
88
|
+
errors.push(`Parameter '${key}' must be a number`);
|
|
89
|
+
}
|
|
90
|
+
}
|
|
91
|
+
|
|
92
|
+
return { valid: errors.length === 0, errors };
|
|
93
|
+
}
|
|
94
|
+
|
|
95
|
+
/**
|
|
96
|
+
* Execute a tool with given parameters
|
|
97
|
+
* @param {string} name - Tool name
|
|
98
|
+
* @param {Object} params - Tool parameters
|
|
99
|
+
* @returns {Promise<{success: boolean, result?: any, error?: string}>}
|
|
100
|
+
*/
|
|
101
|
+
export async function executeTool(name, params = {}) {
|
|
102
|
+
const tool = tools.get(name);
|
|
103
|
+
|
|
104
|
+
if (!tool) {
|
|
105
|
+
return {
|
|
106
|
+
success: false,
|
|
107
|
+
error: `Tool not found: ${name}`
|
|
108
|
+
};
|
|
109
|
+
}
|
|
110
|
+
|
|
111
|
+
// Validate parameters
|
|
112
|
+
const validation = validateParams(tool, params);
|
|
113
|
+
if (!validation.valid) {
|
|
114
|
+
return {
|
|
115
|
+
success: false,
|
|
116
|
+
error: `Parameter validation failed: ${validation.errors.join(', ')}`
|
|
117
|
+
};
|
|
118
|
+
}
|
|
119
|
+
|
|
120
|
+
// Execute tool
|
|
121
|
+
try {
|
|
122
|
+
const result = await tool.execute(params);
|
|
123
|
+
return {
|
|
124
|
+
success: true,
|
|
125
|
+
result
|
|
126
|
+
};
|
|
127
|
+
} catch (error) {
|
|
128
|
+
return {
|
|
129
|
+
success: false,
|
|
130
|
+
error: error.message || 'Tool execution failed'
|
|
131
|
+
};
|
|
132
|
+
}
|
|
133
|
+
}
|
|
134
|
+
|
|
135
|
+
/**
|
|
136
|
+
* Get tool schema in MCP-compatible format
|
|
137
|
+
* @param {string} name - Tool name
|
|
138
|
+
* @returns {Object|null} - Tool schema or null
|
|
139
|
+
*/
|
|
140
|
+
export function getToolSchema(name) {
|
|
141
|
+
const tool = tools.get(name);
|
|
142
|
+
if (!tool) return null;
|
|
143
|
+
|
|
144
|
+
return {
|
|
145
|
+
name: tool.name,
|
|
146
|
+
description: tool.description,
|
|
147
|
+
inputSchema: {
|
|
148
|
+
type: 'object',
|
|
149
|
+
properties: tool.parameters?.properties || {},
|
|
150
|
+
required: tool.parameters?.required || []
|
|
151
|
+
}
|
|
152
|
+
};
|
|
153
|
+
}
|
|
154
|
+
|
|
155
|
+
/**
|
|
156
|
+
* Get all tool schemas in MCP-compatible format
|
|
157
|
+
* @returns {Array<Object>} - Array of tool schemas
|
|
158
|
+
*/
|
|
159
|
+
export function getAllToolSchemas() {
|
|
160
|
+
return Array.from(tools.keys()).map(name => getToolSchema(name));
|
|
161
|
+
}
|
|
162
|
+
|
|
163
|
+
// Register built-in tools
|
|
164
|
+
registerTool(editFileTool);
|
|
165
|
+
registerTool(getModulesByDepthTool);
|
|
166
|
+
registerTool(classifyFoldersTool);
|
|
167
|
+
registerTool(detectChangedModulesTool);
|
|
168
|
+
registerTool(discoverDesignFilesTool);
|
|
169
|
+
registerTool(generateModuleDocsTool);
|
|
170
|
+
registerTool(uiGeneratePreviewTool);
|
|
171
|
+
registerTool(uiInstantiatePrototypesTool);
|
|
172
|
+
registerTool(updateModuleClaudeTool);
|
|
173
|
+
registerTool(convertTokensToCssTool);
|
|
174
|
+
|
|
175
|
+
// Export for external tool registration
|
|
176
|
+
export { registerTool };
|