mirror of
https://github.com/OpenHands/OpenHands.git
synced 2025-12-26 05:48:36 +08:00
Minor changes to agent state management (#1597)
* move towards event stream * refactor agent state changes * move agent state logic * fix callbacks * break on finish * closer to working * change frontend to accomodate new flow * handle start action * fix locked stream * revert message * logspam * no async on close * get rid of agent_task * fix up closing * better asyncio handling * sleep to give back control * fix key * logspam * update frontend agent state actions * fix pause and cancel * delint * fix map * delint * wait for agent to finish * fix unit test * event stream enums * fix merge issues * fix lint * fix test * fix test * add user message action * add user message action * fix up user messages * fix main.py flow * refactor message waiting * lint * fix test * fix test * simplify if/else * fix state reset * logspam * add error status * minor changes to control bar * handle user messages when not awaiting * restart agent after stopping * Update opendevin/controller/agent_controller.py Co-authored-by: Engel Nyst <enyst@users.noreply.github.com> * delint * refactor initialize * delint * fix dispatch --------- Co-authored-by: Engel Nyst <enyst@users.noreply.github.com>
This commit is contained in:
parent
c9970e6817
commit
d0967122f8
@ -16,7 +16,6 @@ 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;
|
||||
@ -73,7 +72,7 @@ function App(): JSX.Element {
|
||||
if (initOnce) return;
|
||||
initOnce = true;
|
||||
|
||||
initializeAgent(getSettings());
|
||||
initializeAgent();
|
||||
|
||||
Socket.registerCallback("open", [getMsgTotal]);
|
||||
|
||||
|
||||
@ -25,11 +25,7 @@ const IgnoreTaskStateMap: { [k: string]: AgentState[] } = {
|
||||
AgentState.FINISHED,
|
||||
AgentState.AWAITING_USER_INPUT,
|
||||
],
|
||||
[AgentState.STOPPED]: [
|
||||
AgentState.INIT,
|
||||
AgentState.STOPPED,
|
||||
AgentState.FINISHED,
|
||||
],
|
||||
[AgentState.STOPPED]: [AgentState.INIT, AgentState.STOPPED],
|
||||
};
|
||||
|
||||
interface ButtonProps {
|
||||
@ -76,18 +72,15 @@ function AgentControlBar() {
|
||||
return;
|
||||
}
|
||||
|
||||
let act = action;
|
||||
|
||||
if (act === AgentState.STOPPED) {
|
||||
act = AgentState.STOPPED;
|
||||
if (action === AgentState.STOPPED) {
|
||||
clearMsgs().then().catch();
|
||||
store.dispatch(clearMessages());
|
||||
} else {
|
||||
setIsLoading(true);
|
||||
}
|
||||
|
||||
setDesiredState(act);
|
||||
changeAgentState(act);
|
||||
setDesiredState(action);
|
||||
changeAgentState(action);
|
||||
};
|
||||
|
||||
useEffect(() => {
|
||||
@ -125,7 +118,7 @@ function AgentControlBar() {
|
||||
isLoading ||
|
||||
IgnoreTaskStateMap[AgentState.PAUSED].includes(curAgentState)
|
||||
}
|
||||
content="Pause the agent task"
|
||||
content="Pause the current task"
|
||||
action={AgentState.PAUSED}
|
||||
handleAction={handleAction}
|
||||
large
|
||||
@ -135,7 +128,7 @@ function AgentControlBar() {
|
||||
)}
|
||||
<ActionButton
|
||||
isDisabled={isLoading}
|
||||
content="Restart a new agent task"
|
||||
content="Start a new task"
|
||||
action={AgentState.STOPPED}
|
||||
handleAction={handleAction}
|
||||
>
|
||||
|
||||
@ -31,6 +31,10 @@ const AgentStatusMap: { [k: string]: { message: string; indicator: string } } =
|
||||
message: "Agent has finished the task.",
|
||||
indicator: "bg-green-500",
|
||||
},
|
||||
[AgentState.ERROR]: {
|
||||
message: "Agent encountered an error.",
|
||||
indicator: "bg-red-500",
|
||||
},
|
||||
};
|
||||
|
||||
function AgentStatusBar() {
|
||||
|
||||
@ -14,7 +14,9 @@ function ChatInterface() {
|
||||
const { curAgentState } = useSelector((state: RootState) => state.agent);
|
||||
|
||||
const handleSendMessage = (content: string) => {
|
||||
const isTask = curAgentState === AgentState.INIT;
|
||||
const isTask =
|
||||
curAgentState === AgentState.INIT ||
|
||||
curAgentState === AgentState.FINISHED;
|
||||
dispatch(addUserMessage(content));
|
||||
sendChatMessage(content, isTask);
|
||||
};
|
||||
|
||||
@ -74,7 +74,7 @@ function SettingsModal({ isOpen, onOpenChange }: SettingsProps) {
|
||||
const updatedSettings = getSettingsDifference(settings);
|
||||
saveSettings(settings);
|
||||
i18next.changeLanguage(settings.LANGUAGE);
|
||||
initializeAgent(settings); // reinitialize the agent with the new settings
|
||||
initializeAgent(); // reinitialize the agent with the new settings
|
||||
|
||||
const sensitiveKeys = ["LLM_API_KEY"];
|
||||
|
||||
|
||||
@ -2,7 +2,7 @@ import { describe, expect, it, vi } from "vitest";
|
||||
|
||||
import ActionType from "#/types/ActionType";
|
||||
import { initializeAgent } from "./agent";
|
||||
import { Settings } from "./settings";
|
||||
import { Settings, saveSettings } from "./settings";
|
||||
import Socket from "./socket";
|
||||
|
||||
const sendSpy = vi.spyOn(Socket, "send");
|
||||
@ -21,7 +21,8 @@ describe("initializeAgent", () => {
|
||||
args: settings,
|
||||
};
|
||||
|
||||
initializeAgent(settings);
|
||||
saveSettings(settings);
|
||||
initializeAgent();
|
||||
|
||||
expect(sendSpy).toHaveBeenCalledWith(JSON.stringify(event));
|
||||
});
|
||||
|
||||
@ -1,12 +1,13 @@
|
||||
import ActionType from "#/types/ActionType";
|
||||
import { Settings } from "./settings";
|
||||
import { getSettings } from "./settings";
|
||||
import Socket from "./socket";
|
||||
|
||||
/**
|
||||
* Initialize the agent with the current settings.
|
||||
* @param settings - The new settings.
|
||||
*/
|
||||
export const initializeAgent = (settings: Settings) => {
|
||||
export const initializeAgent = () => {
|
||||
const settings = getSettings();
|
||||
const event = { action: ActionType.INIT, args: settings };
|
||||
const eventString = JSON.stringify(event);
|
||||
Socket.send(eventString);
|
||||
|
||||
@ -1,11 +1,19 @@
|
||||
import ActionType from "#/types/ActionType";
|
||||
import AgentState from "#/types/AgentState";
|
||||
import Socket from "./socket";
|
||||
import { initializeAgent } from "./agent";
|
||||
|
||||
export function changeAgentState(message: AgentState): void {
|
||||
const INIT_DELAY = 1000;
|
||||
|
||||
export function changeAgentState(state: AgentState): void {
|
||||
const eventString = JSON.stringify({
|
||||
action: ActionType.CHANGE_AGENT_STATE,
|
||||
args: { agent_state: message },
|
||||
args: { agent_state: state },
|
||||
});
|
||||
Socket.send(eventString);
|
||||
if (state === AgentState.STOPPED) {
|
||||
setTimeout(() => {
|
||||
initializeAgent();
|
||||
}, INIT_DELAY);
|
||||
}
|
||||
}
|
||||
|
||||
@ -54,6 +54,7 @@ class AgentController:
|
||||
state: State | None = None
|
||||
_agent_state: AgentState = AgentState.LOADING
|
||||
_cur_step: int = 0
|
||||
_pending_talk_action: AgentTalkAction | None = None
|
||||
|
||||
def __init__(
|
||||
self,
|
||||
@ -175,13 +176,19 @@ class AgentController:
|
||||
if isinstance(event, ChangeAgentStateAction):
|
||||
await self.set_agent_state_to(event.agent_state) # type: ignore
|
||||
elif isinstance(event, MessageAction) and event.source == EventSource.USER:
|
||||
# FIXME: we're hacking a message action into a user message observation, for the benefit of CodeAct
|
||||
await self.add_history(
|
||||
self._pending_talk_action,
|
||||
UserMessageObservation(event.content),
|
||||
add_to_stream=False,
|
||||
)
|
||||
await self.set_agent_state_to(AgentState.RUNNING)
|
||||
if self._pending_talk_action is None:
|
||||
await self.add_history(
|
||||
NullAction(), UserMessageObservation(event.content)
|
||||
)
|
||||
else:
|
||||
# FIXME: we're hacking a message action into a user message observation, for the benefit of CodeAct
|
||||
await self.add_history(
|
||||
self._pending_talk_action,
|
||||
UserMessageObservation(event.content),
|
||||
add_to_stream=False,
|
||||
)
|
||||
self._pending_talk_action = None
|
||||
await self.set_agent_state_to(AgentState.RUNNING)
|
||||
|
||||
async def reset_task(self):
|
||||
if self.agent_task is not None:
|
||||
|
||||
Loading…
x
Reference in New Issue
Block a user