bridgerapi 1.5.0 → 1.6.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/dist/cli.js +185 -44
- package/package.json +1 -1
package/dist/cli.js
CHANGED
|
@@ -245,6 +245,11 @@ var BACKENDS = [
|
|
|
245
245
|
new DroidBackend()
|
|
246
246
|
];
|
|
247
247
|
function pickBackend(model2) {
|
|
248
|
+
const override = process.env.BRIDGERAPI_BACKEND?.toLowerCase();
|
|
249
|
+
if (override) {
|
|
250
|
+
const forced = BACKENDS.find((b) => b.name === override && b.available());
|
|
251
|
+
if (forced) return forced;
|
|
252
|
+
}
|
|
248
253
|
const m = model2.toLowerCase();
|
|
249
254
|
for (const b of BACKENDS) {
|
|
250
255
|
if (b.prefixes.some((p) => m.startsWith(p)) && b.available()) return b;
|
|
@@ -335,10 +340,10 @@ async function handleChat(req, res) {
|
|
|
335
340
|
const model2 = body.model ?? "claude-sonnet-4-6";
|
|
336
341
|
const streaming = Boolean(body.stream);
|
|
337
342
|
const prompt = messagesToPrompt(messages);
|
|
338
|
-
const
|
|
343
|
+
const backend2 = pickBackend(model2);
|
|
339
344
|
const id = `chatcmpl-${(0, import_crypto.randomUUID)().replace(/-/g, "").slice(0, 20)}`;
|
|
340
345
|
const ts = Math.floor(Date.now() / 1e3);
|
|
341
|
-
console.log(` ${
|
|
346
|
+
console.log(` ${backend2.name} model=${model2} stream=${streaming} turns=${messages.length}`);
|
|
342
347
|
if (streaming) {
|
|
343
348
|
cors(res, 200);
|
|
344
349
|
res.setHeader("Content-Type", "text/event-stream");
|
|
@@ -347,7 +352,7 @@ async function handleChat(req, res) {
|
|
|
347
352
|
res.flushHeaders();
|
|
348
353
|
res.write(chunk(id, ts, model2, { role: "assistant" }));
|
|
349
354
|
try {
|
|
350
|
-
for await (const raw of
|
|
355
|
+
for await (const raw of backend2.stream(prompt, model2)) {
|
|
351
356
|
res.write(chunk(id, ts, model2, { content: raw.toString("utf8") }));
|
|
352
357
|
}
|
|
353
358
|
} catch (err) {
|
|
@@ -358,7 +363,7 @@ async function handleChat(req, res) {
|
|
|
358
363
|
res.end();
|
|
359
364
|
} else {
|
|
360
365
|
try {
|
|
361
|
-
const [text, usage] = await
|
|
366
|
+
const [text, usage] = await backend2.runBlocking(prompt, model2);
|
|
362
367
|
sendJson(res, 200, completion(id, ts, model2, text, usage));
|
|
363
368
|
} catch (err) {
|
|
364
369
|
console.error(` error: ${err.message}`);
|
|
@@ -402,10 +407,13 @@ var LABEL = "com.bridgerapi.server";
|
|
|
402
407
|
function plistPath() {
|
|
403
408
|
return (0, import_path.join)(HOME2, "Library/LaunchAgents", `${LABEL}.plist`);
|
|
404
409
|
}
|
|
405
|
-
function writePlist(port2, scriptPath, nodePath) {
|
|
410
|
+
function writePlist(port2, scriptPath, nodePath, backend2) {
|
|
406
411
|
const logDir = (0, import_path.join)(HOME2, ".bridgerapi");
|
|
407
412
|
(0, import_fs2.mkdirSync)(logDir, { recursive: true });
|
|
408
413
|
(0, import_fs2.mkdirSync)((0, import_path.join)(HOME2, "Library/LaunchAgents"), { recursive: true });
|
|
414
|
+
const backendEntry = backend2 ? `
|
|
415
|
+
<key>BRIDGERAPI_BACKEND</key>
|
|
416
|
+
<string>${backend2}</string>` : "";
|
|
409
417
|
const plist = `<?xml version="1.0" encoding="UTF-8"?>
|
|
410
418
|
<!DOCTYPE plist PUBLIC "-//Apple//DTD PLIST 1.0//EN"
|
|
411
419
|
"http://www.apple.com/DTDs/PropertyList-1.0.dtd">
|
|
@@ -430,7 +438,7 @@ function writePlist(port2, scriptPath, nodePath) {
|
|
|
430
438
|
<key>HOME</key>
|
|
431
439
|
<string>${HOME2}</string>
|
|
432
440
|
<key>CUSTOM_OKBRIDGER_API_KEY</key>
|
|
433
|
-
<string>local</string
|
|
441
|
+
<string>local</string>${backendEntry}
|
|
434
442
|
</dict>
|
|
435
443
|
|
|
436
444
|
<key>StandardOutPath</key>
|
|
@@ -451,10 +459,12 @@ function unitPath() {
|
|
|
451
459
|
const configHome = process.env.XDG_CONFIG_HOME ?? (0, import_path.join)(HOME2, ".config");
|
|
452
460
|
return (0, import_path.join)(configHome, "systemd/user/bridgerapi.service");
|
|
453
461
|
}
|
|
454
|
-
function writeUnit(port2, scriptPath, nodePath) {
|
|
462
|
+
function writeUnit(port2, scriptPath, nodePath, backend2) {
|
|
455
463
|
const logDir = (0, import_path.join)(HOME2, ".bridgerapi");
|
|
456
464
|
(0, import_fs2.mkdirSync)(logDir, { recursive: true });
|
|
457
465
|
(0, import_fs2.mkdirSync)((0, import_path.join)(HOME2, ".config/systemd/user"), { recursive: true });
|
|
466
|
+
const backendLine = backend2 ? `
|
|
467
|
+
Environment=BRIDGERAPI_BACKEND=${backend2}` : "";
|
|
458
468
|
const unit = `[Unit]
|
|
459
469
|
Description=bridgerapi \u2014 OpenAI-compatible bridge for AI CLIs
|
|
460
470
|
After=network.target
|
|
@@ -465,7 +475,7 @@ ExecStart=${nodePath} ${scriptPath} start
|
|
|
465
475
|
Environment=BRIDGERAPI_PORT=${port2}
|
|
466
476
|
Environment=HOME=${HOME2}
|
|
467
477
|
Environment=CUSTOM_OKBRIDGER_API_KEY=local
|
|
468
|
-
Environment=PATH=${HOME2}/.local/bin:/usr/local/bin:/usr/bin:/bin
|
|
478
|
+
Environment=PATH=${HOME2}/.local/bin:/usr/local/bin:/usr/bin:/bin${backendLine}
|
|
469
479
|
Restart=always
|
|
470
480
|
StandardOutput=append:${logDir}/server.log
|
|
471
481
|
StandardError=append:${logDir}/server.log
|
|
@@ -475,7 +485,7 @@ WantedBy=default.target
|
|
|
475
485
|
`;
|
|
476
486
|
(0, import_fs2.writeFileSync)(unitPath(), unit);
|
|
477
487
|
}
|
|
478
|
-
function installService(port2) {
|
|
488
|
+
function installService(port2, backend2) {
|
|
479
489
|
const scriptPath = process.argv[1];
|
|
480
490
|
const nodePath = process.execPath;
|
|
481
491
|
const os = (0, import_os2.platform)();
|
|
@@ -484,11 +494,11 @@ function installService(port2) {
|
|
|
484
494
|
(0, import_child_process2.execSync)(`launchctl unload "${plistPath()}" 2>/dev/null`, { stdio: "ignore" });
|
|
485
495
|
} catch {
|
|
486
496
|
}
|
|
487
|
-
writePlist(port2, scriptPath, nodePath);
|
|
497
|
+
writePlist(port2, scriptPath, nodePath, backend2);
|
|
488
498
|
(0, import_child_process2.execSync)(`launchctl load -w "${plistPath()}"`);
|
|
489
499
|
console.log(`\u2713 LaunchAgent installed \u2192 ${plistPath()}`);
|
|
490
500
|
} else if (os === "linux") {
|
|
491
|
-
writeUnit(port2, scriptPath, nodePath);
|
|
501
|
+
writeUnit(port2, scriptPath, nodePath, backend2);
|
|
492
502
|
try {
|
|
493
503
|
(0, import_child_process2.execSync)("systemctl --user daemon-reload");
|
|
494
504
|
} catch {
|
|
@@ -547,13 +557,33 @@ function serviceStatus() {
|
|
|
547
557
|
return { running: false };
|
|
548
558
|
}
|
|
549
559
|
|
|
550
|
-
// src/
|
|
560
|
+
// src/config.ts
|
|
551
561
|
var import_fs3 = require("fs");
|
|
552
562
|
var import_os3 = require("os");
|
|
553
563
|
var import_path2 = require("path");
|
|
564
|
+
var CONFIG_DIR = (0, import_path2.join)((0, import_os3.homedir)(), ".bridgerapi");
|
|
565
|
+
var CONFIG_FILE = (0, import_path2.join)(CONFIG_DIR, "config.json");
|
|
566
|
+
function loadConfig() {
|
|
567
|
+
try {
|
|
568
|
+
if ((0, import_fs3.existsSync)(CONFIG_FILE)) {
|
|
569
|
+
return JSON.parse((0, import_fs3.readFileSync)(CONFIG_FILE, "utf8"));
|
|
570
|
+
}
|
|
571
|
+
} catch {
|
|
572
|
+
}
|
|
573
|
+
return {};
|
|
574
|
+
}
|
|
575
|
+
function saveConfig(cfg) {
|
|
576
|
+
(0, import_fs3.mkdirSync)(CONFIG_DIR, { recursive: true });
|
|
577
|
+
(0, import_fs3.writeFileSync)(CONFIG_FILE, JSON.stringify(cfg, null, 2) + "\n");
|
|
578
|
+
}
|
|
579
|
+
|
|
580
|
+
// src/cli.ts
|
|
581
|
+
var import_fs4 = require("fs");
|
|
582
|
+
var import_os4 = require("os");
|
|
583
|
+
var import_path3 = require("path");
|
|
554
584
|
var import_readline = require("readline");
|
|
555
|
-
var
|
|
556
|
-
var LOG_DIR = (0,
|
|
585
|
+
var DEFAULT_PORT = parseInt(process.env.BRIDGERAPI_PORT ?? "8082");
|
|
586
|
+
var LOG_DIR = (0, import_path3.join)((0, import_os4.homedir)(), ".bridgerapi");
|
|
557
587
|
var INSTALL_HINTS = {
|
|
558
588
|
claude: "claude login (Claude Code \u2014 claude.ai/download)",
|
|
559
589
|
gemini: "gemini auth (Gemini CLI \u2014 npm i -g @google/gemini-cli)",
|
|
@@ -576,7 +606,6 @@ async function cmdSetup() {
|
|
|
576
606
|
console.log(" \u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500");
|
|
577
607
|
console.log();
|
|
578
608
|
const available = BACKENDS.filter((b) => b.available());
|
|
579
|
-
const missing = BACKENDS.filter((b) => !b.available());
|
|
580
609
|
console.log(" Backends detected:\n");
|
|
581
610
|
for (const b of BACKENDS) {
|
|
582
611
|
const ok = b.available();
|
|
@@ -588,8 +617,30 @@ async function cmdSetup() {
|
|
|
588
617
|
console.log(" No backends found. Install at least one CLI above, then re-run: bridgerapi");
|
|
589
618
|
process.exit(1);
|
|
590
619
|
}
|
|
591
|
-
const
|
|
592
|
-
|
|
620
|
+
const cfg = loadConfig();
|
|
621
|
+
let chosenBackend;
|
|
622
|
+
if (available.length === 1) {
|
|
623
|
+
chosenBackend = available[0].name;
|
|
624
|
+
} else {
|
|
625
|
+
const names = available.map((b) => b.name);
|
|
626
|
+
const currentDefault = cfg.backend && names.includes(cfg.backend) ? cfg.backend : names[0];
|
|
627
|
+
const defaultIdx = names.indexOf(currentDefault);
|
|
628
|
+
console.log(" Which backend do you want to use as default?\n");
|
|
629
|
+
names.forEach((name, i) => {
|
|
630
|
+
const marker = i === defaultIdx ? " \u2190 default" : "";
|
|
631
|
+
console.log(` ${i + 1} ${name}${marker}`);
|
|
632
|
+
});
|
|
633
|
+
console.log();
|
|
634
|
+
const backendAnswer = await ask(` Choose [${defaultIdx + 1}]: `);
|
|
635
|
+
const parsed = parseInt(backendAnswer);
|
|
636
|
+
const backendIdx = backendAnswer && !isNaN(parsed) ? parsed - 1 : defaultIdx;
|
|
637
|
+
chosenBackend = names[Math.max(0, Math.min(backendIdx, names.length - 1))];
|
|
638
|
+
console.log();
|
|
639
|
+
}
|
|
640
|
+
const defaultPort = cfg.port ?? DEFAULT_PORT;
|
|
641
|
+
const portAnswer = await ask(` Port [${defaultPort}]: `);
|
|
642
|
+
const port2 = portAnswer ? parseInt(portAnswer) || defaultPort : defaultPort;
|
|
643
|
+
saveConfig({ backend: chosenBackend, port: port2 });
|
|
593
644
|
console.log();
|
|
594
645
|
console.log(" How do you want to run bridgerapi?");
|
|
595
646
|
console.log(" 1 Foreground (stops when terminal closes)");
|
|
@@ -598,13 +649,16 @@ async function cmdSetup() {
|
|
|
598
649
|
const choice = await ask(" Choose [1/2]: ");
|
|
599
650
|
console.log();
|
|
600
651
|
if (choice === "2") {
|
|
601
|
-
cmdInstall(port2);
|
|
652
|
+
cmdInstall(port2, chosenBackend);
|
|
602
653
|
} else {
|
|
603
|
-
cmdStart(port2);
|
|
654
|
+
cmdStart(port2, chosenBackend);
|
|
604
655
|
}
|
|
605
656
|
}
|
|
606
|
-
function cmdStart(port2) {
|
|
607
|
-
(0,
|
|
657
|
+
function cmdStart(port2, backend2) {
|
|
658
|
+
(0, import_fs4.mkdirSync)(LOG_DIR, { recursive: true });
|
|
659
|
+
const cfg = loadConfig();
|
|
660
|
+
const activeBackend = backend2 ?? cfg.backend;
|
|
661
|
+
if (activeBackend) process.env.BRIDGERAPI_BACKEND = activeBackend;
|
|
608
662
|
const available = BACKENDS.filter((b) => b.available());
|
|
609
663
|
if (available.length === 0) {
|
|
610
664
|
console.error(" No CLI backends found. Run: bridgerapi to see setup instructions.");
|
|
@@ -617,7 +671,8 @@ function cmdStart(port2) {
|
|
|
617
671
|
console.log(` Base URL : http://127.0.0.1:${port2}/v1`);
|
|
618
672
|
console.log(` API Key : local`);
|
|
619
673
|
console.log();
|
|
620
|
-
|
|
674
|
+
const backendLabel = activeBackend ? `${activeBackend} (all requests routed here)` : available.map((b) => b.name).join(", ") + " (auto-routed by model prefix)";
|
|
675
|
+
console.log(` Backend : ${backendLabel}`);
|
|
621
676
|
console.log(` Logs : ${LOG_DIR}/server.log`);
|
|
622
677
|
console.log();
|
|
623
678
|
console.log(" Ctrl+C to stop.");
|
|
@@ -631,9 +686,11 @@ function cmdStart(port2) {
|
|
|
631
686
|
process.exit(1);
|
|
632
687
|
});
|
|
633
688
|
}
|
|
634
|
-
function cmdInstall(port2) {
|
|
689
|
+
function cmdInstall(port2, backend2) {
|
|
690
|
+
const cfg = loadConfig();
|
|
691
|
+
const activeBackend = backend2 ?? cfg.backend;
|
|
635
692
|
try {
|
|
636
|
-
installService(port2);
|
|
693
|
+
installService(port2, activeBackend);
|
|
637
694
|
console.log();
|
|
638
695
|
console.log(" Waiting for server to start\u2026");
|
|
639
696
|
let attempts = 0;
|
|
@@ -649,6 +706,7 @@ function cmdInstall(port2) {
|
|
|
649
706
|
console.log();
|
|
650
707
|
console.log(` Base URL : http://127.0.0.1:${port2}/v1`);
|
|
651
708
|
console.log(` API Key : local`);
|
|
709
|
+
if (activeBackend) console.log(` Backend : ${activeBackend}`);
|
|
652
710
|
console.log();
|
|
653
711
|
console.log(` Logs : tail -f ${LOG_DIR}/server.log`);
|
|
654
712
|
console.log(` Stop : bridgerapi uninstall`);
|
|
@@ -679,11 +737,13 @@ function cmdUninstall() {
|
|
|
679
737
|
}
|
|
680
738
|
}
|
|
681
739
|
function cmdStatus(port2) {
|
|
740
|
+
const cfg = loadConfig();
|
|
682
741
|
const { running, pid } = serviceStatus();
|
|
683
742
|
if (running) {
|
|
684
743
|
console.log(` bridgerapi is running${pid ? ` (pid ${pid})` : ""}`);
|
|
685
744
|
console.log(` Base URL : http://127.0.0.1:${port2}/v1`);
|
|
686
745
|
console.log(` API Key : local`);
|
|
746
|
+
if (cfg.backend) console.log(` Backend : ${cfg.backend}`);
|
|
687
747
|
} else {
|
|
688
748
|
console.log(" bridgerapi is not running.");
|
|
689
749
|
console.log(" Run: bridgerapi \u2192 setup wizard");
|
|
@@ -691,16 +751,76 @@ function cmdStatus(port2) {
|
|
|
691
751
|
console.log(" Run: bridgerapi install \u2192 install background service");
|
|
692
752
|
}
|
|
693
753
|
}
|
|
694
|
-
|
|
754
|
+
function cmdConfig(args) {
|
|
755
|
+
const cfg = loadConfig();
|
|
756
|
+
if (args[0] === "set") {
|
|
757
|
+
for (const pair of args.slice(1)) {
|
|
758
|
+
const eqIdx = pair.indexOf("=");
|
|
759
|
+
if (eqIdx === -1) {
|
|
760
|
+
console.error(` Invalid format: ${pair} (use key=value)`);
|
|
761
|
+
process.exit(1);
|
|
762
|
+
}
|
|
763
|
+
const key = pair.slice(0, eqIdx);
|
|
764
|
+
const val = pair.slice(eqIdx + 1);
|
|
765
|
+
if (key === "backend") {
|
|
766
|
+
const known = BACKENDS.find((b) => b.name === val);
|
|
767
|
+
if (!known) {
|
|
768
|
+
console.error(` Unknown backend: ${val}`);
|
|
769
|
+
console.error(` Valid options: ${BACKENDS.map((b) => b.name).join(", ")}`);
|
|
770
|
+
process.exit(1);
|
|
771
|
+
}
|
|
772
|
+
cfg.backend = val;
|
|
773
|
+
console.log(` backend \u2192 ${val}`);
|
|
774
|
+
} else if (key === "port") {
|
|
775
|
+
const p = parseInt(val);
|
|
776
|
+
if (isNaN(p) || p < 1 || p > 65535) {
|
|
777
|
+
console.error(" Invalid port number");
|
|
778
|
+
process.exit(1);
|
|
779
|
+
}
|
|
780
|
+
cfg.port = p;
|
|
781
|
+
console.log(` port \u2192 ${p}`);
|
|
782
|
+
} else {
|
|
783
|
+
console.error(` Unknown key: ${key}`);
|
|
784
|
+
console.error(` Valid keys: backend, port`);
|
|
785
|
+
process.exit(1);
|
|
786
|
+
}
|
|
787
|
+
}
|
|
788
|
+
saveConfig(cfg);
|
|
789
|
+
console.log(" Saved.");
|
|
790
|
+
return;
|
|
791
|
+
}
|
|
792
|
+
if (args[0] === "reset") {
|
|
793
|
+
saveConfig({});
|
|
794
|
+
console.log(" Config reset to defaults.");
|
|
795
|
+
return;
|
|
796
|
+
}
|
|
797
|
+
console.log();
|
|
798
|
+
console.log(" bridgerapi config");
|
|
799
|
+
console.log(" \u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500");
|
|
800
|
+
console.log(` backend : ${cfg.backend ?? "(auto \u2014 routed by model prefix)"}`);
|
|
801
|
+
console.log(` port : ${cfg.port ?? `${DEFAULT_PORT} (default)`}`);
|
|
802
|
+
console.log(` file : ${(0, import_path3.join)((0, import_os4.homedir)(), ".bridgerapi/config.json")}`);
|
|
803
|
+
console.log();
|
|
804
|
+
console.log(" To change:");
|
|
805
|
+
console.log(` bridgerapi config set backend=claude`);
|
|
806
|
+
console.log(` bridgerapi config set port=9000`);
|
|
807
|
+
console.log(` bridgerapi config reset`);
|
|
808
|
+
console.log();
|
|
809
|
+
}
|
|
810
|
+
async function cmdChat(model2, backendFlag) {
|
|
811
|
+
const cfg = loadConfig();
|
|
812
|
+
const activeBackend = backendFlag ?? (model2 && BACKENDS.find((b) => b.name === model2?.toLowerCase())?.name) ?? cfg.backend;
|
|
813
|
+
if (activeBackend) process.env.BRIDGERAPI_BACKEND = activeBackend;
|
|
814
|
+
const resolvedModel = model2 && BACKENDS.find((b) => b.name === model2.toLowerCase()) ? void 0 : model2;
|
|
695
815
|
const available = BACKENDS.filter((b) => b.available());
|
|
696
816
|
if (available.length === 0) {
|
|
697
817
|
console.error(" No backends found. Run: bridgerapi to see setup instructions.");
|
|
698
818
|
process.exit(1);
|
|
699
819
|
}
|
|
700
|
-
const
|
|
701
|
-
const
|
|
820
|
+
const fallbackModel = `${activeBackend ?? available[0].name}-default`;
|
|
821
|
+
const backend2 = pickBackend(resolvedModel ?? fallbackModel);
|
|
702
822
|
console.log();
|
|
703
|
-
console.log(` bridgerapi chat \u2014 ${
|
|
823
|
+
console.log(` bridgerapi chat \u2014 ${backend2.name}`);
|
|
704
824
|
console.log(" \u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500");
|
|
705
825
|
console.log(" Type a message and press Enter. Ctrl+C to exit.");
|
|
706
826
|
console.log();
|
|
@@ -721,8 +841,8 @@ async function cmdChat(model2) {
|
|
|
721
841
|
process.stdout.write("\n");
|
|
722
842
|
let reply = "";
|
|
723
843
|
try {
|
|
724
|
-
process.stdout.write(`${
|
|
725
|
-
for await (const chunk2 of
|
|
844
|
+
process.stdout.write(`${backend2.name}: `);
|
|
845
|
+
for await (const chunk2 of backend2.stream(messagesToPrompt(history), resolvedModel ?? fallbackModel)) {
|
|
726
846
|
const piece = chunk2.toString("utf8");
|
|
727
847
|
process.stdout.write(piece);
|
|
728
848
|
reply += piece;
|
|
@@ -743,39 +863,57 @@ function showHelp() {
|
|
|
743
863
|
bridgerapi \u2014 OpenAI-compatible API bridge for AI CLI tools
|
|
744
864
|
|
|
745
865
|
Usage:
|
|
746
|
-
bridgerapi
|
|
747
|
-
bridgerapi chat [--model m]
|
|
748
|
-
bridgerapi
|
|
749
|
-
bridgerapi
|
|
750
|
-
bridgerapi
|
|
751
|
-
bridgerapi
|
|
866
|
+
bridgerapi Interactive setup wizard
|
|
867
|
+
bridgerapi chat [--model m] Chat in the terminal (routes by model prefix)
|
|
868
|
+
bridgerapi chat --backend <name> Chat using a specific backend
|
|
869
|
+
bridgerapi start [--port n] Start API server in the foreground
|
|
870
|
+
bridgerapi start --backend <name> Start forcing a specific backend for all requests
|
|
871
|
+
bridgerapi install [--port n] Install as a background service
|
|
872
|
+
bridgerapi uninstall Remove background service
|
|
873
|
+
bridgerapi status Show service status
|
|
874
|
+
bridgerapi config Show saved configuration
|
|
875
|
+
bridgerapi config set backend=<b> Set default backend (claude|gemini|codex|copilot|droid)
|
|
876
|
+
bridgerapi config set port=<n> Set default port
|
|
877
|
+
bridgerapi config reset Clear saved configuration
|
|
878
|
+
|
|
879
|
+
Backends: claude, gemini, codex, copilot, droid
|
|
752
880
|
`.trim());
|
|
753
881
|
}
|
|
754
882
|
function parseArgs() {
|
|
883
|
+
const cfg = loadConfig();
|
|
755
884
|
const args = process.argv.slice(2);
|
|
756
885
|
const cmd2 = args[0] ?? "";
|
|
757
|
-
let port2 =
|
|
886
|
+
let port2 = cfg.port ?? DEFAULT_PORT;
|
|
758
887
|
let model2;
|
|
888
|
+
let backend2;
|
|
889
|
+
const rest2 = [];
|
|
759
890
|
for (let i = 1; i < args.length; i++) {
|
|
760
|
-
if ((args[i] === "--port" || args[i] === "-p") && args[i + 1])
|
|
761
|
-
|
|
891
|
+
if ((args[i] === "--port" || args[i] === "-p") && args[i + 1]) {
|
|
892
|
+
port2 = parseInt(args[++i]);
|
|
893
|
+
} else if ((args[i] === "--model" || args[i] === "-m") && args[i + 1]) {
|
|
894
|
+
model2 = args[++i];
|
|
895
|
+
} else if ((args[i] === "--backend" || args[i] === "-b") && args[i + 1]) {
|
|
896
|
+
backend2 = args[++i];
|
|
897
|
+
} else {
|
|
898
|
+
rest2.push(args[i]);
|
|
899
|
+
}
|
|
762
900
|
}
|
|
763
|
-
return { cmd: cmd2, port: port2, model: model2 };
|
|
901
|
+
return { cmd: cmd2, port: port2, model: model2, backend: backend2, rest: rest2 };
|
|
764
902
|
}
|
|
765
|
-
var { cmd, port, model } = parseArgs();
|
|
903
|
+
var { cmd, port, model, backend, rest } = parseArgs();
|
|
766
904
|
switch (cmd) {
|
|
767
905
|
case "":
|
|
768
906
|
case "setup":
|
|
769
907
|
cmdSetup();
|
|
770
908
|
break;
|
|
771
909
|
case "chat":
|
|
772
|
-
cmdChat(model);
|
|
910
|
+
cmdChat(model, backend);
|
|
773
911
|
break;
|
|
774
912
|
case "start":
|
|
775
|
-
cmdStart(port);
|
|
913
|
+
cmdStart(port, backend);
|
|
776
914
|
break;
|
|
777
915
|
case "install":
|
|
778
|
-
cmdInstall(port);
|
|
916
|
+
cmdInstall(port, backend);
|
|
779
917
|
break;
|
|
780
918
|
case "uninstall":
|
|
781
919
|
cmdUninstall();
|
|
@@ -783,6 +921,9 @@ switch (cmd) {
|
|
|
783
921
|
case "status":
|
|
784
922
|
cmdStatus(port);
|
|
785
923
|
break;
|
|
924
|
+
case "config":
|
|
925
|
+
cmdConfig(rest);
|
|
926
|
+
break;
|
|
786
927
|
case "help":
|
|
787
928
|
case "--help":
|
|
788
929
|
case "-h":
|