-
-
Notifications
You must be signed in to change notification settings - Fork 9.2k
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
feat: implement agent global state #400
Changes from 27 commits
6b35326
4e36a48
a0b199d
f7dcc73
2855687
7d8f9ab
30e77ff
a280460
8da0cb1
acd105d
f2e082e
d70d817
1561d2e
05687e3
b6facf6
ff5a11a
50a384f
bd84241
77d6a8b
e16933b
444b1c1
e418eab
6a73ad1
0402392
3d14b53
39886c6
6c58802
fb15157
a832040
File filter
Filter by extension
Conversations
Jump to
Diff view
Diff view
There are no files selected for viewing
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,38 @@ | ||
import { createSelectors } from "./helpers"; | ||
import type { StateCreator } from "zustand"; | ||
import { create } from "zustand"; | ||
import type AutonomousAgent from "../AutonomousAgent"; | ||
|
||
const initialAgentState = { | ||
agent: null, | ||
isAgentStopped: true, | ||
}; | ||
|
||
interface AgentSlice { | ||
agent: AutonomousAgent | null; | ||
isAgentStopped: boolean; | ||
setIsAgentStopped: () => void; | ||
setAgent: (newAgent: AutonomousAgent | null) => void; | ||
} | ||
|
||
const createAgentSlice: StateCreator<AgentSlice> = (set, get) => { | ||
return { | ||
...initialAgentState, | ||
setIsAgentStopped: () => { | ||
set((state) => ({ | ||
isAgentStopped: !state.agent?.isRunning, | ||
})); | ||
}, | ||
setAgent: (newAgent) => { | ||
set(() => ({ | ||
agent: newAgent, | ||
})); | ||
}, | ||
}; | ||
}; | ||
|
||
export const useAgentStore = createSelectors( | ||
create<AgentSlice>()((...a) => ({ | ||
...createAgentSlice(...a), | ||
})) | ||
); |
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -1 +1,2 @@ | ||
export * from "./messageStore"; | ||
export * from "./agentStore"; |
Original file line number | Diff line number | Diff line change | ||||||||||||
---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|
|
@@ -19,25 +19,33 @@ import { useAuth } from "../hooks/useAuth"; | |||||||||||||
import type { Message } from "../types/agentTypes"; | ||||||||||||||
import { useAgent } from "../hooks/useAgent"; | ||||||||||||||
import { isEmptyOrBlank } from "../utils/whitespace"; | ||||||||||||||
import { useMessageStore, resetAllSlices } from "../components/store"; | ||||||||||||||
import { | ||||||||||||||
useMessageStore, | ||||||||||||||
useAgentStore, | ||||||||||||||
resetAllMessageSlices, | ||||||||||||||
} from "../components/stores"; | ||||||||||||||
import { isTask } from "../types/agentTypes"; | ||||||||||||||
import { serverSideTranslations } from "next-i18next/serverSideTranslations"; | ||||||||||||||
import { useSettings } from "../hooks/useSettings"; | ||||||||||||||
|
||||||||||||||
const Home: NextPage = () => { | ||||||||||||||
const [t] = useTranslation(); | ||||||||||||||
// zustand states | ||||||||||||||
// zustand states with state dependencies | ||||||||||||||
const addMessage = useMessageStore.use.addMessage(); | ||||||||||||||
const messages = useMessageStore.use.messages(); | ||||||||||||||
const tasks = useMessageStore.use.tasks(); | ||||||||||||||
const addMessage = useMessageStore.use.addMessage(); | ||||||||||||||
const updateTaskStatus = useMessageStore.use.updateTaskStatus(); | ||||||||||||||
|
||||||||||||||
const setAgent = useAgentStore.use.setAgent(); | ||||||||||||||
const isAgentStopped = useAgentStore.use.isAgentStopped(); | ||||||||||||||
const setIsAgentStopped = useAgentStore.use.setIsAgentStopped(); | ||||||||||||||
const agent = useAgentStore.use.agent(); | ||||||||||||||
|
||||||||||||||
const { session, status } = useAuth(); | ||||||||||||||
const [name, setName] = React.useState<string>(""); | ||||||||||||||
const [goalInput, setGoalInput] = React.useState<string>(""); | ||||||||||||||
const [agent, setAgent] = React.useState<AutonomousAgent | null>(null); | ||||||||||||||
const settingsModel = useSettings(); | ||||||||||||||
const [shouldAgentStop, setShouldAgentStop] = React.useState(false); | ||||||||||||||
|
||||||||||||||
const [showHelpDialog, setShowHelpDialog] = React.useState(false); | ||||||||||||||
const [showSettingsDialog, setShowSettingsDialog] = React.useState(false); | ||||||||||||||
const [hasSaved, setHasSaved] = React.useState(false); | ||||||||||||||
|
@@ -62,10 +70,8 @@ const Home: NextPage = () => { | |||||||||||||
}, []); | ||||||||||||||
|
||||||||||||||
useEffect(() => { | ||||||||||||||
if (agent == null) { | ||||||||||||||
setShouldAgentStop(false); | ||||||||||||||
} | ||||||||||||||
}, [agent]); | ||||||||||||||
setIsAgentStopped(); | ||||||||||||||
}, [agent, setIsAgentStopped]); | ||||||||||||||
|
||||||||||||||
const handleAddMessage = (message: Message) => { | ||||||||||||||
if (isTask(message)) { | ||||||||||||||
|
@@ -78,21 +84,19 @@ const Home: NextPage = () => { | |||||||||||||
const disableDeployAgent = | ||||||||||||||
agent != null || isEmptyOrBlank(name) || isEmptyOrBlank(goalInput); | ||||||||||||||
|
||||||||||||||
const isAgentStopped = () => !agent?.isRunning || agent === null; | ||||||||||||||
|
||||||||||||||
const handleNewGoal = () => { | ||||||||||||||
const agent = new AutonomousAgent( | ||||||||||||||
const newAgent = new AutonomousAgent( | ||||||||||||||
name.trim(), | ||||||||||||||
goalInput.trim(), | ||||||||||||||
handleAddMessage, | ||||||||||||||
() => setAgent(null), | ||||||||||||||
settingsModel.settings, | ||||||||||||||
session ?? undefined | ||||||||||||||
); | ||||||||||||||
setAgent(agent); | ||||||||||||||
setAgent(newAgent); | ||||||||||||||
setHasSaved(false); | ||||||||||||||
resetAllSlices(); | ||||||||||||||
agent.run().then(console.log).catch(console.error); | ||||||||||||||
resetAllMessageSlices(); | ||||||||||||||
newAgent?.run().then(console.log).catch(console.error); | ||||||||||||||
}; | ||||||||||||||
|
||||||||||||||
const handleKeyPress = ( | ||||||||||||||
|
@@ -109,7 +113,6 @@ const Home: NextPage = () => { | |||||||||||||
}; | ||||||||||||||
|
||||||||||||||
const handleStopAgent = () => { | ||||||||||||||
setShouldAgentStop(true); | ||||||||||||||
agent?.stopAgent(); | ||||||||||||||
}; | ||||||||||||||
|
||||||||||||||
|
@@ -121,7 +124,7 @@ const Home: NextPage = () => { | |||||||||||||
|
||||||||||||||
const shouldShowSave = | ||||||||||||||
status === "authenticated" && | ||||||||||||||
!agent?.isRunning && | ||||||||||||||
isAgentStopped && | ||||||||||||||
messages.length && | ||||||||||||||
!hasSaved; | ||||||||||||||
|
||||||||||||||
|
@@ -194,11 +197,8 @@ const Home: NextPage = () => { | |||||||||||||
: undefined | ||||||||||||||
} | ||||||||||||||
scrollToBottom | ||||||||||||||
isAgentStopped={isAgentStopped()} | ||||||||||||||
/> | ||||||||||||||
{tasks.length > 0 && ( | ||||||||||||||
<TaskWindow isAgentStopped={isAgentStopped()} /> | ||||||||||||||
)} | ||||||||||||||
{tasks.length > 0 && <TaskWindow />} | ||||||||||||||
</Expand> | ||||||||||||||
|
||||||||||||||
<div className="flex w-full flex-col gap-2 sm:m-4 "> | ||||||||||||||
|
@@ -248,11 +248,11 @@ const Home: NextPage = () => { | |||||||||||||
)} | ||||||||||||||
</Button> | ||||||||||||||
<Button | ||||||||||||||
disabled={agent == null} | ||||||||||||||
disabled={agent === null} | ||||||||||||||
onClick={handleStopAgent} | ||||||||||||||
enabledClassName={"bg-red-600 hover:bg-red-400"} | ||||||||||||||
> | ||||||||||||||
{shouldAgentStop ? ( | ||||||||||||||
{!isAgentStopped && agent === null ? ( | ||||||||||||||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Not sure if this makes semantic sense. The above is saying: There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. agreed, I could be wrong but this might be outdated code and imo we should just remove this completely. my understanding is that this is handling a state where agent has been shutdown (i.e. set to In today's code, AgentGPT/src/components/AutonomousAgent.ts Lines 255 to 260 in 4e83cd0
CC: @asim-shrestha There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Yeah lets refactor this after |
||||||||||||||
<> | ||||||||||||||
<VscLoading className="animate-spin" size={20} /> | ||||||||||||||
<span className="ml-2">{t("Stopping")}</span> | ||||||||||||||
|
Original file line number | Diff line number | Diff line change | ||||||||||||||||||||||||||||||||||||||||||
---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|
@@ -1,5 +1,6 @@ | ||||||||||||||||||||||||||||||||||||||||||||
import { z } from "zod"; | ||||||||||||||||||||||||||||||||||||||||||||
|
||||||||||||||||||||||||||||||||||||||||||||
/* Message & Task Type */ | ||||||||||||||||||||||||||||||||||||||||||||
export const [ | ||||||||||||||||||||||||||||||||||||||||||||
MESSAGE_TYPE_GOAL, | ||||||||||||||||||||||||||||||||||||||||||||
MESSAGE_TYPE_THINKING, | ||||||||||||||||||||||||||||||||||||||||||||
|
@@ -65,6 +66,20 @@ export const messageSchema = z.union([taskSchema, nonTaskScehma]); | |||||||||||||||||||||||||||||||||||||||||||
export type Task = z.infer<typeof taskSchema>; | ||||||||||||||||||||||||||||||||||||||||||||
export type Message = z.infer<typeof messageSchema>; | ||||||||||||||||||||||||||||||||||||||||||||
|
||||||||||||||||||||||||||||||||||||||||||||
/* Agent Type */ | ||||||||||||||||||||||||||||||||||||||||||||
export const [AGENT_STATUS_RUNNING, AGENT_STATUS_STOPPED] = [ | ||||||||||||||||||||||||||||||||||||||||||||
"running" as const, | ||||||||||||||||||||||||||||||||||||||||||||
"stopped" as const, | ||||||||||||||||||||||||||||||||||||||||||||
]; | ||||||||||||||||||||||||||||||||||||||||||||
|
||||||||||||||||||||||||||||||||||||||||||||
const AgentStatusSchema = z.union([ | ||||||||||||||||||||||||||||||||||||||||||||
z.literal(AGENT_STATUS_RUNNING), | ||||||||||||||||||||||||||||||||||||||||||||
z.literal(AGENT_STATUS_STOPPED), | ||||||||||||||||||||||||||||||||||||||||||||
z.literal(""), | ||||||||||||||||||||||||||||||||||||||||||||
]); | ||||||||||||||||||||||||||||||||||||||||||||
|
||||||||||||||||||||||||||||||||||||||||||||
export type AgentStatus = z.infer<typeof AgentStatusSchema>; | ||||||||||||||||||||||||||||||||||||||||||||
|
||||||||||||||||||||||||||||||||||||||||||||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. This seems a hard to work with. Any reason we cant do the below?
Suggested change
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. made it more concise 🎉 AgentGPT/src/types/agentTypes.ts Lines 70 to 77 in a832040
keeping |
||||||||||||||||||||||||||||||||||||||||||||
/* Type Predicates */ | ||||||||||||||||||||||||||||||||||||||||||||
export const isTask = (value: unknown): value is Task => { | ||||||||||||||||||||||||||||||||||||||||||||
try { | ||||||||||||||||||||||||||||||||||||||||||||
|
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
an interface of
Might make more sense. Remove agent would agent.stop(), setAgent(null) and also update isAgentStopped