@stan-chen/simple-cli 0.2.3 ā 0.2.5
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 +62 -63
- package/dist/anyllm.py +62 -0
- package/dist/builtins.d.ts +726 -0
- package/dist/builtins.js +481 -0
- package/dist/cli.d.ts +0 -4
- package/dist/cli.js +34 -493
- package/dist/engine.d.ts +33 -0
- package/dist/engine.js +138 -0
- package/dist/learnings.d.ts +15 -0
- package/dist/learnings.js +54 -0
- package/dist/llm.d.ts +18 -0
- package/dist/llm.js +73 -0
- package/dist/mcp.d.ts +132 -0
- package/dist/mcp.js +43 -0
- package/dist/skills.d.ts +5 -16
- package/dist/skills.js +91 -253
- package/dist/tui.d.ts +1 -0
- package/dist/tui.js +15 -0
- package/package.json +10 -6
- package/dist/claw/jit.d.ts +0 -5
- package/dist/claw/jit.js +0 -138
- package/dist/claw/management.d.ts +0 -3
- package/dist/claw/management.js +0 -107
- package/dist/commands/add.d.ts +0 -9
- package/dist/commands/add.js +0 -50
- package/dist/commands/git/commit.d.ts +0 -12
- package/dist/commands/git/commit.js +0 -98
- package/dist/commands/git/status.d.ts +0 -6
- package/dist/commands/git/status.js +0 -42
- package/dist/commands/index.d.ts +0 -16
- package/dist/commands/index.js +0 -377
- package/dist/commands/mcp/status.d.ts +0 -6
- package/dist/commands/mcp/status.js +0 -31
- package/dist/commands/swarm.d.ts +0 -36
- package/dist/commands/swarm.js +0 -236
- package/dist/commands.d.ts +0 -32
- package/dist/commands.js +0 -427
- package/dist/context.d.ts +0 -116
- package/dist/context.js +0 -337
- package/dist/index.d.ts +0 -6
- package/dist/index.js +0 -109
- package/dist/lib/agent.d.ts +0 -99
- package/dist/lib/agent.js +0 -313
- package/dist/lib/editor.d.ts +0 -74
- package/dist/lib/editor.js +0 -441
- package/dist/lib/git.d.ts +0 -164
- package/dist/lib/git.js +0 -356
- package/dist/lib/shim.d.ts +0 -4
- package/dist/lib/shim.js +0 -30
- package/dist/lib/ui.d.ts +0 -159
- package/dist/lib/ui.js +0 -277
- package/dist/mcp/client.d.ts +0 -22
- package/dist/mcp/client.js +0 -81
- package/dist/mcp/manager.d.ts +0 -186
- package/dist/mcp/manager.js +0 -446
- package/dist/prompts/provider.d.ts +0 -22
- package/dist/prompts/provider.js +0 -79
- package/dist/providers/index.d.ts +0 -31
- package/dist/providers/index.js +0 -93
- package/dist/providers/multi.d.ts +0 -12
- package/dist/providers/multi.js +0 -28
- package/dist/registry.d.ts +0 -29
- package/dist/registry.js +0 -443
- package/dist/repoMap.d.ts +0 -5
- package/dist/repoMap.js +0 -79
- package/dist/router.d.ts +0 -41
- package/dist/router.js +0 -118
- package/dist/swarm/coordinator.d.ts +0 -86
- package/dist/swarm/coordinator.js +0 -257
- package/dist/swarm/index.d.ts +0 -28
- package/dist/swarm/index.js +0 -29
- package/dist/swarm/task.d.ts +0 -104
- package/dist/swarm/task.js +0 -221
- package/dist/swarm/types.d.ts +0 -132
- package/dist/swarm/types.js +0 -37
- package/dist/swarm/worker.d.ts +0 -109
- package/dist/swarm/worker.js +0 -369
- package/dist/tools/analyzeFile.d.ts +0 -16
- package/dist/tools/analyzeFile.js +0 -43
- package/dist/tools/analyze_file.d.ts +0 -16
- package/dist/tools/analyze_file.js +0 -43
- package/dist/tools/clawBrain.d.ts +0 -23
- package/dist/tools/clawBrain.js +0 -136
- package/dist/tools/claw_brain.d.ts +0 -23
- package/dist/tools/claw_brain.js +0 -139
- package/dist/tools/deleteFile.d.ts +0 -19
- package/dist/tools/deleteFile.js +0 -36
- package/dist/tools/delete_file.d.ts +0 -19
- package/dist/tools/delete_file.js +0 -36
- package/dist/tools/fileOps.d.ts +0 -22
- package/dist/tools/fileOps.js +0 -43
- package/dist/tools/file_ops.d.ts +0 -22
- package/dist/tools/file_ops.js +0 -43
- package/dist/tools/git.d.ts +0 -40
- package/dist/tools/git.js +0 -236
- package/dist/tools/glob.d.ts +0 -34
- package/dist/tools/glob.js +0 -165
- package/dist/tools/grep.d.ts +0 -53
- package/dist/tools/grep.js +0 -296
- package/dist/tools/linter.d.ts +0 -35
- package/dist/tools/linter.js +0 -407
- package/dist/tools/listDir.d.ts +0 -29
- package/dist/tools/listDir.js +0 -50
- package/dist/tools/list_dir.d.ts +0 -29
- package/dist/tools/list_dir.js +0 -50
- package/dist/tools/memory.d.ts +0 -34
- package/dist/tools/memory.js +0 -215
- package/dist/tools/organizer.d.ts +0 -1
- package/dist/tools/organizer.js +0 -65
- package/dist/tools/readFiles.d.ts +0 -25
- package/dist/tools/readFiles.js +0 -31
- package/dist/tools/read_files.d.ts +0 -25
- package/dist/tools/read_files.js +0 -31
- package/dist/tools/reloadTools.d.ts +0 -11
- package/dist/tools/reloadTools.js +0 -22
- package/dist/tools/reload_tools.d.ts +0 -11
- package/dist/tools/reload_tools.js +0 -22
- package/dist/tools/runCommand.d.ts +0 -32
- package/dist/tools/runCommand.js +0 -79
- package/dist/tools/run_command.d.ts +0 -32
- package/dist/tools/run_command.js +0 -103
- package/dist/tools/scheduler.d.ts +0 -25
- package/dist/tools/scheduler.js +0 -65
- package/dist/tools/scraper.d.ts +0 -31
- package/dist/tools/scraper.js +0 -211
- package/dist/tools/writeFiles.d.ts +0 -63
- package/dist/tools/writeFiles.js +0 -87
- package/dist/tools/write_files.d.ts +0 -84
- package/dist/tools/write_files.js +0 -91
- package/dist/tools/write_to_file.d.ts +0 -15
- package/dist/tools/write_to_file.js +0 -21
- package/dist/ui/server.d.ts +0 -5
- package/dist/ui/server.js +0 -74
- package/dist/watcher.d.ts +0 -35
- package/dist/watcher.js +0 -164
- /package/{docs/assets ā assets}/logo.jpeg +0 -0
package/dist/commands/index.js
DELETED
|
@@ -1,377 +0,0 @@
|
|
|
1
|
-
import { Command, Flags } from '@oclif/core';
|
|
2
|
-
import * as ui from '../lib/ui.js';
|
|
3
|
-
import { Agent, summarizeHistory } from '../lib/agent.js';
|
|
4
|
-
import { getGitManager } from '../lib/git.js';
|
|
5
|
-
import { getContextManager } from '../context.js';
|
|
6
|
-
import { createProvider } from '../providers/index.js';
|
|
7
|
-
import { createMultiProvider } from '../providers/multi.js';
|
|
8
|
-
import { routeTask, loadTierConfig } from '../router.js';
|
|
9
|
-
import { getMCPManager } from '../mcp/manager.js';
|
|
10
|
-
import { getActiveSkill, setActiveSkill, listSkills } from '../skills.js';
|
|
11
|
-
import { createFileWatcher } from '../watcher.js';
|
|
12
|
-
import 'dotenv/config';
|
|
13
|
-
export default class Chat extends Command {
|
|
14
|
-
static description = 'Start an interactive coding session';
|
|
15
|
-
static flags = {
|
|
16
|
-
yolo: Flags.boolean({
|
|
17
|
-
description: 'Auto-approve all tool executions',
|
|
18
|
-
default: false,
|
|
19
|
-
}),
|
|
20
|
-
moe: Flags.boolean({
|
|
21
|
-
description: 'Enable Mix of Experts routing',
|
|
22
|
-
default: false,
|
|
23
|
-
}),
|
|
24
|
-
watch: Flags.boolean({
|
|
25
|
-
description: 'Watch files for AI comments',
|
|
26
|
-
default: false,
|
|
27
|
-
}),
|
|
28
|
-
skill: Flags.string({
|
|
29
|
-
description: 'Initial skill/mode (code, architect, test, etc.)',
|
|
30
|
-
default: 'code',
|
|
31
|
-
}),
|
|
32
|
-
'auto-commit': Flags.boolean({
|
|
33
|
-
description: 'Auto-commit after successful changes',
|
|
34
|
-
default: false,
|
|
35
|
-
}),
|
|
36
|
-
'auto-lint': Flags.boolean({
|
|
37
|
-
description: 'Auto-lint after file changes',
|
|
38
|
-
default: true,
|
|
39
|
-
}),
|
|
40
|
-
'auto-test': Flags.boolean({
|
|
41
|
-
description: 'Auto-run tests after changes',
|
|
42
|
-
default: false,
|
|
43
|
-
}),
|
|
44
|
-
'test-cmd': Flags.string({
|
|
45
|
-
description: 'Test command to run',
|
|
46
|
-
}),
|
|
47
|
-
};
|
|
48
|
-
async run() {
|
|
49
|
-
const { flags } = await this.parse(Chat);
|
|
50
|
-
// Show banner
|
|
51
|
-
ui.intro('Simple-CLI v0.2.0');
|
|
52
|
-
ui.log(`Mode: ${flags.moe ? 'MoE' : 'Single'} | ${flags.yolo ? 'YOLO' : 'Safe'} | Skill: @${flags.skill}`);
|
|
53
|
-
// Initialize context
|
|
54
|
-
const ctx = getContextManager();
|
|
55
|
-
await ctx.initialize();
|
|
56
|
-
ui.success(`Loaded ${ctx.getTools().size} tools`);
|
|
57
|
-
// Set initial skill
|
|
58
|
-
const skill = setActiveSkill(flags.skill);
|
|
59
|
-
if (skill) {
|
|
60
|
-
ctx.setSkill(skill);
|
|
61
|
-
}
|
|
62
|
-
// Initialize git
|
|
63
|
-
const git = getGitManager();
|
|
64
|
-
const isGitRepo = await git.isRepo();
|
|
65
|
-
if (isGitRepo) {
|
|
66
|
-
const branch = await git.currentBranch();
|
|
67
|
-
ui.log(`Git: ${branch || 'detached HEAD'}`);
|
|
68
|
-
}
|
|
69
|
-
// Initialize MCP
|
|
70
|
-
const mcpManager = getMCPManager();
|
|
71
|
-
try {
|
|
72
|
-
const configs = await mcpManager.loadConfig();
|
|
73
|
-
if (configs.length > 0) {
|
|
74
|
-
await ui.spin(`Connecting to ${configs.length} MCP server(s)`, async () => {
|
|
75
|
-
await mcpManager.connectAll(configs);
|
|
76
|
-
});
|
|
77
|
-
}
|
|
78
|
-
}
|
|
79
|
-
catch {
|
|
80
|
-
// MCP not configured
|
|
81
|
-
}
|
|
82
|
-
// Initialize providers
|
|
83
|
-
const tierConfigs = flags.moe ? loadTierConfig() : null;
|
|
84
|
-
const multiProvider = tierConfigs ? createMultiProvider(tierConfigs) : null;
|
|
85
|
-
const singleProvider = !flags.moe ? createProvider() : null;
|
|
86
|
-
// Initialize file watcher
|
|
87
|
-
let watcher = null;
|
|
88
|
-
if (flags.watch) {
|
|
89
|
-
watcher = createFileWatcher({
|
|
90
|
-
root: ctx.getCwd(),
|
|
91
|
-
onAIComment: (path, comments) => {
|
|
92
|
-
ui.note(comments.map(c => `Line ${c.line}: ${c.text}`).join('\n'), `AI Comments in ${path}`);
|
|
93
|
-
},
|
|
94
|
-
});
|
|
95
|
-
ui.success('File watcher active');
|
|
96
|
-
}
|
|
97
|
-
// Generate function
|
|
98
|
-
const generate = async (messages) => {
|
|
99
|
-
const fullPrompt = await ctx.buildSystemPrompt();
|
|
100
|
-
const llmMessages = messages.map(m => ({ role: m.role, content: m.content }));
|
|
101
|
-
if (flags.moe && multiProvider && tierConfigs) {
|
|
102
|
-
const userMsg = messages.find(m => m.role === 'user')?.content || '';
|
|
103
|
-
const routing = await routeTask(userMsg, async (prompt) => {
|
|
104
|
-
const res = await multiProvider.generateWithTier(1, prompt, [{ role: 'user', content: userMsg }]);
|
|
105
|
-
return res.message || res.thought || res.raw || '';
|
|
106
|
-
});
|
|
107
|
-
return multiProvider.generateWithTier(routing.tier, fullPrompt, llmMessages);
|
|
108
|
-
}
|
|
109
|
-
return singleProvider.generateResponse(fullPrompt, llmMessages);
|
|
110
|
-
};
|
|
111
|
-
// Tool execution
|
|
112
|
-
const executeTool = async (name, args) => {
|
|
113
|
-
const tools = ctx.getTools();
|
|
114
|
-
const tool = tools.get(name);
|
|
115
|
-
if (!tool) {
|
|
116
|
-
throw new Error(`Tool not found: ${name}`);
|
|
117
|
-
}
|
|
118
|
-
// Permission check
|
|
119
|
-
if (!flags.yolo && tool.permission !== 'read') {
|
|
120
|
-
const confirmed = await ui.confirm({
|
|
121
|
-
message: `Execute ${name}?`,
|
|
122
|
-
initialValue: false,
|
|
123
|
-
});
|
|
124
|
-
if (ui.isCancel(confirmed) || !confirmed) {
|
|
125
|
-
return 'Cancelled by user';
|
|
126
|
-
}
|
|
127
|
-
}
|
|
128
|
-
return tool.execute(args);
|
|
129
|
-
};
|
|
130
|
-
// Create agent
|
|
131
|
-
const agent = new Agent({
|
|
132
|
-
config: {
|
|
133
|
-
maxReflections: 3,
|
|
134
|
-
autoLint: flags['auto-lint'],
|
|
135
|
-
autoTest: flags['auto-test'],
|
|
136
|
-
autoCommit: flags['auto-commit'],
|
|
137
|
-
testCommand: flags['test-cmd'],
|
|
138
|
-
},
|
|
139
|
-
git,
|
|
140
|
-
generateFn: generate,
|
|
141
|
-
executeTool,
|
|
142
|
-
lintFn: flags['auto-lint'] ? async (file) => {
|
|
143
|
-
const { execute } = await import('../tools/linter.js');
|
|
144
|
-
const result = await execute({ path: file, fix: false });
|
|
145
|
-
return { passed: result.passed, output: result.output };
|
|
146
|
-
} : undefined,
|
|
147
|
-
testFn: flags['auto-test'] && flags['test-cmd'] ? async () => {
|
|
148
|
-
const { execute } = await import('../tools/run_command.js');
|
|
149
|
-
const result = await execute({ command: flags['test-cmd'] });
|
|
150
|
-
return { passed: result.exitCode === 0, output: result.stdout + result.stderr };
|
|
151
|
-
} : undefined,
|
|
152
|
-
});
|
|
153
|
-
// Main loop
|
|
154
|
-
while (true) {
|
|
155
|
-
const currentSkill = getActiveSkill();
|
|
156
|
-
const input = await ui.text({
|
|
157
|
-
message: `[${currentSkill.name}]`,
|
|
158
|
-
placeholder: 'Type a message or /help...',
|
|
159
|
-
});
|
|
160
|
-
if (ui.isCancel(input)) {
|
|
161
|
-
break;
|
|
162
|
-
}
|
|
163
|
-
const message = input.trim();
|
|
164
|
-
if (!message)
|
|
165
|
-
continue;
|
|
166
|
-
// Handle slash commands
|
|
167
|
-
if (message.startsWith('/')) {
|
|
168
|
-
await handleCommand(message, ctx, git, mcpManager);
|
|
169
|
-
continue;
|
|
170
|
-
}
|
|
171
|
-
// Handle skill switching
|
|
172
|
-
if (message.startsWith('@')) {
|
|
173
|
-
const skillName = message.slice(1).trim();
|
|
174
|
-
if (skillName === 'list') {
|
|
175
|
-
ui.note(listSkills().map(s => `@${s.name} - ${s.description}`).join('\n'), 'Available Skills');
|
|
176
|
-
}
|
|
177
|
-
else {
|
|
178
|
-
const newSkill = setActiveSkill(skillName);
|
|
179
|
-
if (newSkill) {
|
|
180
|
-
ctx.setSkill(newSkill);
|
|
181
|
-
ui.success(`Switched to @${newSkill.name}`);
|
|
182
|
-
}
|
|
183
|
-
else {
|
|
184
|
-
ui.error(`Unknown skill: @${skillName}`);
|
|
185
|
-
}
|
|
186
|
-
}
|
|
187
|
-
continue;
|
|
188
|
-
}
|
|
189
|
-
// Add watch context if available
|
|
190
|
-
let fullMessage = message;
|
|
191
|
-
if (watcher) {
|
|
192
|
-
const watchPrompt = watcher.getActionableCommentsPrompt();
|
|
193
|
-
if (watchPrompt) {
|
|
194
|
-
fullMessage = `${watchPrompt}\n\nUser request: ${message}`;
|
|
195
|
-
}
|
|
196
|
-
}
|
|
197
|
-
// Process with agent
|
|
198
|
-
try {
|
|
199
|
-
ctx.addMessage('user', message);
|
|
200
|
-
const history = ctx.getHistory();
|
|
201
|
-
// Summarize if too long
|
|
202
|
-
const summarizedHistory = await summarizeHistory(history, generate, 20);
|
|
203
|
-
const systemPrompt = await ctx.buildSystemPrompt();
|
|
204
|
-
const result = await agent.process(fullMessage, summarizedHistory, systemPrompt);
|
|
205
|
-
// Add response to history
|
|
206
|
-
if (result.response.action && 'message' in result.response.action) {
|
|
207
|
-
ctx.addMessage('assistant', result.response.action.message);
|
|
208
|
-
}
|
|
209
|
-
}
|
|
210
|
-
catch (error) {
|
|
211
|
-
ui.error(`Error: ${error instanceof Error ? error.message : error}`);
|
|
212
|
-
}
|
|
213
|
-
}
|
|
214
|
-
// Cleanup
|
|
215
|
-
watcher?.stop();
|
|
216
|
-
await mcpManager.disconnectAll();
|
|
217
|
-
ui.outro('Goodbye!');
|
|
218
|
-
}
|
|
219
|
-
}
|
|
220
|
-
/**
|
|
221
|
-
* Handle slash commands
|
|
222
|
-
*/
|
|
223
|
-
async function handleCommand(input, ctx, git, mcpManager) {
|
|
224
|
-
const [cmd, ...args] = input.slice(1).split(/\s+/);
|
|
225
|
-
const argsStr = args.join(' ');
|
|
226
|
-
switch (cmd.toLowerCase()) {
|
|
227
|
-
case 'help':
|
|
228
|
-
case 'h':
|
|
229
|
-
ui.note(`
|
|
230
|
-
/add <file> - Add file to context
|
|
231
|
-
/drop [file] - Remove file from context
|
|
232
|
-
/ls - List files in context
|
|
233
|
-
/clear - Clear chat history
|
|
234
|
-
/diff - Show git diff
|
|
235
|
-
/status - Show git status
|
|
236
|
-
/commit [msg] - Commit changes
|
|
237
|
-
/undo - Undo last commit
|
|
238
|
-
/tokens - Show token estimate
|
|
239
|
-
/mcp [cmd] - MCP management
|
|
240
|
-
/skill <name> - Switch skill
|
|
241
|
-
/exit - Exit
|
|
242
|
-
`, 'Commands');
|
|
243
|
-
break;
|
|
244
|
-
case 'add':
|
|
245
|
-
case 'a':
|
|
246
|
-
if (argsStr) {
|
|
247
|
-
const added = ctx.addFile(argsStr);
|
|
248
|
-
if (added) {
|
|
249
|
-
ui.success(`Added ${argsStr}`);
|
|
250
|
-
}
|
|
251
|
-
else {
|
|
252
|
-
ui.error(`File not found: ${argsStr}`);
|
|
253
|
-
}
|
|
254
|
-
}
|
|
255
|
-
else {
|
|
256
|
-
ui.error('Usage: /add <file>');
|
|
257
|
-
}
|
|
258
|
-
break;
|
|
259
|
-
case 'drop':
|
|
260
|
-
case 'd':
|
|
261
|
-
if (argsStr) {
|
|
262
|
-
ctx.removeFile(argsStr);
|
|
263
|
-
ui.success(`Dropped ${argsStr}`);
|
|
264
|
-
}
|
|
265
|
-
else {
|
|
266
|
-
// Drop all
|
|
267
|
-
const files = ctx.getFiles();
|
|
268
|
-
for (const f of [...files.active, ...files.readOnly]) {
|
|
269
|
-
ctx.removeFile(f);
|
|
270
|
-
}
|
|
271
|
-
ui.success('Dropped all files');
|
|
272
|
-
}
|
|
273
|
-
break;
|
|
274
|
-
case 'ls':
|
|
275
|
-
case 'files':
|
|
276
|
-
const files = ctx.getFiles();
|
|
277
|
-
if (files.active.length === 0 && files.readOnly.length === 0) {
|
|
278
|
-
ui.log('No files in context');
|
|
279
|
-
}
|
|
280
|
-
else {
|
|
281
|
-
ui.showFileStatus([
|
|
282
|
-
...files.active.map(f => ({ path: f, status: 'modified' })),
|
|
283
|
-
...files.readOnly.map(f => ({ path: f, status: 'readonly' })),
|
|
284
|
-
]);
|
|
285
|
-
}
|
|
286
|
-
break;
|
|
287
|
-
case 'clear':
|
|
288
|
-
ctx.clearHistory();
|
|
289
|
-
ui.success('Chat history cleared');
|
|
290
|
-
break;
|
|
291
|
-
case 'diff':
|
|
292
|
-
const diff = await git.diff();
|
|
293
|
-
if (diff) {
|
|
294
|
-
ui.showDiff(diff);
|
|
295
|
-
}
|
|
296
|
-
else {
|
|
297
|
-
ui.log('No changes');
|
|
298
|
-
}
|
|
299
|
-
break;
|
|
300
|
-
case 'status':
|
|
301
|
-
const status = await git.status();
|
|
302
|
-
ui.log(`Branch: ${status.current}`);
|
|
303
|
-
if (status.modified.length)
|
|
304
|
-
ui.log(`Modified: ${status.modified.join(', ')}`);
|
|
305
|
-
if (status.created.length)
|
|
306
|
-
ui.log(`Created: ${status.created.join(', ')}`);
|
|
307
|
-
if (status.deleted.length)
|
|
308
|
-
ui.log(`Deleted: ${status.deleted.join(', ')}`);
|
|
309
|
-
if (status.not_added.length)
|
|
310
|
-
ui.log(`Untracked: ${status.not_added.join(', ')}`);
|
|
311
|
-
break;
|
|
312
|
-
case 'commit':
|
|
313
|
-
const commitDiff = await git.stagedDiff();
|
|
314
|
-
if (!commitDiff && !(await git.status()).staged.length) {
|
|
315
|
-
await git.addAll();
|
|
316
|
-
}
|
|
317
|
-
const result = await git.commit({ message: argsStr || 'Update' });
|
|
318
|
-
if (result) {
|
|
319
|
-
ui.success(`Committed: ${result.hash} ${result.message}`);
|
|
320
|
-
}
|
|
321
|
-
else {
|
|
322
|
-
ui.error('Nothing to commit');
|
|
323
|
-
}
|
|
324
|
-
break;
|
|
325
|
-
case 'undo':
|
|
326
|
-
if (await git.undoLastCommit()) {
|
|
327
|
-
ui.success('Undid last commit');
|
|
328
|
-
}
|
|
329
|
-
else {
|
|
330
|
-
ui.error('Failed to undo');
|
|
331
|
-
}
|
|
332
|
-
break;
|
|
333
|
-
case 'tokens':
|
|
334
|
-
const tokens = await ctx.estimateTokenCount();
|
|
335
|
-
ui.showTokens(tokens);
|
|
336
|
-
break;
|
|
337
|
-
case 'mcp':
|
|
338
|
-
const subCmd = args[0];
|
|
339
|
-
if (subCmd === 'status') {
|
|
340
|
-
const statuses = mcpManager.getAllServerStatuses();
|
|
341
|
-
for (const [name, status] of statuses) {
|
|
342
|
-
ui.log(`${name}: ${status}`);
|
|
343
|
-
}
|
|
344
|
-
}
|
|
345
|
-
else if (subCmd === 'tools') {
|
|
346
|
-
const tools = mcpManager.getAllTools();
|
|
347
|
-
for (const tool of tools) {
|
|
348
|
-
ui.log(`${tool.name} (${tool.serverName}): ${tool.description}`);
|
|
349
|
-
}
|
|
350
|
-
}
|
|
351
|
-
else {
|
|
352
|
-
ui.log('Usage: /mcp [status|tools]');
|
|
353
|
-
}
|
|
354
|
-
break;
|
|
355
|
-
case 'skill':
|
|
356
|
-
if (argsStr) {
|
|
357
|
-
const newSkill = setActiveSkill(argsStr);
|
|
358
|
-
if (newSkill) {
|
|
359
|
-
ctx.setSkill(newSkill);
|
|
360
|
-
ui.success(`Switched to @${newSkill.name}`);
|
|
361
|
-
}
|
|
362
|
-
else {
|
|
363
|
-
ui.error(`Unknown skill: ${argsStr}`);
|
|
364
|
-
}
|
|
365
|
-
}
|
|
366
|
-
else {
|
|
367
|
-
ui.note(listSkills().map(s => `@${s.name} - ${s.description}`).join('\n'), 'Available Skills');
|
|
368
|
-
}
|
|
369
|
-
break;
|
|
370
|
-
case 'exit':
|
|
371
|
-
case 'quit':
|
|
372
|
-
case 'q':
|
|
373
|
-
process.exit(0);
|
|
374
|
-
default:
|
|
375
|
-
ui.error(`Unknown command: /${cmd}`);
|
|
376
|
-
}
|
|
377
|
-
}
|
|
@@ -1,31 +0,0 @@
|
|
|
1
|
-
import { Command } from '@oclif/core';
|
|
2
|
-
import * as ui from '../../lib/ui.js';
|
|
3
|
-
import { getMCPManager, MCPServerStatus } from '../../mcp/manager.js';
|
|
4
|
-
export default class MCPStatus extends Command {
|
|
5
|
-
static description = 'Show MCP server status';
|
|
6
|
-
static examples = ['<%= config.bin %> mcp status'];
|
|
7
|
-
async run() {
|
|
8
|
-
const manager = getMCPManager();
|
|
9
|
-
const statuses = manager.getAllServerStatuses();
|
|
10
|
-
if (statuses.size === 0) {
|
|
11
|
-
ui.log('No MCP servers configured');
|
|
12
|
-
ui.note('Create a mcp.json file to configure MCP servers', 'Hint');
|
|
13
|
-
return;
|
|
14
|
-
}
|
|
15
|
-
ui.log('MCP Servers:\n');
|
|
16
|
-
const statusIcon = {
|
|
17
|
-
[MCPServerStatus.CONNECTED]: ui.theme.success('ā'),
|
|
18
|
-
[MCPServerStatus.CONNECTING]: ui.theme.warning('ā'),
|
|
19
|
-
[MCPServerStatus.DISCONNECTED]: ui.theme.muted('ā'),
|
|
20
|
-
[MCPServerStatus.ERROR]: ui.theme.error('ā'),
|
|
21
|
-
};
|
|
22
|
-
for (const [name, status] of statuses) {
|
|
23
|
-
ui.log(` ${statusIcon[status]} ${name}: ${status}`);
|
|
24
|
-
}
|
|
25
|
-
// Show tool count
|
|
26
|
-
const tools = manager.getAllTools();
|
|
27
|
-
const resources = manager.getAllResources();
|
|
28
|
-
const prompts = manager.getAllPrompts();
|
|
29
|
-
ui.log(`\nDiscovered: ${tools.length} tools, ${resources.length} resources, ${prompts.length} prompts`);
|
|
30
|
-
}
|
|
31
|
-
}
|
package/dist/commands/swarm.d.ts
DELETED
|
@@ -1,36 +0,0 @@
|
|
|
1
|
-
/**
|
|
2
|
-
* Swarm Command - Run multiple agents in parallel
|
|
3
|
-
*/
|
|
4
|
-
import { type SwarmTask, type CoordinatorOptions } from '../swarm/index.js';
|
|
5
|
-
export interface SwarmCliOptions {
|
|
6
|
-
tasksFile?: string;
|
|
7
|
-
task?: string;
|
|
8
|
-
scope?: string;
|
|
9
|
-
concurrency?: number;
|
|
10
|
-
timeout?: number;
|
|
11
|
-
yolo?: boolean;
|
|
12
|
-
branch?: string;
|
|
13
|
-
}
|
|
14
|
-
/**
|
|
15
|
-
* Parse swarm options from command line arguments
|
|
16
|
-
*/
|
|
17
|
-
export declare function parseSwarmArgs(args: string[]): SwarmCliOptions;
|
|
18
|
-
/**
|
|
19
|
-
* Load tasks from a JSON file
|
|
20
|
-
*/
|
|
21
|
-
export declare function loadTasksFromFile(filePath: string): {
|
|
22
|
-
tasks: SwarmTask[];
|
|
23
|
-
options?: Partial<CoordinatorOptions>;
|
|
24
|
-
};
|
|
25
|
-
/**
|
|
26
|
-
* Create tasks from a glob pattern
|
|
27
|
-
*/
|
|
28
|
-
export declare function createTasksFromScope(task: string, scope: string, type?: SwarmTask['type']): Promise<SwarmTask[]>;
|
|
29
|
-
/**
|
|
30
|
-
* Run swarm orchestrator
|
|
31
|
-
*/
|
|
32
|
-
export declare function runSwarm(options: SwarmCliOptions): Promise<void>;
|
|
33
|
-
/**
|
|
34
|
-
* Print swarm help
|
|
35
|
-
*/
|
|
36
|
-
export declare function printSwarmHelp(): void;
|
package/dist/commands/swarm.js
DELETED
|
@@ -1,236 +0,0 @@
|
|
|
1
|
-
/**
|
|
2
|
-
* Swarm Command - Run multiple agents in parallel
|
|
3
|
-
*/
|
|
4
|
-
import { readFileSync, existsSync } from 'fs';
|
|
5
|
-
import { SwarmCoordinator } from '../swarm/index.js';
|
|
6
|
-
import { execute as globExecute } from '../tools/glob.js';
|
|
7
|
-
/**
|
|
8
|
-
* Parse swarm options from command line arguments
|
|
9
|
-
*/
|
|
10
|
-
export function parseSwarmArgs(args) {
|
|
11
|
-
const options = {};
|
|
12
|
-
for (let i = 0; i < args.length; i++) {
|
|
13
|
-
const arg = args[i];
|
|
14
|
-
if (arg === '--tasks' && args[i + 1]) {
|
|
15
|
-
options.tasksFile = args[++i];
|
|
16
|
-
}
|
|
17
|
-
else if (arg === '--task' && args[i + 1]) {
|
|
18
|
-
options.task = args[++i];
|
|
19
|
-
}
|
|
20
|
-
else if (arg === '--scope' && args[i + 1]) {
|
|
21
|
-
options.scope = args[++i];
|
|
22
|
-
}
|
|
23
|
-
else if (arg === '--concurrency' && args[i + 1]) {
|
|
24
|
-
options.concurrency = parseInt(args[++i], 10);
|
|
25
|
-
}
|
|
26
|
-
else if (arg === '--timeout' && args[i + 1]) {
|
|
27
|
-
options.timeout = parseInt(args[++i], 10);
|
|
28
|
-
}
|
|
29
|
-
else if (arg === '--branch' && args[i + 1]) {
|
|
30
|
-
options.branch = args[++i];
|
|
31
|
-
}
|
|
32
|
-
else if (arg === '--yolo') {
|
|
33
|
-
options.yolo = true;
|
|
34
|
-
}
|
|
35
|
-
else if (!arg.startsWith('--') && !options.tasksFile && existsSync(arg)) {
|
|
36
|
-
// Positional argument - tasks file
|
|
37
|
-
options.tasksFile = arg;
|
|
38
|
-
}
|
|
39
|
-
}
|
|
40
|
-
return options;
|
|
41
|
-
}
|
|
42
|
-
/**
|
|
43
|
-
* Load tasks from a JSON file
|
|
44
|
-
*/
|
|
45
|
-
export function loadTasksFromFile(filePath) {
|
|
46
|
-
if (!existsSync(filePath)) {
|
|
47
|
-
throw new Error(`Tasks file not found: ${filePath}`);
|
|
48
|
-
}
|
|
49
|
-
const content = readFileSync(filePath, 'utf-8');
|
|
50
|
-
const data = JSON.parse(content);
|
|
51
|
-
// Support both { tasks: [...] } and [...] formats
|
|
52
|
-
if (Array.isArray(data)) {
|
|
53
|
-
return { tasks: data };
|
|
54
|
-
}
|
|
55
|
-
const tasks = data.tasks || [];
|
|
56
|
-
const options = {};
|
|
57
|
-
if (data.session) {
|
|
58
|
-
if (data.session.concurrency)
|
|
59
|
-
options.concurrency = data.session.concurrency;
|
|
60
|
-
if (data.session.timeout)
|
|
61
|
-
options.timeout = data.session.timeout;
|
|
62
|
-
if (data.session.branch)
|
|
63
|
-
options.branch = data.session.branch;
|
|
64
|
-
}
|
|
65
|
-
return { tasks, options };
|
|
66
|
-
}
|
|
67
|
-
/**
|
|
68
|
-
* Create tasks from a glob pattern
|
|
69
|
-
*/
|
|
70
|
-
export async function createTasksFromScope(task, scope, type = 'implement') {
|
|
71
|
-
const result = await globExecute({ pattern: scope, maxResults: 100, includeDirectories: false });
|
|
72
|
-
return result.matches.map((file, i) => ({
|
|
73
|
-
id: `task-${i}`,
|
|
74
|
-
type,
|
|
75
|
-
description: `${task} in ${file}`,
|
|
76
|
-
scope: { files: [file] },
|
|
77
|
-
dependencies: [],
|
|
78
|
-
priority: 2,
|
|
79
|
-
timeout: 300000,
|
|
80
|
-
retries: 2,
|
|
81
|
-
}));
|
|
82
|
-
}
|
|
83
|
-
/**
|
|
84
|
-
* Run swarm orchestrator
|
|
85
|
-
*/
|
|
86
|
-
export async function runSwarm(options) {
|
|
87
|
-
console.log('\nš Simple-CLI Swarm Mode\n');
|
|
88
|
-
let tasks = [];
|
|
89
|
-
let coordinatorOptions = {};
|
|
90
|
-
// Load tasks from file or create from options
|
|
91
|
-
if (options.tasksFile) {
|
|
92
|
-
console.log(`š Loading tasks from ${options.tasksFile}...`);
|
|
93
|
-
const loaded = loadTasksFromFile(options.tasksFile);
|
|
94
|
-
tasks = loaded.tasks;
|
|
95
|
-
coordinatorOptions = loaded.options || {};
|
|
96
|
-
}
|
|
97
|
-
else if (options.task && options.scope) {
|
|
98
|
-
console.log(`š Creating tasks from scope: ${options.scope}...`);
|
|
99
|
-
tasks = await createTasksFromScope(options.task, options.scope);
|
|
100
|
-
}
|
|
101
|
-
else if (options.task) {
|
|
102
|
-
// Single task
|
|
103
|
-
tasks = [{
|
|
104
|
-
id: 'single-task',
|
|
105
|
-
type: 'implement',
|
|
106
|
-
description: options.task,
|
|
107
|
-
scope: {},
|
|
108
|
-
dependencies: [],
|
|
109
|
-
priority: 1,
|
|
110
|
-
timeout: options.timeout || 300000,
|
|
111
|
-
retries: 2,
|
|
112
|
-
}];
|
|
113
|
-
}
|
|
114
|
-
if (tasks.length === 0) {
|
|
115
|
-
console.error('ā No tasks to run. Provide --tasks <file> or --task "description"');
|
|
116
|
-
process.exit(1);
|
|
117
|
-
}
|
|
118
|
-
console.log(`š ${tasks.length} task(s) to execute\n`);
|
|
119
|
-
// Apply CLI options
|
|
120
|
-
if (options.concurrency)
|
|
121
|
-
coordinatorOptions.concurrency = options.concurrency;
|
|
122
|
-
if (options.timeout)
|
|
123
|
-
coordinatorOptions.timeout = options.timeout;
|
|
124
|
-
if (options.branch)
|
|
125
|
-
coordinatorOptions.branch = options.branch;
|
|
126
|
-
if (options.yolo !== undefined)
|
|
127
|
-
coordinatorOptions.yolo = options.yolo;
|
|
128
|
-
// Create coordinator
|
|
129
|
-
const coordinator = new SwarmCoordinator({
|
|
130
|
-
cwd: process.cwd(),
|
|
131
|
-
...coordinatorOptions,
|
|
132
|
-
});
|
|
133
|
-
// Add event handlers
|
|
134
|
-
coordinator.on('task:start', (task, workerId) => {
|
|
135
|
-
console.log(`š [${workerId}] Starting: ${task.description.slice(0, 60)}...`);
|
|
136
|
-
});
|
|
137
|
-
coordinator.on('task:complete', (task, result) => {
|
|
138
|
-
const status = result.success ? 'ā
' : 'ā ļø';
|
|
139
|
-
console.log(`${status} [${task.id}] Done in ${result.duration}ms`);
|
|
140
|
-
if (result.filesChanged.length > 0) {
|
|
141
|
-
console.log(` Files: ${result.filesChanged.join(', ')}`);
|
|
142
|
-
}
|
|
143
|
-
});
|
|
144
|
-
coordinator.on('task:fail', (task, error) => {
|
|
145
|
-
console.error(`ā [${task.id}] Failed: ${error.message}`);
|
|
146
|
-
});
|
|
147
|
-
coordinator.on('task:retry', (task, attempt) => {
|
|
148
|
-
console.log(`š [${task.id}] Retry attempt ${attempt}`);
|
|
149
|
-
});
|
|
150
|
-
// Add tasks
|
|
151
|
-
coordinator.addTasks(tasks);
|
|
152
|
-
// Run swarm
|
|
153
|
-
const startTime = Date.now();
|
|
154
|
-
console.log(`ā±ļø Starting swarm with concurrency: ${coordinatorOptions.concurrency || 4}\n`);
|
|
155
|
-
try {
|
|
156
|
-
const result = await coordinator.run();
|
|
157
|
-
// Print summary
|
|
158
|
-
console.log('\n' + 'ā'.repeat(50));
|
|
159
|
-
console.log('š SWARM COMPLETE');
|
|
160
|
-
console.log('ā'.repeat(50));
|
|
161
|
-
console.log(` Total Tasks: ${result.total}`);
|
|
162
|
-
console.log(` Completed: ${result.completed} ā
`);
|
|
163
|
-
console.log(` Failed: ${result.failed} ā`);
|
|
164
|
-
console.log(` Skipped: ${result.skipped} āļø`);
|
|
165
|
-
console.log(` Duration: ${((Date.now() - startTime) / 1000).toFixed(1)}s`);
|
|
166
|
-
console.log(` Success Rate: ${(result.successRate * 100).toFixed(1)}%`);
|
|
167
|
-
if (result.failedTasks.length > 0) {
|
|
168
|
-
console.log('\nā Failed Tasks:');
|
|
169
|
-
for (const f of result.failedTasks) {
|
|
170
|
-
console.log(` - ${f.task.id}: ${f.error}`);
|
|
171
|
-
}
|
|
172
|
-
}
|
|
173
|
-
console.log('ā'.repeat(50) + '\n');
|
|
174
|
-
// Exit with error code if any failures
|
|
175
|
-
if (result.failed > 0) {
|
|
176
|
-
process.exit(1);
|
|
177
|
-
}
|
|
178
|
-
}
|
|
179
|
-
catch (error) {
|
|
180
|
-
console.error(`\nā Swarm error: ${error instanceof Error ? error.message : error}`);
|
|
181
|
-
process.exit(1);
|
|
182
|
-
}
|
|
183
|
-
}
|
|
184
|
-
/**
|
|
185
|
-
* Print swarm help
|
|
186
|
-
*/
|
|
187
|
-
export function printSwarmHelp() {
|
|
188
|
-
console.log(`
|
|
189
|
-
š Simple-CLI Swarm Mode
|
|
190
|
-
|
|
191
|
-
USAGE
|
|
192
|
-
simple --swarm [options]
|
|
193
|
-
|
|
194
|
-
OPTIONS
|
|
195
|
-
--tasks <file> Load tasks from JSON file
|
|
196
|
-
--task "desc" Single task description
|
|
197
|
-
--scope "pattern" Glob pattern for files (creates task per file)
|
|
198
|
-
--concurrency <n> Max parallel workers (default: 4)
|
|
199
|
-
--timeout <ms> Task timeout in milliseconds
|
|
200
|
-
--branch <name> Git branch for changes
|
|
201
|
-
--yolo Auto-approve all actions
|
|
202
|
-
|
|
203
|
-
EXAMPLES
|
|
204
|
-
# Run tasks from file
|
|
205
|
-
simple --swarm --tasks tasks.json
|
|
206
|
-
|
|
207
|
-
# Single task
|
|
208
|
-
simple --swarm --yolo --task "add tests to all files"
|
|
209
|
-
|
|
210
|
-
# Task per file matching pattern
|
|
211
|
-
simple --swarm --yolo --task "add JSDoc" --scope "src/**/*.ts"
|
|
212
|
-
|
|
213
|
-
# With concurrency limit
|
|
214
|
-
simple --swarm --concurrency 2 --tasks tasks.json
|
|
215
|
-
|
|
216
|
-
TASKS FILE FORMAT
|
|
217
|
-
{
|
|
218
|
-
"session": {
|
|
219
|
-
"concurrency": 4,
|
|
220
|
-
"timeout": 300000,
|
|
221
|
-
"branch": "feature/swarm"
|
|
222
|
-
},
|
|
223
|
-
"tasks": [
|
|
224
|
-
{
|
|
225
|
-
"id": "task-1",
|
|
226
|
-
"type": "implement",
|
|
227
|
-
"description": "Add validation",
|
|
228
|
-
"scope": { "files": ["src/api.ts"] },
|
|
229
|
-
"priority": 1,
|
|
230
|
-
"timeout": 60000,
|
|
231
|
-
"retries": 2
|
|
232
|
-
}
|
|
233
|
-
]
|
|
234
|
-
}
|
|
235
|
-
`);
|
|
236
|
-
}
|