From 179bab605eaaffc5f9f6c52347ac94af68df6326 Mon Sep 17 00:00:00 2001 From: musistudio Date: Fri, 25 Jul 2025 17:17:14 +0800 Subject: [PATCH] release v1.0.27 to fix some bugs and enhance tools --- package.json | 5 ++-- pnpm-lock.yaml | 21 ++++++++++++---- src/cli.ts | 16 +++++++++++-- src/utils/index.ts | 60 ++++++++++++++++++++++++++++++---------------- 4 files changed, 72 insertions(+), 30 deletions(-) diff --git a/package.json b/package.json index 0f64b6e..c62c8c2 100644 --- a/package.json +++ b/package.json @@ -1,6 +1,6 @@ { "name": "@musistudio/claude-code-router", - "version": "1.0.26", + "version": "1.0.27", "description": "Use Claude Code without an Anthropics account and route it to another LLM provider", "bin": { "ccr": "./dist/cli.js" @@ -19,8 +19,9 @@ "author": "musistudio", "license": "MIT", "dependencies": { - "@musistudio/llms": "^1.0.12", + "@musistudio/llms": "^1.0.14", "dotenv": "^16.4.7", + "json5": "^2.2.3", "tiktoken": "^1.0.21", "uuid": "^11.1.0" }, diff --git a/pnpm-lock.yaml b/pnpm-lock.yaml index 476be12..af98484 100644 --- a/pnpm-lock.yaml +++ b/pnpm-lock.yaml @@ -9,11 +9,14 @@ importers: .: dependencies: '@musistudio/llms': - specifier: ^1.0.12 - version: 1.0.12(ws@8.18.3)(zod@3.25.67) + specifier: ^1.0.14 + version: 1.0.14(ws@8.18.3)(zod@3.25.67) dotenv: specifier: ^16.4.7 version: 16.6.1 + json5: + specifier: ^2.2.3 + version: 2.2.3 tiktoken: specifier: ^1.0.21 version: 1.0.21 @@ -223,8 +226,8 @@ packages: '@modelcontextprotocol/sdk': optional: true - '@musistudio/llms@1.0.12': - resolution: {integrity: sha512-5sRIrt8UgXDLqim1xZrnMxugUW2m6zopXMQ+wF5Px20hH06aLO0zdT3Gyq78IKJZ+Xupkj+h1FooCAtWl+6bLw==} + '@musistudio/llms@1.0.14': + resolution: {integrity: sha512-56+i7hAmdx4QUFBD5ey0EbWPlzQ882d9PCZB1Ky5mvMt5LLFx5x2RzfiJo0LWdvEInfPRAIufgwt8lISyApOUQ==} '@nodelib/fs.scandir@2.1.5': resolution: {integrity: sha512-vq24Bq3ym5HEQm2NKCr3yXDwjc7vTsEThRDnkp2DK9p1uqLR+DHurm/NOTo0KG7HYHU7eppKZj3MyqYuMBf62g==} @@ -445,6 +448,11 @@ packages: json-schema-traverse@1.0.0: resolution: {integrity: sha512-NM8/P9n3XjXhIZn1lLhkFaACTOURQXjWhV4BA/RnOv8xvgqtqpAX9IO4mRQxSx1Rlo4tqzeqb0sOlruaOy3dug==} + json5@2.2.3: + resolution: {integrity: sha512-XmOWe7eyHYH14cLdVPoyg+GOH3rYX++KpzrylJwSW98t3Nk+U8XOl8FWKOgwtzdb8lXGf6zYwDUzeHMWfxasyg==} + engines: {node: '>=6'} + hasBin: true + jwa@2.0.1: resolution: {integrity: sha512-hRF04fqJIP8Abbkq5NKGN0Bbr3JxlQ+qhZufXVr0DvujKy93ZCbXZMHDL4EOtodSbCWxOqR8MS1tXA5hwqCXDg==} @@ -824,13 +832,14 @@ snapshots: - supports-color - utf-8-validate - '@musistudio/llms@1.0.12(ws@8.18.3)(zod@3.25.67)': + '@musistudio/llms@1.0.14(ws@8.18.3)(zod@3.25.67)': dependencies: '@anthropic-ai/sdk': 0.54.0 '@fastify/cors': 11.0.1 '@google/genai': 1.8.0 dotenv: 16.6.1 fastify: 5.4.0 + json5: 2.2.3 openai: 5.8.2(ws@8.18.3)(zod@3.25.67) undici: 7.11.0 uuid: 11.1.0 @@ -1115,6 +1124,8 @@ snapshots: json-schema-traverse@1.0.0: {} + json5@2.2.3: {} + jwa@2.0.1: dependencies: buffer-equal-constant-time: 1.0.1 diff --git a/src/cli.ts b/src/cli.ts index 26d004c..6e8780c 100644 --- a/src/cli.ts +++ b/src/cli.ts @@ -83,14 +83,26 @@ async function main() { const cliPath = join(__dirname, "cli.js"); const startProcess = spawn("node", [cliPath, "start"], { detached: true, - stdio: "ignore", + stdio: ["ignore", "pipe", "pipe"], + }); + + let errorMessage = ""; + startProcess.stderr?.on("data", (data) => { + errorMessage += data.toString(); }); startProcess.on("error", (error) => { - console.error("Failed to start service:", 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()) { diff --git a/src/utils/index.ts b/src/utils/index.ts index 5c43667..ba0c3f1 100644 --- a/src/utils/index.ts +++ b/src/utils/index.ts @@ -1,5 +1,6 @@ import fs from "node:fs/promises"; import readline from "node:readline"; +import JSON5 from "json5"; import { CONFIG_FILE, DEFAULT_CONFIG, @@ -45,33 +46,50 @@ const confirm = async (query: string): Promise => { export const readConfigFile = async () => { try { const config = await fs.readFile(CONFIG_FILE, "utf-8"); - return JSON.parse(config); - } catch { - const name = await question("Enter Provider Name: "); - const APIKEY = await question("Enter Provider API KEY: "); - const baseUrl = await question("Enter Provider URL: "); - const model = await question("Enter MODEL Name: "); - const config = Object.assign({}, DEFAULT_CONFIG, { - Providers: [ - { - name, - api_base_url: baseUrl, - api_key: APIKEY, - models: [model], + try { + // Try to parse with JSON5 first (which also supports standard JSON) + return JSON5.parse(config); + } catch (parseError) { + console.error(`Failed to parse config file at ${CONFIG_FILE}`); + console.error("Error details:", (parseError as Error).message); + console.error("Please check your config file syntax."); + process.exit(1); + } + } catch (readError: any) { + if (readError.code === "ENOENT") { + // Config file doesn't exist, prompt user for initial setup + const name = await question("Enter Provider Name: "); + const APIKEY = await question("Enter Provider API KEY: "); + const baseUrl = await question("Enter Provider URL: "); + const model = await question("Enter MODEL Name: "); + const config = Object.assign({}, DEFAULT_CONFIG, { + Providers: [ + { + name, + api_base_url: baseUrl, + api_key: APIKEY, + models: [model], + }, + ], + Router: { + default: `${name},${model}`, }, - ], - Router: { - default: `${name},${model}`, - }, - }); - await writeConfigFile(config); - return config; + }); + await writeConfigFile(config); + return config; + } else { + console.error(`Failed to read config file at ${CONFIG_FILE}`); + console.error("Error details:", readError.message); + process.exit(1); + } } }; export const writeConfigFile = async (config: any) => { await ensureDir(HOME_DIR); - await fs.writeFile(CONFIG_FILE, JSON.stringify(config, null, 2)); + // Add a comment to indicate JSON5 support + const configWithComment = `// This config file supports JSON5 format (comments, trailing commas, etc.)\n${JSON5.stringify(config, null, 2)}`; + await fs.writeFile(CONFIG_FILE, configWithComment); }; export const initConfig = async () => {