Download src/hooks/chat/use-plan-mode-interceptor.ts from SaylorTwift/openhands: direct link, hf CLI and curl.
- Browser
- Download file 3.72 kB
-
https://huggingface.co/SaylorTwift/openhands/resolve/main/src/hooks/chat/use-plan-mode-interceptor.ts
- Command line
-
hf download hf://SaylorTwift/openhands/src/hooks/chat/use-plan-mode-interceptor.ts
-
curl -L -o use-plan-mode-interceptor.ts https://huggingface.co/SaylorTwift/openhands/resolve/main/src/hooks/chat/use-plan-mode-interceptor.ts
3.72 kB
| import { useCallback } from "react"; | |
| import { useConversationStore } from "#/stores/conversation-store"; | |
| import { useHandlePlanClick } from "#/hooks/use-handle-plan-click"; | |
| import { | |
| useMainWebSocketStatus, | |
| useUnifiedWebSocketStatus, | |
| } from "#/hooks/use-unified-websocket-status"; | |
| import { usePlanningAgentState } from "#/hooks/use-agent-state"; | |
| import { AgentState } from "#/types/agent-state"; | |
| import { PLAN_COMMAND, CODE_COMMAND } from "#/utils/constants"; | |
| const PLAN_PREFIX = `${PLAN_COMMAND} `; | |
| const CODE_PREFIX = `${CODE_COMMAND} `; | |
| /** | |
| * Intercepts "/plan [task]" and "/code [task]" and toggles the conversation's | |
| * mode like the Code/Plan button, instead of sending them as a chat message. | |
| * A bare command only switches mode; "<task>" is sent immediately (mode is | |
| * set synchronously first, so the send routes to the new mode — see | |
| * conversation-websocket-context.tsx's `getState().conversationMode` read), | |
| * or becomes the new planner's `initial_message` if it doesn't exist yet. | |
| * | |
| * Swallows the command while the relevant agent is running, a planner is | |
| * being created, or the socket it needs is disconnected — "/code" gates on | |
| * the main socket alone (not the main+planning merged status) so a momentary | |
| * planning reconnect can't swallow it, and "/plan <task>" also checks the | |
| * planner's own running state so it can't be routed into one still mid-run. | |
| */ | |
| export const usePlanModeInterceptor = ( | |
| conversationId: string | null | undefined, | |
| curAgentState: AgentState, | |
| onSubmit: (message: string) => void, | |
| ) => { | |
| const setConversationMode = useConversationStore( | |
| (s) => s.setConversationMode, | |
| ); | |
| const { handlePlanClick, hasPlanner, isCreatingConversation } = | |
| useHandlePlanClick(); | |
| const isMainWebSocketConnected = useMainWebSocketStatus() === "OPEN"; | |
| const isWebSocketConnected = useUnifiedWebSocketStatus() === "OPEN"; | |
| const { isPlanningAgentRunning } = usePlanningAgentState(); | |
| return useCallback( | |
| (message: string) => { | |
| const trimmed = message.trim(); | |
| const isPlan = | |
| trimmed === PLAN_COMMAND || trimmed.startsWith(PLAN_PREFIX); | |
| const isCode = | |
| trimmed === CODE_COMMAND || trimmed.startsWith(CODE_PREFIX); | |
| if (!conversationId || (!isPlan && !isCode)) { | |
| onSubmit(message); | |
| return; | |
| } | |
| if (curAgentState === AgentState.RUNNING || isCreatingConversation) { | |
| return; | |
| } | |
| if (isPlan) { | |
| if (isPlanningAgentRunning || !isWebSocketConnected) { | |
| return; | |
| } | |
| const task = trimmed.slice(PLAN_COMMAND.length).trim(); | |
| if (task && hasPlanner) { | |
| // Planner already exists: switch mode, then send normally — the | |
| // send path reads the just-set mode synchronously, so this routes | |
| // to the planner rather than the code agent. | |
| setConversationMode("plan"); | |
| onSubmit(task); | |
| } else { | |
| handlePlanClick(undefined, task || undefined); | |
| } | |
| } else { | |
| if (!isMainWebSocketConnected) { | |
| return; | |
| } | |
| setConversationMode("code"); | |
| const task = trimmed.slice(CODE_COMMAND.length).trim(); | |
| if (task) { | |
| // The parent (code) conversation always already exists, so this | |
| // can always send immediately — same synchronous-mode-read routing | |
| // as the /plan-with-existing-planner case above. | |
| onSubmit(task); | |
| } | |
| } | |
| }, | |
| [ | |
| conversationId, | |
| curAgentState, | |
| hasPlanner, | |
| isCreatingConversation, | |
| isMainWebSocketConnected, | |
| isPlanningAgentRunning, | |
| isWebSocketConnected, | |
| onSubmit, | |
| handlePlanClick, | |
| setConversationMode, | |
| ], | |
| ); | |
| }; | |