50c 2.8.0 → 2.9.0
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/bin/50c.js +264 -25
- package/package.json +2 -2
package/bin/50c.js
CHANGED
|
@@ -73,12 +73,243 @@ async function runMCP() {
|
|
|
73
73
|
});
|
|
74
74
|
}
|
|
75
75
|
|
|
76
|
+
// Detect IDE from environment/process
|
|
77
|
+
function detectIDE() {
|
|
78
|
+
const env = process.env;
|
|
79
|
+
if (env.CURSOR_SESSION || env.CURSOR_TRACE_ID) return 'cursor';
|
|
80
|
+
if (env.WINDSURF_SESSION) return 'windsurf';
|
|
81
|
+
if (env.VSCODE_PID || env.TERM_PROGRAM === 'vscode') return 'vscode';
|
|
82
|
+
if (env.CLAUDE_DESKTOP) return 'claude-desktop';
|
|
83
|
+
// Check for common IDE paths
|
|
84
|
+
const cwd = process.cwd();
|
|
85
|
+
if (cwd.includes('.cursor')) return 'cursor';
|
|
86
|
+
if (cwd.includes('windsurf')) return 'windsurf';
|
|
87
|
+
return null;
|
|
88
|
+
}
|
|
89
|
+
|
|
90
|
+
// Get MCP config path for IDE
|
|
91
|
+
function getMCPConfigPath(ide) {
|
|
92
|
+
const os = require('os');
|
|
93
|
+
const path = require('path');
|
|
94
|
+
const home = os.homedir();
|
|
95
|
+
|
|
96
|
+
const paths = {
|
|
97
|
+
'cursor': path.join(home, '.cursor', 'mcp.json'),
|
|
98
|
+
'windsurf': path.join(home, '.codeium', 'windsurf', 'mcp_config.json'),
|
|
99
|
+
'vscode': path.join(home, '.vscode', 'mcp.json'),
|
|
100
|
+
'claude-desktop': process.platform === 'win32'
|
|
101
|
+
? path.join(home, 'AppData', 'Roaming', 'Claude', 'claude_desktop_config.json')
|
|
102
|
+
: path.join(home, 'Library', 'Application Support', 'Claude', 'claude_desktop_config.json'),
|
|
103
|
+
'verdent': path.join(home, '.verdent', 'mcp.json')
|
|
104
|
+
};
|
|
105
|
+
return paths[ide] || null;
|
|
106
|
+
}
|
|
107
|
+
|
|
76
108
|
// CLI Mode
|
|
77
109
|
async function runCLI(args) {
|
|
78
110
|
const cmd = args[0];
|
|
79
111
|
const cmdArgs = args.slice(1);
|
|
112
|
+
const fs = require('fs');
|
|
113
|
+
const path = require('path');
|
|
114
|
+
const os = require('os');
|
|
80
115
|
|
|
81
116
|
switch (cmd) {
|
|
117
|
+
case 'init': {
|
|
118
|
+
console.log('\n 50c init - Quick Setup\n');
|
|
119
|
+
|
|
120
|
+
// Detect IDE
|
|
121
|
+
const ide = detectIDE() || cmdArgs[0];
|
|
122
|
+
const ides = ['cursor', 'windsurf', 'vscode', 'claude-desktop', 'verdent'];
|
|
123
|
+
|
|
124
|
+
if (!ide) {
|
|
125
|
+
console.log(' Detected IDE: none\n');
|
|
126
|
+
console.log(' Which IDE are you using?');
|
|
127
|
+
ides.forEach((i, idx) => console.log(` ${idx + 1}. ${i}`));
|
|
128
|
+
console.log('\n Run: 50c init <ide>');
|
|
129
|
+
console.log(' Example: 50c init cursor\n');
|
|
130
|
+
break;
|
|
131
|
+
}
|
|
132
|
+
|
|
133
|
+
if (!ides.includes(ide)) {
|
|
134
|
+
console.log(` Unknown IDE: ${ide}`);
|
|
135
|
+
console.log(` Supported: ${ides.join(', ')}\n`);
|
|
136
|
+
break;
|
|
137
|
+
}
|
|
138
|
+
|
|
139
|
+
console.log(` IDE: ${ide}`);
|
|
140
|
+
|
|
141
|
+
// Check for API key
|
|
142
|
+
const apiKey = process.env.FIFTYC_API_KEY || process.env.FIFTY_CENT_API_KEY;
|
|
143
|
+
if (apiKey) {
|
|
144
|
+
console.log(` API Key: ${apiKey.slice(0, 8)}...`);
|
|
145
|
+
} else {
|
|
146
|
+
console.log(' API Key: not set');
|
|
147
|
+
console.log('\n Get your key at: https://50c.ai');
|
|
148
|
+
console.log(' Then run: 50c init <ide>\n');
|
|
149
|
+
}
|
|
150
|
+
|
|
151
|
+
// Get config path
|
|
152
|
+
const configPath = getMCPConfigPath(ide);
|
|
153
|
+
if (!configPath) {
|
|
154
|
+
console.log(` Config path: unknown for ${ide}\n`);
|
|
155
|
+
break;
|
|
156
|
+
}
|
|
157
|
+
|
|
158
|
+
console.log(` Config: ${configPath}`);
|
|
159
|
+
|
|
160
|
+
// Generate config
|
|
161
|
+
const mcpConfig = {
|
|
162
|
+
mcpServers: {
|
|
163
|
+
'50c': {
|
|
164
|
+
command: 'npx',
|
|
165
|
+
args: ['-y', '50c'],
|
|
166
|
+
env: apiKey ? { FIFTYC_API_KEY: apiKey } : {}
|
|
167
|
+
}
|
|
168
|
+
}
|
|
169
|
+
};
|
|
170
|
+
|
|
171
|
+
// Check if file exists
|
|
172
|
+
let existingConfig = {};
|
|
173
|
+
try {
|
|
174
|
+
if (fs.existsSync(configPath)) {
|
|
175
|
+
existingConfig = JSON.parse(fs.readFileSync(configPath, 'utf8'));
|
|
176
|
+
console.log(' Status: updating existing config');
|
|
177
|
+
} else {
|
|
178
|
+
console.log(' Status: creating new config');
|
|
179
|
+
}
|
|
180
|
+
} catch (e) {
|
|
181
|
+
console.log(' Status: creating new config');
|
|
182
|
+
}
|
|
183
|
+
|
|
184
|
+
// Merge configs
|
|
185
|
+
const finalConfig = {
|
|
186
|
+
...existingConfig,
|
|
187
|
+
mcpServers: {
|
|
188
|
+
...(existingConfig.mcpServers || {}),
|
|
189
|
+
'50c': mcpConfig.mcpServers['50c']
|
|
190
|
+
}
|
|
191
|
+
};
|
|
192
|
+
|
|
193
|
+
// Create directory if needed
|
|
194
|
+
const configDir = path.dirname(configPath);
|
|
195
|
+
if (!fs.existsSync(configDir)) {
|
|
196
|
+
fs.mkdirSync(configDir, { recursive: true });
|
|
197
|
+
}
|
|
198
|
+
|
|
199
|
+
// Write config
|
|
200
|
+
fs.writeFileSync(configPath, JSON.stringify(finalConfig, null, 2));
|
|
201
|
+
console.log('\n Done! 50c added to ' + ide);
|
|
202
|
+
|
|
203
|
+
// Show next steps
|
|
204
|
+
console.log('\n Next steps:');
|
|
205
|
+
console.log(' 1. Restart ' + ide);
|
|
206
|
+
console.log(' 2. 50c should appear with 117+ tools');
|
|
207
|
+
if (!apiKey) {
|
|
208
|
+
console.log(' 3. Set FIFTYC_API_KEY in the config for full access');
|
|
209
|
+
}
|
|
210
|
+
console.log('\n Try: 50c tools (see all available tools)');
|
|
211
|
+
console.log(' 50c doctor (check setup)\n');
|
|
212
|
+
break;
|
|
213
|
+
}
|
|
214
|
+
|
|
215
|
+
case 'tools': {
|
|
216
|
+
const tools = await lib.getTools();
|
|
217
|
+
const packFilter = cmdArgs.find(a => a.startsWith('--pack='))?.split('=')[1];
|
|
218
|
+
const search = cmdArgs.find(a => !a.startsWith('--'));
|
|
219
|
+
|
|
220
|
+
let filtered = tools;
|
|
221
|
+
if (packFilter) {
|
|
222
|
+
filtered = tools.filter(t => t.name.startsWith(packFilter) || t.name.includes(packFilter));
|
|
223
|
+
}
|
|
224
|
+
if (search) {
|
|
225
|
+
const s = search.toLowerCase();
|
|
226
|
+
filtered = filtered.filter(t =>
|
|
227
|
+
t.name.toLowerCase().includes(s) ||
|
|
228
|
+
(t.description || '').toLowerCase().includes(s)
|
|
229
|
+
);
|
|
230
|
+
}
|
|
231
|
+
|
|
232
|
+
console.log(`\n 50c Tools (${filtered.length}/${tools.length})\n`);
|
|
233
|
+
|
|
234
|
+
// Group by prefix
|
|
235
|
+
const groups = {};
|
|
236
|
+
filtered.forEach(t => {
|
|
237
|
+
const prefix = t.name.split('_')[0];
|
|
238
|
+
if (!groups[prefix]) groups[prefix] = [];
|
|
239
|
+
groups[prefix].push(t);
|
|
240
|
+
});
|
|
241
|
+
|
|
242
|
+
for (const [prefix, groupTools] of Object.entries(groups)) {
|
|
243
|
+
console.log(` ${prefix} (${groupTools.length}):`);
|
|
244
|
+
groupTools.slice(0, 5).forEach(t => {
|
|
245
|
+
const cost = t.cost ? ` $${t.cost.toFixed(2)}` : ' FREE';
|
|
246
|
+
console.log(` ${t.name}${cost}`);
|
|
247
|
+
});
|
|
248
|
+
if (groupTools.length > 5) {
|
|
249
|
+
console.log(` ... and ${groupTools.length - 5} more`);
|
|
250
|
+
}
|
|
251
|
+
console.log('');
|
|
252
|
+
}
|
|
253
|
+
|
|
254
|
+
console.log(' Filter: 50c tools <search>');
|
|
255
|
+
console.log(' 50c tools --pack=grabr\n');
|
|
256
|
+
break;
|
|
257
|
+
}
|
|
258
|
+
|
|
259
|
+
case 'doctor': {
|
|
260
|
+
console.log('\n 50c doctor - System Check\n');
|
|
261
|
+
|
|
262
|
+
// Check API key
|
|
263
|
+
const apiKey = process.env.FIFTYC_API_KEY || process.env.FIFTY_CENT_API_KEY;
|
|
264
|
+
console.log(` API Key: ${apiKey ? 'set (' + apiKey.slice(0, 8) + '...)' : 'not set'}`);
|
|
265
|
+
|
|
266
|
+
// Check vault
|
|
267
|
+
const vaultStatus = await lib.vault.status();
|
|
268
|
+
console.log(` Vault: ${vaultStatus.initialized ? 'initialized' : 'not initialized'}`);
|
|
269
|
+
if (vaultStatus.initialized) {
|
|
270
|
+
console.log(` ${vaultStatus.locked ? 'locked' : 'unlocked'}`);
|
|
271
|
+
}
|
|
272
|
+
|
|
273
|
+
// Check packs
|
|
274
|
+
const packs = await lib.packs.listPacks();
|
|
275
|
+
console.log(` Packs: ${packs.enabled?.length || 0} enabled`);
|
|
276
|
+
|
|
277
|
+
// Check tools
|
|
278
|
+
const tools = await lib.getTools();
|
|
279
|
+
console.log(` Tools: ${tools.length} available`);
|
|
280
|
+
|
|
281
|
+
// Check IDE configs
|
|
282
|
+
console.log('\n IDE Configs:');
|
|
283
|
+
const ides = ['cursor', 'windsurf', 'vscode', 'claude-desktop', 'verdent'];
|
|
284
|
+
for (const ide of ides) {
|
|
285
|
+
const configPath = getMCPConfigPath(ide);
|
|
286
|
+
if (configPath && fs.existsSync(configPath)) {
|
|
287
|
+
try {
|
|
288
|
+
const config = JSON.parse(fs.readFileSync(configPath, 'utf8'));
|
|
289
|
+
const has50c = config.mcpServers?.['50c'] ? 'configured' : 'no 50c';
|
|
290
|
+
console.log(` ${ide}: ${has50c}`);
|
|
291
|
+
} catch (e) {
|
|
292
|
+
console.log(` ${ide}: invalid config`);
|
|
293
|
+
}
|
|
294
|
+
}
|
|
295
|
+
}
|
|
296
|
+
|
|
297
|
+
// Overall status
|
|
298
|
+
console.log('\n Status:');
|
|
299
|
+
if (!apiKey) {
|
|
300
|
+
console.log(' ! Set FIFTYC_API_KEY for API access');
|
|
301
|
+
}
|
|
302
|
+
if (!vaultStatus.initialized) {
|
|
303
|
+
console.log(' ! Run: 50c vault init <passphrase>');
|
|
304
|
+
}
|
|
305
|
+
if (apiKey && vaultStatus.initialized && tools.length > 50) {
|
|
306
|
+
console.log(' All good! 50c is ready.\n');
|
|
307
|
+
} else {
|
|
308
|
+
console.log('\n Run: 50c init <ide> to configure\n');
|
|
309
|
+
}
|
|
310
|
+
break;
|
|
311
|
+
}
|
|
312
|
+
|
|
82
313
|
case 'status':
|
|
83
314
|
console.log(JSON.stringify(await lib.getStatus(), null, 2));
|
|
84
315
|
break;
|
|
@@ -185,36 +416,44 @@ async function runCLI(args) {
|
|
|
185
416
|
break;
|
|
186
417
|
|
|
187
418
|
case 'help':
|
|
419
|
+
case '-h':
|
|
420
|
+
case '--help':
|
|
188
421
|
default:
|
|
189
|
-
console.log(`
|
|
422
|
+
console.log(`
|
|
423
|
+
50c - AI Toolkit (117+ tools)
|
|
190
424
|
|
|
191
|
-
|
|
192
|
-
|
|
193
|
-
|
|
194
|
-
|
|
195
|
-
50c enable <pack> Enable a pack
|
|
196
|
-
50c disable <pack> Disable a pack
|
|
197
|
-
50c packs List packs
|
|
198
|
-
50c vault <cmd> Vault commands
|
|
425
|
+
Quick Start:
|
|
426
|
+
50c init <ide> Auto-configure for your IDE
|
|
427
|
+
50c tools List all available tools
|
|
428
|
+
50c doctor Check setup and diagnose issues
|
|
199
429
|
|
|
200
|
-
Packs:
|
|
201
|
-
|
|
202
|
-
|
|
203
|
-
|
|
204
|
-
|
|
205
|
-
ux UI/UX toolkit (17 tools)
|
|
430
|
+
Packs:
|
|
431
|
+
50c packs List enabled/available packs
|
|
432
|
+
50c enable <pack> Enable a pack
|
|
433
|
+
50c disable <pack> Disable a pack
|
|
434
|
+
50c discover Show pack recommendations
|
|
206
435
|
|
|
207
|
-
|
|
208
|
-
|
|
209
|
-
|
|
210
|
-
|
|
211
|
-
|
|
212
|
-
|
|
213
|
-
|
|
214
|
-
|
|
215
|
-
|
|
436
|
+
Vault (secure storage):
|
|
437
|
+
50c vault init <pass> Initialize encrypted vault
|
|
438
|
+
50c vault add <k> <v> Store a credential
|
|
439
|
+
50c vault get <key> Retrieve a credential
|
|
440
|
+
50c vault list List stored credentials
|
|
441
|
+
|
|
442
|
+
MCP Server:
|
|
443
|
+
50c Start MCP server (for IDEs)
|
|
444
|
+
50c --mcp Force MCP mode
|
|
445
|
+
|
|
446
|
+
Supported IDEs:
|
|
447
|
+
cursor, windsurf, vscode, claude-desktop, verdent
|
|
448
|
+
|
|
449
|
+
Example:
|
|
450
|
+
$ npx -y 50c init cursor
|
|
451
|
+
$ 50c tools grabr
|
|
452
|
+
$ 50c vault init mysecret
|
|
216
453
|
|
|
217
|
-
|
|
454
|
+
Docs: https://50c.ai/docs
|
|
455
|
+
Help: https://discord.gg/50c
|
|
456
|
+
`);
|
|
218
457
|
}
|
|
219
458
|
}
|
|
220
459
|
|
package/package.json
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "50c",
|
|
3
|
-
"version": "2.
|
|
4
|
-
"description": "AI toolkit with
|
|
3
|
+
"version": "2.9.0",
|
|
4
|
+
"description": "AI toolkit with init/doctor CLI. One install, 117+ tools.",
|
|
5
5
|
"main": "lib/index.js",
|
|
6
6
|
"bin": {
|
|
7
7
|
"50c": "./bin/50c.js"
|