@musistudio/claude-code-router 1.0.55 → 1.0.57

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/README.md CHANGED
@@ -587,5 +587,7 @@ A huge thank you to all our sponsors for their generous support!
587
587
  - @\*霄
588
588
  - @\*\*吉
589
589
  - @\*\*飞
590
+ - @\*\*驰
591
+ - @x\*g
590
592
 
591
593
  (If your name is masked, please contact me via my homepage email to update it with your GitHub username.)
package/README_zh.md CHANGED
@@ -560,6 +560,8 @@ jobs:
560
560
  - @\*霄
561
561
  - @\*\*吉
562
562
  - @\*\*飞
563
+ - @\*\*驰
564
+ - @x\*g
563
565
 
564
566
  (如果您的名字被屏蔽,请通过我的主页电子邮件与我联系,以便使用您的 GitHub 用户名进行更新。)
565
567
 
package/dist/cli.js CHANGED
@@ -67229,60 +67229,6 @@ var require_static = __commonJS({
67229
67229
  }
67230
67230
  });
67231
67231
 
67232
- // package.json
67233
- var require_package3 = __commonJS({
67234
- "package.json"(exports2, module2) {
67235
- module2.exports = {
67236
- name: "@musistudio/claude-code-router",
67237
- version: "1.0.55",
67238
- description: "Use Claude Code without an Anthropics account and route it to another LLM provider",
67239
- bin: {
67240
- ccr: "dist/cli.js"
67241
- },
67242
- scripts: {
67243
- build: "node scripts/build.js",
67244
- release: "npm run build && npm publish"
67245
- },
67246
- keywords: [
67247
- "claude",
67248
- "code",
67249
- "router",
67250
- "llm",
67251
- "anthropic"
67252
- ],
67253
- author: "musistudio",
67254
- license: "MIT",
67255
- dependencies: {
67256
- "@fastify/static": "^8.2.0",
67257
- "@musistudio/llms": "^1.0.35",
67258
- dotenv: "^16.4.7",
67259
- "find-process": "^2.0.0",
67260
- json5: "^2.2.3",
67261
- minimist: "^1.2.8",
67262
- openurl: "^1.1.1",
67263
- "rotating-file-stream": "^3.2.7",
67264
- "shell-quote": "^1.8.3",
67265
- tiktoken: "^1.0.21",
67266
- uuid: "^11.1.0"
67267
- },
67268
- devDependencies: {
67269
- "@types/node": "^24.0.15",
67270
- esbuild: "^0.25.1",
67271
- fastify: "^5.4.0",
67272
- shx: "^0.4.0",
67273
- typescript: "^5.8.2"
67274
- },
67275
- publishConfig: {
67276
- ignore: [
67277
- "!build/",
67278
- "src/",
67279
- "screenshots/"
67280
- ]
67281
- }
67282
- };
67283
- }
67284
- });
67285
-
67286
67232
  // node_modules/.pnpm/tiktoken@1.0.22/node_modules/tiktoken/tiktoken_bg.cjs
67287
67233
  var require_tiktoken_bg = __commonJS({
67288
67234
  "node_modules/.pnpm/tiktoken@1.0.22/node_modules/tiktoken/tiktoken_bg.cjs"(exports2, module2) {
@@ -67742,6 +67688,60 @@ var require_tiktoken = __commonJS({
67742
67688
  }
67743
67689
  });
67744
67690
 
67691
+ // package.json
67692
+ var require_package3 = __commonJS({
67693
+ "package.json"(exports2, module2) {
67694
+ module2.exports = {
67695
+ name: "@musistudio/claude-code-router",
67696
+ version: "1.0.57",
67697
+ description: "Use Claude Code without an Anthropics account and route it to another LLM provider",
67698
+ bin: {
67699
+ ccr: "dist/cli.js"
67700
+ },
67701
+ scripts: {
67702
+ build: "node scripts/build.js",
67703
+ release: "npm run build && npm publish"
67704
+ },
67705
+ keywords: [
67706
+ "claude",
67707
+ "code",
67708
+ "router",
67709
+ "llm",
67710
+ "anthropic"
67711
+ ],
67712
+ author: "musistudio",
67713
+ license: "MIT",
67714
+ dependencies: {
67715
+ "@fastify/static": "^8.2.0",
67716
+ "@musistudio/llms": "^1.0.35",
67717
+ dotenv: "^16.4.7",
67718
+ "find-process": "^2.0.0",
67719
+ json5: "^2.2.3",
67720
+ minimist: "^1.2.8",
67721
+ openurl: "^1.1.1",
67722
+ "rotating-file-stream": "^3.2.7",
67723
+ "shell-quote": "^1.8.3",
67724
+ tiktoken: "^1.0.21",
67725
+ uuid: "^11.1.0"
67726
+ },
67727
+ devDependencies: {
67728
+ "@types/node": "^24.0.15",
67729
+ esbuild: "^0.25.1",
67730
+ fastify: "^5.4.0",
67731
+ shx: "^0.4.0",
67732
+ typescript: "^5.8.2"
67733
+ },
67734
+ publishConfig: {
67735
+ ignore: [
67736
+ "!build/",
67737
+ "src/",
67738
+ "screenshots/"
67739
+ ]
67740
+ }
67741
+ };
67742
+ }
67743
+ });
67744
+
67745
67745
  // node_modules/.pnpm/find-process@2.0.0/node_modules/find-process/dist/utils.js
67746
67746
  var require_utils3 = __commonJS({
67747
67747
  "node_modules/.pnpm/find-process@2.0.0/node_modules/find-process/dist/utils.js"(exports2) {
@@ -80401,142 +80401,6 @@ var import_path2 = require("path");
80401
80401
  var import_static = __toESM(require_static());
80402
80402
  var import_fs2 = require("fs");
80403
80403
  var import_os = require("os");
80404
- var createServer = (config) => {
80405
- const server = new fR(config);
80406
- server.app.get("/api/config", async (req, reply) => {
80407
- return await readConfigFile();
80408
- });
80409
- server.app.get("/api/transformers", async () => {
80410
- const transformers = server.app._server.transformerService.getAllTransformers();
80411
- const transformerList = Array.from(transformers.entries()).map(
80412
- ([name, transformer]) => ({
80413
- name,
80414
- endpoint: transformer.endPoint || null
80415
- })
80416
- );
80417
- return { transformers: transformerList };
80418
- });
80419
- server.app.post("/api/config", async (req, reply) => {
80420
- const newConfig = req.body;
80421
- const backupPath = await backupConfigFile();
80422
- if (backupPath) {
80423
- console.log(`Backed up existing configuration file to ${backupPath}`);
80424
- }
80425
- await writeConfigFile(newConfig);
80426
- return { success: true, message: "Config saved successfully" };
80427
- });
80428
- server.app.post("/api/restart", async (req, reply) => {
80429
- reply.send({ success: true, message: "Service restart initiated" });
80430
- setTimeout(() => {
80431
- const { spawn: spawn3 } = require("child_process");
80432
- spawn3(process.execPath, [process.argv[1], "restart"], {
80433
- detached: true,
80434
- stdio: "ignore"
80435
- });
80436
- }, 1e3);
80437
- });
80438
- server.app.register(import_static.default, {
80439
- root: (0, import_path2.join)(__dirname, "..", "dist"),
80440
- prefix: "/ui/",
80441
- maxAge: "1h"
80442
- });
80443
- server.app.get("/ui", async (_, reply) => {
80444
- return reply.redirect("/ui/");
80445
- });
80446
- server.app.get("/api/update/check", async (req, reply) => {
80447
- try {
80448
- const currentVersion = require_package3().version;
80449
- const { hasUpdate, latestVersion, changelog } = await checkForUpdates(currentVersion);
80450
- return {
80451
- hasUpdate,
80452
- latestVersion: hasUpdate ? latestVersion : void 0,
80453
- changelog: hasUpdate ? changelog : void 0
80454
- };
80455
- } catch (error) {
80456
- console.error("Failed to check for updates:", error);
80457
- reply.status(500).send({ error: "Failed to check for updates" });
80458
- }
80459
- });
80460
- server.app.post("/api/update/perform", async (req, reply) => {
80461
- try {
80462
- const accessLevel = req.accessLevel || "restricted";
80463
- if (accessLevel !== "full") {
80464
- reply.status(403).send("Full access required to perform updates");
80465
- return;
80466
- }
80467
- const result = await performUpdate();
80468
- return result;
80469
- } catch (error) {
80470
- console.error("Failed to perform update:", error);
80471
- reply.status(500).send({ error: "Failed to perform update" });
80472
- }
80473
- });
80474
- server.app.get("/api/logs/files", async (req, reply) => {
80475
- try {
80476
- const logDir = (0, import_path2.join)((0, import_os.homedir)(), ".claude-code-router", "logs");
80477
- const logFiles = [];
80478
- if ((0, import_fs2.existsSync)(logDir)) {
80479
- const files = (0, import_fs2.readdirSync)(logDir);
80480
- for (const file of files) {
80481
- if (file.endsWith(".log")) {
80482
- const filePath = (0, import_path2.join)(logDir, file);
80483
- const stats = (0, import_fs2.statSync)(filePath);
80484
- logFiles.push({
80485
- name: file,
80486
- path: filePath,
80487
- size: stats.size,
80488
- lastModified: stats.mtime.toISOString()
80489
- });
80490
- }
80491
- }
80492
- logFiles.sort((a, b) => new Date(b.lastModified).getTime() - new Date(a.lastModified).getTime());
80493
- }
80494
- return logFiles;
80495
- } catch (error) {
80496
- console.error("Failed to get log files:", error);
80497
- reply.status(500).send({ error: "Failed to get log files" });
80498
- }
80499
- });
80500
- server.app.get("/api/logs", async (req, reply) => {
80501
- try {
80502
- const filePath = req.query.file;
80503
- let logFilePath;
80504
- if (filePath) {
80505
- logFilePath = filePath;
80506
- } else {
80507
- logFilePath = (0, import_path2.join)((0, import_os.homedir)(), ".claude-code-router", "logs", "app.log");
80508
- }
80509
- if (!(0, import_fs2.existsSync)(logFilePath)) {
80510
- return [];
80511
- }
80512
- const logContent = (0, import_fs2.readFileSync)(logFilePath, "utf8");
80513
- const logLines = logContent.split("\n").filter((line) => line.trim());
80514
- return logLines;
80515
- } catch (error) {
80516
- console.error("Failed to get logs:", error);
80517
- reply.status(500).send({ error: "Failed to get logs" });
80518
- }
80519
- });
80520
- server.app.delete("/api/logs", async (req, reply) => {
80521
- try {
80522
- const filePath = req.query.file;
80523
- let logFilePath;
80524
- if (filePath) {
80525
- logFilePath = filePath;
80526
- } else {
80527
- logFilePath = (0, import_path2.join)((0, import_os.homedir)(), ".claude-code-router", "logs", "app.log");
80528
- }
80529
- if ((0, import_fs2.existsSync)(logFilePath)) {
80530
- (0, import_fs2.writeFileSync)(logFilePath, "", "utf8");
80531
- }
80532
- return { success: true, message: "Logs cleared successfully" };
80533
- } catch (error) {
80534
- console.error("Failed to clear logs:", error);
80535
- reply.status(500).send({ error: "Failed to clear logs" });
80536
- }
80537
- });
80538
- return server;
80539
- };
80540
80404
 
80541
80405
  // src/utils/router.ts
80542
80406
  var import_tiktoken = __toESM(require_tiktoken());
@@ -80716,6 +80580,149 @@ var router = async (req, _res, context) => {
80716
80580
  return;
80717
80581
  };
80718
80582
 
80583
+ // src/server.ts
80584
+ var createServer = (config) => {
80585
+ const server = new fR(config);
80586
+ server.app.post("/v1/messages/count_tokens", async (req, reply) => {
80587
+ const { messages, tools, system } = req.body;
80588
+ const tokenCount = calculateTokenCount(messages, system, tools);
80589
+ return { "input_tokens": tokenCount };
80590
+ });
80591
+ server.app.get("/api/config", async (req, reply) => {
80592
+ return await readConfigFile();
80593
+ });
80594
+ server.app.get("/api/transformers", async () => {
80595
+ const transformers = server.app._server.transformerService.getAllTransformers();
80596
+ const transformerList = Array.from(transformers.entries()).map(
80597
+ ([name, transformer]) => ({
80598
+ name,
80599
+ endpoint: transformer.endPoint || null
80600
+ })
80601
+ );
80602
+ return { transformers: transformerList };
80603
+ });
80604
+ server.app.post("/api/config", async (req, reply) => {
80605
+ const newConfig = req.body;
80606
+ const backupPath = await backupConfigFile();
80607
+ if (backupPath) {
80608
+ console.log(`Backed up existing configuration file to ${backupPath}`);
80609
+ }
80610
+ await writeConfigFile(newConfig);
80611
+ return { success: true, message: "Config saved successfully" };
80612
+ });
80613
+ server.app.post("/api/restart", async (req, reply) => {
80614
+ reply.send({ success: true, message: "Service restart initiated" });
80615
+ setTimeout(() => {
80616
+ const { spawn: spawn3 } = require("child_process");
80617
+ spawn3(process.execPath, [process.argv[1], "restart"], {
80618
+ detached: true,
80619
+ stdio: "ignore"
80620
+ });
80621
+ }, 1e3);
80622
+ });
80623
+ server.app.register(import_static.default, {
80624
+ root: (0, import_path2.join)(__dirname, "..", "dist"),
80625
+ prefix: "/ui/",
80626
+ maxAge: "1h"
80627
+ });
80628
+ server.app.get("/ui", async (_, reply) => {
80629
+ return reply.redirect("/ui/");
80630
+ });
80631
+ server.app.get("/api/update/check", async (req, reply) => {
80632
+ try {
80633
+ const currentVersion = require_package3().version;
80634
+ const { hasUpdate, latestVersion, changelog } = await checkForUpdates(currentVersion);
80635
+ return {
80636
+ hasUpdate,
80637
+ latestVersion: hasUpdate ? latestVersion : void 0,
80638
+ changelog: hasUpdate ? changelog : void 0
80639
+ };
80640
+ } catch (error) {
80641
+ console.error("Failed to check for updates:", error);
80642
+ reply.status(500).send({ error: "Failed to check for updates" });
80643
+ }
80644
+ });
80645
+ server.app.post("/api/update/perform", async (req, reply) => {
80646
+ try {
80647
+ const accessLevel = req.accessLevel || "restricted";
80648
+ if (accessLevel !== "full") {
80649
+ reply.status(403).send("Full access required to perform updates");
80650
+ return;
80651
+ }
80652
+ const result = await performUpdate();
80653
+ return result;
80654
+ } catch (error) {
80655
+ console.error("Failed to perform update:", error);
80656
+ reply.status(500).send({ error: "Failed to perform update" });
80657
+ }
80658
+ });
80659
+ server.app.get("/api/logs/files", async (req, reply) => {
80660
+ try {
80661
+ const logDir = (0, import_path2.join)((0, import_os.homedir)(), ".claude-code-router", "logs");
80662
+ const logFiles = [];
80663
+ if ((0, import_fs2.existsSync)(logDir)) {
80664
+ const files = (0, import_fs2.readdirSync)(logDir);
80665
+ for (const file of files) {
80666
+ if (file.endsWith(".log")) {
80667
+ const filePath = (0, import_path2.join)(logDir, file);
80668
+ const stats = (0, import_fs2.statSync)(filePath);
80669
+ logFiles.push({
80670
+ name: file,
80671
+ path: filePath,
80672
+ size: stats.size,
80673
+ lastModified: stats.mtime.toISOString()
80674
+ });
80675
+ }
80676
+ }
80677
+ logFiles.sort((a, b) => new Date(b.lastModified).getTime() - new Date(a.lastModified).getTime());
80678
+ }
80679
+ return logFiles;
80680
+ } catch (error) {
80681
+ console.error("Failed to get log files:", error);
80682
+ reply.status(500).send({ error: "Failed to get log files" });
80683
+ }
80684
+ });
80685
+ server.app.get("/api/logs", async (req, reply) => {
80686
+ try {
80687
+ const filePath = req.query.file;
80688
+ let logFilePath;
80689
+ if (filePath) {
80690
+ logFilePath = filePath;
80691
+ } else {
80692
+ logFilePath = (0, import_path2.join)((0, import_os.homedir)(), ".claude-code-router", "logs", "app.log");
80693
+ }
80694
+ if (!(0, import_fs2.existsSync)(logFilePath)) {
80695
+ return [];
80696
+ }
80697
+ const logContent = (0, import_fs2.readFileSync)(logFilePath, "utf8");
80698
+ const logLines = logContent.split("\n").filter((line) => line.trim());
80699
+ return logLines;
80700
+ } catch (error) {
80701
+ console.error("Failed to get logs:", error);
80702
+ reply.status(500).send({ error: "Failed to get logs" });
80703
+ }
80704
+ });
80705
+ server.app.delete("/api/logs", async (req, reply) => {
80706
+ try {
80707
+ const filePath = req.query.file;
80708
+ let logFilePath;
80709
+ if (filePath) {
80710
+ logFilePath = filePath;
80711
+ } else {
80712
+ logFilePath = (0, import_path2.join)((0, import_os.homedir)(), ".claude-code-router", "logs", "app.log");
80713
+ }
80714
+ if ((0, import_fs2.existsSync)(logFilePath)) {
80715
+ (0, import_fs2.writeFileSync)(logFilePath, "", "utf8");
80716
+ }
80717
+ return { success: true, message: "Logs cleared successfully" };
80718
+ } catch (error) {
80719
+ console.error("Failed to clear logs:", error);
80720
+ reply.status(500).send({ error: "Failed to clear logs" });
80721
+ }
80722
+ });
80723
+ return server;
80724
+ };
80725
+
80719
80726
  // src/middleware/auth.ts
80720
80727
  var apiKeyAuth = (config) => async (req, reply, done) => {
80721
80728
  if (["/", "/health"].includes(req.url) || req.url.startsWith("/ui")) {
@@ -83323,7 +83330,7 @@ async function run(options = {}) {
83323
83330
  });
83324
83331
  });
83325
83332
  server.addHook("preHandler", async (req, reply) => {
83326
- if (req.url.startsWith("/v1/messages")) {
83333
+ if (req.url.startsWith("/v1/messages") && !req.url.startsWith("/v1/messages/count_tokens")) {
83327
83334
  const useAgents = [];
83328
83335
  for (const agent of agents_default.getAllAgents()) {
83329
83336
  if (agent.shouldHandle(req, config)) {
@@ -83356,7 +83363,7 @@ async function run(options = {}) {
83356
83363
  event.emit("onError", request, reply, error);
83357
83364
  });
83358
83365
  server.addHook("onSend", (req, reply, payload, done) => {
83359
- if (req.sessionId && req.url.startsWith("/v1/messages")) {
83366
+ if (req.sessionId && req.url.startsWith("/v1/messages") && !req.url.startsWith("/v1/messages/count_tokens")) {
83360
83367
  if (payload instanceof ReadableStream) {
83361
83368
  if (req.agents) {
83362
83369
  const abortController = new AbortController();
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@musistudio/claude-code-router",
3
- "version": "1.0.55",
3
+ "version": "1.0.57",
4
4
  "description": "Use Claude Code without an Anthropics account and route it to another LLM provider",
5
5
  "bin": {
6
6
  "ccr": "dist/cli.js"