44 */
55import type { OpenClawConfig } from "../config/types.openclaw.js" ;
66import { isRecord } from "../utils.js" ;
7+ import {
8+ isToolAllowedByPolicies ,
9+ resolveEffectiveToolPolicy ,
10+ resolveGroupToolPolicy ,
11+ resolveInheritedToolPolicyForSession ,
12+ resolveSubagentToolPolicyForSession ,
13+ } from "./agent-tools.policy.js" ;
714import { externalCliDiscoveryForProviderAuth } from "./auth-profiles/external-cli-discovery.js" ;
815import { listProfilesForProvider } from "./auth-profiles/profile-list.js" ;
916import { ensureAuthProfileStore } from "./auth-profiles/store.js" ;
1017import {
1118 type CodexNativeSearchMode ,
1219 resolveCodexNativeWebSearchConfig ,
1320} from "./codex-native-web-search.shared.js" ;
21+ import type { SandboxToolPolicy } from "./sandbox.js" ;
22+ import { resolveSenderToolPolicy } from "./sender-tool-policy.js" ;
23+ import {
24+ isSubagentEnvelopeSession ,
25+ resolveSubagentCapabilityStore ,
26+ } from "./subagent-capabilities.js" ;
27+ import { mergeAlsoAllowPolicy , resolveToolProfilePolicy } from "./tool-policy.js" ;
1428
1529type CodexNativeSearchActivation = {
1630 globalWebSearchEnabled : boolean ;
@@ -23,13 +37,33 @@ type CodexNativeSearchActivation = {
2337 | "globally_disabled"
2438 | "codex_not_enabled"
2539 | "model_not_eligible"
26- | "codex_auth_missing" ;
40+ | "codex_auth_missing"
41+ | "tool_policy_denied" ;
2742} ;
2843
2944type CodexNativeSearchPayloadPatchResult = {
3045 status : "payload_not_object" | "native_tool_already_present" | "injected" ;
3146} ;
3247
48+ export type NativeWebSearchToolPolicyParams = {
49+ config ?: OpenClawConfig ;
50+ modelProvider ?: string ;
51+ modelId ?: string ;
52+ agentId ?: string ;
53+ sessionKey ?: string ;
54+ sandboxToolPolicy ?: SandboxToolPolicy ;
55+ messageProvider ?: string ;
56+ agentAccountId ?: string | null ;
57+ groupId ?: string | null ;
58+ groupChannel ?: string | null ;
59+ groupSpace ?: string | null ;
60+ spawnedBy ?: string | null ;
61+ senderId ?: string | null ;
62+ senderName ?: string | null ;
63+ senderUsername ?: string | null ;
64+ senderE164 ?: string | null ;
65+ } ;
66+
3367const OPENAI_AUTH_PROVIDER_IDS = [ "openai" ] as const ;
3468
3569function isOpenAIAuthProviderId ( provider : string | undefined ) : boolean {
@@ -96,6 +130,20 @@ export function resolveCodexNativeSearchActivation(params: {
96130 config ?: OpenClawConfig ;
97131 modelProvider ?: string ;
98132 modelApi ?: string ;
133+ modelId ?: string ;
134+ agentId ?: string ;
135+ sessionKey ?: string ;
136+ sandboxToolPolicy ?: SandboxToolPolicy ;
137+ messageProvider ?: string ;
138+ agentAccountId ?: string | null ;
139+ groupId ?: string | null ;
140+ groupChannel ?: string | null ;
141+ groupSpace ?: string | null ;
142+ spawnedBy ?: string | null ;
143+ senderId ?: string | null ;
144+ senderName ?: string | null ;
145+ senderUsername ?: string | null ;
146+ senderE164 ?: string | null ;
99147 agentDir ?: string ;
100148} ) : CodexNativeSearchActivation {
101149 const globalWebSearchEnabled = params . config ?. tools ?. web ?. search ?. enabled !== false ;
@@ -105,7 +153,6 @@ export function resolveCodexNativeSearchActivation(params: {
105153 params . modelApi !== "openai-chatgpt-responses" ||
106154 ! isOpenAIAuthProviderId ( params . modelProvider ) ||
107155 hasAvailableCodexAuth ( params ) ;
108-
109156 if ( ! globalWebSearchEnabled ) {
110157 return {
111158 globalWebSearchEnabled,
@@ -154,6 +201,18 @@ export function resolveCodexNativeSearchActivation(params: {
154201 } ;
155202 }
156203
204+ if ( ! isNativeWebSearchAllowedByToolPolicy ( params ) ) {
205+ return {
206+ globalWebSearchEnabled,
207+ codexNativeEnabled : true ,
208+ codexMode : codexConfig . mode ,
209+ nativeEligible : true ,
210+ hasRequiredAuth : true ,
211+ state : "managed_only" ,
212+ inactiveReason : "tool_policy_denied" ,
213+ } ;
214+ }
215+
157216 return {
158217 globalWebSearchEnabled,
159218 codexNativeEnabled : true ,
@@ -164,6 +223,89 @@ export function resolveCodexNativeSearchActivation(params: {
164223 } ;
165224}
166225
226+ export function isNativeWebSearchAllowedByToolPolicy (
227+ params : NativeWebSearchToolPolicyParams ,
228+ ) : boolean {
229+ const {
230+ agentId,
231+ globalPolicy,
232+ globalProviderPolicy,
233+ agentPolicy,
234+ agentProviderPolicy,
235+ profile,
236+ providerProfile,
237+ profileAlsoAllow,
238+ providerProfileAlsoAllow,
239+ } = resolveEffectiveToolPolicy ( {
240+ config : params . config ,
241+ sessionKey : params . sessionKey ,
242+ agentId : params . agentId ,
243+ modelProvider : params . modelProvider ,
244+ modelId : params . modelId ,
245+ } ) ;
246+ const profilePolicy = mergeAlsoAllowPolicy ( resolveToolProfilePolicy ( profile ) , profileAlsoAllow ) ;
247+ const providerProfilePolicy = mergeAlsoAllowPolicy (
248+ resolveToolProfilePolicy ( providerProfile ) ,
249+ providerProfileAlsoAllow ,
250+ ) ;
251+ const groupPolicy = resolveGroupToolPolicy ( {
252+ config : params . config ,
253+ sessionKey : params . sessionKey ,
254+ spawnedBy : params . spawnedBy ,
255+ messageProvider : params . messageProvider ,
256+ groupId : params . groupId ,
257+ groupChannel : params . groupChannel ,
258+ groupSpace : params . groupSpace ,
259+ accountId : params . agentAccountId ,
260+ senderId : params . senderId ,
261+ senderName : params . senderName ,
262+ senderUsername : params . senderUsername ,
263+ senderE164 : params . senderE164 ,
264+ } ) ;
265+ const senderPolicy = resolveSenderToolPolicy ( {
266+ config : params . config ,
267+ agentId,
268+ messageProvider : params . messageProvider ,
269+ senderId : params . senderId ,
270+ senderName : params . senderName ,
271+ senderUsername : params . senderUsername ,
272+ senderE164 : params . senderE164 ,
273+ } ) ;
274+ const subagentStore = resolveSubagentCapabilityStore ( params . sessionKey , {
275+ cfg : params . config ,
276+ } ) ;
277+ const subagentPolicy =
278+ params . sessionKey &&
279+ isSubagentEnvelopeSession ( params . sessionKey , {
280+ cfg : params . config ,
281+ store : subagentStore ,
282+ } )
283+ ? resolveSubagentToolPolicyForSession ( params . config , params . sessionKey , {
284+ store : subagentStore ,
285+ } )
286+ : undefined ;
287+ const inheritedToolPolicy = resolveInheritedToolPolicyForSession (
288+ params . config ,
289+ params . sessionKey ,
290+ {
291+ store : subagentStore ,
292+ } ,
293+ ) ;
294+ return isToolAllowedByPolicies ( "web_search" , [
295+ profilePolicy ,
296+ providerProfilePolicy ,
297+ globalPolicy ,
298+ globalProviderPolicy ,
299+ agentPolicy ,
300+ agentProviderPolicy ,
301+ groupPolicy ,
302+ senderPolicy ,
303+ params . sandboxToolPolicy ,
304+ subagentPolicy ,
305+ inheritedToolPolicy ,
306+ ] ) ;
307+ }
308+
167309/** Builds the OpenAI Responses `web_search` tool payload from config. */
168310export function buildCodexNativeWebSearchTool (
169311 config : OpenClawConfig | undefined ,
@@ -219,6 +361,20 @@ export function shouldSuppressManagedWebSearchTool(params: {
219361 config ?: OpenClawConfig ;
220362 modelProvider ?: string ;
221363 modelApi ?: string ;
364+ modelId ?: string ;
365+ agentId ?: string ;
366+ sessionKey ?: string ;
367+ sandboxToolPolicy ?: SandboxToolPolicy ;
368+ messageProvider ?: string ;
369+ agentAccountId ?: string | null ;
370+ groupId ?: string | null ;
371+ groupChannel ?: string | null ;
372+ groupSpace ?: string | null ;
373+ spawnedBy ?: string | null ;
374+ senderId ?: string | null ;
375+ senderName ?: string | null ;
376+ senderUsername ?: string | null ;
377+ senderE164 ?: string | null ;
222378 agentDir ?: string ;
223379} ) : boolean {
224380 return resolveCodexNativeSearchActivation ( params ) . state === "native_active" ;
0 commit comments