swarm-code 0.1.3 → 0.1.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/dist/interactive.js +74 -33
- package/package.json +1 -1
package/dist/interactive.js
CHANGED
|
@@ -478,41 +478,39 @@ function checkboxSelect(items) {
|
|
|
478
478
|
}
|
|
479
479
|
};
|
|
480
480
|
let rendered = false;
|
|
481
|
+
process.stdout.write("\x1b[?25l"); // Hide cursor
|
|
481
482
|
render();
|
|
482
483
|
rendered = true;
|
|
483
484
|
const wasRaw = stdin.isRaw;
|
|
484
485
|
if (stdin.isTTY)
|
|
485
486
|
stdin.setRawMode(true);
|
|
487
|
+
const cleanup = () => {
|
|
488
|
+
stdin.removeListener("data", onData);
|
|
489
|
+
if (stdin.isTTY)
|
|
490
|
+
stdin.setRawMode(wasRaw ?? false);
|
|
491
|
+
process.stdout.write("\x1b[?25h"); // Show cursor
|
|
492
|
+
};
|
|
486
493
|
const onData = (data) => {
|
|
487
494
|
const key = data.toString();
|
|
488
495
|
if (key === "\x1b[A" || key === "k") {
|
|
489
|
-
// Up
|
|
490
496
|
cursor = (cursor - 1 + items.length) % items.length;
|
|
491
497
|
render();
|
|
492
498
|
}
|
|
493
499
|
else if (key === "\x1b[B" || key === "j") {
|
|
494
|
-
// Down
|
|
495
500
|
cursor = (cursor + 1) % items.length;
|
|
496
501
|
render();
|
|
497
502
|
}
|
|
498
503
|
else if (key === " ") {
|
|
499
|
-
// Toggle
|
|
500
504
|
items[cursor].checked = !items[cursor].checked;
|
|
501
505
|
render();
|
|
502
506
|
}
|
|
503
507
|
else if (key === "\r" || key === "\n") {
|
|
504
|
-
|
|
505
|
-
stdin.removeListener("data", onData);
|
|
506
|
-
if (stdin.isTTY)
|
|
507
|
-
stdin.setRawMode(wasRaw ?? false);
|
|
508
|
+
cleanup();
|
|
508
509
|
const selected = items.map((item, i) => (item.checked ? i : -1)).filter((i) => i >= 0);
|
|
509
510
|
resolve(selected);
|
|
510
511
|
}
|
|
511
512
|
else if (key === "\x1b" || key === "\x03") {
|
|
512
|
-
|
|
513
|
-
stdin.removeListener("data", onData);
|
|
514
|
-
if (stdin.isTTY)
|
|
515
|
-
stdin.setRawMode(wasRaw ?? false);
|
|
513
|
+
cleanup();
|
|
516
514
|
resolve([]);
|
|
517
515
|
}
|
|
518
516
|
};
|
|
@@ -1584,30 +1582,73 @@ async function interactive() {
|
|
|
1584
1582
|
console.log();
|
|
1585
1583
|
}
|
|
1586
1584
|
else {
|
|
1587
|
-
// Agent works without keys (e.g. OpenCode) —
|
|
1588
|
-
console.log(` ${c.bold}${agent.name}${c.reset} ${c.dim}—
|
|
1589
|
-
|
|
1590
|
-
|
|
1591
|
-
|
|
1585
|
+
// Agent works without keys (e.g. OpenCode) — choose backend
|
|
1586
|
+
console.log(` ${c.bold}${agent.name}${c.reset} ${c.dim}— choose your backend:${c.reset}\n`);
|
|
1587
|
+
console.log(` ${c.dim}1${c.reset} Ollama ${c.dim}Run models locally (free, requires download)${c.reset}`);
|
|
1588
|
+
console.log(` ${c.dim}2${c.reset} OpenRouter ${c.dim}Cloud API for 200+ models (requires API key)${c.reset}`);
|
|
1589
|
+
console.log();
|
|
1590
|
+
const backendChoice = await questionWithEsc(setupRl, ` ${c.cyan}Backend [1-2]:${c.reset} `);
|
|
1591
|
+
const pickedOpenRouter = backendChoice !== null && backendChoice.trim() === "2";
|
|
1592
|
+
if (pickedOpenRouter) {
|
|
1593
|
+
// OpenRouter setup
|
|
1594
|
+
console.log();
|
|
1595
|
+
const orKey = await questionWithEsc(setupRl, ` ${c.cyan}OPENROUTER_API_KEY:${c.reset} `);
|
|
1596
|
+
if (orKey?.trim()) {
|
|
1597
|
+
process.env.OPENROUTER_API_KEY = orKey.trim();
|
|
1598
|
+
try {
|
|
1599
|
+
const envPath = path.join(process.cwd(), ".env");
|
|
1600
|
+
let envContent = "";
|
|
1601
|
+
try {
|
|
1602
|
+
envContent = fs.readFileSync(envPath, "utf-8");
|
|
1603
|
+
}
|
|
1604
|
+
catch { }
|
|
1605
|
+
if (!envContent.includes("OPENROUTER_API_KEY")) {
|
|
1606
|
+
fs.appendFileSync(envPath, `\nOPENROUTER_API_KEY=${orKey.trim()}\n`);
|
|
1607
|
+
}
|
|
1608
|
+
console.log(` ${c.green}✓${c.reset} OpenRouter configured`);
|
|
1609
|
+
}
|
|
1610
|
+
catch {
|
|
1611
|
+
console.log(` ${c.green}✓${c.reset} OpenRouter key set for this session`);
|
|
1612
|
+
}
|
|
1613
|
+
currentModelId = "openrouter/auto";
|
|
1614
|
+
saveModelPreference(currentModelId);
|
|
1615
|
+
}
|
|
1616
|
+
else {
|
|
1617
|
+
console.log(` ${c.dim}No key provided — you can set OPENROUTER_API_KEY in .env later${c.reset}`);
|
|
1618
|
+
}
|
|
1619
|
+
}
|
|
1620
|
+
else {
|
|
1621
|
+
// Ollama setup
|
|
1622
|
+
console.log();
|
|
1623
|
+
const ok = await ensureOllamaSetup(setupRl, "ollama/deepseek-coder-v2");
|
|
1624
|
+
if (ok)
|
|
1625
|
+
usesOllama = true;
|
|
1626
|
+
}
|
|
1592
1627
|
console.log();
|
|
1593
1628
|
}
|
|
1594
1629
|
}
|
|
1595
1630
|
// ── Step 3: Set default model ────────────────────────────────
|
|
1596
|
-
|
|
1597
|
-
|
|
1598
|
-
|
|
1599
|
-
|
|
1600
|
-
|
|
1601
|
-
|
|
1631
|
+
if (currentModelId.startsWith("openrouter/")) {
|
|
1632
|
+
// Already set during OpenRouter setup
|
|
1633
|
+
console.log(` ${c.green}✓${c.reset} Default model: ${c.bold}${currentModelId}${c.reset} ${c.dim}(OpenRouter)${c.reset}`);
|
|
1634
|
+
}
|
|
1635
|
+
else {
|
|
1636
|
+
const activeProvider = Object.keys(PROVIDER_KEYS).find((p) => process.env[providerEnvKey(p)]);
|
|
1637
|
+
if (activeProvider) {
|
|
1638
|
+
currentProviderName = activeProvider;
|
|
1639
|
+
const defaultModel = getDefaultModelForProvider(activeProvider);
|
|
1640
|
+
if (defaultModel) {
|
|
1641
|
+
currentModelId = defaultModel;
|
|
1642
|
+
saveModelPreference(currentModelId);
|
|
1643
|
+
console.log(` ${c.green}✓${c.reset} Default model: ${c.bold}${currentModelId}${c.reset}`);
|
|
1644
|
+
}
|
|
1645
|
+
}
|
|
1646
|
+
else if (usesOllama) {
|
|
1647
|
+
currentModelId = "ollama/deepseek-coder-v2";
|
|
1602
1648
|
saveModelPreference(currentModelId);
|
|
1603
|
-
console.log(` ${c.green}✓${c.reset} Default model: ${c.bold}${currentModelId}${c.reset}`);
|
|
1649
|
+
console.log(` ${c.green}✓${c.reset} Default model: ${c.bold}${currentModelId}${c.reset} ${c.dim}(local)${c.reset}`);
|
|
1604
1650
|
}
|
|
1605
1651
|
}
|
|
1606
|
-
else if (usesOllama) {
|
|
1607
|
-
currentModelId = "ollama/deepseek-coder-v2";
|
|
1608
|
-
saveModelPreference(currentModelId);
|
|
1609
|
-
console.log(` ${c.green}✓${c.reset} Default model: ${c.bold}${currentModelId}${c.reset} ${c.dim}(local)${c.reset}`);
|
|
1610
|
-
}
|
|
1611
1652
|
console.log();
|
|
1612
1653
|
setupRl.close();
|
|
1613
1654
|
}
|
|
@@ -1639,12 +1680,12 @@ async function interactive() {
|
|
|
1639
1680
|
}
|
|
1640
1681
|
}
|
|
1641
1682
|
if (!currentModel) {
|
|
1642
|
-
if (currentModelId.startsWith("ollama/")) {
|
|
1643
|
-
//
|
|
1644
|
-
|
|
1645
|
-
console.log(`\n ${c.green}✓${c.reset}
|
|
1683
|
+
if (currentModelId.startsWith("ollama/") || currentModelId.startsWith("openrouter/")) {
|
|
1684
|
+
// Non-pi-ai model — redirect to swarm mode which uses OpenCode natively.
|
|
1685
|
+
const backend = currentModelId.startsWith("ollama/") ? "Ollama" : "OpenRouter";
|
|
1686
|
+
console.log(`\n ${c.green}✓${c.reset} ${backend} model selected: ${c.bold}${currentModelId}${c.reset}`);
|
|
1646
1687
|
console.log(`\n ${c.dim}This interactive REPL uses direct LLM API calls.${c.reset}`);
|
|
1647
|
-
console.log(` ${c.dim}To use
|
|
1688
|
+
console.log(` ${c.dim}To use ${backend} with OpenCode, run:${c.reset}\n`);
|
|
1648
1689
|
console.log(` ${c.bold}swarm --dir ./your-project "your task"${c.reset}\n`);
|
|
1649
1690
|
process.exit(0);
|
|
1650
1691
|
}
|
package/package.json
CHANGED