@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.
Files changed (100) hide show
  1. package/README.md +58 -271
  2. package/dist/anyllm.py +62 -0
  3. package/dist/builtins.d.ts +726 -0
  4. package/dist/builtins.js +481 -0
  5. package/dist/cli.d.ts +0 -4
  6. package/dist/cli.js +37 -279
  7. package/dist/engine.d.ts +33 -0
  8. package/dist/engine.js +138 -0
  9. package/dist/learnings.d.ts +15 -0
  10. package/dist/learnings.js +54 -0
  11. package/dist/llm.d.ts +18 -0
  12. package/dist/llm.js +66 -0
  13. package/dist/mcp.d.ts +132 -0
  14. package/dist/mcp.js +43 -0
  15. package/dist/skills.d.ts +5 -16
  16. package/dist/skills.js +91 -253
  17. package/dist/tui.d.ts +1 -0
  18. package/dist/tui.js +10 -0
  19. package/package.json +88 -78
  20. package/dist/commands/add.d.ts +0 -9
  21. package/dist/commands/add.js +0 -50
  22. package/dist/commands/git/commit.d.ts +0 -12
  23. package/dist/commands/git/commit.js +0 -97
  24. package/dist/commands/git/status.d.ts +0 -6
  25. package/dist/commands/git/status.js +0 -42
  26. package/dist/commands/index.d.ts +0 -16
  27. package/dist/commands/index.js +0 -376
  28. package/dist/commands/mcp/status.d.ts +0 -6
  29. package/dist/commands/mcp/status.js +0 -31
  30. package/dist/commands/swarm.d.ts +0 -36
  31. package/dist/commands/swarm.js +0 -236
  32. package/dist/commands.d.ts +0 -32
  33. package/dist/commands.js +0 -427
  34. package/dist/context.d.ts +0 -116
  35. package/dist/context.js +0 -327
  36. package/dist/index.d.ts +0 -6
  37. package/dist/index.js +0 -109
  38. package/dist/lib/agent.d.ts +0 -98
  39. package/dist/lib/agent.js +0 -281
  40. package/dist/lib/editor.d.ts +0 -74
  41. package/dist/lib/editor.js +0 -441
  42. package/dist/lib/git.d.ts +0 -164
  43. package/dist/lib/git.js +0 -351
  44. package/dist/lib/ui.d.ts +0 -159
  45. package/dist/lib/ui.js +0 -252
  46. package/dist/mcp/client.d.ts +0 -22
  47. package/dist/mcp/client.js +0 -81
  48. package/dist/mcp/manager.d.ts +0 -186
  49. package/dist/mcp/manager.js +0 -446
  50. package/dist/prompts/provider.d.ts +0 -22
  51. package/dist/prompts/provider.js +0 -78
  52. package/dist/providers/index.d.ts +0 -15
  53. package/dist/providers/index.js +0 -82
  54. package/dist/providers/multi.d.ts +0 -11
  55. package/dist/providers/multi.js +0 -28
  56. package/dist/registry.d.ts +0 -24
  57. package/dist/registry.js +0 -379
  58. package/dist/repoMap.d.ts +0 -5
  59. package/dist/repoMap.js +0 -79
  60. package/dist/router.d.ts +0 -41
  61. package/dist/router.js +0 -108
  62. package/dist/swarm/coordinator.d.ts +0 -86
  63. package/dist/swarm/coordinator.js +0 -257
  64. package/dist/swarm/index.d.ts +0 -28
  65. package/dist/swarm/index.js +0 -29
  66. package/dist/swarm/task.d.ts +0 -104
  67. package/dist/swarm/task.js +0 -221
  68. package/dist/swarm/types.d.ts +0 -132
  69. package/dist/swarm/types.js +0 -37
  70. package/dist/swarm/worker.d.ts +0 -107
  71. package/dist/swarm/worker.js +0 -299
  72. package/dist/tools/analyzeFile.d.ts +0 -16
  73. package/dist/tools/analyzeFile.js +0 -43
  74. package/dist/tools/git.d.ts +0 -40
  75. package/dist/tools/git.js +0 -236
  76. package/dist/tools/glob.d.ts +0 -34
  77. package/dist/tools/glob.js +0 -165
  78. package/dist/tools/grep.d.ts +0 -53
  79. package/dist/tools/grep.js +0 -296
  80. package/dist/tools/linter.d.ts +0 -35
  81. package/dist/tools/linter.js +0 -349
  82. package/dist/tools/listDir.d.ts +0 -29
  83. package/dist/tools/listDir.js +0 -50
  84. package/dist/tools/memory.d.ts +0 -34
  85. package/dist/tools/memory.js +0 -215
  86. package/dist/tools/readFiles.d.ts +0 -25
  87. package/dist/tools/readFiles.js +0 -31
  88. package/dist/tools/reloadTools.d.ts +0 -11
  89. package/dist/tools/reloadTools.js +0 -22
  90. package/dist/tools/runCommand.d.ts +0 -32
  91. package/dist/tools/runCommand.js +0 -79
  92. package/dist/tools/scraper.d.ts +0 -31
  93. package/dist/tools/scraper.js +0 -211
  94. package/dist/tools/writeFiles.d.ts +0 -63
  95. package/dist/tools/writeFiles.js +0 -87
  96. package/dist/ui/server.d.ts +0 -5
  97. package/dist/ui/server.js +0 -74
  98. package/dist/watcher.d.ts +0 -35
  99. package/dist/watcher.js +0 -164
  100. /package/{docs/assets → assets}/logo.jpeg +0 -0
package/dist/ui/server.js DELETED
@@ -1,74 +0,0 @@
1
- import http from 'http';
2
- import fs from 'fs';
3
- import path from 'path';
4
- import { fileURLToPath } from 'url';
5
- import { getContextManager } from '../context.js';
6
- import { createProvider } from '../providers/index.js';
7
- const __dirname = path.dirname(fileURLToPath(import.meta.url));
8
- export async function startServer(options) {
9
- const { port, host } = options;
10
- // Initialize Simple-CLI core
11
- const ctx = getContextManager();
12
- await ctx.initialize();
13
- const provider = createProvider();
14
- const server = http.createServer(async (req, res) => {
15
- // Basic router
16
- if (req.method === 'GET' && (req.url === '/' || req.url === '/index.html')) {
17
- res.writeHead(200, { 'Content-Type': 'text/html' });
18
- res.end(fs.readFileSync(path.join(__dirname, 'index.html')));
19
- return;
20
- }
21
- if (req.method === 'POST' && req.url === '/api/chat') {
22
- let body = '';
23
- req.on('data', chunk => { body += chunk; });
24
- req.on('end', async () => {
25
- try {
26
- const { message } = JSON.parse(body);
27
- if (!message) {
28
- res.writeHead(400);
29
- res.end(JSON.stringify({ error: 'Message required' }));
30
- return;
31
- }
32
- // Add message to context
33
- ctx.addMessage('user', message);
34
- // Get system prompt and history
35
- const systemPrompt = await ctx.buildSystemPrompt();
36
- const history = ctx.getHistory();
37
- // Generate response
38
- const response = await provider.generateResponse(systemPrompt, history.map(m => ({ role: m.role, content: m.content })));
39
- // Parse response (minimalist version of cli.ts logic)
40
- const thought = response.match(/<thought>([\s\S]*?)<\/thought>/)?.[1]?.trim();
41
- const jsonMatch = response.match(/\{[\s\S]*"tool"[\s\S]*\}/);
42
- let action = { tool: 'none', message: 'No action', args: {} };
43
- if (jsonMatch) {
44
- try {
45
- action = JSON.parse(jsonMatch[0]);
46
- }
47
- catch { /* ignore */ }
48
- }
49
- const messageText = action.message || response.replace(/<thought>[\s\S]*?<\/thought>/, '').replace(/\{[\s\S]*"tool"[\s\S]*\}/, '').trim();
50
- // Update context
51
- ctx.addMessage('assistant', response);
52
- res.writeHead(200, { 'Content-Type': 'application/json' });
53
- res.end(JSON.stringify({
54
- message: messageText,
55
- thought,
56
- action
57
- }));
58
- }
59
- catch (error) {
60
- res.writeHead(500);
61
- res.end(JSON.stringify({ error: error.message }));
62
- }
63
- });
64
- return;
65
- }
66
- // 404
67
- res.writeHead(404);
68
- res.end('Not Found');
69
- });
70
- server.listen(port, host, () => {
71
- console.log(`\n🚀 Simple-CLI UI running at http://${host}:${port}`);
72
- console.log(` Press Ctrl+C to stop\n`);
73
- });
74
- }
package/dist/watcher.d.ts DELETED
@@ -1,35 +0,0 @@
1
- /**
2
- * File Watcher - Watch files for changes and AI comments
3
- * Uses chokidar for robust cross-platform watching
4
- */
5
- import { EventEmitter } from 'events';
6
- export interface WatcherOptions {
7
- root: string;
8
- ignorePatterns?: RegExp[];
9
- onFileChange?: (filePath: string, type: 'add' | 'change' | 'unlink') => void;
10
- onAIComment?: (filePath: string, comments: AIComment[]) => void;
11
- verbose?: boolean;
12
- }
13
- export interface AIComment {
14
- line: number;
15
- text: string;
16
- action: 'request' | 'question' | 'note';
17
- }
18
- export declare class FileWatcher extends EventEmitter {
19
- private options;
20
- private watcher;
21
- private watchedFiles;
22
- private ignorePatterns;
23
- private verbose;
24
- constructor(options: WatcherOptions);
25
- start(): void;
26
- stop(): void;
27
- private shouldIgnore;
28
- private handleChange;
29
- private handleUnlink;
30
- private extractAIComments;
31
- hasActionableComments(): boolean;
32
- getActionableCommentsPrompt(): string;
33
- private log;
34
- }
35
- export declare function createFileWatcher(options: WatcherOptions): FileWatcher;
package/dist/watcher.js DELETED
@@ -1,164 +0,0 @@
1
- /**
2
- * File Watcher - Watch files for changes and AI comments
3
- * Uses chokidar for robust cross-platform watching
4
- */
5
- import * as chokidar from 'chokidar';
6
- import { readFile } from 'fs/promises';
7
- import { relative } from 'path';
8
- import { EventEmitter } from 'events';
9
- // AI comment pattern (matches: # ai!, // ai?, -- ai, etc.)
10
- const AI_COMMENT_PATTERN = /(?:#|\/\/|--|;+)\s*(ai\b.*|ai\b.*|.*\bai[?!]?)\s*$/i;
11
- // Default ignore patterns
12
- const IGNORE_PATTERNS = [
13
- /node_modules/,
14
- /\.git/,
15
- /dist\//,
16
- /build\//,
17
- /\.next/,
18
- /\.nuxt/,
19
- /__pycache__/,
20
- /\.pytest_cache/,
21
- /\.venv/,
22
- /venv/,
23
- /\.env$/,
24
- /\.DS_Store/,
25
- /\.swp$/,
26
- /\.swo$/,
27
- /\.bak$/,
28
- /~$/,
29
- /\.tmp$/,
30
- /\.log$/,
31
- ];
32
- const MAX_FILE_SIZE = 1024 * 1024; // 1MB
33
- export class FileWatcher extends EventEmitter {
34
- options;
35
- watcher = null;
36
- watchedFiles = new Map();
37
- ignorePatterns;
38
- verbose;
39
- constructor(options) {
40
- super();
41
- this.options = options;
42
- this.ignorePatterns = [...IGNORE_PATTERNS, ...(options.ignorePatterns || [])];
43
- this.verbose = options.verbose || false;
44
- if (options.onFileChange)
45
- this.on('file-change', options.onFileChange);
46
- if (options.onAIComment)
47
- this.on('ai-comment', options.onAIComment);
48
- }
49
- start() {
50
- if (this.watcher)
51
- return;
52
- this.log(`Starting chokidar watcher on ${this.options.root}`);
53
- this.watcher = chokidar.watch(this.options.root, {
54
- ignored: (path) => this.shouldIgnore(path),
55
- persistent: true,
56
- ignoreInitial: false,
57
- awaitWriteFinish: {
58
- stabilityThreshold: 300,
59
- pollInterval: 100
60
- }
61
- });
62
- this.watcher
63
- .on('add', (path) => this.handleChange(path, 'add'))
64
- .on('change', (path) => this.handleChange(path, 'change'))
65
- .on('unlink', (path) => this.handleUnlink(path));
66
- }
67
- stop() {
68
- if (this.watcher) {
69
- this.watcher.close();
70
- this.watcher = null;
71
- this.log('Watcher stopped');
72
- }
73
- this.watchedFiles.clear();
74
- }
75
- shouldIgnore(path) {
76
- const relPath = relative(this.options.root, path);
77
- // Always include root
78
- if (path === this.options.root)
79
- return false;
80
- return this.ignorePatterns.some(pattern => pattern.test(relPath));
81
- }
82
- async handleChange(path, type) {
83
- const relPath = relative(this.options.root, path);
84
- // Skip large files (chokidar might have already stat-ed, but we want to be safe before reading)
85
- // Note: chokidar doesn't expose stat size in event easily without another stat call or 'add' stats arg
86
- // For simplicity, we just read.
87
- try {
88
- // ... Check size logic could go here if critical
89
- const comments = await this.extractAIComments(path);
90
- const existing = this.watchedFiles.get(path);
91
- const hasNewComments = comments.length > 0 && (!existing || JSON.stringify(comments) !== JSON.stringify(existing.aiComments));
92
- this.watchedFiles.set(path, { path, aiComments: comments });
93
- this.emit('file-change', relPath, type);
94
- if (hasNewComments) {
95
- this.emit('ai-comment', relPath, comments);
96
- }
97
- }
98
- catch (e) {
99
- this.log(`Error processing ${relPath}: ${e}`);
100
- }
101
- }
102
- handleUnlink(path) {
103
- const relPath = relative(this.options.root, path);
104
- this.watchedFiles.delete(path);
105
- this.emit('file-change', relPath, 'unlink');
106
- }
107
- async extractAIComments(filePath) {
108
- try {
109
- const content = await readFile(filePath, 'utf-8');
110
- if (content.length > MAX_FILE_SIZE)
111
- return [];
112
- const lines = content.split('\n');
113
- const comments = [];
114
- for (let i = 0; i < lines.length; i++) {
115
- const match = AI_COMMENT_PATTERN.exec(lines[i]);
116
- if (match) {
117
- const text = match[1].trim();
118
- let action = 'note';
119
- const lower = text.toLowerCase();
120
- if (lower.endsWith('!') || lower.startsWith('ai!'))
121
- action = 'request';
122
- else if (lower.endsWith('?') || lower.startsWith('ai?'))
123
- action = 'question';
124
- comments.push({ line: i + 1, text, action });
125
- }
126
- }
127
- return comments;
128
- }
129
- catch {
130
- return [];
131
- }
132
- }
133
- hasActionableComments() {
134
- for (const [_, file] of this.watchedFiles) {
135
- if (file.aiComments.some(c => c.action === 'request' || c.action === 'question')) {
136
- return true;
137
- }
138
- }
139
- return false;
140
- }
141
- getActionableCommentsPrompt() {
142
- const parts = [];
143
- for (const [path, file] of this.watchedFiles) {
144
- const actionable = file.aiComments.filter(c => c.action === 'request' || c.action === 'question');
145
- if (actionable.length > 0) {
146
- const relPath = relative(this.options.root, path);
147
- parts.push(`\n${relPath}:`);
148
- for (const c of actionable) {
149
- parts.push(` Line ${c.line} [${c.action === 'request' ? '!' : '?'}]: ${c.text}`);
150
- }
151
- }
152
- }
153
- return parts.length > 0 ? `The following AI comments were found in the codebase:${parts.join('\n')}` : '';
154
- }
155
- log(msg) {
156
- if (this.verbose)
157
- console.log(`[Watcher] ${msg}`);
158
- }
159
- }
160
- export function createFileWatcher(options) {
161
- const w = new FileWatcher(options);
162
- w.start();
163
- return w;
164
- }
File without changes