diff --git a/apps/fabro-web/app/components/steer-composer.tsx b/apps/fabro-web/app/components/steer-composer.tsx new file mode 100644 index 000000000..b2b613fd6 --- /dev/null +++ b/apps/fabro-web/app/components/steer-composer.tsx @@ -0,0 +1,92 @@ +import { useState, useCallback, useRef, useEffect } from "react"; + +import { useSteerRun } from "../lib/mutations"; + +interface SteerComposerProps { + runId: string; + onClose: () => void; +} + +export function SteerComposer({ runId, onClose }: SteerComposerProps) { + const [text, setText] = useState(""); + const [error, setError] = useState(null); + const textareaRef = useRef(null); + const steerMutation = useSteerRun(runId); + + useEffect(() => { + textareaRef.current?.focus(); + }, []); + + const submit = useCallback( + async (interrupt: boolean) => { + if (!text.trim()) return; + setError(null); + try { + await steerMutation.trigger({ text: text.trim(), interrupt }); + setText(""); + onClose(); + } catch (err: unknown) { + const message = + err instanceof Error ? err.message : "Failed to deliver steer."; + setError(message); + } + }, + [text, steerMutation, onClose], + ); + + const handleKeyDown = useCallback( + (e: React.KeyboardEvent) => { + if (e.key === "Enter" && !e.shiftKey) { + e.preventDefault(); + submit(false); + } + }, + [submit], + ); + + return ( +
+
+
+
+
+

Steer agent

+ +
+