@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.d.ts
DELETED
|
@@ -1,32 +0,0 @@
|
|
|
1
|
-
/**
|
|
2
|
-
* Slash Commands System
|
|
3
|
-
* Based on Aider's commands.py
|
|
4
|
-
*/
|
|
5
|
-
export interface CommandContext {
|
|
6
|
-
cwd: string;
|
|
7
|
-
activeFiles: Set<string>;
|
|
8
|
-
readOnlyFiles: Set<string>;
|
|
9
|
-
history: Array<{
|
|
10
|
-
role: string;
|
|
11
|
-
content: string;
|
|
12
|
-
}>;
|
|
13
|
-
io: {
|
|
14
|
-
output: (message: string) => void;
|
|
15
|
-
error: (message: string) => void;
|
|
16
|
-
confirm: (message: string) => Promise<boolean>;
|
|
17
|
-
prompt: (message: string) => Promise<string>;
|
|
18
|
-
};
|
|
19
|
-
}
|
|
20
|
-
export interface Command {
|
|
21
|
-
name: string;
|
|
22
|
-
aliases: string[];
|
|
23
|
-
description: string;
|
|
24
|
-
execute: (args: string, context: CommandContext) => Promise<string | void>;
|
|
25
|
-
}
|
|
26
|
-
export declare function parseCommand(input: string): {
|
|
27
|
-
command: string;
|
|
28
|
-
args: string;
|
|
29
|
-
} | null;
|
|
30
|
-
export declare const commands: Command[];
|
|
31
|
-
export declare function findCommand(name: string): Command | undefined;
|
|
32
|
-
export declare function executeCommand(input: string, context: CommandContext): Promise<string | void>;
|
package/dist/commands.js
DELETED
|
@@ -1,427 +0,0 @@
|
|
|
1
|
-
/**
|
|
2
|
-
* Slash Commands System
|
|
3
|
-
* Based on Aider's commands.py
|
|
4
|
-
*/
|
|
5
|
-
import { readFile, writeFile } from 'fs/promises';
|
|
6
|
-
import { existsSync } from 'fs';
|
|
7
|
-
import { relative, resolve } from 'path';
|
|
8
|
-
import { getMCPManager } from './mcp/manager.js';
|
|
9
|
-
import { getStagedDiff } from './tools/git.js';
|
|
10
|
-
import { execute as grepExecute } from './tools/grep.js';
|
|
11
|
-
import { execute as globExecute } from './tools/glob.js';
|
|
12
|
-
// Parse command line into command and args
|
|
13
|
-
export function parseCommand(input) {
|
|
14
|
-
if (!input.startsWith('/')) {
|
|
15
|
-
return null;
|
|
16
|
-
}
|
|
17
|
-
const trimmed = input.slice(1).trim();
|
|
18
|
-
const spaceIndex = trimmed.indexOf(' ');
|
|
19
|
-
if (spaceIndex === -1) {
|
|
20
|
-
return { command: trimmed.toLowerCase(), args: '' };
|
|
21
|
-
}
|
|
22
|
-
return {
|
|
23
|
-
command: trimmed.slice(0, spaceIndex).toLowerCase(),
|
|
24
|
-
args: trimmed.slice(spaceIndex + 1).trim(),
|
|
25
|
-
};
|
|
26
|
-
}
|
|
27
|
-
// Built-in commands
|
|
28
|
-
export const commands = [
|
|
29
|
-
// File Management
|
|
30
|
-
{
|
|
31
|
-
name: 'add',
|
|
32
|
-
aliases: ['a'],
|
|
33
|
-
description: 'Add files to the chat context',
|
|
34
|
-
execute: async (args, ctx) => {
|
|
35
|
-
if (!args) {
|
|
36
|
-
ctx.io.output('Usage: /add <file_pattern>');
|
|
37
|
-
return;
|
|
38
|
-
}
|
|
39
|
-
const patterns = args.split(/\s+/);
|
|
40
|
-
let added = 0;
|
|
41
|
-
for (const pattern of patterns) {
|
|
42
|
-
// Check if it's a glob pattern
|
|
43
|
-
if (pattern.includes('*')) {
|
|
44
|
-
const result = await globExecute({ pattern, cwd: ctx.cwd, ignore: [], maxResults: 1000, includeDirectories: false });
|
|
45
|
-
for (const file of result.matches) {
|
|
46
|
-
const fullPath = resolve(ctx.cwd, file);
|
|
47
|
-
if (!ctx.activeFiles.has(fullPath)) {
|
|
48
|
-
ctx.activeFiles.add(fullPath);
|
|
49
|
-
ctx.io.output(`Added ${file}`);
|
|
50
|
-
added++;
|
|
51
|
-
}
|
|
52
|
-
}
|
|
53
|
-
}
|
|
54
|
-
else {
|
|
55
|
-
const fullPath = resolve(ctx.cwd, pattern);
|
|
56
|
-
if (existsSync(fullPath)) {
|
|
57
|
-
if (!ctx.activeFiles.has(fullPath)) {
|
|
58
|
-
ctx.activeFiles.add(fullPath);
|
|
59
|
-
ctx.io.output(`Added ${pattern}`);
|
|
60
|
-
added++;
|
|
61
|
-
}
|
|
62
|
-
}
|
|
63
|
-
else {
|
|
64
|
-
// File doesn't exist - offer to create it
|
|
65
|
-
const create = await ctx.io.confirm(`File ${pattern} doesn't exist. Create it?`);
|
|
66
|
-
if (create) {
|
|
67
|
-
await writeFile(fullPath, '');
|
|
68
|
-
ctx.activeFiles.add(fullPath);
|
|
69
|
-
ctx.io.output(`Created and added ${pattern}`);
|
|
70
|
-
added++;
|
|
71
|
-
}
|
|
72
|
-
}
|
|
73
|
-
}
|
|
74
|
-
}
|
|
75
|
-
ctx.io.output(`Added ${added} file(s) to the chat`);
|
|
76
|
-
},
|
|
77
|
-
},
|
|
78
|
-
{
|
|
79
|
-
name: 'drop',
|
|
80
|
-
aliases: ['d', 'remove'],
|
|
81
|
-
description: 'Remove files from the chat context',
|
|
82
|
-
execute: async (args, ctx) => {
|
|
83
|
-
if (!args) {
|
|
84
|
-
// Drop all files
|
|
85
|
-
const count = ctx.activeFiles.size;
|
|
86
|
-
ctx.activeFiles.clear();
|
|
87
|
-
ctx.io.output(`Dropped all ${count} file(s)`);
|
|
88
|
-
return;
|
|
89
|
-
}
|
|
90
|
-
const patterns = args.split(/\s+/);
|
|
91
|
-
let dropped = 0;
|
|
92
|
-
for (const pattern of patterns) {
|
|
93
|
-
const fullPath = resolve(ctx.cwd, pattern);
|
|
94
|
-
if (ctx.activeFiles.has(fullPath)) {
|
|
95
|
-
ctx.activeFiles.delete(fullPath);
|
|
96
|
-
ctx.io.output(`Dropped ${pattern}`);
|
|
97
|
-
dropped++;
|
|
98
|
-
}
|
|
99
|
-
}
|
|
100
|
-
ctx.io.output(`Dropped ${dropped} file(s)`);
|
|
101
|
-
},
|
|
102
|
-
},
|
|
103
|
-
{
|
|
104
|
-
name: 'ls',
|
|
105
|
-
aliases: ['files', 'list'],
|
|
106
|
-
description: 'List files in the chat context',
|
|
107
|
-
execute: async (args, ctx) => {
|
|
108
|
-
if (ctx.activeFiles.size === 0 && ctx.readOnlyFiles.size === 0) {
|
|
109
|
-
ctx.io.output('No files in chat context');
|
|
110
|
-
return;
|
|
111
|
-
}
|
|
112
|
-
if (ctx.activeFiles.size > 0) {
|
|
113
|
-
ctx.io.output('\nEditable files:');
|
|
114
|
-
for (const file of ctx.activeFiles) {
|
|
115
|
-
ctx.io.output(` ${relative(ctx.cwd, file)}`);
|
|
116
|
-
}
|
|
117
|
-
}
|
|
118
|
-
if (ctx.readOnlyFiles.size > 0) {
|
|
119
|
-
ctx.io.output('\nRead-only files:');
|
|
120
|
-
for (const file of ctx.readOnlyFiles) {
|
|
121
|
-
ctx.io.output(` ${relative(ctx.cwd, file)}`);
|
|
122
|
-
}
|
|
123
|
-
}
|
|
124
|
-
},
|
|
125
|
-
},
|
|
126
|
-
{
|
|
127
|
-
name: 'read-only',
|
|
128
|
-
aliases: ['ro'],
|
|
129
|
-
description: 'Add files as read-only context',
|
|
130
|
-
execute: async (args, ctx) => {
|
|
131
|
-
if (!args) {
|
|
132
|
-
// Convert all active files to read-only
|
|
133
|
-
for (const file of ctx.activeFiles) {
|
|
134
|
-
ctx.readOnlyFiles.add(file);
|
|
135
|
-
}
|
|
136
|
-
ctx.activeFiles.clear();
|
|
137
|
-
ctx.io.output('Converted all files to read-only');
|
|
138
|
-
return;
|
|
139
|
-
}
|
|
140
|
-
const patterns = args.split(/\s+/);
|
|
141
|
-
for (const pattern of patterns) {
|
|
142
|
-
if (pattern.includes('*')) {
|
|
143
|
-
const result = await globExecute({ pattern, cwd: ctx.cwd, maxResults: 1000, includeDirectories: false });
|
|
144
|
-
for (const file of result.matches) {
|
|
145
|
-
const fullPath = resolve(ctx.cwd, file);
|
|
146
|
-
ctx.readOnlyFiles.add(fullPath);
|
|
147
|
-
ctx.io.output(`Added ${file} as read-only`);
|
|
148
|
-
}
|
|
149
|
-
}
|
|
150
|
-
else {
|
|
151
|
-
const fullPath = resolve(ctx.cwd, pattern);
|
|
152
|
-
if (existsSync(fullPath)) {
|
|
153
|
-
ctx.readOnlyFiles.add(fullPath);
|
|
154
|
-
ctx.io.output(`Added ${pattern} as read-only`);
|
|
155
|
-
}
|
|
156
|
-
}
|
|
157
|
-
}
|
|
158
|
-
},
|
|
159
|
-
},
|
|
160
|
-
// Git Integration
|
|
161
|
-
{
|
|
162
|
-
name: 'git',
|
|
163
|
-
aliases: [],
|
|
164
|
-
description: 'Run a git command',
|
|
165
|
-
execute: async (args, ctx) => {
|
|
166
|
-
const { spawnSync } = await import('child_process');
|
|
167
|
-
const result = spawnSync('git', args.split(/\s+/), {
|
|
168
|
-
cwd: ctx.cwd,
|
|
169
|
-
encoding: 'utf-8',
|
|
170
|
-
});
|
|
171
|
-
if (result.stdout)
|
|
172
|
-
ctx.io.output(result.stdout);
|
|
173
|
-
if (result.stderr)
|
|
174
|
-
ctx.io.error(result.stderr);
|
|
175
|
-
},
|
|
176
|
-
},
|
|
177
|
-
{
|
|
178
|
-
name: 'diff',
|
|
179
|
-
aliases: [],
|
|
180
|
-
description: 'Show git diff of changes',
|
|
181
|
-
execute: async (args, ctx) => {
|
|
182
|
-
const { spawnSync } = await import('child_process');
|
|
183
|
-
const gitArgs = args ? args.split(/\s+/) : [];
|
|
184
|
-
const result = spawnSync('git', ['diff', '--no-color', ...gitArgs], {
|
|
185
|
-
cwd: ctx.cwd,
|
|
186
|
-
encoding: 'utf-8',
|
|
187
|
-
});
|
|
188
|
-
if (result.stdout) {
|
|
189
|
-
ctx.io.output(result.stdout);
|
|
190
|
-
}
|
|
191
|
-
else {
|
|
192
|
-
ctx.io.output('No changes');
|
|
193
|
-
}
|
|
194
|
-
},
|
|
195
|
-
},
|
|
196
|
-
{
|
|
197
|
-
name: 'commit',
|
|
198
|
-
aliases: [],
|
|
199
|
-
description: 'Commit staged changes with AI-generated message',
|
|
200
|
-
execute: async (args, ctx) => {
|
|
201
|
-
const diff = getStagedDiff(ctx.cwd);
|
|
202
|
-
if (!diff) {
|
|
203
|
-
ctx.io.output('No staged changes to commit');
|
|
204
|
-
return;
|
|
205
|
-
}
|
|
206
|
-
const message = args || 'Update files';
|
|
207
|
-
const { spawnSync } = await import('child_process');
|
|
208
|
-
const result = spawnSync('git', ['commit', '-m', message], {
|
|
209
|
-
cwd: ctx.cwd,
|
|
210
|
-
encoding: 'utf-8',
|
|
211
|
-
});
|
|
212
|
-
if (result.stdout)
|
|
213
|
-
ctx.io.output(result.stdout);
|
|
214
|
-
if (result.stderr)
|
|
215
|
-
ctx.io.error(result.stderr);
|
|
216
|
-
},
|
|
217
|
-
},
|
|
218
|
-
// Search
|
|
219
|
-
{
|
|
220
|
-
name: 'search',
|
|
221
|
-
aliases: ['grep', 'find'],
|
|
222
|
-
description: 'Search for pattern in files',
|
|
223
|
-
execute: async (args, ctx) => {
|
|
224
|
-
if (!args) {
|
|
225
|
-
ctx.io.output('Usage: /search <pattern> [path]');
|
|
226
|
-
return;
|
|
227
|
-
}
|
|
228
|
-
const parts = args.split(/\s+/);
|
|
229
|
-
const pattern = parts[0];
|
|
230
|
-
const path = parts[1] || ctx.cwd;
|
|
231
|
-
const result = await grepExecute({
|
|
232
|
-
pattern,
|
|
233
|
-
path,
|
|
234
|
-
maxResults: 50,
|
|
235
|
-
ignoreCase: true,
|
|
236
|
-
contextLines: 2,
|
|
237
|
-
filesOnly: false,
|
|
238
|
-
includeHidden: false,
|
|
239
|
-
});
|
|
240
|
-
if (result.matches.length === 0) {
|
|
241
|
-
ctx.io.output('No matches found');
|
|
242
|
-
return;
|
|
243
|
-
}
|
|
244
|
-
ctx.io.output(`Found ${result.count} matches in ${result.files.length} file(s):`);
|
|
245
|
-
for (const match of result.matches.slice(0, 20)) {
|
|
246
|
-
ctx.io.output(` ${match.file}:${match.line}: ${match.text.trim()}`);
|
|
247
|
-
}
|
|
248
|
-
if (result.truncated) {
|
|
249
|
-
ctx.io.output(` ... and more (truncated)`);
|
|
250
|
-
}
|
|
251
|
-
},
|
|
252
|
-
},
|
|
253
|
-
// Chat Management
|
|
254
|
-
{
|
|
255
|
-
name: 'clear',
|
|
256
|
-
aliases: ['reset'],
|
|
257
|
-
description: 'Clear chat history',
|
|
258
|
-
execute: async (args, ctx) => {
|
|
259
|
-
ctx.history.length = 0;
|
|
260
|
-
ctx.io.output('Chat history cleared');
|
|
261
|
-
},
|
|
262
|
-
},
|
|
263
|
-
{
|
|
264
|
-
name: 'undo',
|
|
265
|
-
aliases: [],
|
|
266
|
-
description: 'Undo the last git commit made by the AI',
|
|
267
|
-
execute: async (args, ctx) => {
|
|
268
|
-
const { spawnSync } = await import('child_process');
|
|
269
|
-
const result = spawnSync('git', ['reset', '--soft', 'HEAD~1'], {
|
|
270
|
-
cwd: ctx.cwd,
|
|
271
|
-
encoding: 'utf-8',
|
|
272
|
-
});
|
|
273
|
-
if (result.status === 0) {
|
|
274
|
-
ctx.io.output('Undid last commit');
|
|
275
|
-
}
|
|
276
|
-
else {
|
|
277
|
-
ctx.io.error('Failed to undo commit');
|
|
278
|
-
}
|
|
279
|
-
},
|
|
280
|
-
},
|
|
281
|
-
// Context
|
|
282
|
-
{
|
|
283
|
-
name: 'tokens',
|
|
284
|
-
aliases: [],
|
|
285
|
-
description: 'Show approximate token count',
|
|
286
|
-
execute: async (args, ctx) => {
|
|
287
|
-
let totalChars = 0;
|
|
288
|
-
for (const file of ctx.activeFiles) {
|
|
289
|
-
try {
|
|
290
|
-
const content = await readFile(file, 'utf-8');
|
|
291
|
-
totalChars += content.length;
|
|
292
|
-
}
|
|
293
|
-
catch { }
|
|
294
|
-
}
|
|
295
|
-
for (const file of ctx.readOnlyFiles) {
|
|
296
|
-
try {
|
|
297
|
-
const content = await readFile(file, 'utf-8');
|
|
298
|
-
totalChars += content.length;
|
|
299
|
-
}
|
|
300
|
-
catch { }
|
|
301
|
-
}
|
|
302
|
-
for (const msg of ctx.history) {
|
|
303
|
-
totalChars += msg.content.length;
|
|
304
|
-
}
|
|
305
|
-
// Rough estimate: ~4 chars per token
|
|
306
|
-
const estimatedTokens = Math.ceil(totalChars / 4);
|
|
307
|
-
ctx.io.output(`Approximate tokens: ${estimatedTokens.toLocaleString()}`);
|
|
308
|
-
ctx.io.output(` Files: ${ctx.activeFiles.size} editable, ${ctx.readOnlyFiles.size} read-only`);
|
|
309
|
-
ctx.io.output(` History: ${ctx.history.length} messages`);
|
|
310
|
-
},
|
|
311
|
-
},
|
|
312
|
-
// MCP
|
|
313
|
-
{
|
|
314
|
-
name: 'mcp',
|
|
315
|
-
aliases: [],
|
|
316
|
-
description: 'MCP server management',
|
|
317
|
-
execute: async (args, ctx) => {
|
|
318
|
-
const manager = getMCPManager();
|
|
319
|
-
const parts = args.split(/\s+/);
|
|
320
|
-
const subcommand = parts[0] || 'status';
|
|
321
|
-
switch (subcommand) {
|
|
322
|
-
case 'status': {
|
|
323
|
-
const statuses = manager.getAllServerStatuses();
|
|
324
|
-
if (statuses.size === 0) {
|
|
325
|
-
ctx.io.output('No MCP servers configured');
|
|
326
|
-
return;
|
|
327
|
-
}
|
|
328
|
-
ctx.io.output('MCP Servers:');
|
|
329
|
-
for (const [name, status] of statuses) {
|
|
330
|
-
ctx.io.output(` ${name}: ${status}`);
|
|
331
|
-
}
|
|
332
|
-
break;
|
|
333
|
-
}
|
|
334
|
-
case 'tools': {
|
|
335
|
-
const tools = manager.getAllTools();
|
|
336
|
-
if (tools.length === 0) {
|
|
337
|
-
ctx.io.output('No MCP tools available');
|
|
338
|
-
return;
|
|
339
|
-
}
|
|
340
|
-
ctx.io.output(`MCP Tools (${tools.length}):`);
|
|
341
|
-
for (const tool of tools) {
|
|
342
|
-
ctx.io.output(` ${tool.name} (${tool.serverName}): ${tool.description}`);
|
|
343
|
-
}
|
|
344
|
-
break;
|
|
345
|
-
}
|
|
346
|
-
case 'connect': {
|
|
347
|
-
await manager.connectAll();
|
|
348
|
-
ctx.io.output('Connected to MCP servers');
|
|
349
|
-
break;
|
|
350
|
-
}
|
|
351
|
-
case 'disconnect': {
|
|
352
|
-
await manager.disconnectAll();
|
|
353
|
-
ctx.io.output('Disconnected from MCP servers');
|
|
354
|
-
break;
|
|
355
|
-
}
|
|
356
|
-
default:
|
|
357
|
-
ctx.io.output('Usage: /mcp [status|tools|connect|disconnect]');
|
|
358
|
-
}
|
|
359
|
-
},
|
|
360
|
-
},
|
|
361
|
-
// Web
|
|
362
|
-
{
|
|
363
|
-
name: 'web',
|
|
364
|
-
aliases: ['url', 'fetch'],
|
|
365
|
-
description: 'Fetch a URL and add to context',
|
|
366
|
-
execute: async (args, ctx) => {
|
|
367
|
-
if (!args) {
|
|
368
|
-
ctx.io.output('Usage: /web <url>');
|
|
369
|
-
return;
|
|
370
|
-
}
|
|
371
|
-
const { execute: scrapeExecute } = await import('./tools/scraper.js');
|
|
372
|
-
const result = await scrapeExecute({ url: args, convertToMarkdown: true, verifySSL: true, timeout: 10000 });
|
|
373
|
-
if (result.error) {
|
|
374
|
-
ctx.io.error(`Failed to fetch: ${result.error}`);
|
|
375
|
-
return;
|
|
376
|
-
}
|
|
377
|
-
ctx.io.output(`Fetched ${args} (${result.content.length} chars)`);
|
|
378
|
-
// Add to history as context
|
|
379
|
-
ctx.history.push({
|
|
380
|
-
role: 'user',
|
|
381
|
-
content: `Content from ${args}:\n\n${result.content}`,
|
|
382
|
-
});
|
|
383
|
-
},
|
|
384
|
-
},
|
|
385
|
-
// Help
|
|
386
|
-
{
|
|
387
|
-
name: 'help',
|
|
388
|
-
aliases: ['h', '?'],
|
|
389
|
-
description: 'Show available commands',
|
|
390
|
-
execute: async (args, ctx) => {
|
|
391
|
-
ctx.io.output('\nAvailable commands:\n');
|
|
392
|
-
for (const cmd of commands) {
|
|
393
|
-
const aliases = cmd.aliases.length > 0 ? ` (${cmd.aliases.join(', ')})` : '';
|
|
394
|
-
ctx.io.output(` /${cmd.name}${aliases}`);
|
|
395
|
-
ctx.io.output(` ${cmd.description}\n`);
|
|
396
|
-
}
|
|
397
|
-
},
|
|
398
|
-
},
|
|
399
|
-
// Exit
|
|
400
|
-
{
|
|
401
|
-
name: 'exit',
|
|
402
|
-
aliases: ['quit', 'q'],
|
|
403
|
-
description: 'Exit the CLI',
|
|
404
|
-
execute: async (args, ctx) => {
|
|
405
|
-
ctx.io.output('Goodbye!');
|
|
406
|
-
process.exit(0);
|
|
407
|
-
},
|
|
408
|
-
},
|
|
409
|
-
];
|
|
410
|
-
// Find command by name or alias
|
|
411
|
-
export function findCommand(name) {
|
|
412
|
-
const lower = name.toLowerCase();
|
|
413
|
-
return commands.find(cmd => cmd.name === lower || cmd.aliases.includes(lower));
|
|
414
|
-
}
|
|
415
|
-
// Execute a command
|
|
416
|
-
export async function executeCommand(input, context) {
|
|
417
|
-
const parsed = parseCommand(input);
|
|
418
|
-
if (!parsed) {
|
|
419
|
-
return undefined; // Not a command
|
|
420
|
-
}
|
|
421
|
-
const command = findCommand(parsed.command);
|
|
422
|
-
if (!command) {
|
|
423
|
-
context.io.error(`Unknown command: /${parsed.command}. Type /help for available commands.`);
|
|
424
|
-
return;
|
|
425
|
-
}
|
|
426
|
-
return command.execute(parsed.args, context);
|
|
427
|
-
}
|
package/dist/context.d.ts
DELETED
|
@@ -1,116 +0,0 @@
|
|
|
1
|
-
/**
|
|
2
|
-
* Context Manager - Manages conversation context and file state
|
|
3
|
-
* Based on Aider's coder.py and GeminiCLI's context management
|
|
4
|
-
* Uses gpt-tokenizer for accurate token counting (with fallback)
|
|
5
|
-
*/
|
|
6
|
-
import { type Skill } from './skills.js';
|
|
7
|
-
import { type Tool } from './registry.js';
|
|
8
|
-
export interface Message {
|
|
9
|
-
role: 'user' | 'assistant' | 'system';
|
|
10
|
-
content: string;
|
|
11
|
-
timestamp?: number;
|
|
12
|
-
}
|
|
13
|
-
export interface ContextState {
|
|
14
|
-
cwd: string;
|
|
15
|
-
activeFiles: Set<string>;
|
|
16
|
-
readOnlyFiles: Set<string>;
|
|
17
|
-
history: Message[];
|
|
18
|
-
skill: Skill;
|
|
19
|
-
tokenEstimate: number;
|
|
20
|
-
}
|
|
21
|
-
/**
|
|
22
|
-
* Synchronous token count (uses cached encoder or estimation)
|
|
23
|
-
*/
|
|
24
|
-
declare function countTokens(text: string): number;
|
|
25
|
-
/**
|
|
26
|
-
* ContextManager class
|
|
27
|
-
* Manages the conversation context, file state, and system prompts
|
|
28
|
-
*/
|
|
29
|
-
export declare class ContextManager {
|
|
30
|
-
private cwd;
|
|
31
|
-
private activeFiles;
|
|
32
|
-
private readOnlyFiles;
|
|
33
|
-
private history;
|
|
34
|
-
private skill;
|
|
35
|
-
private tools;
|
|
36
|
-
private repoMapCache;
|
|
37
|
-
private repoMapTimestamp;
|
|
38
|
-
constructor(cwd?: string);
|
|
39
|
-
/**
|
|
40
|
-
* Initialize the context manager
|
|
41
|
-
*/
|
|
42
|
-
initialize(): Promise<void>;
|
|
43
|
-
/**
|
|
44
|
-
* Add a file to active context
|
|
45
|
-
*/
|
|
46
|
-
addFile(path: string, readOnly?: boolean): boolean;
|
|
47
|
-
/**
|
|
48
|
-
* Remove a file from context
|
|
49
|
-
*/
|
|
50
|
-
removeFile(path: string): boolean;
|
|
51
|
-
/**
|
|
52
|
-
* Add a message to history
|
|
53
|
-
*/
|
|
54
|
-
addMessage(role: Message['role'], content: string): void;
|
|
55
|
-
/**
|
|
56
|
-
* Clear conversation history
|
|
57
|
-
*/
|
|
58
|
-
clearHistory(): void;
|
|
59
|
-
/**
|
|
60
|
-
* Get all files in context
|
|
61
|
-
*/
|
|
62
|
-
getFiles(): {
|
|
63
|
-
active: string[];
|
|
64
|
-
readOnly: string[];
|
|
65
|
-
};
|
|
66
|
-
/**
|
|
67
|
-
* Read all files in context
|
|
68
|
-
*/
|
|
69
|
-
getFileContents(): Promise<Map<string, string>>;
|
|
70
|
-
/**
|
|
71
|
-
* Set the active skill
|
|
72
|
-
*/
|
|
73
|
-
setSkill(skill: Skill): void;
|
|
74
|
-
/**
|
|
75
|
-
* Get the current skill
|
|
76
|
-
*/
|
|
77
|
-
getSkill(): Skill;
|
|
78
|
-
/**
|
|
79
|
-
* Refresh the repository map
|
|
80
|
-
*/
|
|
81
|
-
refreshRepoMap(): Promise<string>;
|
|
82
|
-
/**
|
|
83
|
-
* Build the system prompt
|
|
84
|
-
*/
|
|
85
|
-
buildSystemPrompt(): Promise<string>;
|
|
86
|
-
/**
|
|
87
|
-
* Build messages for LLM
|
|
88
|
-
*/
|
|
89
|
-
buildMessages(userMessage: string): Promise<Message[]>;
|
|
90
|
-
/**
|
|
91
|
-
* Estimate token count using accurate tokenizer
|
|
92
|
-
*/
|
|
93
|
-
estimateTokenCount(): Promise<number>;
|
|
94
|
-
/**
|
|
95
|
-
* Get current state
|
|
96
|
-
*/
|
|
97
|
-
getState(): ContextState;
|
|
98
|
-
/**
|
|
99
|
-
* Restore state
|
|
100
|
-
*/
|
|
101
|
-
restoreState(state: Partial<ContextState>): void;
|
|
102
|
-
/**
|
|
103
|
-
* Get conversation history
|
|
104
|
-
*/
|
|
105
|
-
getHistory(): Message[];
|
|
106
|
-
/**
|
|
107
|
-
* Get tools
|
|
108
|
-
*/
|
|
109
|
-
getTools(): Map<string, Tool>;
|
|
110
|
-
/**
|
|
111
|
-
* Get working directory
|
|
112
|
-
*/
|
|
113
|
-
getCwd(): string;
|
|
114
|
-
}
|
|
115
|
-
export declare function getContextManager(cwd?: string): ContextManager;
|
|
116
|
-
export { countTokens };
|