@stan-chen/simple-cli 0.2.3 → 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 +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 +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 +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/swarm/worker.js
DELETED
|
@@ -1,369 +0,0 @@
|
|
|
1
|
-
/**
|
|
2
|
-
* Worker - Spawns and manages Simple-CLI worker processes
|
|
3
|
-
*/
|
|
4
|
-
import { spawn } from 'child_process';
|
|
5
|
-
import { EventEmitter } from 'events';
|
|
6
|
-
import { randomUUID } from 'crypto';
|
|
7
|
-
export class Worker extends EventEmitter {
|
|
8
|
-
id;
|
|
9
|
-
process = null;
|
|
10
|
-
state = 'idle';
|
|
11
|
-
currentTask = null;
|
|
12
|
-
startedAt = 0;
|
|
13
|
-
output = '';
|
|
14
|
-
options;
|
|
15
|
-
isTerminating = false;
|
|
16
|
-
onUnexpectedExit = (code) => {
|
|
17
|
-
if (!this.isTerminating) {
|
|
18
|
-
this.emit('error', new Error(`Worker process exited unexpectedly with code ${code}`));
|
|
19
|
-
}
|
|
20
|
-
};
|
|
21
|
-
constructor(options) {
|
|
22
|
-
super();
|
|
23
|
-
this.id = `worker-${randomUUID().slice(0, 8)}`;
|
|
24
|
-
this.options = options;
|
|
25
|
-
}
|
|
26
|
-
/**
|
|
27
|
-
* Get current worker status
|
|
28
|
-
*/
|
|
29
|
-
getStatus() {
|
|
30
|
-
return {
|
|
31
|
-
id: this.id,
|
|
32
|
-
pid: this.process?.pid,
|
|
33
|
-
state: this.state,
|
|
34
|
-
currentTask: this.currentTask?.id,
|
|
35
|
-
startedAt: this.startedAt || undefined,
|
|
36
|
-
completedAt: this.state === 'completed' || this.state === 'failed' ? Date.now() : undefined,
|
|
37
|
-
};
|
|
38
|
-
}
|
|
39
|
-
/**
|
|
40
|
-
* Execute a task
|
|
41
|
-
*/
|
|
42
|
-
async execute(task) {
|
|
43
|
-
if (this.state === 'running') {
|
|
44
|
-
throw new Error(`Worker ${this.id} is already running a task`);
|
|
45
|
-
}
|
|
46
|
-
this.currentTask = task;
|
|
47
|
-
this.state = 'running';
|
|
48
|
-
this.startedAt = Date.now();
|
|
49
|
-
this.output = '';
|
|
50
|
-
return new Promise((resolve, reject) => {
|
|
51
|
-
const timeout = task.timeout || this.options.timeout;
|
|
52
|
-
let timeoutId = null;
|
|
53
|
-
let resolved = false;
|
|
54
|
-
const cleanup = () => {
|
|
55
|
-
if (timeoutId)
|
|
56
|
-
clearTimeout(timeoutId);
|
|
57
|
-
this.process = null;
|
|
58
|
-
};
|
|
59
|
-
const finish = (result) => {
|
|
60
|
-
if (resolved)
|
|
61
|
-
return;
|
|
62
|
-
resolved = true;
|
|
63
|
-
cleanup();
|
|
64
|
-
this.state = result.success ? 'completed' : 'failed';
|
|
65
|
-
this.emit('complete', result);
|
|
66
|
-
resolve(result);
|
|
67
|
-
};
|
|
68
|
-
// Build the prompt from task
|
|
69
|
-
const prompt = this.buildPrompt(task);
|
|
70
|
-
// Spawn Simple-CLI process
|
|
71
|
-
const args = ['--yolo'];
|
|
72
|
-
if (this.options.yolo)
|
|
73
|
-
args.push('--yolo');
|
|
74
|
-
args.push(prompt);
|
|
75
|
-
// Use node to run the CLI directly
|
|
76
|
-
const cliPath = new URL('../index.js', import.meta.url).pathname;
|
|
77
|
-
this.process = spawn('node', [cliPath, ...args], {
|
|
78
|
-
cwd: this.options.cwd,
|
|
79
|
-
env: {
|
|
80
|
-
...process.env,
|
|
81
|
-
...this.options.env,
|
|
82
|
-
SIMPLE_CLI_WORKER: this.id,
|
|
83
|
-
SIMPLE_CLI_TASK: task.id,
|
|
84
|
-
},
|
|
85
|
-
stdio: ['pipe', 'pipe', 'pipe'],
|
|
86
|
-
});
|
|
87
|
-
this.emit('spawn', this.getStatus());
|
|
88
|
-
// Collect output
|
|
89
|
-
this.process.stdout?.on('data', (data) => {
|
|
90
|
-
this.output += data.toString();
|
|
91
|
-
});
|
|
92
|
-
this.process.stderr?.on('data', (data) => {
|
|
93
|
-
this.output += data.toString();
|
|
94
|
-
});
|
|
95
|
-
// Handle process exit
|
|
96
|
-
this.process.on('close', (code) => {
|
|
97
|
-
const duration = Date.now() - this.startedAt;
|
|
98
|
-
const success = code === 0;
|
|
99
|
-
// Parse output for changed files (simplified)
|
|
100
|
-
const filesChanged = this.parseChangedFiles(this.output);
|
|
101
|
-
const commitHash = this.parseCommitHash(this.output);
|
|
102
|
-
finish({
|
|
103
|
-
success,
|
|
104
|
-
filesChanged,
|
|
105
|
-
commitHash,
|
|
106
|
-
error: success ? undefined : `Process exited with code ${code}`,
|
|
107
|
-
duration,
|
|
108
|
-
output: this.output,
|
|
109
|
-
});
|
|
110
|
-
});
|
|
111
|
-
this.process.on('error', (err) => {
|
|
112
|
-
finish({
|
|
113
|
-
success: false,
|
|
114
|
-
filesChanged: [],
|
|
115
|
-
error: err.message,
|
|
116
|
-
duration: Date.now() - this.startedAt,
|
|
117
|
-
output: this.output,
|
|
118
|
-
});
|
|
119
|
-
});
|
|
120
|
-
// Set timeout
|
|
121
|
-
timeoutId = setTimeout(() => {
|
|
122
|
-
if (!resolved) {
|
|
123
|
-
(async () => {
|
|
124
|
-
try {
|
|
125
|
-
await this.kill();
|
|
126
|
-
}
|
|
127
|
-
catch (e) { /* best-effort */ }
|
|
128
|
-
finish({
|
|
129
|
-
success: false,
|
|
130
|
-
filesChanged: [],
|
|
131
|
-
error: `Task timed out after ${timeout}ms`,
|
|
132
|
-
duration: timeout,
|
|
133
|
-
output: this.output,
|
|
134
|
-
});
|
|
135
|
-
})();
|
|
136
|
-
}
|
|
137
|
-
}, timeout);
|
|
138
|
-
// Send task to stdin and close
|
|
139
|
-
this.process.stdin?.write(prompt);
|
|
140
|
-
this.process.stdin?.end();
|
|
141
|
-
});
|
|
142
|
-
}
|
|
143
|
-
/**
|
|
144
|
-
* Build prompt from task
|
|
145
|
-
*/
|
|
146
|
-
buildPrompt(task) {
|
|
147
|
-
let prompt = task.description;
|
|
148
|
-
if (task.scope.files && task.scope.files.length > 0) {
|
|
149
|
-
prompt += `\n\nFocus on these files: ${task.scope.files.join(', ')}`;
|
|
150
|
-
}
|
|
151
|
-
if (task.scope.directories && task.scope.directories.length > 0) {
|
|
152
|
-
prompt += `\n\nWork in these directories: ${task.scope.directories.join(', ')}`;
|
|
153
|
-
}
|
|
154
|
-
if (task.scope.pattern) {
|
|
155
|
-
prompt += `\n\nApply to files matching: ${task.scope.pattern}`;
|
|
156
|
-
}
|
|
157
|
-
return prompt;
|
|
158
|
-
}
|
|
159
|
-
/**
|
|
160
|
-
* Parse changed files from output
|
|
161
|
-
*/
|
|
162
|
-
parseChangedFiles(output) {
|
|
163
|
-
const files = [];
|
|
164
|
-
// Look for common patterns indicating file changes
|
|
165
|
-
const patterns = [
|
|
166
|
-
/(?:wrote|created|modified|updated)\s+([^\s]+)/gi,
|
|
167
|
-
/\[Result\].*(?:wrote|created)\s+([^\s]+)/gi,
|
|
168
|
-
];
|
|
169
|
-
for (const pattern of patterns) {
|
|
170
|
-
let match;
|
|
171
|
-
while ((match = pattern.exec(output)) !== null) {
|
|
172
|
-
const file = match[1].replace(/['"`,]/g, '');
|
|
173
|
-
if (file && !files.includes(file)) {
|
|
174
|
-
files.push(file);
|
|
175
|
-
}
|
|
176
|
-
}
|
|
177
|
-
}
|
|
178
|
-
return files;
|
|
179
|
-
}
|
|
180
|
-
/**
|
|
181
|
-
* Parse commit hash from output
|
|
182
|
-
*/
|
|
183
|
-
parseCommitHash(output) {
|
|
184
|
-
const match = output.match(/commit\s+([a-f0-9]{7,40})/i);
|
|
185
|
-
return match ? match[1] : undefined;
|
|
186
|
-
}
|
|
187
|
-
/**
|
|
188
|
-
* Kill the worker process
|
|
189
|
-
*/
|
|
190
|
-
kill() {
|
|
191
|
-
// Keep backwards-compatible signature: return a Promise but allow callers to ignore it.
|
|
192
|
-
const graceMs = 5000;
|
|
193
|
-
const promise = (async () => {
|
|
194
|
-
if (!this.process)
|
|
195
|
-
return;
|
|
196
|
-
if (this.process.killed)
|
|
197
|
-
return;
|
|
198
|
-
this.isTerminating = true;
|
|
199
|
-
// stop reporting unexpected-exit while we intentionally terminate
|
|
200
|
-
try {
|
|
201
|
-
this.process.off('exit', this.onUnexpectedExit);
|
|
202
|
-
}
|
|
203
|
-
catch (e) { }
|
|
204
|
-
// If IPC is available, politely ask the child to shutdown
|
|
205
|
-
try {
|
|
206
|
-
if (this.process.connected) {
|
|
207
|
-
try {
|
|
208
|
-
this.process.send({ type: 'shutdown' });
|
|
209
|
-
}
|
|
210
|
-
catch (e) { }
|
|
211
|
-
}
|
|
212
|
-
}
|
|
213
|
-
catch (e) { }
|
|
214
|
-
try {
|
|
215
|
-
this.process.kill('SIGTERM');
|
|
216
|
-
}
|
|
217
|
-
catch (e) {
|
|
218
|
-
// ignore
|
|
219
|
-
}
|
|
220
|
-
// wait for exit up to graceMs, otherwise force-kill
|
|
221
|
-
await new Promise((resolve) => {
|
|
222
|
-
let resolved = false;
|
|
223
|
-
const onExit = () => {
|
|
224
|
-
if (resolved)
|
|
225
|
-
return;
|
|
226
|
-
resolved = true;
|
|
227
|
-
clearTimeout(timer);
|
|
228
|
-
resolve(undefined);
|
|
229
|
-
};
|
|
230
|
-
const timer = setTimeout(() => {
|
|
231
|
-
try {
|
|
232
|
-
if (this.process && !this.process.killed)
|
|
233
|
-
this.process.kill('SIGKILL');
|
|
234
|
-
}
|
|
235
|
-
catch (e) { }
|
|
236
|
-
// still wait for exit event
|
|
237
|
-
}, graceMs);
|
|
238
|
-
try {
|
|
239
|
-
if (this.process)
|
|
240
|
-
this.process.once('exit', onExit);
|
|
241
|
-
}
|
|
242
|
-
catch (e) {
|
|
243
|
-
resolve(undefined);
|
|
244
|
-
}
|
|
245
|
-
});
|
|
246
|
-
try {
|
|
247
|
-
this.process = null;
|
|
248
|
-
}
|
|
249
|
-
catch (e) { }
|
|
250
|
-
})();
|
|
251
|
-
// Log kill action for auditing
|
|
252
|
-
try {
|
|
253
|
-
const fs = require('fs');
|
|
254
|
-
const path = require('path');
|
|
255
|
-
fs.appendFileSync(path.join(process.cwd(), '.worker_kill.log'), `${new Date().toISOString()} kill requested for worker ${this.id}\n`);
|
|
256
|
-
}
|
|
257
|
-
catch (e) { }
|
|
258
|
-
return promise;
|
|
259
|
-
}
|
|
260
|
-
/**
|
|
261
|
-
* Check if worker is busy
|
|
262
|
-
*/
|
|
263
|
-
isBusy() {
|
|
264
|
-
return this.state === 'running';
|
|
265
|
-
}
|
|
266
|
-
/**
|
|
267
|
-
* Check if worker is available
|
|
268
|
-
*/
|
|
269
|
-
isAvailable() {
|
|
270
|
-
return this.state === 'idle' || this.state === 'completed' || this.state === 'failed';
|
|
271
|
-
}
|
|
272
|
-
/**
|
|
273
|
-
* Reset worker for reuse
|
|
274
|
-
*/
|
|
275
|
-
reset() {
|
|
276
|
-
this.state = 'idle';
|
|
277
|
-
this.currentTask = null;
|
|
278
|
-
this.startedAt = 0;
|
|
279
|
-
this.output = '';
|
|
280
|
-
this.process = null;
|
|
281
|
-
}
|
|
282
|
-
/**
|
|
283
|
-
* Get task output
|
|
284
|
-
*/
|
|
285
|
-
getOutput() {
|
|
286
|
-
return this.output;
|
|
287
|
-
}
|
|
288
|
-
}
|
|
289
|
-
/**
|
|
290
|
-
* Worker pool for managing multiple workers
|
|
291
|
-
*/
|
|
292
|
-
export class WorkerPool {
|
|
293
|
-
workers = [];
|
|
294
|
-
inUse = new Set();
|
|
295
|
-
options;
|
|
296
|
-
maxWorkers;
|
|
297
|
-
constructor(maxWorkers, options) {
|
|
298
|
-
this.maxWorkers = maxWorkers;
|
|
299
|
-
this.options = options;
|
|
300
|
-
}
|
|
301
|
-
/**
|
|
302
|
-
* Get an available worker (or create one if pool not full)
|
|
303
|
-
*/
|
|
304
|
-
getWorker() {
|
|
305
|
-
// Create new worker if pool not full
|
|
306
|
-
if (this.workers.length < this.maxWorkers) {
|
|
307
|
-
const worker = new Worker(this.options);
|
|
308
|
-
this.workers.push(worker);
|
|
309
|
-
this.inUse.add(worker.id);
|
|
310
|
-
return worker;
|
|
311
|
-
}
|
|
312
|
-
// Try to find an available worker that's not in use
|
|
313
|
-
const available = this.workers.find(w => w.isAvailable() && !this.inUse.has(w.id));
|
|
314
|
-
if (available) {
|
|
315
|
-
available.reset();
|
|
316
|
-
this.inUse.add(available.id);
|
|
317
|
-
return available;
|
|
318
|
-
}
|
|
319
|
-
return null;
|
|
320
|
-
}
|
|
321
|
-
/**
|
|
322
|
-
* Release a worker back to the pool
|
|
323
|
-
*/
|
|
324
|
-
releaseWorker(worker) {
|
|
325
|
-
this.inUse.delete(worker.id);
|
|
326
|
-
}
|
|
327
|
-
/**
|
|
328
|
-
* Get all workers
|
|
329
|
-
*/
|
|
330
|
-
getAllWorkers() {
|
|
331
|
-
return [...this.workers];
|
|
332
|
-
}
|
|
333
|
-
/**
|
|
334
|
-
* Get worker by ID
|
|
335
|
-
*/
|
|
336
|
-
getWorkerById(id) {
|
|
337
|
-
return this.workers.find(w => w.id === id);
|
|
338
|
-
}
|
|
339
|
-
/**
|
|
340
|
-
* Get number of busy workers
|
|
341
|
-
*/
|
|
342
|
-
getBusyCount() {
|
|
343
|
-
return this.workers.filter(w => w.isBusy()).length;
|
|
344
|
-
}
|
|
345
|
-
/**
|
|
346
|
-
* Get number of available workers
|
|
347
|
-
*/
|
|
348
|
-
getAvailableCount() {
|
|
349
|
-
return Math.max(0, this.maxWorkers - this.getBusyCount());
|
|
350
|
-
}
|
|
351
|
-
/**
|
|
352
|
-
* Kill all workers
|
|
353
|
-
*/
|
|
354
|
-
killAll() {
|
|
355
|
-
for (const worker of this.workers) {
|
|
356
|
-
worker.kill();
|
|
357
|
-
}
|
|
358
|
-
}
|
|
359
|
-
/**
|
|
360
|
-
* Get pool status
|
|
361
|
-
*/
|
|
362
|
-
getStatus() {
|
|
363
|
-
return {
|
|
364
|
-
total: this.workers.length,
|
|
365
|
-
busy: this.getBusyCount(),
|
|
366
|
-
available: this.getAvailableCount(),
|
|
367
|
-
};
|
|
368
|
-
}
|
|
369
|
-
}
|
|
@@ -1,16 +0,0 @@
|
|
|
1
|
-
/**
|
|
2
|
-
* Tool: analyzeFile
|
|
3
|
-
* Structured analysis of a Source File (TS/JS) using ts-morph
|
|
4
|
-
*/
|
|
5
|
-
import { z } from 'zod';
|
|
6
|
-
export declare const name = "analyzeFile";
|
|
7
|
-
export declare const description = "Perform structured analysis of a TypeScript/JavaScript file to extract classes, functions, and interfaces.";
|
|
8
|
-
export declare const permission: "read";
|
|
9
|
-
export declare const schema: z.ZodObject<{
|
|
10
|
-
path: z.ZodString;
|
|
11
|
-
}, "strip", z.ZodTypeAny, {
|
|
12
|
-
path: string;
|
|
13
|
-
}, {
|
|
14
|
-
path: string;
|
|
15
|
-
}>;
|
|
16
|
-
export declare const execute: (args: Record<string, unknown>) => Promise<unknown>;
|
|
@@ -1,43 +0,0 @@
|
|
|
1
|
-
/**
|
|
2
|
-
* Tool: analyzeFile
|
|
3
|
-
* Structured analysis of a Source File (TS/JS) using ts-morph
|
|
4
|
-
*/
|
|
5
|
-
import { Project, ScriptTarget } from 'ts-morph';
|
|
6
|
-
import { z } from 'zod';
|
|
7
|
-
import { readFile } from 'fs/promises';
|
|
8
|
-
export const name = 'analyzeFile';
|
|
9
|
-
export const description = 'Perform structured analysis of a TypeScript/JavaScript file to extract classes, functions, and interfaces.';
|
|
10
|
-
export const permission = 'read';
|
|
11
|
-
export const schema = z.object({
|
|
12
|
-
path: z.string().describe('Path to the file to analyze')
|
|
13
|
-
});
|
|
14
|
-
export const execute = async (args) => {
|
|
15
|
-
const parsed = schema.parse(args);
|
|
16
|
-
const path = parsed.path;
|
|
17
|
-
try {
|
|
18
|
-
const content = await readFile(path, 'utf-8');
|
|
19
|
-
const project = new Project({
|
|
20
|
-
compilerOptions: { target: ScriptTarget.ESNext, allowJs: true },
|
|
21
|
-
useInMemoryFileSystem: true
|
|
22
|
-
});
|
|
23
|
-
const sourceFile = project.createSourceFile(path, content);
|
|
24
|
-
return {
|
|
25
|
-
path,
|
|
26
|
-
classes: sourceFile.getClasses().map(c => ({
|
|
27
|
-
name: c.getName(),
|
|
28
|
-
methods: c.getMethods().map(m => m.getName()),
|
|
29
|
-
properties: c.getProperties().map(p => p.getName())
|
|
30
|
-
})),
|
|
31
|
-
functions: sourceFile.getFunctions().map(f => ({
|
|
32
|
-
name: f.getName(),
|
|
33
|
-
params: f.getParameters().map(p => p.getName())
|
|
34
|
-
})),
|
|
35
|
-
interfaces: sourceFile.getInterfaces().map(i => i.getName()),
|
|
36
|
-
types: sourceFile.getTypeAliases().map(t => t.getName()),
|
|
37
|
-
exports: sourceFile.getExportedDeclarations().keys()
|
|
38
|
-
};
|
|
39
|
-
}
|
|
40
|
-
catch (error) {
|
|
41
|
-
throw new Error(`Failed to analyze file ${path}: ${error instanceof Error ? error.message : error}`);
|
|
42
|
-
}
|
|
43
|
-
};
|
|
@@ -1,16 +0,0 @@
|
|
|
1
|
-
/**
|
|
2
|
-
* Tool: analyzeFile
|
|
3
|
-
* Structured analysis of a Source File (TS/JS) using ts-morph
|
|
4
|
-
*/
|
|
5
|
-
import { z } from 'zod';
|
|
6
|
-
export declare const name = "analyze_file";
|
|
7
|
-
export declare const description = "Perform structured analysis of a TypeScript/JavaScript file to extract classes, functions, and interfaces.";
|
|
8
|
-
export declare const permission: "read";
|
|
9
|
-
export declare const schema: z.ZodObject<{
|
|
10
|
-
path: z.ZodString;
|
|
11
|
-
}, "strip", z.ZodTypeAny, {
|
|
12
|
-
path: string;
|
|
13
|
-
}, {
|
|
14
|
-
path: string;
|
|
15
|
-
}>;
|
|
16
|
-
export declare const execute: (args: Record<string, unknown>) => Promise<unknown>;
|
|
@@ -1,43 +0,0 @@
|
|
|
1
|
-
/**
|
|
2
|
-
* Tool: analyzeFile
|
|
3
|
-
* Structured analysis of a Source File (TS/JS) using ts-morph
|
|
4
|
-
*/
|
|
5
|
-
import { Project, ScriptTarget } from 'ts-morph';
|
|
6
|
-
import { z } from 'zod';
|
|
7
|
-
import { readFile } from 'fs/promises';
|
|
8
|
-
export const name = 'analyze_file';
|
|
9
|
-
export const description = 'Perform structured analysis of a TypeScript/JavaScript file to extract classes, functions, and interfaces.';
|
|
10
|
-
export const permission = 'read';
|
|
11
|
-
export const schema = z.object({
|
|
12
|
-
path: z.string().describe('Path to the file to analyze')
|
|
13
|
-
});
|
|
14
|
-
export const execute = async (args) => {
|
|
15
|
-
const parsed = schema.parse(args);
|
|
16
|
-
const path = parsed.path;
|
|
17
|
-
try {
|
|
18
|
-
const content = await readFile(path, 'utf-8');
|
|
19
|
-
const project = new Project({
|
|
20
|
-
compilerOptions: { target: ScriptTarget.ESNext, allowJs: true },
|
|
21
|
-
useInMemoryFileSystem: true
|
|
22
|
-
});
|
|
23
|
-
const sourceFile = project.createSourceFile(path, content);
|
|
24
|
-
return {
|
|
25
|
-
path,
|
|
26
|
-
classes: sourceFile.getClasses().map(c => ({
|
|
27
|
-
name: c.getName(),
|
|
28
|
-
methods: c.getMethods().map(m => m.getName()),
|
|
29
|
-
properties: c.getProperties().map(p => p.getName())
|
|
30
|
-
})),
|
|
31
|
-
functions: sourceFile.getFunctions().map(f => ({
|
|
32
|
-
name: f.getName(),
|
|
33
|
-
params: f.getParameters().map(p => p.getName())
|
|
34
|
-
})),
|
|
35
|
-
interfaces: sourceFile.getInterfaces().map(i => i.getName()),
|
|
36
|
-
types: sourceFile.getTypeAliases().map(t => t.getName()),
|
|
37
|
-
exports: sourceFile.getExportedDeclarations().keys()
|
|
38
|
-
};
|
|
39
|
-
}
|
|
40
|
-
catch (error) {
|
|
41
|
-
throw new Error(`Failed to analyze file ${path}: ${error instanceof Error ? error.message : error}`);
|
|
42
|
-
}
|
|
43
|
-
};
|
|
@@ -1,23 +0,0 @@
|
|
|
1
|
-
/**
|
|
2
|
-
* ClawBrain - Agentic Reasoning and Persistence for Autonomous Mode
|
|
3
|
-
*/
|
|
4
|
-
import { z } from 'zod';
|
|
5
|
-
import type { Tool } from '../registry.js';
|
|
6
|
-
export declare const inputSchema: z.ZodObject<{
|
|
7
|
-
action: z.ZodEnum<["set_goal", "update_status", "log_reflection", "get_summary", "prune", "link_files"]>;
|
|
8
|
-
content: z.ZodOptional<z.ZodString>;
|
|
9
|
-
status: z.ZodOptional<z.ZodEnum<["planning", "executing", "completed", "failed"]>>;
|
|
10
|
-
links: z.ZodOptional<z.ZodArray<z.ZodString, "many">>;
|
|
11
|
-
}, "strip", z.ZodTypeAny, {
|
|
12
|
-
action: "log_reflection" | "get_summary" | "prune" | "set_goal" | "update_status" | "link_files";
|
|
13
|
-
status?: "completed" | "failed" | "planning" | "executing" | undefined;
|
|
14
|
-
content?: string | undefined;
|
|
15
|
-
links?: string[] | undefined;
|
|
16
|
-
}, {
|
|
17
|
-
action: "log_reflection" | "get_summary" | "prune" | "set_goal" | "update_status" | "link_files";
|
|
18
|
-
status?: "completed" | "failed" | "planning" | "executing" | undefined;
|
|
19
|
-
content?: string | undefined;
|
|
20
|
-
links?: string[] | undefined;
|
|
21
|
-
}>;
|
|
22
|
-
export declare const execute: (args: Record<string, unknown>, cwd?: string) => Promise<any>;
|
|
23
|
-
export declare const tool: Tool;
|
package/dist/tools/clawBrain.js
DELETED
|
@@ -1,136 +0,0 @@
|
|
|
1
|
-
/**
|
|
2
|
-
* ClawBrain - Agentic Reasoning and Persistence for Autonomous Mode
|
|
3
|
-
*/
|
|
4
|
-
import { z } from 'zod';
|
|
5
|
-
import { readFile, writeFile, mkdir } from 'fs/promises';
|
|
6
|
-
import { existsSync } from 'fs';
|
|
7
|
-
import { join } from 'path';
|
|
8
|
-
export const inputSchema = z.object({
|
|
9
|
-
action: z.enum(['set_goal', 'update_status', 'log_reflection', 'get_summary', 'prune', 'link_files']),
|
|
10
|
-
content: z.string().optional().describe('Text content for the action'),
|
|
11
|
-
status: z.enum(['planning', 'executing', 'completed', 'failed']).optional().describe('Current mission status'),
|
|
12
|
-
links: z.array(z.string()).optional().describe('Paths or IDs to link in the graph'),
|
|
13
|
-
});
|
|
14
|
-
const MISSION_FILE = '.simple/workdir/mission.json';
|
|
15
|
-
async function loadMission(cwd) {
|
|
16
|
-
const path = join(cwd, MISSION_FILE);
|
|
17
|
-
if (!existsSync(path)) {
|
|
18
|
-
return { goal: 'Unknown', status: 'planning', reflections: [], lastUpdated: Date.now() };
|
|
19
|
-
}
|
|
20
|
-
try {
|
|
21
|
-
return JSON.parse(await readFile(path, 'utf-8'));
|
|
22
|
-
}
|
|
23
|
-
catch {
|
|
24
|
-
return { goal: 'Unknown', status: 'planning', reflections: [], lastUpdated: Date.now() };
|
|
25
|
-
}
|
|
26
|
-
}
|
|
27
|
-
async function saveMission(cwd, mission) {
|
|
28
|
-
const path = join(cwd, MISSION_FILE);
|
|
29
|
-
await mkdir(join(cwd, '.simple/workdir'), { recursive: true });
|
|
30
|
-
mission.lastUpdated = Date.now();
|
|
31
|
-
await writeFile(path, JSON.stringify(mission, null, 2));
|
|
32
|
-
}
|
|
33
|
-
export const execute = async (args, cwd = process.cwd()) => {
|
|
34
|
-
const { action, content, status, links } = inputSchema.parse(args);
|
|
35
|
-
const mission = await loadMission(cwd);
|
|
36
|
-
switch (action) {
|
|
37
|
-
case 'set_goal':
|
|
38
|
-
mission.goal = content || mission.goal;
|
|
39
|
-
if (status)
|
|
40
|
-
mission.status = status;
|
|
41
|
-
await saveMission(cwd, mission);
|
|
42
|
-
return { success: true, message: `Goal set to: ${mission.goal}` };
|
|
43
|
-
case 'update_status':
|
|
44
|
-
if (status)
|
|
45
|
-
mission.status = status;
|
|
46
|
-
if (content)
|
|
47
|
-
mission.reflections.push(`[Status Update] ${content}`);
|
|
48
|
-
await saveMission(cwd, mission);
|
|
49
|
-
return { success: true, status: mission.status };
|
|
50
|
-
case 'log_reflection':
|
|
51
|
-
if (content) {
|
|
52
|
-
mission.reflections.push(content);
|
|
53
|
-
if (mission.reflections.length > 50)
|
|
54
|
-
mission.reflections.shift();
|
|
55
|
-
await saveMission(cwd, mission);
|
|
56
|
-
// Write to reflections directory for JIT context
|
|
57
|
-
const reflectionsDir = join(cwd, '.simple/workdir/memory/reflections');
|
|
58
|
-
await mkdir(reflectionsDir, { recursive: true });
|
|
59
|
-
const fileName = `reflection-${Date.now()}.md`;
|
|
60
|
-
await writeFile(join(reflectionsDir, fileName), content);
|
|
61
|
-
}
|
|
62
|
-
return { success: true, added: !!content };
|
|
63
|
-
case 'link_files':
|
|
64
|
-
if (links && links.length > 0) {
|
|
65
|
-
const graphDir = join(cwd, '.simple/workdir/memory/graph');
|
|
66
|
-
await mkdir(graphDir, { recursive: true });
|
|
67
|
-
const graphFile = join(graphDir, 'links.jsonl');
|
|
68
|
-
const entry = JSON.stringify({ timestamp: Date.now(), links, goal: mission.goal }) + '\n';
|
|
69
|
-
await writeFile(graphFile, entry, { flag: 'a' });
|
|
70
|
-
}
|
|
71
|
-
return { success: true, linked: links?.length || 0 };
|
|
72
|
-
case 'get_summary':
|
|
73
|
-
return {
|
|
74
|
-
goal: mission.goal,
|
|
75
|
-
status: mission.status,
|
|
76
|
-
recent_reflections: mission.reflections.slice(-5),
|
|
77
|
-
last_updated: new Date(mission.lastUpdated).toISOString()
|
|
78
|
-
};
|
|
79
|
-
case 'prune': {
|
|
80
|
-
const memoryDir = join(cwd, '.simple/workdir/memory');
|
|
81
|
-
const notesDir = join(memoryDir, 'notes');
|
|
82
|
-
await mkdir(notesDir, { recursive: true });
|
|
83
|
-
if (mission.reflections.length === 0) {
|
|
84
|
-
return { success: true, message: 'Nothing to prune.' };
|
|
85
|
-
}
|
|
86
|
-
const archiveFile = join(notesDir, `archive-${Date.now()}.md`);
|
|
87
|
-
let consolidated;
|
|
88
|
-
try {
|
|
89
|
-
const { createProvider } = await import('../providers/index.js');
|
|
90
|
-
const provider = createProvider();
|
|
91
|
-
const prompt = `Consolidate and summarize the following mission reflections into a concise technical brief.
|
|
92
|
-
Keep ONLY unique technical insights, discovered paths, and finalized facts.
|
|
93
|
-
Original Goal: ${mission.goal}\n\nReflections:\n${mission.reflections.join('\n')}`;
|
|
94
|
-
console.log('🤖 Summarizing reflections for pruning...');
|
|
95
|
-
const summary = await provider.generateResponse('You are a technical documentarian.', [
|
|
96
|
-
{ role: 'user', content: prompt }
|
|
97
|
-
]);
|
|
98
|
-
let summaryText = summary;
|
|
99
|
-
try {
|
|
100
|
-
const parsed = JSON.parse(summary);
|
|
101
|
-
summaryText = parsed.thought || parsed.message || summary;
|
|
102
|
-
}
|
|
103
|
-
catch { /* not JSON */ }
|
|
104
|
-
consolidated = [
|
|
105
|
-
`# Mission Summary Archive: ${mission.goal}`,
|
|
106
|
-
`Status: ${mission.status}`,
|
|
107
|
-
`Date: ${new Date().toISOString()}`,
|
|
108
|
-
'',
|
|
109
|
-
'## Executive Summary',
|
|
110
|
-
summaryText
|
|
111
|
-
].join('\n');
|
|
112
|
-
}
|
|
113
|
-
catch (e) {
|
|
114
|
-
// Fallback to basic concatenation if LLM fails
|
|
115
|
-
consolidated = mission.reflections.map(r => `- ${r}`).join('\n');
|
|
116
|
-
}
|
|
117
|
-
await writeFile(archiveFile, consolidated);
|
|
118
|
-
mission.reflections = mission.reflections.slice(-3); // Keep only very recent context
|
|
119
|
-
await saveMission(cwd, mission);
|
|
120
|
-
return {
|
|
121
|
-
success: true,
|
|
122
|
-
message: 'Memory pruned and summarized with LLM.',
|
|
123
|
-
archivePath: archiveFile
|
|
124
|
-
};
|
|
125
|
-
}
|
|
126
|
-
default:
|
|
127
|
-
throw new Error(`Invalid action: ${action}`);
|
|
128
|
-
}
|
|
129
|
-
};
|
|
130
|
-
export const tool = {
|
|
131
|
-
name: 'clawBrain',
|
|
132
|
-
description: 'Manage autonomous mission state and technical reasoning. Use to set goals, log reflections, and track status.',
|
|
133
|
-
inputSchema,
|
|
134
|
-
permission: 'write',
|
|
135
|
-
execute: async (args) => execute(args),
|
|
136
|
-
};
|
|
@@ -1,23 +0,0 @@
|
|
|
1
|
-
/**
|
|
2
|
-
* ClawBrain - Agentic Reasoning and Persistence for Autonomous Mode
|
|
3
|
-
*/
|
|
4
|
-
import { z } from 'zod';
|
|
5
|
-
import type { Tool } from '../registry.js';
|
|
6
|
-
export declare const inputSchema: z.ZodObject<{
|
|
7
|
-
action: z.ZodEnum<["set_goal", "update_status", "log_reflection", "get_summary", "prune", "link_files"]>;
|
|
8
|
-
content: z.ZodOptional<z.ZodString>;
|
|
9
|
-
status: z.ZodOptional<z.ZodEnum<["planning", "executing", "completed", "failed"]>>;
|
|
10
|
-
links: z.ZodOptional<z.ZodArray<z.ZodString, "many">>;
|
|
11
|
-
}, "strip", z.ZodTypeAny, {
|
|
12
|
-
action: "log_reflection" | "get_summary" | "prune" | "set_goal" | "update_status" | "link_files";
|
|
13
|
-
status?: "completed" | "failed" | "planning" | "executing" | undefined;
|
|
14
|
-
content?: string | undefined;
|
|
15
|
-
links?: string[] | undefined;
|
|
16
|
-
}, {
|
|
17
|
-
action: "log_reflection" | "get_summary" | "prune" | "set_goal" | "update_status" | "link_files";
|
|
18
|
-
status?: "completed" | "failed" | "planning" | "executing" | undefined;
|
|
19
|
-
content?: string | undefined;
|
|
20
|
-
links?: string[] | undefined;
|
|
21
|
-
}>;
|
|
22
|
-
export declare const execute: (args: Record<string, unknown>, cwd?: string) => Promise<any>;
|
|
23
|
-
export declare const tool: Tool;
|