diff --git a/package.json b/package.json index 871a6b5..87c8390 100644 --- a/package.json +++ b/package.json @@ -20,11 +20,11 @@ "license": "MIT", "dependencies": { "@fastify/static": "^8.2.0", - "@musistudio/llms": "^1.0.30", + "@musistudio/llms": "^1.0.31", "dotenv": "^16.4.7", "json5": "^2.2.3", "openurl": "^1.1.1", - "pino-rotating-file-stream": "^0.0.2", + "rotating-file-stream": "^3.2.7", "tiktoken": "^1.0.21", "uuid": "^11.1.0" }, diff --git a/pnpm-lock.yaml b/pnpm-lock.yaml index 3363332..81ab13d 100644 --- a/pnpm-lock.yaml +++ b/pnpm-lock.yaml @@ -12,8 +12,8 @@ importers: specifier: ^8.2.0 version: 8.2.0 '@musistudio/llms': - specifier: ^1.0.30 - version: 1.0.30(ws@8.18.3) + specifier: ^1.0.31 + version: 1.0.31(ws@8.18.3) dotenv: specifier: ^16.4.7 version: 16.6.1 @@ -23,9 +23,9 @@ importers: openurl: specifier: ^1.1.1 version: 1.1.1 - pino-rotating-file-stream: - specifier: ^0.0.2 - version: 0.0.2 + rotating-file-stream: + specifier: ^3.2.7 + version: 3.2.7 tiktoken: specifier: ^1.0.21 version: 1.0.22 @@ -266,8 +266,8 @@ packages: resolution: {integrity: sha512-9I2Zn6+NJLfaGoz9jN3lpwDgAYvfGeNYdbAIjJOqzs4Tpc+VU3Jqq4IofSUBKajiDS8k9fZIg18/z13mpk1bsA==} engines: {node: '>=8'} - '@musistudio/llms@1.0.30': - resolution: {integrity: sha512-vqeAz+noIm0G53DVDnyyAgv90HxObG/URlPjQE89YQafG10xkRUemHyuyscRgiHKvut9Z0FF0i8m0Uiqat068A==} + '@musistudio/llms@1.0.31': + resolution: {integrity: sha512-zPzGAnpB60g6iGldfxzkzohTbUtrg7y1VnTNORRESnC2Fd/4XiSdIHoaURzp7RJ4hnTYkolDLMfvlmHUmdr9AA==} '@nodelib/fs.scandir@2.1.5': resolution: {integrity: sha512-vq24Bq3ym5HEQm2NKCr3yXDwjc7vTsEThRDnkp2DK9p1uqLR+DHurm/NOTo0KG7HYHU7eppKZj3MyqYuMBf62g==} @@ -716,9 +716,6 @@ 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==} @@ -769,8 +766,8 @@ packages: rfdc@1.4.1: resolution: {integrity: sha512-q1b3N5QkRUWUl7iyylaaj3kOpIT0N2i9MqIEQXP73GVsN9cw3fdx8X63cEmWhJGi2PPCF23Ijp7ktmd39rawIA==} - rotating-file-stream@3.2.6: - resolution: {integrity: sha512-r8yShzMWUvWXkRzbOXDM1fEaMpc3qo2PzK7bBH/0p0Nl/uz8Mud/Y+0XTQxe3kbSnDF7qBH2tSe83WDKA7o3ww==} + rotating-file-stream@3.2.7: + resolution: {integrity: sha512-SVquhBEVvRFY+nWLUc791Y0MIlyZrEClRZwZFLLRgJKldHyV1z4e2e/dp9LPqCS3AM//uq/c3PnOFgjqnm5P+A==} engines: {node: '>=14.0'} run-parallel@1.2.0: @@ -1111,7 +1108,7 @@ snapshots: '@lukeed/ms@2.0.2': {} - '@musistudio/llms@1.0.30(ws@8.18.3)': + '@musistudio/llms@1.0.31(ws@8.18.3)': dependencies: '@anthropic-ai/sdk': 0.54.0 '@fastify/cors': 11.1.0 @@ -1613,10 +1610,6 @@ 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.9.0: @@ -1666,7 +1659,7 @@ snapshots: rfdc@1.4.1: {} - rotating-file-stream@3.2.6: {} + rotating-file-stream@3.2.7: {} run-parallel@1.2.0: dependencies: diff --git a/src/index.ts b/src/index.ts index a971758..c6273db 100644 --- a/src/index.ts +++ b/src/index.ts @@ -12,7 +12,7 @@ import { savePid, } from "./utils/processCheck"; import { CONFIG_FILE } from "./constants"; -import createWriteStream from "pino-rotating-file-stream"; +import { createStream } from 'rotating-file-stream'; import { HOME_DIR } from "./constants"; import { configureLogging } from "./utils/log"; import { sessionUsageCache } from "./utils/cache"; @@ -22,7 +22,9 @@ import {rewriteStream} from "./utils/rewriteStream"; import JSON5 from "json5"; import { IAgent } from "./agents/type"; import agentsManager from "./agents"; +import { EventEmitter } from "node:events"; +const event = new EventEmitter() async function initializeClaudeConfig() { const homeDir = homedir(); @@ -95,15 +97,28 @@ async function run(options: RunOptions = {}) { : port; // Configure logger based on config settings + const pad = num => (num > 9 ? "" : "0") + num; + const generator = (time, index) => { + if (!time) { + time = new Date() + } + + var month = time.getFullYear() + "" + pad(time.getMonth() + 1); + var day = pad(time.getDate()); + var hour = pad(time.getHours()); + var minute = pad(time.getMinutes()); + + return `./logs/ccr-${month}${day}${hour}${minute}${pad(time.getSeconds())}${index ? `_${index}` : ''}.log`; + }; const loggerConfig = config.LOG !== false ? { level: config.LOG_LEVEL || "debug", - stream: createWriteStream({ + stream: createStream(generator, { path: HOME_DIR, - filename: config.LOGNAME || `./logs/ccr-${+new Date()}.log`, maxFiles: 3, interval: "1d", + compress: 'gzip' }), } : false; @@ -165,9 +180,15 @@ async function run(options: RunOptions = {}) { if (useAgents.length) { req.agents = useAgents; } - await router(req, reply, config); + await router(req, reply, { + config, + event + }); } }); + server.addHook("onError", async (request, reply, error) => { + event.emit('onError', request, reply, error); + }) server.addHook("onSend", (req, reply, payload, done) => { if (req.sessionId && req.url.startsWith("/v1/messages")) { if (payload instanceof ReadableStream) { @@ -335,10 +356,16 @@ async function run(options: RunOptions = {}) { sessionUsageCache.put(req.sessionId, payload.usage); } if (typeof payload ==='object' && payload.error) { - done(payload.error, null) + return done(payload.error, null) } done(null, payload) }); + server.addHook("onSend", async (req, reply, payload) => { + console.log('主应用onSend') + event.emit('onSend', req, reply, payload); + return payload; + }) + server.start(); } diff --git a/src/utils/router.ts b/src/utils/router.ts index 5ac1b87..79d939e 100644 --- a/src/utils/router.ts +++ b/src/utils/router.ts @@ -140,7 +140,8 @@ const getUseModel = async ( return config.Router!.default; }; -export const router = async (req: any, _res: any, config: any) => { +export const router = async (req: any, _res: any, context: any) => { + const { config, event } = context; // Parse sessionId from metadata.user_id if (req.body.metadata?.user_id) { const parts = req.body.metadata.user_id.split("_session_"); @@ -162,7 +163,9 @@ export const router = async (req: any, _res: any, config: any) => { try { const customRouter = require(config.CUSTOM_ROUTER_PATH); req.tokenCount = tokenCount; // Pass token count to custom router - model = await customRouter(req, config); + model = await customRouter(req, config, { + event + }); } catch (e: any) { log("failed to load custom router", e.message); }