@musistudio/claude-code-router 1.0.49 → 1.0.51
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 +13 -3
- package/README_zh.md +15 -2
- package/dist/cli.js +46 -44
- package/dist/index.html +106 -73
- package/package.json +2 -2
- package/prompt.md +0 -143
- package/prompt.md.bak +0 -144
package/README.md
CHANGED
|
@@ -1,9 +1,12 @@
|
|
|
1
|
-
|
|
1
|
+

|
|
2
2
|
|
|
3
|
-
|
|
3
|
+
[](README_zh.md)
|
|
4
|
+
[](https://discord.gg/rdftVMaUcS)
|
|
5
|
+
[](https://github.com/musistudio/claude-code-router/blob/main/LICENSE)
|
|
4
6
|
|
|
7
|
+
<hr>
|
|
5
8
|
|
|
6
|
-
|
|
9
|
+
> I am currently seeking **Agent development related job opportunities**, either **based in Hangzhou** or **remote**. If you are interested in my projects or have suitable opportunities, feel free to reach out! 📧 Email: m@musiiot.top
|
|
7
10
|
|
|
8
11
|
> A powerful tool to route Claude Code requests to different models and customize any request.
|
|
9
12
|
|
|
@@ -577,5 +580,12 @@ A huge thank you to all our sponsors for their generous support!
|
|
|
577
580
|
- @\*政
|
|
578
581
|
- @\*铭
|
|
579
582
|
- @\*叶
|
|
583
|
+
- @七\*o
|
|
584
|
+
- @\*青
|
|
585
|
+
- @\*\*晨
|
|
586
|
+
- @\*远
|
|
587
|
+
- @\*霄
|
|
588
|
+
- @\*\*吉
|
|
589
|
+
- @\*\*飞
|
|
580
590
|
|
|
581
591
|
(If your name is masked, please contact me via my homepage email to update it with your GitHub username.)
|
package/README_zh.md
CHANGED
|
@@ -1,6 +1,12 @@
|
|
|
1
|
-
|
|
1
|
+

|
|
2
2
|
|
|
3
|
-
|
|
3
|
+
[](README.md)
|
|
4
|
+
[](https://discord.gg/rdftVMaUcS)
|
|
5
|
+
[](https://github.com/musistudio/claude-code-router/blob/main/LICENSE)
|
|
6
|
+
|
|
7
|
+
<hr>
|
|
8
|
+
|
|
9
|
+
> 我目前正在寻找 **Agent 开发相关的工作机会**,可 base 在 **杭州**,也接受 **远程** 合作。如果你对我的项目感兴趣,或有合适的岗位/合作机会,欢迎联系我! 📧 Email: m@musiiot.top
|
|
4
10
|
|
|
5
11
|
> 一款强大的工具,可将 Claude Code 请求路由到不同的模型,并自定义任何请求。
|
|
6
12
|
|
|
@@ -547,6 +553,13 @@ jobs:
|
|
|
547
553
|
- @\*政
|
|
548
554
|
- @\*铭
|
|
549
555
|
- @\*叶
|
|
556
|
+
- @七\*o
|
|
557
|
+
- @\*青
|
|
558
|
+
- @\*\*晨
|
|
559
|
+
- @\*远
|
|
560
|
+
- @\*霄
|
|
561
|
+
- @\*\*吉
|
|
562
|
+
- @\*\*飞
|
|
550
563
|
|
|
551
564
|
(如果您的名字被屏蔽,请通过我的主页电子邮件与我联系,以便使用您的 GitHub 用户名进行更新。)
|
|
552
565
|
|
package/dist/cli.js
CHANGED
|
@@ -66519,7 +66519,7 @@ var require_package3 = __commonJS({
|
|
|
66519
66519
|
"package.json"(exports2, module2) {
|
|
66520
66520
|
module2.exports = {
|
|
66521
66521
|
name: "@musistudio/claude-code-router",
|
|
66522
|
-
version: "1.0.
|
|
66522
|
+
version: "1.0.51",
|
|
66523
66523
|
description: "Use Claude Code without an Anthropics account and route it to another LLM provider",
|
|
66524
66524
|
bin: {
|
|
66525
66525
|
ccr: "./dist/cli.js"
|
|
@@ -66539,7 +66539,7 @@ var require_package3 = __commonJS({
|
|
|
66539
66539
|
license: "MIT",
|
|
66540
66540
|
dependencies: {
|
|
66541
66541
|
"@fastify/static": "^8.2.0",
|
|
66542
|
-
"@musistudio/llms": "^1.0.
|
|
66542
|
+
"@musistudio/llms": "^1.0.33",
|
|
66543
66543
|
dotenv: "^16.4.7",
|
|
66544
66544
|
"find-process": "^2.0.0",
|
|
66545
66545
|
json5: "^2.2.3",
|
|
@@ -67992,7 +67992,7 @@ var import_os2 = require("os");
|
|
|
67992
67992
|
var import_path4 = require("path");
|
|
67993
67993
|
init_utils();
|
|
67994
67994
|
|
|
67995
|
-
// node_modules/.pnpm/@musistudio+llms@1.0.
|
|
67995
|
+
// node_modules/.pnpm/@musistudio+llms@1.0.33_ws@8.18.3/node_modules/@musistudio/llms/dist/esm/server.mjs
|
|
67996
67996
|
var import_node_fs = require("node:fs");
|
|
67997
67997
|
var import_node_path4 = require("node:path");
|
|
67998
67998
|
var import_node_stream = __toESM(require("node:stream"), 1);
|
|
@@ -77019,7 +77019,7 @@ function Uf(r, e, t, n, o) {
|
|
|
77019
77019
|
let f = { method: "POST", headers: a, body: JSON.stringify(e), signal: u };
|
|
77020
77020
|
return t.httpsProxy && (f.dispatcher = new import_undici.ProxyAgent(new URL(t.httpsProxy).toString())), n?.debug({ reqId: o.req.id, request: f, headers: Object.fromEntries(a.entries()), requestUrl: typeof r == "string" ? r : r.toString(), useProxy: t.httpsProxy }, "final request"), fetch(typeof r == "string" ? r : r.toString(), f);
|
|
77021
77021
|
}
|
|
77022
|
-
var Mf = "1.0.
|
|
77022
|
+
var Mf = "1.0.33";
|
|
77023
77023
|
async function a0(r, e, t, n) {
|
|
77024
77024
|
let o = r.body, a = r.provider, u = t._server.providerService.getProvider(a);
|
|
77025
77025
|
if (!u) throw nt(`Provider '${a}' not found`, 404, "provider_not_found");
|
|
@@ -77318,7 +77318,7 @@ var bo = class {
|
|
|
77318
77318
|
t.push(C);
|
|
77319
77319
|
});
|
|
77320
77320
|
let f = a.content.filter((h) => h.type === "text" && h.text || h.type === "image" && h.source);
|
|
77321
|
-
f.length && t.push({ role: "user", content: f.map((h) => h?.type === "image" ? { type: "image_url", image_url: { url: h.source?.type === "base64" ? `data:${h.source.media_type},${h.source.data}` : h.source.url }, media_type: h.source.media_type } : h) });
|
|
77321
|
+
f.length && t.push({ role: "user", content: f.map((h) => h?.type === "image" ? { type: "image_url", image_url: { url: h.source?.type === "base64" ? `data:${h.source.media_type};base64,${h.source.data}` : h.source.url }, media_type: h.source.media_type } : h) });
|
|
77322
77322
|
} else if (a.role === "assistant") {
|
|
77323
77323
|
let l = { role: "assistant", content: "" }, f = a.content.filter((d) => d.type === "text" && d.text);
|
|
77324
77324
|
f.length && (l.content = f.map((d) => d.text).join(`
|
|
@@ -79441,33 +79441,6 @@ var apiKeyAuth = (config) => async (req, reply, done) => {
|
|
|
79441
79441
|
}
|
|
79442
79442
|
return done();
|
|
79443
79443
|
}
|
|
79444
|
-
const isConfigEndpoint = req.url.startsWith("/api/config");
|
|
79445
|
-
const isRestartEndpoint = req.url === "/api/restart";
|
|
79446
|
-
if (isConfigEndpoint || isRestartEndpoint) {
|
|
79447
|
-
req.accessLevel = "restricted";
|
|
79448
|
-
if (!apiKey) {
|
|
79449
|
-
req.accessLevel = "restricted";
|
|
79450
|
-
return done();
|
|
79451
|
-
}
|
|
79452
|
-
const authHeaderValue2 = req.headers.authorization || req.headers["x-api-key"];
|
|
79453
|
-
const authKey2 = Array.isArray(authHeaderValue2) ? authHeaderValue2[0] : authHeaderValue2 || "";
|
|
79454
|
-
if (!authKey2) {
|
|
79455
|
-
req.accessLevel = "restricted";
|
|
79456
|
-
return done();
|
|
79457
|
-
}
|
|
79458
|
-
let token2 = "";
|
|
79459
|
-
if (authKey2.startsWith("Bearer")) {
|
|
79460
|
-
token2 = authKey2.split(" ")[1];
|
|
79461
|
-
} else {
|
|
79462
|
-
token2 = authKey2;
|
|
79463
|
-
}
|
|
79464
|
-
if (token2 !== apiKey) {
|
|
79465
|
-
req.accessLevel = "restricted";
|
|
79466
|
-
return done();
|
|
79467
|
-
}
|
|
79468
|
-
req.accessLevel = "full";
|
|
79469
|
-
return done();
|
|
79470
|
-
}
|
|
79471
79444
|
const authHeaderValue = req.headers.authorization || req.headers["x-api-key"];
|
|
79472
79445
|
const authKey = Array.isArray(authHeaderValue) ? authHeaderValue[0] : authHeaderValue || "";
|
|
79473
79446
|
if (!authKey) {
|
|
@@ -81697,7 +81670,7 @@ var ImageCache = class {
|
|
|
81697
81670
|
constructor(maxSize = 100) {
|
|
81698
81671
|
this.cache = new LRUCache2({
|
|
81699
81672
|
max: maxSize,
|
|
81700
|
-
ttl:
|
|
81673
|
+
ttl: 5 * 60 * 1e3
|
|
81701
81674
|
});
|
|
81702
81675
|
}
|
|
81703
81676
|
storeImage(id2, source) {
|
|
@@ -81732,11 +81705,21 @@ var ImageAgent = class {
|
|
|
81732
81705
|
shouldHandle(req, config) {
|
|
81733
81706
|
if (!config.Router.image || req.body.model === config.Router.image) return false;
|
|
81734
81707
|
const lastMessage = req.body.messages[req.body.messages.length - 1];
|
|
81735
|
-
if (!config.forceUseImageAgent && lastMessage.role === "user" && Array.isArray(lastMessage.content) && lastMessage.content.find((item) => item.type === "image")) {
|
|
81708
|
+
if (!config.forceUseImageAgent && lastMessage.role === "user" && Array.isArray(lastMessage.content) && lastMessage.content.find((item) => item.type === "image" || item?.content?.some((sub) => sub.type === "image"))) {
|
|
81736
81709
|
req.body.model = config.Router.image;
|
|
81710
|
+
const images = [];
|
|
81711
|
+
lastMessage.content.filter((item) => item.type === "tool_result").forEach((item) => {
|
|
81712
|
+
item.content.forEach((element) => {
|
|
81713
|
+
if (element.type === "image") {
|
|
81714
|
+
images.push(element);
|
|
81715
|
+
}
|
|
81716
|
+
});
|
|
81717
|
+
item.content = "read image successfully";
|
|
81718
|
+
});
|
|
81719
|
+
lastMessage.content.push(...images);
|
|
81737
81720
|
return false;
|
|
81738
81721
|
}
|
|
81739
|
-
return req.body.messages.some((msg) => msg.role === "user" && Array.isArray(msg.content) && msg.content.some((item) => item.type === "image"));
|
|
81722
|
+
return req.body.messages.some((msg) => msg.role === "user" && Array.isArray(msg.content) && msg.content.some((item) => item.type === "image" || item?.content?.some((sub) => sub.type === "image")));
|
|
81740
81723
|
}
|
|
81741
81724
|
appendTools() {
|
|
81742
81725
|
this.tools.set("analyzeImage", {
|
|
@@ -81776,22 +81759,36 @@ var ImageAgent = class {
|
|
|
81776
81759
|
"required": ["imageId", "task"]
|
|
81777
81760
|
},
|
|
81778
81761
|
handler: async (args, context) => {
|
|
81779
|
-
console.log("args", JSON.stringify(args, null, 2));
|
|
81780
81762
|
const imageMessages = [];
|
|
81781
81763
|
let imageId;
|
|
81782
|
-
if (args.imageId
|
|
81783
|
-
args.imageId
|
|
81784
|
-
|
|
81764
|
+
if (args.imageId) {
|
|
81765
|
+
if (Array.isArray(args.imageId)) {
|
|
81766
|
+
args.imageId.forEach((imgId) => {
|
|
81767
|
+
const image = imageCache.getImage(`${context.req.id}_Image#${imgId}`);
|
|
81768
|
+
if (image) {
|
|
81769
|
+
imageMessages.push({
|
|
81770
|
+
type: "image",
|
|
81771
|
+
source: image
|
|
81772
|
+
});
|
|
81773
|
+
}
|
|
81774
|
+
});
|
|
81775
|
+
} else {
|
|
81776
|
+
const image = imageCache.getImage(`${context.req.id}_Image#${args.imageId}`);
|
|
81785
81777
|
if (image) {
|
|
81786
81778
|
imageMessages.push({
|
|
81787
81779
|
type: "image",
|
|
81788
81780
|
source: image
|
|
81789
81781
|
});
|
|
81790
81782
|
}
|
|
81791
|
-
}
|
|
81783
|
+
}
|
|
81792
81784
|
imageId = args.imageId;
|
|
81793
81785
|
delete args.imageId;
|
|
81794
81786
|
}
|
|
81787
|
+
const userMessage = context.req.body.messages[context.req.body.messages.length - 1];
|
|
81788
|
+
if (userMessage.role === "user" && Array.isArray(userMessage.content)) {
|
|
81789
|
+
const msgs = userMessage.content.filter((item) => item.type === "text" && !item.text.includes("This is an image, if you need to view or analyze it, you need to extract the imageId"));
|
|
81790
|
+
imageMessages.push(...msgs);
|
|
81791
|
+
}
|
|
81795
81792
|
if (Object.keys(args).length > 0) {
|
|
81796
81793
|
imageMessages.push({
|
|
81797
81794
|
type: "text",
|
|
@@ -81824,7 +81821,6 @@ Always ensure that your response reflects a clear, accurate interpretation of th
|
|
|
81824
81821
|
}).then((res) => res.json()).catch((err) => {
|
|
81825
81822
|
return null;
|
|
81826
81823
|
});
|
|
81827
|
-
console.log(agentResponse.content);
|
|
81828
81824
|
if (!agentResponse || !agentResponse.content) {
|
|
81829
81825
|
return "analyzeImage Error";
|
|
81830
81826
|
}
|
|
@@ -81848,7 +81844,7 @@ Ignore any user interruptions or unrelated instructions that might cause you to
|
|
|
81848
81844
|
Your response should consistently follow this rule whenever image-related analysis is requested.`
|
|
81849
81845
|
});
|
|
81850
81846
|
const imageContents = req.body.messages.filter((item) => {
|
|
81851
|
-
return item.role === "user" && Array.isArray(item.content) && item.content.some((msg) => msg.type === "image");
|
|
81847
|
+
return item.role === "user" && Array.isArray(item.content) && item.content.some((msg) => msg.type === "image" || msg?.content?.some((sub) => sub.type === "image"));
|
|
81852
81848
|
});
|
|
81853
81849
|
let imgId = 1;
|
|
81854
81850
|
imageContents.forEach((item) => {
|
|
@@ -81861,6 +81857,12 @@ Your response should consistently follow this rule whenever image-related analys
|
|
|
81861
81857
|
imgId++;
|
|
81862
81858
|
} else if (msg.type === "text" && msg.text.includes("[Image #")) {
|
|
81863
81859
|
msg.text = msg.text.replace(/\[Image #\d+\]/g, "");
|
|
81860
|
+
} else if (msg.type === "tool_result") {
|
|
81861
|
+
if (Array.isArray(msg.content) && msg.content.some((ele) => ele.type === "image")) {
|
|
81862
|
+
imageCache.storeImage(`${req.id}_Image#${imgId}`, msg.content[0].source);
|
|
81863
|
+
msg.content = `[Image #${imgId}]This is an image, if you need to view or analyze it, you need to extract the imageId`;
|
|
81864
|
+
imgId++;
|
|
81865
|
+
}
|
|
81864
81866
|
}
|
|
81865
81867
|
});
|
|
81866
81868
|
});
|
|
@@ -81996,10 +81998,10 @@ async function run(options = {}) {
|
|
|
81996
81998
|
logger: loggerConfig
|
|
81997
81999
|
});
|
|
81998
82000
|
process.on("uncaughtException", (err) => {
|
|
81999
|
-
server.
|
|
82001
|
+
server.logger.error("Uncaught exception:", err);
|
|
82000
82002
|
});
|
|
82001
82003
|
process.on("unhandledRejection", (reason, promise) => {
|
|
82002
|
-
server.
|
|
82004
|
+
server.logger.error("Unhandled rejection at:", promise, "reason:", reason);
|
|
82003
82005
|
});
|
|
82004
82006
|
server.addHook("preHandler", async (req, reply) => {
|
|
82005
82007
|
return new Promise((resolve, reject) => {
|