Fix state dir in docker mode (#5840)

This commit is contained in:
Robert Brennan 2024-12-26 17:42:04 -05:00 committed by GitHub
parent a021045dce
commit b34209c9a0
No known key found for this signature in database
GPG Key ID: B5690EEEBB952194
7 changed files with 70 additions and 63 deletions

View File

@ -49,7 +49,7 @@ docker run -it --rm --pull=always \
-e SANDBOX_RUNTIME_CONTAINER_IMAGE=docker.all-hands.dev/all-hands-ai/runtime:0.17-nikolaik \
-e LOG_ALL_EVENTS=true \
-v /var/run/docker.sock:/var/run/docker.sock \
-v ~/.openhands-state:/home/openhands/.openhands-state \
-v ~/.openhands-state:/.openhands-state \
-p 3000:3000 \
--add-host host.docker.internal:host-gateway \
--name openhands-app \

View File

@ -43,7 +43,8 @@ ENV WORKSPACE_BASE=/opt/workspace_base
ENV OPENHANDS_BUILD_VERSION=$OPENHANDS_BUILD_VERSION
ENV SANDBOX_USER_ID=0
ENV FILE_STORE=local
ENV FILE_STORE_PATH=~/.openhands-state
ENV FILE_STORE_PATH=/.openhands-state
RUN mkdir -p $FILE_STORE_PATH
RUN mkdir -p $WORKSPACE_BASE
RUN apt-get update -y \

View File

@ -25,7 +25,6 @@ export function SecurityAnalyzerInput({
</label>
<Autocomplete
isDisabled={isDisabled}
isRequired
id="security-analyzer"
name="security-analyzer"
aria-label="Security Analyzer"

View File

@ -7,11 +7,7 @@ import { getDefaultSettings, Settings } from "#/services/settings";
import { extractModelAndProvider } from "#/utils/extract-model-and-provider";
import { DangerModal } from "../confirmation-modals/danger-modal";
import { I18nKey } from "#/i18n/declaration";
import {
extractSettings,
saveSettingsView,
updateSettingsVersion,
} from "#/utils/settings-utils";
import { extractSettings, saveSettingsView } from "#/utils/settings-utils";
import { useEndSession } from "#/hooks/use-end-session";
import { useSettings } from "#/context/settings-context";
import { ModalButton } from "../../buttons/modal-button";
@ -24,7 +20,6 @@ import { CustomModelInput } from "../../inputs/custom-model-input";
import { SecurityAnalyzerInput } from "../../inputs/security-analyzers-input";
import { ModalBackdrop } from "../modal-backdrop";
import { ModelSelector } from "./model-selector";
import { useAuth } from "#/context/auth-context";
interface SettingsFormProps {
disabled?: boolean;
@ -45,7 +40,6 @@ export function SettingsForm({
}: SettingsFormProps) {
const { saveSettings } = useSettings();
const endSession = useEndSession();
const { logout } = useAuth();
const location = useLocation();
const { t } = useTranslation();
@ -98,7 +92,6 @@ export function SettingsForm({
const newSettings = extractSettings(formData);
saveSettingsView(isUsingAdvancedOptions ? "advanced" : "basic");
updateSettingsVersion(logout);
saveSettings(newSettings);
resetOngoingSession();

View File

@ -5,6 +5,7 @@ import { useGitHubAuthUrl } from "#/hooks/use-github-auth-url";
import { useIsAuthed } from "#/hooks/query/use-is-authed";
import { useAuth } from "#/context/auth-context";
import { useSettings } from "#/context/settings-context";
import { updateSettingsVersion } from "#/utils/settings-utils";
import { useConfig } from "#/hooks/query/use-config";
import { Sidebar } from "#/components/features/sidebar/sidebar";
import { WaitlistModal } from "#/components/features/waitlist/waitlist-modal";
@ -45,6 +46,7 @@ export function ErrorBoundary() {
export default function MainApp() {
const { gitHubToken } = useAuth();
const { settings } = useSettings();
const { logout } = useAuth();
const [consentFormIsOpen, setConsentFormIsOpen] = React.useState(
!localStorage.getItem("analytics-consent"),
@ -65,6 +67,10 @@ export default function MainApp() {
}
}, [settings.LANGUAGE]);
React.useEffect(() => {
updateSettingsVersion(logout);
}, []);
const isInWaitlist =
!isFetchingAuth && !isAuthed && config.data?.APP_MODE === "saas";

View File

@ -1,6 +1,6 @@
import { openHands } from "#/api/open-hands-axios";
export const LATEST_SETTINGS_VERSION = 4;
export const LATEST_SETTINGS_VERSION = 5;
export type Settings = {
LLM_MODEL: string;
@ -45,54 +45,8 @@ export const getCurrentSettingsVersion = () => {
export const settingsAreUpToDate = () =>
getCurrentSettingsVersion() === LATEST_SETTINGS_VERSION;
export const maybeMigrateSettings = (logout: () => void) => {
// Sometimes we ship major changes, like a new default agent.
// In this case, we may want to override a previous choice made by the user.
const currentVersion = getCurrentSettingsVersion();
if (currentVersion < 1) {
localStorage.setItem("AGENT", DEFAULT_SETTINGS.AGENT);
}
if (currentVersion < 2) {
const customModel = localStorage.getItem("CUSTOM_LLM_MODEL");
if (customModel) {
localStorage.setItem("LLM_MODEL", customModel);
}
localStorage.removeItem("CUSTOM_LLM_MODEL");
localStorage.removeItem("USING_CUSTOM_MODEL");
}
if (currentVersion < 3) {
localStorage.removeItem("token");
}
if (currentVersion < 4) {
logout();
}
};
/**
* Get the default settings
*/
export const getDefaultSettings = (): Settings => DEFAULT_SETTINGS;
/**
* Get the settings from the server or use the default settings if not found
*/
export const getSettings = async (): Promise<Settings> => {
const { data: apiSettings } =
await openHands.get<ApiSettings>("/api/settings");
if (apiSettings != null) {
return {
LLM_MODEL: apiSettings.llm_model,
LLM_BASE_URL: apiSettings.llm_base_url,
AGENT: apiSettings.agent,
LANGUAGE: apiSettings.language,
CONFIRMATION_MODE: apiSettings.confirmation_mode,
SECURITY_ANALYZER: apiSettings.security_analyzer,
LLM_API_KEY: "",
};
}
// TODO: localStorage settings are deprecated. Remove this after 1/31/2025
export const getLocalStorageSettings = (): Settings => {
const llmModel = localStorage.getItem("LLM_MODEL");
const baseUrl = localStorage.getItem("LLM_BASE_URL");
const agent = localStorage.getItem("AGENT");
@ -133,7 +87,61 @@ export const saveSettings = async (
const { data } = await openHands.post("/api/settings", apiSettings);
return data;
} catch (error) {
console.error("Error saving settings:", error);
return false;
}
};
export const maybeMigrateSettings = async (logout: () => void) => {
// Sometimes we ship major changes, like a new default agent.
// In this case, we may want to override a previous choice made by the user.
const currentVersion = getCurrentSettingsVersion();
if (currentVersion < 1) {
localStorage.setItem("AGENT", DEFAULT_SETTINGS.AGENT);
}
if (currentVersion < 2) {
const customModel = localStorage.getItem("CUSTOM_LLM_MODEL");
if (customModel) {
localStorage.setItem("LLM_MODEL", customModel);
}
localStorage.removeItem("CUSTOM_LLM_MODEL");
localStorage.removeItem("USING_CUSTOM_MODEL");
}
if (currentVersion < 3) {
localStorage.removeItem("token");
}
if (currentVersion < 4) {
logout();
}
if (currentVersion < 5) {
const localSettings = getLocalStorageSettings();
await saveSettings(localSettings);
}
};
/**
* Get the default settings
*/
export const getDefaultSettings = (): Settings => DEFAULT_SETTINGS;
/**
* Get the settings from the server or use the default settings if not found
*/
export const getSettings = async (): Promise<Settings> => {
const { data: apiSettings } =
await openHands.get<ApiSettings>("/api/settings");
if (apiSettings != null) {
return {
LLM_MODEL: apiSettings.llm_model,
LLM_BASE_URL: apiSettings.llm_base_url,
AGENT: apiSettings.agent,
LANGUAGE: apiSettings.language,
CONFIRMATION_MODE: apiSettings.confirmation_mode,
SECURITY_ANALYZER: apiSettings.security_analyzer,
LLM_API_KEY: "",
};
}
return getLocalStorageSettings();
};

View File

@ -82,9 +82,9 @@ const saveSettingsView = (view: "basic" | "advanced") => {
* Updates the settings version in local storage if the current settings are not up to date.
* If the settings are outdated, it attempts to migrate them before updating the version.
*/
const updateSettingsVersion = (logout: () => void) => {
const updateSettingsVersion = async (logout: () => void) => {
if (!settingsAreUpToDate()) {
maybeMigrateSettings(logout);
await maybeMigrateSettings(logout);
localStorage.setItem(
"SETTINGS_VERSION",
LATEST_SETTINGS_VERSION.toString(),