From 0c00e84e774891257c72dbdc0bd092aea7c33916 Mon Sep 17 00:00:00 2001 From: Jim Su Date: Wed, 3 Apr 2024 13:56:47 -0400 Subject: [PATCH] Send initialization arguments only when stored in localStorage (#618) * Send initialization arguments only when stored in localStorage * Fix mock default-model path --- frontend/.eslintrc | 4 ++-- frontend/src/components/SettingModal.tsx | 9 ++++++++- frontend/src/services/settingsService.ts | 9 +++++++++ frontend/src/socket/socket.ts | 12 +++++++++++- frontend/src/state/settingsSlice.ts | 2 +- opendevin/mock/listen.py | 4 ++++ opendevin/server/listen.py | 5 +++++ 7 files changed, 40 insertions(+), 5 deletions(-) diff --git a/frontend/.eslintrc b/frontend/.eslintrc index e259190dc5..c151040b0e 100644 --- a/frontend/.eslintrc +++ b/frontend/.eslintrc @@ -18,11 +18,11 @@ { "files": ["*.ts", "*.tsx"], "rules": { - // Allow state modification in Redux reducers + // Allow state modification in reduce and Redux reducers "no-param-reassign": ["error", { "props": true, "ignorePropertyModificationsFor": [ - "state" + "acc", "state" ] }], // For https://stackoverflow.com/questions/55844608/stuck-with-eslint-error-i-e-separately-loops-should-be-avoided-in-favor-of-arra diff --git a/frontend/src/components/SettingModal.tsx b/frontend/src/components/SettingModal.tsx index fdac5880eb..b95be89773 100644 --- a/frontend/src/components/SettingModal.tsx +++ b/frontend/src/components/SettingModal.tsx @@ -18,6 +18,7 @@ import { fetchAgents, INITIAL_MODELS, sendSettings, + getInitialModel, } from "../services/settingsService"; import { setModel, @@ -54,6 +55,12 @@ function SettingModal({ isOpen, onClose }: Props): JSX.Element { ); useEffect(() => { + async function setInitialModel() { + const initialModel = await getInitialModel(); + store.dispatch(setModel(initialModel)); + } + setInitialModel(); + fetchModels().then((fetchedModels) => { setSupportedModels(fetchedModels); localStorage.setItem("supportedModels", JSON.stringify(fetchedModels)); @@ -100,7 +107,7 @@ function SettingModal({ isOpen, onClose }: Props): JSX.Element { }))} label="Model" placeholder="Select a model" - defaultSelectedKey={model} + selectedKey={model} // className="max-w-xs" onSelectionChange={(key) => { store.dispatch(setModel(key as string)); diff --git a/frontend/src/services/settingsService.ts b/frontend/src/services/settingsService.ts index 3ff8d1be6d..51f3e105ff 100644 --- a/frontend/src/services/settingsService.ts +++ b/frontend/src/services/settingsService.ts @@ -2,6 +2,15 @@ import { appendAssistantMessage } from "../state/chatSlice"; import { setInitialized } from "../state/taskSlice"; import store from "../store"; +export async function getInitialModel() { + if (localStorage.getItem("model")) { + return localStorage.getItem("model"); + } + + const res = await fetch("/api/default-model"); + return res.json(); +} + export async function fetchModels() { const response = await fetch(`/api/litellm-models`); return response.json(); diff --git a/frontend/src/socket/socket.ts b/frontend/src/socket/socket.ts index 5284a4fc7f..b53590fe7a 100644 --- a/frontend/src/socket/socket.ts +++ b/frontend/src/socket/socket.ts @@ -12,7 +12,17 @@ const WS_URL = `ws://${window.location.host}/ws`; const socket = new WebSocket(WS_URL); socket.addEventListener("open", () => { - const { settings } = store.getState(); + const settingKeys = ["model", "agent", "workspaceDirectory"]; + const settings = settingKeys.reduce( + (acc, key) => { + const value = localStorage.getItem(key); + if (value) { + acc[key] = value; + } + return acc; + }, + {} as Record, + ); sendSettings(socket, settings, false); }); socket.addEventListener("message", (event) => { diff --git a/frontend/src/state/settingsSlice.ts b/frontend/src/state/settingsSlice.ts index c24b92daf6..a694099a6b 100644 --- a/frontend/src/state/settingsSlice.ts +++ b/frontend/src/state/settingsSlice.ts @@ -3,7 +3,7 @@ import { createSlice } from "@reduxjs/toolkit"; export const settingsSlice = createSlice({ name: "settings", initialState: { - model: localStorage.getItem("model") || "gpt-4-0125-preview", + model: localStorage.getItem("model") || "", agent: localStorage.getItem("agent") || "MonologueAgent", workspaceDirectory: localStorage.getItem("workspaceDirectory") || "./workspace", diff --git a/opendevin/mock/listen.py b/opendevin/mock/listen.py index 20dd3e48e2..3e50c638f3 100644 --- a/opendevin/mock/listen.py +++ b/opendevin/mock/listen.py @@ -42,5 +42,9 @@ def read_llm_agents(): "PlannerAgent", ] +@app.get("/default-model") +def read_default_model(): + return "gpt-4" + if __name__ == "__main__": uvicorn.run(app, host="127.0.0.1", port=3000) diff --git a/opendevin/server/listen.py b/opendevin/server/listen.py index 2287019840..c9d11621fa 100644 --- a/opendevin/server/listen.py +++ b/opendevin/server/listen.py @@ -4,6 +4,7 @@ from fastapi.middleware.cors import CORSMiddleware import agenthub # noqa F401 (we import this to get the agents registered) import litellm from opendevin.agent import Agent +from opendevin import config app = FastAPI() @@ -36,3 +37,7 @@ async def get_litellm_agents(): Get all agents supported by LiteLLM. """ return Agent.listAgents() + +@app.get("/default-model") +def read_default_model(): + return config.get_or_error("LLM_MODEL")