diff --git a/frontend/src/app/pages/AgentChat/OpenSwarmThread/OpenSwarmThread.tsx b/frontend/src/app/pages/AgentChat/OpenSwarmThread/OpenSwarmThread.tsx index 52914051..e5e750b7 100644 --- a/frontend/src/app/pages/AgentChat/OpenSwarmThread/OpenSwarmThread.tsx +++ b/frontend/src/app/pages/AgentChat/OpenSwarmThread/OpenSwarmThread.tsx @@ -6,7 +6,7 @@ import { AuiIf, } from '@assistant-ui/react'; import { ArrowDownIcon } from 'lucide-react'; -import { Button } from '@/app/pages/AgentChat/_shared/button'; +import { Button } from '@/app/pages/AgentChat/_shared/Button'; import { TooltipProvider } from './components/tooltip'; import { TooltipIconButton } from './components/TooltipIconButton'; import { UserMessage } from './components/UserMessage/UserMessage'; diff --git a/frontend/src/app/pages/AgentChat/OpenSwarmThread/components/TooltipIconButton.tsx b/frontend/src/app/pages/AgentChat/OpenSwarmThread/components/TooltipIconButton.tsx index ce4075e6..7993c599 100644 --- a/frontend/src/app/pages/AgentChat/OpenSwarmThread/components/TooltipIconButton.tsx +++ b/frontend/src/app/pages/AgentChat/OpenSwarmThread/components/TooltipIconButton.tsx @@ -8,7 +8,7 @@ import { TooltipContent, TooltipTrigger, } from "./tooltip"; -import { Button } from "@/app/pages/AgentChat/_shared/button"; +import { Button } from "@/app/pages/AgentChat/_shared/Button"; import { cn } from "@/lib/utils"; type TooltipIconButtonProps = ComponentPropsWithRef & { diff --git a/frontend/src/app/pages/AgentChat/OpenSwarmThread/components/UserMessage/UserMessage.tsx b/frontend/src/app/pages/AgentChat/OpenSwarmThread/components/UserMessage/UserMessage.tsx index 5ceab5b1..fb28cf55 100644 --- a/frontend/src/app/pages/AgentChat/OpenSwarmThread/components/UserMessage/UserMessage.tsx +++ b/frontend/src/app/pages/AgentChat/OpenSwarmThread/components/UserMessage/UserMessage.tsx @@ -81,7 +81,7 @@ function useOriginalMessage(): AgentMessage | undefined { try { messageId = aui.message().getState().id; } catch { - return undefined; + // intentionally empty — messageId stays undefined } return useAppSelector((state) => { diff --git a/frontend/src/app/pages/AgentChat/OpenSwarmThread/components/UserMessage/UserMessageAttachments.tsx b/frontend/src/app/pages/AgentChat/OpenSwarmThread/components/UserMessage/UserMessageAttachments.tsx index db8af860..8789f68a 100644 --- a/frontend/src/app/pages/AgentChat/OpenSwarmThread/components/UserMessage/UserMessageAttachments.tsx +++ b/frontend/src/app/pages/AgentChat/OpenSwarmThread/components/UserMessage/UserMessageAttachments.tsx @@ -29,19 +29,23 @@ const useFileSrc = (file: File | undefined) => { useEffect(() => { if (!file) { - setSrc(undefined); return; } + let revoked = false; const objectUrl = URL.createObjectURL(file); - setSrc(objectUrl); + queueMicrotask(() => { + if (!revoked) setSrc(objectUrl); + }); return () => { + revoked = true; URL.revokeObjectURL(objectUrl); + queueMicrotask(() => setSrc(undefined)); }; }, [file]); - return src; + return file ? src : undefined; }; const useAttachmentSrc = () => { diff --git a/frontend/src/app/pages/AgentChat/toolkit/approvalToolkit/components/ActionButtons/ActionButtons.tsx b/frontend/src/app/pages/AgentChat/toolkit/approvalToolkit/components/ActionButtons/ActionButtons.tsx index 806b8d79..3cf2bdc1 100644 --- a/frontend/src/app/pages/AgentChat/toolkit/approvalToolkit/components/ActionButtons/ActionButtons.tsx +++ b/frontend/src/app/pages/AgentChat/toolkit/approvalToolkit/components/ActionButtons/ActionButtons.tsx @@ -3,7 +3,7 @@ import type { Action } from "../../utils/types"; import { useActionButtons } from "./useActionButtons"; import { cn } from "@/lib/utils"; -import { Button } from "@/app/pages/AgentChat/_shared/button"; +import { Button } from "@/app/pages/AgentChat/_shared/Button"; interface ActionButtonsProps { actions: Action[]; diff --git a/frontend/src/app/pages/AgentChat/toolkit/approvalToolkit/components/ToolQuestion/OptionList/OptionList.tsx b/frontend/src/app/pages/AgentChat/toolkit/approvalToolkit/components/ToolQuestion/OptionList/OptionList.tsx index b92b36fb..7687299e 100644 --- a/frontend/src/app/pages/AgentChat/toolkit/approvalToolkit/components/ToolQuestion/OptionList/OptionList.tsx +++ b/frontend/src/app/pages/AgentChat/toolkit/approvalToolkit/components/ToolQuestion/OptionList/OptionList.tsx @@ -4,7 +4,6 @@ import { useMemo, useState, useCallback, - useEffect, useRef, Fragment, } from "react"; @@ -229,7 +228,7 @@ export function OptionList({ onBeforeAction, className, }: OptionListProps) { - if (process.env["NODE_ENV"] !== "production") { + if (import.meta.env.DEV) { if (value !== undefined && defaultValue !== undefined) { console.warn( "[OptionList] Both `value` (controlled) and `defaultValue` (uncontrolled) were provided. `defaultValue` is ignored when `value` is set.", @@ -297,7 +296,7 @@ export function OptionList({ ]); const optionRefs = useRef>([]); - const [activeIndex, setActiveIndex] = useState(() => { + const [rawActiveIndex, setActiveIndex] = useState(() => { const firstSelected = optionStates.findIndex( (s) => s.isSelected && !s.isDisabled, ); @@ -306,20 +305,18 @@ export function OptionList({ return firstEnabled >= 0 ? firstEnabled : 0; }); - useEffect(() => { - if (optionStates.length === 0) return; - setActiveIndex((prev) => { - if ( - prev < 0 || - prev >= optionStates.length || - optionStates[prev].isDisabled - ) { - const firstEnabled = optionStates.findIndex((s) => !s.isDisabled); - return firstEnabled >= 0 ? firstEnabled : 0; - } - return prev; - }); - }, [optionStates]); + const activeIndex = useMemo(() => { + if ( + optionStates.length === 0 || + (rawActiveIndex >= 0 && + rawActiveIndex < optionStates.length && + !optionStates[rawActiveIndex].isDisabled) + ) { + return rawActiveIndex; + } + const firstEnabled = optionStates.findIndex((s) => !s.isDisabled); + return firstEnabled >= 0 ? firstEnabled : 0; + }, [rawActiveIndex, optionStates]); const updateSelection = useCallback( (next: Set) => { diff --git a/frontend/src/app/pages/AgentChat/toolkit/approvalToolkit/components/ToolQuestion/OptionList/_adapter.tsx b/frontend/src/app/pages/AgentChat/toolkit/approvalToolkit/components/ToolQuestion/OptionList/_adapter.tsx index 04631370..db2afbbc 100644 --- a/frontend/src/app/pages/AgentChat/toolkit/approvalToolkit/components/ToolQuestion/OptionList/_adapter.tsx +++ b/frontend/src/app/pages/AgentChat/toolkit/approvalToolkit/components/ToolQuestion/OptionList/_adapter.tsx @@ -1,3 +1,3 @@ export { cn } from "@/lib/utils"; -export { Button } from "@/app/pages/AgentChat/_shared/button"; +export { Button } from "@/app/pages/AgentChat/_shared/Button"; export { Separator } from "../../separator"; diff --git a/frontend/src/app/pages/AgentChat/toolkit/approvalToolkit/components/ToolQuestion/OptionList/utils/actions-config.ts b/frontend/src/app/pages/AgentChat/toolkit/approvalToolkit/components/ToolQuestion/OptionList/utils/actions-config.ts index a1b0aa55..ad211826 100644 --- a/frontend/src/app/pages/AgentChat/toolkit/approvalToolkit/components/ToolQuestion/OptionList/utils/actions-config.ts +++ b/frontend/src/app/pages/AgentChat/toolkit/approvalToolkit/components/ToolQuestion/OptionList/utils/actions-config.ts @@ -1,4 +1,4 @@ -import type { Action, ActionsConfig } from "./schema"; +import type { Action, ActionsConfig } from "@/app/pages/AgentChat/toolkit/approvalToolkit/utils/types"; export type ActionsProp = ActionsConfig | Action[]; diff --git a/frontend/src/app/pages/AgentChat/toolkit/approvalToolkit/components/ToolQuestion/QuestionFlow/_adapter.tsx b/frontend/src/app/pages/AgentChat/toolkit/approvalToolkit/components/ToolQuestion/QuestionFlow/_adapter.tsx index 04631370..db2afbbc 100644 --- a/frontend/src/app/pages/AgentChat/toolkit/approvalToolkit/components/ToolQuestion/QuestionFlow/_adapter.tsx +++ b/frontend/src/app/pages/AgentChat/toolkit/approvalToolkit/components/ToolQuestion/QuestionFlow/_adapter.tsx @@ -1,3 +1,3 @@ export { cn } from "@/lib/utils"; -export { Button } from "@/app/pages/AgentChat/_shared/button"; +export { Button } from "@/app/pages/AgentChat/_shared/Button"; export { Separator } from "../../separator"; diff --git a/frontend/src/app/pages/AgentChat/toolkit/nativeToolkit/components/CodeBlock/_adapter.tsx b/frontend/src/app/pages/AgentChat/toolkit/nativeToolkit/components/CodeBlock/_adapter.tsx index a4cf635f..ab29c2a8 100644 --- a/frontend/src/app/pages/AgentChat/toolkit/nativeToolkit/components/CodeBlock/_adapter.tsx +++ b/frontend/src/app/pages/AgentChat/toolkit/nativeToolkit/components/CodeBlock/_adapter.tsx @@ -1,3 +1,3 @@ export { cn } from "@/lib/utils"; -export { Button } from "@/app/pages/AgentChat/_shared/button"; +export { Button } from "@/app/pages/AgentChat/_shared/Button"; export { Collapsible, CollapsibleTrigger } from "@/app/pages/AgentChat/_shared/collapsible"; diff --git a/frontend/src/app/pages/AgentChat/toolkit/nativeToolkit/components/CodeBlock/components/CodeBlockRoot/helpers.tsx b/frontend/src/app/pages/AgentChat/toolkit/nativeToolkit/components/CodeBlock/components/CodeBlockRoot/helpers.tsx index 7d7ebdbd..aeb844be 100644 --- a/frontend/src/app/pages/AgentChat/toolkit/nativeToolkit/components/CodeBlock/components/CodeBlockRoot/helpers.tsx +++ b/frontend/src/app/pages/AgentChat/toolkit/nativeToolkit/components/CodeBlock/components/CodeBlockRoot/helpers.tsx @@ -1,9 +1,5 @@ "use client"; -import { - useState, - useEffect, -} from "react"; import { createHighlighter, type Highlighter } from "shiki/bundle/web"; import { createJavaScriptRegexEngine } from "shiki/engine/javascript"; import pierreDarkTheme from "../../../_shared/pierre-dark-theme.js"; @@ -57,52 +53,4 @@ export function setCachedHtml(cacheKey: string, html: string): void { } htmlCache.set(cacheKey, html); -} - -export function getSystemTheme(): "light" | "dark" { - if (typeof window === "undefined") return "light"; - return window.matchMedia?.("(prefers-color-scheme: dark)").matches - ? "dark" - : "light"; -} - -export function getDocumentTheme(): "light" | "dark" | null { - if (typeof document === "undefined") return null; - const root = document.documentElement; - const dataTheme = root.getAttribute("data-theme")?.toLowerCase(); - if (dataTheme === "dark") return "dark"; - if (dataTheme === "light") return "light"; - if (root.classList.contains("dark")) return "dark"; - if (root.classList.contains("light")) return "light"; - return null; -} - -export function useResolvedTheme(): "light" | "dark" { - const [theme, setTheme] = useState<"light" | "dark">(() => { - return getDocumentTheme() ?? getSystemTheme(); - }); - - useEffect(() => { - if (typeof window === "undefined" || typeof document === "undefined") { - return; - } - - const update = () => setTheme(getDocumentTheme() ?? getSystemTheme()); - - const mql = window.matchMedia?.("(prefers-color-scheme: dark)"); - mql?.addEventListener("change", update); - - const observer = new MutationObserver(update); - observer.observe(document.documentElement, { - attributes: true, - attributeFilter: ["class", "data-theme"], - }); - - return () => { - mql?.removeEventListener("change", update); - observer.disconnect(); - }; - }, []); - - return theme; } \ No newline at end of file diff --git a/frontend/src/app/pages/AgentChat/toolkit/nativeToolkit/components/CodeDiff/CodeDiff.tsx b/frontend/src/app/pages/AgentChat/toolkit/nativeToolkit/components/CodeDiff/CodeDiff.tsx index 8e2427fb..fbf7c4cc 100644 --- a/frontend/src/app/pages/AgentChat/toolkit/nativeToolkit/components/CodeDiff/CodeDiff.tsx +++ b/frontend/src/app/pages/AgentChat/toolkit/nativeToolkit/components/CodeDiff/CodeDiff.tsx @@ -6,7 +6,7 @@ import { useEffect, useMemo, createContext, - use, + useContext, type ReactNode, } from "react"; import { @@ -137,7 +137,7 @@ type CodeDiffSharedState = { const CodeDiffContext = createContext(null); function useCodeDiff(): CodeDiffSharedState { - const context = use(CodeDiffContext); + const context = useContext(CodeDiffContext); if (!context) { throw new Error( "CodeDiff subcomponents must be used within .", diff --git a/frontend/src/app/pages/AgentChat/toolkit/nativeToolkit/components/CodeDiff/_adapter.tsx b/frontend/src/app/pages/AgentChat/toolkit/nativeToolkit/components/CodeDiff/_adapter.tsx index a4cf635f..ab29c2a8 100644 --- a/frontend/src/app/pages/AgentChat/toolkit/nativeToolkit/components/CodeDiff/_adapter.tsx +++ b/frontend/src/app/pages/AgentChat/toolkit/nativeToolkit/components/CodeDiff/_adapter.tsx @@ -1,3 +1,3 @@ export { cn } from "@/lib/utils"; -export { Button } from "@/app/pages/AgentChat/_shared/button"; +export { Button } from "@/app/pages/AgentChat/_shared/Button"; export { Collapsible, CollapsibleTrigger } from "@/app/pages/AgentChat/_shared/collapsible"; diff --git a/frontend/src/app/pages/AgentChat/toolkit/nativeToolkit/components/Terminal/_adapter.tsx b/frontend/src/app/pages/AgentChat/toolkit/nativeToolkit/components/Terminal/_adapter.tsx index a4cf635f..ab29c2a8 100644 --- a/frontend/src/app/pages/AgentChat/toolkit/nativeToolkit/components/Terminal/_adapter.tsx +++ b/frontend/src/app/pages/AgentChat/toolkit/nativeToolkit/components/Terminal/_adapter.tsx @@ -1,3 +1,3 @@ export { cn } from "@/lib/utils"; -export { Button } from "@/app/pages/AgentChat/_shared/button"; +export { Button } from "@/app/pages/AgentChat/_shared/Button"; export { Collapsible, CollapsibleTrigger } from "@/app/pages/AgentChat/_shared/collapsible"; diff --git a/frontend/src/app/pages/_shared/element_selection/ElementSelectionProvider.tsx b/frontend/src/app/pages/_shared/element_selection/ElementSelectionProvider.tsx index 7b402230..97e74153 100644 --- a/frontend/src/app/pages/_shared/element_selection/ElementSelectionProvider.tsx +++ b/frontend/src/app/pages/_shared/element_selection/ElementSelectionProvider.tsx @@ -1,4 +1,4 @@ -import React, { useState, useRef, useCallback, useMemo } from 'react'; +import React, { useState, useRef, useCallback, useMemo, useEffect } from 'react'; import { type SelectedElement } from './SelectedElement'; import { ElementSelectionContext } from './useElementSelection'; @@ -10,7 +10,9 @@ export const ElementSelectionProvider: React.FC<{ children: React.ReactNode }> = const iframeRef = useRef(null); const activeOwnerIdRef = useRef(activeOwnerId); - activeOwnerIdRef.current = activeOwnerId; + useEffect(() => { + activeOwnerIdRef.current = activeOwnerId; + }, [activeOwnerId]); const selectedElements = useMemo( () => (activeOwnerId ? elementsByOwner[activeOwnerId] ?? [] : []), diff --git a/frontend/src/vite-env.d.ts b/frontend/src/vite-env.d.ts new file mode 100644 index 00000000..11f02fe2 --- /dev/null +++ b/frontend/src/vite-env.d.ts @@ -0,0 +1 @@ +///