relese v1.0.34 to optimize the log
This commit is contained in:
@@ -290,6 +290,7 @@ Transformers allow you to modify the request and response payloads to ensure com
|
||||
- `enhancetool`: Adds a layer of error tolerance to the tool call parameters returned by the LLM (this will cause the tool call information to no longer be streamed).
|
||||
- `cleancache`: Clears the `cache_control` field from requests.
|
||||
- `vertex-gemini`: Handles the Gemini API using Vertex authentication.
|
||||
- `qwen-cli` (experimental): Unofficial support for qwen3-coder-plus model via Qwen CLI [qwen-cli.js](https://gist.github.com/musistudio/f5a67841ced39912fd99e42200d5ca8b).
|
||||
|
||||
**Custom Transformers:**
|
||||
|
||||
@@ -506,5 +507,10 @@ A huge thank you to all our sponsors for their generous support!
|
||||
- @\*亿
|
||||
- @\*辉
|
||||
- @JACK
|
||||
- @\*光
|
||||
- @W\*l
|
||||
- [@kesku](https://github.com/kesku)
|
||||
- @水\*丫
|
||||
- @二吉吉
|
||||
|
||||
(If your name is masked, please contact me via my homepage email to update it with your GitHub username.)
|
||||
|
||||
@@ -284,6 +284,7 @@ Transformers 允许您修改请求和响应负载,以确保与不同提供商
|
||||
- `enhancetool`: 对 LLM 返回的工具调用参数增加一层容错处理(这会导致不再流式返回工具调用信息)。
|
||||
- `cleancache`: 清除请求中的 `cache_control` 字段。
|
||||
- `vertex-gemini`: 处理使用 vertex 鉴权的 gemini api。
|
||||
- `qwen-cli` (实验性): 通过 Qwen CLI [qwen-cli.js](https://gist.github.com/musistudio/f5a67841ced39912fd99e42200d5ca8b) 对 qwen3-coder-plus 的非官方支持。
|
||||
|
||||
**自定义 Transformer:**
|
||||
|
||||
@@ -497,6 +498,11 @@ jobs:
|
||||
- @\*亿
|
||||
- @\*辉
|
||||
- @JACK
|
||||
- @\*光
|
||||
- @W\*l
|
||||
- [@kesku](https://github.com/kesku)
|
||||
- @水\*丫
|
||||
- @二吉吉
|
||||
|
||||
(如果您的名字被屏蔽,请通过我的主页电子邮件与我联系,以便使用您的 GitHub 用户名进行更新。)
|
||||
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
{
|
||||
"name": "@musistudio/claude-code-router",
|
||||
"version": "1.0.33",
|
||||
"version": "1.0.34",
|
||||
"description": "Use Claude Code without an Anthropics account and route it to another LLM provider",
|
||||
"bin": {
|
||||
"ccr": "./dist/cli.js"
|
||||
@@ -20,10 +20,11 @@
|
||||
"license": "MIT",
|
||||
"dependencies": {
|
||||
"@fastify/static": "^8.2.0",
|
||||
"@musistudio/llms": "v1.0.19",
|
||||
"@musistudio/llms": "^1.0.21",
|
||||
"dotenv": "^16.4.7",
|
||||
"json5": "^2.2.3",
|
||||
"openurl": "^1.1.1",
|
||||
"pino-rotating-file-stream": "^0.0.2",
|
||||
"tiktoken": "^1.0.21",
|
||||
"uuid": "^11.1.0"
|
||||
},
|
||||
|
||||
26
pnpm-lock.yaml
generated
26
pnpm-lock.yaml
generated
@@ -12,8 +12,8 @@ importers:
|
||||
specifier: ^8.2.0
|
||||
version: 8.2.0
|
||||
'@musistudio/llms':
|
||||
specifier: v1.0.19
|
||||
version: 1.0.19(ws@8.18.3)(zod@3.25.67)
|
||||
specifier: ^1.0.21
|
||||
version: 1.0.21(ws@8.18.3)(zod@3.25.67)
|
||||
dotenv:
|
||||
specifier: ^16.4.7
|
||||
version: 16.6.1
|
||||
@@ -23,6 +23,9 @@ importers:
|
||||
openurl:
|
||||
specifier: ^1.1.1
|
||||
version: 1.1.1
|
||||
pino-rotating-file-stream:
|
||||
specifier: ^0.0.2
|
||||
version: 0.0.2
|
||||
tiktoken:
|
||||
specifier: ^1.0.21
|
||||
version: 1.0.21
|
||||
@@ -257,8 +260,8 @@ packages:
|
||||
resolution: {integrity: sha512-9I2Zn6+NJLfaGoz9jN3lpwDgAYvfGeNYdbAIjJOqzs4Tpc+VU3Jqq4IofSUBKajiDS8k9fZIg18/z13mpk1bsA==}
|
||||
engines: {node: '>=8'}
|
||||
|
||||
'@musistudio/llms@1.0.19':
|
||||
resolution: {integrity: sha512-+U29ZxqXUQJBur5kE9d3e0mC19H0uetwxYvMpWCF4lBtXb2syBPIop2KeolBP+5/vSUz8M45HFd8yKFfVDEO3A==}
|
||||
'@musistudio/llms@1.0.21':
|
||||
resolution: {integrity: sha512-oRSs9U0o13HCNaw+fesLnJv75t+AUSKn37LxJOlO1yNWYucjfB76vo3y3rK47wztxv2rmSumrlbu2FzjRG4YuQ==}
|
||||
|
||||
'@nodelib/fs.scandir@2.1.5':
|
||||
resolution: {integrity: sha512-vq24Bq3ym5HEQm2NKCr3yXDwjc7vTsEThRDnkp2DK9p1uqLR+DHurm/NOTo0KG7HYHU7eppKZj3MyqYuMBf62g==}
|
||||
@@ -707,6 +710,9 @@ packages:
|
||||
pino-abstract-transport@2.0.0:
|
||||
resolution: {integrity: sha512-F63x5tizV6WCh4R6RHyi2Ml+M70DNRXt/+HANowMflpgGFMAym/VKm6G7ZOQRjqN7XbGxK1Lg9t6ZrtzOaivMw==}
|
||||
|
||||
pino-rotating-file-stream@0.0.2:
|
||||
resolution: {integrity: sha512-knF+ReDBMQMB7gzBfuFpUmCrXpRen6YYh5Q9Ymmj//dDHeH4QEMwAV7VoGEEM+30s7VHqfbabazs9wxkMO2BIQ==}
|
||||
|
||||
pino-std-serializers@7.0.0:
|
||||
resolution: {integrity: sha512-e906FRY0+tV27iq4juKzSYPbUj2do2X2JX4EzSca1631EB2QJQUqGbDuERal7LCtOpxl6x3+nvo9NPZcmjkiFA==}
|
||||
|
||||
@@ -757,6 +763,10 @@ packages:
|
||||
rfdc@1.4.1:
|
||||
resolution: {integrity: sha512-q1b3N5QkRUWUl7iyylaaj3kOpIT0N2i9MqIEQXP73GVsN9cw3fdx8X63cEmWhJGi2PPCF23Ijp7ktmd39rawIA==}
|
||||
|
||||
rotating-file-stream@3.2.6:
|
||||
resolution: {integrity: sha512-r8yShzMWUvWXkRzbOXDM1fEaMpc3qo2PzK7bBH/0p0Nl/uz8Mud/Y+0XTQxe3kbSnDF7qBH2tSe83WDKA7o3ww==}
|
||||
engines: {node: '>=14.0'}
|
||||
|
||||
run-parallel@1.2.0:
|
||||
resolution: {integrity: sha512-5l4VyZR86LZ/lDxZTR6jqL8AFE2S0IFLMP26AbjsLVADxHdhB/c0GUsH+y39UfCi3dzz8OlQuPmnaJOMoDHQBA==}
|
||||
|
||||
@@ -1102,7 +1112,7 @@ snapshots:
|
||||
|
||||
'@lukeed/ms@2.0.2': {}
|
||||
|
||||
'@musistudio/llms@1.0.19(ws@8.18.3)(zod@3.25.67)':
|
||||
'@musistudio/llms@1.0.21(ws@8.18.3)(zod@3.25.67)':
|
||||
dependencies:
|
||||
'@anthropic-ai/sdk': 0.54.0
|
||||
'@fastify/cors': 11.0.1
|
||||
@@ -1604,6 +1614,10 @@ snapshots:
|
||||
dependencies:
|
||||
split2: 4.2.0
|
||||
|
||||
pino-rotating-file-stream@0.0.2:
|
||||
dependencies:
|
||||
rotating-file-stream: 3.2.6
|
||||
|
||||
pino-std-serializers@7.0.0: {}
|
||||
|
||||
pino@9.7.0:
|
||||
@@ -1653,6 +1667,8 @@ snapshots:
|
||||
|
||||
rfdc@1.4.1: {}
|
||||
|
||||
rotating-file-stream@3.2.6: {}
|
||||
|
||||
run-parallel@1.2.0:
|
||||
dependencies:
|
||||
queue-microtask: 1.2.3
|
||||
|
||||
30
src/index.ts
30
src/index.ts
@@ -1,8 +1,8 @@
|
||||
import { existsSync } from "fs";
|
||||
import { writeFile } from "fs/promises";
|
||||
import { homedir } from "os";
|
||||
import { join } from "path";
|
||||
import { initConfig, initDir } from "./utils";
|
||||
import path, { join } from "path";
|
||||
import { initConfig, initDir, cleanupLogFiles } from "./utils";
|
||||
import { createServer } from "./server";
|
||||
import { router } from "./utils/router";
|
||||
import { apiKeyAuth } from "./middleware/auth";
|
||||
@@ -12,6 +12,8 @@ import {
|
||||
savePid,
|
||||
} from "./utils/processCheck";
|
||||
import { CONFIG_FILE } from "./constants";
|
||||
import createWriteStream from "pino-rotating-file-stream";
|
||||
import { HOME_DIR } from "./constants";
|
||||
|
||||
async function initializeClaudeConfig() {
|
||||
const homeDir = homedir();
|
||||
@@ -46,14 +48,14 @@ async function run(options: RunOptions = {}) {
|
||||
|
||||
await initializeClaudeConfig();
|
||||
await initDir();
|
||||
// Clean up old log files, keeping only the 10 most recent ones
|
||||
await cleanupLogFiles();
|
||||
const config = await initConfig();
|
||||
let HOST = config.HOST;
|
||||
|
||||
if (config.HOST && !config.APIKEY) {
|
||||
HOST = "127.0.0.1";
|
||||
console.warn(
|
||||
"⚠️ API key is not set. HOST is forced to 127.0.0.1."
|
||||
);
|
||||
console.warn("⚠️ API key is not set. HOST is forced to 127.0.0.1.");
|
||||
}
|
||||
|
||||
const port = config.PORT || 3456;
|
||||
@@ -73,12 +75,15 @@ async function run(options: RunOptions = {}) {
|
||||
cleanupPidFile();
|
||||
process.exit(0);
|
||||
});
|
||||
console.log(HOST)
|
||||
console.log(HOST);
|
||||
|
||||
// Use port from environment variable if set (for background process)
|
||||
const servicePort = process.env.SERVICE_PORT
|
||||
? parseInt(process.env.SERVICE_PORT)
|
||||
: port;
|
||||
|
||||
const startTime = new Date().toISOString();
|
||||
|
||||
const server = createServer({
|
||||
jsonPath: CONFIG_FILE,
|
||||
initialConfig: {
|
||||
@@ -92,6 +97,15 @@ async function run(options: RunOptions = {}) {
|
||||
"claude-code-router.log"
|
||||
),
|
||||
},
|
||||
logger: {
|
||||
level: "debug",
|
||||
stream: createWriteStream({
|
||||
path: HOME_DIR,
|
||||
filename: `./logs/ccr-${startTime}.log`,
|
||||
maxFiles: 3,
|
||||
interval: "1d",
|
||||
}),
|
||||
},
|
||||
});
|
||||
// Add async preHandler hook for authentication
|
||||
server.addHook("preHandler", async (req, reply) => {
|
||||
@@ -105,8 +119,8 @@ async function run(options: RunOptions = {}) {
|
||||
});
|
||||
});
|
||||
server.addHook("preHandler", async (req, reply) => {
|
||||
if(req.url.startsWith("/v1/messages")) {
|
||||
router(req, reply, config)
|
||||
if (req.url.startsWith("/v1/messages")) {
|
||||
router(req, reply, config);
|
||||
}
|
||||
});
|
||||
server.start();
|
||||
|
||||
@@ -9,6 +9,7 @@ import {
|
||||
PLUGINS_DIR,
|
||||
} from "../constants";
|
||||
import { getSystemUUID, generateTempAPIKey, getTempAPIKey } from "./systemUUID";
|
||||
import { cleanupLogFiles } from "./logCleanup";
|
||||
|
||||
const ensureDir = async (dir_path: string) => {
|
||||
try {
|
||||
@@ -139,3 +140,6 @@ export const initConfig = async () => {
|
||||
|
||||
// 导出系统UUID相关函数
|
||||
export { getSystemUUID, generateTempAPIKey, getTempAPIKey };
|
||||
|
||||
// 导出日志清理函数
|
||||
export { cleanupLogFiles };
|
||||
|
||||
44
src/utils/logCleanup.ts
Normal file
44
src/utils/logCleanup.ts
Normal file
@@ -0,0 +1,44 @@
|
||||
import fs from "node:fs/promises";
|
||||
import path from "node:path";
|
||||
import { HOME_DIR } from "../constants";
|
||||
|
||||
/**
|
||||
* Cleans up old log files, keeping only the most recent ones
|
||||
* @param maxFiles - Maximum number of log files to keep (default: 9)
|
||||
*/
|
||||
export async function cleanupLogFiles(maxFiles: number = 9): Promise<void> {
|
||||
try {
|
||||
const logsDir = path.join(HOME_DIR, "logs");
|
||||
|
||||
// Check if logs directory exists
|
||||
try {
|
||||
await fs.access(logsDir);
|
||||
} catch {
|
||||
// Logs directory doesn't exist, nothing to clean up
|
||||
return;
|
||||
}
|
||||
|
||||
// Read all files in the logs directory
|
||||
const files = await fs.readdir(logsDir);
|
||||
|
||||
// Filter for log files (files starting with 'ccr-' and ending with '.log')
|
||||
const logFiles = files
|
||||
.filter(file => file.startsWith('ccr-') && file.endsWith('.log'))
|
||||
.sort()
|
||||
.reverse(); // Sort in descending order (newest first)
|
||||
|
||||
// Delete files exceeding the maxFiles limit
|
||||
if (logFiles.length > maxFiles) {
|
||||
for (let i = maxFiles; i < logFiles.length; i++) {
|
||||
const filePath = path.join(logsDir, logFiles[i]);
|
||||
try {
|
||||
await fs.unlink(filePath);
|
||||
} catch (error) {
|
||||
console.warn(`Failed to delete log file ${filePath}:`, error);
|
||||
}
|
||||
}
|
||||
}
|
||||
} catch (error) {
|
||||
console.warn("Failed to clean up log files:", error);
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user