import { useCallback } from 'react'; import { ChatPanelWrapper, ChatHeader } from 'officerdev'; import { useOpenSeoChanged } from './channel'; /** * A chat beside the app. * * ── Why this plugin has one at all ── * * `fofos-admin`'s layout note draws the line: a chat panel is worth a third of the screen on the day the * plugin ships a `skills/` directory, and not before. This ships one — and more than that, OpenSEO's own * MCP server is the point of the integration. The conversation here is where that gets used. * * ── The panel is ours; the chat inside it is the platform's ── * * `PluginScreen` pins the layout to this plugin's own panel keys, so naming `officerdev/chat` in * layout.ts renders the fallback instead — proxy-manager learned that by getting two of the same panel. * `ChatPanelWrapper` brings the session persistence, the agent bar and resume-the-newest with it. */ const CHAT_CONTEXT = { context: 'plugin', contextId: 'openseo' } as const; export const ChatPanel = ({ panelId }: { panelId: string }) => { const [, changed] = useOpenSeoChanged(); /* A turn that ran tools may have changed something the app is showing — a project created, a crawl started, a keyword list added. Gated on `hadToolCalls` because a turn that only talked changed nothing, and re-reading after every sentence puts a request behind every reply. */ const onTurnComplete = useCallback((hadToolCalls: boolean) => { if (hadToolCalls) changed(); }, [changed]); return (
); }; export const ChatPanelHeader = ({ panelId }: { panelId: string }) => ( );