PATH = '/data/ai/audio/server/src/services/llm/index.ts' with open(PATH, 'r', encoding='utf-8') as f: src = f.read() # Fix 1: 替换 n -> node (line 142) src = src.replace( "if (!n.provider.hasModel(modelId)) continue;\n const fp = n.provider.vendor + ':' + (node.provider._apiKey || '').slice(-12);", "if (!n.provider.hasModel(modelId)) continue;\n const fp = n.provider.vendor + ':' + ((n.provider as any)._apiKey || '').slice(-12);", ) # Fix 2: pickNextModelAfterFailure 里的 _apiKey 加 as any src = src.replace( "const fp = node.provider.vendor + ':' + (node.provider._apiKey || '').slice(-12);", "const fp = node.provider.vendor + ':' + ((node.provider as any)._apiKey || '').slice(-12);", ) # Fix 3: findVendorForModel 里的 _apiKey 也加 as any src = src.replace( " if (tried.has(fp)) continue;\n return n;\n }\n return registry.listAvailable().find(n => n.provider.hasModel(modelId)) || null;", " if (tried.has(fp)) continue;\n return n;\n }\n return registry.listAvailable().find(n => n.provider.hasModel(modelId)) || null;", 0 ) # noop # 找 findVendorForModel 函数, 把它的 _apiKey 也加 as any old_fvf = """function findVendorForModel(modelId) { const registry = getLlmRegistry(); const tried = _currentTriedNodes(); for (const n of registry.listAvailable()) { if (!n.provider.hasModel(modelId)) continue; const fp = n.provider.vendor + ':' + (n.provider._apiKey || '').slice(-12); if (tried.has(fp)) continue; return n; } return registry.listAvailable().find(n => n.provider.hasModel(modelId)) || null; }""" new_fvf = """function findVendorForModel(modelId) { const registry = getLlmRegistry(); const tried = _currentTriedNodes(); for (const n of registry.listAvailable()) { if (!n.provider.hasModel(modelId)) continue; const fp = n.provider.vendor + ':' + ((n.provider as any)._apiKey || '').slice(-12); if (tried.has(fp)) continue; return n; } return registry.listAvailable().find(n => n.provider.hasModel(modelId)) || null; }""" if old_fvf in src: src = src.replace(old_fvf, new_fvf) print("OK: findVendorForModel ts-fix") else: print("WARN: findVendorForModel pattern not found (may have been modified)") # 同样把 resolveProviderKey 里的 _apiKey 加 as any (兼容) old_rpk = """function resolveProviderKey(modelId) { // 关键: 优先用 registry 查找(保留 vendorKey 区分), 而不是 config.models.getModel // 因为 getModel 只返回第一个匹配的, minimax Key1 和 Key2 都提供同名 modelId 时 // 永远只会返回 Key1, 导致 Key2 被误判为 Key1 已经试过, fallback 转一圈就停 const registry = getLlmRegistry(); for (const node of registry.listEnabled()) { if (node.provider.hasModel(modelId)) { // 用 vendorKey + apiKey 指纹, 即使两个 key 同 vendor 也能区分 const apiKey = node.provider._apiKey || ''; if (apiKey) { return node.provider.vendor + ':' + apiKey.slice(-12); } return node.provider.vendor; } } // 最后 fallback: 直接看 models.json const cfg = config.models.getModel?.(modelId); return cfg?.vendor || modelId; }""" new_rpk = """function resolveProviderKey(modelId) { const registry = getLlmRegistry(); for (const node of registry.listEnabled()) { if (node.provider.hasModel(modelId)) { const apiKey = (node.provider as any)._apiKey || ''; if (apiKey) { return node.provider.vendor + ':' + apiKey.slice(-12); } return node.provider.vendor; } } const cfg = config.models.getModel?.(modelId); return cfg?.vendor || modelId; }""" if old_rpk in src: src = src.replace(old_rpk, new_rpk) print("OK: resolveProviderKey ts-fix") else: print("WARN: resolveProviderKey pattern not found") with open(PATH, 'w', encoding='utf-8') as f: f.write(src) print("done")