@@ -18,6 +18,7 @@ import {
1818 createSingleModelChain ,
1919 getModelPolicyChain ,
2020 getFlashLitePolicyChain ,
21+ SILENT_ACTIONS ,
2122} from './policyCatalog.js' ;
2223import {
2324 DEFAULT_GEMINI_FLASH_LITE_MODEL ,
@@ -29,6 +30,7 @@ import {
2930} from '../config/models.js' ;
3031import type { ModelSelectionResult } from './modelAvailabilityService.js' ;
3132import type { ModelConfigKey } from '../services/modelConfigService.js' ;
33+ import { ApprovalMode } from '../policy/types.js' ;
3234
3335/**
3436 * Resolves the active policy chain for the given config, ensuring the
@@ -43,7 +45,7 @@ export function resolvePolicyChain(
4345 preferredModel ?? config . getActiveModel ?.( ) ?? config . getModel ( ) ;
4446 const configuredModel = config . getModel ( ) ;
4547
46- let chain ;
48+ let chain : ModelPolicyChain | undefined ;
4749 const useGemini31 = config . getGemini31LaunchedSync ?.( ) ?? false ;
4850 const useGemini31FlashLite =
4951 config . getGemini31FlashLiteLaunchedSync ?.( ) ?? false ;
@@ -103,45 +105,55 @@ export function resolvePolicyChain(
103105 // No matching modelChains found, default to single model chain
104106 chain = createSingleModelChain ( modelFromConfig ) ;
105107 }
106- return applyDynamicSlicing ( chain , resolvedModel , wrapsAround ) ;
107- }
108-
109- // --- LEGACY PATH ---
108+ chain = applyDynamicSlicing ( chain , resolvedModel , wrapsAround ) ;
109+ } else {
110+ // --- LEGACY PATH ---
110111
111- if ( resolvedModel === DEFAULT_GEMINI_FLASH_LITE_MODEL ) {
112- chain = getFlashLitePolicyChain ( ) ;
113- } else if (
114- isGemini3Model ( resolvedModel , config ) ||
115- isAutoPreferred ||
116- isAutoConfigured
117- ) {
118- if ( hasAccessToPreview ) {
119- const previewEnabled =
120- isGemini3Model ( resolvedModel , config ) ||
121- preferredModel === PREVIEW_GEMINI_MODEL_AUTO ||
122- configuredModel === PREVIEW_GEMINI_MODEL_AUTO ;
123- chain = getModelPolicyChain ( {
124- previewEnabled,
125- userTier : config . getUserTier ( ) ,
126- useGemini31,
127- useGemini31FlashLite,
128- useCustomToolModel,
129- } ) ;
112+ if ( resolvedModel === DEFAULT_GEMINI_FLASH_LITE_MODEL ) {
113+ chain = getFlashLitePolicyChain ( ) ;
114+ } else if (
115+ isGemini3Model ( resolvedModel , config ) ||
116+ isAutoPreferred ||
117+ isAutoConfigured
118+ ) {
119+ if ( hasAccessToPreview ) {
120+ const previewEnabled =
121+ isGemini3Model ( resolvedModel , config ) ||
122+ preferredModel === PREVIEW_GEMINI_MODEL_AUTO ||
123+ configuredModel === PREVIEW_GEMINI_MODEL_AUTO ;
124+ chain = getModelPolicyChain ( {
125+ previewEnabled,
126+ userTier : config . getUserTier ( ) ,
127+ useGemini31,
128+ useGemini31FlashLite,
129+ useCustomToolModel,
130+ } ) ;
131+ } else {
132+ // User requested Gemini 3 but has no access. Proactively downgrade
133+ // to the stable Gemini 2.5 chain.
134+ chain = getModelPolicyChain ( {
135+ previewEnabled : false ,
136+ userTier : config . getUserTier ( ) ,
137+ useGemini31,
138+ useGemini31FlashLite,
139+ useCustomToolModel,
140+ } ) ;
141+ }
130142 } else {
131- // User requested Gemini 3 but has no access. Proactively downgrade
132- // to the stable Gemini 2.5 chain.
133- chain = getModelPolicyChain ( {
134- previewEnabled : false ,
135- userTier : config . getUserTier ( ) ,
136- useGemini31,
137- useGemini31FlashLite,
138- useCustomToolModel,
139- } ) ;
143+ chain = createSingleModelChain ( modelFromConfig ) ;
140144 }
141- } else {
142- chain = createSingleModelChain ( modelFromConfig ) ;
145+ chain = applyDynamicSlicing ( chain , resolvedModel , wrapsAround ) ;
143146 }
144- return applyDynamicSlicing ( chain , resolvedModel , wrapsAround ) ;
147+
148+ // Apply Unified Silent Injection for Plan Mode with defensive checks
149+ if ( config ?. getApprovalMode ?.( ) === ApprovalMode . PLAN ) {
150+ return chain . map ( ( policy ) => ( {
151+ ...policy ,
152+ actions : { ...SILENT_ACTIONS } ,
153+ } ) ) ;
154+ }
155+
156+ return chain ;
145157}
146158
147159/**
0 commit comments