Add the assistant: a chat that drives the MCP tools in-process
Docs / docs (push) Successful in 42s
Playwright Tests / test-playwright (1, 2) (push) Failing after 2m42s
Playwright Tests / test-playwright (2, 2) (push) Failing after 10s
pre-commit / pre-commit (push) Failing after 2m33s
Test Backend / test-backend (push) Failing after 2m48s
Compose Smoke Test / test-compose (push) Failing after 9s
Playwright Tests / merge-reports (push) Failing after 2m17s
Docs / docs (push) Successful in 42s
Playwright Tests / test-playwright (1, 2) (push) Failing after 2m42s
Playwright Tests / test-playwright (2, 2) (push) Failing after 10s
pre-commit / pre-commit (push) Failing after 2m33s
Test Backend / test-backend (push) Failing after 2m48s
Compose Smoke Test / test-compose (push) Failing after 9s
Playwright Tests / merge-reports (push) Failing after 2m17s
A provider set under Settings (OpenAI-compatible; key encrypted in flow-data/ai.json) turns on an Assistant panel in the sidebar. Each turn runs the FastMCP tools in-process as the person chatting, streams the rounds over SSE and keeps one transcript per user. The panel floats on any screen and shares the editor's lane: a settings panel keeps the top half, the chat the bottom. The MCP client is now built once, for the endpoint and the chat. Co-Authored-By: Claude Fable 5.1 <noreply@anthropic.com>
This commit is contained in:
@@ -2,7 +2,7 @@ import { Info, X } from "lucide-react"
|
||||
import { AnimatePresence, motion } from "motion/react"
|
||||
import type { ReactNode } from "react"
|
||||
import { useEffect, useState } from "react"
|
||||
|
||||
import { chatStore, useChat } from "@/components/Chat/chatStore"
|
||||
import { Button } from "@/components/ui/button"
|
||||
import { Input } from "@/components/ui/input"
|
||||
import { Label } from "@/components/ui/label"
|
||||
@@ -180,6 +180,8 @@ export function PanelTitle({
|
||||
* for that.
|
||||
*
|
||||
* Node settings and flow settings share it, so the two read as one surface.
|
||||
* The assistant shares it too, and the lane: while it is open, a settings
|
||||
* panel keeps the top half and the chat takes the bottom.
|
||||
*/
|
||||
export function SidePanel({
|
||||
open,
|
||||
@@ -187,6 +189,8 @@ export function SidePanel({
|
||||
testId,
|
||||
bodyKey,
|
||||
expanded = false,
|
||||
fixed = false,
|
||||
stacked,
|
||||
header,
|
||||
footer,
|
||||
children,
|
||||
@@ -200,12 +204,26 @@ export function SidePanel({
|
||||
bodyKey: string
|
||||
/** Take the width a code editor needs, still floating over the canvas. */
|
||||
expanded?: boolean
|
||||
/** Pinned to the viewport rather than the canvas: a panel on any screen. */
|
||||
fixed?: boolean
|
||||
/**
|
||||
* Which half of the lane to keep. Left unset, the panel counts itself as
|
||||
* open and keeps the top whenever the assistant is open beside it.
|
||||
*/
|
||||
stacked?: "top" | "bottom" | false
|
||||
header: ReactNode
|
||||
footer?: ReactNode
|
||||
children: ReactNode
|
||||
onClose: () => void
|
||||
}) {
|
||||
const isMobile = useIsMobile()
|
||||
const chat = useChat()
|
||||
const shares = stacked === undefined
|
||||
useEffect(() => {
|
||||
if (!shares || !open || isMobile) return
|
||||
return chatStore.registerPanel()
|
||||
}, [shares, open, isMobile])
|
||||
const half = shares ? (chat.open ? "top" : false) : stacked
|
||||
|
||||
useEffect(() => {
|
||||
if (!open) return
|
||||
@@ -284,12 +302,19 @@ export function SidePanel({
|
||||
data-testid={testId}
|
||||
data-expanded={expanded || undefined}
|
||||
className={cn(
|
||||
"pointer-events-auto absolute z-20 flex flex-col overflow-hidden rounded-lg border border-border bg-card/80 shadow-e2 backdrop-blur-md",
|
||||
"pointer-events-auto z-20 flex flex-col overflow-hidden rounded-lg border border-border bg-card/80 shadow-e2 backdrop-blur-md",
|
||||
fixed ? "fixed" : "absolute",
|
||||
expanded
|
||||
? // Still a floating surface, given the whole inset: the toolbar
|
||||
// and the flow-name box translate off screen while it is open.
|
||||
"inset-4"
|
||||
: "inset-y-4 right-4 w-[400px]",
|
||||
: "right-4 w-[400px]",
|
||||
!expanded &&
|
||||
(half === "top"
|
||||
? "top-4 bottom-[calc(50%+0.5rem)]"
|
||||
: half === "bottom"
|
||||
? "top-[calc(50%+0.5rem)] bottom-4"
|
||||
: "inset-y-4"),
|
||||
)}
|
||||
>
|
||||
{contents}
|
||||
|
||||
Reference in New Issue
Block a user