swiftroutercli 1.0.0 ā 1.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/assets/logo.png +0 -0
- package/dist/config.js +17 -7
- package/dist/constants.js +11 -0
- package/dist/index.js +76 -16
- package/package.json +4 -1
- package/src/config.ts +22 -8
- package/src/constants.ts +14 -0
- package/src/index.ts +78 -16
package/assets/logo.png
ADDED
|
Binary file
|
package/dist/config.js
CHANGED
|
@@ -1,18 +1,28 @@
|
|
|
1
1
|
import fs from "fs";
|
|
2
2
|
import path from "path";
|
|
3
|
-
import
|
|
4
|
-
const CONFIG_FILE = path.join(os.homedir(), ".swiftrouter-cli", "config.json");
|
|
3
|
+
import { CONFIG_FILE, ENV_API_KEY, ENV_BASE_URL } from "./constants.js";
|
|
5
4
|
export function loadConfig() {
|
|
5
|
+
// 1. Check for Environment Variables overriding everything else
|
|
6
|
+
const envApiKey = process.env[ENV_API_KEY];
|
|
7
|
+
const envBaseUrl = process.env[ENV_BASE_URL];
|
|
8
|
+
let fileConfig = null;
|
|
9
|
+
// 2. Load from file if exists
|
|
6
10
|
try {
|
|
7
|
-
if (
|
|
8
|
-
|
|
11
|
+
if (fs.existsSync(CONFIG_FILE)) {
|
|
12
|
+
const data = fs.readFileSync(CONFIG_FILE, "utf-8");
|
|
13
|
+
fileConfig = JSON.parse(data);
|
|
9
14
|
}
|
|
10
|
-
const data = fs.readFileSync(CONFIG_FILE, "utf-8");
|
|
11
|
-
return JSON.parse(data);
|
|
12
15
|
}
|
|
13
16
|
catch (error) {
|
|
14
|
-
|
|
17
|
+
// ignore parse errors and fallback
|
|
15
18
|
}
|
|
19
|
+
// 3. Merge Env Vars with File Config (Env wins)
|
|
20
|
+
const finalApiKey = envApiKey || fileConfig?.apiKey;
|
|
21
|
+
const finalBaseUrl = envBaseUrl || fileConfig?.baseUrl;
|
|
22
|
+
if (finalApiKey && finalBaseUrl) {
|
|
23
|
+
return { apiKey: finalApiKey, baseUrl: finalBaseUrl };
|
|
24
|
+
}
|
|
25
|
+
return null;
|
|
16
26
|
}
|
|
17
27
|
export function saveConfig(config) {
|
|
18
28
|
const dir = path.dirname(CONFIG_FILE);
|
|
@@ -0,0 +1,11 @@
|
|
|
1
|
+
import os from "os";
|
|
2
|
+
import path from "path";
|
|
3
|
+
// Application Defaults
|
|
4
|
+
export const DEFAULT_BASE_URL = "http://localhost:3000";
|
|
5
|
+
export const DEFAULT_MODEL = "gpt-4o-mini";
|
|
6
|
+
// System Paths
|
|
7
|
+
export const CONFIG_DIR = path.join(os.homedir(), ".swiftrouter-cli");
|
|
8
|
+
export const CONFIG_FILE = path.join(CONFIG_DIR, "config.json");
|
|
9
|
+
// Environment Variable Keys
|
|
10
|
+
export const ENV_API_KEY = "SWIFTROUTER_API_KEY";
|
|
11
|
+
export const ENV_BASE_URL = "SWIFTROUTER_BASE_URL";
|
package/dist/index.js
CHANGED
|
@@ -1,36 +1,54 @@
|
|
|
1
1
|
#!/usr/bin/env node
|
|
2
2
|
import { Command } from "commander";
|
|
3
3
|
import * as readline from "readline/promises";
|
|
4
|
+
import chalk from "chalk";
|
|
5
|
+
import ora from "ora";
|
|
4
6
|
import { loadConfig, saveConfig } from "./config.js";
|
|
5
7
|
import { fetchModels } from "./api/client.js";
|
|
6
8
|
import { startChat } from "./ui/Chat.js";
|
|
9
|
+
import { DEFAULT_BASE_URL, DEFAULT_MODEL, CONFIG_FILE } from "./constants.js";
|
|
10
|
+
import terminalImage from "terminal-image";
|
|
11
|
+
import { fileURLToPath } from "url";
|
|
12
|
+
import path from "path";
|
|
13
|
+
import fs from "fs";
|
|
14
|
+
const __filename = fileURLToPath(import.meta.url);
|
|
15
|
+
const __dirname = path.dirname(__filename);
|
|
7
16
|
const program = new Command();
|
|
8
17
|
async function ensureConfig() {
|
|
9
18
|
const existingConfig = loadConfig();
|
|
10
19
|
if (existingConfig && existingConfig.apiKey && existingConfig.baseUrl) {
|
|
11
20
|
return existingConfig;
|
|
12
21
|
}
|
|
13
|
-
|
|
14
|
-
|
|
22
|
+
try {
|
|
23
|
+
const logoPath = path.join(__dirname, "..", "assets", "logo.png");
|
|
24
|
+
if (fs.existsSync(logoPath)) {
|
|
25
|
+
console.log(await terminalImage.file(logoPath, { height: "25%" }));
|
|
26
|
+
}
|
|
27
|
+
}
|
|
28
|
+
catch (e) {
|
|
29
|
+
// Ignore if logo cannot be rendered
|
|
30
|
+
}
|
|
31
|
+
console.log(chalk.cyan.bold("\nš Welcome to SwiftRouterCLI!"));
|
|
32
|
+
console.log(chalk.gray("It looks like this is your first time. Let's get you set up.\n"));
|
|
15
33
|
const rl = readline.createInterface({
|
|
16
34
|
input: process.stdin,
|
|
17
35
|
output: process.stdout,
|
|
18
36
|
});
|
|
19
|
-
const apiKey = await rl.question("Please enter your SwiftRouter API Key: ");
|
|
20
|
-
const baseUrlInput = await rl.question(
|
|
37
|
+
const apiKey = await rl.question(chalk.bold("Please enter your SwiftRouter API Key: "));
|
|
38
|
+
const baseUrlInput = await rl.question(chalk.bold(`Please enter your SwiftRouter Base URL (default: ${DEFAULT_BASE_URL}): `));
|
|
21
39
|
rl.close();
|
|
22
40
|
const config = {
|
|
23
41
|
apiKey: apiKey.trim(),
|
|
24
|
-
baseUrl: baseUrlInput.trim() ||
|
|
42
|
+
baseUrl: baseUrlInput.trim() || DEFAULT_BASE_URL,
|
|
25
43
|
};
|
|
26
44
|
saveConfig(config);
|
|
27
|
-
console.log("\nā
Configuration saved securely! Starting your session...\n");
|
|
45
|
+
console.log(chalk.green("\nā
Configuration saved securely! Starting your session...\n"));
|
|
28
46
|
return config;
|
|
29
47
|
}
|
|
30
48
|
program
|
|
31
49
|
.name("swiftrouter")
|
|
32
50
|
.description("CLI for SwiftRouter AI Gateway")
|
|
33
|
-
.version("1.0.
|
|
51
|
+
.version("1.0.1");
|
|
34
52
|
program
|
|
35
53
|
.command("config")
|
|
36
54
|
.description("Manually configure the CLI with your SwiftRouter API Key and Base URL")
|
|
@@ -43,41 +61,83 @@ program
|
|
|
43
61
|
if (options.setBaseUrl)
|
|
44
62
|
config.baseUrl = options.setBaseUrl;
|
|
45
63
|
if (!config.apiKey || !config.baseUrl) {
|
|
46
|
-
console.error("Please provide both an API Key and a Base URL.");
|
|
47
|
-
console.log("Usage: swiftrouter config --set-api-key <KEY> --set-base-url <URL>");
|
|
64
|
+
console.error(chalk.red("Please provide both an API Key and a Base URL."));
|
|
65
|
+
console.log(chalk.gray("Usage: swiftrouter config --set-api-key <KEY> --set-base-url <URL>"));
|
|
48
66
|
process.exit(1);
|
|
49
67
|
}
|
|
50
68
|
saveConfig(config);
|
|
51
|
-
console.log("ā
Configuration saved successfully!");
|
|
69
|
+
console.log(chalk.green("ā
Configuration saved successfully!"));
|
|
52
70
|
});
|
|
53
71
|
program
|
|
54
72
|
.command("models")
|
|
55
73
|
.description("List available models from SwiftRouter")
|
|
56
74
|
.action(async () => {
|
|
57
75
|
const config = await ensureConfig();
|
|
76
|
+
const spinner = ora("Fetching models from SwiftRouter...").start();
|
|
58
77
|
try {
|
|
59
|
-
console.log("Fetching models...");
|
|
60
78
|
const models = await fetchModels(config);
|
|
61
|
-
|
|
62
|
-
|
|
79
|
+
spinner.succeed(`Found ${models.length} models!`);
|
|
80
|
+
console.log(chalk.dim("\nAvailable Models:"));
|
|
81
|
+
models.forEach((m) => console.log(chalk.cyan(` - ${m.id}`)));
|
|
63
82
|
}
|
|
64
83
|
catch (e) {
|
|
65
|
-
|
|
84
|
+
spinner.fail("Failed to fetch models.");
|
|
85
|
+
if (e.message.includes("fetch failed") || e.message.includes("ECONNREFUSED")) {
|
|
86
|
+
console.error(chalk.red.bold(`\nā Error: Cannot connect to SwiftRouter backend at ${config.baseUrl}`));
|
|
87
|
+
console.error(chalk.dim("Please ensure your SwiftRouter server is currently running."));
|
|
88
|
+
}
|
|
89
|
+
else {
|
|
90
|
+
console.error(chalk.red(e.message));
|
|
91
|
+
}
|
|
66
92
|
}
|
|
67
93
|
});
|
|
68
94
|
program
|
|
69
95
|
.command("chat")
|
|
70
96
|
.description("Start an interactive chat session")
|
|
71
97
|
.argument("[prompt]", "Initial prompt to start the chat")
|
|
72
|
-
.option("-m, --model <model>", "Model to use",
|
|
98
|
+
.option("-m, --model <model>", "Model to use", DEFAULT_MODEL)
|
|
73
99
|
.action(async (prompt, options) => {
|
|
74
100
|
const config = await ensureConfig();
|
|
75
101
|
if (!prompt) {
|
|
76
|
-
console.log("Starting empty chat session...");
|
|
77
102
|
startChat(config, options.model, "");
|
|
78
103
|
}
|
|
79
104
|
else {
|
|
80
105
|
startChat(config, options.model, prompt);
|
|
81
106
|
}
|
|
82
107
|
});
|
|
108
|
+
program
|
|
109
|
+
.command("status")
|
|
110
|
+
.description("Check the current configuration and connection status")
|
|
111
|
+
.action(async () => {
|
|
112
|
+
const config = loadConfig();
|
|
113
|
+
if (!config || !config.apiKey || !config.baseUrl) {
|
|
114
|
+
console.log(chalk.yellow("ā ļø SwiftRouterCLI is not authenticated."));
|
|
115
|
+
console.log(`Run ${chalk.cyan("swiftrouter config")} or any command to setup.`);
|
|
116
|
+
return;
|
|
117
|
+
}
|
|
118
|
+
console.log(chalk.bold("SwiftRouterCLI Status:"));
|
|
119
|
+
console.log(chalk.green("ā
Authenticated"));
|
|
120
|
+
console.log(`${chalk.gray("Base URL:")} ${config.baseUrl}`);
|
|
121
|
+
console.log(`${chalk.gray("API Key:")} sk-...${config.apiKey.slice(-4)}`);
|
|
122
|
+
const spinner = ora("\nPinging SwiftRouter Server...").start();
|
|
123
|
+
try {
|
|
124
|
+
const models = await fetchModels(config);
|
|
125
|
+
spinner.succeed(chalk.green(`Connected! Found ${models.length} active models.`));
|
|
126
|
+
}
|
|
127
|
+
catch (e) {
|
|
128
|
+
spinner.fail(chalk.red("Failed to reach server. Are you sure it's running?"));
|
|
129
|
+
}
|
|
130
|
+
});
|
|
131
|
+
program
|
|
132
|
+
.command("logout")
|
|
133
|
+
.description("Clear your local SwiftRouter configuration securely")
|
|
134
|
+
.action(() => {
|
|
135
|
+
if (fs.existsSync(CONFIG_FILE)) {
|
|
136
|
+
fs.unlinkSync(CONFIG_FILE);
|
|
137
|
+
console.log(chalk.green("ā
Successfully logged out. Configuration deleted."));
|
|
138
|
+
}
|
|
139
|
+
else {
|
|
140
|
+
console.log(chalk.gray("You were not logged in."));
|
|
141
|
+
}
|
|
142
|
+
});
|
|
83
143
|
program.parse();
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "swiftroutercli",
|
|
3
|
-
"version": "1.
|
|
3
|
+
"version": "1.1.1",
|
|
4
4
|
"description": "",
|
|
5
5
|
"type": "module",
|
|
6
6
|
"main": "dist/index.js",
|
|
@@ -16,11 +16,14 @@
|
|
|
16
16
|
"author": "",
|
|
17
17
|
"license": "ISC",
|
|
18
18
|
"dependencies": {
|
|
19
|
+
"chalk": "^4.1.2",
|
|
19
20
|
"commander": "^14.0.3",
|
|
20
21
|
"dotenv": "^17.3.1",
|
|
21
22
|
"eventsource-parser": "^3.0.6",
|
|
22
23
|
"ink": "^6.8.0",
|
|
24
|
+
"ora": "^5.4.1",
|
|
23
25
|
"react": "^19.2.4",
|
|
26
|
+
"terminal-image": "^4.2.0",
|
|
24
27
|
"undici": "^7.22.0",
|
|
25
28
|
"zod": "^4.3.6"
|
|
26
29
|
},
|
package/src/config.ts
CHANGED
|
@@ -1,24 +1,38 @@
|
|
|
1
1
|
import fs from "fs";
|
|
2
2
|
import path from "path";
|
|
3
|
-
import
|
|
3
|
+
import { CONFIG_FILE, ENV_API_KEY, ENV_BASE_URL } from "./constants.js";
|
|
4
4
|
|
|
5
5
|
export interface Config {
|
|
6
6
|
apiKey: string;
|
|
7
7
|
baseUrl: string;
|
|
8
8
|
}
|
|
9
9
|
|
|
10
|
-
const CONFIG_FILE = path.join(os.homedir(), ".swiftrouter-cli", "config.json");
|
|
11
|
-
|
|
12
10
|
export function loadConfig(): Config | null {
|
|
11
|
+
// 1. Check for Environment Variables overriding everything else
|
|
12
|
+
const envApiKey = process.env[ENV_API_KEY];
|
|
13
|
+
const envBaseUrl = process.env[ENV_BASE_URL];
|
|
14
|
+
|
|
15
|
+
let fileConfig: Config | null = null;
|
|
16
|
+
|
|
17
|
+
// 2. Load from file if exists
|
|
13
18
|
try {
|
|
14
|
-
if (
|
|
15
|
-
|
|
19
|
+
if (fs.existsSync(CONFIG_FILE)) {
|
|
20
|
+
const data = fs.readFileSync(CONFIG_FILE, "utf-8");
|
|
21
|
+
fileConfig = JSON.parse(data) as Config;
|
|
16
22
|
}
|
|
17
|
-
const data = fs.readFileSync(CONFIG_FILE, "utf-8");
|
|
18
|
-
return JSON.parse(data) as Config;
|
|
19
23
|
} catch (error) {
|
|
20
|
-
|
|
24
|
+
// ignore parse errors and fallback
|
|
21
25
|
}
|
|
26
|
+
|
|
27
|
+
// 3. Merge Env Vars with File Config (Env wins)
|
|
28
|
+
const finalApiKey = envApiKey || fileConfig?.apiKey;
|
|
29
|
+
const finalBaseUrl = envBaseUrl || fileConfig?.baseUrl;
|
|
30
|
+
|
|
31
|
+
if (finalApiKey && finalBaseUrl) {
|
|
32
|
+
return { apiKey: finalApiKey, baseUrl: finalBaseUrl };
|
|
33
|
+
}
|
|
34
|
+
|
|
35
|
+
return null;
|
|
22
36
|
}
|
|
23
37
|
|
|
24
38
|
export function saveConfig(config: Config) {
|
package/src/constants.ts
ADDED
|
@@ -0,0 +1,14 @@
|
|
|
1
|
+
import os from "os";
|
|
2
|
+
import path from "path";
|
|
3
|
+
|
|
4
|
+
// Application Defaults
|
|
5
|
+
export const DEFAULT_BASE_URL = "http://localhost:3000";
|
|
6
|
+
export const DEFAULT_MODEL = "gpt-4o-mini";
|
|
7
|
+
|
|
8
|
+
// System Paths
|
|
9
|
+
export const CONFIG_DIR = path.join(os.homedir(), ".swiftrouter-cli");
|
|
10
|
+
export const CONFIG_FILE = path.join(CONFIG_DIR, "config.json");
|
|
11
|
+
|
|
12
|
+
// Environment Variable Keys
|
|
13
|
+
export const ENV_API_KEY = "SWIFTROUTER_API_KEY";
|
|
14
|
+
export const ENV_BASE_URL = "SWIFTROUTER_BASE_URL";
|
package/src/index.ts
CHANGED
|
@@ -1,9 +1,19 @@
|
|
|
1
1
|
#!/usr/bin/env node
|
|
2
2
|
import { Command } from "commander";
|
|
3
3
|
import * as readline from "readline/promises";
|
|
4
|
+
import chalk from "chalk";
|
|
5
|
+
import ora from "ora";
|
|
4
6
|
import { loadConfig, saveConfig, Config } from "./config.js";
|
|
5
7
|
import { fetchModels } from "./api/client.js";
|
|
6
8
|
import { startChat } from "./ui/Chat.js";
|
|
9
|
+
import { DEFAULT_BASE_URL, DEFAULT_MODEL, CONFIG_FILE } from "./constants.js";
|
|
10
|
+
import terminalImage from "terminal-image";
|
|
11
|
+
import { fileURLToPath } from "url";
|
|
12
|
+
import path from "path";
|
|
13
|
+
import fs from "fs";
|
|
14
|
+
|
|
15
|
+
const __filename = fileURLToPath(import.meta.url);
|
|
16
|
+
const __dirname = path.dirname(__filename);
|
|
7
17
|
|
|
8
18
|
const program = new Command();
|
|
9
19
|
|
|
@@ -13,28 +23,37 @@ async function ensureConfig(): Promise<Config> {
|
|
|
13
23
|
return existingConfig;
|
|
14
24
|
}
|
|
15
25
|
|
|
16
|
-
|
|
17
|
-
|
|
26
|
+
try {
|
|
27
|
+
const logoPath = path.join(__dirname, "..", "assets", "logo.png");
|
|
28
|
+
if (fs.existsSync(logoPath)) {
|
|
29
|
+
console.log(await terminalImage.file(logoPath, { height: "25%" }));
|
|
30
|
+
}
|
|
31
|
+
} catch (e) {
|
|
32
|
+
// Ignore if logo cannot be rendered
|
|
33
|
+
}
|
|
34
|
+
|
|
35
|
+
console.log(chalk.cyan.bold("\nš Welcome to SwiftRouterCLI!"));
|
|
36
|
+
console.log(chalk.gray("It looks like this is your first time. Let's get you set up.\n"));
|
|
18
37
|
|
|
19
38
|
const rl = readline.createInterface({
|
|
20
39
|
input: process.stdin,
|
|
21
40
|
output: process.stdout,
|
|
22
41
|
});
|
|
23
42
|
|
|
24
|
-
const apiKey = await rl.question("Please enter your SwiftRouter API Key: ");
|
|
43
|
+
const apiKey = await rl.question(chalk.bold("Please enter your SwiftRouter API Key: "));
|
|
25
44
|
const baseUrlInput = await rl.question(
|
|
26
|
-
|
|
45
|
+
chalk.bold(`Please enter your SwiftRouter Base URL (default: ${DEFAULT_BASE_URL}): `)
|
|
27
46
|
);
|
|
28
47
|
|
|
29
48
|
rl.close();
|
|
30
49
|
|
|
31
50
|
const config: Config = {
|
|
32
51
|
apiKey: apiKey.trim(),
|
|
33
|
-
baseUrl: baseUrlInput.trim() ||
|
|
52
|
+
baseUrl: baseUrlInput.trim() || DEFAULT_BASE_URL,
|
|
34
53
|
};
|
|
35
54
|
|
|
36
55
|
saveConfig(config);
|
|
37
|
-
console.log("\nā
Configuration saved securely! Starting your session...\n");
|
|
56
|
+
console.log(chalk.green("\nā
Configuration saved securely! Starting your session...\n"));
|
|
38
57
|
|
|
39
58
|
return config;
|
|
40
59
|
}
|
|
@@ -42,7 +61,7 @@ async function ensureConfig(): Promise<Config> {
|
|
|
42
61
|
program
|
|
43
62
|
.name("swiftrouter")
|
|
44
63
|
.description("CLI for SwiftRouter AI Gateway")
|
|
45
|
-
.version("1.0.
|
|
64
|
+
.version("1.0.1");
|
|
46
65
|
|
|
47
66
|
program
|
|
48
67
|
.command("config")
|
|
@@ -56,13 +75,13 @@ program
|
|
|
56
75
|
if (options.setBaseUrl) config.baseUrl = options.setBaseUrl;
|
|
57
76
|
|
|
58
77
|
if (!config.apiKey || !config.baseUrl) {
|
|
59
|
-
console.error("Please provide both an API Key and a Base URL.");
|
|
60
|
-
console.log("Usage: swiftrouter config --set-api-key <KEY> --set-base-url <URL>");
|
|
78
|
+
console.error(chalk.red("Please provide both an API Key and a Base URL."));
|
|
79
|
+
console.log(chalk.gray("Usage: swiftrouter config --set-api-key <KEY> --set-base-url <URL>"));
|
|
61
80
|
process.exit(1);
|
|
62
81
|
}
|
|
63
82
|
|
|
64
83
|
saveConfig(config);
|
|
65
|
-
console.log("ā
Configuration saved successfully!");
|
|
84
|
+
console.log(chalk.green("ā
Configuration saved successfully!"));
|
|
66
85
|
});
|
|
67
86
|
|
|
68
87
|
program
|
|
@@ -70,14 +89,21 @@ program
|
|
|
70
89
|
.description("List available models from SwiftRouter")
|
|
71
90
|
.action(async () => {
|
|
72
91
|
const config = await ensureConfig();
|
|
92
|
+
const spinner = ora("Fetching models from SwiftRouter...").start();
|
|
73
93
|
|
|
74
94
|
try {
|
|
75
|
-
console.log("Fetching models...");
|
|
76
95
|
const models = await fetchModels(config);
|
|
77
|
-
|
|
78
|
-
|
|
96
|
+
spinner.succeed(`Found ${models.length} models!`);
|
|
97
|
+
console.log(chalk.dim("\nAvailable Models:"));
|
|
98
|
+
models.forEach((m: any) => console.log(chalk.cyan(` - ${m.id}`)));
|
|
79
99
|
} catch (e: any) {
|
|
80
|
-
|
|
100
|
+
spinner.fail("Failed to fetch models.");
|
|
101
|
+
if (e.message.includes("fetch failed") || e.message.includes("ECONNREFUSED")) {
|
|
102
|
+
console.error(chalk.red.bold(`\nā Error: Cannot connect to SwiftRouter backend at ${config.baseUrl}`));
|
|
103
|
+
console.error(chalk.dim("Please ensure your SwiftRouter server is currently running."));
|
|
104
|
+
} else {
|
|
105
|
+
console.error(chalk.red(e.message));
|
|
106
|
+
}
|
|
81
107
|
}
|
|
82
108
|
});
|
|
83
109
|
|
|
@@ -85,16 +111,52 @@ program
|
|
|
85
111
|
.command("chat")
|
|
86
112
|
.description("Start an interactive chat session")
|
|
87
113
|
.argument("[prompt]", "Initial prompt to start the chat")
|
|
88
|
-
.option("-m, --model <model>", "Model to use",
|
|
114
|
+
.option("-m, --model <model>", "Model to use", DEFAULT_MODEL)
|
|
89
115
|
.action(async (prompt, options) => {
|
|
90
116
|
const config = await ensureConfig();
|
|
91
117
|
|
|
92
118
|
if (!prompt) {
|
|
93
|
-
console.log("Starting empty chat session...");
|
|
94
119
|
startChat(config, options.model, "");
|
|
95
120
|
} else {
|
|
96
121
|
startChat(config, options.model, prompt);
|
|
97
122
|
}
|
|
98
123
|
});
|
|
99
124
|
|
|
125
|
+
program
|
|
126
|
+
.command("status")
|
|
127
|
+
.description("Check the current configuration and connection status")
|
|
128
|
+
.action(async () => {
|
|
129
|
+
const config = loadConfig();
|
|
130
|
+
if (!config || !config.apiKey || !config.baseUrl) {
|
|
131
|
+
console.log(chalk.yellow("ā ļø SwiftRouterCLI is not authenticated."));
|
|
132
|
+
console.log(`Run ${chalk.cyan("swiftrouter config")} or any command to setup.`);
|
|
133
|
+
return;
|
|
134
|
+
}
|
|
135
|
+
|
|
136
|
+
console.log(chalk.bold("SwiftRouterCLI Status:"));
|
|
137
|
+
console.log(chalk.green("ā
Authenticated"));
|
|
138
|
+
console.log(`${chalk.gray("Base URL:")} ${config.baseUrl}`);
|
|
139
|
+
console.log(`${chalk.gray("API Key:")} sk-...${config.apiKey.slice(-4)}`);
|
|
140
|
+
|
|
141
|
+
const spinner = ora("\nPinging SwiftRouter Server...").start();
|
|
142
|
+
try {
|
|
143
|
+
const models = await fetchModels(config);
|
|
144
|
+
spinner.succeed(chalk.green(`Connected! Found ${models.length} active models.`));
|
|
145
|
+
} catch (e) {
|
|
146
|
+
spinner.fail(chalk.red("Failed to reach server. Are you sure it's running?"));
|
|
147
|
+
}
|
|
148
|
+
});
|
|
149
|
+
|
|
150
|
+
program
|
|
151
|
+
.command("logout")
|
|
152
|
+
.description("Clear your local SwiftRouter configuration securely")
|
|
153
|
+
.action(() => {
|
|
154
|
+
if (fs.existsSync(CONFIG_FILE)) {
|
|
155
|
+
fs.unlinkSync(CONFIG_FILE);
|
|
156
|
+
console.log(chalk.green("ā
Successfully logged out. Configuration deleted."));
|
|
157
|
+
} else {
|
|
158
|
+
console.log(chalk.gray("You were not logged in."));
|
|
159
|
+
}
|
|
160
|
+
});
|
|
161
|
+
|
|
100
162
|
program.parse();
|