aicodeswitch 4.0.4 → 5.0.0
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 +6 -5
- package/UPGRADE.md +5 -6
- package/dist/server/coding-plan.js +94 -0
- package/dist/server/config-managed-fields.js +1 -0
- package/dist/server/conversions/compact.js +613 -0
- package/dist/server/conversions/detector.js +70 -0
- package/dist/server/conversions/index.js +285 -0
- package/dist/server/conversions/pairs/claude-completions/request.js +167 -0
- package/dist/server/conversions/pairs/claude-completions/response.js +56 -0
- package/dist/server/conversions/pairs/claude-completions/streaming.js +259 -0
- package/dist/server/conversions/pairs/claude-gemini/request.js +130 -0
- package/dist/server/conversions/pairs/claude-gemini/response.js +65 -0
- package/dist/server/conversions/pairs/claude-gemini/streaming.js +199 -0
- package/dist/server/conversions/pairs/claude-responses/request.js +190 -0
- package/dist/server/conversions/pairs/claude-responses/response.js +89 -0
- package/dist/server/conversions/pairs/claude-responses/streaming.js +266 -0
- package/dist/server/conversions/pairs/completions-claude/request.js +111 -0
- package/dist/server/conversions/pairs/completions-claude/response.js +67 -0
- package/dist/server/conversions/pairs/completions-claude/streaming.js +165 -0
- package/dist/server/conversions/pairs/completions-gemini/request.js +169 -0
- package/dist/server/conversions/pairs/completions-gemini/response.js +70 -0
- package/dist/server/conversions/pairs/completions-gemini/streaming.js +132 -0
- package/dist/server/conversions/pairs/completions-responses/request.js +149 -0
- package/dist/server/conversions/pairs/completions-responses/response.js +74 -0
- package/dist/server/conversions/pairs/completions-responses/streaming.js +189 -0
- package/dist/server/conversions/pairs/gemini-claude/request.js +118 -0
- package/dist/server/conversions/pairs/gemini-claude/response.js +45 -0
- package/dist/server/conversions/pairs/gemini-claude/streaming.js +146 -0
- package/dist/server/conversions/pairs/gemini-completions/request.js +151 -0
- package/dist/server/conversions/pairs/gemini-completions/response.js +54 -0
- package/dist/server/conversions/pairs/gemini-completions/streaming.js +108 -0
- package/dist/server/conversions/pairs/gemini-responses/request.js +18 -0
- package/dist/server/conversions/pairs/gemini-responses/response.js +18 -0
- package/dist/server/conversions/pairs/gemini-responses/streaming.js +43 -0
- package/dist/server/conversions/pairs/responses-claude/request.js +155 -0
- package/dist/server/conversions/pairs/responses-claude/response.js +70 -0
- package/dist/server/conversions/pairs/responses-claude/streaming.js +345 -0
- package/dist/server/conversions/pairs/responses-completions/request.js +207 -0
- package/dist/server/conversions/pairs/responses-completions/response.js +96 -0
- package/dist/server/conversions/pairs/responses-completions/streaming.js +344 -0
- package/dist/server/conversions/pairs/responses-gemini/request.js +18 -0
- package/dist/server/conversions/pairs/responses-gemini/response.js +18 -0
- package/dist/server/conversions/pairs/responses-gemini/streaming.js +43 -0
- package/dist/server/conversions/pairs/responses-responses/request.js +115 -0
- package/dist/server/conversions/pipeline.js +296 -0
- package/dist/server/conversions/stream-converter-adapter.js +49 -0
- package/dist/server/conversions/thinking/effort.js +61 -0
- package/dist/server/conversions/thinking/mapper.js +59 -0
- package/dist/server/conversions/thinking/providers.js +76 -0
- package/dist/server/conversions/types.js +5 -0
- package/dist/server/conversions/url-normalizer.js +58 -0
- package/dist/server/conversions/utils/format-mappers.js +57 -0
- package/dist/server/conversions/utils/id.js +33 -0
- package/dist/server/conversions/utils/stop-reasons.js +95 -0
- package/dist/server/conversions/utils/streaming-helpers.js +59 -0
- package/dist/server/conversions/utils/tool-schema.js +169 -0
- package/dist/server/conversions/utils/usage.js +82 -0
- package/dist/server/fs-database.js +465 -135
- package/dist/server/main.js +93 -33
- package/dist/server/original-config-reader.js +1 -1
- package/dist/server/proxy-server.js +887 -633
- package/dist/server/transformers/chunk-collector.js +5 -1
- package/dist/server/transformers/streaming.js +6 -3235
- package/dist/server/type-migration.js +2 -3
- package/dist/server/utils.js +5 -0
- package/dist/ui/assets/{index-C7G0whng.css → index-BHR12ImE.css} +1 -1
- package/dist/ui/assets/index-DjdBW1yu.js +517 -0
- package/dist/ui/index.html +2 -2
- package/package.json +1 -1
- package/dist/server/transformers/transformers.js +0 -1767
- package/dist/ui/assets/index-Dl-B9pXM.js +0 -514
- package/schema/claude.schema.md +0 -946
- package/schema/deepseek-chat.schema.md +0 -799
- package/schema/gemini.schema.md +0 -1408
- package/schema/openai-chat-completions.schema.md +0 -1088
- package/schema/openai-responses.schema.md +0 -226196
- package/schema/stream.md +0 -2592
package/README.md
CHANGED
|
@@ -4,6 +4,7 @@
|
|
|
4
4
|
|
|
5
5
|
AI Code Switch 是帮助你在本地管理 AI 编程工具接入大模型的工具。
|
|
6
6
|
它可以让你的 Claude Code、Codex 等工具不再局限于官方模型。
|
|
7
|
+
为所有编程工具提供本地API驱动,自动智能的切换不同场景下的模型。
|
|
7
8
|
|
|
8
9
|
**而且它尽可能简单的帮你解决这件事。**
|
|
9
10
|
|
|
@@ -13,11 +14,12 @@ AI Code Switch 是帮助你在本地管理 AI 编程工具接入大模型的工
|
|
|
13
14
|
## 功能要点
|
|
14
15
|
|
|
15
16
|
* 可登记任意的大模型API接口服务,让你可以在一个面板管理你的大模型厂商
|
|
16
|
-
*
|
|
17
|
+
* 一键切换模型:可以注册多个供应商的多个API接口,当想要切换模型时,只需要点击一个按钮就可以立即切换
|
|
17
18
|
* 自动配置:无需你手动去修改claude code或codex的系统配置文件,aicodeswitch自动帮你修改,你只要启动它,无需配置claude code或codex就可以让它们正常工作
|
|
18
19
|
* 一键配置供应商,省去复杂的供应商配置流程
|
|
20
|
+
* 启动所有已知大模型接口标准,可接入任意客户端,包括但不限于openclaw、hermes、trae等,根据不同需要自主配置接口对应的大模型服务
|
|
19
21
|
* API转流:将兼容openai接口标准的模型,轻松接入到claude code中,支持将符合openai、anthropic、gemini的数据格式转发给claude code或codex
|
|
20
|
-
*
|
|
22
|
+
* 按需中转请求:根据请求类型,让不同的模型来处理不同的任务,节省成本,基于该特性,可以让glm等原生非多模态模型支持图像识别
|
|
21
23
|
* 智能故障切换:当API服务发生故障时,智能切换到其他API服务进行尝试,无需手动切换,特别适用于中转服务商
|
|
22
24
|
* 代理:针对无法直接访问的模型服务,例如地区被ban,支持设置代理来解决
|
|
23
25
|
* tokens超量限制:避免其中一个服务商的用量超过限制,浪费了钱,适合有免费额度的服务商
|
|
@@ -27,10 +29,9 @@ AI Code Switch 是帮助你在本地管理 AI 编程工具接入大模型的工
|
|
|
27
29
|
* Skills管理:一键搜索和安装Skills,一键启用skill到claude code或codex
|
|
28
30
|
* MCP管理:一键安装预设MCP,一键启用MCP
|
|
29
31
|
* 导入和导出:一键备份数据,在多太电脑间共享aicodeswitch配置
|
|
30
|
-
*
|
|
32
|
+
* 服务端部署,自定义API Key,支持B/S架构,让aicodeswitch成为在线服务,提供给团队使用
|
|
31
33
|
* 数据完全本地,自主可控
|
|
32
34
|
* 特殊语法:在发送的提示词最前面添加`[!]`来直接切换为高智商模型服务(`[x]`关闭),简单快捷
|
|
33
|
-
* 服务端部署,可随时随地使用
|
|
34
35
|
|
|
35
36
|
## 桌面客户端
|
|
36
37
|
|
|
@@ -121,7 +122,7 @@ Codex的配置覆盖逻辑一模一样。
|
|
|
121
122
|
3. 避免你忘记曾经注册过那些供应商
|
|
122
123
|
4. 充分榨干不怎么用的供应商的服务,避免充值后不怎么用浪费了
|
|
123
124
|
|
|
124
|
-
###
|
|
125
|
+
### 什么是API服务的“源类型”
|
|
125
126
|
|
|
126
127
|
供应商接口返回的数据格式标准类型,目前支持以下几种:
|
|
127
128
|
|
package/UPGRADE.md
CHANGED
|
@@ -1,7 +1,6 @@
|
|
|
1
|
-
|
|
1
|
+
升级到 v5.0.0 版本将会有破坏性影响,你需要注意:
|
|
2
|
+
|
|
3
|
+
* 我们移除了 `Deepseek` 类型的服务,它原本的 `reasoning_content` 特殊字段已被合并进入 `chat completions` 类型,升级会自动完成数据库迁移,你不需要手动修改。
|
|
4
|
+
* 我们启用了新的数据流格式转化器,请你实时关注新版本,如遇到问题,我们会实时修复发布新版本。
|
|
5
|
+
* 我们对路由管理进行了升级,现在你可以将 aicodeswitch 使用于其他**任意的编程工具**,之需要填写对应的 API 即可。升级后,路由本身不再绑定claude-code/codex,你需要在Claude Code配置、Codex配置中,激活想要用来服务的路由,让这两个最重要的编程工具能够正常工作(我们会在升级过程中帮你自动迁移数据库,因此,你不需要手动处理)。
|
|
2
6
|
|
|
3
|
-
* 对于API服务,你需要进行检查,OpenAI 类型的服务,请检查 `baseUrl` 是否以 `/v1` 结尾,如果是,请移除。
|
|
4
|
-
* 对codex/claude-code的配置覆盖逻辑,不再与“是否激活路由”绑定,而是在启动服务时写入覆盖并备份,停止服务时恢复备份。
|
|
5
|
-
* 升级后,一旦你启动 AICodeSwitch,就可以统计到所有请求,让你的AI编程统计数据更准确。
|
|
6
|
-
* 由于Codex升级后,数据结构有了较大的变化,导致我们的转流可能存在问题,请为Codex使用复合Responses API标准的接口(注:部分国内厂商实现的responses接口不够完善,部分工具不支持)。
|
|
7
|
-
* 升级后,数据版本会变更,如果重启后没有看到原来的数据,需退回上一个版本,导出数据后重新升级,并导入备份的数据。
|
|
@@ -0,0 +1,94 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
/**
|
|
3
|
+
* 编程套餐限制检测工具
|
|
4
|
+
*
|
|
5
|
+
* 从 AICodingBus 的 isCodingToolRequest 逻辑移植而来。
|
|
6
|
+
* 用于判断当前请求是否来自编程工具(Claude Code / Codex / Cursor 等),
|
|
7
|
+
* 配合 APIService.enableCodingPlan 实现编程套餐限制。
|
|
8
|
+
*/
|
|
9
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
10
|
+
exports.isCodingToolRequest = isCodingToolRequest;
|
|
11
|
+
/**
|
|
12
|
+
* 检测请求是否来自编程工具
|
|
13
|
+
*
|
|
14
|
+
* 检测策略(三层):
|
|
15
|
+
* 1. HTTP Headers —— 识别已知的编程工具 User-Agent / 特征 Header
|
|
16
|
+
* 2. 请求体 —— Claude Messages / OpenAI Responses / OpenAI Chat Completions 格式中的 tool_use / tool_calls 等标记
|
|
17
|
+
* 3. 都不匹配 —— 判定为非编程请求
|
|
18
|
+
*
|
|
19
|
+
* @param body 请求体(已解析为对象)
|
|
20
|
+
* @param format 客户端请求格式(claude / completions / responses / gemini)
|
|
21
|
+
* @param headers 请求头(小写 key)
|
|
22
|
+
*/
|
|
23
|
+
function isCodingToolRequest(body, format, headers) {
|
|
24
|
+
const reasons = [];
|
|
25
|
+
// ── Layer 1: HTTP Headers ──────────────────────────────────────────
|
|
26
|
+
if (headers) {
|
|
27
|
+
const ua = (headers['user-agent'] || '').toLowerCase();
|
|
28
|
+
// Claude Code: user-agent 包含 "claude-cli" 或 "claude-vscode"
|
|
29
|
+
if (ua.includes('claude-cli') || ua.includes('claude-vscode'))
|
|
30
|
+
return { isCoding: true, reason: '' };
|
|
31
|
+
// Claude Code: 特征 header
|
|
32
|
+
if (headers['x-claude-code-session-id'])
|
|
33
|
+
return { isCoding: true, reason: '' };
|
|
34
|
+
// Codex: user-agent 包含 "codex"
|
|
35
|
+
if (ua.includes('codex'))
|
|
36
|
+
return { isCoding: true, reason: '' };
|
|
37
|
+
// Codex: originator header
|
|
38
|
+
if ((headers['originator'] || '').toLowerCase().includes('codex'))
|
|
39
|
+
return { isCoding: true, reason: '' };
|
|
40
|
+
}
|
|
41
|
+
// ── Layer 2: Claude Messages API ───────────────────────────────────
|
|
42
|
+
if (format === 'claude' && Array.isArray(body === null || body === void 0 ? void 0 : body.messages)) {
|
|
43
|
+
for (const msg of body.messages) {
|
|
44
|
+
const contents = Array.isArray(msg.content) ? msg.content : [];
|
|
45
|
+
for (const block of contents) {
|
|
46
|
+
if (block.type === 'tool_use' || block.type === 'tool_result')
|
|
47
|
+
return { isCoding: true, reason: '' };
|
|
48
|
+
}
|
|
49
|
+
}
|
|
50
|
+
if (Array.isArray(body.tools) && body.tools.length > 0)
|
|
51
|
+
return { isCoding: true, reason: '' };
|
|
52
|
+
reasons.push('claude messages: no tool_use/tool_result blocks, no tools array');
|
|
53
|
+
}
|
|
54
|
+
// ── Layer 2: OpenAI Responses API (Codex) ──────────────────────────
|
|
55
|
+
if (Array.isArray(body === null || body === void 0 ? void 0 : body.input)) {
|
|
56
|
+
for (const item of body.input) {
|
|
57
|
+
if (item.type === 'message' && item.role === 'developer')
|
|
58
|
+
return { isCoding: true, reason: '' };
|
|
59
|
+
if (item.type === 'function_call' || item.type === 'function_call_output')
|
|
60
|
+
return { isCoding: true, reason: '' };
|
|
61
|
+
}
|
|
62
|
+
reasons.push('responses input: no developer role message, no function_call/function_call_output');
|
|
63
|
+
}
|
|
64
|
+
// ── Layer 2: OpenAI Chat Completions ───────────────────────────────
|
|
65
|
+
if (format === 'completions' && Array.isArray(body === null || body === void 0 ? void 0 : body.messages)) {
|
|
66
|
+
for (const msg of body.messages) {
|
|
67
|
+
if (msg.role === 'tool')
|
|
68
|
+
return { isCoding: true, reason: '' };
|
|
69
|
+
if (Array.isArray(msg.tool_calls) && msg.tool_calls.length > 0)
|
|
70
|
+
return { isCoding: true, reason: '' };
|
|
71
|
+
}
|
|
72
|
+
if (Array.isArray(body.tools) && body.tools.length > 0)
|
|
73
|
+
return { isCoding: true, reason: '' };
|
|
74
|
+
reasons.push('openai messages: no tool role, no tool_calls, no tools array');
|
|
75
|
+
}
|
|
76
|
+
// ── Layer 2: Gemini ────────────────────────────────────────────────
|
|
77
|
+
if (format === 'gemini' && (body === null || body === void 0 ? void 0 : body.contents)) {
|
|
78
|
+
const contents = Array.isArray(body.contents) ? body.contents : [];
|
|
79
|
+
for (const part of contents) {
|
|
80
|
+
const parts = Array.isArray(part.parts) ? part.parts : [];
|
|
81
|
+
for (const p of parts) {
|
|
82
|
+
if (p.functionCall || p.functionResponse)
|
|
83
|
+
return { isCoding: true, reason: '' };
|
|
84
|
+
}
|
|
85
|
+
}
|
|
86
|
+
if (Array.isArray(body.tools) && body.tools.length > 0)
|
|
87
|
+
return { isCoding: true, reason: '' };
|
|
88
|
+
reasons.push('gemini: no functionCall/functionResponse, no tools array');
|
|
89
|
+
}
|
|
90
|
+
if (reasons.length === 0) {
|
|
91
|
+
reasons.push(`no matching format checked (format=${format}, hasMessages=${!!(body === null || body === void 0 ? void 0 : body.messages)}, hasInput=${!!(body === null || body === void 0 ? void 0 : body.input)})`);
|
|
92
|
+
}
|
|
93
|
+
return { isCoding: false, reason: reasons.join('; ') };
|
|
94
|
+
}
|
|
@@ -10,6 +10,7 @@ exports.CLAUDE_SETTINGS_MANAGED_FIELDS = [
|
|
|
10
10
|
{ path: ['env', 'API_TIMEOUT_MS'] },
|
|
11
11
|
{ path: ['env', 'CLAUDE_CODE_DISABLE_NONESSENTIAL_TRAFFIC'] },
|
|
12
12
|
{ path: ['env', 'CLAUDE_CODE_EXPERIMENTAL_AGENT_TEAMS'], optional: true },
|
|
13
|
+
{ path: ['env', 'CLAUDE_AUTOCOMPACT_PCT_OVERRIDE'], optional: true },
|
|
13
14
|
{ path: ['env', 'ANTHROPIC_DEFAULT_HAIKU_MODEL'], optional: true },
|
|
14
15
|
{ path: ['env', 'ANTHROPIC_DEFAULT_SONNET_MODEL'], optional: true },
|
|
15
16
|
{ path: ['env', 'ANTHROPIC_DEFAULT_OPUS_MODEL'], optional: true },
|