@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/engine.js
ADDED
|
@@ -0,0 +1,138 @@
|
|
|
1
|
+
import { readdir } from 'fs/promises';
|
|
2
|
+
import { existsSync } from 'fs';
|
|
3
|
+
import { join, relative } from 'path';
|
|
4
|
+
import { pathToFileURL } from 'url';
|
|
5
|
+
import pc from 'picocolors';
|
|
6
|
+
import { text, isCancel } from '@clack/prompts';
|
|
7
|
+
import { LearningManager } from './learnings.js';
|
|
8
|
+
async function getRepoMap(cwd) {
|
|
9
|
+
const files = [];
|
|
10
|
+
async function walk(dir) {
|
|
11
|
+
const entries = await readdir(dir, { withFileTypes: true });
|
|
12
|
+
for (const e of entries) {
|
|
13
|
+
if (['node_modules', '.git', 'dist'].includes(e.name))
|
|
14
|
+
continue;
|
|
15
|
+
const res = join(dir, e.name);
|
|
16
|
+
if (e.isDirectory())
|
|
17
|
+
await walk(res);
|
|
18
|
+
else if (['.ts', '.js', '.py', '.md'].includes(res.slice(-3)))
|
|
19
|
+
files.push(relative(cwd, res));
|
|
20
|
+
}
|
|
21
|
+
}
|
|
22
|
+
try {
|
|
23
|
+
await walk(cwd);
|
|
24
|
+
}
|
|
25
|
+
catch { }
|
|
26
|
+
return files.slice(0, 50).join('\n');
|
|
27
|
+
}
|
|
28
|
+
export class Context {
|
|
29
|
+
history = [];
|
|
30
|
+
activeFiles = new Set();
|
|
31
|
+
cwd;
|
|
32
|
+
skill;
|
|
33
|
+
constructor(cwd, skill) {
|
|
34
|
+
this.cwd = cwd;
|
|
35
|
+
this.skill = skill;
|
|
36
|
+
}
|
|
37
|
+
async buildPrompt(tools) {
|
|
38
|
+
const repoMap = await getRepoMap(this.cwd);
|
|
39
|
+
const toolDefs = Array.from(tools.values()).map(t => `- ${t.name}: ${t.description}`).join('\n');
|
|
40
|
+
return `${this.skill.systemPrompt}\n\n## Tools\n${toolDefs}\n\n## Repository\n${repoMap}\n\n## Active Files\n${Array.from(this.activeFiles).map(f => relative(this.cwd, f)).join(', ')}`;
|
|
41
|
+
}
|
|
42
|
+
}
|
|
43
|
+
export class Registry {
|
|
44
|
+
tools = new Map();
|
|
45
|
+
async loadProjectTools(cwd) {
|
|
46
|
+
const dir = join(cwd, '.agent', 'tools');
|
|
47
|
+
if (!existsSync(dir))
|
|
48
|
+
return;
|
|
49
|
+
for (const f of await readdir(dir)) {
|
|
50
|
+
if (f.endsWith('.ts') || f.endsWith('.js')) {
|
|
51
|
+
const mod = await import(pathToFileURL(join(dir, f)).href);
|
|
52
|
+
const t = mod.tool || mod.default;
|
|
53
|
+
if (t?.name)
|
|
54
|
+
this.tools.set(t.name, t);
|
|
55
|
+
}
|
|
56
|
+
}
|
|
57
|
+
}
|
|
58
|
+
}
|
|
59
|
+
export class Engine {
|
|
60
|
+
llm;
|
|
61
|
+
registry;
|
|
62
|
+
mcp;
|
|
63
|
+
learningManager;
|
|
64
|
+
constructor(llm, registry, mcp) {
|
|
65
|
+
this.llm = llm;
|
|
66
|
+
this.registry = registry;
|
|
67
|
+
this.mcp = mcp;
|
|
68
|
+
this.learningManager = new LearningManager(process.cwd());
|
|
69
|
+
}
|
|
70
|
+
async run(ctx, initialPrompt, options = { interactive: true }) {
|
|
71
|
+
await this.learningManager.load();
|
|
72
|
+
let input = initialPrompt;
|
|
73
|
+
await this.mcp.init();
|
|
74
|
+
(await this.mcp.getTools()).forEach(t => this.registry.tools.set(t.name, t));
|
|
75
|
+
// Ensure tools are loaded for the context cwd
|
|
76
|
+
await this.registry.loadProjectTools(ctx.cwd);
|
|
77
|
+
while (true) {
|
|
78
|
+
if (!input) {
|
|
79
|
+
if (!options.interactive)
|
|
80
|
+
break;
|
|
81
|
+
const res = await text({ message: pc.cyan('Chat') });
|
|
82
|
+
if (isCancel(res))
|
|
83
|
+
break;
|
|
84
|
+
input = res;
|
|
85
|
+
}
|
|
86
|
+
ctx.history.push({ role: 'user', content: input });
|
|
87
|
+
// RAG: Inject learnings
|
|
88
|
+
let prompt = await ctx.buildPrompt(this.registry.tools);
|
|
89
|
+
const userHistory = ctx.history.filter(m => m.role === 'user' && !['Continue.', 'Fix the error.'].includes(m.content));
|
|
90
|
+
const lastUserMsg = userHistory[userHistory.length - 1]?.content || '';
|
|
91
|
+
const query = (input && !['Continue.', 'Fix the error.'].includes(input)) ? input : lastUserMsg;
|
|
92
|
+
const learnings = await this.learningManager.search(query);
|
|
93
|
+
if (learnings.length > 0) {
|
|
94
|
+
prompt += `\n\n## Past Learnings\n${learnings.map(l => `- ${l}`).join('\n')}`;
|
|
95
|
+
}
|
|
96
|
+
const response = await this.llm.generate(prompt, ctx.history);
|
|
97
|
+
const { thought, tool, args, message } = response;
|
|
98
|
+
if (thought)
|
|
99
|
+
console.log(pc.dim(`💭 ${thought}`));
|
|
100
|
+
if (tool && tool !== 'none') {
|
|
101
|
+
const t = this.registry.tools.get(tool);
|
|
102
|
+
if (t) {
|
|
103
|
+
console.log(pc.yellow(`⚙ Executing ${tool}...`));
|
|
104
|
+
try {
|
|
105
|
+
const result = await t.execute(args);
|
|
106
|
+
// Reload tools if create_tool was used
|
|
107
|
+
if (tool === 'create_tool') {
|
|
108
|
+
await this.registry.loadProjectTools(ctx.cwd);
|
|
109
|
+
console.log(pc.magenta('🔄 Tools reloaded.'));
|
|
110
|
+
}
|
|
111
|
+
ctx.history.push({ role: 'assistant', content: JSON.stringify(response) });
|
|
112
|
+
ctx.history.push({ role: 'user', content: `Result: ${JSON.stringify(result)}` });
|
|
113
|
+
// Reflection: Learning loop
|
|
114
|
+
const reflectPrompt = "Analyze the previous tool execution. What went well? What failed? Summarize as a concise learning point for future reference.";
|
|
115
|
+
const reflection = await this.llm.generate(reflectPrompt, [...ctx.history, { role: 'user', content: reflectPrompt }]);
|
|
116
|
+
if (reflection.message) {
|
|
117
|
+
// Find the relevant task description
|
|
118
|
+
const userHistory = ctx.history.filter(m => m.role === 'user' && !['Continue.', 'Fix the error.'].includes(m.content));
|
|
119
|
+
const task = (input && !['Continue.', 'Fix the error.'].includes(input)) ? input : (userHistory[userHistory.length - 1]?.content || 'Task');
|
|
120
|
+
await this.learningManager.add(task, reflection.message);
|
|
121
|
+
console.log(pc.blue(`📝 Learning stored: ${reflection.message}`));
|
|
122
|
+
}
|
|
123
|
+
input = 'The previous tool execution was successful. Proceed with the next step.';
|
|
124
|
+
continue;
|
|
125
|
+
}
|
|
126
|
+
catch (e) {
|
|
127
|
+
ctx.history.push({ role: 'user', content: `Error: ${e.message}` });
|
|
128
|
+
input = 'Fix the error.';
|
|
129
|
+
continue;
|
|
130
|
+
}
|
|
131
|
+
}
|
|
132
|
+
}
|
|
133
|
+
console.log(`\n${pc.green('🤖')} ${message || response.raw}\n`);
|
|
134
|
+
ctx.history.push({ role: 'assistant', content: message || response.raw });
|
|
135
|
+
input = undefined;
|
|
136
|
+
}
|
|
137
|
+
}
|
|
138
|
+
}
|
|
@@ -0,0 +1,15 @@
|
|
|
1
|
+
export interface Learning {
|
|
2
|
+
id: string;
|
|
3
|
+
task: string;
|
|
4
|
+
reflection: string;
|
|
5
|
+
timestamp: number;
|
|
6
|
+
}
|
|
7
|
+
export declare class LearningManager {
|
|
8
|
+
private learnings;
|
|
9
|
+
private path;
|
|
10
|
+
constructor(cwd: string);
|
|
11
|
+
load(): Promise<void>;
|
|
12
|
+
save(): Promise<void>;
|
|
13
|
+
add(task: string, reflection: string): Promise<void>;
|
|
14
|
+
search(query: string): Promise<string[]>;
|
|
15
|
+
}
|
|
@@ -0,0 +1,54 @@
|
|
|
1
|
+
import { readFile, writeFile } from 'fs/promises';
|
|
2
|
+
import { existsSync, mkdirSync } from 'fs';
|
|
3
|
+
import { join } from 'path';
|
|
4
|
+
export class LearningManager {
|
|
5
|
+
learnings = [];
|
|
6
|
+
path;
|
|
7
|
+
constructor(cwd) {
|
|
8
|
+
const agentDir = join(cwd, '.agent');
|
|
9
|
+
if (!existsSync(agentDir)) {
|
|
10
|
+
try {
|
|
11
|
+
mkdirSync(agentDir, { recursive: true });
|
|
12
|
+
}
|
|
13
|
+
catch { }
|
|
14
|
+
}
|
|
15
|
+
this.path = join(agentDir, 'learnings.json');
|
|
16
|
+
}
|
|
17
|
+
async load() {
|
|
18
|
+
if (!existsSync(this.path))
|
|
19
|
+
return;
|
|
20
|
+
try {
|
|
21
|
+
const data = await readFile(this.path, 'utf-8');
|
|
22
|
+
this.learnings = JSON.parse(data);
|
|
23
|
+
}
|
|
24
|
+
catch {
|
|
25
|
+
this.learnings = [];
|
|
26
|
+
}
|
|
27
|
+
}
|
|
28
|
+
async save() {
|
|
29
|
+
await writeFile(this.path, JSON.stringify(this.learnings, null, 2));
|
|
30
|
+
}
|
|
31
|
+
async add(task, reflection) {
|
|
32
|
+
this.learnings.push({
|
|
33
|
+
id: Date.now().toString(),
|
|
34
|
+
task,
|
|
35
|
+
reflection,
|
|
36
|
+
timestamp: Date.now()
|
|
37
|
+
});
|
|
38
|
+
await this.save();
|
|
39
|
+
}
|
|
40
|
+
async search(query) {
|
|
41
|
+
if (!query)
|
|
42
|
+
return [];
|
|
43
|
+
const keywords = query.toLowerCase().split(/\s+/).filter(w => w.length > 3);
|
|
44
|
+
if (keywords.length === 0)
|
|
45
|
+
return [];
|
|
46
|
+
return this.learnings
|
|
47
|
+
.filter(l => {
|
|
48
|
+
const text = (l.task + ' ' + l.reflection).toLowerCase();
|
|
49
|
+
return keywords.some(k => text.includes(k));
|
|
50
|
+
})
|
|
51
|
+
.map(l => l.reflection)
|
|
52
|
+
.slice(0, 5);
|
|
53
|
+
}
|
|
54
|
+
}
|
package/dist/llm.d.ts
ADDED
|
@@ -0,0 +1,18 @@
|
|
|
1
|
+
export interface LLMResponse {
|
|
2
|
+
thought: string;
|
|
3
|
+
tool: string;
|
|
4
|
+
args: any;
|
|
5
|
+
message?: string;
|
|
6
|
+
raw: string;
|
|
7
|
+
}
|
|
8
|
+
export declare class LLM {
|
|
9
|
+
private config;
|
|
10
|
+
constructor(config: {
|
|
11
|
+
provider: string;
|
|
12
|
+
model: string;
|
|
13
|
+
apiKey?: string;
|
|
14
|
+
});
|
|
15
|
+
generate(system: string, history: any[]): Promise<LLMResponse>;
|
|
16
|
+
private parse;
|
|
17
|
+
}
|
|
18
|
+
export declare const createLLM: (model?: string) => LLM;
|
package/dist/llm.js
ADDED
|
@@ -0,0 +1,73 @@
|
|
|
1
|
+
import { spawn } from 'child_process';
|
|
2
|
+
import { dirname, join } from 'path';
|
|
3
|
+
import { fileURLToPath } from 'url';
|
|
4
|
+
import { jsonrepair } from 'jsonrepair';
|
|
5
|
+
import fs from 'fs';
|
|
6
|
+
const __dirname = dirname(fileURLToPath(import.meta.url));
|
|
7
|
+
export class LLM {
|
|
8
|
+
config;
|
|
9
|
+
constructor(config) {
|
|
10
|
+
this.config = config;
|
|
11
|
+
}
|
|
12
|
+
async generate(system, history) {
|
|
13
|
+
const payload = {
|
|
14
|
+
...this.config,
|
|
15
|
+
messages: [{ role: 'system', content: system }, ...history],
|
|
16
|
+
api_key: this.config.apiKey || process.env.OPENAI_API_KEY || process.env.GEMINI_API_KEY || process.env.ANTHROPIC_API_KEY
|
|
17
|
+
};
|
|
18
|
+
return new Promise((resolve, reject) => {
|
|
19
|
+
// Find python bridge
|
|
20
|
+
let py = join(__dirname, 'anyllm.py');
|
|
21
|
+
if (!fs.existsSync(py))
|
|
22
|
+
py = join(process.cwd(), 'src/lib/anyllm.py'); // Fallback
|
|
23
|
+
// Try to find a working python command
|
|
24
|
+
const getPyCmd = () => {
|
|
25
|
+
const isWin = process.platform === 'win32';
|
|
26
|
+
// On Windows, preferred is 'python' or 'py' if they aren't store aliases
|
|
27
|
+
// On Linux/Mac, preferred is 'python3'
|
|
28
|
+
return isWin ? 'python' : 'python3';
|
|
29
|
+
};
|
|
30
|
+
const child = spawn(getPyCmd(), [py]);
|
|
31
|
+
let out = '';
|
|
32
|
+
let err = '';
|
|
33
|
+
child.stdout.on('data', d => out += d);
|
|
34
|
+
child.stderr.on('data', d => err += d);
|
|
35
|
+
child.on('close', code => {
|
|
36
|
+
if (code !== 0)
|
|
37
|
+
return reject(new Error(err));
|
|
38
|
+
try {
|
|
39
|
+
const res = JSON.parse(out);
|
|
40
|
+
if (res.error)
|
|
41
|
+
return reject(new Error(res.error));
|
|
42
|
+
resolve(this.parse(res.content));
|
|
43
|
+
}
|
|
44
|
+
catch (e) {
|
|
45
|
+
reject(e);
|
|
46
|
+
}
|
|
47
|
+
});
|
|
48
|
+
child.stdin.write(JSON.stringify(payload));
|
|
49
|
+
child.stdin.end();
|
|
50
|
+
});
|
|
51
|
+
}
|
|
52
|
+
parse(raw) {
|
|
53
|
+
try {
|
|
54
|
+
const repaired = jsonrepair(raw.trim().match(/\{[\s\S]*\}/)?.[0] || raw);
|
|
55
|
+
const p = JSON.parse(repaired);
|
|
56
|
+
return {
|
|
57
|
+
thought: p.thought || '',
|
|
58
|
+
tool: (p.tool || p.command || 'none').toLowerCase(),
|
|
59
|
+
args: p.args || p.parameters || {},
|
|
60
|
+
message: p.message || '',
|
|
61
|
+
raw
|
|
62
|
+
};
|
|
63
|
+
}
|
|
64
|
+
catch {
|
|
65
|
+
return { thought: '', tool: 'none', args: {}, message: raw, raw };
|
|
66
|
+
}
|
|
67
|
+
}
|
|
68
|
+
}
|
|
69
|
+
export const createLLM = (model) => {
|
|
70
|
+
const m = model || process.env.MODEL || 'openai:gpt-5.2-codex';
|
|
71
|
+
const [p, n] = m.includes(':') ? m.split(':') : ['openai', m];
|
|
72
|
+
return new LLM({ provider: p, model: n });
|
|
73
|
+
};
|
package/dist/mcp.d.ts
ADDED
|
@@ -0,0 +1,132 @@
|
|
|
1
|
+
export declare class MCP {
|
|
2
|
+
private clients;
|
|
3
|
+
init(): Promise<void>;
|
|
4
|
+
getTools(): Promise<{
|
|
5
|
+
execute: (args: any) => Promise<{
|
|
6
|
+
[x: string]: unknown;
|
|
7
|
+
content: ({
|
|
8
|
+
type: "text";
|
|
9
|
+
text: string;
|
|
10
|
+
annotations?: {
|
|
11
|
+
audience?: ("user" | "assistant")[] | undefined;
|
|
12
|
+
priority?: number | undefined;
|
|
13
|
+
lastModified?: string | undefined;
|
|
14
|
+
} | undefined;
|
|
15
|
+
_meta?: Record<string, unknown> | undefined;
|
|
16
|
+
} | {
|
|
17
|
+
type: "image";
|
|
18
|
+
data: string;
|
|
19
|
+
mimeType: string;
|
|
20
|
+
annotations?: {
|
|
21
|
+
audience?: ("user" | "assistant")[] | undefined;
|
|
22
|
+
priority?: number | undefined;
|
|
23
|
+
lastModified?: string | undefined;
|
|
24
|
+
} | undefined;
|
|
25
|
+
_meta?: Record<string, unknown> | undefined;
|
|
26
|
+
} | {
|
|
27
|
+
type: "audio";
|
|
28
|
+
data: string;
|
|
29
|
+
mimeType: string;
|
|
30
|
+
annotations?: {
|
|
31
|
+
audience?: ("user" | "assistant")[] | undefined;
|
|
32
|
+
priority?: number | undefined;
|
|
33
|
+
lastModified?: string | undefined;
|
|
34
|
+
} | undefined;
|
|
35
|
+
_meta?: Record<string, unknown> | undefined;
|
|
36
|
+
} | {
|
|
37
|
+
type: "resource";
|
|
38
|
+
resource: {
|
|
39
|
+
uri: string;
|
|
40
|
+
text: string;
|
|
41
|
+
mimeType?: string | undefined;
|
|
42
|
+
_meta?: Record<string, unknown> | undefined;
|
|
43
|
+
} | {
|
|
44
|
+
uri: string;
|
|
45
|
+
blob: string;
|
|
46
|
+
mimeType?: string | undefined;
|
|
47
|
+
_meta?: Record<string, unknown> | undefined;
|
|
48
|
+
};
|
|
49
|
+
annotations?: {
|
|
50
|
+
audience?: ("user" | "assistant")[] | undefined;
|
|
51
|
+
priority?: number | undefined;
|
|
52
|
+
lastModified?: string | undefined;
|
|
53
|
+
} | undefined;
|
|
54
|
+
_meta?: Record<string, unknown> | undefined;
|
|
55
|
+
} | {
|
|
56
|
+
uri: string;
|
|
57
|
+
name: string;
|
|
58
|
+
type: "resource_link";
|
|
59
|
+
description?: string | undefined;
|
|
60
|
+
mimeType?: string | undefined;
|
|
61
|
+
annotations?: {
|
|
62
|
+
audience?: ("user" | "assistant")[] | undefined;
|
|
63
|
+
priority?: number | undefined;
|
|
64
|
+
lastModified?: string | undefined;
|
|
65
|
+
} | undefined;
|
|
66
|
+
_meta?: {
|
|
67
|
+
[x: string]: unknown;
|
|
68
|
+
} | undefined;
|
|
69
|
+
icons?: {
|
|
70
|
+
src: string;
|
|
71
|
+
mimeType?: string | undefined;
|
|
72
|
+
sizes?: string[] | undefined;
|
|
73
|
+
theme?: "light" | "dark" | undefined;
|
|
74
|
+
}[] | undefined;
|
|
75
|
+
title?: string | undefined;
|
|
76
|
+
})[];
|
|
77
|
+
_meta?: {
|
|
78
|
+
[x: string]: unknown;
|
|
79
|
+
progressToken?: string | number | undefined;
|
|
80
|
+
"io.modelcontextprotocol/related-task"?: {
|
|
81
|
+
taskId: string;
|
|
82
|
+
} | undefined;
|
|
83
|
+
} | undefined;
|
|
84
|
+
structuredContent?: Record<string, unknown> | undefined;
|
|
85
|
+
isError?: boolean | undefined;
|
|
86
|
+
} | {
|
|
87
|
+
[x: string]: unknown;
|
|
88
|
+
toolResult: unknown;
|
|
89
|
+
_meta?: {
|
|
90
|
+
[x: string]: unknown;
|
|
91
|
+
progressToken?: string | number | undefined;
|
|
92
|
+
"io.modelcontextprotocol/related-task"?: {
|
|
93
|
+
taskId: string;
|
|
94
|
+
} | undefined;
|
|
95
|
+
} | undefined;
|
|
96
|
+
}>;
|
|
97
|
+
source: "mcp";
|
|
98
|
+
server: string;
|
|
99
|
+
inputSchema: {
|
|
100
|
+
[x: string]: unknown;
|
|
101
|
+
type: "object";
|
|
102
|
+
properties?: Record<string, object> | undefined;
|
|
103
|
+
required?: string[] | undefined;
|
|
104
|
+
};
|
|
105
|
+
name: string;
|
|
106
|
+
description?: string | undefined;
|
|
107
|
+
outputSchema?: {
|
|
108
|
+
[x: string]: unknown;
|
|
109
|
+
type: "object";
|
|
110
|
+
properties?: Record<string, object> | undefined;
|
|
111
|
+
required?: string[] | undefined;
|
|
112
|
+
} | undefined;
|
|
113
|
+
annotations?: {
|
|
114
|
+
title?: string | undefined;
|
|
115
|
+
readOnlyHint?: boolean | undefined;
|
|
116
|
+
destructiveHint?: boolean | undefined;
|
|
117
|
+
idempotentHint?: boolean | undefined;
|
|
118
|
+
openWorldHint?: boolean | undefined;
|
|
119
|
+
} | undefined;
|
|
120
|
+
execution?: {
|
|
121
|
+
taskSupport?: "optional" | "required" | "forbidden" | undefined;
|
|
122
|
+
} | undefined;
|
|
123
|
+
_meta?: Record<string, unknown> | undefined;
|
|
124
|
+
icons?: {
|
|
125
|
+
src: string;
|
|
126
|
+
mimeType?: string | undefined;
|
|
127
|
+
sizes?: string[] | undefined;
|
|
128
|
+
theme?: "light" | "dark" | undefined;
|
|
129
|
+
}[] | undefined;
|
|
130
|
+
title?: string | undefined;
|
|
131
|
+
}[]>;
|
|
132
|
+
}
|
package/dist/mcp.js
ADDED
|
@@ -0,0 +1,43 @@
|
|
|
1
|
+
import { Client } from '@modelcontextprotocol/sdk/client/index.js';
|
|
2
|
+
import { StdioClientTransport } from '@modelcontextprotocol/sdk/client/stdio.js';
|
|
3
|
+
import { existsSync, readFileSync } from 'fs';
|
|
4
|
+
import { join } from 'path';
|
|
5
|
+
export class MCP {
|
|
6
|
+
clients = new Map();
|
|
7
|
+
async init() {
|
|
8
|
+
const configPath = join(process.cwd(), 'mcp.json');
|
|
9
|
+
if (!existsSync(configPath))
|
|
10
|
+
return;
|
|
11
|
+
const config = JSON.parse(readFileSync(configPath, 'utf-8'));
|
|
12
|
+
const servers = config.mcpServers || config.servers || {};
|
|
13
|
+
for (const [name, cfg] of Object.entries(servers)) {
|
|
14
|
+
try {
|
|
15
|
+
const client = new Client({ name: 'simple-cli', version: '1.0.0' }, { capabilities: {} });
|
|
16
|
+
const transport = new StdioClientTransport({
|
|
17
|
+
command: cfg.command,
|
|
18
|
+
args: cfg.args || [],
|
|
19
|
+
env: { ...process.env, ...(cfg.env || {}) }
|
|
20
|
+
});
|
|
21
|
+
await client.connect(transport);
|
|
22
|
+
this.clients.set(name, client);
|
|
23
|
+
console.log(`✓ Connected to MCP: ${name}`);
|
|
24
|
+
}
|
|
25
|
+
catch (e) {
|
|
26
|
+
console.error(`✗ Failed to connect to MCP ${name}:`, e);
|
|
27
|
+
}
|
|
28
|
+
}
|
|
29
|
+
}
|
|
30
|
+
async getTools() {
|
|
31
|
+
const all = [];
|
|
32
|
+
for (const [name, client] of this.clients) {
|
|
33
|
+
const { tools } = await client.listTools();
|
|
34
|
+
all.push(...tools.map(t => ({
|
|
35
|
+
...t,
|
|
36
|
+
execute: (args) => client.callTool({ name: t.name, arguments: args }),
|
|
37
|
+
source: 'mcp',
|
|
38
|
+
server: name
|
|
39
|
+
})));
|
|
40
|
+
}
|
|
41
|
+
return all;
|
|
42
|
+
}
|
|
43
|
+
}
|
package/dist/skills.d.ts
CHANGED
|
@@ -1,25 +1,14 @@
|
|
|
1
|
-
/**
|
|
2
|
-
* Skills/Presets System
|
|
3
|
-
* Based on OpenHands skills and Aider prompts
|
|
4
|
-
* Provides specialized behavior presets for different tasks
|
|
5
|
-
*/
|
|
6
1
|
export interface Skill {
|
|
7
2
|
name: string;
|
|
8
|
-
description
|
|
3
|
+
description?: string;
|
|
9
4
|
systemPrompt: string;
|
|
10
5
|
tools?: string[];
|
|
11
|
-
modelPreference?: string;
|
|
12
|
-
autoActions?: string[];
|
|
13
6
|
}
|
|
14
7
|
export declare const builtinSkills: Record<string, Skill>;
|
|
15
|
-
export declare function
|
|
8
|
+
export declare function loadSkillFromFile(path: string): Promise<Skill | null>;
|
|
9
|
+
export declare function getActiveSkill(cwd?: string): Promise<Skill>;
|
|
16
10
|
export declare function setActiveSkill(name: string): Skill | undefined;
|
|
17
11
|
export declare function listSkills(): Skill[];
|
|
18
|
-
export declare function loadSkillFromFile(path: string): Promise<Skill | null>;
|
|
19
|
-
export declare function saveSkillToFile(skill: Skill, path: string): Promise<void>;
|
|
20
12
|
export declare function loadCustomSkills(dir: string): Promise<Record<string, Skill>>;
|
|
21
|
-
export declare function buildSkillPrompt(skill: Skill, context?:
|
|
22
|
-
|
|
23
|
-
repoMap?: string;
|
|
24
|
-
history?: string;
|
|
25
|
-
}): string;
|
|
13
|
+
export declare function buildSkillPrompt(skill: Skill, context?: any): string;
|
|
14
|
+
export declare function saveSkillToFile(skill: Skill, path: string): Promise<void>;
|