@jsonstudio/rcc 0.89.1457 → 0.89.1489
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/configsamples/config.json +12 -4
- package/dist/build-info.js +2 -2
- package/dist/client/gemini-cli/gemini-cli-protocol-client.js +53 -26
- package/dist/client/gemini-cli/gemini-cli-protocol-client.js.map +1 -1
- package/dist/manager/modules/quota/antigravity-quota-manager.d.ts +4 -0
- package/dist/manager/modules/quota/antigravity-quota-manager.js +130 -2
- package/dist/manager/modules/quota/antigravity-quota-manager.js.map +1 -1
- package/dist/manager/modules/quota/provider-quota-daemon.events.js +63 -2
- package/dist/manager/modules/quota/provider-quota-daemon.events.js.map +1 -1
- package/dist/modules/llmswitch/bridge.js +17 -4
- package/dist/modules/llmswitch/bridge.js.map +1 -1
- package/dist/modules/llmswitch/core-loader.d.ts +1 -1
- package/dist/modules/llmswitch/core-loader.js +15 -3
- package/dist/modules/llmswitch/core-loader.js.map +1 -1
- package/dist/providers/auth/antigravity-userinfo-helper.d.ts +3 -1
- package/dist/providers/auth/antigravity-userinfo-helper.js +41 -7
- package/dist/providers/auth/antigravity-userinfo-helper.js.map +1 -1
- package/dist/providers/auth/gemini-cli-userinfo-helper.js +66 -4
- package/dist/providers/auth/gemini-cli-userinfo-helper.js.map +1 -1
- package/dist/providers/auth/oauth-lifecycle.js +112 -1
- package/dist/providers/auth/oauth-lifecycle.js.map +1 -1
- package/dist/providers/auth/tokenfile-auth.d.ts +12 -0
- package/dist/providers/auth/tokenfile-auth.js +92 -1
- package/dist/providers/auth/tokenfile-auth.js.map +1 -1
- package/dist/providers/core/runtime/gemini-cli-http-provider.d.ts +0 -1
- package/dist/providers/core/runtime/gemini-cli-http-provider.js +118 -78
- package/dist/providers/core/runtime/gemini-cli-http-provider.js.map +1 -1
- package/dist/providers/core/runtime/http-transport-provider.js +10 -3
- package/dist/providers/core/runtime/http-transport-provider.js.map +1 -1
- package/dist/runtime/wasm-runtime/wasm-config.d.ts +73 -0
- package/dist/runtime/wasm-runtime/wasm-config.js +124 -0
- package/dist/runtime/wasm-runtime/wasm-config.js.map +1 -0
- package/dist/runtime/wasm-runtime/wasm-loader.d.ts +40 -0
- package/dist/runtime/wasm-runtime/wasm-loader.js +62 -0
- package/dist/runtime/wasm-runtime/wasm-loader.js.map +1 -0
- package/dist/server/runtime/http-server/index.js +53 -1
- package/dist/server/runtime/http-server/index.js.map +1 -1
- package/docs/antigravity-gemini-format-cleanup.md +54 -13
- package/docs/llms-wasm-migration.md +331 -0
- package/docs/llms-wasm-module-boundaries.md +588 -0
- package/docs/llms-wasm-replay-baseline.md +171 -0
- package/docs/plans/llms-wasm-migration-plan.md +401 -0
- package/package.json +2 -2
- package/scripts/antigravity-token-bridge.mjs +283 -0
|
@@ -0,0 +1,588 @@
|
|
|
1
|
+
---
|
|
2
|
+
title: "llms-wasm 模块边界清单"
|
|
3
|
+
tags:
|
|
4
|
+
- wasm
|
|
5
|
+
- architecture
|
|
6
|
+
- migration
|
|
7
|
+
status: planning
|
|
8
|
+
created: 2026-01-26
|
|
9
|
+
---
|
|
10
|
+
|
|
11
|
+
# llms-wasm 模块边界清单
|
|
12
|
+
|
|
13
|
+
> [!important] 用途
|
|
14
|
+
> 本文档用于:
|
|
15
|
+
> - 明确替换顺序(低风险 → 高风险)
|
|
16
|
+
> - diff 归因(责任归属与修复路径)
|
|
17
|
+
> - 验收与回滚(模块级开关与状态)
|
|
18
|
+
>
|
|
19
|
+
> **责任边界**:Host 只做开关读取/影子分发/指标上报;canonicalization、routing、tools、compat、diff 协议全部在 llmswitch-core。
|
|
20
|
+
|
|
21
|
+
---
|
|
22
|
+
|
|
23
|
+
## 核心原则
|
|
24
|
+
|
|
25
|
+
| 原则 | 说明 | 违反后果 |
|
|
26
|
+
|------|------|----------|
|
|
27
|
+
| **Host 不做修复** | Host 只做开关读取/影子分发/指标上报;不得做 canonicalization、tool 修复、路由决策或 diff 计算 | 违反架构原则,导致职责混乱 |
|
|
28
|
+
| **Core 拥有协议** | 所有 canonicalization、diff ruleset、比较逻辑都在 llmswitch-core | Host 无法复用 diff 能力 |
|
|
29
|
+
| **Provider 是传输** | Provider V2 只负责 auth、HTTP、retries;不解读用户 payload 语义 | 导致旁路单执行路径 |
|
|
30
|
+
| **Fail fast** | 任何上游错误通过 `providerErrorCenter` + `errorHandlingCenter` 冒泡 | 错误被吞没,难以追踪 |
|
|
31
|
+
|
|
32
|
+
> [!important] 统一策略(本轮明确)
|
|
33
|
+
> 1. **统一 tokenizer**:只保留一个权威实现(单一 source of truth),TS/WASM 对齐该实现;禁止多套 tokenizer 并存。
|
|
34
|
+
> 2. **统一 SSE event 协议**:定义唯一 canonical SSE event schema 与对比协议(event + token 级)。
|
|
35
|
+
> 3. **统一 compat profile**:compat profile 规则与触发条件在 llmswitch-core 中统一维护(单一版本化来源)。
|
|
36
|
+
|
|
37
|
+
---
|
|
38
|
+
|
|
39
|
+
## 统一策略落地
|
|
40
|
+
|
|
41
|
+
### A. 统一 tokenizer(single source of truth)
|
|
42
|
+
|
|
43
|
+
> [!important] 目标
|
|
44
|
+
> TS 与 WASM 只保留 **一个权威 tokenizer 实现**;其余入口必须代理到该实现。
|
|
45
|
+
|
|
46
|
+
**建议落地方式**:
|
|
47
|
+
|
|
48
|
+
- 统一入口(示例):`llmswitch-core/src/conversion/shared/tokenizer.ts`
|
|
49
|
+
- TS 与 WASM 入口都 **调用同一接口**(避免各自维护逻辑)
|
|
50
|
+
- 所有 thinking/reasoning 归一规则与 token 化规则 **只定义一次**
|
|
51
|
+
|
|
52
|
+
**约束**:
|
|
53
|
+
|
|
54
|
+
- 禁止在 Host/Provider 做 token 修复
|
|
55
|
+
- 禁止在 compat/adapter 里做 token 相关逻辑
|
|
56
|
+
|
|
57
|
+
### B. 统一 SSE event 协议(canonical + diff)
|
|
58
|
+
|
|
59
|
+
> [!important] 目标
|
|
60
|
+
> 统一 SSE event schema 与对比协议,版本化管理(`sse_protocol_vN`)。
|
|
61
|
+
|
|
62
|
+
**Canonical schema**:
|
|
63
|
+
|
|
64
|
+
- `event_type`(data/error/done)
|
|
65
|
+
- `ordinal_index`(顺序索引)
|
|
66
|
+
- `normalized_payload`(稳定化 payload)
|
|
67
|
+
- `token_digest`(可选,用于 token 级一致性)
|
|
68
|
+
|
|
69
|
+
**比较规则**:
|
|
70
|
+
|
|
71
|
+
- 允许 chunk 拆包差异
|
|
72
|
+
- 以 token 序列一致为通过
|
|
73
|
+
- diff 结果必须绑定 ruleset 版本
|
|
74
|
+
|
|
75
|
+
### C. 统一 compat profile
|
|
76
|
+
|
|
77
|
+
> [!important] 当前实现
|
|
78
|
+
> compat profiles 已在 `llmswitch-core/src/conversion/compat/profiles/*.json` 中集中定义,并通过 `compat-engine.ts` 应用。
|
|
79
|
+
|
|
80
|
+
**约束**:
|
|
81
|
+
|
|
82
|
+
- Host/Provider 只能选择 profile(通过 `routing.target.compatibilityProfile`),不可定义/修改 profile 规则
|
|
83
|
+
- profile 规则与 diff ruleset 一样支持版本化与 audit
|
|
84
|
+
- 禁止在 Host/Provider 做 compat 相关逻辑(字段映射、协议转换)
|
|
85
|
+
|
|
86
|
+
> [!important] 目标
|
|
87
|
+
> compat profile 规则集中在 llmswitch-core,确保版本化、可回溯、可审计。
|
|
88
|
+
|
|
89
|
+
**建议落地方式**:
|
|
90
|
+
|
|
91
|
+
- 统一 registry(示例):`llmswitch-core/src/conversion/compat/compat-profile-registry.ts`
|
|
92
|
+
- compat profile 与 diff ruleset 一样支持版本化与 audit
|
|
93
|
+
- Host/Provider 只能选择 profile,不可定义/修改 profile 规则
|
|
94
|
+
|
|
95
|
+
---
|
|
96
|
+
|
|
97
|
+
## 模块清单
|
|
98
|
+
|
|
99
|
+
> [!note] Contract 定义
|
|
100
|
+
> 以下 Contract 为 TypeScript interface 草案,用于明确输入/输出结构。实际实现可能更复杂,但必须兼容这些基本字段。
|
|
101
|
+
|
|
102
|
+
### 1. tokenizer/encoding(文本与 thinking/reasoning 归一)
|
|
103
|
+
|
|
104
|
+
| 属性 | 值 |
|
|
105
|
+
|------|-----|
|
|
106
|
+
| **模块名** | tokenizer/encoding |
|
|
107
|
+
| **输入 Contract** | `text` / `messages`(视入口而定) |
|
|
108
|
+
| **输出 Contract** | `tokens` / `normalized messages` |
|
|
109
|
+
| **归属目录** | `llmswitch-core/src/conversion/shared/*`(reasoning/thinking 归一相关) |
|
|
110
|
+
| **依赖** | 无 |
|
|
111
|
+
| **Owner** | @team/core |
|
|
112
|
+
| **修复路径** | wasm core |
|
|
113
|
+
| **责任仓库** | `sharedmodule/llmswitch-core` |
|
|
114
|
+
| **入口函数** | `normalizeAnthropicMessage`, `sanitizeThinkingBlock` |
|
|
115
|
+
| **替换优先级** | 高(低风险,无依赖) |
|
|
116
|
+
| **验收阈值** | diff rate ≤ 0.01%, error rate ≤ 0.01% |
|
|
117
|
+
|
|
118
|
+
#### Contract 定义
|
|
119
|
+
|
|
120
|
+
```typescript
|
|
121
|
+
// 输入
|
|
122
|
+
interface TokenizerInput {
|
|
123
|
+
text?: string;
|
|
124
|
+
messages?: Array<{ role: string; content: string | null }>;
|
|
125
|
+
options?: {
|
|
126
|
+
preserveThinkingBlocks?: boolean;
|
|
127
|
+
stripReasoningTags?: boolean;
|
|
128
|
+
};
|
|
129
|
+
}
|
|
130
|
+
|
|
131
|
+
// 输出
|
|
132
|
+
interface TokenizerOutput {
|
|
133
|
+
tokens?: Token[];
|
|
134
|
+
messages?: Array<{ role: string; content: string | null }>;
|
|
135
|
+
metadata?: {
|
|
136
|
+
thinkingBlocksRemoved?: number;
|
|
137
|
+
reasoningTagsStripped?: number;
|
|
138
|
+
};
|
|
139
|
+
}
|
|
140
|
+
|
|
141
|
+
interface Token {
|
|
142
|
+
type: 'text' | 'thinking' | 'reasoning';
|
|
143
|
+
content: string;
|
|
144
|
+
signature?: string; // for thinking blocks
|
|
145
|
+
}
|
|
146
|
+
```
|
|
147
|
+
|
|
148
|
+
> [!note] 说明
|
|
149
|
+
> tokenizer 负责文本编码、thinking 块清理、reasoning 标签处理等。无外部依赖,适合最先替换。
|
|
150
|
+
|
|
151
|
+
---
|
|
152
|
+
|
|
153
|
+
### 2. tool canonicalization
|
|
154
|
+
|
|
155
|
+
| 属性 | 值 |
|
|
156
|
+
|------|-----|
|
|
157
|
+
| **模块名** | tool canonicalization |
|
|
158
|
+
| **输入 Contract** | `ToolCallRaw[]` |
|
|
159
|
+
| **输出 Contract** | `ToolCallCanonical[]` |
|
|
160
|
+
| **归属目录** | `llmswitch-core/src/tools/*` |
|
|
161
|
+
| **依赖** | tokenizer (args normalization) |
|
|
162
|
+
| **Owner** | @team/tools |
|
|
163
|
+
| **修复路径** | wasm core |
|
|
164
|
+
| **责任仓库** | `sharedmodule/llmswitch-core` |
|
|
165
|
+
| **入口函数** | `tool-registry.ts`, `args-json.ts`, `apply-patch/*` |
|
|
166
|
+
| **替换优先级** | 高(依赖 tokenizer) |
|
|
167
|
+
| **验收阈值** | diff rate ≤ 0.1%, error rate ≤ 0.05% |
|
|
168
|
+
|
|
169
|
+
#### Contract 定义
|
|
170
|
+
|
|
171
|
+
```typescript
|
|
172
|
+
// 输入
|
|
173
|
+
interface ToolCallRaw {
|
|
174
|
+
id: string;
|
|
175
|
+
type: 'function' | 'code_interpreter';
|
|
176
|
+
function?: {
|
|
177
|
+
name: string;
|
|
178
|
+
arguments: string | Record<string, unknown>;
|
|
179
|
+
};
|
|
180
|
+
code_interpreter?: {
|
|
181
|
+
code: string;
|
|
182
|
+
};
|
|
183
|
+
}
|
|
184
|
+
|
|
185
|
+
// 输出
|
|
186
|
+
interface ToolCallCanonical {
|
|
187
|
+
id: string; // normalized via ToolCallIdManager
|
|
188
|
+
type: 'function' | 'code_interpreter';
|
|
189
|
+
function?: {
|
|
190
|
+
name: string;
|
|
191
|
+
arguments: Record<string, unknown>; // always object
|
|
192
|
+
};
|
|
193
|
+
code_interpreter?: {
|
|
194
|
+
code: string;
|
|
195
|
+
};
|
|
196
|
+
metadata?: {
|
|
197
|
+
idStyle: 'fc' | 'preserve';
|
|
198
|
+
argsRepaired?: boolean;
|
|
199
|
+
};
|
|
200
|
+
}
|
|
201
|
+
```
|
|
202
|
+
|
|
203
|
+
> [!note] 说明
|
|
204
|
+
> tool canonicalization 负责工具调用 ID 管理、参数修复、结构化 patch 应用等。依赖 tokenizer 进行参数字符串化。
|
|
205
|
+
|
|
206
|
+
---
|
|
207
|
+
|
|
208
|
+
### 3. compat layer
|
|
209
|
+
|
|
210
|
+
| 属性 | 值 |
|
|
211
|
+
|------|-----|
|
|
212
|
+
| **模块名** | compat layer |
|
|
213
|
+
| **输入 Contract** | `UpstreamResponse` (provider-specific) |
|
|
214
|
+
| **输出 Contract** | `CanonicalResponse` (unified) |
|
|
215
|
+
| **归属目录** | `llmswitch-core/src/conversion/compat/*` |
|
|
216
|
+
| **依赖** | routing (provider config) |
|
|
217
|
+
| **Owner** | @team/compat |
|
|
218
|
+
| **修复路径** | compat adapter |
|
|
219
|
+
| **责任仓库** | `sharedmodule/llmswitch-core` |
|
|
220
|
+
| **入口函数** | `*-adapter.ts` (per provider) |
|
|
221
|
+
| **替换优先级** | 中(依赖 routing) |
|
|
222
|
+
| **验收阈值** | diff rate ≤ 0.5%, error rate ≤ 0.1% |
|
|
223
|
+
|
|
224
|
+
#### Contract 定义
|
|
225
|
+
|
|
226
|
+
```typescript
|
|
227
|
+
// 输入(provider-specific)
|
|
228
|
+
interface UpstreamResponse {
|
|
229
|
+
provider: string; // 'anthropic' | 'openai' | 'gemini' | ...
|
|
230
|
+
raw: {
|
|
231
|
+
body: unknown;
|
|
232
|
+
headers: Record<string, string>;
|
|
233
|
+
statusCode: number;
|
|
234
|
+
};
|
|
235
|
+
compatibilityProfile?: string; // e.g. 'anthropic-v1', 'openai-v1'
|
|
236
|
+
}
|
|
237
|
+
|
|
238
|
+
// 输出(unified)
|
|
239
|
+
interface CanonicalResponse {
|
|
240
|
+
id: string;
|
|
241
|
+
object: 'chat.completion' | 'chat.completion.chunk';
|
|
242
|
+
created: number;
|
|
243
|
+
model: string;
|
|
244
|
+
choices: Array<{
|
|
245
|
+
index: number;
|
|
246
|
+
message?: {
|
|
247
|
+
role: 'assistant' | 'user' | 'system' | 'tool';
|
|
248
|
+
content: string | null;
|
|
249
|
+
tool_calls?: ToolCallCanonical[];
|
|
250
|
+
};
|
|
251
|
+
delta?: {
|
|
252
|
+
role?: string;
|
|
253
|
+
content?: string;
|
|
254
|
+
tool_calls?: Array<{
|
|
255
|
+
index: number;
|
|
256
|
+
id: string;
|
|
257
|
+
function?: { name: string; arguments: string };
|
|
258
|
+
}>;
|
|
259
|
+
};
|
|
260
|
+
finish_reason: string | null;
|
|
261
|
+
}>;
|
|
262
|
+
usage?: {
|
|
263
|
+
prompt_tokens: number;
|
|
264
|
+
completion_tokens: number;
|
|
265
|
+
total_tokens: number;
|
|
266
|
+
};
|
|
267
|
+
metadata?: {
|
|
268
|
+
provider: string;
|
|
269
|
+
compatibilityProfile: string;
|
|
270
|
+
fieldsRemapped: string[];
|
|
271
|
+
};
|
|
272
|
+
}
|
|
273
|
+
```
|
|
274
|
+
|
|
275
|
+
> [!note] 说明
|
|
276
|
+
> compat layer 负责将不同 provider 的响应转换为统一的 canonical 格式。通过 `compatibilityProfile` 触发。
|
|
277
|
+
|
|
278
|
+
---
|
|
279
|
+
|
|
280
|
+
### 4. streaming (SSE)
|
|
281
|
+
|
|
282
|
+
| 属性 | 值 |
|
|
283
|
+
|------|-----|
|
|
284
|
+
| **模块名** | streaming (SSE) |
|
|
285
|
+
| **输入 Contract** | `SSEChunk[]` (raw) |
|
|
286
|
+
| **输出 Contract** | `CanonicalSSEEvents[]` (canonicalized) |
|
|
287
|
+
| **归属目录** | `llmswitch-core/src/sse/*` |
|
|
288
|
+
| **依赖** | compat (response schema) |
|
|
289
|
+
| **Owner** | @team/streaming |
|
|
290
|
+
| **修复路径** | wasm core |
|
|
291
|
+
| **责任仓库** | `sharedmodule/llmswitch-core` |
|
|
292
|
+
| **入口函数** | `json-to-sse/*`, `sse-to-json/*` |
|
|
293
|
+
| **替换优先级** | 高(依赖 compat) |
|
|
294
|
+
| **验收阈值** | diff rate ≤ 0.5%, error rate ≤ 0.1% |
|
|
295
|
+
|
|
296
|
+
#### Contract 定义
|
|
297
|
+
|
|
298
|
+
```typescript
|
|
299
|
+
// 输入(raw SSE chunk)
|
|
300
|
+
interface SSEChunk {
|
|
301
|
+
event: string; // 'data' | 'error' | 'done'
|
|
302
|
+
data: string; // JSON string
|
|
303
|
+
index?: number;
|
|
304
|
+
timestamp?: number;
|
|
305
|
+
}
|
|
306
|
+
|
|
307
|
+
// 输出(canonicalized)
|
|
308
|
+
interface CanonicalSSEEvent {
|
|
309
|
+
event_type: 'data' | 'error' | 'done';
|
|
310
|
+
ordinal_index: number;
|
|
311
|
+
normalized_payload: string;
|
|
312
|
+
token_digest?: string; // for token-level comparison
|
|
313
|
+
metadata?: {
|
|
314
|
+
chunkSplit?: boolean; // true if this is a split chunk
|
|
315
|
+
originalIndex?: number;
|
|
316
|
+
};
|
|
317
|
+
}
|
|
318
|
+
|
|
319
|
+
// Diff result
|
|
320
|
+
interface SSEDiffResult {
|
|
321
|
+
request_id: string;
|
|
322
|
+
ts_events: CanonicalSSEEvent[];
|
|
323
|
+
wasm_events: CanonicalSSEEvent[];
|
|
324
|
+
diff_summary: {
|
|
325
|
+
added: CanonicalSSEEvent[];
|
|
326
|
+
removed: CanonicalSSEEvent[];
|
|
327
|
+
reordered: boolean;
|
|
328
|
+
payload_diff: string[];
|
|
329
|
+
};
|
|
330
|
+
final_token_match: boolean; // true if final token sequences match
|
|
331
|
+
}
|
|
332
|
+
```
|
|
333
|
+
|
|
334
|
+
> [!note] 说明
|
|
335
|
+
> streaming 负责 SSE 流式响应的解码、编码、canonicalization。允许 chunk 拆包差异,但要求最终 token 序列一致。
|
|
336
|
+
|
|
337
|
+
---
|
|
338
|
+
|
|
339
|
+
### 5. routing(VirtualRouter 选路与 alias 选择)
|
|
340
|
+
|
|
341
|
+
| 属性 | 值 |
|
|
342
|
+
|------|-----|
|
|
343
|
+
| **模块名** | routing |
|
|
344
|
+
| **输入 Contract** | `RequestContext` |
|
|
345
|
+
| **输出 Contract** | `ProviderTarget` (provider + alias) |
|
|
346
|
+
| **归属目录** | `llmswitch-core/src/router/virtual-router/*` |
|
|
347
|
+
| **依赖** | tools (tool availability) |
|
|
348
|
+
| **Owner** | @team/routing |
|
|
349
|
+
| **修复路径** | wasm core |
|
|
350
|
+
| **责任仓库** | `sharedmodule/llmswitch-core` |
|
|
351
|
+
| **入口函数** | `virtual-router.ts`, `engine-selection/*` |
|
|
352
|
+
| **替换优先级** | 低(高风险,影响全局) |
|
|
353
|
+
| **验收阈值** | diff rate ≤ 0.01%, error rate ≤ 0.001% |
|
|
354
|
+
|
|
355
|
+
#### Contract 定义
|
|
356
|
+
|
|
357
|
+
```typescript
|
|
358
|
+
// 输入
|
|
359
|
+
interface RequestContext {
|
|
360
|
+
requestId: string;
|
|
361
|
+
tenant: string;
|
|
362
|
+
route: string;
|
|
363
|
+
model: string;
|
|
364
|
+
tools?: {
|
|
365
|
+
names: string[];
|
|
366
|
+
required: string[];
|
|
367
|
+
};
|
|
368
|
+
metadata?: {
|
|
369
|
+
userId?: string;
|
|
370
|
+
sessionId?: string;
|
|
371
|
+
priority?: 'high' | 'normal' | 'low';
|
|
372
|
+
};
|
|
373
|
+
}
|
|
374
|
+
|
|
375
|
+
// 输出
|
|
376
|
+
interface ProviderTarget {
|
|
377
|
+
provider: string; // provider key
|
|
378
|
+
alias: string; // specific provider instance
|
|
379
|
+
configRef?: string; // prefer referencing config rather than embedding secrets
|
|
380
|
+
compatibilityProfile?: string;
|
|
381
|
+
metadata?: {
|
|
382
|
+
selectionReason: string;
|
|
383
|
+
sticky?: boolean;
|
|
384
|
+
priorityTier?: number;
|
|
385
|
+
};
|
|
386
|
+
}
|
|
387
|
+
|
|
388
|
+
// Quota view (for health/cooldown)
|
|
389
|
+
interface ProviderQuotaViewEntry {
|
|
390
|
+
providerKey: string;
|
|
391
|
+
inPool: boolean;
|
|
392
|
+
cooldownUntil?: number;
|
|
393
|
+
blacklistUntil?: number;
|
|
394
|
+
priorityTier?: number;
|
|
395
|
+
selectionPenalty?: number;
|
|
396
|
+
lastErrorAtMs?: number;
|
|
397
|
+
consecutiveErrorCount?: number;
|
|
398
|
+
}
|
|
399
|
+
```
|
|
400
|
+
|
|
401
|
+
> [!note] 说明
|
|
402
|
+
> routing 负责根据请求上下文选择 provider 和 alias。影响所有请求,必须最后替换。
|
|
403
|
+
|
|
404
|
+
### 1. tokenizer/encoding
|
|
405
|
+
|
|
406
|
+
| 属性 | 值 |
|
|
407
|
+
|------|-----|
|
|
408
|
+
| **模块名** | tokenizer/encoding |
|
|
409
|
+
| **输入 Contract** | `text: string` |
|
|
410
|
+
| **输出 Contract** | `tokens: Token[]` |
|
|
411
|
+
| **归属目录** | `llmswitch-core/src/conversion/shared/*` (reasoning-normalizer, etc.) |
|
|
412
|
+
| **依赖** | 无 |
|
|
413
|
+
| **Owner** | @team/core |
|
|
414
|
+
| **修复路径** | wasm core |
|
|
415
|
+
| **责任仓库** | `sharedmodule/llmswitch-core` |
|
|
416
|
+
| **入口函数** | `normalizeAnthropicMessage`, `sanitizeThinkingBlock` |
|
|
417
|
+
| **替换优先级** | 高(低风险,无依赖) |
|
|
418
|
+
| **验收阈值** | diff rate ≤ 0.01%, error rate ≤ 0.01% |
|
|
419
|
+
|
|
420
|
+
> [!note] 说明
|
|
421
|
+
> tokenizer 负责文本编码、thinking 块清理、reasoning 标签处理等。无外部依赖,适合最先替换。
|
|
422
|
+
|
|
423
|
+
---
|
|
424
|
+
|
|
425
|
+
### 2. tool canonicalization
|
|
426
|
+
|
|
427
|
+
| 属性 | 值 |
|
|
428
|
+
|------|-----|
|
|
429
|
+
| **模块名** | tool canonicalization |
|
|
430
|
+
| **输入 Contract** | `ToolCallRaw[]` |
|
|
431
|
+
| **输出 Contract** | `ToolCallCanonical[]` |
|
|
432
|
+
| **归属目录** | `llmswitch-core/src/tools/*` |
|
|
433
|
+
| **依赖** | tokenizer (args normalization) |
|
|
434
|
+
| **Owner** | @team/tools |
|
|
435
|
+
| **修复路径** | wasm core |
|
|
436
|
+
| **责任仓库** | `sharedmodule/llmswitch-core` |
|
|
437
|
+
| **入口函数** | `tool-registry.ts`, `args-json.ts`, `apply-patch/*` |
|
|
438
|
+
| **替换优先级** | 高(依赖 tokenizer) |
|
|
439
|
+
| **验收阈值** | diff rate ≤ 0.1%, error rate ≤ 0.05% |
|
|
440
|
+
|
|
441
|
+
> [!note] 说明
|
|
442
|
+
> tool canonicalization 负责工具调用 ID 管理、参数修复、结构化 patch 应用等。依赖 tokenizer 进行参数字符串化。
|
|
443
|
+
|
|
444
|
+
---
|
|
445
|
+
|
|
446
|
+
### 3. compat layer
|
|
447
|
+
|
|
448
|
+
| 属性 | 值 |
|
|
449
|
+
|------|-----|
|
|
450
|
+
| **模块名** | compat layer |
|
|
451
|
+
| **输入 Contract** | `UpstreamResponse` (provider-specific) |
|
|
452
|
+
| **输出 Contract** | `CanonicalResponse` (unified) |
|
|
453
|
+
| **归属目录** | `llmswitch-core/src/conversion/compat/*` |
|
|
454
|
+
| **依赖** | routing (provider config) |
|
|
455
|
+
| **Owner** | @team/compat |
|
|
456
|
+
| **修复路径** | compat adapter |
|
|
457
|
+
| **责任仓库** | `sharedmodule/llmswitch-core` |
|
|
458
|
+
| **入口函数** | `*-adapter.ts` (per provider) |
|
|
459
|
+
| **替换优先级** | 中(依赖 routing) |
|
|
460
|
+
| **验收阈值** | diff rate ≤ 0.5%, error rate ≤ 0.1% |
|
|
461
|
+
|
|
462
|
+
> [!note] 说明
|
|
463
|
+
> compat layer 负责将不同 provider 的响应转换为统一的 canonical 格式。通过 `compatibilityProfile` 触发。
|
|
464
|
+
|
|
465
|
+
---
|
|
466
|
+
|
|
467
|
+
### 4. streaming (SSE)
|
|
468
|
+
|
|
469
|
+
| 属性 | 值 |
|
|
470
|
+
|------|-----|
|
|
471
|
+
| **模块名** | streaming (SSE) |
|
|
472
|
+
| **输入 Contract** | `SSEChunk[]` (raw) |
|
|
473
|
+
| **输出 Contract** | `CanonicalSSEEvents[]` (canonicalized) |
|
|
474
|
+
| **归属目录** | `llmswitch-core/src/sse/*` |
|
|
475
|
+
| **依赖** | compat (response schema) |
|
|
476
|
+
| **Owner** | @team/streaming |
|
|
477
|
+
| **修复路径** | wasm core |
|
|
478
|
+
| **责任仓库** | `sharedmodule/llmswitch-core` |
|
|
479
|
+
| **入口函数** | `json-to-sse/*`, `sse-to-json/*` |
|
|
480
|
+
| **替换优先级** | 高(依赖 compat) |
|
|
481
|
+
| **验收阈值** | diff rate ≤ 0.5%, error rate ≤ 0.1% |
|
|
482
|
+
|
|
483
|
+
> [!note] 说明
|
|
484
|
+
> streaming 负责 SSE 流式响应的解码、编码、canonicalization。允许 chunk 拆包差异,但要求最终 token 序列一致。
|
|
485
|
+
|
|
486
|
+
---
|
|
487
|
+
|
|
488
|
+
### 5. routing
|
|
489
|
+
|
|
490
|
+
| 属性 | 值 |
|
|
491
|
+
|------|-----|
|
|
492
|
+
| **模块名** | routing |
|
|
493
|
+
| **输入 Contract** | `RequestContext` |
|
|
494
|
+
| **输出 Contract** | `ProviderTarget` (provider + alias) |
|
|
495
|
+
| **归属目录** | `llmswitch-core/src/router/virtual-router/*` |
|
|
496
|
+
| **依赖** | tools (tool availability) |
|
|
497
|
+
| **Owner** | @team/routing |
|
|
498
|
+
| **修复路径** | wasm core |
|
|
499
|
+
| **责任仓库** | `sharedmodule/llmswitch-core` |
|
|
500
|
+
| **入口函数** | `virtual-router.ts`, `engine-selection/*` |
|
|
501
|
+
| **替换优先级** | 低(高风险,影响全局) |
|
|
502
|
+
| **验收阈值** | diff rate ≤ 0.01%, error rate ≤ 0.001% |
|
|
503
|
+
|
|
504
|
+
> [!note] 说明
|
|
505
|
+
> routing 负责根据请求上下文选择 provider 和 alias。影响所有请求,必须最后替换。
|
|
506
|
+
|
|
507
|
+
---
|
|
508
|
+
|
|
509
|
+
## 依赖顺序
|
|
510
|
+
|
|
511
|
+
```mermaid
|
|
512
|
+
graph TD
|
|
513
|
+
A[tokenizer/encoding] --> B[tool canonicalization]
|
|
514
|
+
B --> C[routing]
|
|
515
|
+
C --> D[compat layer]
|
|
516
|
+
D --> E[streaming SSE]
|
|
517
|
+
|
|
518
|
+
style A fill:#c8e6c9
|
|
519
|
+
style B fill:#a5d6a7
|
|
520
|
+
style C fill:#81c784
|
|
521
|
+
style D fill:#66bb6a
|
|
522
|
+
style E fill:#4caf50
|
|
523
|
+
```
|
|
524
|
+
|
|
525
|
+
**替换顺序**:
|
|
526
|
+
|
|
527
|
+
1. tokenizer/encoding(无依赖,低风险)
|
|
528
|
+
2. tool canonicalization(依赖 tokenizer)
|
|
529
|
+
3. compat layer(依赖 routing)
|
|
530
|
+
4. streaming SSE(依赖 compat)
|
|
531
|
+
5. routing(最高风险,最后替换)
|
|
532
|
+
|
|
533
|
+
> [!warning] 注意
|
|
534
|
+
> 实际替换顺序可能需要根据依赖图调整。例如,compat layer 依赖 routing,但 routing 可能依赖 tools。需要根据实际代码确认。
|
|
535
|
+
|
|
536
|
+
---
|
|
537
|
+
|
|
538
|
+
## 责任归属表
|
|
539
|
+
|
|
540
|
+
| 模块 | Owner | 修复路径 | 入口函数/文件(示例) |
|
|
541
|
+
|------|-------|----------|----------------------|
|
|
542
|
+
| tokenizer/encoding | @team/core | wasm core | `llmswitch-core/src/conversion/shared/reasoning-normalizer.ts` |
|
|
543
|
+
| tool canonicalization | @team/tools | wasm core | `llmswitch-core/src/tools/tool-registry.ts` |
|
|
544
|
+
| compat layer | @team/compat | compat adapter | `llmswitch-core/src/conversion/compat/*-adapter.ts` |
|
|
545
|
+
| streaming (SSE) | @team/streaming | wasm core | `llmswitch-core/src/sse/json-to-sse/*` |
|
|
546
|
+
| routing | @team/routing | wasm core | `llmswitch-core/src/router/virtual-router/virtual-router.ts` |
|
|
547
|
+
|
|
548
|
+
> [!important] 修复入口
|
|
549
|
+
> 所有 diff 必须能被归因到“修复路径”:`compat` vs `wasm core`(Host 永远不是修复入口)。
|
|
550
|
+
|
|
551
|
+
---
|
|
552
|
+
|
|
553
|
+
## 验收阈值(按模块)
|
|
554
|
+
|
|
555
|
+
| 模块 | diff rate | error rate | latency delta (P95) | 观察期 |
|
|
556
|
+
|------|-----------|------------|--------------------|--------|
|
|
557
|
+
| tokenizer/encoding | ≤ 0.01% | ≤ 0.01% | ≤ +5ms | 1 周 |
|
|
558
|
+
| tool canonicalization | ≤ 0.1% | ≤ 0.05% | ≤ +10ms | 2 周 |
|
|
559
|
+
| compat layer | ≤ 0.5% | ≤ 0.1% | ≤ +20ms | 2 周 |
|
|
560
|
+
| streaming (SSE) | ≤ 0.5% | ≤ 0.1% | ≤ +50ms | 3 周 |
|
|
561
|
+
| routing | ≤ 0.01% | ≤ 0.001% | ≤ +5ms | 4 周 |
|
|
562
|
+
|
|
563
|
+
> [!note] 统计口径
|
|
564
|
+
> 指标必须按 `tenant`、`route`、`module`、`runtime(ts|wasm)` 分维度统计,并支持按 ruleset 版本回溯。
|
|
565
|
+
|
|
566
|
+
---
|
|
567
|
+
|
|
568
|
+
## Host 侧职责
|
|
569
|
+
|
|
570
|
+
Host (`src/server/runtime/http-server/`) 负责以下内容:
|
|
571
|
+
|
|
572
|
+
- **开关读取**:解析环境变量、config、header,确定运行模式
|
|
573
|
+
- **影子分发**:将请求异步复制到影子 runtime(TS 或 WASM)
|
|
574
|
+
- **指标上报**:通过 `providerErrorCenter` + `errorHandlingCenter` 上报 diff/error/latency
|
|
575
|
+
|
|
576
|
+
**Host 不做**:
|
|
577
|
+
|
|
578
|
+
- canonicalization、tool 修复、路由决策
|
|
579
|
+
- diff 计算、diff ruleset 管理
|
|
580
|
+
- SSE 协议处理
|
|
581
|
+
|
|
582
|
+
---
|
|
583
|
+
|
|
584
|
+
## 相关文档
|
|
585
|
+
|
|
586
|
+
- [[docs/llms-wasm-migration.md]] - 计划概要
|
|
587
|
+
- [[docs/plans/llms-wasm-migration-plan.md]] - 可执行清单
|
|
588
|
+
- [[AGENTS.md]] - 架构原则
|