Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

refactor(frontend): settings and friends #1400

Merged
merged 7 commits into from Apr 29, 2024
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Jump to
Jump to file
Failed to load files.
Diff view
Diff view
5 changes: 3 additions & 2 deletions frontend/src/App.tsx
Expand Up @@ -9,13 +9,14 @@ import Workspace from "#/components/Workspace";
import LoadPreviousSessionModal from "#/components/modals/load-previous-session/LoadPreviousSessionModal";
import SettingsModal from "#/components/modals/settings/SettingsModal";
import { fetchMsgTotal } from "#/services/session";
import { initializeAgent } from "#/services/settingsService";
import Socket from "#/services/socket";
import { ResFetchMsgTotal } from "#/types/ResponseType";
import "./App.css";
import AgentControlBar from "./components/AgentControlBar";
import AgentStatusBar from "./components/AgentStatusBar";
import Terminal from "./components/terminal/Terminal";
import { initializeAgent } from "./services/agent";
import { getSettings } from "./services/settings";

interface Props {
setSettingOpen: (isOpen: boolean) => void;
Expand Down Expand Up @@ -72,7 +73,7 @@ function App(): JSX.Element {
if (initOnce) return;
initOnce = true;

initializeAgent();
initializeAgent(getSettings());

Socket.registerCallback("open", [getMsgTotal]);

Expand Down
9 changes: 9 additions & 0 deletions frontend/src/api/index.ts
@@ -0,0 +1,9 @@
export async function fetchModels() {
const response = await fetch(`/api/litellm-models`);
return response.json();
}

export async function fetchAgents() {
const response = await fetch(`/api/agents`);
return response.json();
}
36 changes: 36 additions & 0 deletions frontend/src/components/modals/base-modal/BaseModal.test.tsx
Expand Up @@ -96,6 +96,42 @@ describe("BaseModal", () => {
expect(screen.getByText("Children")).toBeInTheDocument();
});

it("should disable the action given the condition", () => {
const { rerender } = render(
<BaseModal
isOpen
onOpenChange={vi.fn}
title="Settings"
actions={[
{
label: "Save",
action: () => {},
isDisabled: true,
},
]}
/>,
);

expect(screen.getByText("Save")).toBeDisabled();

rerender(
<BaseModal
isOpen
onOpenChange={vi.fn}
title="Settings"
actions={[
{
label: "Save",
action: () => {},
isDisabled: false,
},
]}
/>,
);

expect(screen.getByText("Save")).not.toBeDisabled();
});

it.skip("should not close if the backdrop or escape key is pressed", () => {
const onOpenChangeMock = vi.fn();
render(
Expand Down
30 changes: 17 additions & 13 deletions frontend/src/components/modals/base-modal/FooterContent.tsx
Expand Up @@ -3,6 +3,7 @@ import React from "react";

export interface Action {
action: () => void;
isDisabled?: boolean;
label: string;
className?: string;
closeAfterAction?: boolean;
Expand All @@ -16,19 +17,22 @@ interface FooterContentProps {
export function FooterContent({ actions, closeModal }: FooterContentProps) {
return (
<>
{actions.map(({ action, label, className, closeAfterAction }) => (
<Button
key={label}
type="button"
onClick={() => {
action();
if (closeAfterAction) closeModal();
}}
className={className}
>
{label}
</Button>
))}
{actions.map(
({ action, isDisabled, label, className, closeAfterAction }) => (
<Button
key={label}
type="button"
isDisabled={isDisabled}
onClick={() => {
action();
if (closeAfterAction) closeModal();
}}
className={className}
>
{label}
</Button>
),
)}
</>
);
}
25 changes: 18 additions & 7 deletions frontend/src/components/modals/settings/SettingsForm.test.tsx
Expand Up @@ -4,15 +4,22 @@ import React from "react";
import { renderWithProviders } from "test-utils";
import AgentTaskState from "#/types/AgentTaskState";
import SettingsForm from "./SettingsForm";
import { Settings } from "#/services/settings";

const onModelChangeMock = vi.fn();
const onAgentChangeMock = vi.fn();
const onLanguageChangeMock = vi.fn();

const renderSettingsForm = (settings: Partial<Settings>) => {
const renderSettingsForm = (settings?: Settings) => {
renderWithProviders(
<SettingsForm
settings={settings}
settings={
settings || {
LLM_MODEL: "model1",
AGENT: "agent1",
LANGUAGE: "en",
}
}
models={["model1", "model2", "model3"]}
agents={["agent1", "agent2", "agent3"]}
onModelChange={onModelChangeMock}
Expand All @@ -24,7 +31,7 @@ const renderSettingsForm = (settings: Partial<Settings>) => {

describe("SettingsForm", () => {
it("should display the first values in the array by default", () => {
renderSettingsForm({});
renderSettingsForm();

const modelInput = screen.getByRole("combobox", { name: "model" });
const agentInput = screen.getByRole("combobox", { name: "agent" });
Expand Down Expand Up @@ -54,7 +61,11 @@ describe("SettingsForm", () => {
it("should disable settings while task is running", () => {
renderWithProviders(
<SettingsForm
settings={{}}
settings={{
LLM_MODEL: "model1",
AGENT: "agent1",
LANGUAGE: "en",
}}
models={["model1", "model2", "model3"]}
agents={["agent1", "agent2", "agent3"]}
onModelChange={onModelChangeMock}
Expand All @@ -74,7 +85,7 @@ describe("SettingsForm", () => {

describe("onChange handlers", () => {
it("should call the onModelChange handler when the model changes", () => {
renderSettingsForm({});
renderSettingsForm();

const modelInput = screen.getByRole("combobox", { name: "model" });
act(() => {
Expand All @@ -90,7 +101,7 @@ describe("SettingsForm", () => {
});

it("should call the onAgentChange handler when the agent changes", () => {
renderSettingsForm({});
renderSettingsForm();

const agentInput = screen.getByRole("combobox", { name: "agent" });
act(() => {
Expand All @@ -106,7 +117,7 @@ describe("SettingsForm", () => {
});

it("should call the onLanguageChange handler when the language changes", () => {
renderSettingsForm({});
renderSettingsForm();

const languageInput = screen.getByRole("combobox", { name: "language" });
act(() => {
Expand Down
3 changes: 2 additions & 1 deletion frontend/src/components/modals/settings/SettingsForm.tsx
Expand Up @@ -6,9 +6,10 @@ import { I18nKey } from "../../../i18n/declaration";
import { RootState } from "../../../store";
import AgentTaskState from "../../../types/AgentTaskState";
import { AutocompleteCombobox } from "./AutocompleteCombobox";
import { Settings } from "#/services/settings";

interface SettingsFormProps {
settings: Partial<Settings>;
settings: Settings;
models: string[];
agents: string[];

Expand Down