mirror of
https://github.com/RooVetGit/Roo-Code.git
synced 2026-08-28 05:27:24 +00:00
fix: prevent false unsaved changes prompt with OpenAI Compatible headers Mark automatic header syncs in ApiOptions and OpenAICompatible as non-user actions (isUserAction: false) and enhance SettingsView change detection to skip automatic syncs with semantically equal values. Root cause: two components (ApiOptions and OpenAICompatible) manage openAiHeaders state and automatically sync it back on mount/remount. These syncs were treated as user changes, triggering a false dirty state. Co-authored-by: Robert McIntyre <robertjmcintyre@users.noreply.github.com>
This commit is contained in:
parent
1e0fc89fa1
commit
2b72a585dc
3 changed files with 22 additions and 5 deletions
|
|
@ -155,7 +155,7 @@ const ApiOptions = ({
|
|||
|
||||
// Only update if the processed object is different from the current config.
|
||||
if (JSON.stringify(currentConfigHeaders) !== JSON.stringify(newHeadersObject)) {
|
||||
setApiConfigurationField("openAiHeaders", newHeadersObject)
|
||||
setApiConfigurationField("openAiHeaders", newHeadersObject, false)
|
||||
}
|
||||
},
|
||||
300,
|
||||
|
|
|
|||
|
|
@ -262,9 +262,19 @@ const SettingsView = forwardRef<SettingsViewRef, SettingsViewProps>(({ onDone, t
|
|||
|
||||
const previousValue = prevState.apiConfiguration?.[field]
|
||||
|
||||
// Helper to check if two values are semantically equal
|
||||
const areValuesEqual = (a: any, b: any): boolean => {
|
||||
if (a === b) return true
|
||||
if (a == null && b == null) return true
|
||||
if (typeof a !== typeof b) return false
|
||||
if (typeof a === "object" && typeof b === "object") {
|
||||
return JSON.stringify(a) === JSON.stringify(b)
|
||||
}
|
||||
return false
|
||||
}
|
||||
|
||||
// Only skip change detection for automatic initialization (not user actions)
|
||||
// This prevents the dirty state when the component initializes and auto-syncs values
|
||||
// Treat undefined, null, and empty string as uninitialized states
|
||||
const isInitialSync =
|
||||
!isUserAction &&
|
||||
(previousValue === undefined || previousValue === "" || previousValue === null) &&
|
||||
|
|
@ -272,7 +282,10 @@ const SettingsView = forwardRef<SettingsViewRef, SettingsViewProps>(({ onDone, t
|
|||
value !== "" &&
|
||||
value !== null
|
||||
|
||||
if (!isInitialSync) {
|
||||
// Also skip if it's an automatic sync with semantically equal values
|
||||
const isAutomaticNoOpSync = !isUserAction && areValuesEqual(previousValue, value)
|
||||
|
||||
if (!isInitialSync && !isAutomaticNoOpSync) {
|
||||
setChangeDetected(true)
|
||||
}
|
||||
return { ...prevState, apiConfiguration: { ...prevState.apiConfiguration, [field]: value } }
|
||||
|
|
|
|||
|
|
@ -24,7 +24,11 @@ import { ThinkingBudget } from "../ThinkingBudget"
|
|||
|
||||
type OpenAICompatibleProps = {
|
||||
apiConfiguration: ProviderSettings
|
||||
setApiConfigurationField: (field: keyof ProviderSettings, value: ProviderSettings[keyof ProviderSettings]) => void
|
||||
setApiConfigurationField: <K extends keyof ProviderSettings>(
|
||||
field: K,
|
||||
value: ProviderSettings[K],
|
||||
isUserAction?: boolean,
|
||||
) => void
|
||||
organizationAllowList: OrganizationAllowList
|
||||
modelValidationError?: string
|
||||
simplifySettings?: boolean
|
||||
|
|
@ -88,7 +92,7 @@ export const OpenAICompatible = ({
|
|||
useEffect(() => {
|
||||
const timer = setTimeout(() => {
|
||||
const headerObject = convertHeadersToObject(customHeaders)
|
||||
setApiConfigurationField("openAiHeaders", headerObject)
|
||||
setApiConfigurationField("openAiHeaders", headerObject, false)
|
||||
}, 300)
|
||||
|
||||
return () => clearTimeout(timer)
|
||||
|
|
|
|||
Loading…
Add table
Reference in a new issue