@stan-chen/simple-cli 0.2.2 → 0.2.4
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 +58 -271
- 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 +37 -279
- 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 +66 -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 +10 -0
- package/package.json +88 -78
- 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 -97
- 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 -376
- 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 -327
- package/dist/index.d.ts +0 -6
- package/dist/index.js +0 -109
- package/dist/lib/agent.d.ts +0 -98
- package/dist/lib/agent.js +0 -281
- 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 -351
- package/dist/lib/ui.d.ts +0 -159
- package/dist/lib/ui.js +0 -252
- 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 -78
- package/dist/providers/index.d.ts +0 -15
- package/dist/providers/index.js +0 -82
- package/dist/providers/multi.d.ts +0 -11
- package/dist/providers/multi.js +0 -28
- package/dist/registry.d.ts +0 -24
- package/dist/registry.js +0 -379
- 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 -108
- 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 -107
- package/dist/swarm/worker.js +0 -299
- package/dist/tools/analyzeFile.d.ts +0 -16
- package/dist/tools/analyzeFile.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 -349
- package/dist/tools/listDir.d.ts +0 -29
- package/dist/tools/listDir.js +0 -50
- package/dist/tools/memory.d.ts +0 -34
- package/dist/tools/memory.js +0 -215
- package/dist/tools/readFiles.d.ts +0 -25
- package/dist/tools/readFiles.js +0 -31
- package/dist/tools/reloadTools.d.ts +0 -11
- package/dist/tools/reloadTools.js +0 -22
- package/dist/tools/runCommand.d.ts +0 -32
- package/dist/tools/runCommand.js +0 -79
- 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/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/tools/linter.js
DELETED
|
@@ -1,349 +0,0 @@
|
|
|
1
|
-
/**
|
|
2
|
-
* Linter Tool - Checks code for syntax errors
|
|
3
|
-
* Based on Aider's linter.py
|
|
4
|
-
*/
|
|
5
|
-
import { z } from 'zod';
|
|
6
|
-
import { execSync, spawnSync } from 'child_process';
|
|
7
|
-
import { readFileSync, existsSync } from 'fs';
|
|
8
|
-
import { extname, basename } from 'path';
|
|
9
|
-
// Input schema
|
|
10
|
-
export const inputSchema = z.object({
|
|
11
|
-
path: z.string().describe('Path to file to lint'),
|
|
12
|
-
fix: z.boolean().optional().default(false).describe('Attempt to auto-fix issues'),
|
|
13
|
-
});
|
|
14
|
-
// Language detection based on file extension
|
|
15
|
-
const LANGUAGE_MAP = {
|
|
16
|
-
'.py': 'python',
|
|
17
|
-
'.js': 'javascript',
|
|
18
|
-
'.jsx': 'javascript',
|
|
19
|
-
'.ts': 'typescript',
|
|
20
|
-
'.tsx': 'typescript',
|
|
21
|
-
'.rb': 'ruby',
|
|
22
|
-
'.go': 'go',
|
|
23
|
-
'.rs': 'rust',
|
|
24
|
-
'.java': 'java',
|
|
25
|
-
'.c': 'c',
|
|
26
|
-
'.cpp': 'cpp',
|
|
27
|
-
'.h': 'c',
|
|
28
|
-
'.hpp': 'cpp',
|
|
29
|
-
'.cs': 'csharp',
|
|
30
|
-
'.php': 'php',
|
|
31
|
-
'.swift': 'swift',
|
|
32
|
-
'.kt': 'kotlin',
|
|
33
|
-
'.scala': 'scala',
|
|
34
|
-
'.sh': 'shell',
|
|
35
|
-
'.bash': 'shell',
|
|
36
|
-
'.zsh': 'shell',
|
|
37
|
-
};
|
|
38
|
-
// Detect language from file
|
|
39
|
-
function detectLanguage(filePath) {
|
|
40
|
-
const ext = extname(filePath).toLowerCase();
|
|
41
|
-
return LANGUAGE_MAP[ext] || null;
|
|
42
|
-
}
|
|
43
|
-
// Parse error output for line numbers
|
|
44
|
-
function parseErrors(output, filePath) {
|
|
45
|
-
const errors = [];
|
|
46
|
-
const fileName = basename(filePath);
|
|
47
|
-
const escapedFileName = fileName.replace(/[.*+?^${}()|[\]\\]/g, '\\$&');
|
|
48
|
-
const escapedFilePath = filePath.replace(/[.*+?^${}()|[\]\\]/g, '\\$&');
|
|
49
|
-
// Common patterns for error messages: file:line:col: message
|
|
50
|
-
// groups: [lineIndex, columnIndex (or -1), messageIndex (or -1)]
|
|
51
|
-
const patterns = [
|
|
52
|
-
// Python/flake8/eslint style: file.py:10:5: E501 line too long
|
|
53
|
-
{ regex: new RegExp(`(?:${escapedFileName}|${escapedFilePath}):(\\d+)(?::(\\d+))?:\\s*(.+)`, 'gm'), groups: [1, 2, 3] },
|
|
54
|
-
// TypeScript/tsc style: file.ts(10,5): error TS1234: message
|
|
55
|
-
{ regex: new RegExp(`(?:${escapedFileName}|${escapedFilePath})\\((\\d+),(\\d+)\\):\\s*(\\w+)\\s+(.+)`, 'gm'), groups: [1, 2, 4] },
|
|
56
|
-
// Python py_compile style: File "file.py", line 10
|
|
57
|
-
{ regex: /File\s+"[^"]+",\s+line\s+(\d+)/gim, groups: [1, -1, -1] },
|
|
58
|
-
// Generic line number: line 10: message
|
|
59
|
-
{ regex: /line\s+(\d+):\s*(.+)/gim, groups: [1, -1, 2] },
|
|
60
|
-
];
|
|
61
|
-
// Also capture standalone error messages like "SyntaxError: ..."
|
|
62
|
-
const syntaxErrorMatch = output.match(/(SyntaxError|IndentationError|TabError):\s*(.+)/i);
|
|
63
|
-
const syntaxErrorMessage = syntaxErrorMatch ? `${syntaxErrorMatch[1]}: ${syntaxErrorMatch[2]}` : null;
|
|
64
|
-
for (const { regex, groups } of patterns) {
|
|
65
|
-
let match;
|
|
66
|
-
while ((match = regex.exec(output)) !== null) {
|
|
67
|
-
const [lineIdx, colIdx, msgIdx] = groups;
|
|
68
|
-
const line = parseInt(match[lineIdx], 10);
|
|
69
|
-
const column = colIdx >= 0 && match[colIdx] ? parseInt(match[colIdx], 10) : undefined;
|
|
70
|
-
let message = msgIdx >= 0 && match[msgIdx] ? match[msgIdx].trim() : '';
|
|
71
|
-
// Use syntax error message if we found one and this pattern doesn't have a message
|
|
72
|
-
if (!message && syntaxErrorMessage) {
|
|
73
|
-
message = syntaxErrorMessage;
|
|
74
|
-
}
|
|
75
|
-
if (line > 0) {
|
|
76
|
-
errors.push({
|
|
77
|
-
line,
|
|
78
|
-
column,
|
|
79
|
-
message: message || 'Syntax error',
|
|
80
|
-
severity: 'error',
|
|
81
|
-
});
|
|
82
|
-
}
|
|
83
|
-
}
|
|
84
|
-
}
|
|
85
|
-
// Deduplicate errors by line number
|
|
86
|
-
const seen = new Set();
|
|
87
|
-
return errors.filter(e => {
|
|
88
|
-
if (seen.has(e.line))
|
|
89
|
-
return false;
|
|
90
|
-
seen.add(e.line);
|
|
91
|
-
return true;
|
|
92
|
-
});
|
|
93
|
-
}
|
|
94
|
-
// Python syntax check using compile
|
|
95
|
-
function lintPython(filePath, code) {
|
|
96
|
-
const errors = [];
|
|
97
|
-
let output = '';
|
|
98
|
-
// Try Python syntax check
|
|
99
|
-
try {
|
|
100
|
-
const result = spawnSync('python3', ['-m', 'py_compile', filePath], {
|
|
101
|
-
encoding: 'utf-8',
|
|
102
|
-
timeout: 10000,
|
|
103
|
-
});
|
|
104
|
-
if (result.status !== 0) {
|
|
105
|
-
output = result.stderr || result.stdout || '';
|
|
106
|
-
errors.push(...parseErrors(output, filePath));
|
|
107
|
-
}
|
|
108
|
-
}
|
|
109
|
-
catch {
|
|
110
|
-
// Fall back to basic syntax check
|
|
111
|
-
try {
|
|
112
|
-
execSync(`python3 -c "compile(open('${filePath}').read(), '${filePath}', 'exec')"`, {
|
|
113
|
-
encoding: 'utf-8',
|
|
114
|
-
timeout: 10000,
|
|
115
|
-
});
|
|
116
|
-
}
|
|
117
|
-
catch (e) {
|
|
118
|
-
if (e instanceof Error) {
|
|
119
|
-
output = e.message;
|
|
120
|
-
errors.push(...parseErrors(output, filePath));
|
|
121
|
-
}
|
|
122
|
-
}
|
|
123
|
-
}
|
|
124
|
-
// Try flake8 for additional checks
|
|
125
|
-
try {
|
|
126
|
-
const result = spawnSync('python3', ['-m', 'flake8', '--select=E9,F821,F823,F831,F406,F407,F701,F702,F704,F706', filePath], {
|
|
127
|
-
encoding: 'utf-8',
|
|
128
|
-
timeout: 10000,
|
|
129
|
-
});
|
|
130
|
-
if (result.stdout) {
|
|
131
|
-
output += '\n' + result.stdout;
|
|
132
|
-
errors.push(...parseErrors(result.stdout, filePath));
|
|
133
|
-
}
|
|
134
|
-
}
|
|
135
|
-
catch {
|
|
136
|
-
// flake8 not available, skip
|
|
137
|
-
}
|
|
138
|
-
return {
|
|
139
|
-
file: filePath,
|
|
140
|
-
language: 'python',
|
|
141
|
-
errors: errors.filter(e => e.severity === 'error'),
|
|
142
|
-
warnings: errors.filter(e => e.severity === 'warning'),
|
|
143
|
-
passed: errors.filter(e => e.severity === 'error').length === 0,
|
|
144
|
-
output: output.trim(),
|
|
145
|
-
};
|
|
146
|
-
}
|
|
147
|
-
// JavaScript/TypeScript linting
|
|
148
|
-
function lintJavaScript(filePath, code, isTypeScript) {
|
|
149
|
-
const errors = [];
|
|
150
|
-
let output = '';
|
|
151
|
-
const language = isTypeScript ? 'typescript' : 'javascript';
|
|
152
|
-
// Basic syntax check using Node.js
|
|
153
|
-
try {
|
|
154
|
-
if (isTypeScript) {
|
|
155
|
-
// Try tsc for TypeScript
|
|
156
|
-
const result = spawnSync('npx', ['tsc', '--noEmit', '--skipLibCheck', filePath], {
|
|
157
|
-
encoding: 'utf-8',
|
|
158
|
-
timeout: 30000,
|
|
159
|
-
});
|
|
160
|
-
if (result.status !== 0) {
|
|
161
|
-
output = (result.stdout || '') + (result.stderr || '');
|
|
162
|
-
errors.push(...parseErrors(output, filePath));
|
|
163
|
-
}
|
|
164
|
-
}
|
|
165
|
-
else {
|
|
166
|
-
// Use Node's vm module for JavaScript syntax check
|
|
167
|
-
const result = spawnSync('node', ['--check', filePath], {
|
|
168
|
-
encoding: 'utf-8',
|
|
169
|
-
timeout: 10000,
|
|
170
|
-
});
|
|
171
|
-
if (result.status !== 0) {
|
|
172
|
-
output = result.stderr || '';
|
|
173
|
-
errors.push(...parseErrors(output, filePath));
|
|
174
|
-
}
|
|
175
|
-
}
|
|
176
|
-
}
|
|
177
|
-
catch (e) {
|
|
178
|
-
if (e instanceof Error) {
|
|
179
|
-
output = e.message;
|
|
180
|
-
}
|
|
181
|
-
}
|
|
182
|
-
// Try ESLint
|
|
183
|
-
try {
|
|
184
|
-
const result = spawnSync('npx', ['eslint', '--format', 'compact', filePath], {
|
|
185
|
-
encoding: 'utf-8',
|
|
186
|
-
timeout: 30000,
|
|
187
|
-
});
|
|
188
|
-
if (result.stdout) {
|
|
189
|
-
output += '\n' + result.stdout;
|
|
190
|
-
errors.push(...parseErrors(result.stdout, filePath));
|
|
191
|
-
}
|
|
192
|
-
}
|
|
193
|
-
catch {
|
|
194
|
-
// ESLint not available
|
|
195
|
-
}
|
|
196
|
-
return {
|
|
197
|
-
file: filePath,
|
|
198
|
-
language,
|
|
199
|
-
errors: errors.filter(e => e.severity === 'error'),
|
|
200
|
-
warnings: errors.filter(e => e.severity === 'warning'),
|
|
201
|
-
passed: errors.filter(e => e.severity === 'error').length === 0,
|
|
202
|
-
output: output.trim(),
|
|
203
|
-
};
|
|
204
|
-
}
|
|
205
|
-
// Go linting
|
|
206
|
-
function lintGo(filePath) {
|
|
207
|
-
const errors = [];
|
|
208
|
-
let output = '';
|
|
209
|
-
try {
|
|
210
|
-
const result = spawnSync('go', ['vet', filePath], {
|
|
211
|
-
encoding: 'utf-8',
|
|
212
|
-
timeout: 30000,
|
|
213
|
-
});
|
|
214
|
-
output = result.stderr + result.stdout;
|
|
215
|
-
if (result.status !== 0) {
|
|
216
|
-
errors.push(...parseErrors(output, filePath));
|
|
217
|
-
}
|
|
218
|
-
}
|
|
219
|
-
catch (e) {
|
|
220
|
-
if (e instanceof Error) {
|
|
221
|
-
output = e.message;
|
|
222
|
-
}
|
|
223
|
-
}
|
|
224
|
-
return {
|
|
225
|
-
file: filePath,
|
|
226
|
-
language: 'go',
|
|
227
|
-
errors: errors.filter(e => e.severity === 'error'),
|
|
228
|
-
warnings: errors.filter(e => e.severity === 'warning'),
|
|
229
|
-
passed: errors.filter(e => e.severity === 'error').length === 0,
|
|
230
|
-
output: output.trim(),
|
|
231
|
-
};
|
|
232
|
-
}
|
|
233
|
-
// Rust linting
|
|
234
|
-
function lintRust(filePath) {
|
|
235
|
-
const errors = [];
|
|
236
|
-
let output = '';
|
|
237
|
-
try {
|
|
238
|
-
const result = spawnSync('rustc', ['--emit=metadata', '-o', '/dev/null', filePath], {
|
|
239
|
-
encoding: 'utf-8',
|
|
240
|
-
timeout: 30000,
|
|
241
|
-
});
|
|
242
|
-
output = result.stderr + result.stdout;
|
|
243
|
-
if (result.status !== 0) {
|
|
244
|
-
errors.push(...parseErrors(output, filePath));
|
|
245
|
-
}
|
|
246
|
-
}
|
|
247
|
-
catch (e) {
|
|
248
|
-
if (e instanceof Error) {
|
|
249
|
-
output = e.message;
|
|
250
|
-
}
|
|
251
|
-
}
|
|
252
|
-
return {
|
|
253
|
-
file: filePath,
|
|
254
|
-
language: 'rust',
|
|
255
|
-
errors: errors.filter(e => e.severity === 'error'),
|
|
256
|
-
warnings: errors.filter(e => e.severity === 'warning'),
|
|
257
|
-
passed: errors.filter(e => e.severity === 'error').length === 0,
|
|
258
|
-
output: output.trim(),
|
|
259
|
-
};
|
|
260
|
-
}
|
|
261
|
-
// Generic shell linting
|
|
262
|
-
function lintShell(filePath) {
|
|
263
|
-
const errors = [];
|
|
264
|
-
let output = '';
|
|
265
|
-
try {
|
|
266
|
-
const result = spawnSync('bash', ['-n', filePath], {
|
|
267
|
-
encoding: 'utf-8',
|
|
268
|
-
timeout: 10000,
|
|
269
|
-
});
|
|
270
|
-
output = result.stderr + result.stdout;
|
|
271
|
-
if (result.status !== 0) {
|
|
272
|
-
errors.push(...parseErrors(output, filePath));
|
|
273
|
-
}
|
|
274
|
-
}
|
|
275
|
-
catch (e) {
|
|
276
|
-
if (e instanceof Error) {
|
|
277
|
-
output = e.message;
|
|
278
|
-
}
|
|
279
|
-
}
|
|
280
|
-
// Try shellcheck
|
|
281
|
-
try {
|
|
282
|
-
const result = spawnSync('shellcheck', ['-f', 'gcc', filePath], {
|
|
283
|
-
encoding: 'utf-8',
|
|
284
|
-
timeout: 10000,
|
|
285
|
-
});
|
|
286
|
-
if (result.stdout) {
|
|
287
|
-
output += '\n' + result.stdout;
|
|
288
|
-
errors.push(...parseErrors(result.stdout, filePath));
|
|
289
|
-
}
|
|
290
|
-
}
|
|
291
|
-
catch {
|
|
292
|
-
// shellcheck not available
|
|
293
|
-
}
|
|
294
|
-
return {
|
|
295
|
-
file: filePath,
|
|
296
|
-
language: 'shell',
|
|
297
|
-
errors: errors.filter(e => e.severity === 'error'),
|
|
298
|
-
warnings: errors.filter(e => e.severity === 'warning'),
|
|
299
|
-
passed: errors.filter(e => e.severity === 'error').length === 0,
|
|
300
|
-
output: output.trim(),
|
|
301
|
-
};
|
|
302
|
-
}
|
|
303
|
-
// Execute linting
|
|
304
|
-
export async function execute(input) {
|
|
305
|
-
const { path: filePath } = inputSchema.parse(input);
|
|
306
|
-
if (!existsSync(filePath)) {
|
|
307
|
-
return {
|
|
308
|
-
file: filePath,
|
|
309
|
-
language: 'unknown',
|
|
310
|
-
errors: [{ line: 0, message: 'File not found', severity: 'error' }],
|
|
311
|
-
warnings: [],
|
|
312
|
-
passed: false,
|
|
313
|
-
output: 'File not found',
|
|
314
|
-
};
|
|
315
|
-
}
|
|
316
|
-
const language = detectLanguage(filePath);
|
|
317
|
-
const code = readFileSync(filePath, 'utf-8');
|
|
318
|
-
switch (language) {
|
|
319
|
-
case 'python':
|
|
320
|
-
return lintPython(filePath, code);
|
|
321
|
-
case 'javascript':
|
|
322
|
-
return lintJavaScript(filePath, code, false);
|
|
323
|
-
case 'typescript':
|
|
324
|
-
return lintJavaScript(filePath, code, true);
|
|
325
|
-
case 'go':
|
|
326
|
-
return lintGo(filePath);
|
|
327
|
-
case 'rust':
|
|
328
|
-
return lintRust(filePath);
|
|
329
|
-
case 'shell':
|
|
330
|
-
return lintShell(filePath);
|
|
331
|
-
default:
|
|
332
|
-
return {
|
|
333
|
-
file: filePath,
|
|
334
|
-
language: language || 'unknown',
|
|
335
|
-
errors: [],
|
|
336
|
-
warnings: [],
|
|
337
|
-
passed: true,
|
|
338
|
-
output: `No linter available for ${language || 'unknown language'}`,
|
|
339
|
-
};
|
|
340
|
-
}
|
|
341
|
-
}
|
|
342
|
-
// Tool definition
|
|
343
|
-
export const tool = {
|
|
344
|
-
name: 'lint',
|
|
345
|
-
description: 'Check a source file for syntax errors and code quality issues. Supports Python, JavaScript, TypeScript, Go, Rust, and shell scripts.',
|
|
346
|
-
inputSchema,
|
|
347
|
-
permission: 'read',
|
|
348
|
-
execute: async (args) => execute(args),
|
|
349
|
-
};
|
package/dist/tools/listDir.d.ts
DELETED
|
@@ -1,29 +0,0 @@
|
|
|
1
|
-
/**
|
|
2
|
-
* Tool: listDir
|
|
3
|
-
* List the contents of a directory (files and subdirectories)
|
|
4
|
-
*/
|
|
5
|
-
import { z } from 'zod';
|
|
6
|
-
export declare const name = "listDir";
|
|
7
|
-
export declare const description = "List the contents of a directory, showing file sizes and directory indicators";
|
|
8
|
-
export declare const permission: "read";
|
|
9
|
-
export declare const schema: z.ZodObject<{
|
|
10
|
-
path: z.ZodOptional<z.ZodString>;
|
|
11
|
-
recursive: z.ZodDefault<z.ZodOptional<z.ZodBoolean>>;
|
|
12
|
-
depth: z.ZodDefault<z.ZodOptional<z.ZodNumber>>;
|
|
13
|
-
}, "strip", z.ZodTypeAny, {
|
|
14
|
-
recursive: boolean;
|
|
15
|
-
depth: number;
|
|
16
|
-
path?: string | undefined;
|
|
17
|
-
}, {
|
|
18
|
-
recursive?: boolean | undefined;
|
|
19
|
-
path?: string | undefined;
|
|
20
|
-
depth?: number | undefined;
|
|
21
|
-
}>;
|
|
22
|
-
interface EntryInfo {
|
|
23
|
-
name: string;
|
|
24
|
-
isDir: boolean;
|
|
25
|
-
size?: number;
|
|
26
|
-
childrenCount?: number;
|
|
27
|
-
}
|
|
28
|
-
export declare const execute: (args: Record<string, unknown>) => Promise<EntryInfo[]>;
|
|
29
|
-
export {};
|
package/dist/tools/listDir.js
DELETED
|
@@ -1,50 +0,0 @@
|
|
|
1
|
-
/**
|
|
2
|
-
* Tool: listDir
|
|
3
|
-
* List the contents of a directory (files and subdirectories)
|
|
4
|
-
*/
|
|
5
|
-
import { readdir, stat } from 'fs/promises';
|
|
6
|
-
import { join } from 'path';
|
|
7
|
-
import { z } from 'zod';
|
|
8
|
-
export const name = 'listDir';
|
|
9
|
-
export const description = 'List the contents of a directory, showing file sizes and directory indicators';
|
|
10
|
-
export const permission = 'read';
|
|
11
|
-
export const schema = z.object({
|
|
12
|
-
path: z.string().optional().describe('Directory path to list (default: current directory)'),
|
|
13
|
-
recursive: z.boolean().optional().default(false).describe('Whether to list recursively'),
|
|
14
|
-
depth: z.number().optional().default(1).describe('Max depth for recursive listing')
|
|
15
|
-
});
|
|
16
|
-
export const execute = async (args) => {
|
|
17
|
-
const parsed = schema.parse(args);
|
|
18
|
-
const rootPath = parsed.path || process.cwd();
|
|
19
|
-
try {
|
|
20
|
-
const entries = await readdir(rootPath, { withFileTypes: true });
|
|
21
|
-
const result = [];
|
|
22
|
-
for (const entry of entries) {
|
|
23
|
-
// Basic ignores
|
|
24
|
-
if (['node_modules', '.git', 'dist', 'build'].includes(entry.name))
|
|
25
|
-
continue;
|
|
26
|
-
const fullPath = join(rootPath, entry.name);
|
|
27
|
-
const isDir = entry.isDirectory();
|
|
28
|
-
let entryInfo = {
|
|
29
|
-
name: entry.name,
|
|
30
|
-
isDir
|
|
31
|
-
};
|
|
32
|
-
if (!isDir) {
|
|
33
|
-
try {
|
|
34
|
-
const s = await stat(fullPath);
|
|
35
|
-
entryInfo.size = s.size;
|
|
36
|
-
}
|
|
37
|
-
catch { }
|
|
38
|
-
}
|
|
39
|
-
else if (parsed.recursive && (parsed.depth || 0) > 0) {
|
|
40
|
-
// We don't actually do recursion here to keep it simple and flat
|
|
41
|
-
// but it's a placeholder for future if needed.
|
|
42
|
-
}
|
|
43
|
-
result.push(entryInfo);
|
|
44
|
-
}
|
|
45
|
-
return result;
|
|
46
|
-
}
|
|
47
|
-
catch (error) {
|
|
48
|
-
throw new Error(`Failed to list directory ${rootPath}: ${error instanceof Error ? error.message : error}`);
|
|
49
|
-
}
|
|
50
|
-
};
|
package/dist/tools/memory.d.ts
DELETED
|
@@ -1,34 +0,0 @@
|
|
|
1
|
-
/**
|
|
2
|
-
* Memory Tool - Persistent context and memory management
|
|
3
|
-
* Based on GeminiCLI's memoryTool.ts
|
|
4
|
-
*/
|
|
5
|
-
import { z } from 'zod';
|
|
6
|
-
import type { Tool } from '../registry.js';
|
|
7
|
-
export declare const inputSchema: z.ZodObject<{
|
|
8
|
-
operation: z.ZodEnum<["get", "set", "delete", "list", "search", "clear"]>;
|
|
9
|
-
key: z.ZodOptional<z.ZodString>;
|
|
10
|
-
value: z.ZodOptional<z.ZodString>;
|
|
11
|
-
query: z.ZodOptional<z.ZodString>;
|
|
12
|
-
namespace: z.ZodDefault<z.ZodOptional<z.ZodString>>;
|
|
13
|
-
}, "strip", z.ZodTypeAny, {
|
|
14
|
-
operation: "search" | "list" | "set" | "clear" | "get" | "delete";
|
|
15
|
-
namespace: string;
|
|
16
|
-
value?: string | undefined;
|
|
17
|
-
key?: string | undefined;
|
|
18
|
-
query?: string | undefined;
|
|
19
|
-
}, {
|
|
20
|
-
operation: "search" | "list" | "set" | "clear" | "get" | "delete";
|
|
21
|
-
value?: string | undefined;
|
|
22
|
-
key?: string | undefined;
|
|
23
|
-
query?: string | undefined;
|
|
24
|
-
namespace?: string | undefined;
|
|
25
|
-
}>;
|
|
26
|
-
type MemoryInput = z.infer<typeof inputSchema>;
|
|
27
|
-
export declare function execute(input: MemoryInput): Promise<{
|
|
28
|
-
operation: string;
|
|
29
|
-
success: boolean;
|
|
30
|
-
data?: unknown;
|
|
31
|
-
error?: string;
|
|
32
|
-
}>;
|
|
33
|
-
export declare const tool: Tool;
|
|
34
|
-
export {};
|
package/dist/tools/memory.js
DELETED
|
@@ -1,215 +0,0 @@
|
|
|
1
|
-
/**
|
|
2
|
-
* Memory Tool - Persistent context and memory management
|
|
3
|
-
* Based on GeminiCLI's memoryTool.ts
|
|
4
|
-
*/
|
|
5
|
-
import { z } from 'zod';
|
|
6
|
-
import { readFile, writeFile, mkdir } from 'fs/promises';
|
|
7
|
-
import { existsSync } from 'fs';
|
|
8
|
-
import { join, dirname } from 'path';
|
|
9
|
-
// Input schema
|
|
10
|
-
export const inputSchema = z.object({
|
|
11
|
-
operation: z.enum(['get', 'set', 'delete', 'list', 'search', 'clear']).describe('Memory operation'),
|
|
12
|
-
key: z.string().optional().describe('Memory key'),
|
|
13
|
-
value: z.string().optional().describe('Value to store'),
|
|
14
|
-
query: z.string().optional().describe('Search query'),
|
|
15
|
-
namespace: z.string().optional().default('default').describe('Memory namespace'),
|
|
16
|
-
});
|
|
17
|
-
// Get memory file path
|
|
18
|
-
function getMemoryPath() {
|
|
19
|
-
const baseDir = process.env.SIMPLE_CLI_DATA_DIR ||
|
|
20
|
-
join(process.env.HOME || '', '.config', 'simplecli');
|
|
21
|
-
return join(baseDir, 'memory.json');
|
|
22
|
-
}
|
|
23
|
-
// Load memory store
|
|
24
|
-
async function loadMemory() {
|
|
25
|
-
const path = getMemoryPath();
|
|
26
|
-
if (!existsSync(path)) {
|
|
27
|
-
return { version: 1, entries: {} };
|
|
28
|
-
}
|
|
29
|
-
try {
|
|
30
|
-
const content = await readFile(path, 'utf-8');
|
|
31
|
-
return JSON.parse(content);
|
|
32
|
-
}
|
|
33
|
-
catch {
|
|
34
|
-
return { version: 1, entries: {} };
|
|
35
|
-
}
|
|
36
|
-
}
|
|
37
|
-
// Save memory store
|
|
38
|
-
async function saveMemory(store) {
|
|
39
|
-
const path = getMemoryPath();
|
|
40
|
-
// Ensure directory exists
|
|
41
|
-
await mkdir(dirname(path), { recursive: true });
|
|
42
|
-
await writeFile(path, JSON.stringify(store, null, 2));
|
|
43
|
-
}
|
|
44
|
-
// Generate unique key
|
|
45
|
-
function generateKey(namespace, key) {
|
|
46
|
-
return `${namespace}:${key}`;
|
|
47
|
-
}
|
|
48
|
-
// Execute memory operation
|
|
49
|
-
export async function execute(input) {
|
|
50
|
-
const { operation, key, value, query, namespace } = inputSchema.parse(input);
|
|
51
|
-
const store = await loadMemory();
|
|
52
|
-
try {
|
|
53
|
-
switch (operation) {
|
|
54
|
-
case 'get': {
|
|
55
|
-
if (!key) {
|
|
56
|
-
return {
|
|
57
|
-
operation,
|
|
58
|
-
success: false,
|
|
59
|
-
error: 'Key required for get operation',
|
|
60
|
-
};
|
|
61
|
-
}
|
|
62
|
-
const fullKey = generateKey(namespace, key);
|
|
63
|
-
const entry = store.entries[fullKey];
|
|
64
|
-
if (!entry) {
|
|
65
|
-
return {
|
|
66
|
-
operation,
|
|
67
|
-
success: true,
|
|
68
|
-
data: null,
|
|
69
|
-
};
|
|
70
|
-
}
|
|
71
|
-
return {
|
|
72
|
-
operation,
|
|
73
|
-
success: true,
|
|
74
|
-
data: {
|
|
75
|
-
key: entry.key,
|
|
76
|
-
value: entry.value,
|
|
77
|
-
timestamp: entry.timestamp,
|
|
78
|
-
},
|
|
79
|
-
};
|
|
80
|
-
}
|
|
81
|
-
case 'set': {
|
|
82
|
-
if (!key || value === undefined) {
|
|
83
|
-
return {
|
|
84
|
-
operation,
|
|
85
|
-
success: false,
|
|
86
|
-
error: 'Key and value required for set operation',
|
|
87
|
-
};
|
|
88
|
-
}
|
|
89
|
-
const fullKey = generateKey(namespace, key);
|
|
90
|
-
store.entries[fullKey] = {
|
|
91
|
-
key,
|
|
92
|
-
value,
|
|
93
|
-
timestamp: Date.now(),
|
|
94
|
-
namespace,
|
|
95
|
-
};
|
|
96
|
-
await saveMemory(store);
|
|
97
|
-
return {
|
|
98
|
-
operation,
|
|
99
|
-
success: true,
|
|
100
|
-
data: { key, stored: true },
|
|
101
|
-
};
|
|
102
|
-
}
|
|
103
|
-
case 'delete': {
|
|
104
|
-
if (!key) {
|
|
105
|
-
return {
|
|
106
|
-
operation,
|
|
107
|
-
success: false,
|
|
108
|
-
error: 'Key required for delete operation',
|
|
109
|
-
};
|
|
110
|
-
}
|
|
111
|
-
const fullKey = generateKey(namespace, key);
|
|
112
|
-
const existed = fullKey in store.entries;
|
|
113
|
-
delete store.entries[fullKey];
|
|
114
|
-
await saveMemory(store);
|
|
115
|
-
return {
|
|
116
|
-
operation,
|
|
117
|
-
success: true,
|
|
118
|
-
data: { key, deleted: existed },
|
|
119
|
-
};
|
|
120
|
-
}
|
|
121
|
-
case 'list': {
|
|
122
|
-
const entries = Object.values(store.entries)
|
|
123
|
-
.filter(e => e.namespace === namespace)
|
|
124
|
-
.map(e => ({
|
|
125
|
-
key: e.key,
|
|
126
|
-
timestamp: e.timestamp,
|
|
127
|
-
preview: e.value.slice(0, 100) + (e.value.length > 100 ? '...' : ''),
|
|
128
|
-
}))
|
|
129
|
-
.sort((a, b) => b.timestamp - a.timestamp);
|
|
130
|
-
return {
|
|
131
|
-
operation,
|
|
132
|
-
success: true,
|
|
133
|
-
data: {
|
|
134
|
-
namespace,
|
|
135
|
-
count: entries.length,
|
|
136
|
-
entries,
|
|
137
|
-
},
|
|
138
|
-
};
|
|
139
|
-
}
|
|
140
|
-
case 'search': {
|
|
141
|
-
if (!query) {
|
|
142
|
-
return {
|
|
143
|
-
operation,
|
|
144
|
-
success: false,
|
|
145
|
-
error: 'Query required for search operation',
|
|
146
|
-
};
|
|
147
|
-
}
|
|
148
|
-
const queryLower = query.toLowerCase();
|
|
149
|
-
const matches = Object.values(store.entries)
|
|
150
|
-
.filter(e => e.key.toLowerCase().includes(queryLower) ||
|
|
151
|
-
e.value.toLowerCase().includes(queryLower))
|
|
152
|
-
.map(e => ({
|
|
153
|
-
key: e.key,
|
|
154
|
-
namespace: e.namespace,
|
|
155
|
-
timestamp: e.timestamp,
|
|
156
|
-
preview: e.value.slice(0, 100) + (e.value.length > 100 ? '...' : ''),
|
|
157
|
-
}))
|
|
158
|
-
.slice(0, 20);
|
|
159
|
-
return {
|
|
160
|
-
operation,
|
|
161
|
-
success: true,
|
|
162
|
-
data: {
|
|
163
|
-
query,
|
|
164
|
-
count: matches.length,
|
|
165
|
-
matches,
|
|
166
|
-
},
|
|
167
|
-
};
|
|
168
|
-
}
|
|
169
|
-
case 'clear': {
|
|
170
|
-
const beforeCount = Object.keys(store.entries).length;
|
|
171
|
-
if (namespace === 'all') {
|
|
172
|
-
store.entries = {};
|
|
173
|
-
}
|
|
174
|
-
else {
|
|
175
|
-
for (const [k, entry] of Object.entries(store.entries)) {
|
|
176
|
-
if (entry.namespace === namespace) {
|
|
177
|
-
delete store.entries[k];
|
|
178
|
-
}
|
|
179
|
-
}
|
|
180
|
-
}
|
|
181
|
-
await saveMemory(store);
|
|
182
|
-
const afterCount = Object.keys(store.entries).length;
|
|
183
|
-
return {
|
|
184
|
-
operation,
|
|
185
|
-
success: true,
|
|
186
|
-
data: {
|
|
187
|
-
namespace,
|
|
188
|
-
cleared: beforeCount - afterCount,
|
|
189
|
-
},
|
|
190
|
-
};
|
|
191
|
-
}
|
|
192
|
-
default:
|
|
193
|
-
return {
|
|
194
|
-
operation,
|
|
195
|
-
success: false,
|
|
196
|
-
error: `Unknown operation: ${operation}`,
|
|
197
|
-
};
|
|
198
|
-
}
|
|
199
|
-
}
|
|
200
|
-
catch (error) {
|
|
201
|
-
return {
|
|
202
|
-
operation,
|
|
203
|
-
success: false,
|
|
204
|
-
error: error instanceof Error ? error.message : String(error),
|
|
205
|
-
};
|
|
206
|
-
}
|
|
207
|
-
}
|
|
208
|
-
// Tool definition
|
|
209
|
-
export const tool = {
|
|
210
|
-
name: 'memory',
|
|
211
|
-
description: 'Store and retrieve persistent memory/context. Operations: get, set, delete, list, search, clear',
|
|
212
|
-
inputSchema,
|
|
213
|
-
permission: 'write',
|
|
214
|
-
execute: async (args) => execute(args),
|
|
215
|
-
};
|