mirror of
https://github.com/musistudio/claude-code-router.git
synced 2026-06-16 21:03:54 +08:00
- Created separate build script to handle both CLI and UI building - Added automatic UI dependency installation - Copy built UI artifacts to dist directory 🤖 Generated with [Claude Code](https://claude.ai/code) Co-Authored-By: Claude <noreply@anthropic.com>
227 lines
6.4 KiB
JavaScript
227 lines
6.4 KiB
JavaScript
#!/usr/bin/env node
|
|
import { run } from "./index";
|
|
import { showStatus } from "./utils/status";
|
|
import { executeCodeCommand } from "./utils/codeCommand";
|
|
import { cleanupPidFile, isServiceRunning, getServiceInfo } from "./utils/processCheck";
|
|
import { version } from "../package.json";
|
|
import { spawn, exec } from "child_process";
|
|
import { PID_FILE, REFERENCE_COUNT_FILE } from "./constants";
|
|
import fs, { existsSync, readFileSync } from "fs";
|
|
import {join} from "path";
|
|
|
|
const command = process.argv[2];
|
|
|
|
const HELP_TEXT = `
|
|
Usage: ccr [command]
|
|
|
|
Commands:
|
|
start Start server
|
|
stop Stop server
|
|
restart Restart server
|
|
status Show server status
|
|
code Execute claude command
|
|
ui Open the web UI in browser
|
|
-v, version Show version information
|
|
-h, help Show help information
|
|
|
|
Example:
|
|
ccr start
|
|
ccr code "Write a Hello World"
|
|
ccr ui
|
|
`;
|
|
|
|
async function waitForService(
|
|
timeout = 10000,
|
|
initialDelay = 1000
|
|
): Promise<boolean> {
|
|
// Wait for an initial period to let the service initialize
|
|
await new Promise((resolve) => setTimeout(resolve, initialDelay));
|
|
|
|
const startTime = Date.now();
|
|
while (Date.now() - startTime < timeout) {
|
|
if (isServiceRunning()) {
|
|
// Wait for an additional short period to ensure service is fully ready
|
|
await new Promise((resolve) => setTimeout(resolve, 500));
|
|
return true;
|
|
}
|
|
await new Promise((resolve) => setTimeout(resolve, 100));
|
|
}
|
|
return false;
|
|
}
|
|
|
|
async function main() {
|
|
switch (command) {
|
|
case "start":
|
|
run();
|
|
break;
|
|
case "stop":
|
|
try {
|
|
const pid = parseInt(readFileSync(PID_FILE, "utf-8"));
|
|
process.kill(pid);
|
|
cleanupPidFile();
|
|
if (existsSync(REFERENCE_COUNT_FILE)) {
|
|
try {
|
|
fs.unlinkSync(REFERENCE_COUNT_FILE);
|
|
} catch (e) {
|
|
// Ignore cleanup errors
|
|
}
|
|
}
|
|
console.log(
|
|
"claude code router service has been successfully stopped."
|
|
);
|
|
} catch (e) {
|
|
console.log(
|
|
"Failed to stop the service. It may have already been stopped."
|
|
);
|
|
cleanupPidFile();
|
|
}
|
|
break;
|
|
case "status":
|
|
await showStatus();
|
|
break;
|
|
case "code":
|
|
if (!isServiceRunning()) {
|
|
console.log("Service not running, starting service...");
|
|
const cliPath = join(__dirname, "cli.js");
|
|
const startProcess = spawn("node", [cliPath, "start"], {
|
|
detached: true,
|
|
stdio: "ignore",
|
|
});
|
|
|
|
// let errorMessage = "";
|
|
// startProcess.stderr?.on("data", (data) => {
|
|
// errorMessage += data.toString();
|
|
// });
|
|
|
|
startProcess.on("error", (error) => {
|
|
console.error("Failed to start service:", error.message);
|
|
process.exit(1);
|
|
});
|
|
|
|
// startProcess.on("close", (code) => {
|
|
// if (code !== 0 && errorMessage) {
|
|
// console.error("Failed to start service:", errorMessage.trim());
|
|
// process.exit(1);
|
|
// }
|
|
// });
|
|
|
|
startProcess.unref();
|
|
|
|
if (await waitForService()) {
|
|
executeCodeCommand(process.argv.slice(3));
|
|
} else {
|
|
console.error(
|
|
"Service startup timeout, please manually run `ccr start` to start the service"
|
|
);
|
|
process.exit(1);
|
|
}
|
|
} else {
|
|
executeCodeCommand(process.argv.slice(3));
|
|
}
|
|
break;
|
|
case "ui":
|
|
// Check if service is running
|
|
if (!isServiceRunning()) {
|
|
console.log("Service not running, starting service...");
|
|
const cliPath = join(__dirname, "cli.js");
|
|
const startProcess = spawn("node", [cliPath, "start"], {
|
|
detached: true,
|
|
stdio: "ignore",
|
|
});
|
|
|
|
startProcess.on("error", (error) => {
|
|
console.error("Failed to start service:", error.message);
|
|
process.exit(1);
|
|
});
|
|
|
|
startProcess.unref();
|
|
|
|
if (!(await waitForService())) {
|
|
console.error(
|
|
"Service startup timeout, please manually run `ccr start` to start the service"
|
|
);
|
|
process.exit(1);
|
|
}
|
|
}
|
|
|
|
// Get service info and open UI
|
|
const serviceInfo = await getServiceInfo();
|
|
const uiUrl = `${serviceInfo.endpoint}/ui/`;
|
|
console.log(`Opening UI at ${uiUrl}`);
|
|
|
|
// Open URL in browser based on platform
|
|
const platform = process.platform;
|
|
let openCommand = "";
|
|
|
|
if (platform === "win32") {
|
|
// Windows
|
|
openCommand = `start ${uiUrl}`;
|
|
} else if (platform === "darwin") {
|
|
// macOS
|
|
openCommand = `open ${uiUrl}`;
|
|
} else if (platform === "linux") {
|
|
// Linux
|
|
openCommand = `xdg-open ${uiUrl}`;
|
|
} else {
|
|
console.error("Unsupported platform for opening browser");
|
|
process.exit(1);
|
|
}
|
|
|
|
exec(openCommand, (error) => {
|
|
if (error) {
|
|
console.error("Failed to open browser:", error.message);
|
|
process.exit(1);
|
|
}
|
|
});
|
|
break;
|
|
case "-v":
|
|
case "version":
|
|
console.log(`claude-code-router version: ${version}`);
|
|
break;
|
|
case "restart":
|
|
// Stop the service if it's running
|
|
try {
|
|
const pid = parseInt(readFileSync(PID_FILE, "utf-8"));
|
|
process.kill(pid);
|
|
cleanupPidFile();
|
|
if (existsSync(REFERENCE_COUNT_FILE)) {
|
|
try {
|
|
fs.unlinkSync(REFERENCE_COUNT_FILE);
|
|
} catch (e) {
|
|
// Ignore cleanup errors
|
|
}
|
|
}
|
|
console.log("claude code router service has been stopped.");
|
|
} catch (e) {
|
|
console.log("Service was not running or failed to stop.");
|
|
cleanupPidFile();
|
|
}
|
|
|
|
// Start the service again in the background
|
|
console.log("Starting claude code router service...");
|
|
const cliPath = join(__dirname, "cli.js");
|
|
const startProcess = spawn("node", [cliPath, "start"], {
|
|
detached: true,
|
|
stdio: "ignore",
|
|
});
|
|
|
|
startProcess.on("error", (error) => {
|
|
console.error("Failed to start service:", error);
|
|
process.exit(1);
|
|
});
|
|
|
|
startProcess.unref();
|
|
console.log("✅ Service started successfully in the background.");
|
|
break;
|
|
case "-h":
|
|
case "help":
|
|
console.log(HELP_TEXT);
|
|
break;
|
|
default:
|
|
console.log(HELP_TEXT);
|
|
process.exit(1);
|
|
}
|
|
}
|
|
|
|
main().catch(console.error);
|