@musistudio/claude-code-router 1.0.7 → 1.0.9
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 +140 -23
- package/blog/images/alipay.jpg +0 -0
- package/blog/images/wechat.jpg +0 -0
- package/dist/cli.js +109 -74
- package/package.json +1 -1
- package/plugins/notebook-tools-filter.js +7 -0
- package/plugins/toolcall-improvement.js +8 -0
package/README.md
CHANGED
|
@@ -2,7 +2,6 @@
|
|
|
2
2
|
|
|
3
3
|
> This is a tool for routing Claude Code requests to different models, and you can customize any request.
|
|
4
4
|
|
|
5
|
-
|
|
6
5
|

|
|
7
6
|
|
|
8
7
|
## Usage
|
|
@@ -25,8 +24,9 @@ npm install -g @musistudio/claude-code-router
|
|
|
25
24
|
ccr code
|
|
26
25
|
```
|
|
27
26
|
|
|
28
|
-
4. Configure routing[optional]
|
|
29
|
-
Set up your `~/.claude-code-router/config.json` file like this:
|
|
27
|
+
4. Configure routing[optional]
|
|
28
|
+
Set up your `~/.claude-code-router/config.json` file like this:
|
|
29
|
+
|
|
30
30
|
```json
|
|
31
31
|
{
|
|
32
32
|
"OPENAI_API_KEY": "sk-xxx",
|
|
@@ -64,33 +64,135 @@ Set up your `~/.claude-code-router/config.json` file like this:
|
|
|
64
64
|
}
|
|
65
65
|
}
|
|
66
66
|
```
|
|
67
|
-
- `background`
|
|
68
|
-
This model will be used to handle some background tasks([background-token-usage](https://docs.anthropic.com/en/docs/claude-code/costs#background-token-usage)). Based on my tests, it doesn’t require high intelligence. I’m using the qwen-coder-2.5:7b model running locally on my MacBook Pro M1 (32GB) via Ollama.
|
|
69
|
-
If your computer can’t run Ollama, you can also use some free models, such as qwen-coder-2.5:3b.
|
|
70
|
-
|
|
71
|
-
|
|
72
|
-
- `think`
|
|
73
|
-
This model will be used when enabling Claude Code to perform reasoning. However, reasoning budget control has not yet been implemented (since the DeepSeek-R1 model does not support it), so there is currently no difference between using UltraThink and Think modes.
|
|
74
|
-
It is worth noting that Plan Mode also use this model to achieve better planning results.
|
|
75
|
-
Note: The reasoning process via the official DeepSeek API may be very slow, so you may need to wait for an extended period of time.
|
|
76
67
|
|
|
68
|
+
- `background`
|
|
69
|
+
This model will be used to handle some background tasks([background-token-usage](https://docs.anthropic.com/en/docs/claude-code/costs#background-token-usage)). Based on my tests, it doesn’t require high intelligence. I’m using the qwen-coder-2.5:7b model running locally on my MacBook Pro M1 (32GB) via Ollama.
|
|
70
|
+
If your computer can’t run Ollama, you can also use some free models, such as qwen-coder-2.5:3b.
|
|
77
71
|
|
|
78
|
-
- `
|
|
79
|
-
This model will be used when
|
|
72
|
+
- `think`
|
|
73
|
+
This model will be used when enabling Claude Code to perform reasoning. However, reasoning budget control has not yet been implemented (since the DeepSeek-R1 model does not support it), so there is currently no difference between using UltraThink and Think modes.
|
|
74
|
+
It is worth noting that Plan Mode also use this model to achieve better planning results.
|
|
75
|
+
Note: The reasoning process via the official DeepSeek API may be very slow, so you may need to wait for an extended period of time.
|
|
80
76
|
|
|
77
|
+
- `longContext`
|
|
78
|
+
This model will be used when the context length exceeds 32K (this value may be modified in the future). You can route the request to a model that performs well with long contexts (I’ve chosen google/gemini-2.5-pro-preview). This scenario has not been thoroughly tested yet, so if you encounter any issues, please submit an issue.
|
|
81
79
|
|
|
82
|
-
- model command
|
|
83
|
-
You can also switch models within Claude Code by using the `/model` command. The format is: `provider,model`, like this:
|
|
84
|
-
`/model openrouter,anthropic/claude-3.5-sonnet`
|
|
85
|
-
This will use the anthropic/claude-3.5-sonnet model provided by OpenRouter to handle all subsequent tasks.
|
|
80
|
+
- model command
|
|
81
|
+
You can also switch models within Claude Code by using the `/model` command. The format is: `provider,model`, like this:
|
|
82
|
+
`/model openrouter,anthropic/claude-3.5-sonnet`
|
|
83
|
+
This will use the anthropic/claude-3.5-sonnet model provided by OpenRouter to handle all subsequent tasks.
|
|
86
84
|
|
|
87
85
|
## Features
|
|
88
|
-
|
|
86
|
+
|
|
89
87
|
- [x] Support change models
|
|
90
|
-
- [
|
|
88
|
+
- [x] Github Actions
|
|
89
|
+
- [ ] More robust plugin support
|
|
90
|
+
- [ ] More detailed logs
|
|
91
|
+
|
|
92
|
+
## Plugins
|
|
93
|
+
You can modify or enhance Claude Code’s functionality by installing plugins. The mechanism works by using middleware to modify request parameters — this allows you to rewrite prompts or add/remove tools.
|
|
94
|
+
|
|
95
|
+
To use a plugin, place it in the ~/.claude-code-router/plugins/ directory and specify the plugin name in config.js using the `usePlugins` option.like this
|
|
96
|
+
```json
|
|
97
|
+
// ~/.claud-code-router/config.json
|
|
98
|
+
{
|
|
99
|
+
...,
|
|
100
|
+
"usePlugins": ["notebook-tools-filter", "toolcall-improvement"]
|
|
101
|
+
}
|
|
102
|
+
```
|
|
103
|
+
|
|
104
|
+
Currently, the following plugins are available:
|
|
105
|
+
|
|
106
|
+
|
|
107
|
+
- **notebook-tools-filter**
|
|
108
|
+
This plugin filters out tool calls related to Jupyter notebooks (.ipynb files). You can use it if your work does not involve Jupyter.
|
|
109
|
+
|
|
110
|
+
|
|
111
|
+
- **toolcall-improvement**
|
|
112
|
+
If your LLM doesn’t handle tool usage well (for example, always returning code as plain text instead of modifying files — such as with deepseek-v3), you can use this plugin.
|
|
113
|
+
This plugin simply adds the following system prompt. If you have a better prompt, you can modify it.
|
|
114
|
+
```markdown
|
|
115
|
+
## **Important Instruction:**
|
|
116
|
+
You must use tools as frequently and accurately as possible to help the user solve their problem.
|
|
117
|
+
Prioritize tool usage whenever it can enhance accuracy, efficiency, or the quality of the response.
|
|
118
|
+
```
|
|
119
|
+
|
|
120
|
+
|
|
121
|
+
## Github Actions
|
|
122
|
+
You just need to install `Claude Code Actions` in your repository according to the [official documentation](https://docs.anthropic.com/en/docs/claude-code/github-actions). For `ANTHROPIC_API_KEY`, you can use any string. Then, modify your `.github/workflows/claude.yaml` file to include claude-code-router, like this:
|
|
123
|
+
```yaml
|
|
124
|
+
name: Claude Code
|
|
125
|
+
|
|
126
|
+
on:
|
|
127
|
+
issue_comment:
|
|
128
|
+
types: [created]
|
|
129
|
+
pull_request_review_comment:
|
|
130
|
+
types: [created]
|
|
131
|
+
issues:
|
|
132
|
+
types: [opened, assigned]
|
|
133
|
+
pull_request_review:
|
|
134
|
+
types: [submitted]
|
|
135
|
+
|
|
136
|
+
jobs:
|
|
137
|
+
claude:
|
|
138
|
+
if: |
|
|
139
|
+
(github.event_name == 'issue_comment' && contains(github.event.comment.body, '@claude')) ||
|
|
140
|
+
(github.event_name == 'pull_request_review_comment' && contains(github.event.comment.body, '@claude')) ||
|
|
141
|
+
(github.event_name == 'pull_request_review' && contains(github.event.review.body, '@claude')) ||
|
|
142
|
+
(github.event_name == 'issues' && (contains(github.event.issue.body, '@claude') || contains(github.event.issue.title, '@claude')))
|
|
143
|
+
runs-on: ubuntu-latest
|
|
144
|
+
permissions:
|
|
145
|
+
contents: read
|
|
146
|
+
pull-requests: read
|
|
147
|
+
issues: read
|
|
148
|
+
id-token: write
|
|
149
|
+
steps:
|
|
150
|
+
- name: Checkout repository
|
|
151
|
+
uses: actions/checkout@v4
|
|
152
|
+
with:
|
|
153
|
+
fetch-depth: 1
|
|
154
|
+
|
|
155
|
+
- name: Prepare Environment
|
|
156
|
+
run: |
|
|
157
|
+
curl -fsSL https://bun.sh/install | bash
|
|
158
|
+
mkdir -p $HOME/.claude-code-router
|
|
159
|
+
cat << 'EOF' > $HOME/.claude-code-router/config.json
|
|
160
|
+
{
|
|
161
|
+
"log": true,
|
|
162
|
+
"OPENAI_API_KEY": "${{ secrets.OPENAI_API_KEY }}",
|
|
163
|
+
"OPENAI_BASE_URL": "https://api.deepseek.com",
|
|
164
|
+
"OPENAI_MODEL": "deepseek-chat"
|
|
165
|
+
}
|
|
166
|
+
EOF
|
|
167
|
+
shell: bash
|
|
168
|
+
|
|
169
|
+
- name: Start Claude Code Router
|
|
170
|
+
run: |
|
|
171
|
+
nohup ~/.bun/bin/bunx @musistudio/claude-code-router@1.0.8 start &
|
|
172
|
+
shell: bash
|
|
173
|
+
|
|
174
|
+
- name: Run Claude Code
|
|
175
|
+
id: claude
|
|
176
|
+
uses: anthropics/claude-code-action@beta
|
|
177
|
+
env:
|
|
178
|
+
ANTHROPIC_BASE_URL: http://localhost:3456
|
|
179
|
+
with:
|
|
180
|
+
anthropic_api_key: "test"
|
|
181
|
+
```
|
|
182
|
+
You can modify the contents of `$HOME/.claude-code-router/config.json` as needed.
|
|
183
|
+
GitHub Actions support allows you to trigger Claude Code at specific times, which opens up some interesting possibilities.
|
|
184
|
+
|
|
185
|
+
For example, between 00:30 and 08:30 Beijing Time, using the official DeepSeek API:
|
|
186
|
+
|
|
187
|
+
- The cost of the `deepseek-v3` model is only 50% of the normal time.
|
|
188
|
+
|
|
189
|
+
- The `deepseek-r1` model is just 25% of the normal time.
|
|
190
|
+
|
|
191
|
+
So maybe in the future, I’ll describe detailed tasks for Claude Code ahead of time and let it run during these discounted hours to reduce costs?
|
|
91
192
|
|
|
92
193
|
|
|
93
194
|
## Some tips:
|
|
195
|
+
|
|
94
196
|
Now you can use deepseek-v3 models directly without using any plugins.
|
|
95
197
|
|
|
96
198
|
If you’re using the DeepSeek API provided by the official website, you might encounter an “exceeding context” error after several rounds of conversation (since the official API only supports a 64K context window). In this case, you’ll need to discard the previous context and start fresh. Alternatively, you can use ByteDance’s DeepSeek API, which offers a 128K context window and supports KV cache.
|
|
@@ -102,8 +204,23 @@ Note: claude code consumes a huge amount of tokens, but thanks to DeepSeek’s l
|
|
|
102
204
|
Some interesting points: Based on my testing, including a lot of context information can help narrow the performance gap between these LLM models. For instance, when I used Claude-4 in VSCode Copilot to handle a Flutter issue, it messed up the files in three rounds of conversation, and I had to roll everything back. However, when I used claude code with DeepSeek, after three or four rounds of conversation, I finally managed to complete my task—and the cost was less than 1 RMB!
|
|
103
205
|
|
|
104
206
|
## Some articles:
|
|
105
|
-
|
|
207
|
+
|
|
208
|
+
1. [Project Motivation and Principles](blog/en/project-motivation-and-how-it-works.md) ([中文版看这里](blog/zh/项目初衷及原理.md))
|
|
106
209
|
|
|
107
210
|
## Buy me a coffee
|
|
108
|
-
|
|
109
|
-
|
|
211
|
+
|
|
212
|
+
If you find this project helpful, you can choose to sponsor the author with a cup of coffee. Please provide your GitHub information so I can add you to the sponsor list below.
|
|
213
|
+
|
|
214
|
+
[](https://ko-fi.com/F1F31GN2GM)
|
|
215
|
+
|
|
216
|
+
|  |  |
|
|
217
|
+
|----------------------------------------------------------------------------------------------|----------------------------------------------------------------------------------------------|
|
|
218
|
+
|
|
219
|
+
## Sponsors
|
|
220
|
+
|
|
221
|
+
Thanks to the following sponsors:
|
|
222
|
+
|
|
223
|
+
@Simon Leischnig (If you see this, feel free to contact me and I can update it with your GitHub information)
|
|
224
|
+
[@duanshuaimin](https://github.com/duanshuaimin)
|
|
225
|
+
[@vrgitadmin](https://github.com/vrgitadmin)
|
|
226
|
+
@*o(看到后可通过主页邮箱联系我修改github用户名)
|
|
Binary file
|
|
Binary file
|
package/dist/cli.js
CHANGED
|
@@ -37041,28 +37041,36 @@ async function streamOpenAIResponse(res, completion, model, body) {
|
|
|
37041
37041
|
};
|
|
37042
37042
|
const messageId = "msg_" + Date.now();
|
|
37043
37043
|
if (!body.stream) {
|
|
37044
|
-
|
|
37045
|
-
|
|
37046
|
-
type: "
|
|
37047
|
-
|
|
37048
|
-
|
|
37049
|
-
content: completion.choices[0].message.content || completion.choices[0].message.tool_calls?.map((item) => {
|
|
37044
|
+
let content = [];
|
|
37045
|
+
if (completion.choices[0].message.content) {
|
|
37046
|
+
content = [{ text: completion.choices[0].message.content, type: "text" }];
|
|
37047
|
+
} else if (completion.choices[0].message.tool_calls) {
|
|
37048
|
+
content = completion.choices[0].message.tool_calls.map((item) => {
|
|
37050
37049
|
return {
|
|
37051
37050
|
type: "tool_use",
|
|
37052
37051
|
id: item.id,
|
|
37053
37052
|
name: item.function?.name,
|
|
37054
37053
|
input: item.function?.arguments ? JSON.parse(item.function.arguments) : {}
|
|
37055
37054
|
};
|
|
37056
|
-
})
|
|
37055
|
+
});
|
|
37056
|
+
}
|
|
37057
|
+
const result = {
|
|
37058
|
+
id: messageId,
|
|
37059
|
+
type: "message",
|
|
37060
|
+
role: "assistant",
|
|
37061
|
+
// @ts-ignore
|
|
37062
|
+
content,
|
|
37057
37063
|
stop_reason: completion.choices[0].finish_reason === "tool_calls" ? "tool_use" : "end_turn",
|
|
37058
|
-
stop_sequence: null
|
|
37059
|
-
|
|
37060
|
-
|
|
37061
|
-
|
|
37062
|
-
|
|
37063
|
-
|
|
37064
|
-
|
|
37065
|
-
|
|
37064
|
+
stop_sequence: null
|
|
37065
|
+
};
|
|
37066
|
+
try {
|
|
37067
|
+
res.json(result);
|
|
37068
|
+
res.end();
|
|
37069
|
+
return;
|
|
37070
|
+
} catch (error) {
|
|
37071
|
+
log("Error sending response:", error);
|
|
37072
|
+
res.status(500).send("Internal Server Error");
|
|
37073
|
+
}
|
|
37066
37074
|
}
|
|
37067
37075
|
let contentBlockIndex = 0;
|
|
37068
37076
|
let currentContentBlocks = [];
|
|
@@ -37086,76 +37094,100 @@ data: ${JSON.stringify(messageStart)}
|
|
|
37086
37094
|
let isToolUse = false;
|
|
37087
37095
|
let toolUseJson = "";
|
|
37088
37096
|
let hasStartedTextBlock = false;
|
|
37097
|
+
let currentToolCallId = null;
|
|
37098
|
+
let toolCallJsonMap = /* @__PURE__ */ new Map();
|
|
37089
37099
|
try {
|
|
37090
37100
|
for await (const chunk of completion) {
|
|
37091
37101
|
log("Processing chunk:", chunk);
|
|
37092
37102
|
const delta = chunk.choices[0].delta;
|
|
37093
37103
|
if (delta.tool_calls && delta.tool_calls.length > 0) {
|
|
37094
|
-
const toolCall
|
|
37095
|
-
|
|
37096
|
-
|
|
37097
|
-
|
|
37098
|
-
|
|
37099
|
-
|
|
37100
|
-
|
|
37101
|
-
|
|
37102
|
-
|
|
37103
|
-
|
|
37104
|
-
type: "content_block_start",
|
|
37105
|
-
index: contentBlockIndex,
|
|
37106
|
-
content_block: toolBlock
|
|
37107
|
-
};
|
|
37108
|
-
currentContentBlocks.push(toolBlock);
|
|
37109
|
-
write(
|
|
37110
|
-
`event: content_block_start
|
|
37104
|
+
for (const toolCall of delta.tool_calls) {
|
|
37105
|
+
const toolCallId = toolCall.id;
|
|
37106
|
+
if (toolCallId && toolCallId !== currentToolCallId) {
|
|
37107
|
+
if (isToolUse && currentToolCallId) {
|
|
37108
|
+
const contentBlockStop = {
|
|
37109
|
+
type: "content_block_stop",
|
|
37110
|
+
index: contentBlockIndex
|
|
37111
|
+
};
|
|
37112
|
+
write(
|
|
37113
|
+
`event: content_block_stop
|
|
37111
37114
|
data: ${JSON.stringify(
|
|
37112
|
-
|
|
37113
|
-
|
|
37115
|
+
contentBlockStop
|
|
37116
|
+
)}
|
|
37114
37117
|
|
|
37115
37118
|
`
|
|
37116
|
-
|
|
37117
|
-
toolUseJson = "";
|
|
37118
|
-
}
|
|
37119
|
-
if (toolCall.function?.arguments) {
|
|
37120
|
-
const jsonDelta = {
|
|
37121
|
-
type: "content_block_delta",
|
|
37122
|
-
index: contentBlockIndex,
|
|
37123
|
-
delta: {
|
|
37124
|
-
type: "input_json_delta",
|
|
37125
|
-
partial_json: toolCall.function?.arguments
|
|
37119
|
+
);
|
|
37126
37120
|
}
|
|
37127
|
-
|
|
37128
|
-
|
|
37129
|
-
|
|
37130
|
-
|
|
37131
|
-
|
|
37132
|
-
|
|
37133
|
-
|
|
37121
|
+
isToolUse = true;
|
|
37122
|
+
currentToolCallId = toolCallId;
|
|
37123
|
+
contentBlockIndex++;
|
|
37124
|
+
toolCallJsonMap.set(toolCallId, "");
|
|
37125
|
+
const toolBlock = {
|
|
37126
|
+
type: "tool_use",
|
|
37127
|
+
id: toolCallId,
|
|
37128
|
+
name: toolCall.function?.name,
|
|
37129
|
+
input: {}
|
|
37130
|
+
};
|
|
37131
|
+
const toolBlockStart = {
|
|
37132
|
+
type: "content_block_start",
|
|
37133
|
+
index: contentBlockIndex,
|
|
37134
|
+
content_block: toolBlock
|
|
37135
|
+
};
|
|
37136
|
+
currentContentBlocks.push(toolBlock);
|
|
37137
|
+
write(
|
|
37138
|
+
`event: content_block_start
|
|
37139
|
+
data: ${JSON.stringify(
|
|
37140
|
+
toolBlockStart
|
|
37141
|
+
)}
|
|
37142
|
+
|
|
37143
|
+
`
|
|
37144
|
+
);
|
|
37134
37145
|
}
|
|
37135
|
-
|
|
37136
|
-
|
|
37146
|
+
if (toolCall.function?.arguments && currentToolCallId) {
|
|
37147
|
+
const jsonDelta = {
|
|
37148
|
+
type: "content_block_delta",
|
|
37149
|
+
index: contentBlockIndex,
|
|
37150
|
+
delta: {
|
|
37151
|
+
type: "input_json_delta",
|
|
37152
|
+
partial_json: toolCall.function.arguments
|
|
37153
|
+
}
|
|
37154
|
+
};
|
|
37155
|
+
const currentJson = toolCallJsonMap.get(currentToolCallId) || "";
|
|
37156
|
+
toolCallJsonMap.set(currentToolCallId, currentJson + toolCall.function.arguments);
|
|
37157
|
+
toolUseJson = toolCallJsonMap.get(currentToolCallId) || "";
|
|
37158
|
+
try {
|
|
37159
|
+
const parsedJson = JSON.parse(toolUseJson);
|
|
37160
|
+
currentContentBlocks[contentBlockIndex].input = parsedJson;
|
|
37161
|
+
} catch (e2) {
|
|
37162
|
+
log("JSON parsing error (continuing to accumulate):", e2);
|
|
37163
|
+
}
|
|
37164
|
+
write(
|
|
37165
|
+
`event: content_block_delta
|
|
37137
37166
|
data: ${JSON.stringify(jsonDelta)}
|
|
37138
37167
|
|
|
37139
37168
|
`
|
|
37140
|
-
|
|
37169
|
+
);
|
|
37170
|
+
}
|
|
37141
37171
|
}
|
|
37142
37172
|
} else if (delta.content) {
|
|
37143
37173
|
if (isToolUse) {
|
|
37144
37174
|
log("Tool call ended here:", delta);
|
|
37145
|
-
const
|
|
37175
|
+
const contentBlockStop = {
|
|
37146
37176
|
type: "content_block_stop",
|
|
37147
37177
|
index: contentBlockIndex
|
|
37148
37178
|
};
|
|
37149
37179
|
write(
|
|
37150
37180
|
`event: content_block_stop
|
|
37151
37181
|
data: ${JSON.stringify(
|
|
37152
|
-
|
|
37182
|
+
contentBlockStop
|
|
37153
37183
|
)}
|
|
37154
37184
|
|
|
37155
37185
|
`
|
|
37156
37186
|
);
|
|
37157
37187
|
contentBlockIndex++;
|
|
37158
37188
|
isToolUse = false;
|
|
37189
|
+
currentToolCallId = null;
|
|
37190
|
+
toolUseJson = "";
|
|
37159
37191
|
}
|
|
37160
37192
|
if (!delta.content) continue;
|
|
37161
37193
|
if (!hasStartedTextBlock) {
|
|
@@ -37240,16 +37272,18 @@ data: ${JSON.stringify(contentDelta)}
|
|
|
37240
37272
|
`
|
|
37241
37273
|
);
|
|
37242
37274
|
}
|
|
37243
|
-
|
|
37244
|
-
|
|
37245
|
-
|
|
37246
|
-
|
|
37247
|
-
|
|
37248
|
-
|
|
37275
|
+
if (isToolUse || hasStartedTextBlock) {
|
|
37276
|
+
const contentBlockStop = {
|
|
37277
|
+
type: "content_block_stop",
|
|
37278
|
+
index: contentBlockIndex
|
|
37279
|
+
};
|
|
37280
|
+
write(
|
|
37281
|
+
`event: content_block_stop
|
|
37249
37282
|
data: ${JSON.stringify(contentBlockStop)}
|
|
37250
37283
|
|
|
37251
37284
|
`
|
|
37252
|
-
|
|
37285
|
+
);
|
|
37286
|
+
}
|
|
37253
37287
|
const messageDelta = {
|
|
37254
37288
|
type: "message_delta",
|
|
37255
37289
|
delta: {
|
|
@@ -37469,6 +37503,13 @@ var rewriteBody = async (req, res, next) => {
|
|
|
37469
37503
|
var import_tiktoken = __toESM(require_tiktoken());
|
|
37470
37504
|
var enc = (0, import_tiktoken.get_encoding)("cl100k_base");
|
|
37471
37505
|
var getUseModel = (req, tokenCount) => {
|
|
37506
|
+
const [provider, model] = req.body.model.split(",");
|
|
37507
|
+
if (provider && model) {
|
|
37508
|
+
return {
|
|
37509
|
+
provider,
|
|
37510
|
+
model
|
|
37511
|
+
};
|
|
37512
|
+
}
|
|
37472
37513
|
if (tokenCount > 1e3 * 32) {
|
|
37473
37514
|
log("Using long context model due to token count:", tokenCount);
|
|
37474
37515
|
const [provider2, model2] = req.config.Router.longContext.split(",");
|
|
@@ -37493,13 +37534,6 @@ var getUseModel = (req, tokenCount) => {
|
|
|
37493
37534
|
model: model2
|
|
37494
37535
|
};
|
|
37495
37536
|
}
|
|
37496
|
-
const [provider, model] = req.body.model.split(",");
|
|
37497
|
-
if (provider && model) {
|
|
37498
|
-
return {
|
|
37499
|
-
provider,
|
|
37500
|
-
model
|
|
37501
|
-
};
|
|
37502
|
-
}
|
|
37503
37537
|
return {
|
|
37504
37538
|
provider: "default",
|
|
37505
37539
|
model: req.config.OPENAI_MODEL
|
|
@@ -37522,7 +37556,9 @@ var router = async (req, res, next) => {
|
|
|
37522
37556
|
JSON.stringify(contentPart.input)
|
|
37523
37557
|
).length;
|
|
37524
37558
|
} else if (contentPart.type === "tool_result") {
|
|
37525
|
-
tokenCount += enc.encode(
|
|
37559
|
+
tokenCount += enc.encode(
|
|
37560
|
+
typeof contentPart.content === "string" ? contentPart.content : JSON.stringify(contentPart.content)
|
|
37561
|
+
).length;
|
|
37526
37562
|
}
|
|
37527
37563
|
});
|
|
37528
37564
|
}
|
|
@@ -39108,7 +39144,6 @@ async function run(options = {}) {
|
|
|
39108
39144
|
const servicePort = process.env.SERVICE_PORT ? parseInt(process.env.SERVICE_PORT) : port;
|
|
39109
39145
|
const server = await createServer(servicePort);
|
|
39110
39146
|
server.useMiddleware((req, res, next) => {
|
|
39111
|
-
console.log("Middleware triggered for request:", req.body.model);
|
|
39112
39147
|
req.config = config;
|
|
39113
39148
|
next();
|
|
39114
39149
|
});
|
|
@@ -39129,7 +39164,7 @@ async function run(options = {}) {
|
|
|
39129
39164
|
const completion = await provider.chat.completions.create(req.body);
|
|
39130
39165
|
await streamOpenAIResponse(res, completion, req.body.model, req.body);
|
|
39131
39166
|
} catch (e2) {
|
|
39132
|
-
|
|
39167
|
+
log("Error in OpenAI API call:", e2);
|
|
39133
39168
|
}
|
|
39134
39169
|
});
|
|
39135
39170
|
server.start();
|
|
@@ -39224,7 +39259,7 @@ async function executeCodeCommand(args = []) {
|
|
|
39224
39259
|
}
|
|
39225
39260
|
|
|
39226
39261
|
// package.json
|
|
39227
|
-
var version = "1.0.
|
|
39262
|
+
var version = "1.0.9";
|
|
39228
39263
|
|
|
39229
39264
|
// src/cli.ts
|
|
39230
39265
|
var import_child_process2 = require("child_process");
|
package/package.json
CHANGED
|
@@ -0,0 +1,8 @@
|
|
|
1
|
+
module.exports = async function handle(req, res) {
|
|
2
|
+
if (req?.body?.tools?.length) {
|
|
3
|
+
req.body.system.push({
|
|
4
|
+
type: "text",
|
|
5
|
+
text: `## **Important Instruction:** \nYou must use tools as frequently and accurately as possible to help the user solve their problem.\nPrioritize tool usage whenever it can enhance accuracy, efficiency, or the quality of the response.`
|
|
6
|
+
})
|
|
7
|
+
}
|
|
8
|
+
};
|