fix: restore allowPrivateNetwork for self-hosted STT endpoints (#66692) (thanks @jhsmith409)

* fix(audio): restore allowPrivateNetwork for self-hosted STT endpoints

resolveProviderExecutionContext built the request object passed to
transcribeAudio using only sanitizeConfiguredProviderRequest on the
tool-level config and entry — which strips allowPrivateNetwork. The
provider-level request config (models.providers.*.request) was never
included in the merge, so allowPrivateNetwork:true was silently dropped.

Additionally, resolveProviderRequestPolicyConfig only read allowPrivate
Network from params.allowPrivateNetwork (a direct parameter) and ignored
params.request?.allowPrivateNetwork even when it was present.

Fix both gaps:
- runner.entries.ts: use mergeModelProviderRequestOverrides with
  sanitizeConfiguredModelProviderRequest(providerConfig?.request) so
  models.providers.*.request.allowPrivateNetwork flows through to the
  media execution context
- provider-request-config.ts: fall back to params.request?.allowPrivate
  Network when params.allowPrivateNetwork is undefined

Fixes #66691. Regression introduced in v2026.4.14.

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>

* test(media-understanding): assert allowPrivateNetwork flows through resolveProviderExecutionContext

Regression test for the bug where providerConfig.request.allowPrivateNetwork
was dropped when building the AudioTranscriptionRequest passed to media
providers. Verifies that setting allowPrivateNetwork in the provider config
reaches the provider's request object after the fix to use
mergeModelProviderRequestOverrides + sanitizeConfiguredModelProviderRequest.

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>

* test(media-understanding): tighten allowPrivateNetwork regression types

* fix: restore allowPrivateNetwork for self-hosted STT endpoints (#66692) (thanks @jhsmith409)

---------

Co-authored-by: Jim Smith <jhsmith0@me.com>
Co-authored-by: Claude Sonnet 4.6 <noreply@anthropic.com>
Co-authored-by: Ayaan Zaidi <hi@obviy.us>
This commit is contained in:
Jim Smith
2026-04-14 22:35:37 -04:00
committed by GitHub
parent b1d03b4057
commit 0c0463b2b7
4 changed files with 58 additions and 2 deletions

View File

@@ -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,
};
}

View File

@@ -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<string, unknown> | 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),
);

View File

@@ -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);
});
});