Download src/utils/settings/applySettingsChange.ts from chenbhao/codev: direct link, hf CLI and curl.
- Browser
- Download file 3.66 kB
-
https://huggingface.co/chenbhao/codev/resolve/afbc7edaae4e6bb0102ba024b49ce8be89d2264c/src/utils/settings/applySettingsChange.ts
- Command line
-
hf download hf://chenbhao/codev@afbc7edaae4e6bb0102ba024b49ce8be89d2264c/src/utils/settings/applySettingsChange.ts
-
curl -L -o applySettingsChange.ts https://huggingface.co/chenbhao/codev/resolve/afbc7edaae4e6bb0102ba024b49ce8be89d2264c/src/utils/settings/applySettingsChange.ts
3.66 kB
| import type { AppState } from '../../state/AppState.js' | |
| import { logForDebugging } from '../debug.js' | |
| import { updateHooksConfigSnapshot } from '../hooks/hooksConfigSnapshot.js' | |
| import { | |
| createDisabledBypassPermissionsContext, | |
| findOverlyBroadBashPermissions, | |
| isBypassPermissionsModeDisabled, | |
| removeDangerousPermissions, | |
| transitionPlanAutoMode, | |
| } from '../permissions/permissionSetup.js' | |
| import { syncPermissionRulesFromDisk } from '../permissions/permissions.js' | |
| import { loadAllPermissionRulesFromDisk } from '../permissions/permissionsLoader.js' | |
| import type { SettingSource } from './constants.js' | |
| import { getInitialSettings } from './settings.js' | |
| /** | |
| * Apply a settings change to app state. Re-reads settings from disk, | |
| * reloads permissions and hooks, and pushes the new state. | |
| * | |
| * Used by both the interactive path (AppState.tsx via useSettingsChange) and | |
| * the headless/SDK path (print.ts direct subscribe) so that managed-settings | |
| * / policy changes are fully applied in both modes. | |
| * | |
| * The settings cache is reset by the notifier (changeDetector.fanOut) before | |
| * listeners are iterated, so getInitialSettings() here reads fresh disk | |
| * state. Previously this function reset the cache itself, which — combined | |
| * with useSettingsChange's own reset — caused N disk reloads per notification | |
| * for N subscribers. | |
| * | |
| * Side-effects like clearing auth caches and applying env vars are handled by | |
| * `onChangeAppState` which fires when `settings` changes in state. | |
| */ | |
| export function applySettingsChange( | |
| source: SettingSource, | |
| setAppState: (f: (prev: AppState) => AppState) => void, | |
| ): void { | |
| const newSettings = getInitialSettings() | |
| logForDebugging(`Settings changed from ${source}, updating app state`) | |
| const updatedRules = loadAllPermissionRulesFromDisk() | |
| updateHooksConfigSnapshot() | |
| setAppState(prev => { | |
| let newContext = syncPermissionRulesFromDisk( | |
| prev.toolPermissionContext, | |
| updatedRules, | |
| ) | |
| // Ant-only: re-strip overly broad Bash allow rules after settings sync | |
| if ( | |
| process.env.USER_TYPE === 'ant' && | |
| process.env.CLAUDE_CODE_ENTRYPOINT !== 'local-agent' | |
| ) { | |
| const overlyBroad = findOverlyBroadBashPermissions(updatedRules, []) | |
| if (overlyBroad.length > 0) { | |
| newContext = removeDangerousPermissions(newContext, overlyBroad) | |
| } | |
| } | |
| if ( | |
| newContext.isBypassPermissionsModeAvailable && | |
| isBypassPermissionsModeDisabled() | |
| ) { | |
| newContext = createDisabledBypassPermissionsContext(newContext) | |
| } | |
| newContext = transitionPlanAutoMode(newContext) | |
| // Sync effortLevel from settings to top-level AppState when it changes | |
| // (e.g. via applyFlagSettings from IDE). Only propagate if the setting | |
| // itself changed — otherwise unrelated settings churn (e.g. tips dismissal | |
| // on startup) would clobber a --effort CLI flag value held in AppState. | |
| const prevEffort = prev.settings.effortLevel | |
| const newEffort = newSettings.effortLevel | |
| const effortChanged = prevEffort !== newEffort | |
| return { | |
| ...prev, | |
| settings: newSettings, | |
| toolPermissionContext: newContext, | |
| // Only propagate a defined new value — when the disk key is absent | |
| // (e.g. /effort max for non-ants writes undefined; --effort CLI flag), | |
| // prev.settings.effortLevel can be stale (internal writes suppress the | |
| // watcher that would resync AppState.settings), so effortChanged would | |
| // be true and we'd wipe a session-scoped value held in effortValue. | |
| ...(effortChanged && newEffort !== undefined | |
| ? { effortValue: newEffort } | |
| : {}), | |
| } | |
| }) | |
| } | |