diff --git a/src/agents/pi-embedded-runner/model.ts b/src/agents/pi-embedded-runner/model.ts index a960ac90458..a9eff8fbdaf 100644 --- a/src/agents/pi-embedded-runner/model.ts +++ b/src/agents/pi-embedded-runner/model.ts @@ -57,13 +57,7 @@ export function resolveModel( const resolvedAgentDir = agentDir ?? resolveOpenClawAgentDir(); const authStorage = discoverAuthStorage(resolvedAgentDir); const modelRegistry = discoverModels(authStorage, resolvedAgentDir); - let model = modelRegistry.find(provider, modelId) as Model | null; - - // Fallback: OpenRouter's "auto" model is stored with full id "openrouter/auto" - // but parseModelRef splits it into provider="openrouter", modelId="auto" - if (!model && provider === "openrouter" && modelId === "auto") { - model = modelRegistry.find(provider, "openrouter/auto") as Model | null; - } + const model = modelRegistry.find(provider, modelId) as Model | null; if (!model) { const providers = cfg?.models?.providers ?? {}; diff --git a/src/telegram/fetch.test.ts b/src/telegram/fetch.test.ts index 2012fb21777..9f1c676119b 100644 --- a/src/telegram/fetch.test.ts +++ b/src/telegram/fetch.test.ts @@ -3,6 +3,7 @@ import { resolveFetch } from "../infra/fetch.js"; import { resetTelegramFetchStateForTests, resolveTelegramFetch } from "./fetch.js"; const setDefaultAutoSelectFamily = vi.hoisted(() => vi.fn()); +const setDefaultResultOrder = vi.hoisted(() => vi.fn()); vi.mock("node:net", async () => { const actual = await vi.importActual("node:net"); @@ -12,11 +13,20 @@ vi.mock("node:net", async () => { }; }); +vi.mock("node:dns", async () => { + const actual = await vi.importActual("node:dns"); + return { + ...actual, + setDefaultResultOrder, + }; +}); + const originalFetch = globalThis.fetch; afterEach(() => { resetTelegramFetchStateForTests(); - setDefaultAutoSelectFamily.mockClear(); + setDefaultAutoSelectFamily.mockReset(); + setDefaultResultOrder.mockReset(); vi.unstubAllEnvs(); vi.clearAllMocks(); if (originalFetch) { @@ -105,4 +115,22 @@ describe("resolveTelegramFetch", () => { resolveTelegramFetch(undefined, { network: { autoSelectFamily: true } }); expect(setDefaultAutoSelectFamily).toHaveBeenCalledWith(false); }); + + it("applies dns result order from config", async () => { + globalThis.fetch = vi.fn(async () => ({})) as unknown as typeof fetch; + resolveTelegramFetch(undefined, { network: { dnsResultOrder: "verbatim" } }); + expect(setDefaultResultOrder).toHaveBeenCalledWith("verbatim"); + }); + + it("retries dns setter on next call when previous attempt threw", async () => { + setDefaultResultOrder.mockImplementationOnce(() => { + throw new Error("dns setter failed once"); + }); + globalThis.fetch = vi.fn(async () => ({})) as unknown as typeof fetch; + + resolveTelegramFetch(undefined, { network: { dnsResultOrder: "ipv4first" } }); + resolveTelegramFetch(undefined, { network: { dnsResultOrder: "ipv4first" } }); + + expect(setDefaultResultOrder).toHaveBeenCalledTimes(2); + }); }); diff --git a/src/telegram/fetch.ts b/src/telegram/fetch.ts index fb75b248dd9..48fdf72eff7 100644 --- a/src/telegram/fetch.ts +++ b/src/telegram/fetch.ts @@ -19,10 +19,10 @@ function applyTelegramNetworkWorkarounds(network?: TelegramNetworkConfig): void // Apply autoSelectFamily workaround const autoSelectDecision = resolveTelegramAutoSelectFamilyDecision({ network }); if (autoSelectDecision.value !== null && autoSelectDecision.value !== appliedAutoSelectFamily) { - appliedAutoSelectFamily = autoSelectDecision.value; if (typeof net.setDefaultAutoSelectFamily === "function") { try { net.setDefaultAutoSelectFamily(autoSelectDecision.value); + appliedAutoSelectFamily = autoSelectDecision.value; const label = autoSelectDecision.source ? ` (${autoSelectDecision.source})` : ""; log.info(`autoSelectFamily=${autoSelectDecision.value}${label}`); } catch { @@ -36,10 +36,10 @@ function applyTelegramNetworkWorkarounds(network?: TelegramNetworkConfig): void // See: https://github.com/openclaw/openclaw/issues/5311 const dnsDecision = resolveTelegramDnsResultOrderDecision({ network }); if (dnsDecision.value !== null && dnsDecision.value !== appliedDnsResultOrder) { - appliedDnsResultOrder = dnsDecision.value; if (typeof dns.setDefaultResultOrder === "function") { try { dns.setDefaultResultOrder(dnsDecision.value as "ipv4first" | "verbatim"); + appliedDnsResultOrder = dnsDecision.value; const label = dnsDecision.source ? ` (${dnsDecision.source})` : ""; log.info(`dnsResultOrder=${dnsDecision.value}${label}`); } catch { @@ -67,4 +67,5 @@ export function resolveTelegramFetch( export function resetTelegramFetchStateForTests(): void { appliedAutoSelectFamily = null; + appliedDnsResultOrder = null; } diff --git a/src/telegram/network-config.test.ts b/src/telegram/network-config.test.ts index 5182f097444..7a7dd197c75 100644 --- a/src/telegram/network-config.test.ts +++ b/src/telegram/network-config.test.ts @@ -2,6 +2,7 @@ import { afterEach, describe, expect, it, vi } from "vitest"; import { resetTelegramNetworkConfigStateForTests, resolveTelegramAutoSelectFamilyDecision, + resolveTelegramDnsResultOrderDecision, } from "./network-config.js"; // Mock isWSL2Sync at the top level @@ -129,3 +130,34 @@ describe("resolveTelegramAutoSelectFamilyDecision", () => { }); }); }); + +describe("resolveTelegramDnsResultOrderDecision", () => { + it("uses env override when provided", () => { + const decision = resolveTelegramDnsResultOrderDecision({ + env: { OPENCLAW_TELEGRAM_DNS_RESULT_ORDER: "verbatim" }, + nodeMajor: 22, + }); + expect(decision).toEqual({ + value: "verbatim", + source: "env:OPENCLAW_TELEGRAM_DNS_RESULT_ORDER", + }); + }); + + it("uses config override when provided", () => { + const decision = resolveTelegramDnsResultOrderDecision({ + network: { dnsResultOrder: "ipv4first" }, + nodeMajor: 20, + }); + expect(decision).toEqual({ value: "ipv4first", source: "config" }); + }); + + it("defaults to ipv4first on Node 22", () => { + const decision = resolveTelegramDnsResultOrderDecision({ nodeMajor: 22 }); + expect(decision).toEqual({ value: "ipv4first", source: "default-node22" }); + }); + + it("returns null when no dns decision applies", () => { + const decision = resolveTelegramDnsResultOrderDecision({ nodeMajor: 20 }); + expect(decision).toEqual({ value: null }); + }); +});