release v1.0.39

This commit is contained in:
musistudio
2025-08-16 15:17:06 +08:00
parent e078127ac6
commit 19d0f3b8f5
5 changed files with 42 additions and 16 deletions

View File

@@ -1,6 +1,6 @@
{ {
"name": "@musistudio/claude-code-router", "name": "@musistudio/claude-code-router",
"version": "1.0.38", "version": "1.0.39",
"description": "Use Claude Code without an Anthropics account and route it to another LLM provider", "description": "Use Claude Code without an Anthropics account and route it to another LLM provider",
"bin": { "bin": {
"ccr": "./dist/cli.js" "ccr": "./dist/cli.js"
@@ -20,7 +20,7 @@
"license": "MIT", "license": "MIT",
"dependencies": { "dependencies": {
"@fastify/static": "^8.2.0", "@fastify/static": "^8.2.0",
"@musistudio/llms": "^1.0.24", "@musistudio/llms": "^1.0.25",
"dotenv": "^16.4.7", "dotenv": "^16.4.7",
"json5": "^2.2.3", "json5": "^2.2.3",
"openurl": "^1.1.1", "openurl": "^1.1.1",

10
pnpm-lock.yaml generated
View File

@@ -12,8 +12,8 @@ importers:
specifier: ^8.2.0 specifier: ^8.2.0
version: 8.2.0 version: 8.2.0
'@musistudio/llms': '@musistudio/llms':
specifier: ^1.0.24 specifier: ^1.0.25
version: 1.0.24(ws@8.18.3)(zod@3.25.67) version: 1.0.25(ws@8.18.3)(zod@3.25.67)
dotenv: dotenv:
specifier: ^16.4.7 specifier: ^16.4.7
version: 16.6.1 version: 16.6.1
@@ -260,8 +260,8 @@ packages:
resolution: {integrity: sha512-9I2Zn6+NJLfaGoz9jN3lpwDgAYvfGeNYdbAIjJOqzs4Tpc+VU3Jqq4IofSUBKajiDS8k9fZIg18/z13mpk1bsA==} resolution: {integrity: sha512-9I2Zn6+NJLfaGoz9jN3lpwDgAYvfGeNYdbAIjJOqzs4Tpc+VU3Jqq4IofSUBKajiDS8k9fZIg18/z13mpk1bsA==}
engines: {node: '>=8'} engines: {node: '>=8'}
'@musistudio/llms@1.0.24': '@musistudio/llms@1.0.25':
resolution: {integrity: sha512-Hz6ZT92/ZM/eR5kTdCBHD6zoEMOvT5u6g/vfCir5Hwvl4QGHk3g30EmX1pZAXJf83kLnB/lSEq/HQimFIXHIhQ==} resolution: {integrity: sha512-l+MbVrCrUN/BbYDAJVqpDCkQm4i/baYigxv9ZhNLaQXUU1OVFRvxMq7nQrZdv4AsmVExsKzLNw+m/+B181Ot6Q==}
'@nodelib/fs.scandir@2.1.5': '@nodelib/fs.scandir@2.1.5':
resolution: {integrity: sha512-vq24Bq3ym5HEQm2NKCr3yXDwjc7vTsEThRDnkp2DK9p1uqLR+DHurm/NOTo0KG7HYHU7eppKZj3MyqYuMBf62g==} resolution: {integrity: sha512-vq24Bq3ym5HEQm2NKCr3yXDwjc7vTsEThRDnkp2DK9p1uqLR+DHurm/NOTo0KG7HYHU7eppKZj3MyqYuMBf62g==}
@@ -1112,7 +1112,7 @@ snapshots:
'@lukeed/ms@2.0.2': {} '@lukeed/ms@2.0.2': {}
'@musistudio/llms@1.0.24(ws@8.18.3)(zod@3.25.67)': '@musistudio/llms@1.0.25(ws@8.18.3)(zod@3.25.67)':
dependencies: dependencies:
'@anthropic-ai/sdk': 0.54.0 '@anthropic-ai/sdk': 0.54.0
'@fastify/cors': 11.0.1 '@fastify/cors': 11.0.1

View File

@@ -89,7 +89,7 @@ async function run(options: RunOptions = {}) {
// Configure logger based on config settings // Configure logger based on config settings
const loggerConfig = config.LOG !== false ? { const loggerConfig = config.LOG !== false ? {
level: config.LOG_LEVEL || "info", level: config.LOG_LEVEL || "debug",
stream: createWriteStream({ stream: createWriteStream({
path: HOME_DIR, path: HOME_DIR,
filename: config.LOGNAME || `./logs/ccr-${+new Date()}.log`, filename: config.LOGNAME || `./logs/ccr-${+new Date()}.log`,

View File

@@ -16,6 +16,18 @@ export async function executeCodeCommand(args: string[] = []) {
API_TIMEOUT_MS: String(config.API_TIMEOUT_MS ?? 600000), // Default to 10 minutes if not set API_TIMEOUT_MS: String(config.API_TIMEOUT_MS ?? 600000), // Default to 10 minutes if not set
}; };
const settingsFlag: Record<string, any> = {};
if (config?.StatusLine?.enabled) {
settingsFlag.statusLine = {
type: "command",
command: "ccr statusline",
padding: 0,
};
}
if (Object.keys(settingsFlag).length > 0) {
args.push(`--settings=${JSON.stringify(settingsFlag)}`);
}
// Non-interactive mode for automation environments // Non-interactive mode for automation environments
if (config.NON_INTERACTIVE_MODE) { if (config.NON_INTERACTIVE_MODE) {
env.CI = "true"; env.CI = "true";
@@ -39,21 +51,28 @@ export async function executeCodeCommand(args: string[] = []) {
// Execute claude command // Execute claude command
const claudePath = process.env.CLAUDE_PATH || "claude"; const claudePath = process.env.CLAUDE_PATH || "claude";
// Properly join arguments to preserve spaces in quotes // Properly join arguments to preserve spaces in quotes
// Wrap each argument in double quotes to preserve single and double quotes inside arguments // Wrap each argument in double quotes to preserve single and double quotes inside arguments
const joinedArgs = args.length > 0 ? args.map(arg => `"${arg.replace(/\"/g, '\\"')}"`).join(" ") : ""; const joinedArgs =
args.length > 0
? args.map((arg) => `"${arg.replace(/\"/g, '\\"')}"`).join(" ")
: "";
// 🔥 CONFIG-DRIVEN: stdio configuration based on environment // 🔥 CONFIG-DRIVEN: stdio configuration based on environment
const stdioConfig: StdioOptions = config.NON_INTERACTIVE_MODE const stdioConfig: StdioOptions = config.NON_INTERACTIVE_MODE
? ["pipe", "inherit", "inherit"] // Pipe stdin for non-interactive ? ["pipe", "inherit", "inherit"] // Pipe stdin for non-interactive
: "inherit"; // Default inherited behavior : "inherit"; // Default inherited behavior
const claudeProcess = spawn(claudePath + (joinedArgs ? ` ${joinedArgs}` : ""), [], { const claudeProcess = spawn(
env, claudePath + (joinedArgs ? ` ${joinedArgs}` : ""),
stdio: stdioConfig, [],
shell: true, {
}); env,
stdio: stdioConfig,
shell: true,
}
);
// Close stdin for non-interactive mode // Close stdin for non-interactive mode
if (config.NON_INTERACTIVE_MODE) { if (config.NON_INTERACTIVE_MODE) {

View File

@@ -125,7 +125,14 @@ const getUseModel = async (req: any, tokenCount: number, config: any) => {
return config.Router!.default; return config.Router!.default;
}; };
export const router = async (req: any, _res: any, config: any) => { export const router = async (req: any, _res: any, config: any) => {
// Parse sessionId from metadata.user_id
if (req.body.metadata?.user_id) {
const parts = req.body.metadata.user_id.split('_session_');
if (parts.length > 1) {
req.sessionId = parts[1];
}
}
const { messages, system = [], tools }: MessageCreateParamsBase = req.body; const { messages, system = [], tools }: MessageCreateParamsBase = req.body;
try { try {
const tokenCount = calculateTokenCount( const tokenCount = calculateTokenCount(