swarm-code 0.1.0 → 0.1.1
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/dist/cli.js +5 -5
- package/dist/interactive.js +107 -28
- package/package.json +1 -1
package/dist/cli.js
CHANGED
|
@@ -21,10 +21,10 @@ const { runRlmLoop } = await import("./core/rlm.js");
|
|
|
21
21
|
// ── Arg parsing ─────────────────────────────────────────────────────────────
|
|
22
22
|
function usage() {
|
|
23
23
|
console.error(`
|
|
24
|
-
swarm run —
|
|
24
|
+
swarm run — Text processing mode (RLM)
|
|
25
25
|
|
|
26
26
|
USAGE
|
|
27
|
-
|
|
27
|
+
swarm run [OPTIONS] "<query>"
|
|
28
28
|
|
|
29
29
|
OPTIONS
|
|
30
30
|
--model <id> Model ID (default: RLM_MODEL from .env)
|
|
@@ -34,9 +34,9 @@ OPTIONS
|
|
|
34
34
|
--verbose Show iteration progress
|
|
35
35
|
|
|
36
36
|
EXAMPLES
|
|
37
|
-
|
|
38
|
-
curl -s https://example.com/large.py |
|
|
39
|
-
|
|
37
|
+
swarm run --file big.txt "List all classes"
|
|
38
|
+
curl -s https://example.com/large.py | swarm run --stdin "Summarize"
|
|
39
|
+
swarm run --url https://raw.githubusercontent.com/.../typing.py "Count public classes"
|
|
40
40
|
`.trim());
|
|
41
41
|
process.exit(1);
|
|
42
42
|
}
|
package/dist/interactive.js
CHANGED
|
@@ -309,14 +309,14 @@ function handleMultiLineAsContext(input) {
|
|
|
309
309
|
function printBanner() {
|
|
310
310
|
console.log(`
|
|
311
311
|
${c.cyan}${c.bold}
|
|
312
|
-
|
|
313
|
-
|
|
314
|
-
|
|
315
|
-
|
|
316
|
-
|
|
317
|
-
|
|
312
|
+
███████╗██╗ ██╗ █████╗ ██████╗ ███╗ ███╗
|
|
313
|
+
██╔════╝██║ ██║██╔══██╗██╔══██╗████╗ ████║
|
|
314
|
+
███████╗██║ █╗ ██║███████║██████╔╝██╔████╔██║
|
|
315
|
+
╚════██║██║███╗██║██╔══██║██╔══██╗██║╚██╔╝██║
|
|
316
|
+
███████║╚███╔███╔╝██║ ██║██║ ██║██║ ╚═╝ ██║
|
|
317
|
+
╚══════╝ ╚══╝╚══╝ ╚═╝ ╚═╝╚═╝ ╚═╝╚═╝ ╚═╝
|
|
318
318
|
${c.reset}
|
|
319
|
-
${c.dim}
|
|
319
|
+
${c.dim} Swarm-native coding agent orchestrator${c.reset}
|
|
320
320
|
`);
|
|
321
321
|
}
|
|
322
322
|
// ── Status line ─────────────────────────────────────────────────────────────
|
|
@@ -1285,45 +1285,124 @@ async function interactive() {
|
|
|
1285
1285
|
if (!hasAnyApiKey()) {
|
|
1286
1286
|
printBanner();
|
|
1287
1287
|
console.log(` ${c.bold}Welcome! Let's get you set up.${c.reset}\n`);
|
|
1288
|
+
// Agent definitions — each lists which API keys it needs (if any)
|
|
1289
|
+
const AGENT_CHOICES = [
|
|
1290
|
+
{
|
|
1291
|
+
name: "OpenCode",
|
|
1292
|
+
id: "opencode",
|
|
1293
|
+
desc: "Multi-provider + open-source (Ollama, DeepSeek, Kimi, GLM, ...)",
|
|
1294
|
+
keys: SETUP_PROVIDERS, // optionally accepts any provider
|
|
1295
|
+
requiresKey: false, // can run with local/open-source models, no API key needed
|
|
1296
|
+
},
|
|
1297
|
+
{
|
|
1298
|
+
name: "Claude Code",
|
|
1299
|
+
id: "claude-code",
|
|
1300
|
+
desc: "Anthropic",
|
|
1301
|
+
keys: SETUP_PROVIDERS.filter((p) => p.piProvider === "anthropic"),
|
|
1302
|
+
requiresKey: true,
|
|
1303
|
+
},
|
|
1304
|
+
{
|
|
1305
|
+
name: "Codex",
|
|
1306
|
+
id: "codex",
|
|
1307
|
+
desc: "OpenAI",
|
|
1308
|
+
keys: SETUP_PROVIDERS.filter((p) => p.piProvider === "openai"),
|
|
1309
|
+
requiresKey: true,
|
|
1310
|
+
},
|
|
1311
|
+
{
|
|
1312
|
+
name: "Aider",
|
|
1313
|
+
id: "aider",
|
|
1314
|
+
desc: "Git-aware AI pair programmer (Anthropic, OpenAI)",
|
|
1315
|
+
keys: SETUP_PROVIDERS.filter((p) => p.piProvider === "anthropic" || p.piProvider === "openai"),
|
|
1316
|
+
requiresKey: true,
|
|
1317
|
+
},
|
|
1318
|
+
{
|
|
1319
|
+
name: "Direct LLM",
|
|
1320
|
+
id: "direct-llm",
|
|
1321
|
+
desc: "Bare API calls, no coding agent",
|
|
1322
|
+
keys: SETUP_PROVIDERS,
|
|
1323
|
+
requiresKey: true,
|
|
1324
|
+
},
|
|
1325
|
+
];
|
|
1288
1326
|
const setupRl = readline.createInterface({ input: stdin, output: stdout, terminal: true });
|
|
1289
1327
|
let setupDone = false;
|
|
1290
1328
|
while (!setupDone) {
|
|
1291
|
-
console.log(` ${c.bold}Select your
|
|
1292
|
-
for (let i = 0; i <
|
|
1293
|
-
|
|
1329
|
+
console.log(` ${c.bold}Select your coding agent:${c.reset}\n`);
|
|
1330
|
+
for (let i = 0; i < AGENT_CHOICES.length; i++) {
|
|
1331
|
+
const a = AGENT_CHOICES[i];
|
|
1332
|
+
console.log(` ${c.dim}${i + 1}${c.reset} ${a.name} ${c.dim}${a.desc}${c.reset}`);
|
|
1294
1333
|
}
|
|
1295
1334
|
console.log();
|
|
1296
|
-
const choice = await questionWithEsc(setupRl, ` ${c.cyan}
|
|
1335
|
+
const choice = await questionWithEsc(setupRl, ` ${c.cyan}Agent [1-${AGENT_CHOICES.length}]:${c.reset} `);
|
|
1297
1336
|
if (choice === null) {
|
|
1298
|
-
// ESC at provider selection → exit
|
|
1299
1337
|
console.log(`\n ${c.dim}Exiting.${c.reset}\n`);
|
|
1300
1338
|
setupRl.close();
|
|
1301
1339
|
process.exit(0);
|
|
1302
1340
|
}
|
|
1303
1341
|
const idx = parseInt(choice, 10) - 1;
|
|
1304
|
-
if (Number.isNaN(idx) || idx < 0 || idx >=
|
|
1342
|
+
if (Number.isNaN(idx) || idx < 0 || idx >= AGENT_CHOICES.length) {
|
|
1305
1343
|
console.log(`\n ${c.dim}Invalid choice.${c.reset}\n`);
|
|
1306
1344
|
continue;
|
|
1307
1345
|
}
|
|
1308
|
-
const
|
|
1309
|
-
|
|
1310
|
-
|
|
1311
|
-
|
|
1346
|
+
const agent = AGENT_CHOICES[idx];
|
|
1347
|
+
console.log(`\n ${c.green}✓${c.reset} Agent: ${c.bold}${agent.name}${c.reset}\n`);
|
|
1348
|
+
// Prompt for API key(s) one by one based on the selected agent
|
|
1349
|
+
let gotAnyKey = false;
|
|
1350
|
+
if (agent.requiresKey) {
|
|
1351
|
+
// Agent requires at least one key — prompt until we get one
|
|
1352
|
+
console.log(` ${c.dim}${agent.name} requires an API key. Configure one now:${c.reset}\n`);
|
|
1353
|
+
for (const provider of agent.keys) {
|
|
1354
|
+
const gotKey = await promptForProviderKey(setupRl, provider);
|
|
1355
|
+
if (gotKey === null)
|
|
1356
|
+
break; // ESC — skip remaining
|
|
1357
|
+
if (gotKey) {
|
|
1358
|
+
gotAnyKey = true;
|
|
1359
|
+
break; // Got one — that's enough
|
|
1360
|
+
}
|
|
1361
|
+
}
|
|
1362
|
+
if (!gotAnyKey) {
|
|
1363
|
+
console.log(`\n ${c.dim}No key provided. Try another agent or set keys in .env${c.reset}\n`);
|
|
1364
|
+
continue;
|
|
1365
|
+
}
|
|
1366
|
+
}
|
|
1367
|
+
else {
|
|
1368
|
+
// Agent works without keys (e.g. OpenCode with open-source models)
|
|
1369
|
+
// Offer to configure a provider key optionally
|
|
1370
|
+
console.log(` ${c.dim}${agent.name} works with open-source models (no API key needed).${c.reset}`);
|
|
1371
|
+
console.log(` ${c.dim}Optionally configure a provider for cloud models:${c.reset}\n`);
|
|
1372
|
+
for (const provider of agent.keys) {
|
|
1373
|
+
console.log(` ${c.dim}-${c.reset} ${provider.name} ${c.dim}(${provider.env})${c.reset}`);
|
|
1374
|
+
}
|
|
1312
1375
|
console.log();
|
|
1313
|
-
|
|
1376
|
+
const addKey = await questionWithEsc(setupRl, ` ${c.cyan}Add an API key? [y/N]:${c.reset} `);
|
|
1377
|
+
if (addKey !== null && (addKey.toLowerCase() === "y" || addKey.toLowerCase() === "yes")) {
|
|
1378
|
+
for (const provider of agent.keys) {
|
|
1379
|
+
const gotKey = await promptForProviderKey(setupRl, provider);
|
|
1380
|
+
if (gotKey === null)
|
|
1381
|
+
break;
|
|
1382
|
+
if (gotKey) {
|
|
1383
|
+
gotAnyKey = true;
|
|
1384
|
+
break;
|
|
1385
|
+
}
|
|
1386
|
+
}
|
|
1387
|
+
}
|
|
1314
1388
|
}
|
|
1315
|
-
|
|
1316
|
-
|
|
1317
|
-
|
|
1318
|
-
|
|
1389
|
+
// Set default model
|
|
1390
|
+
const activeProvider = Object.keys(PROVIDER_KEYS).find((p) => process.env[providerEnvKey(p)]);
|
|
1391
|
+
if (activeProvider) {
|
|
1392
|
+
// Has an API key — use that provider's default model
|
|
1393
|
+
currentProviderName = activeProvider;
|
|
1394
|
+
const defaultModel = getDefaultModelForProvider(activeProvider);
|
|
1395
|
+
if (defaultModel) {
|
|
1396
|
+
currentModelId = defaultModel;
|
|
1397
|
+
saveModelPreference(currentModelId);
|
|
1398
|
+
console.log(` ${c.green}✓${c.reset} Default model: ${c.bold}${currentModelId}${c.reset}`);
|
|
1399
|
+
}
|
|
1319
1400
|
}
|
|
1320
|
-
|
|
1321
|
-
|
|
1322
|
-
|
|
1323
|
-
if (defaultModel) {
|
|
1324
|
-
currentModelId = defaultModel;
|
|
1401
|
+
else {
|
|
1402
|
+
// No API key — default to open-source model via OpenCode
|
|
1403
|
+
currentModelId = "ollama/deepseek-coder-v2";
|
|
1325
1404
|
saveModelPreference(currentModelId);
|
|
1326
|
-
console.log(` ${c.green}✓${c.reset} Default model: ${c.bold}${currentModelId}${c.reset}`);
|
|
1405
|
+
console.log(` ${c.green}✓${c.reset} Default model: ${c.bold}${currentModelId}${c.reset} ${c.dim}(open-source, requires Ollama)${c.reset}`);
|
|
1327
1406
|
}
|
|
1328
1407
|
console.log();
|
|
1329
1408
|
setupDone = true;
|
package/package.json
CHANGED