@peterwangze/claude-trigger-router 1.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 ADDED
@@ -0,0 +1,295 @@
1
+ # Claude Trigger Router
2
+
3
+ 面向 Claude Code 的本地模型路由代理。它接管 Claude Code 发出的上游请求,再按你的规则和路由策略分发到不同模型。
4
+
5
+ 核心目标只有两件事:
6
+
7
+ - 让你用 `Models[].id` 管理模型,而不是到处手写 `provider,model`
8
+ - 让你只关心模型接入信息,消息格式转换由路由层统一处理
9
+
10
+ ## 快速开始
11
+
12
+ ### 1. 安装
13
+
14
+ ```bash
15
+ npm install -g @peterwangze/claude-trigger-router
16
+ ```
17
+
18
+ 如果 npm registry 还没有同步到最新公开包,或者当前包尚未完成首次公开发布,可以先临时改用 GitHub 安装:
19
+
20
+ ```bash
21
+ npm install -g github:peterwangze/claude-trigger-router
22
+ ```
23
+
24
+ ### 2. 运行初始化向导
25
+
26
+ ```bash
27
+ ctr setup
28
+ ```
29
+
30
+ `ctr setup` 会:
31
+
32
+ - 检查当前配置是否可复用
33
+ - 检测旧版 `~/.ccr/config.yaml`
34
+ - 尝试迁移成新的 `Models` 配置
35
+ - 提供 `openrouter` / `deepseek` / `openai-compatible` / `anthropic` / `siliconflow` / `custom` 预设
36
+ - 在需要时询问最少必要字段
37
+ - 保存配置后启动服务并进入 Claude Code
38
+
39
+ ### 3. 使用最小配置
40
+
41
+ 如果你更喜欢手动编辑,也可以先执行:
42
+
43
+ ```bash
44
+ ctr init
45
+ ```
46
+
47
+ 然后把 `~/.claude-trigger-router/config.yaml` 调整为:
48
+
49
+ ```yaml
50
+ Models:
51
+ - id: sonnet
52
+ api: "https://openrouter.ai/api/v1/chat/completions"
53
+ key: "sk-xxx"
54
+ interface: "openai"
55
+ model: "anthropic/claude-sonnet-4"
56
+ thinking: "auto"
57
+
58
+ Router:
59
+ default: "sonnet"
60
+ ```
61
+
62
+ ### 4. 启动服务
63
+
64
+ ```bash
65
+ ctr start
66
+ ```
67
+
68
+ 确认配置可用后,可改为后台运行:
69
+
70
+ ```bash
71
+ ctr start --daemon
72
+ ```
73
+
74
+ ### 5. 启动 Claude Code
75
+
76
+ ```bash
77
+ ctr code
78
+ ```
79
+
80
+ `ctr code` 会检查目标端口上是否真的是 Claude Trigger Router,然后再注入 `ANTHROPIC_BASE_URL` 并拉起 Claude Code。
81
+
82
+ ## 新配置心智
83
+
84
+ 推荐始终从 `Models` 出发。每个模型接入项描述的是“这个模型怎么连”,而不是“内部 provider 怎么拼”。
85
+
86
+ 每个模型的最少必填字段是:
87
+
88
+ | 字段 | 是否必填 | 说明 |
89
+ |------|----------|------|
90
+ | `id` | 必填 | 模型唯一标识,供 Router / TriggerRouter / SmartRouter / Governance 引用 |
91
+ | `api` | 必填 | 上游接口地址 |
92
+ | `key` | 必填 | 对应 API Key |
93
+ | `interface` | 必填 | 接口类型,当前支持 `openai` / `anthropic` |
94
+ | `model` | 必填 | 目标模型名 |
95
+ | `thinking` | 可选 | 思考强度,推荐 `off / auto / on / low / medium / high` |
96
+
97
+ 额外可选项:
98
+
99
+ - `metadata.vendor_hint`
100
+ - `metadata.supports_reasoning`
101
+ - `metadata.supports_tools`
102
+ - `metadata.supports_images`
103
+
104
+ 兼容性说明:
105
+
106
+ - 当前实现仍兼容旧字段 `api_base_url` / `api_key` / `protocol`
107
+ - 保存和对外展示优先使用新字段 `api` / `key` / `interface`
108
+ - `thinking` 既支持简写字符串,也支持 `{ mode, effort, budget_tokens }` 对象
109
+
110
+ ## 接口类型怎么选
111
+
112
+ `interface` 只表示目标上游期望的消息协议类型,不等于“厂商名”。
113
+
114
+ 常见映射如下:
115
+
116
+ | 场景 | `api` 示例 | `interface` |
117
+ |------|------------|-------------|
118
+ | OpenAI 官方 | `https://api.openai.com/v1/chat/completions` | `openai` |
119
+ | Anthropic 官方 | `https://api.anthropic.com/v1/messages` | `anthropic` |
120
+ | OpenRouter | `https://openrouter.ai/api/v1/chat/completions` | `openai` |
121
+ | DeepSeek | `https://api.deepseek.com/chat/completions` | `openai` |
122
+ | SiliconFlow / 本地兼容服务 | 对应兼容地址 | `openai` |
123
+
124
+ 路由层会按 `interface` 把统一消息转换成目标上游请求体。
125
+
126
+ 当前统一转换已覆盖:
127
+
128
+ - 文本消息
129
+ - 图片输入
130
+ - tool call / tool result
131
+ - `thinking`
132
+
133
+ 如果目标模型声明不支持某项能力,路由会做显式降级,并给出 warning。
134
+
135
+ ## 常见路由配置
136
+
137
+ ### 单模型
138
+
139
+ ```yaml
140
+ Models:
141
+ - id: sonnet
142
+ api: "https://openrouter.ai/api/v1/chat/completions"
143
+ key: "sk-xxx"
144
+ interface: "openai"
145
+ model: "anthropic/claude-sonnet-4"
146
+
147
+ Router:
148
+ default: "sonnet"
149
+ ```
150
+
151
+ ### 规则路由
152
+
153
+ ```yaml
154
+ Models:
155
+ - id: sonnet
156
+ api: "https://openrouter.ai/api/v1/chat/completions"
157
+ key: "sk-xxx"
158
+ interface: "openai"
159
+ model: "anthropic/claude-sonnet-4"
160
+
161
+ - id: opus
162
+ api: "https://openrouter.ai/api/v1/chat/completions"
163
+ key: "sk-xxx"
164
+ interface: "openai"
165
+ model: "anthropic/claude-opus-4"
166
+
167
+ Router:
168
+ default: "sonnet"
169
+
170
+ TriggerRouter:
171
+ enabled: true
172
+ analysis_scope: "last_message"
173
+ rules:
174
+ - name: "architecture"
175
+ priority: 90
176
+ enabled: true
177
+ patterns:
178
+ - type: exact
179
+ keywords: ["架构设计", "system design"]
180
+ model: "opus"
181
+ ```
182
+
183
+ ### 规则 + 智能路由
184
+
185
+ ```yaml
186
+ Models:
187
+ - id: sonnet
188
+ api: "https://openrouter.ai/api/v1/chat/completions"
189
+ key: "sk-xxx"
190
+ interface: "openai"
191
+ model: "anthropic/claude-sonnet-4"
192
+
193
+ - id: reasoner
194
+ api: "https://api.deepseek.com/chat/completions"
195
+ key: "sk-xxx"
196
+ interface: "openai"
197
+ model: "deepseek-reasoner"
198
+ thinking: "high"
199
+
200
+ Router:
201
+ default: "sonnet"
202
+ think: "reasoner"
203
+
204
+ SmartRouter:
205
+ enabled: true
206
+ router_model: "sonnet"
207
+ candidates:
208
+ - model: "sonnet"
209
+ description: "通用编程与调试"
210
+ - model: "reasoner"
211
+ description: "复杂推理与严谨分析"
212
+ ```
213
+
214
+ 完整示例见 `config/trigger.example.yaml`。
215
+
216
+ ## warning 与 capability hint
217
+
218
+ 如果你已经知道某个模型不支持完整能力,可以在配置里显式声明:
219
+
220
+ ```yaml
221
+ Models:
222
+ - id: restricted
223
+ api: "https://api.example.com/v1/chat/completions"
224
+ key: "sk-xxx"
225
+ interface: "openai"
226
+ model: "vendor/text-only"
227
+ thinking: "high"
228
+ metadata:
229
+ supports_reasoning: false
230
+ supports_tools: false
231
+ supports_images: false
232
+ ```
233
+
234
+ 当前行为:
235
+
236
+ - `supports_reasoning: false` 时,请求里的 `thinking` 会被忽略
237
+ - `supports_tools: false` 时,工具定义和 tool call/result 会退化为文本
238
+ - `supports_images: false` 时,图片块会退化为文本说明
239
+
240
+ 这些信息会出现在:
241
+
242
+ - `ctr setup` 的配置提示
243
+ - `POST /api/config` 返回的 `warnings`
244
+ - `GET /api/models/compiled`
245
+ - `/ui` 的 Draft Config Preview 和 Capability Warnings
246
+
247
+ ## `/ui` 可以做什么
248
+
249
+ 访问 `http://127.0.0.1:3456/ui` 后,可以直接:
250
+
251
+ - 编辑 `Models` 草稿
252
+ - 预览 compiled model map
253
+ - 查看 `errors / warnings / capabilityWarnings`
254
+ - 保存当前草稿配置
255
+ - 对部分 warning 执行快捷修正
256
+
257
+ `/ui` 的新增模型卡片和 Provider template 现在也共用同一份 preset 目录,不同模板会带出各自的默认模型、示例项和 placeholder。
258
+
259
+ 适合用来做配置校准,但主线配置入口仍然建议优先用 `ctr setup` 或直接编辑配置文件。
260
+
261
+ ## 旧配置迁移
262
+
263
+ 如果你还在使用旧的 `Providers + provider,model` 配置:
264
+
265
+ - 当前版本仍然兼容旧格式
266
+ - `ctr setup` 会优先尝试迁移旧 `ccr` 配置
267
+ - 路由字段推荐逐步改成直接引用 `Models[].id`
268
+
269
+ 迁移后的核心变化是:
270
+
271
+ - `provider,model` -> `modelId`
272
+ - `api_base_url` -> `api`
273
+ - `api_key` -> `key`
274
+ - `protocol` -> `interface`
275
+
276
+ 详见 `docs/models-migration-guide.md`。
277
+
278
+ ## 常用命令
279
+
280
+ ```bash
281
+ ctr setup
282
+ ctr init
283
+ ctr start
284
+ ctr start --daemon
285
+ ctr stop
286
+ ctr restart --daemon
287
+ ctr status
288
+ ctr code
289
+ ```
290
+
291
+ ## 推荐阅读
292
+
293
+ - 配置模板与分工建议:`docs/configuration-guide.md`
294
+ - 旧配置迁移:`docs/models-migration-guide.md`
295
+ - 完整示例:`config/trigger.example.yaml`
@@ -0,0 +1,208 @@
1
+ # Claude Trigger Router 配置示例
2
+ # 复制到 ~/.claude-trigger-router/config.yaml 后,先替换 API Key 和模型名。
3
+ #
4
+ # 常见 provider preset(与 `ctr setup`、`/ui` Provider template 保持一致):
5
+ # - openrouter: https://openrouter.ai/api/v1/chat/completions
6
+ # - deepseek: https://api.deepseek.com/chat/completions
7
+ # - openai-compatible: https://api.openai.com/v1/chat/completions
8
+ # - anthropic: https://api.anthropic.com/v1/messages
9
+ # - siliconflow: https://api.siliconflow.cn/v1/chat/completions
10
+ # - custom/local: 自定义兼容地址,例如 Ollama / vLLM / one-api
11
+
12
+ HOST: "127.0.0.1"
13
+ PORT: 3456
14
+
15
+ LOG: true
16
+ LOG_LEVEL: "debug"
17
+
18
+ # 1) Models:推荐优先使用的简化模型接入配置
19
+ Models:
20
+ - id: sonnet
21
+ api: "https://openrouter.ai/api/v1/chat/completions"
22
+ key: "sk-xxx"
23
+ interface: "openai"
24
+ model: "anthropic/claude-sonnet-4"
25
+ thinking: "auto"
26
+
27
+ - id: opus
28
+ api: "https://openrouter.ai/api/v1/chat/completions"
29
+ key: "sk-xxx"
30
+ interface: "openai"
31
+ model: "anthropic/claude-opus-4"
32
+
33
+ - id: deepseek_reasoner
34
+ api: "https://api.deepseek.com/chat/completions"
35
+ key: "sk-xxx"
36
+ interface: "openai"
37
+ model: "deepseek-reasoner"
38
+ thinking: "high"
39
+
40
+ - id: ollama_qwen
41
+ api: "http://localhost:11434/v1/chat/completions"
42
+ key: "ollama"
43
+ interface: "openai"
44
+ model: "qwen2.5-coder:latest"
45
+ thinking: "off"
46
+
47
+ # 2) Router:推荐直接引用 model id
48
+ Router:
49
+ default: "sonnet"
50
+ background: "ollama_qwen"
51
+ think: "deepseek_reasoner"
52
+ longContext: "opus"
53
+ longContextThreshold: 60000
54
+ webSearch: "sonnet"
55
+
56
+ # 3) TriggerRouter:高确定性任务优先走规则路由
57
+ TriggerRouter:
58
+ enabled: true
59
+ analysis_scope: "last_message"
60
+ llm_intent_recognition: false
61
+ rules:
62
+ - name: "architecture"
63
+ priority: 90
64
+ enabled: true
65
+ description: "架构设计与系统方案任务"
66
+ patterns:
67
+ - type: exact
68
+ keywords:
69
+ - "架构设计"
70
+ - "系统设计"
71
+ - "技术方案"
72
+ - "architecture"
73
+ - "system design"
74
+ - type: regex
75
+ pattern: "(架构|系统设计|技术方案)"
76
+ model: "opus"
77
+
78
+ - name: "code_review"
79
+ priority: 80
80
+ enabled: true
81
+ description: "代码审查与风险评估任务"
82
+ patterns:
83
+ - type: exact
84
+ keywords:
85
+ - "代码审查"
86
+ - "code review"
87
+ - "review code"
88
+ - "检查代码"
89
+ - type: regex
90
+ pattern: "(代码|code).{0,5}(审查|review|检查|审核)"
91
+ model: "sonnet"
92
+
93
+ - name: "complex_reasoning"
94
+ priority: 70
95
+ enabled: true
96
+ description: "复杂推理与严谨分析任务"
97
+ patterns:
98
+ - type: exact
99
+ keywords:
100
+ - "深入分析"
101
+ - "复杂推理"
102
+ - "逻辑推理"
103
+ - "deep analysis"
104
+ - "reasoning"
105
+ - type: regex
106
+ pattern: "(深入|复杂|详细).{0,5}(分析|推理|解析)"
107
+ model: "deepseek_reasoner"
108
+
109
+ - name: "simple_task"
110
+ priority: 10
111
+ enabled: true
112
+ description: "快速简单任务"
113
+ patterns:
114
+ - type: exact
115
+ keywords:
116
+ - "快速"
117
+ - "简单"
118
+ - "quick"
119
+ - "simple"
120
+ model: "ollama_qwen"
121
+
122
+ # 4) SmartRouter:规则没命中时,让路由模型从候选模型中挑选
123
+ SmartRouter:
124
+ enabled: true
125
+ router_model: "sonnet"
126
+ candidates:
127
+ - model: "sonnet"
128
+ description: "通用编程、代码生成、日常调试、多轮对话"
129
+
130
+ - model: "deepseek_reasoner"
131
+ description: "复杂推理、逻辑分析、需要严谨思考的任务"
132
+
133
+ - model: "opus"
134
+ description: "架构设计、系统规划、长文档与复杂评审任务"
135
+
136
+ cache_ttl: 600000
137
+ max_tokens: 256
138
+ fallback: "default"
139
+
140
+ # 5) Governance:治理配置也推荐直接引用 model id
141
+ Governance:
142
+ enabled: true
143
+
144
+ sticky:
145
+ enabled: true
146
+ session_ttl_ms: 3600000
147
+ fingerprint_similarity_threshold: 0.82
148
+ break_on_explicit_route: true
149
+ alignment:
150
+ enabled: true
151
+ summarizer_model: "sonnet"
152
+ max_summary_tokens: 256
153
+
154
+ cascade:
155
+ enabled: true
156
+ max_attempts: 2
157
+ triggers:
158
+ compile_failure: true
159
+ test_failure: true
160
+ placeholder_patterns:
161
+ - "TODO"
162
+ - "...rest of code"
163
+ - "placeholder"
164
+ levels:
165
+ - from: "sonnet"
166
+ to: "opus"
167
+ reasoning: "high"
168
+
169
+ semantic:
170
+ enabled: true
171
+ mode: "embedding"
172
+ threshold: 0.2
173
+ prototypes:
174
+ architecture: "重构 系统 结构 模块 拆分 架构 设计"
175
+ code_review: "代码 审查 风险 评审 review"
176
+ complex_reasoning: "复杂 推理 分析 严谨 逻辑 reasoning"
177
+
178
+ shadow:
179
+ enabled: true
180
+ mode: "async_audit"
181
+ verifier_model: "sonnet"
182
+ sample_rate: 0.2
183
+ checks:
184
+ placeholder_patterns: true
185
+ length_anomaly: true
186
+ missing_code_block: true
187
+
188
+ observability:
189
+ anomaly_thresholds:
190
+ min_sample_size: 3
191
+ cascade_warn_rate: 0.4
192
+ cascade_critical_rate: 0.6
193
+ shadow_warn_rate: 0.5
194
+ shadow_critical_rate: 0.7
195
+ latency_warn_ms: 1500
196
+ latency_critical_ms: 3000
197
+ spike_warn_rate: 0.5
198
+ spike_delta_rate: 0.3
199
+
200
+ # 6) Legacy 兼容:如果你仍在使用旧配置,可继续保留 Providers
201
+ # Providers:
202
+ # - name: openrouter
203
+ # api_base_url: "https://openrouter.ai/api/v1/chat/completions"
204
+ # api_key: "sk-xxx"
205
+ # models:
206
+ # - "anthropic/claude-sonnet-4"
207
+ # transformer:
208
+ # use: ["openrouter"]