Skip to content

Commit 89d23b3

Browse files
committed
fix(search): redact native web search provider context
1 parent 7f45e7b commit 89d23b3

9 files changed

Lines changed: 39 additions & 73 deletions

File tree

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1,2 +1,2 @@
1-
b15dd03c86dcd1d069c6987f2e158aeaa5d32611dac9eb640b8b1d7e2c6a560e plugin-sdk-api-baseline.json
2-
1e184dcbe980490f42bad6f44b4ce5a26b597e1c137fc00433031847829d5c3f plugin-sdk-api-baseline.jsonl
1+
424f72310250c242a3157994c45f7319370c1bf99014a13ee5f86cc811f43dd4 plugin-sdk-api-baseline.json
2+
87e786df92be36c22a7b392162c9fa39b634094d15aec4736d8b65be8d7cfd9c plugin-sdk-api-baseline.jsonl

extensions/openai/native-web-search.ts

Lines changed: 2 additions & 14 deletions
Original file line numberDiff line numberDiff line change
@@ -3,15 +3,10 @@ import type { StreamFn } from "openclaw/plugin-sdk/agent-core";
33
import type { OpenClawConfig } from "openclaw/plugin-sdk/config-contracts";
44
import { streamSimple } from "openclaw/plugin-sdk/llm";
55
import { normalizeProviderId } from "openclaw/plugin-sdk/provider-model-shared";
6-
import { isProviderNativeWebSearchAllowedByToolPolicy } from "openclaw/plugin-sdk/provider-stream-family";
76
import { streamWithPayloadPatch } from "openclaw/plugin-sdk/provider-stream-shared";
87
import { isRecord } from "openclaw/plugin-sdk/string-coerce-runtime";
98
import { isOpenAIApiBaseUrl } from "./base-url.js";
109

11-
type NativeWebSearchPolicyContext = Parameters<
12-
typeof isProviderNativeWebSearchAllowedByToolPolicy
13-
>[0]["nativeWebSearchPolicyContext"];
14-
1510
const OPENAI_WEB_SEARCH_TOOL = { type: "web_search" } as const;
1611

1712
type OpenAINativeWebSearchPatchResult =
@@ -95,22 +90,15 @@ export function createOpenAINativeWebSearchWrapper(
9590
params: {
9691
config?: OpenClawConfig;
9792
agentId?: string;
98-
nativeWebSearchPolicyContext?: NativeWebSearchPolicyContext;
93+
nativeWebSearchAllowedByToolPolicy?: boolean;
9994
},
10095
): StreamFn {
10196
const underlying = baseStreamFn ?? streamSimple;
10297
return (model, context, options) => {
10398
if (!shouldEnableOpenAINativeWebSearch({ config: params.config, model })) {
10499
return underlying(model, context, options);
105100
}
106-
if (
107-
!isProviderNativeWebSearchAllowedByToolPolicy({
108-
config: params.config,
109-
model,
110-
agentId: params.agentId,
111-
nativeWebSearchPolicyContext: params.nativeWebSearchPolicyContext,
112-
})
113-
) {
101+
if (params.nativeWebSearchAllowedByToolPolicy === false) {
114102
return underlying(model, context, options);
115103
}
116104
return streamWithPayloadPatch(underlying, model, context, options, (payload) => {

extensions/openai/openai-provider.test.ts

Lines changed: 3 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -82,7 +82,7 @@ function runWrappedPayloadCase(params: {
8282
extraParams?: Record<string, unknown>;
8383
cfg?: Record<string, unknown>;
8484
agentId?: string;
85-
nativeWebSearchPolicyContext?: unknown;
85+
nativeWebSearchAllowedByToolPolicy?: boolean;
8686
payload?: Record<string, unknown>;
8787
}) {
8888
const payload = params.payload ?? { store: false };
@@ -100,7 +100,7 @@ function runWrappedPayloadCase(params: {
100100
config: params.cfg as never,
101101
agentDir: "/tmp/openai-provider-test",
102102
agentId: params.agentId,
103-
nativeWebSearchPolicyContext: params.nativeWebSearchPolicyContext,
103+
nativeWebSearchAllowedByToolPolicy: params.nativeWebSearchAllowedByToolPolicy,
104104
streamFn: baseStreamFn,
105105
} as never);
106106

@@ -1236,6 +1236,7 @@ describe("buildOpenAIProvider", () => {
12361236
provider: "openai",
12371237
modelId: "gpt-5.4",
12381238
agentId: "main",
1239+
nativeWebSearchAllowedByToolPolicy: false,
12391240
cfg: {
12401241
agents: {
12411242
list: [

extensions/openai/shared.ts

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -89,7 +89,7 @@ const wrapOpenAIResponsesProviderStreamFn: NonNullable<
8989
createOpenAINativeWebSearchWrapper(wrapOpenAIResponsesStreamFn?.(ctx) ?? ctx.streamFn, {
9090
config: ctx.config,
9191
agentId: ctx.agentId,
92-
nativeWebSearchPolicyContext: ctx.nativeWebSearchPolicyContext,
92+
nativeWebSearchAllowedByToolPolicy: ctx.nativeWebSearchAllowedByToolPolicy,
9393
});
9494

9595
export function buildOpenAIResponsesProviderHooks(options?: {

src/agents/embedded-agent-runner-extraparams.test.ts

Lines changed: 3 additions & 15 deletions
Original file line numberDiff line numberDiff line change
@@ -469,7 +469,7 @@ function createTestOpenAIProviderWrapper(
469469
config: params.context.config,
470470
agentDir: params.context.agentDir,
471471
agentId: params.context.agentId,
472-
...params.context.nativeWebSearchPolicyContext,
472+
nativeWebSearchAllowedByToolPolicy: params.context.nativeWebSearchAllowedByToolPolicy,
473473
});
474474
streamFn = createOpenAIStringContentWrapper(streamFn);
475475
streamFn = createOpenAICompletionsStrictMessageKeysWrapper(streamFn);
@@ -563,20 +563,8 @@ describe("applyExtraParamsToAgent", () => {
563563

564564
expect(capturedContext?.agentDir).toBe("/tmp/openclaw-agent");
565565
expect(capturedContext?.workspaceDir).toBe("/tmp/openclaw-workspace");
566-
expect(capturedContext?.nativeWebSearchPolicyContext).toEqual({
567-
sessionKey: "agent:cass:main",
568-
sandboxToolPolicy: { deny: ["group:web"] },
569-
messageProvider: "teams",
570-
agentAccountId: "acct-1",
571-
groupId: "group-1",
572-
groupChannel: "General",
573-
groupSpace: "space-1",
574-
spawnedBy: "agent:cass:main",
575-
senderId: "alice",
576-
senderName: "Alice",
577-
senderUsername: "alice-user",
578-
senderE164: "+15551234567",
579-
});
566+
expect(capturedContext?.nativeWebSearchAllowedByToolPolicy).toBe(false);
567+
expect("nativeWebSearchPolicyContext" in (capturedContext ?? {})).toBe(false);
580568
});
581569

582570
function runResponsesPayloadMutationCase(params: {

src/agents/embedded-agent-runner/extra-params.ts

Lines changed: 15 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -1,3 +1,7 @@
1+
import {
2+
type NativeWebSearchToolPolicyParams,
3+
isNativeWebSearchAllowedByToolPolicy,
4+
} from "../../agents/codex-native-web-search-core.js";
15
/**
26
* Resolves model extra parameters and transport overrides for embedded agents.
37
*/
@@ -30,7 +34,6 @@ import {
3034
wrapProviderStreamFn as wrapProviderStreamFnRuntime,
3135
} from "../../plugins/provider-hook-runtime.js";
3236
import type { ProviderRuntimeModel } from "../../plugins/provider-runtime-model.types.js";
33-
import type { ProviderNativeWebSearchPolicyContext } from "../../plugins/types.js";
3437
import { canonicalizeMaxTokensParam, resolveMaxTokensParam } from "../model-max-tokens-params.js";
3538
import { legacyModelKey, modelKey } from "../model-selection-normalize.js";
3639
import { supportsGptParallelToolCallsPayload } from "../provider-api-families.js";
@@ -1046,7 +1049,7 @@ export function applyExtraParamsToAgent(
10461049
resolvedTransport?: SupportedTransport,
10471050
options?: {
10481051
preparedExtraParams?: Record<string, unknown>;
1049-
nativeWebSearchPolicyContext?: ProviderNativeWebSearchPolicyContext;
1052+
nativeWebSearchPolicyContext?: NativeWebSearchToolPolicyParams;
10501053
},
10511054
): { effectiveExtraParams: Record<string, unknown> } {
10521055
const resolvedExtraParams = resolveExtraParams({
@@ -1093,6 +1096,15 @@ export function applyExtraParamsToAgent(
10931096
};
10941097

10951098
const providerStreamBase = agent.streamFn;
1099+
const nativeWebSearchAllowedByToolPolicy = options?.nativeWebSearchPolicyContext
1100+
? isNativeWebSearchAllowedByToolPolicy({
1101+
config: cfg,
1102+
modelProvider: model?.provider,
1103+
modelId: model?.id,
1104+
agentId,
1105+
...options.nativeWebSearchPolicyContext,
1106+
})
1107+
: undefined;
10961108
const pluginWrappedStreamFn = providerRuntimeDeps.wrapProviderStreamFn({
10971109
provider,
10981110
config: cfg,
@@ -1101,7 +1113,7 @@ export function applyExtraParamsToAgent(
11011113
agentDir,
11021114
workspaceDir,
11031115
agentId,
1104-
nativeWebSearchPolicyContext: options?.nativeWebSearchPolicyContext,
1116+
nativeWebSearchAllowedByToolPolicy,
11051117
provider,
11061118
modelId,
11071119
extraParams: effectiveExtraParams,

src/llm/providers/stream-wrappers/openai.ts

Lines changed: 10 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -630,6 +630,7 @@ export function createCodexNativeWebSearchWrapper(
630630
senderName?: string | null;
631631
senderUsername?: string | null;
632632
senderE164?: string | null;
633+
nativeWebSearchAllowedByToolPolicy?: boolean;
633634
codeModeToolSurfaceEnabled?: boolean;
634635
},
635636
): StreamFn {
@@ -663,6 +664,15 @@ export function createCodexNativeWebSearchWrapper(
663664
return underlying(model, context, codeModeOptions);
664665
}
665666

667+
if (params.nativeWebSearchAllowedByToolPolicy === false) {
668+
log.debug(
669+
`skipping Codex native web search (tool_policy_denied) for ${
670+
model.provider ?? "unknown"
671+
}/${model.id ?? "unknown"}`,
672+
);
673+
return underlying(model, context, options);
674+
}
675+
666676
const activation = resolveCodexNativeSearchActivation({
667677
config: params.config,
668678
modelProvider: readStringValue(model.provider),

src/plugin-sdk/provider-stream.ts

Lines changed: 2 additions & 20 deletions
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,4 @@
11
// Provider stream helpers expose shared wrapper families and payload transforms for provider plugins.
2-
import { readStringValue } from "@openclaw/normalization-core/string-coerce";
3-
import { isNativeWebSearchAllowedByToolPolicy } from "../agents/codex-native-web-search-core.js";
4-
import type { OpenClawConfig } from "../config/types.openclaw.js";
52
import { createGoogleThinkingPayloadWrapper } from "../llm/providers/stream-wrappers/google.js";
63
import { createMinimaxFastModeWrapper } from "../llm/providers/stream-wrappers/minimax.js";
74
import { resolveMoonshotThinkingKeep } from "../llm/providers/stream-wrappers/moonshot-thinking.js";
@@ -24,7 +21,7 @@ import {
2421
createOpenRouterWrapper,
2522
isProxyReasoningUnsupported,
2623
} from "../llm/providers/stream-wrappers/proxy.js";
27-
import type { ProviderNativeWebSearchPolicyContext, ProviderPlugin } from "../plugins/types.js";
24+
import type { ProviderPlugin } from "../plugins/types.js";
2825
import type { ProviderWrapStreamFnContext } from "./plugin-entry.js";
2926
import {
3027
createMoonshotThinkingWrapper,
@@ -68,21 +65,6 @@ export type ProviderStreamFamily =
6865

6966
type ProviderStreamFamilyHooks = Pick<ProviderPlugin, "wrapStreamFn">;
7067

71-
export function isProviderNativeWebSearchAllowedByToolPolicy(params: {
72-
config?: OpenClawConfig;
73-
model?: { id?: unknown; provider?: unknown };
74-
agentId?: string;
75-
nativeWebSearchPolicyContext?: ProviderNativeWebSearchPolicyContext;
76-
}): boolean {
77-
return isNativeWebSearchAllowedByToolPolicy({
78-
config: params.config,
79-
modelProvider: readStringValue(params.model?.provider),
80-
modelId: readStringValue(params.model?.id),
81-
agentId: params.agentId,
82-
...params.nativeWebSearchPolicyContext,
83-
});
84-
}
85-
8668
/** Builds provider hook objects for one supported stream-wrapper family. */
8769
export function buildProviderStreamFamilyHooks(
8870
/**
@@ -149,7 +131,7 @@ export function buildProviderStreamFamilyHooks(
149131
config: ctx.config,
150132
agentDir: ctx.agentDir,
151133
agentId: ctx.agentId,
152-
...ctx.nativeWebSearchPolicyContext,
134+
nativeWebSearchAllowedByToolPolicy: ctx.nativeWebSearchAllowedByToolPolicy,
153135
});
154136
nextStreamFn = createOpenAIStringContentWrapper(nextStreamFn);
155137
return createOpenAIResponsesContextManagementWrapper(

src/plugins/types.ts

Lines changed: 1 addition & 16 deletions
Original file line numberDiff line numberDiff line change
@@ -696,21 +696,6 @@ export type ProviderAuthDoctorHintContext = {
696696
profileId?: string;
697697
};
698698

699-
export type ProviderNativeWebSearchPolicyContext = {
700-
sessionKey?: string;
701-
sandboxToolPolicy?: { allow?: string[]; deny?: string[] };
702-
messageProvider?: string;
703-
agentAccountId?: string | null;
704-
groupId?: string | null;
705-
groupChannel?: string | null;
706-
groupSpace?: string | null;
707-
spawnedBy?: string | null;
708-
senderId?: string | null;
709-
senderName?: string | null;
710-
senderUsername?: string | null;
711-
senderE164?: string | null;
712-
};
713-
714699
/**
715700
* Provider-owned extra-param normalization before OpenClaw builds its generic
716701
* stream option wrapper.
@@ -723,7 +708,7 @@ export type ProviderPrepareExtraParamsContext = {
723708
agentDir?: string;
724709
workspaceDir?: string;
725710
agentId?: string;
726-
nativeWebSearchPolicyContext?: ProviderNativeWebSearchPolicyContext;
711+
nativeWebSearchAllowedByToolPolicy?: boolean;
727712
provider: string;
728713
modelId: string;
729714
model?: ProviderRuntimeModel;

0 commit comments

Comments
 (0)