@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/mcp/manager.js
DELETED
|
@@ -1,446 +0,0 @@
|
|
|
1
|
-
/**
|
|
2
|
-
* MCP Client Manager - Manages multiple MCP server connections
|
|
3
|
-
* Supports Composio, custom MCP servers, and dynamic tool discovery
|
|
4
|
-
* Based on GeminiCLI's mcp-client.ts patterns
|
|
5
|
-
*/
|
|
6
|
-
import { Client } from '@modelcontextprotocol/sdk/client/index.js';
|
|
7
|
-
import { StdioClientTransport } from '@modelcontextprotocol/sdk/client/stdio.js';
|
|
8
|
-
import { z } from 'zod';
|
|
9
|
-
import { existsSync, readFileSync } from 'fs';
|
|
10
|
-
import { join } from 'path';
|
|
11
|
-
// MCP Server Configuration Schema
|
|
12
|
-
export const MCPServerConfigSchema = z.object({
|
|
13
|
-
name: z.string(),
|
|
14
|
-
command: z.string().optional(),
|
|
15
|
-
args: z.array(z.string()).optional(),
|
|
16
|
-
env: z.record(z.string()).optional(),
|
|
17
|
-
url: z.string().optional(),
|
|
18
|
-
type: z.enum(['stdio', 'sse', 'http']).optional(),
|
|
19
|
-
timeout: z.number().optional(),
|
|
20
|
-
trust: z.enum(['full', 'partial', 'none']).optional(),
|
|
21
|
-
enabled: z.boolean().optional().default(true),
|
|
22
|
-
});
|
|
23
|
-
// Server Status
|
|
24
|
-
export var MCPServerStatus;
|
|
25
|
-
(function (MCPServerStatus) {
|
|
26
|
-
MCPServerStatus["DISCONNECTED"] = "disconnected";
|
|
27
|
-
MCPServerStatus["CONNECTING"] = "connecting";
|
|
28
|
-
MCPServerStatus["CONNECTED"] = "connected";
|
|
29
|
-
MCPServerStatus["ERROR"] = "error";
|
|
30
|
-
})(MCPServerStatus || (MCPServerStatus = {}));
|
|
31
|
-
/**
|
|
32
|
-
* MCP Client Manager
|
|
33
|
-
* Manages connections to multiple MCP servers and aggregates their tools
|
|
34
|
-
*/
|
|
35
|
-
export class MCPManager {
|
|
36
|
-
servers = new Map();
|
|
37
|
-
onStatusChange;
|
|
38
|
-
constructor(options) {
|
|
39
|
-
this.onStatusChange = options?.onStatusChange;
|
|
40
|
-
}
|
|
41
|
-
/**
|
|
42
|
-
* Load MCP configuration from all available sources
|
|
43
|
-
*/
|
|
44
|
-
async loadConfig(configPath) {
|
|
45
|
-
const allConfigs = [];
|
|
46
|
-
const sources = [
|
|
47
|
-
{ path: configPath, type: 'file' },
|
|
48
|
-
{ path: join(process.cwd(), 'mcp.json'), type: 'file' },
|
|
49
|
-
{ path: join(process.cwd(), '.mcp.json'), type: 'file' },
|
|
50
|
-
{ path: join(process.cwd(), 'mcp'), type: 'dir' },
|
|
51
|
-
{ path: join(process.env.HOME || '', '.config', 'simplecli', 'mcp.json'), type: 'file' },
|
|
52
|
-
{ path: join(process.env.APPDATA || '', 'simplecli', 'mcp.json'), type: 'file' },
|
|
53
|
-
].filter(s => s.path && existsSync(s.path));
|
|
54
|
-
for (const source of sources) {
|
|
55
|
-
try {
|
|
56
|
-
if (source.type === 'file') {
|
|
57
|
-
const content = readFileSync(source.path, 'utf-8');
|
|
58
|
-
allConfigs.push(...this.parseConfigContent(content));
|
|
59
|
-
}
|
|
60
|
-
else if (source.type === 'dir') {
|
|
61
|
-
// Scan directory for .json files
|
|
62
|
-
const { readdir } = await import('fs/promises');
|
|
63
|
-
const files = await readdir(source.path);
|
|
64
|
-
for (const file of files) {
|
|
65
|
-
if (file.endsWith('.json')) {
|
|
66
|
-
const content = readFileSync(join(source.path, file), 'utf-8');
|
|
67
|
-
allConfigs.push(...this.parseConfigContent(content));
|
|
68
|
-
}
|
|
69
|
-
}
|
|
70
|
-
}
|
|
71
|
-
}
|
|
72
|
-
catch (e) {
|
|
73
|
-
if (process.env.DEBUG)
|
|
74
|
-
console.error(`Failed to load MCP source ${source.path}:`, e);
|
|
75
|
-
}
|
|
76
|
-
}
|
|
77
|
-
// De-duplicate by name, preferring earlier (local) configs
|
|
78
|
-
const unique = new Map();
|
|
79
|
-
for (const config of allConfigs) {
|
|
80
|
-
if (!unique.has(config.name)) {
|
|
81
|
-
unique.set(config.name, config);
|
|
82
|
-
}
|
|
83
|
-
}
|
|
84
|
-
return Array.from(unique.values()).filter(s => s.enabled !== false);
|
|
85
|
-
}
|
|
86
|
-
/**
|
|
87
|
-
* Parse MCP config content which can be in multiple formats
|
|
88
|
-
*/
|
|
89
|
-
parseConfigContent(content) {
|
|
90
|
-
try {
|
|
91
|
-
const config = JSON.parse(content);
|
|
92
|
-
// Handle { servers: [...] } format
|
|
93
|
-
if (Array.isArray(config.servers)) {
|
|
94
|
-
return config.servers;
|
|
95
|
-
}
|
|
96
|
-
// Handle { mcpServers: { name: config } } format (Claude-style)
|
|
97
|
-
if (config.mcpServers) {
|
|
98
|
-
return Object.entries(config.mcpServers).map(([name, cfg]) => ({
|
|
99
|
-
name,
|
|
100
|
-
...cfg
|
|
101
|
-
}));
|
|
102
|
-
}
|
|
103
|
-
// Handle single server config
|
|
104
|
-
if (config.name && (config.command || config.url)) {
|
|
105
|
-
return [config];
|
|
106
|
-
}
|
|
107
|
-
}
|
|
108
|
-
catch (e) {
|
|
109
|
-
if (process.env.DEBUG)
|
|
110
|
-
console.error('Failed to parse MCP content:', e);
|
|
111
|
-
}
|
|
112
|
-
return [];
|
|
113
|
-
}
|
|
114
|
-
/**
|
|
115
|
-
* Connect to an MCP server
|
|
116
|
-
*/
|
|
117
|
-
async connect(config) {
|
|
118
|
-
const serverName = config.name;
|
|
119
|
-
if (this.servers.has(serverName)) {
|
|
120
|
-
await this.disconnect(serverName);
|
|
121
|
-
}
|
|
122
|
-
const state = {
|
|
123
|
-
client: null,
|
|
124
|
-
transport: null,
|
|
125
|
-
status: MCPServerStatus.CONNECTING,
|
|
126
|
-
config,
|
|
127
|
-
tools: [],
|
|
128
|
-
resources: [],
|
|
129
|
-
prompts: [],
|
|
130
|
-
};
|
|
131
|
-
this.servers.set(serverName, state);
|
|
132
|
-
this.updateStatus(serverName, MCPServerStatus.CONNECTING);
|
|
133
|
-
try {
|
|
134
|
-
const client = new Client({ name: 'simplecli', version: '0.2.1' }, { capabilities: {} });
|
|
135
|
-
let transport;
|
|
136
|
-
if (config.command) {
|
|
137
|
-
// Stdio transport
|
|
138
|
-
transport = new StdioClientTransport({
|
|
139
|
-
command: config.command,
|
|
140
|
-
args: config.args || [],
|
|
141
|
-
env: { ...process.env, ...(config.env || {}) },
|
|
142
|
-
});
|
|
143
|
-
}
|
|
144
|
-
else if (config.url) {
|
|
145
|
-
// For URL-based transports, we'd need additional SDK imports
|
|
146
|
-
// For now, throw an error suggesting stdio
|
|
147
|
-
throw new Error('URL-based MCP transports require additional configuration. Use stdio transport with command.');
|
|
148
|
-
}
|
|
149
|
-
else {
|
|
150
|
-
throw new Error(`Invalid MCP server config for ${serverName}: missing command or url`);
|
|
151
|
-
}
|
|
152
|
-
// Connect with a 5-second timeout
|
|
153
|
-
await Promise.race([
|
|
154
|
-
client.connect(transport),
|
|
155
|
-
new Promise((_, reject) => setTimeout(() => reject(new Error('Connection timeout')), 5000))
|
|
156
|
-
]);
|
|
157
|
-
state.client = client;
|
|
158
|
-
state.transport = transport;
|
|
159
|
-
state.status = MCPServerStatus.CONNECTED;
|
|
160
|
-
// Discover tools, resources, and prompts
|
|
161
|
-
await this.discover(serverName);
|
|
162
|
-
this.updateStatus(serverName, MCPServerStatus.CONNECTED);
|
|
163
|
-
console.log(`✓ Connected to MCP server: ${serverName}`);
|
|
164
|
-
}
|
|
165
|
-
catch (error) {
|
|
166
|
-
state.status = MCPServerStatus.ERROR;
|
|
167
|
-
state.error = error instanceof Error ? error.message : String(error);
|
|
168
|
-
this.updateStatus(serverName, MCPServerStatus.ERROR);
|
|
169
|
-
console.error(`✗ Failed to connect to MCP server ${serverName}:`, state.error);
|
|
170
|
-
}
|
|
171
|
-
}
|
|
172
|
-
/**
|
|
173
|
-
* Connect to all configured servers
|
|
174
|
-
*/
|
|
175
|
-
async connectAll(configs) {
|
|
176
|
-
const serverConfigs = configs || await this.loadConfig();
|
|
177
|
-
await Promise.all(serverConfigs.map(config => this.connect(config).catch(e => {
|
|
178
|
-
console.error(`Failed to connect to ${config.name}:`, e);
|
|
179
|
-
})));
|
|
180
|
-
}
|
|
181
|
-
/**
|
|
182
|
-
* Disconnect from an MCP server
|
|
183
|
-
*/
|
|
184
|
-
async disconnect(serverName) {
|
|
185
|
-
const state = this.servers.get(serverName);
|
|
186
|
-
if (!state)
|
|
187
|
-
return;
|
|
188
|
-
try {
|
|
189
|
-
if (state.transport) {
|
|
190
|
-
await state.transport.close();
|
|
191
|
-
}
|
|
192
|
-
if (state.client) {
|
|
193
|
-
await state.client.close();
|
|
194
|
-
}
|
|
195
|
-
}
|
|
196
|
-
catch (e) {
|
|
197
|
-
// Ignore close errors
|
|
198
|
-
}
|
|
199
|
-
this.servers.delete(serverName);
|
|
200
|
-
this.updateStatus(serverName, MCPServerStatus.DISCONNECTED);
|
|
201
|
-
}
|
|
202
|
-
/**
|
|
203
|
-
* Disconnect from all servers
|
|
204
|
-
*/
|
|
205
|
-
async disconnectAll() {
|
|
206
|
-
await Promise.all(Array.from(this.servers.keys()).map(name => this.disconnect(name)));
|
|
207
|
-
}
|
|
208
|
-
/**
|
|
209
|
-
* Discover tools, resources, and prompts from a server
|
|
210
|
-
*/
|
|
211
|
-
async discover(serverName) {
|
|
212
|
-
const state = this.servers.get(serverName);
|
|
213
|
-
if (!state?.client)
|
|
214
|
-
return;
|
|
215
|
-
const client = state.client;
|
|
216
|
-
// Discover tools
|
|
217
|
-
try {
|
|
218
|
-
const toolsResult = await client.listTools();
|
|
219
|
-
state.tools = toolsResult.tools.map(tool => ({
|
|
220
|
-
name: tool.name,
|
|
221
|
-
description: tool.description || '',
|
|
222
|
-
serverName,
|
|
223
|
-
inputSchema: tool.inputSchema || {},
|
|
224
|
-
execute: async (args) => {
|
|
225
|
-
const result = await client.callTool({ name: tool.name, arguments: args });
|
|
226
|
-
return result;
|
|
227
|
-
},
|
|
228
|
-
}));
|
|
229
|
-
}
|
|
230
|
-
catch {
|
|
231
|
-
// Server may not support tools
|
|
232
|
-
}
|
|
233
|
-
// Discover resources
|
|
234
|
-
try {
|
|
235
|
-
const resourcesResult = await client.listResources();
|
|
236
|
-
state.resources = resourcesResult.resources.map(resource => ({
|
|
237
|
-
uri: resource.uri,
|
|
238
|
-
name: resource.name,
|
|
239
|
-
description: resource.description,
|
|
240
|
-
mimeType: resource.mimeType,
|
|
241
|
-
serverName,
|
|
242
|
-
}));
|
|
243
|
-
}
|
|
244
|
-
catch {
|
|
245
|
-
// Server may not support resources
|
|
246
|
-
}
|
|
247
|
-
// Discover prompts
|
|
248
|
-
try {
|
|
249
|
-
const promptsResult = await client.listPrompts();
|
|
250
|
-
state.prompts = promptsResult.prompts.map(prompt => ({
|
|
251
|
-
name: prompt.name,
|
|
252
|
-
description: prompt.description,
|
|
253
|
-
serverName,
|
|
254
|
-
arguments: prompt.arguments,
|
|
255
|
-
invoke: async (params) => {
|
|
256
|
-
const stringParams = {};
|
|
257
|
-
for (const [k, v] of Object.entries(params)) {
|
|
258
|
-
stringParams[k] = String(v);
|
|
259
|
-
}
|
|
260
|
-
const result = await client.getPrompt({ name: prompt.name, arguments: stringParams });
|
|
261
|
-
return {
|
|
262
|
-
messages: result.messages.map(m => ({
|
|
263
|
-
role: m.role,
|
|
264
|
-
content: typeof m.content === 'string' ? m.content : JSON.stringify(m.content),
|
|
265
|
-
})),
|
|
266
|
-
};
|
|
267
|
-
},
|
|
268
|
-
}));
|
|
269
|
-
}
|
|
270
|
-
catch {
|
|
271
|
-
// Server may not support prompts
|
|
272
|
-
}
|
|
273
|
-
}
|
|
274
|
-
/**
|
|
275
|
-
* Get all discovered tools from all connected servers
|
|
276
|
-
*/
|
|
277
|
-
getAllTools() {
|
|
278
|
-
const tools = [];
|
|
279
|
-
for (const state of this.servers.values()) {
|
|
280
|
-
if (state.status === MCPServerStatus.CONNECTED) {
|
|
281
|
-
tools.push(...state.tools);
|
|
282
|
-
}
|
|
283
|
-
}
|
|
284
|
-
return tools;
|
|
285
|
-
}
|
|
286
|
-
/**
|
|
287
|
-
* Get all discovered resources from all connected servers
|
|
288
|
-
*/
|
|
289
|
-
getAllResources() {
|
|
290
|
-
const resources = [];
|
|
291
|
-
for (const state of this.servers.values()) {
|
|
292
|
-
if (state.status === MCPServerStatus.CONNECTED) {
|
|
293
|
-
resources.push(...state.resources);
|
|
294
|
-
}
|
|
295
|
-
}
|
|
296
|
-
return resources;
|
|
297
|
-
}
|
|
298
|
-
/**
|
|
299
|
-
* Get all discovered prompts from all connected servers
|
|
300
|
-
*/
|
|
301
|
-
getAllPrompts() {
|
|
302
|
-
const prompts = [];
|
|
303
|
-
for (const state of this.servers.values()) {
|
|
304
|
-
if (state.status === MCPServerStatus.CONNECTED) {
|
|
305
|
-
prompts.push(...state.prompts);
|
|
306
|
-
}
|
|
307
|
-
}
|
|
308
|
-
return prompts;
|
|
309
|
-
}
|
|
310
|
-
/**
|
|
311
|
-
* Get a specific tool by name
|
|
312
|
-
*/
|
|
313
|
-
getTool(name) {
|
|
314
|
-
return this.getAllTools().find(t => t.name === name);
|
|
315
|
-
}
|
|
316
|
-
/**
|
|
317
|
-
* Execute an MCP tool
|
|
318
|
-
*/
|
|
319
|
-
async executeTool(name, args) {
|
|
320
|
-
const tool = this.getTool(name);
|
|
321
|
-
if (!tool) {
|
|
322
|
-
throw new Error(`MCP tool not found: ${name}`);
|
|
323
|
-
}
|
|
324
|
-
return tool.execute(args);
|
|
325
|
-
}
|
|
326
|
-
/**
|
|
327
|
-
* Read an MCP resource
|
|
328
|
-
*/
|
|
329
|
-
async readResource(uri) {
|
|
330
|
-
// Find which server has this resource
|
|
331
|
-
for (const state of this.servers.values()) {
|
|
332
|
-
if (state.status !== MCPServerStatus.CONNECTED || !state.client)
|
|
333
|
-
continue;
|
|
334
|
-
const resource = state.resources.find(r => r.uri === uri);
|
|
335
|
-
if (resource) {
|
|
336
|
-
const result = await state.client.readResource({ uri });
|
|
337
|
-
return result;
|
|
338
|
-
}
|
|
339
|
-
}
|
|
340
|
-
throw new Error(`Resource not found: ${uri}`);
|
|
341
|
-
}
|
|
342
|
-
/**
|
|
343
|
-
* Invoke an MCP prompt
|
|
344
|
-
*/
|
|
345
|
-
async invokePrompt(name, params) {
|
|
346
|
-
const prompt = this.getAllPrompts().find(p => p.name === name);
|
|
347
|
-
if (!prompt) {
|
|
348
|
-
throw new Error(`MCP prompt not found: ${name}`);
|
|
349
|
-
}
|
|
350
|
-
return prompt.invoke(params);
|
|
351
|
-
}
|
|
352
|
-
/**
|
|
353
|
-
* Get server status
|
|
354
|
-
*/
|
|
355
|
-
getServerStatus(serverName) {
|
|
356
|
-
return this.servers.get(serverName)?.status || MCPServerStatus.DISCONNECTED;
|
|
357
|
-
}
|
|
358
|
-
/**
|
|
359
|
-
* Get all server statuses
|
|
360
|
-
*/
|
|
361
|
-
getAllServerStatuses() {
|
|
362
|
-
const statuses = new Map();
|
|
363
|
-
for (const [name, state] of this.servers) {
|
|
364
|
-
statuses.set(name, state.status);
|
|
365
|
-
}
|
|
366
|
-
return statuses;
|
|
367
|
-
}
|
|
368
|
-
updateStatus(serverName, status) {
|
|
369
|
-
this.onStatusChange?.(serverName, status);
|
|
370
|
-
}
|
|
371
|
-
}
|
|
372
|
-
/**
|
|
373
|
-
* Create Composio MCP configuration
|
|
374
|
-
* Composio provides pre-built integrations for 250+ tools
|
|
375
|
-
*/
|
|
376
|
-
export function createComposioConfig(apiKey) {
|
|
377
|
-
return {
|
|
378
|
-
name: 'composio',
|
|
379
|
-
command: 'npx',
|
|
380
|
-
args: ['-y', 'composio-core', 'mcp'],
|
|
381
|
-
env: apiKey ? { COMPOSIO_API_KEY: apiKey } : {},
|
|
382
|
-
trust: 'full',
|
|
383
|
-
enabled: true,
|
|
384
|
-
};
|
|
385
|
-
}
|
|
386
|
-
/**
|
|
387
|
-
* Create filesystem MCP configuration
|
|
388
|
-
*/
|
|
389
|
-
export function createFilesystemConfig(allowedPaths) {
|
|
390
|
-
return {
|
|
391
|
-
name: 'filesystem',
|
|
392
|
-
command: 'npx',
|
|
393
|
-
args: ['-y', '@modelcontextprotocol/server-filesystem', ...allowedPaths],
|
|
394
|
-
trust: 'full',
|
|
395
|
-
enabled: true,
|
|
396
|
-
};
|
|
397
|
-
}
|
|
398
|
-
/**
|
|
399
|
-
* Create GitHub MCP configuration
|
|
400
|
-
*/
|
|
401
|
-
export function createGitHubConfig(token) {
|
|
402
|
-
return {
|
|
403
|
-
name: 'github',
|
|
404
|
-
command: 'npx',
|
|
405
|
-
args: ['-y', '@modelcontextprotocol/server-github'],
|
|
406
|
-
env: token ? { GITHUB_PERSONAL_ACCESS_TOKEN: token } : {},
|
|
407
|
-
trust: 'full',
|
|
408
|
-
enabled: true,
|
|
409
|
-
};
|
|
410
|
-
}
|
|
411
|
-
/**
|
|
412
|
-
* Create memory/context MCP configuration
|
|
413
|
-
*/
|
|
414
|
-
export function createMemoryConfig() {
|
|
415
|
-
return {
|
|
416
|
-
name: 'memory',
|
|
417
|
-
command: 'npx',
|
|
418
|
-
args: ['-y', '@modelcontextprotocol/server-memory'],
|
|
419
|
-
trust: 'full',
|
|
420
|
-
enabled: true,
|
|
421
|
-
};
|
|
422
|
-
}
|
|
423
|
-
/**
|
|
424
|
-
* Create Brave Search MCP configuration
|
|
425
|
-
*/
|
|
426
|
-
export function createBraveSearchConfig(apiKey) {
|
|
427
|
-
return {
|
|
428
|
-
name: 'brave-search',
|
|
429
|
-
command: 'npx',
|
|
430
|
-
args: ['-y', '@modelcontextprotocol/server-brave-search'],
|
|
431
|
-
env: apiKey ? { BRAVE_API_KEY: apiKey } : {},
|
|
432
|
-
trust: 'full',
|
|
433
|
-
enabled: true,
|
|
434
|
-
};
|
|
435
|
-
}
|
|
436
|
-
// Singleton instance
|
|
437
|
-
let mcpManager = null;
|
|
438
|
-
/**
|
|
439
|
-
* Get or create the global MCP manager instance
|
|
440
|
-
*/
|
|
441
|
-
export function getMCPManager() {
|
|
442
|
-
if (!mcpManager) {
|
|
443
|
-
mcpManager = new MCPManager();
|
|
444
|
-
}
|
|
445
|
-
return mcpManager;
|
|
446
|
-
}
|
|
@@ -1,22 +0,0 @@
|
|
|
1
|
-
/**
|
|
2
|
-
* Prompt Provider - Manages composition of system prompts
|
|
3
|
-
* Supports built-in defaults, project-specific overrides, and modular personas.
|
|
4
|
-
*/
|
|
5
|
-
export interface PromptOptions {
|
|
6
|
-
cwd: string;
|
|
7
|
-
skillPrompt?: string;
|
|
8
|
-
}
|
|
9
|
-
export declare class PromptProvider {
|
|
10
|
-
/**
|
|
11
|
-
* Builds the full system prompt by composing multiple layers:
|
|
12
|
-
* 1. Built-in system instructions (src/prompts/defaults)
|
|
13
|
-
* 2. Global user overrides (~/.simple/prompts)
|
|
14
|
-
* 3. Project-specific prompts (.simple/prompts)
|
|
15
|
-
* 4. Current skill instructions
|
|
16
|
-
* 5. Local project rules (AGENT.md)
|
|
17
|
-
*/
|
|
18
|
-
getSystemPrompt(options: PromptOptions): Promise<string>;
|
|
19
|
-
private loadFromDirectory;
|
|
20
|
-
private loadProjectRules;
|
|
21
|
-
}
|
|
22
|
-
export declare function getPromptProvider(): PromptProvider;
|
package/dist/prompts/provider.js
DELETED
|
@@ -1,79 +0,0 @@
|
|
|
1
|
-
/**
|
|
2
|
-
* Prompt Provider - Manages composition of system prompts
|
|
3
|
-
* Supports built-in defaults, project-specific overrides, and modular personas.
|
|
4
|
-
*/
|
|
5
|
-
import { readFileSync, existsSync, readdirSync } from 'fs';
|
|
6
|
-
import { join, dirname } from 'path';
|
|
7
|
-
import { fileURLToPath } from 'url';
|
|
8
|
-
import { homedir } from 'os';
|
|
9
|
-
const __filename = fileURLToPath(import.meta.url);
|
|
10
|
-
const __dirname = dirname(__filename);
|
|
11
|
-
export class PromptProvider {
|
|
12
|
-
/**
|
|
13
|
-
* Builds the full system prompt by composing multiple layers:
|
|
14
|
-
* 1. Built-in system instructions (src/prompts/defaults)
|
|
15
|
-
* 2. Global user overrides (~/.simple/prompts)
|
|
16
|
-
* 3. Project-specific prompts (.simple/prompts)
|
|
17
|
-
* 4. Current skill instructions
|
|
18
|
-
* 5. Local project rules (AGENT.md)
|
|
19
|
-
*/
|
|
20
|
-
async getSystemPrompt(options) {
|
|
21
|
-
const parts = [];
|
|
22
|
-
// 1. Built-in defaults (Hardcoded in the package)
|
|
23
|
-
const builtInDir = join(__dirname, 'defaults');
|
|
24
|
-
if (existsSync(builtInDir)) {
|
|
25
|
-
parts.push(...this.loadFromDirectory(builtInDir));
|
|
26
|
-
}
|
|
27
|
-
// 2. Global user rules (~/.simple/AGENT.md)
|
|
28
|
-
const globalRulesPath = join(homedir(), '.simple', 'AGENT.md');
|
|
29
|
-
if (existsSync(globalRulesPath)) {
|
|
30
|
-
parts.push('\n## Global Rules\n' + readFileSync(globalRulesPath, 'utf-8'));
|
|
31
|
-
}
|
|
32
|
-
// 3. Project rules (AGENT.md)
|
|
33
|
-
const rules = this.loadProjectRules(options.cwd);
|
|
34
|
-
if (rules) {
|
|
35
|
-
parts.push('\n## Project Rules\n' + rules);
|
|
36
|
-
}
|
|
37
|
-
// 4. Skill-specific prompt (Dynamic based on @skill)
|
|
38
|
-
if (options.skillPrompt) {
|
|
39
|
-
parts.push('\n## Skill Context: ' + options.skillPrompt);
|
|
40
|
-
}
|
|
41
|
-
return parts.join('\n\n').trim();
|
|
42
|
-
}
|
|
43
|
-
loadFromDirectory(dir) {
|
|
44
|
-
try {
|
|
45
|
-
return readdirSync(dir)
|
|
46
|
-
.filter(f => f.endsWith('.md') || f.endsWith('.mdc'))
|
|
47
|
-
.sort() // Ensure deterministic order
|
|
48
|
-
.map(f => readFileSync(join(dir, f), 'utf-8'));
|
|
49
|
-
}
|
|
50
|
-
catch {
|
|
51
|
-
return [];
|
|
52
|
-
}
|
|
53
|
-
}
|
|
54
|
-
loadProjectRules(cwd) {
|
|
55
|
-
const commonPaths = [
|
|
56
|
-
'.simple/workdir/AGENT.md',
|
|
57
|
-
'.simple/AGENT.md',
|
|
58
|
-
'.agent/AGENT.md',
|
|
59
|
-
'AGENT.md',
|
|
60
|
-
'.agent.md',
|
|
61
|
-
'.cursorrules',
|
|
62
|
-
'.aider/agent.md'
|
|
63
|
-
];
|
|
64
|
-
for (const p of commonPaths) {
|
|
65
|
-
const fullPath = join(cwd, p);
|
|
66
|
-
if (existsSync(fullPath)) {
|
|
67
|
-
return readFileSync(fullPath, 'utf-8');
|
|
68
|
-
}
|
|
69
|
-
}
|
|
70
|
-
return null;
|
|
71
|
-
}
|
|
72
|
-
}
|
|
73
|
-
let provider = null;
|
|
74
|
-
export function getPromptProvider() {
|
|
75
|
-
if (!provider) {
|
|
76
|
-
provider = new PromptProvider();
|
|
77
|
-
}
|
|
78
|
-
return provider;
|
|
79
|
-
}
|
|
@@ -1,31 +0,0 @@
|
|
|
1
|
-
/**
|
|
2
|
-
* Provider Bridge: Unified LLM interface via Vercel AI SDK
|
|
3
|
-
* Support for OpenAI, Anthropic, Google (Gemini), and custom endpoints.
|
|
4
|
-
*/
|
|
5
|
-
import { type TypeLLMResponse } from '@stan-chen/typellm';
|
|
6
|
-
export interface Message {
|
|
7
|
-
role: 'user' | 'assistant' | 'system';
|
|
8
|
-
content: string;
|
|
9
|
-
}
|
|
10
|
-
export interface Provider {
|
|
11
|
-
name: string;
|
|
12
|
-
model: string;
|
|
13
|
-
generateResponse: (systemPrompt: string, messages: Message[]) => Promise<TypeLLMResponse>;
|
|
14
|
-
}
|
|
15
|
-
/**
|
|
16
|
-
* Structured output strategy:
|
|
17
|
-
* - Uses strong system prompts with explicit JSON format examples
|
|
18
|
-
* - Response parsing with jsonrepair (in cli.ts)
|
|
19
|
-
* - Format reminders in user messages (in context.ts)
|
|
20
|
-
*
|
|
21
|
-
* This approach works across ALL providers without hitting
|
|
22
|
-
* provider-specific schema limitations (e.g., OpenAI's additionalProperties requirement)
|
|
23
|
-
*/
|
|
24
|
-
/**
|
|
25
|
-
* Creates a provider instance using TypeLLM
|
|
26
|
-
*/
|
|
27
|
-
export declare const createProviderForModel: (modelId: string) => Provider;
|
|
28
|
-
/**
|
|
29
|
-
* Creates the default provider
|
|
30
|
-
*/
|
|
31
|
-
export declare const createProvider: () => Provider;
|
package/dist/providers/index.js
DELETED
|
@@ -1,93 +0,0 @@
|
|
|
1
|
-
/**
|
|
2
|
-
* Provider Bridge: Unified LLM interface via Vercel AI SDK
|
|
3
|
-
* Support for OpenAI, Anthropic, Google (Gemini), and custom endpoints.
|
|
4
|
-
*/
|
|
5
|
-
import { createTypeLLM } from '@stan-chen/typellm';
|
|
6
|
-
/**
|
|
7
|
-
* Structured output strategy:
|
|
8
|
-
* - Uses strong system prompts with explicit JSON format examples
|
|
9
|
-
* - Response parsing with jsonrepair (in cli.ts)
|
|
10
|
-
* - Format reminders in user messages (in context.ts)
|
|
11
|
-
*
|
|
12
|
-
* This approach works across ALL providers without hitting
|
|
13
|
-
* provider-specific schema limitations (e.g., OpenAI's additionalProperties requirement)
|
|
14
|
-
*/
|
|
15
|
-
/**
|
|
16
|
-
* Creates a provider instance using TypeLLM
|
|
17
|
-
*/
|
|
18
|
-
export const createProviderForModel = (modelId) => {
|
|
19
|
-
let providerType = 'openai';
|
|
20
|
-
let actualModel = modelId;
|
|
21
|
-
let baseURL;
|
|
22
|
-
// Handle provider selection
|
|
23
|
-
if (modelId.startsWith('anthropic:')) {
|
|
24
|
-
actualModel = modelId.split(':')[1] || modelId;
|
|
25
|
-
providerType = 'anthropic';
|
|
26
|
-
}
|
|
27
|
-
else if (modelId.startsWith('google:') || modelId.startsWith('gemini:')) {
|
|
28
|
-
actualModel = modelId.split(':')[1] || modelId;
|
|
29
|
-
providerType = 'google';
|
|
30
|
-
}
|
|
31
|
-
else if (modelId.startsWith('openai:')) {
|
|
32
|
-
actualModel = modelId.split(':')[1] || modelId;
|
|
33
|
-
providerType = 'openai';
|
|
34
|
-
}
|
|
35
|
-
else if (modelId.startsWith('claude') || (process.env.ANTHROPIC_API_KEY && !process.env.OPENAI_API_KEY)) {
|
|
36
|
-
providerType = 'anthropic';
|
|
37
|
-
}
|
|
38
|
-
else if (modelId.startsWith('gemini') || (process.env.GEMINI_API_KEY && !process.env.OPENAI_API_KEY)) {
|
|
39
|
-
providerType = 'google';
|
|
40
|
-
}
|
|
41
|
-
else if (process.env.LITELLM_BASE_URL) {
|
|
42
|
-
providerType = 'litellm';
|
|
43
|
-
baseURL = process.env.LITELLM_BASE_URL;
|
|
44
|
-
}
|
|
45
|
-
else {
|
|
46
|
-
providerType = 'openai';
|
|
47
|
-
}
|
|
48
|
-
// Final check for the Google key mapping
|
|
49
|
-
if (providerType === 'google' && process.env.GEMINI_API_KEY && !process.env.GOOGLE_GENERATIVE_AI_API_KEY) {
|
|
50
|
-
process.env.GOOGLE_GENERATIVE_AI_API_KEY = process.env.GEMINI_API_KEY;
|
|
51
|
-
}
|
|
52
|
-
const llm = createTypeLLM({
|
|
53
|
-
provider: providerType,
|
|
54
|
-
model: actualModel,
|
|
55
|
-
baseURL: baseURL,
|
|
56
|
-
apiKey: providerType === 'openai' ? process.env.OPENAI_API_KEY :
|
|
57
|
-
providerType === 'google' ? process.env.GEMINI_API_KEY || process.env.GOOGLE_GENERATIVE_AI_API_KEY :
|
|
58
|
-
providerType === 'anthropic' ? process.env.ANTHROPIC_API_KEY :
|
|
59
|
-
undefined,
|
|
60
|
-
temperature: 0
|
|
61
|
-
});
|
|
62
|
-
return {
|
|
63
|
-
name: providerType,
|
|
64
|
-
model: actualModel,
|
|
65
|
-
generateResponse: async (systemPrompt, messages) => {
|
|
66
|
-
try {
|
|
67
|
-
const response = await llm.generate(systemPrompt, messages);
|
|
68
|
-
if ((process.env.DEBUG === 'true') && response)
|
|
69
|
-
console.log(`[DEBUG] TypeLLM Response: ${JSON.stringify(response).substring(0, 300)}...`);
|
|
70
|
-
return response;
|
|
71
|
-
}
|
|
72
|
-
catch (e) {
|
|
73
|
-
const msg = `Error calling TypeLLM: ${e instanceof Error ? e.message : e}`;
|
|
74
|
-
return {
|
|
75
|
-
thought: 'Error occurred during generation',
|
|
76
|
-
tool: 'none',
|
|
77
|
-
args: {},
|
|
78
|
-
message: msg,
|
|
79
|
-
raw: msg
|
|
80
|
-
};
|
|
81
|
-
}
|
|
82
|
-
}
|
|
83
|
-
};
|
|
84
|
-
};
|
|
85
|
-
/**
|
|
86
|
-
* Creates the default provider
|
|
87
|
-
*/
|
|
88
|
-
export const createProvider = () => {
|
|
89
|
-
const isClaw = process.argv.includes('--claw') || process.argv.includes('-claw');
|
|
90
|
-
const model = (isClaw ? process.env.CLAW_MODEL : null) || process.env.OPENAI_MODEL || process.env.GEMINI_MODEL || 'gpt-4o-mini';
|
|
91
|
-
console.log(`🤖 Using TypeLLM with model: ${model}`);
|
|
92
|
-
return createProviderForModel(model);
|
|
93
|
-
};
|
|
@@ -1,12 +0,0 @@
|
|
|
1
|
-
/**
|
|
2
|
-
* Multi-Provider: Manages multiple LLM models for MoE routing via LiteLLM
|
|
3
|
-
* Each tier can use a different model from any provider
|
|
4
|
-
*/
|
|
5
|
-
import { type Provider, type Message } from './index.js';
|
|
6
|
-
import type { Tier, TierConfig } from '../router.js';
|
|
7
|
-
import type { TypeLLMResponse } from '@stan-chen/typellm';
|
|
8
|
-
export interface MultiProvider {
|
|
9
|
-
getProvider: (tier: Tier) => Provider;
|
|
10
|
-
generateWithTier: (tier: Tier, systemPrompt: string, messages: Message[]) => Promise<TypeLLMResponse>;
|
|
11
|
-
}
|
|
12
|
-
export declare const createMultiProvider: (tierConfigs: Map<Tier, TierConfig>) => MultiProvider;
|