diff --git a/src/hooks/useVisualConfig.ts b/src/hooks/useVisualConfig.ts index b03f47a..228b0bd 100644 --- a/src/hooks/useVisualConfig.ts +++ b/src/hooks/useVisualConfig.ts @@ -92,6 +92,18 @@ function setBooleanInDoc(doc: YamlDocument, path: YamlPath, value: boolean): voi if (docHas(doc, path)) doc.setIn(path, false); } +function shouldWriteManagedField( + doc: YamlDocument, + path: YamlPath, + dirtyFields: Set, + dirtyKey: string +): boolean { + // Optional fields managed by the visual editor must not be created during unrelated saves. + // Only materialize them when the YAML already had the key or the user changed that field. + // Use this guard for future optional visual-editor fields instead of unconditional `setIn`. + return docHas(doc, path) || dirtyFields.has(dirtyKey); +} + function setStringInDoc(doc: YamlDocument, path: YamlPath, value: unknown): void { const safe = typeof value === 'string' ? value : ''; const trimmed = safe.trim(); @@ -770,8 +782,8 @@ export function useVisualConfig() { undefined, createInitialVisualConfigState ); - const { visualValues, visualParseError } = state; - const visualDirty = state.dirtyFields.size > 0; + const { visualValues, visualParseError, dirtyFields } = state; + const visualDirty = dirtyFields.size > 0; const visualValidationErrors = useMemo( () => getVisualConfigValidationErrors(visualValues), [visualValues] @@ -845,7 +857,7 @@ export function useVisualConfig() { quotaSwitchProject: Boolean(quotaExceeded?.['switch-project'] ?? true), quotaSwitchPreviewModel: Boolean(quotaExceeded?.['switch-preview-model'] ?? true), - quotaAntigravityCredits: Boolean(quotaExceeded?.['antigravity-credits'] ?? true), + quotaAntigravityCredits: Boolean(quotaExceeded?.['antigravity-credits'] ?? false), routingStrategy: routing?.strategy === 'fill-first' ? 'fill-first' : 'round-robin', routingSessionAffinity: Boolean( @@ -962,15 +974,28 @@ export function useVisualConfig() { docHas(doc, ['quota-exceeded']) || !values.quotaSwitchProject || !values.quotaSwitchPreviewModel || - !values.quotaAntigravityCredits + shouldWriteManagedField( + doc, + ['quota-exceeded', 'antigravity-credits'], + dirtyFields, + 'quotaAntigravityCredits' + ) ) { ensureMapInDoc(doc, ['quota-exceeded']); + const writeQuotaAntigravityCredits = shouldWriteManagedField( + doc, + ['quota-exceeded', 'antigravity-credits'], + dirtyFields, + 'quotaAntigravityCredits' + ); doc.setIn(['quota-exceeded', 'switch-project'], values.quotaSwitchProject); doc.setIn(['quota-exceeded', 'switch-preview-model'], values.quotaSwitchPreviewModel); - doc.setIn( - ['quota-exceeded', 'antigravity-credits'], - values.quotaAntigravityCredits - ); + if (writeQuotaAntigravityCredits) { + doc.setIn( + ['quota-exceeded', 'antigravity-credits'], + values.quotaAntigravityCredits + ); + } deleteIfMapEmpty(doc, ['quota-exceeded']); } @@ -1072,7 +1097,7 @@ export function useVisualConfig() { return currentYaml; } }, - [visualValues] + [dirtyFields, visualValues] ); const setVisualValues = useCallback((newValues: Partial) => { diff --git a/src/types/visualConfig.ts b/src/types/visualConfig.ts index 560d985..76cdf8a 100644 --- a/src/types/visualConfig.ts +++ b/src/types/visualConfig.ts @@ -117,7 +117,7 @@ export const DEFAULT_VISUAL_VALUES: VisualConfigValues = { maxRetryInterval: '', quotaSwitchProject: true, quotaSwitchPreviewModel: true, - quotaAntigravityCredits: true, + quotaAntigravityCredits: false, routingStrategy: 'round-robin', routingSessionAffinity: false, routingSessionAffinityTTL: '',