diff --git a/frontend/src/components/workspace/input-box.tsx b/frontend/src/components/workspace/input-box.tsx index 7d9607aa..92b377be 100644 --- a/frontend/src/components/workspace/input-box.tsx +++ b/frontend/src/components/workspace/input-box.tsx @@ -59,7 +59,6 @@ import { import { useI18n } from "@/core/i18n/hooks"; import { useModels } from "@/core/models/hooks"; import type { AgentThreadContext } from "@/core/threads"; -import { useIframeSkill } from "@/hooks/use-iframe-skill"; import { cn } from "@/lib/utils"; import { @@ -82,6 +81,79 @@ import { import { ModeHoverGuide } from "./mode-hover-guide"; import { Tooltip } from "./tooltip"; +const POST_MESSAGE_TYPES = { + SELECT_SKILL: "selectSkill", + OPEN_SKILL_DIALOG: "openSkillDialog", +} as const; + +const RECEIVE_MESSAGE_TYPES = { + SELECTED_SKILL: "selectedSkill", +} as const; + +type IframeSelectedSkillMessage = { + type: typeof RECEIVE_MESSAGE_TYPES.SELECTED_SKILL; + id: string | number; + title: string; +}; + +type IframeSkillData = { + skill_id: string; + title: string; +}; + +function sendIframeMessageToParent(message: unknown): void { + if (window.parent !== window) { + window.parent.postMessage(message, "*"); + } +} + +function useEmbeddedIframeSkill() { + const searchParams = useSearchParams(); + const skillIdFromQuery = searchParams.get("skill_id"); + const titleFromQuery = searchParams.get("title"); + const [selectedSkill, setSelectedSkill] = useState( + null, + ); + + useEffect(() => { + if (skillIdFromQuery && titleFromQuery) { + setSelectedSkill({ skill_id: skillIdFromQuery, title: titleFromQuery }); + } + }, [skillIdFromQuery, titleFromQuery]); + + useEffect(() => { + const handleMessage = (event: MessageEvent) => { + if (event.data?.type === RECEIVE_MESSAGE_TYPES.SELECTED_SKILL) { + const { id, title } = event.data as IframeSelectedSkillMessage; + setSelectedSkill({ skill_id: String(id), title }); + } + }; + window.addEventListener("message", handleMessage); + return () => window.removeEventListener("message", handleMessage); + }, []); + + const sendSelectSkill = useCallback((skill_id: string) => { + sendIframeMessageToParent({ type: POST_MESSAGE_TYPES.SELECT_SKILL, skill_id }); + }, []); + + const openSkillDialog = useCallback(() => { + sendIframeMessageToParent({ + type: POST_MESSAGE_TYPES.OPEN_SKILL_DIALOG, + openSkillDialog: true, + }); + }, []); + + const clearSkill = useCallback(() => { + setSelectedSkill(null); + sendIframeMessageToParent({ + type: POST_MESSAGE_TYPES.SELECT_SKILL, + skill_id: "0", + }); + }, []); + + return { selectedSkill, sendSelectSkill, openSkillDialog, clearSkill }; +} + export function InputBox({ className, disabled, @@ -125,7 +197,7 @@ export function InputBox({ }) { const { t } = useI18n(); const searchParams = useSearchParams(); - const iframeSkill = useIframeSkill(); + const iframeSkill = useEmbeddedIframeSkill(); const params = useParams(); const threadId = threadIdProp ?? params?.thread_id;