"use client"; import { ModelSelector } from "@/components/assistant-ui/model-selector"; import { AssistantComposer } from "@/components/docs/assistant/composer"; import { AssistantActionBar } from "@/components/docs/assistant/assistant-action-bar"; import { XuluxMarkdownText } from "./XuluxMarkdownText"; import { AssistantFooter } from "@/components/docs/assistant/footer"; import { UserMessage } from "@/components/docs/assistant/messages"; import { useAssistantPanel } from "@/components/docs/assistant/context"; import { Reasoning } from "@/components/assistant-ui/reasoning"; import { DotMatrix } from "@/components/assistant-ui/dot-matrix"; import { analytics } from "@/lib/analytics"; import { getComposerMessageMetrics } from "@/lib/assistant-analytics-helpers"; import { useXuluxAnalytics, withXuluxContext, } from "@/lib/xulux/analytics-context"; import { getXuluxThreadWelcome } from "@/lib/xulux/thread-welcome"; import { AuiIf, ErrorPrimitive, MessagePrimitive, ThreadPrimitive, useAui, useAuiState, } from "@assistant-ui/react"; import Image from "next/image"; import { type ReactNode, useEffect, useMemo, useRef, useState } from "react"; import { XuluxPoweredBy } from "../XuluxPoweredBy"; import { useXuluxTemplateContext } from "./XuluxTemplateContext"; import { XuluxToolCall } from "./XuluxToolCall"; import { XuluxUsageLimitBanner } from "./XuluxUsageLimitBanner"; const XULUX_CONTEXT_WINDOW = 400_000; const XULUX_DEFAULT_MODEL_ID = "gpt-5.4-mini"; const XULUX_MODELS = [ { id: "gpt-5.4-mini", name: "GPT-5.4 Mini", modelName: "gpt-5.4-mini", }, ] as const; type XuluxModelId = (typeof XULUX_MODELS)[number]["id"]; export function XuluxThread({ onNewThread, }: { onNewThread: () => void; }): ReactNode { const template = useXuluxTemplateContext(); const welcome = useMemo(() => getXuluxThreadWelcome(template), [template]); return ( s.thread.isEmpty}>
{({ message }) => { if (message.role === "user") return ; if (message.role === "assistant") return ; return null; }}
} />
); } function XuluxPendingMessageHandler(): ReactNode { const { pendingMessage, clearPendingMessage } = useAssistantPanel(); const aui = useAui(); const isRunning = useAuiState((s) => s.thread.isRunning); const processedRef = useRef(null); useEffect(() => { if (!pendingMessage || processedRef.current === pendingMessage) return; if (isRunning) return; processedRef.current = pendingMessage; clearPendingMessage(); aui.thread().append(pendingMessage); }, [pendingMessage, clearPendingMessage, aui, isRunning]); return null; } function XuluxComposer({ onNewThread, placeholder, }: { onNewThread: () => void; placeholder: string; }): ReactNode { const aui = useAui(); const analyticsCtx = useXuluxAnalytics(); return (
} onSubmit={() => { const metrics = getComposerMessageMetrics(aui.composer().getState()); if (!metrics) return; analytics.xulux.promptSubmitted( withXuluxContext(analyticsCtx, { source: "composer", message_length: metrics.messageLength, }), ); }} />
); } function XuluxModelSelector(): ReactNode { const aui = useAui(); const [modelValue, setModelValue] = useState( XULUX_DEFAULT_MODEL_ID, ); const selectedModel = XULUX_MODELS.find((model) => model.id === modelValue) ?? XULUX_MODELS[0]; const modelOptions = useMemo( () => XULUX_MODELS.map((model) => ({ id: model.id, name: model.name, icon: ( {model.name} ), })), [], ); useEffect(() => { return aui.modelContext().register({ getModelContext: () => ({ config: { modelName: selectedModel.modelName, }, }), }); }, [aui, selectedModel]); return ( { if (isXuluxModelId(value)) setModelValue(value); }} > ); } function XuluxAssistantMessage(): ReactNode { return (
{({ part }) => { if (part.type === "text") { return (
); } if (part.type === "reasoning") { return (
); } if (part.type === "tool-call") { return (
{part.toolUI ?? }
); } return null; }}
s.thread.isRunning && s.message.content.length === 0 } >
Connecting
); } function XuluxWelcome({ welcome, templateTitle, }: { welcome: ReturnType; templateTitle?: string | undefined; }): ReactNode { return (
{templateTitle ? ( {templateTitle} ) : null}

{welcome.headline}

{welcome.body}

); } function isXuluxModelId(value: string): value is XuluxModelId { return XULUX_MODELS.some((model) => model.id === value); }