diff --git a/CHANGELOG.md b/CHANGELOG.md index 2c894b54165..4c84fd340c5 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -40,6 +40,7 @@ Docs: https://docs.openclaw.ai - Telegram/native commands: restore plugin-registry-backed auto defaults for native commands and native skills so Telegram slash commands keep registering when `commands.native` and `commands.nativeSkills` stay on `auto`. (#66843) Thanks @kashevk0. - fix(bluebubbles): replay missed webhook messages after gateway restart via a persistent per-account cursor and `/api/v1/message/query?after=` pass, so messages delivered while the gateway was down no longer disappear. Uses the existing `processMessage` path and is deduped by #66816's inbound GUID cache. (#66857, #66721) Thanks @omarshahine. - Telegram/native commands: keep Telegram command-sync cache process-local so gateway restarts re-register the menu instead of trusting stale on-disk sync state after Telegram cleared commands out-of-band. (#66730) Thanks @nightq. +- Audio/self-hosted STT: restore `models.providers.*.request.allowPrivateNetwork` for audio transcription so private or LAN speech-to-text endpoints stop tripping SSRF blocks after the v2026.4.14 regression. (#66692) Thanks @jhsmith409. ## 2026.4.14 diff --git a/src/agents/provider-request-config.ts b/src/agents/provider-request-config.ts index b2f4bf467bd..624d3fd4909 100644 --- a/src/agents/provider-request-config.ts +++ b/src/agents/provider-request-config.ts @@ -661,7 +661,7 @@ export function resolveProviderRequestPolicyConfig( tls: resolveTlsOverride(params.request?.tls), policy, capabilities, - allowPrivateNetwork: params.allowPrivateNetwork ?? false, + allowPrivateNetwork: params.allowPrivateNetwork ?? params.request?.allowPrivateNetwork ?? false, }; } diff --git a/src/media-understanding/runner.entries.ts b/src/media-understanding/runner.entries.ts index 2a945192ecb..c890872e150 100644 --- a/src/media-understanding/runner.entries.ts +++ b/src/media-understanding/runner.entries.ts @@ -6,7 +6,9 @@ import { } from "../agents/api-key-rotation.js"; import { requireApiKey, resolveApiKeyForProvider } from "../agents/model-auth.js"; import { + mergeModelProviderRequestOverrides, mergeProviderRequestOverrides, + sanitizeConfiguredModelProviderRequest, sanitizeConfiguredProviderRequest, } from "../agents/provider-request-config.js"; import type { MsgContext } from "../auto-reply/templating.js"; @@ -429,7 +431,8 @@ async function resolveProviderExecutionContext(params: { ...sanitizeProviderHeaders(params.entry.headers as Record | undefined), }; const headers = Object.keys(mergedHeaders).length > 0 ? mergedHeaders : undefined; - const request = mergeProviderRequestOverrides( + const request = mergeModelProviderRequestOverrides( + sanitizeConfiguredModelProviderRequest(providerConfig?.request), sanitizeConfiguredProviderRequest(params.config?.request), sanitizeConfiguredProviderRequest(params.entry.request), ); diff --git a/src/media-understanding/runner.proxy.test.ts b/src/media-understanding/runner.proxy.test.ts index c919cc85189..febe654951b 100644 --- a/src/media-understanding/runner.proxy.test.ts +++ b/src/media-understanding/runner.proxy.test.ts @@ -178,4 +178,56 @@ describe("runCapability proxy fetch passthrough", () => { }); expect(seenFetchFn).toBeUndefined(); }); + + it("passes allowPrivateNetwork to audio provider when set in providerConfig.request", async () => { + let seenRequest: AudioTranscriptionRequest["request"]; + + await withAudioFixture("openclaw-audio-allowprivatenetwork", async ({ ctx, media, cache }) => { + const providerRegistry = buildProviderRegistry({ + openai: { + id: "openai", + capabilities: ["audio"], + transcribeAudio: async (req: AudioTranscriptionRequest) => { + seenRequest = req.request; + return { text: "ok", model: req.model }; + }, + }, + }); + + const cfg = { + models: { + providers: { + openai: { + apiKey: "test-key", // pragma: allowlist secret + request: { + allowPrivateNetwork: true, + }, + models: [], + }, + }, + }, + tools: { + media: { + audio: { + enabled: true, + models: [{ provider: "openai", model: "whisper-1" }], + }, + }, + }, + } as unknown as OpenClawConfig; + + const result = await runCapability({ + capability: "audio", + cfg, + ctx, + attachments: cache, + media, + providerRegistry, + }); + + expect(result.outputs[0]?.text).toBe("ok"); + }); + + expect(seenRequest?.allowPrivateNetwork).toBe(true); + }); });