@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.
Files changed (44) hide show
  1. package/configsamples/config.json +12 -4
  2. package/dist/build-info.js +2 -2
  3. package/dist/client/gemini-cli/gemini-cli-protocol-client.js +53 -26
  4. package/dist/client/gemini-cli/gemini-cli-protocol-client.js.map +1 -1
  5. package/dist/manager/modules/quota/antigravity-quota-manager.d.ts +4 -0
  6. package/dist/manager/modules/quota/antigravity-quota-manager.js +130 -2
  7. package/dist/manager/modules/quota/antigravity-quota-manager.js.map +1 -1
  8. package/dist/manager/modules/quota/provider-quota-daemon.events.js +63 -2
  9. package/dist/manager/modules/quota/provider-quota-daemon.events.js.map +1 -1
  10. package/dist/modules/llmswitch/bridge.js +17 -4
  11. package/dist/modules/llmswitch/bridge.js.map +1 -1
  12. package/dist/modules/llmswitch/core-loader.d.ts +1 -1
  13. package/dist/modules/llmswitch/core-loader.js +15 -3
  14. package/dist/modules/llmswitch/core-loader.js.map +1 -1
  15. package/dist/providers/auth/antigravity-userinfo-helper.d.ts +3 -1
  16. package/dist/providers/auth/antigravity-userinfo-helper.js +41 -7
  17. package/dist/providers/auth/antigravity-userinfo-helper.js.map +1 -1
  18. package/dist/providers/auth/gemini-cli-userinfo-helper.js +66 -4
  19. package/dist/providers/auth/gemini-cli-userinfo-helper.js.map +1 -1
  20. package/dist/providers/auth/oauth-lifecycle.js +112 -1
  21. package/dist/providers/auth/oauth-lifecycle.js.map +1 -1
  22. package/dist/providers/auth/tokenfile-auth.d.ts +12 -0
  23. package/dist/providers/auth/tokenfile-auth.js +92 -1
  24. package/dist/providers/auth/tokenfile-auth.js.map +1 -1
  25. package/dist/providers/core/runtime/gemini-cli-http-provider.d.ts +0 -1
  26. package/dist/providers/core/runtime/gemini-cli-http-provider.js +118 -78
  27. package/dist/providers/core/runtime/gemini-cli-http-provider.js.map +1 -1
  28. package/dist/providers/core/runtime/http-transport-provider.js +10 -3
  29. package/dist/providers/core/runtime/http-transport-provider.js.map +1 -1
  30. package/dist/runtime/wasm-runtime/wasm-config.d.ts +73 -0
  31. package/dist/runtime/wasm-runtime/wasm-config.js +124 -0
  32. package/dist/runtime/wasm-runtime/wasm-config.js.map +1 -0
  33. package/dist/runtime/wasm-runtime/wasm-loader.d.ts +40 -0
  34. package/dist/runtime/wasm-runtime/wasm-loader.js +62 -0
  35. package/dist/runtime/wasm-runtime/wasm-loader.js.map +1 -0
  36. package/dist/server/runtime/http-server/index.js +53 -1
  37. package/dist/server/runtime/http-server/index.js.map +1 -1
  38. package/docs/antigravity-gemini-format-cleanup.md +54 -13
  39. package/docs/llms-wasm-migration.md +331 -0
  40. package/docs/llms-wasm-module-boundaries.md +588 -0
  41. package/docs/llms-wasm-replay-baseline.md +171 -0
  42. package/docs/plans/llms-wasm-migration-plan.md +401 -0
  43. package/package.json +2 -2
  44. 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]] - 架构原则