fix the issue of multiple calude using one server by claude code
This commit is contained in:
10
src/cli.ts
10
src/cli.ts
@@ -43,10 +43,12 @@ async function waitForService(
|
|||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
import { spawn } from "child_process";
|
||||||
|
|
||||||
async function main() {
|
async function main() {
|
||||||
switch (command) {
|
switch (command) {
|
||||||
case "start":
|
case "start":
|
||||||
await run({ daemon: true });
|
run();
|
||||||
break;
|
break;
|
||||||
case "stop":
|
case "stop":
|
||||||
await closeService();
|
await closeService();
|
||||||
@@ -57,8 +59,10 @@ async function main() {
|
|||||||
case "code":
|
case "code":
|
||||||
if (!isServiceRunning()) {
|
if (!isServiceRunning()) {
|
||||||
console.log("Service not running, starting service...");
|
console.log("Service not running, starting service...");
|
||||||
await run({ daemon: true });
|
spawn("ccr", ["start"], {
|
||||||
// Wait for service to start, exit with error if timeout
|
detached: true,
|
||||||
|
stdio: "ignore",
|
||||||
|
}).unref();
|
||||||
if (await waitForService()) {
|
if (await waitForService()) {
|
||||||
executeCodeCommand(process.argv.slice(3));
|
executeCodeCommand(process.argv.slice(3));
|
||||||
} else {
|
} else {
|
||||||
|
|||||||
18
src/index.ts
18
src/index.ts
@@ -6,8 +6,8 @@ import { formatRequest } from "./middlewares/formatRequest";
|
|||||||
import { rewriteBody } from "./middlewares/rewriteBody";
|
import { rewriteBody } from "./middlewares/rewriteBody";
|
||||||
import OpenAI from "openai";
|
import OpenAI from "openai";
|
||||||
import { streamOpenAIResponse } from "./utils/stream";
|
import { streamOpenAIResponse } from "./utils/stream";
|
||||||
import { isServiceRunning, savePid } from "./utils/processCheck";
|
import { cleanupPidFile, isServiceRunning, savePid } from "./utils/processCheck";
|
||||||
import { fork } from "child_process";
|
|
||||||
|
|
||||||
async function initializeClaudeConfig() {
|
async function initializeClaudeConfig() {
|
||||||
const homeDir = process.env.HOME;
|
const homeDir = process.env.HOME;
|
||||||
@@ -31,7 +31,6 @@ async function initializeClaudeConfig() {
|
|||||||
|
|
||||||
interface RunOptions {
|
interface RunOptions {
|
||||||
port?: number;
|
port?: number;
|
||||||
daemon?: boolean;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
async function run(options: RunOptions = {}) {
|
async function run(options: RunOptions = {}) {
|
||||||
@@ -50,6 +49,19 @@ async function run(options: RunOptions = {}) {
|
|||||||
// Save the PID of the background process
|
// Save the PID of the background process
|
||||||
savePid(process.pid);
|
savePid(process.pid);
|
||||||
|
|
||||||
|
// Handle SIGINT (Ctrl+C) to clean up PID file
|
||||||
|
process.on('SIGINT', () => {
|
||||||
|
console.log("Received SIGINT, cleaning up...");
|
||||||
|
cleanupPidFile();
|
||||||
|
process.exit(0);
|
||||||
|
});
|
||||||
|
|
||||||
|
// Handle SIGTERM to clean up PID file
|
||||||
|
process.on('SIGTERM', () => {
|
||||||
|
cleanupPidFile();
|
||||||
|
process.exit(0);
|
||||||
|
});
|
||||||
|
|
||||||
// Use port from environment variable if set (for background process)
|
// Use port from environment variable if set (for background process)
|
||||||
const servicePort = process.env.SERVICE_PORT
|
const servicePort = process.env.SERVICE_PORT
|
||||||
? parseInt(process.env.SERVICE_PORT)
|
? parseInt(process.env.SERVICE_PORT)
|
||||||
|
|||||||
@@ -1,21 +1,25 @@
|
|||||||
import { isServiceRunning, cleanupPidFile } from './processCheck';
|
import { isServiceRunning, cleanupPidFile, getReferenceCount } from './processCheck';
|
||||||
import { existsSync, readFileSync } from 'fs';
|
import { readFileSync } from 'fs';
|
||||||
import { homedir } from 'os';
|
import { HOME_DIR } from '../constants';
|
||||||
import { join } from 'path';
|
import { join } from 'path';
|
||||||
|
|
||||||
export async function closeService() {
|
export async function closeService() {
|
||||||
const PID_FILE = join(homedir(), '.claude-code-router.pid');
|
const PID_FILE = join(HOME_DIR, '.claude-code-router.pid');
|
||||||
|
|
||||||
if (!isServiceRunning()) {
|
if (!isServiceRunning()) {
|
||||||
console.log("No service is currently running.");
|
console.log("No service is currently running.");
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if (getReferenceCount() > 0) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
try {
|
try {
|
||||||
const pid = parseInt(readFileSync(PID_FILE, 'utf-8'));
|
const pid = parseInt(readFileSync(PID_FILE, 'utf-8'));
|
||||||
process.kill(pid);
|
process.kill(pid);
|
||||||
cleanupPidFile();
|
cleanupPidFile();
|
||||||
console.log("Service has been successfully stopped.");
|
console.log("claude code router service has been successfully stopped.");
|
||||||
} catch (e) {
|
} catch (e) {
|
||||||
console.log("Failed to stop the service. It may have already been stopped.");
|
console.log("Failed to stop the service. It may have already been stopped.");
|
||||||
cleanupPidFile();
|
cleanupPidFile();
|
||||||
|
|||||||
@@ -1,5 +1,6 @@
|
|||||||
import { spawn } from 'child_process';
|
import { spawn } from 'child_process';
|
||||||
import { isServiceRunning } from './processCheck';
|
import { isServiceRunning, incrementReferenceCount, decrementReferenceCount } from './processCheck';
|
||||||
|
import { closeService } from './close';
|
||||||
|
|
||||||
export async function executeCodeCommand(args: string[] = []) {
|
export async function executeCodeCommand(args: string[] = []) {
|
||||||
// Service check is now handled in cli.ts
|
// Service check is now handled in cli.ts
|
||||||
@@ -13,6 +14,9 @@ export async function executeCodeCommand(args: string[] = []) {
|
|||||||
API_TIMEOUT_MS: '600000'
|
API_TIMEOUT_MS: '600000'
|
||||||
};
|
};
|
||||||
|
|
||||||
|
// Increment reference count when command starts
|
||||||
|
incrementReferenceCount();
|
||||||
|
|
||||||
// Execute claude command
|
// Execute claude command
|
||||||
const claudeProcess = spawn('claude', args, {
|
const claudeProcess = spawn('claude', args, {
|
||||||
env,
|
env,
|
||||||
@@ -23,10 +27,13 @@ export async function executeCodeCommand(args: string[] = []) {
|
|||||||
claudeProcess.on('error', (error) => {
|
claudeProcess.on('error', (error) => {
|
||||||
console.error('Failed to start claude command:', error.message);
|
console.error('Failed to start claude command:', error.message);
|
||||||
console.log('Make sure Claude Code is installed: npm install -g @anthropic-ai/claude-code');
|
console.log('Make sure Claude Code is installed: npm install -g @anthropic-ai/claude-code');
|
||||||
|
decrementReferenceCount();
|
||||||
process.exit(1);
|
process.exit(1);
|
||||||
});
|
});
|
||||||
|
|
||||||
claudeProcess.on('close', (code) => {
|
claudeProcess.on('close', (code) => {
|
||||||
|
decrementReferenceCount();
|
||||||
|
closeService()
|
||||||
process.exit(code || 0);
|
process.exit(code || 0);
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -1,6 +1,32 @@
|
|||||||
import { existsSync, readFileSync, writeFileSync } from 'fs';
|
import { existsSync, readFileSync, writeFileSync } from 'fs';
|
||||||
import { PID_FILE } from '../constants';
|
import { PID_FILE } from '../constants';
|
||||||
|
|
||||||
|
const REFERENCE_COUNT_FILE = '/tmp/claude-code-reference-count.txt';
|
||||||
|
|
||||||
|
export function incrementReferenceCount() {
|
||||||
|
let count = 0;
|
||||||
|
if (existsSync(REFERENCE_COUNT_FILE)) {
|
||||||
|
count = parseInt(readFileSync(REFERENCE_COUNT_FILE, 'utf-8')) || 0;
|
||||||
|
}
|
||||||
|
count++;
|
||||||
|
writeFileSync(REFERENCE_COUNT_FILE, count.toString());
|
||||||
|
}
|
||||||
|
|
||||||
|
export function decrementReferenceCount() {
|
||||||
|
let count = 0;
|
||||||
|
if (existsSync(REFERENCE_COUNT_FILE)) {
|
||||||
|
count = parseInt(readFileSync(REFERENCE_COUNT_FILE, 'utf-8')) || 0;
|
||||||
|
}
|
||||||
|
count = Math.max(0, count - 1);
|
||||||
|
writeFileSync(REFERENCE_COUNT_FILE, count.toString());
|
||||||
|
}
|
||||||
|
|
||||||
|
export function getReferenceCount(): number {
|
||||||
|
if (!existsSync(REFERENCE_COUNT_FILE)) {
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
return parseInt(readFileSync(REFERENCE_COUNT_FILE, 'utf-8')) || 0;
|
||||||
|
}
|
||||||
|
|
||||||
export function isServiceRunning(): boolean {
|
export function isServiceRunning(): boolean {
|
||||||
if (!existsSync(PID_FILE)) {
|
if (!existsSync(PID_FILE)) {
|
||||||
@@ -55,6 +81,7 @@ export function getServiceInfo() {
|
|||||||
pid,
|
pid,
|
||||||
port: 3456,
|
port: 3456,
|
||||||
endpoint: 'http://127.0.0.1:3456',
|
endpoint: 'http://127.0.0.1:3456',
|
||||||
pidFile: PID_FILE
|
pidFile: PID_FILE,
|
||||||
|
referenceCount: getReferenceCount()
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
|||||||
Reference in New Issue
Block a user