mirror of
https://github.com/RooVetGit/Roo-Code.git
synced 2026-08-28 05:27:24 +00:00
183 lines
4.3 KiB
TypeScript
183 lines
4.3 KiB
TypeScript
import { useCallback } from "react"
|
|
import { randomUUID } from "crypto"
|
|
import type { WebviewMessage } from "@roo-code/types"
|
|
|
|
import { getGlobalCommand } from "../../lib/utils/commands.js"
|
|
|
|
import { useCLIStore } from "../store.js"
|
|
import { useUIStateStore } from "../stores/uiStateStore.js"
|
|
|
|
export interface UseTaskSubmitOptions {
|
|
sendToExtension: ((msg: WebviewMessage) => void) | null
|
|
runTask: ((prompt: string) => Promise<void>) | null
|
|
seenMessageIds: React.MutableRefObject<Set<string>>
|
|
firstTextMessageSkipped: React.MutableRefObject<boolean>
|
|
}
|
|
|
|
export interface UseTaskSubmitReturn {
|
|
handleSubmit: (text: string) => Promise<void>
|
|
handleApprove: () => void
|
|
handleReject: () => void
|
|
}
|
|
|
|
/**
|
|
* Hook to handle task submission, user responses, and approvals.
|
|
*
|
|
* Responsibilities:
|
|
* - Process user message submissions
|
|
* - Detect and handle global commands (like /new)
|
|
* - Handle pending ask responses
|
|
* - Start new tasks or continue existing ones
|
|
* - Handle Y/N approval responses
|
|
*/
|
|
export function useTaskSubmit({
|
|
sendToExtension,
|
|
runTask,
|
|
seenMessageIds,
|
|
firstTextMessageSkipped,
|
|
}: UseTaskSubmitOptions): UseTaskSubmitReturn {
|
|
const {
|
|
pendingAsk,
|
|
hasStartedTask,
|
|
isComplete,
|
|
addMessage,
|
|
setPendingAsk,
|
|
setHasStartedTask,
|
|
setLoading,
|
|
setComplete,
|
|
setError,
|
|
} = useCLIStore()
|
|
|
|
const { setShowCustomInput, setIsTransitioningToCustomInput } = useUIStateStore()
|
|
|
|
/**
|
|
* Handle user text submission (from input or followup question)
|
|
*/
|
|
const handleSubmit = useCallback(
|
|
async (text: string) => {
|
|
if (!sendToExtension || !text.trim()) {
|
|
return
|
|
}
|
|
|
|
const trimmedText = text.trim()
|
|
|
|
if (trimmedText === "__CUSTOM__") {
|
|
return
|
|
}
|
|
|
|
// Check for CLI global action commands (e.g., /new)
|
|
if (trimmedText.startsWith("/")) {
|
|
const commandMatch = trimmedText.match(/^\/(\w+)(?:\s|$)/)
|
|
|
|
if (commandMatch && commandMatch[1]) {
|
|
const globalCommand = getGlobalCommand(commandMatch[1])
|
|
|
|
if (globalCommand?.action === "clearTask") {
|
|
// Reset CLI state and send clearTask to extension.
|
|
useCLIStore.getState().reset()
|
|
|
|
// Reset component-level refs to avoid stale message tracking.
|
|
seenMessageIds.current.clear()
|
|
firstTextMessageSkipped.current = false
|
|
sendToExtension({ type: "clearTask" })
|
|
|
|
// Re-request state, commands and modes since reset() cleared them.
|
|
sendToExtension({ type: "requestCommands" })
|
|
sendToExtension({ type: "requestModes" })
|
|
return
|
|
}
|
|
}
|
|
}
|
|
|
|
if (pendingAsk) {
|
|
addMessage({ id: randomUUID(), role: "user", content: trimmedText })
|
|
|
|
sendToExtension({
|
|
type: "askResponse",
|
|
askResponse: "messageResponse",
|
|
text: trimmedText,
|
|
})
|
|
|
|
setPendingAsk(null)
|
|
setShowCustomInput(false)
|
|
setIsTransitioningToCustomInput(false)
|
|
setLoading(true)
|
|
} else if (!hasStartedTask) {
|
|
setHasStartedTask(true)
|
|
setLoading(true)
|
|
addMessage({ id: randomUUID(), role: "user", content: trimmedText })
|
|
|
|
try {
|
|
if (runTask) {
|
|
await runTask(trimmedText)
|
|
}
|
|
} catch (err) {
|
|
setError(err instanceof Error ? err.message : String(err))
|
|
setLoading(false)
|
|
}
|
|
} else {
|
|
if (isComplete) {
|
|
setComplete(false)
|
|
}
|
|
|
|
setLoading(true)
|
|
addMessage({ id: randomUUID(), role: "user", content: trimmedText })
|
|
|
|
sendToExtension({
|
|
type: "askResponse",
|
|
askResponse: "messageResponse",
|
|
text: trimmedText,
|
|
})
|
|
}
|
|
},
|
|
[
|
|
sendToExtension,
|
|
runTask,
|
|
pendingAsk,
|
|
hasStartedTask,
|
|
isComplete,
|
|
addMessage,
|
|
setPendingAsk,
|
|
setHasStartedTask,
|
|
setLoading,
|
|
setComplete,
|
|
setError,
|
|
setShowCustomInput,
|
|
setIsTransitioningToCustomInput,
|
|
seenMessageIds,
|
|
firstTextMessageSkipped,
|
|
],
|
|
)
|
|
|
|
/**
|
|
* Handle approval (Y key)
|
|
*/
|
|
const handleApprove = useCallback(() => {
|
|
if (!sendToExtension) {
|
|
return
|
|
}
|
|
|
|
sendToExtension({ type: "askResponse", askResponse: "yesButtonClicked" })
|
|
setPendingAsk(null)
|
|
setLoading(true)
|
|
}, [sendToExtension, setPendingAsk, setLoading])
|
|
|
|
/**
|
|
* Handle rejection (N key)
|
|
*/
|
|
const handleReject = useCallback(() => {
|
|
if (!sendToExtension) {
|
|
return
|
|
}
|
|
|
|
sendToExtension({ type: "askResponse", askResponse: "noButtonClicked" })
|
|
setPendingAsk(null)
|
|
setLoading(true)
|
|
}, [sendToExtension, setPendingAsk, setLoading])
|
|
|
|
return {
|
|
handleSubmit,
|
|
handleApprove,
|
|
handleReject,
|
|
}
|
|
}
|