refactor(frontend): move option APIs to a dedicated service handler (#10933)

This commit is contained in:
Hiep Le 2025-09-12 00:43:15 +07:00 committed by GitHub
parent c142cc27ff
commit 95d7c10608
No known key found for this signature in database
GPG Key ID: B5690EEEBB952194
23 changed files with 128 additions and 111 deletions

View File

@ -3,7 +3,7 @@ import { screen } from "@testing-library/react";
import { renderWithProviders } from "test-utils";
import { createRoutesStub } from "react-router";
import { ExpandableMessage } from "#/components/features/chat/expandable-message";
import OpenHands from "#/api/open-hands";
import OptionService from "#/api/option-service/option-service.api";
vi.mock("react-i18next", async () => {
const actual = await vi.importActual("react-i18next");
@ -113,7 +113,7 @@ describe("ExpandableMessage", () => {
});
it("should render the out of credits message when the user is out of credits", async () => {
const getConfigSpy = vi.spyOn(OpenHands, "getConfig");
const getConfigSpy = vi.spyOn(OptionService, "getConfig");
// @ts-expect-error - We only care about the APP_MODE and FEATURE_FLAGS fields
getConfigSpy.mockResolvedValue({
APP_MODE: "saas",

View File

@ -7,6 +7,7 @@ import { Provider } from "react-redux";
import { createRoutesStub, Outlet } from "react-router";
import SettingsService from "#/settings-service/settings-service.api";
import OpenHands from "#/api/open-hands";
import OptionService from "#/api/option-service/option-service.api";
import { GitRepository } from "#/types/git";
import { RepoConnector } from "#/components/features/home/repo-connector";
import { MOCK_DEFAULT_USER_SETTINGS } from "#/mocks/handlers";
@ -177,7 +178,7 @@ describe("RepoConnector", () => {
});
it("should render the 'add github repos' link in dropdown if saas mode and github provider is set", async () => {
const getConfiSpy = vi.spyOn(OpenHands, "getConfig");
const getConfiSpy = vi.spyOn(OptionService, "getConfig");
// @ts-expect-error - only return the APP_MODE and APP_SLUG
getConfiSpy.mockResolvedValue({
APP_MODE: "saas",
@ -224,7 +225,7 @@ describe("RepoConnector", () => {
});
it("should not render the 'add github repos' link if github provider is not set", async () => {
const getConfiSpy = vi.spyOn(OpenHands, "getConfig");
const getConfiSpy = vi.spyOn(OptionService, "getConfig");
// @ts-expect-error - only return the APP_MODE and APP_SLUG
getConfiSpy.mockResolvedValue({
APP_MODE: "saas",
@ -269,7 +270,7 @@ describe("RepoConnector", () => {
});
it("should not render the 'add github repos' link in dropdown if oss mode", async () => {
const getConfiSpy = vi.spyOn(OpenHands, "getConfig");
const getConfiSpy = vi.spyOn(OptionService, "getConfig");
// @ts-expect-error - only return the APP_MODE
getConfiSpy.mockResolvedValue({
APP_MODE: "oss",

View File

@ -3,12 +3,13 @@ import { render, screen, waitFor } from "@testing-library/react";
import userEvent from "@testing-library/user-event";
import { afterEach, beforeEach, describe, expect, it, test, vi } from "vitest";
import OpenHands from "#/api/open-hands";
import OptionService from "#/api/option-service/option-service.api";
import { PaymentForm } from "#/components/features/payment/payment-form";
describe("PaymentForm", () => {
const getBalanceSpy = vi.spyOn(OpenHands, "getBalance");
const createCheckoutSessionSpy = vi.spyOn(OpenHands, "createCheckoutSession");
const getConfigSpy = vi.spyOn(OpenHands, "getConfig");
const getConfigSpy = vi.spyOn(OptionService, "getConfig");
const renderPaymentForm = () =>
render(<PaymentForm />, {

View File

@ -8,6 +8,7 @@ import {
import userEvent from "@testing-library/user-event";
import MainApp from "#/routes/root-layout";
import i18n from "#/i18n";
import OptionService from "#/api/option-service/option-service.api";
import * as CaptureConsent from "#/utils/handle-capture-consent";
import SettingsService from "#/settings-service/settings-service.api";
import OpenHands from "#/api/open-hands";
@ -63,7 +64,7 @@ describe("frontend/routes/_oh", () => {
// FIXME: This test fails when it shouldn't be, please investigate
it.skip("should render and capture the user's consent if oss mode", async () => {
const user = userEvent.setup();
const getConfigSpy = vi.spyOn(OpenHands, "getConfig");
const getConfigSpy = vi.spyOn(OptionService, "getConfig");
const getSettingsSpy = vi.spyOn(SettingsService, "getSettings");
const handleCaptureConsentSpy = vi.spyOn(
CaptureConsent,
@ -107,7 +108,7 @@ describe("frontend/routes/_oh", () => {
});
it("should not render the user consent form if saas mode", async () => {
const getConfigSpy = vi.spyOn(OpenHands, "getConfig");
const getConfigSpy = vi.spyOn(OptionService, "getConfig");
getConfigSpy.mockResolvedValue({
APP_MODE: "saas",
GITHUB_CLIENT_ID: "test-id",
@ -185,7 +186,7 @@ describe("frontend/routes/_oh", () => {
});
it("should render a you're in toast if it is a new user and in saas mode", async () => {
const getConfigSpy = vi.spyOn(OpenHands, "getConfig");
const getConfigSpy = vi.spyOn(OptionService, "getConfig");
const getSettingsSpy = vi.spyOn(SettingsService, "getSettings");
const displaySuccessToastSpy = vi.spyOn(
ToastHandlers,

View File

@ -8,9 +8,10 @@ import { I18nextProvider } from "react-i18next";
import GitSettingsScreen from "#/routes/git-settings";
import SettingsService from "#/settings-service/settings-service.api";
import OpenHands from "#/api/open-hands";
import OptionService from "#/api/option-service/option-service.api";
import AuthService from "#/api/auth-service/auth-service.api";
import { MOCK_DEFAULT_USER_SETTINGS } from "#/mocks/handlers";
import { GetConfigResponse } from "#/api/open-hands.types";
import { GetConfigResponse } from "#/api/option-service/option.types";
import * as ToastHandlers from "#/utils/custom-toast-handlers";
import { SecretsService } from "#/api/secrets-service";
@ -110,7 +111,7 @@ describe("Content", () => {
});
it("should render the inputs if OSS mode", async () => {
const getConfigSpy = vi.spyOn(OpenHands, "getConfig");
const getConfigSpy = vi.spyOn(OptionService, "getConfig");
getConfigSpy.mockResolvedValue(VALID_OSS_CONFIG);
const { rerender } = renderGitSettingsScreen();
@ -153,7 +154,7 @@ describe("Content", () => {
});
it("should set '<hidden>' placeholder and indicator if the GitHub token is set", async () => {
const getConfigSpy = vi.spyOn(OpenHands, "getConfig");
const getConfigSpy = vi.spyOn(OptionService, "getConfig");
const getSettingsSpy = vi.spyOn(SettingsService, "getSettings");
getConfigSpy.mockResolvedValue(VALID_OSS_CONFIG);
@ -228,7 +229,7 @@ describe("Content", () => {
});
it("should render the 'Configure GitHub Repositories' button if SaaS mode and app slug exists", async () => {
const getConfigSpy = vi.spyOn(OpenHands, "getConfig");
const getConfigSpy = vi.spyOn(OptionService, "getConfig");
getConfigSpy.mockResolvedValue(VALID_OSS_CONFIG);
const { rerender } = renderGitSettingsScreen();
@ -272,7 +273,7 @@ describe("Form submission", () => {
it("should save the GitHub token", async () => {
const saveProvidersSpy = vi.spyOn(SecretsService, "addGitProvider");
saveProvidersSpy.mockImplementation(() => Promise.resolve(true));
const getConfigSpy = vi.spyOn(OpenHands, "getConfig");
const getConfigSpy = vi.spyOn(OptionService, "getConfig");
getConfigSpy.mockResolvedValue(VALID_OSS_CONFIG);
renderGitSettingsScreen();
@ -293,7 +294,7 @@ describe("Form submission", () => {
it("should save GitLab tokens", async () => {
const saveProvidersSpy = vi.spyOn(SecretsService, "addGitProvider");
saveProvidersSpy.mockImplementation(() => Promise.resolve(true));
const getConfigSpy = vi.spyOn(OpenHands, "getConfig");
const getConfigSpy = vi.spyOn(OptionService, "getConfig");
getConfigSpy.mockResolvedValue(VALID_OSS_CONFIG);
renderGitSettingsScreen();
@ -314,7 +315,7 @@ describe("Form submission", () => {
it("should save the Bitbucket token", async () => {
const saveProvidersSpy = vi.spyOn(SecretsService, "addGitProvider");
saveProvidersSpy.mockImplementation(() => Promise.resolve(true));
const getConfigSpy = vi.spyOn(OpenHands, "getConfig");
const getConfigSpy = vi.spyOn(OptionService, "getConfig");
getConfigSpy.mockResolvedValue(VALID_OSS_CONFIG);
renderGitSettingsScreen();
@ -333,7 +334,7 @@ describe("Form submission", () => {
});
it("should disable the button if there is no input", async () => {
const getConfigSpy = vi.spyOn(OpenHands, "getConfig");
const getConfigSpy = vi.spyOn(OptionService, "getConfig");
getConfigSpy.mockResolvedValue(VALID_OSS_CONFIG);
renderGitSettingsScreen();
@ -359,7 +360,7 @@ describe("Form submission", () => {
});
it("should enable a disconnect tokens button if there is at least one token set", async () => {
const getConfigSpy = vi.spyOn(OpenHands, "getConfig");
const getConfigSpy = vi.spyOn(OptionService, "getConfig");
const getSettingsSpy = vi.spyOn(SettingsService, "getSettings");
getConfigSpy.mockResolvedValue(VALID_OSS_CONFIG);
@ -393,7 +394,7 @@ describe("Form submission", () => {
});
it("should call logout when pressing the disconnect tokens button", async () => {
const getConfigSpy = vi.spyOn(OpenHands, "getConfig");
const getConfigSpy = vi.spyOn(OptionService, "getConfig");
const logoutSpy = vi.spyOn(AuthService, "logout");
const getSettingsSpy = vi.spyOn(SettingsService, "getSettings");
@ -420,7 +421,7 @@ describe("Form submission", () => {
// flaky test
it.skip("should disable the button when submitting changes", async () => {
const saveSettingsSpy = vi.spyOn(SecretsService, "addGitProvider");
const getConfigSpy = vi.spyOn(OpenHands, "getConfig");
const getConfigSpy = vi.spyOn(OptionService, "getConfig");
getConfigSpy.mockResolvedValue(VALID_OSS_CONFIG);
renderGitSettingsScreen();
@ -444,7 +445,7 @@ describe("Form submission", () => {
it("should disable the button after submitting changes", async () => {
const saveProvidersSpy = vi.spyOn(SecretsService, "addGitProvider");
const getConfigSpy = vi.spyOn(OpenHands, "getConfig");
const getConfigSpy = vi.spyOn(OptionService, "getConfig");
getConfigSpy.mockResolvedValue(VALID_OSS_CONFIG);
renderGitSettingsScreen();

View File

@ -9,6 +9,7 @@ import HomeScreen from "#/routes/home";
import { GitRepository } from "#/types/git";
import SettingsService from "#/settings-service/settings-service.api";
import OpenHands from "#/api/open-hands";
import OptionService from "#/api/option-service/option-service.api";
import MainApp from "#/routes/root-layout";
import { MOCK_DEFAULT_USER_SETTINGS } from "#/mocks/handlers";
@ -359,7 +360,7 @@ describe("Settings 404", () => {
vi.resetAllMocks();
});
const getConfigSpy = vi.spyOn(OpenHands, "getConfig");
const getConfigSpy = vi.spyOn(OptionService, "getConfig");
const getSettingsSpy = vi.spyOn(SettingsService, "getSettings");
it("should open the settings modal if GET /settings fails with a 404", async () => {
@ -418,7 +419,7 @@ describe("Settings 404", () => {
});
describe("Setup Payment modal", () => {
const getConfigSpy = vi.spyOn(OpenHands, "getConfig");
const getConfigSpy = vi.spyOn(OptionService, "getConfig");
const getSettingsSpy = vi.spyOn(SettingsService, "getSettings");
it("should only render if SaaS mode and is new user", async () => {

View File

@ -5,6 +5,7 @@ import { QueryClientProvider, QueryClient } from "@tanstack/react-query";
import LlmSettingsScreen from "#/routes/llm-settings";
import SettingsService from "#/settings-service/settings-service.api";
import OpenHands from "#/api/open-hands";
import OptionService from "#/api/option-service/option-service.api";
import {
MOCK_DEFAULT_USER_SETTINGS,
resetTestHandlersMockSettings,
@ -697,7 +698,7 @@ describe("Status toasts", () => {
describe("SaaS mode", () => {
it("should not render the runtime settings input in oss mode", async () => {
const getConfigSpy = vi.spyOn(OpenHands, "getConfig");
const getConfigSpy = vi.spyOn(OptionService, "getConfig");
// @ts-expect-error - only return mode
getConfigSpy.mockResolvedValue({
APP_MODE: "oss",
@ -715,7 +716,7 @@ describe("SaaS mode", () => {
});
it("should render the runtime settings input in saas mode", async () => {
const getConfigSpy = vi.spyOn(OpenHands, "getConfig");
const getConfigSpy = vi.spyOn(OptionService, "getConfig");
// @ts-expect-error - only return mode
getConfigSpy.mockResolvedValue({
APP_MODE: "saas",
@ -733,7 +734,7 @@ describe("SaaS mode", () => {
});
it("should always render the runtime settings input as disabled", async () => {
const getConfigSpy = vi.spyOn(OpenHands, "getConfig");
const getConfigSpy = vi.spyOn(OptionService, "getConfig");
// @ts-expect-error - only return mode
getConfigSpy.mockResolvedValue({
APP_MODE: "saas",

View File

@ -8,6 +8,7 @@ import { SecretsService } from "#/api/secrets-service";
import { GetSecretsResponse } from "#/api/secrets-service.types";
import SettingsService from "#/settings-service/settings-service.api";
import OpenHands from "#/api/open-hands";
import OptionService from "#/api/option-service/option-service.api";
import { MOCK_DEFAULT_USER_SETTINGS } from "#/mocks/handlers";
const MOCK_GET_SECRETS_RESPONSE: GetSecretsResponse["custom_secrets"] = [
@ -54,7 +55,7 @@ const renderSecretsSettings = () =>
});
beforeEach(() => {
const getConfigSpy = vi.spyOn(OpenHands, "getConfig");
const getConfigSpy = vi.spyOn(OptionService, "getConfig");
// @ts-expect-error - only return the config we need
getConfigSpy.mockResolvedValue({
APP_MODE: "oss",
@ -68,7 +69,7 @@ describe("Content", () => {
});
it("should NOT render a button to connect with git if they havent already in oss", async () => {
const getConfigSpy = vi.spyOn(OpenHands, "getConfig");
const getConfigSpy = vi.spyOn(OptionService, "getConfig");
const getSettingsSpy = vi.spyOn(SettingsService, "getSettings");
const getSecretsSpy = vi.spyOn(SecretsService, "getSecrets");
// @ts-expect-error - only return the config we need
@ -88,8 +89,7 @@ describe("Content", () => {
});
it("should render add secret button in saas mode", async () => {
const getConfigSpy = vi.spyOn(OpenHands, "getConfig");
const getSettingsSpy = vi.spyOn(SettingsService, "getSettings");
const getConfigSpy = vi.spyOn(OptionService, "getConfig");
const getSecretsSpy = vi.spyOn(SecretsService, "getSecrets");
// @ts-expect-error - only return the config we need
getConfigSpy.mockResolvedValue({

View File

@ -4,6 +4,7 @@ import { describe, expect, it, vi } from "vitest";
import { QueryClientProvider } from "@tanstack/react-query";
import SettingsScreen, { clientLoader } from "#/routes/settings";
import OpenHands from "#/api/open-hands";
import OptionService from "#/api/option-service/option-service.api";
// Mock the i18next hook
vi.mock("react-i18next", async () => {
@ -93,7 +94,7 @@ describe("Settings Screen", () => {
it("should render the navbar", async () => {
const sectionsToInclude = ["llm", "integrations", "application", "secrets"];
const sectionsToExclude = ["api keys", "credits", "billing"];
const getConfigSpy = vi.spyOn(OpenHands, "getConfig");
const getConfigSpy = vi.spyOn(OptionService, "getConfig");
// @ts-expect-error - only return app mode
getConfigSpy.mockResolvedValue({
APP_MODE: "oss",
@ -156,7 +157,7 @@ describe("Settings Screen", () => {
});
it("should not be able to access saas-only routes in oss mode", async () => {
const getConfigSpy = vi.spyOn(OpenHands, "getConfig");
const getConfigSpy = vi.spyOn(OptionService, "getConfig");
// @ts-expect-error - only return app mode
getConfigSpy.mockResolvedValue({
APP_MODE: "oss",

View File

@ -1,6 +1,6 @@
import { openHands } from "../open-hands-axios";
import { AuthenticateResponse, GitHubAccessTokenResponse } from "./auth.types";
import { GetConfigResponse } from "../open-hands.types";
import { GetConfigResponse } from "../option-service/option.types";
/**
* Authentication service for handling all authentication-related API calls

View File

@ -2,7 +2,6 @@ import { AxiosHeaders } from "axios";
import {
Feedback,
FeedbackResponse,
GetConfigResponse,
GetVSCodeUrlResponse,
Conversation,
ResultSet,
@ -64,42 +63,6 @@ class OpenHands {
return `/api/conversations/${conversationId}`;
}
/**
* Retrieve the list of models available
* @returns List of models available
*/
static async getModels(): Promise<string[]> {
const { data } = await openHands.get<string[]>("/api/options/models");
return data;
}
/**
* Retrieve the list of agents available
* @returns List of agents available
*/
static async getAgents(): Promise<string[]> {
const { data } = await openHands.get<string[]>("/api/options/agents");
return data;
}
/**
* Retrieve the list of security analyzers available
* @returns List of security analyzers available
*/
static async getSecurityAnalyzers(): Promise<string[]> {
const { data } = await openHands.get<string[]>(
"/api/options/security-analyzers",
);
return data;
}
static async getConfig(): Promise<GetConfigResponse> {
const { data } = await openHands.get<GetConfigResponse>(
"/api/options/config",
);
return data;
}
static getConversationHeaders(): AxiosHeaders {
const headers = new AxiosHeaders();
const sessionApiKey = this.currentConversation?.session_api_key;

View File

@ -50,25 +50,6 @@ export interface GetTrajectoryResponse {
error?: string;
}
export interface GetConfigResponse {
APP_MODE: "saas" | "oss";
APP_SLUG?: string;
GITHUB_CLIENT_ID: string;
POSTHOG_CLIENT_KEY: string;
PROVIDERS_CONFIGURED?: Provider[];
AUTH_URL?: string;
FEATURE_FLAGS: {
ENABLE_BILLING: boolean;
HIDE_LLM_SETTINGS: boolean;
ENABLE_JIRA: boolean;
ENABLE_JIRA_DC: boolean;
ENABLE_LINEAR: boolean;
};
MAINTENANCE?: {
startTime: string;
};
}
export interface RepositorySelection {
selected_repository: string | null;
selected_branch: string | null;

View File

@ -0,0 +1,49 @@
import { openHands } from "../open-hands-axios";
import { GetConfigResponse } from "./option.types";
/**
* Service for handling API options endpoints
*/
class OptionService {
/**
* Retrieve the list of models available
* @returns List of models available
*/
static async getModels(): Promise<string[]> {
const { data } = await openHands.get<string[]>("/api/options/models");
return data;
}
/**
* Retrieve the list of agents available
* @returns List of agents available
*/
static async getAgents(): Promise<string[]> {
const { data } = await openHands.get<string[]>("/api/options/agents");
return data;
}
/**
* Retrieve the list of security analyzers available
* @returns List of security analyzers available
*/
static async getSecurityAnalyzers(): Promise<string[]> {
const { data } = await openHands.get<string[]>(
"/api/options/security-analyzers",
);
return data;
}
/**
* Get the configuration from the server
* @returns Configuration response
*/
static async getConfig(): Promise<GetConfigResponse> {
const { data } = await openHands.get<GetConfigResponse>(
"/api/options/config",
);
return data;
}
}
export default OptionService;

View File

@ -0,0 +1,20 @@
import { Provider } from "#/types/settings";
export interface GetConfigResponse {
APP_MODE: "saas" | "oss";
APP_SLUG?: string;
GITHUB_CLIENT_ID: string;
POSTHOG_CLIENT_KEY: string;
PROVIDERS_CONFIGURED?: Provider[];
AUTH_URL?: string;
FEATURE_FLAGS: {
ENABLE_BILLING: boolean;
HIDE_LLM_SETTINGS: boolean;
ENABLE_JIRA: boolean;
ENABLE_JIRA_DC: boolean;
ENABLE_LINEAR: boolean;
};
MAINTENANCE?: {
startTime: string;
};
}

View File

@ -9,7 +9,7 @@ import GitHubLogo from "#/assets/branding/github-logo.svg?react";
import GitLabLogo from "#/assets/branding/gitlab-logo.svg?react";
import BitbucketLogo from "#/assets/branding/bitbucket-logo.svg?react";
import { useAuthUrl } from "#/hooks/use-auth-url";
import { GetConfigResponse } from "#/api/open-hands.types";
import { GetConfigResponse } from "#/api/option-service/option.types";
import { Provider } from "#/types/settings";
interface AuthModalProps {

View File

@ -13,7 +13,7 @@ import posthog from "posthog-js";
import "./i18n";
import { QueryClientProvider } from "@tanstack/react-query";
import store from "./store";
import OpenHands from "./api/open-hands";
import OptionService from "./api/option-service/option-service.api";
import { displayErrorToast } from "./utils/custom-toast-handlers";
import { queryClient } from "./query-client-config";
@ -25,7 +25,7 @@ function PosthogInit() {
React.useEffect(() => {
(async () => {
try {
const config = await OpenHands.getConfig();
const config = await OptionService.getConfig();
setPosthogClientKey(config.POSTHOG_CLIENT_KEY);
} catch (error) {
displayErrorToast("Error fetching PostHog client key");

View File

@ -1,10 +1,10 @@
import { useQuery } from "@tanstack/react-query";
import OpenHands from "#/api/open-hands";
import OptionService from "#/api/option-service/option-service.api";
const fetchAiConfigOptions = async () => ({
models: await OpenHands.getModels(),
agents: await OpenHands.getAgents(),
securityAnalyzers: await OpenHands.getSecurityAnalyzers(),
models: await OptionService.getModels(),
agents: await OptionService.getAgents(),
securityAnalyzers: await OptionService.getSecurityAnalyzers(),
});
export const useAIConfigOptions = () =>

View File

@ -1,5 +1,5 @@
import { useQuery } from "@tanstack/react-query";
import OpenHands from "#/api/open-hands";
import OptionService from "#/api/option-service/option-service.api";
import { useIsOnTosPage } from "#/hooks/use-is-on-tos-page";
export const useConfig = () => {
@ -7,7 +7,7 @@ export const useConfig = () => {
return useQuery({
queryKey: ["config"],
queryFn: OpenHands.getConfig,
queryFn: OptionService.getConfig,
staleTime: 1000 * 60 * 5, // 5 minutes
gcTime: 1000 * 60 * 15, // 15 minutes,
enabled: !isOnTosPage,

View File

@ -1,5 +1,5 @@
import { generateAuthUrl } from "#/utils/generate-auth-url";
import { GetConfigResponse } from "#/api/open-hands.types";
import { GetConfigResponse } from "#/api/option-service/option.types";
interface UseAuthUrlConfig {
appMode: GetConfigResponse["APP_MODE"] | null;

View File

@ -1,5 +1,5 @@
import { useAuthUrl } from "./use-auth-url";
import { GetConfigResponse } from "#/api/open-hands.types";
import { GetConfigResponse } from "#/api/option-service/option.types";
interface UseGitHubAuthUrlConfig {
appMode: GetConfigResponse["APP_MODE"] | null;

View File

@ -1,9 +1,6 @@
import { delay, http, HttpResponse } from "msw";
import {
Conversation,
ResultSet,
GetConfigResponse,
} from "#/api/open-hands.types";
import { GetConfigResponse } from "#/api/option-service/option.types";
import { Conversation, ResultSet } from "#/api/open-hands.types";
import { DEFAULT_SETTINGS } from "#/services/settings";
import { STRIPE_BILLING_HANDLERS } from "./billing-handlers";
import { Provider } from "#/types/settings";

View File

@ -1,6 +1,6 @@
import { queryClient } from "#/query-client-config";
import { GetConfigResponse } from "#/api/open-hands.types";
import OpenHands from "#/api/open-hands";
import { GetConfigResponse } from "#/api/option-service/option.types";
import OptionService from "#/api/option-service/option-service.api";
import { MicroagentManagementContent } from "#/components/features/microagent-management/microagent-management-content";
import { ConversationSubscriptionsProvider } from "#/context/conversation-subscriptions-provider";
import { EventHandler } from "#/wrapper/event-handler";
@ -8,7 +8,7 @@ import { EventHandler } from "#/wrapper/event-handler";
export const clientLoader = async () => {
let config = queryClient.getQueryData<GetConfigResponse>(["config"]);
if (!config) {
config = await OpenHands.getConfig();
config = await OptionService.getConfig();
queryClient.setQueryData<GetConfigResponse>(["config"], config);
}

View File

@ -6,9 +6,9 @@ import { cn } from "#/utils/utils";
import { useConfig } from "#/hooks/query/use-config";
import { I18nKey } from "#/i18n/declaration";
import { Route } from "./+types/settings";
import OpenHands from "#/api/open-hands";
import OptionService from "#/api/option-service/option-service.api";
import { queryClient } from "#/query-client-config";
import { GetConfigResponse } from "#/api/open-hands.types";
import { GetConfigResponse } from "#/api/option-service/option.types";
import { useSubscriptionAccess } from "#/hooks/query/use-subscription-access";
const SAAS_ONLY_PATHS = [
@ -42,7 +42,7 @@ export const clientLoader = async ({ request }: Route.ClientLoaderArgs) => {
let config = queryClient.getQueryData<GetConfigResponse>(["config"]);
if (!config) {
config = await OpenHands.getConfig();
config = await OptionService.getConfig();
queryClient.setQueryData<GetConfigResponse>(["config"], config);
}