@dedenlabs/claude-code-router-cli 2.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.
Binary file
@@ -0,0 +1,130 @@
1
+ "use strict";
2
+
3
+ // src/transformers/glm-thinking.ts
4
+ var GLMThinkingTransformer = class {
5
+ name;
6
+ enabled;
7
+ debug;
8
+ constructor(options = {}) {
9
+ this.name = "glm-thinking";
10
+ this.enabled = options.enabled !== "false" && options.enabled !== false;
11
+ this.debug = options.debug !== "false" && options.debug !== false || false;
12
+ console.log("\u{1F4A1}GLM\u601D\u8003\u6A21\u5F0F\u8F6C\u6362\u5668\u5DF2\u6FC0\u6D3B", { enabled: this.enabled });
13
+ }
14
+ /**
15
+ * 检测思维链类型
16
+ */
17
+ detectThinkingType(prompt) {
18
+ const keywords = {
19
+ mathematical: ["\u8BA1\u7B97", "\u6570\u5B66", "\u516C\u5F0F", "\u65B9\u7A0B", "\u51E0\u4F55", "\u4EE3\u6570", "calculate", "math", "formula", "\u6C42\u89E3", "\u51FD\u6570", "\u79EF\u5206", "\u5BFC\u6570", "\u6781\u9650", "\u8BC1\u660E\u9898"],
20
+ logical: ["\u903B\u8F91", "\u63A8\u7406", "\u8BC1\u660E", "\u6F14\u7ECE", "\u5F52\u7EB3", "logic", "reasoning", "proof", "\u63A8\u65AD", "\u5047\u8BBE", "\u7ED3\u8BBA"],
21
+ causal: ["\u539F\u56E0", "\u7ED3\u679C", "\u56E0\u679C", "\u5F71\u54CD", "\u5BFC\u81F4", "cause", "effect", "impact", "\u5206\u6790", "\u9884\u6D4B", "\u5173\u7CFB"],
22
+ analytical: ["\u5206\u6790", "\u5206\u89E3", "\u8BC4\u4F30", "\u5224\u65AD", "analyze", "evaluate", "assess", "\u6BD4\u8F83", "\u603B\u7ED3", "\u4F18\u7F3A\u70B9"],
23
+ creative: ["\u521B\u610F", "\u521B\u65B0", "\u60F3\u8C61", "\u8BBE\u8BA1", "creative", "innovative", "design", "\u6784\u601D", "\u4F18\u5316", "\u6539\u8FDB"],
24
+ strategic: ["\u7B56\u7565", "\u8BA1\u5212", "\u51B3\u7B56", "\u9009\u62E9", "strategy", "plan", "decision", "\u65B9\u6848", "\u5EFA\u8BAE", "\u89C4\u5212"],
25
+ programming: ["\u4EE3\u7801", "\u7F16\u7A0B", "\u7B97\u6CD5", "\u7A0B\u5E8F", "code", "algorithm", "function", "\u5B9E\u73B0", "\u5F00\u53D1", "\u8C03\u8BD5"],
26
+ problem_solving: ["\u95EE\u9898", "\u89E3\u51B3", "\u65B9\u6CD5", "\u6B65\u9AA4", "problem", "solve", "solution", "\u601D\u8DEF", "\u6D41\u7A0B"]
27
+ };
28
+ for (const [type, words] of Object.entries(keywords)) {
29
+ const matchedWords = [];
30
+ const matchCount = words.filter((word) => {
31
+ if (prompt.toLowerCase().includes(word.toLowerCase())) {
32
+ matchedWords.push(word);
33
+ return true;
34
+ }
35
+ return false;
36
+ }).length;
37
+ if (matchCount > 0) {
38
+ return type;
39
+ }
40
+ }
41
+ if (this.requiresComplexReasoning(prompt)) {
42
+ return "logical";
43
+ }
44
+ return false;
45
+ }
46
+ /**
47
+ * 判断是否需要复杂推理
48
+ */
49
+ requiresComplexReasoning(prompt) {
50
+ const complexityIndicators = [
51
+ "\u6B65\u9AA4",
52
+ "\u6D41\u7A0B",
53
+ "\u8FC7\u7A0B",
54
+ "\u65B9\u6CD5",
55
+ "\u601D\u8DEF",
56
+ "\u8BE6\u7EC6",
57
+ "\u89E3\u91CA",
58
+ "\u4E3A\u4EC0\u4E48",
59
+ "\u5982\u4F55",
60
+ "\u600E\u6837",
61
+ "\u5982\u679C",
62
+ "\u90A3\u4E48",
63
+ "\u9996\u5148",
64
+ "\u5176\u6B21",
65
+ "\u6700\u540E",
66
+ "\u6BD4\u8F83",
67
+ "\u5BF9\u6BD4",
68
+ "\u9009\u62E9",
69
+ "\u5224\u65AD",
70
+ "\u8003\u8651",
71
+ "\u7EFC\u5408",
72
+ "\u603B\u7ED3"
73
+ ];
74
+ return complexityIndicators.some(
75
+ (indicator) => prompt.toLowerCase().includes(indicator.toLowerCase())
76
+ );
77
+ }
78
+ /**
79
+ * 获取用户消息内容
80
+ */
81
+ getUserMessage(request) {
82
+ const messages = request.messages || [];
83
+ const lastMessage = messages[messages.length - 1];
84
+ if (!lastMessage || lastMessage.role !== "user") {
85
+ return "";
86
+ }
87
+ if (Array.isArray(lastMessage.content)) {
88
+ return lastMessage.content.filter((item) => item.type === "text").map((item) => item.text || "").join("\n");
89
+ }
90
+ return lastMessage.content || "";
91
+ }
92
+ /**
93
+ * 转换请求输入 - 添加thinking参数
94
+ */
95
+ async transformRequestIn(request) {
96
+ if (!this.enabled) return request;
97
+ try {
98
+ const { thinking, ...requestWithoutThinking } = request;
99
+ const userMessage = this.getUserMessage(requestWithoutThinking);
100
+ if (this.enabled) {
101
+ const thinkingType = this.detectThinkingType(userMessage);
102
+ if (thinkingType) {
103
+ console.log(`\u{1F4A1} GLM\u601D\u8003\u4E2D... \u542F\u7528${thinkingType}\u7C7B\u578B\u601D\u7EF4\u6A21\u5F0F`);
104
+ return {
105
+ ...requestWithoutThinking,
106
+ thinking: {
107
+ type: "enabled",
108
+ category: thinkingType
109
+ }
110
+ };
111
+ }
112
+ }
113
+ return requestWithoutThinking;
114
+ } catch (error) {
115
+ console.error("\u8F6C\u6362\u8BF7\u6C42\u65F6\u53D1\u751F\u9519\u8BEF", {
116
+ error: error.message,
117
+ stack: error.stack
118
+ });
119
+ return request;
120
+ }
121
+ }
122
+ /**
123
+ * 转换响应输出 - 处理thinking响应
124
+ * 目前暂未实现,预留接口
125
+ */
126
+ async transformResponseOut(response) {
127
+ return response;
128
+ }
129
+ };
130
+ module.exports = GLMThinkingTransformer;
@@ -0,0 +1,167 @@
1
+ "use strict";
2
+ var __create = Object.create;
3
+ var __defProp = Object.defineProperty;
4
+ var __getOwnPropDesc = Object.getOwnPropertyDescriptor;
5
+ var __getOwnPropNames = Object.getOwnPropertyNames;
6
+ var __getProtoOf = Object.getPrototypeOf;
7
+ var __hasOwnProp = Object.prototype.hasOwnProperty;
8
+ var __commonJS = (cb, mod) => function __require() {
9
+ return mod || (0, cb[__getOwnPropNames(cb)[0]])((mod = { exports: {} }).exports, mod), mod.exports;
10
+ };
11
+ var __copyProps = (to, from, except, desc) => {
12
+ if (from && typeof from === "object" || typeof from === "function") {
13
+ for (let key of __getOwnPropNames(from))
14
+ if (!__hasOwnProp.call(to, key) && key !== except)
15
+ __defProp(to, key, { get: () => from[key], enumerable: !(desc = __getOwnPropDesc(from, key)) || desc.enumerable });
16
+ }
17
+ return to;
18
+ };
19
+ var __reExport = (target, mod, secondTarget) => (__copyProps(target, mod, "default"), secondTarget && __copyProps(secondTarget, mod, "default"));
20
+ var __toESM = (mod, isNodeMode, target) => (target = mod != null ? __create(__getProtoOf(mod)) : {}, __copyProps(
21
+ // If the importer is in node compatibility mode or this is not an ESM
22
+ // file that has been converted to a CommonJS file using a Babel-
23
+ // compatible transform (i.e. "__esModule" has not been set), then set
24
+ // "default" to the CommonJS "module.exports" for node compatibility.
25
+ isNodeMode || !mod || !mod.__esModule ? __defProp(target, "default", { value: mod, enumerable: true }) : target,
26
+ mod
27
+ ));
28
+ var __toCommonJS = (mod) => __copyProps(__defProp({}, "__esModule", { value: true }), mod);
29
+
30
+ // src/transformers/glm-thinking.ts
31
+ var require_glm_thinking = __commonJS({
32
+ "src/transformers/glm-thinking.ts"(exports2, module2) {
33
+ "use strict";
34
+ var GLMThinkingTransformer = class {
35
+ name;
36
+ enabled;
37
+ debug;
38
+ constructor(options = {}) {
39
+ this.name = "glm-thinking";
40
+ this.enabled = options.enabled !== "false" && options.enabled !== false;
41
+ this.debug = options.debug !== "false" && options.debug !== false || false;
42
+ console.log("\u{1F4A1}GLM\u601D\u8003\u6A21\u5F0F\u8F6C\u6362\u5668\u5DF2\u6FC0\u6D3B", { enabled: this.enabled });
43
+ }
44
+ /**
45
+ * 检测思维链类型
46
+ */
47
+ detectThinkingType(prompt) {
48
+ const keywords = {
49
+ mathematical: ["\u8BA1\u7B97", "\u6570\u5B66", "\u516C\u5F0F", "\u65B9\u7A0B", "\u51E0\u4F55", "\u4EE3\u6570", "calculate", "math", "formula", "\u6C42\u89E3", "\u51FD\u6570", "\u79EF\u5206", "\u5BFC\u6570", "\u6781\u9650", "\u8BC1\u660E\u9898"],
50
+ logical: ["\u903B\u8F91", "\u63A8\u7406", "\u8BC1\u660E", "\u6F14\u7ECE", "\u5F52\u7EB3", "logic", "reasoning", "proof", "\u63A8\u65AD", "\u5047\u8BBE", "\u7ED3\u8BBA"],
51
+ causal: ["\u539F\u56E0", "\u7ED3\u679C", "\u56E0\u679C", "\u5F71\u54CD", "\u5BFC\u81F4", "cause", "effect", "impact", "\u5206\u6790", "\u9884\u6D4B", "\u5173\u7CFB"],
52
+ analytical: ["\u5206\u6790", "\u5206\u89E3", "\u8BC4\u4F30", "\u5224\u65AD", "analyze", "evaluate", "assess", "\u6BD4\u8F83", "\u603B\u7ED3", "\u4F18\u7F3A\u70B9"],
53
+ creative: ["\u521B\u610F", "\u521B\u65B0", "\u60F3\u8C61", "\u8BBE\u8BA1", "creative", "innovative", "design", "\u6784\u601D", "\u4F18\u5316", "\u6539\u8FDB"],
54
+ strategic: ["\u7B56\u7565", "\u8BA1\u5212", "\u51B3\u7B56", "\u9009\u62E9", "strategy", "plan", "decision", "\u65B9\u6848", "\u5EFA\u8BAE", "\u89C4\u5212"],
55
+ programming: ["\u4EE3\u7801", "\u7F16\u7A0B", "\u7B97\u6CD5", "\u7A0B\u5E8F", "code", "algorithm", "function", "\u5B9E\u73B0", "\u5F00\u53D1", "\u8C03\u8BD5"],
56
+ problem_solving: ["\u95EE\u9898", "\u89E3\u51B3", "\u65B9\u6CD5", "\u6B65\u9AA4", "problem", "solve", "solution", "\u601D\u8DEF", "\u6D41\u7A0B"]
57
+ };
58
+ for (const [type, words] of Object.entries(keywords)) {
59
+ const matchedWords = [];
60
+ const matchCount = words.filter((word) => {
61
+ if (prompt.toLowerCase().includes(word.toLowerCase())) {
62
+ matchedWords.push(word);
63
+ return true;
64
+ }
65
+ return false;
66
+ }).length;
67
+ if (matchCount > 0) {
68
+ return type;
69
+ }
70
+ }
71
+ if (this.requiresComplexReasoning(prompt)) {
72
+ return "logical";
73
+ }
74
+ return false;
75
+ }
76
+ /**
77
+ * 判断是否需要复杂推理
78
+ */
79
+ requiresComplexReasoning(prompt) {
80
+ const complexityIndicators = [
81
+ "\u6B65\u9AA4",
82
+ "\u6D41\u7A0B",
83
+ "\u8FC7\u7A0B",
84
+ "\u65B9\u6CD5",
85
+ "\u601D\u8DEF",
86
+ "\u8BE6\u7EC6",
87
+ "\u89E3\u91CA",
88
+ "\u4E3A\u4EC0\u4E48",
89
+ "\u5982\u4F55",
90
+ "\u600E\u6837",
91
+ "\u5982\u679C",
92
+ "\u90A3\u4E48",
93
+ "\u9996\u5148",
94
+ "\u5176\u6B21",
95
+ "\u6700\u540E",
96
+ "\u6BD4\u8F83",
97
+ "\u5BF9\u6BD4",
98
+ "\u9009\u62E9",
99
+ "\u5224\u65AD",
100
+ "\u8003\u8651",
101
+ "\u7EFC\u5408",
102
+ "\u603B\u7ED3"
103
+ ];
104
+ return complexityIndicators.some(
105
+ (indicator) => prompt.toLowerCase().includes(indicator.toLowerCase())
106
+ );
107
+ }
108
+ /**
109
+ * 获取用户消息内容
110
+ */
111
+ getUserMessage(request) {
112
+ const messages = request.messages || [];
113
+ const lastMessage = messages[messages.length - 1];
114
+ if (!lastMessage || lastMessage.role !== "user") {
115
+ return "";
116
+ }
117
+ if (Array.isArray(lastMessage.content)) {
118
+ return lastMessage.content.filter((item) => item.type === "text").map((item) => item.text || "").join("\n");
119
+ }
120
+ return lastMessage.content || "";
121
+ }
122
+ /**
123
+ * 转换请求输入 - 添加thinking参数
124
+ */
125
+ async transformRequestIn(request) {
126
+ if (!this.enabled) return request;
127
+ try {
128
+ const { thinking, ...requestWithoutThinking } = request;
129
+ const userMessage = this.getUserMessage(requestWithoutThinking);
130
+ if (this.enabled) {
131
+ const thinkingType = this.detectThinkingType(userMessage);
132
+ if (thinkingType) {
133
+ console.log(`\u{1F4A1} GLM\u601D\u8003\u4E2D... \u542F\u7528${thinkingType}\u7C7B\u578B\u601D\u7EF4\u6A21\u5F0F`);
134
+ return {
135
+ ...requestWithoutThinking,
136
+ thinking: {
137
+ type: "enabled",
138
+ category: thinkingType
139
+ }
140
+ };
141
+ }
142
+ }
143
+ return requestWithoutThinking;
144
+ } catch (error) {
145
+ console.error("\u8F6C\u6362\u8BF7\u6C42\u65F6\u53D1\u751F\u9519\u8BEF", {
146
+ error: error.message,
147
+ stack: error.stack
148
+ });
149
+ return request;
150
+ }
151
+ }
152
+ /**
153
+ * 转换响应输出 - 处理thinking响应
154
+ * 目前暂未实现,预留接口
155
+ */
156
+ async transformResponseOut(response) {
157
+ return response;
158
+ }
159
+ };
160
+ module2.exports = GLMThinkingTransformer;
161
+ }
162
+ });
163
+
164
+ // src/transformers/index.ts
165
+ var index_exports = {};
166
+ module.exports = __toCommonJS(index_exports);
167
+ __reExport(index_exports, __toESM(require_glm_thinking()), module.exports);
@@ -0,0 +1,166 @@
1
+ # 外部规则功能说明
2
+
3
+ ## 概述
4
+
5
+ 统一路由引擎支持通过 `externalFunction` 条件类型加载外部 JavaScript 文件中的自定义规则。这使得路由系统更加灵活,可以动态加载和执行复杂的业务逻辑。
6
+
7
+ ## 功能特点
8
+
9
+ 1. **动态加载**:运行时动态导入外部 JS 文件
10
+ 2. **函数执行**:支持调用外部文件中的指定函数
11
+ 3. **错误处理**:完善的错误捕获和日志记录
12
+ 4. **安全检查**:验证函数类型和返回值
13
+
14
+ ## 使用方法
15
+
16
+ ### 1. 定义外部规则
17
+
18
+ 在配置文件中,使用 `externalFunction` 条件类型:
19
+
20
+ ```json
21
+ {
22
+ "name": "规则名称",
23
+ "condition": {
24
+ "type": "externalFunction",
25
+ "externalFunction": {
26
+ "path": "./path/to/external/rule.js",
27
+ "functionName": "functionName"
28
+ }
29
+ },
30
+ "action": {
31
+ "route": "target-route"
32
+ }
33
+ }
34
+ ```
35
+
36
+ ### 2. 外部规则文件格式
37
+
38
+ 外部 JS 文件需要导出一个或多个函数:
39
+
40
+ ```javascript
41
+ // single-function-export.js
42
+ function myCondition(context) {
43
+ // 实现你的逻辑
44
+ return true; // 返回布尔值
45
+ }
46
+
47
+ module.exports = {
48
+ myCondition
49
+ };
50
+ ```
51
+
52
+ 或使用 ES6 模块语法:
53
+
54
+ ```javascript
55
+ // multi-function-export.js
56
+ export function condition1(context) {
57
+ return context.tokenCount > 1000;
58
+ }
59
+
60
+ export function condition2(context) {
61
+ return context.req?.headers?.['x-premium'] === 'true';
62
+ }
63
+ ```
64
+
65
+ ### 3. 上下文参数
66
+
67
+ 外部函数接收一个 `RouteContext` 对象,包含:
68
+
69
+ - `tokenCount`: Token 数量
70
+ - `messages`: 消息数组
71
+ - `system`: 系统消息
72
+ - `tools`: 工具数组
73
+ - `sessionId`: 会话 ID
74
+ - `lastUsage`: 上次使用记录
75
+ - `log`: 日志对象
76
+ - `event`: 事件对象
77
+ - `req`: 完整请求对象
78
+
79
+ ## 示例规则
80
+
81
+ ### 1. 用户偏好路由
82
+
83
+ 根据用户邮箱或ID路由到偏好模型:
84
+
85
+ ```javascript
86
+ // user-preference.js
87
+ const userPreferences = {
88
+ 'user@example.com': { provider: 'openai', model: 'gpt-4' },
89
+ 'admin@example.com': { provider: 'anthropic', model: 'claude-3' }
90
+ };
91
+
92
+ function checkUserPreference(context) {
93
+ const userEmail = extractUserEmail(context);
94
+ const preference = userPreferences[userEmail];
95
+ return preference !== undefined;
96
+ }
97
+ ```
98
+
99
+ ### 2. 时间路由
100
+
101
+ 根据当前时间路由到不同模型:
102
+
103
+ ```javascript
104
+ // time-based.js
105
+ function isBusinessHours(context) {
106
+ const hour = new Date().getHours();
107
+ const isWeekday = [1,2,3,4,5].includes(new Date().getDay());
108
+ return isWeekday && hour >= 9 && hour < 18;
109
+ }
110
+ ```
111
+
112
+ ### 3. 复杂条件路由
113
+
114
+ 组合多个条件进行决策:
115
+
116
+ ```javascript
117
+ // complex-routing.js
118
+ function evaluateComplexCondition(context) {
119
+ const hasCodeTools = checkForCodeTools(context.tools);
120
+ const isComplexTask = analyzeComplexity(context.messages);
121
+ const hasLongContext = context.tokenCount > 10000;
122
+
123
+ return hasCodeTools && isComplexTask && hasLongContext;
124
+ }
125
+ ```
126
+
127
+ ## 最佳实践
128
+
129
+ 1. **错误处理**:始终使用 try-catch 包装可能出错的代码
130
+ 2. **日志记录**:使用 `console.log` 记录调试信息
131
+ 3. **返回值**:确保返回布尔值,路由系统会自动转换
132
+ 4. **模块化**:将相关逻辑分组到不同文件
133
+ 5. **测试**:在生产环境使用前充分测试
134
+
135
+ ## 安全考虑
136
+
137
+ 1. **路径验证**:系统会验证文件路径的合法性
138
+ 2. **函数检查**:确保导出的是有效函数
139
+ 3. **执行隔离**:外部函数错误不会影响主路由系统
140
+ 4. **日志审计**:所有执行都会被记录
141
+
142
+ ## 加载机制
143
+
144
+ 1. 系统在评估规则时动态 `import()` 外部模块
145
+ 2. 支持相对路径(相对于配置文件)
146
+ 3. 缓存机制:导入的模块会被 Node.js 缓存
147
+ 4. 异步支持:外部函数可以是异步的
148
+
149
+ ## 调试技巧
150
+
151
+ 在配置中启用调试模式可以看到详细的外部函数执行日志:
152
+
153
+ ```json
154
+ {
155
+ "debug": {
156
+ "enabled": true,
157
+ "logLevel": "debug"
158
+ }
159
+ }
160
+ ```
161
+
162
+ 日志会显示:
163
+ - 外部函数路径
164
+ - 执行参数
165
+ - 返回结果
166
+ - 任何错误信息
@@ -0,0 +1,82 @@
1
+ {
2
+ "engine": "unified",
3
+ "defaultRoute": "gpt-4,openai",
4
+ "rules": [
5
+ {
6
+ "name": "userPreferenceRouting",
7
+ "priority": 100,
8
+ "enabled": true,
9
+ "condition": {
10
+ "type": "externalFunction",
11
+ "externalFunction": {
12
+ "path": "./external-rules/user-preference.js",
13
+ "functionName": "checkUserPreference"
14
+ }
15
+ },
16
+ "action": {
17
+ "route": "gpt-4,openai"
18
+ }
19
+ },
20
+ {
21
+ "name": "timeBasedRouting",
22
+ "priority": 90,
23
+ "enabled": true,
24
+ "condition": {
25
+ "type": "externalFunction",
26
+ "externalFunction": {
27
+ "path": "./external-rules/time-based.js",
28
+ "functionName": "isBusinessHours"
29
+ }
30
+ },
31
+ "action": {
32
+ "route": "claude-3-opus,anthropic"
33
+ }
34
+ },
35
+ {
36
+ "name": "peakHoursRouting",
37
+ "priority": 85,
38
+ "enabled": true,
39
+ "condition": {
40
+ "type": "externalFunction",
41
+ "externalFunction": {
42
+ "path": "./external-rules/time-based.js",
43
+ "functionName": "isPeakHours"
44
+ }
45
+ },
46
+ "action": {
47
+ "route": "gemini-pro,google"
48
+ }
49
+ },
50
+ {
51
+ "name": "complexRouting",
52
+ "priority": 80,
53
+ "enabled": true,
54
+ "condition": {
55
+ "type": "externalFunction",
56
+ "externalFunction": {
57
+ "path": "./external-rules/complex-routing.js",
58
+ "functionName": "evaluateComplexCondition"
59
+ }
60
+ },
61
+ "action": {
62
+ "route": "claude-3-sonnet,anthropic"
63
+ }
64
+ }
65
+ ],
66
+ "cache": {
67
+ "enabled": true,
68
+ "maxSize": 1000,
69
+ "ttl": 300000
70
+ },
71
+ "debug": {
72
+ "enabled": true,
73
+ "logLevel": "debug",
74
+ "logToFile": true,
75
+ "logToConsole": true,
76
+ "logDir": "./logs"
77
+ },
78
+ "contextThreshold": {
79
+ "default": 1000,
80
+ "longContext": 60000
81
+ }
82
+ }