diff --git a/src/components/artifacts/ArtifactRenderer.tsx b/src/components/artifacts/ArtifactRenderer.tsx index 5d4e5e87..4f123746 100644 --- a/src/components/artifacts/ArtifactRenderer.tsx +++ b/src/components/artifacts/ArtifactRenderer.tsx @@ -1,3 +1,5 @@ +import { useGraphContext } from "@/contexts/GraphContext"; +import { getArtifactContent } from "@/contexts/utils"; import { convertToOpenAIFormat } from "@/lib/convert_messages"; import { cn } from "@/lib/utils"; import { @@ -7,19 +9,17 @@ import { } from "@/types"; import { EditorView } from "@codemirror/view"; import { HumanMessage } from "@langchain/core/messages"; -import { Forward, LoaderCircle, CircleCheck } from "lucide-react"; +import { CircleCheck, Forward, LoaderCircle } from "lucide-react"; import React, { useCallback, useEffect, useRef, useState } from "react"; import { v4 as uuidv4 } from "uuid"; import { ReflectionsDialog } from "../reflections-dialog/ReflectionsDialog"; import { TooltipIconButton } from "../ui/assistant-ui/tooltip-icon-button"; import { ActionsToolbar, CodeToolBar } from "./actions_toolbar"; -import { CodeRenderer } from "./CodeRenderer"; -import { TextRenderer } from "./TextRenderer"; import { CustomQuickActions } from "./actions_toolbar/custom"; -import { getArtifactContent } from "@/contexts/utils"; import { ArtifactLoading } from "./ArtifactLoading"; +import { CodeRenderer } from "./CodeRenderer"; import { AskOpenCanvas } from "./components/AskOpenCanvas"; -import { useGraphContext } from "@/contexts/GraphContext"; +import { TextRenderer } from "./TextRenderer"; export interface ArtifactRendererProps { isEditing: boolean; @@ -412,6 +412,7 @@ function ArtifactRendererComponent(props: ArtifactRendererProps) { )} {currentArtifactContent.type === "text" ? ( ) : null} {currentArtifactContent.type === "code" ? ( Promise; + setMessages: React.Dispatch>; + handleClose: () => void; language: ProgrammingLanguageOptions; } @@ -48,6 +51,10 @@ export function PortToLanguageOptions(props: PortToLanguageOptionsProps) { } props.handleClose(); + props.setMessages((prevMessages) => [ + ...prevMessages, + new HumanMessage(`Port the code to ${prettifyLanguage(portLanguage)}`), + ]); await streamMessage({ portLanguage, }); diff --git a/src/components/artifacts/actions_toolbar/code/index.tsx b/src/components/artifacts/actions_toolbar/code/index.tsx index db4a075c..a1bd6161 100644 --- a/src/components/artifacts/actions_toolbar/code/index.tsx +++ b/src/components/artifacts/actions_toolbar/code/index.tsx @@ -1,15 +1,17 @@ -import { useEffect, useRef, useState } from "react"; -import { MessageCircleCode, Code, ScrollText, Bug, BookA } from "lucide-react"; -import { cn } from "@/lib/utils"; import { TooltipIconButton } from "@/components/ui/assistant-ui/tooltip-icon-button"; -import { PortToLanguageOptions } from "./PortToLanguage"; -import { ProgrammingLanguageOptions } from "@/types"; import { GraphInput } from "@/contexts/GraphContext"; +import { cn } from "@/lib/utils"; +import { ProgrammingLanguageOptions } from "@/types"; +import { BaseMessage, HumanMessage } from "@langchain/core/messages"; +import { BookA, Bug, Code, MessageCircleCode, ScrollText } from "lucide-react"; +import { useEffect, useRef, useState } from "react"; +import { PortToLanguageOptions } from "./PortToLanguage"; type SharedComponentProps = { handleClose: () => void; streamMessage: (params: GraphInput) => Promise; language: ProgrammingLanguageOptions; + setMessages: React.Dispatch>; }; type ToolbarOption = { @@ -23,6 +25,7 @@ export interface CodeToolbarProps { streamMessage: (params: GraphInput) => Promise; isTextSelected: boolean; language: ProgrammingLanguageOptions; + setMessages: React.Dispatch>; } const toolbarOptions: ToolbarOption[] = [ @@ -55,7 +58,7 @@ const toolbarOptions: ToolbarOption[] = [ ]; export function CodeToolBar(props: CodeToolbarProps) { - const { streamMessage } = props; + const { streamMessage, setMessages } = props; const [isExpanded, setIsExpanded] = useState(false); const [activeOption, setActiveOption] = useState(null); const toolbarRef = useRef(null); @@ -97,6 +100,22 @@ export function CodeToolBar(props: CodeToolbarProps) { setIsExpanded(false); setActiveOption(null); + + const actionMessages = { + addComments: "Add descriptive inline comments to my code", + addLogs: "Insert log statements into my code", + fixBugs: "Fix any potential bugs in my code", + }; + + if (actionMessages[optionId as keyof typeof actionMessages]) { + setMessages((prevMessages) => [ + ...prevMessages, + new HumanMessage( + actionMessages[optionId as keyof typeof actionMessages] + ), + ]); + } + if (optionId === "addComments") { await streamMessage({ addComments: true, diff --git a/src/components/artifacts/actions_toolbar/custom/index.tsx b/src/components/artifacts/actions_toolbar/custom/index.tsx index 6342023b..c011c0aa 100644 --- a/src/components/artifacts/actions_toolbar/custom/index.tsx +++ b/src/components/artifacts/actions_toolbar/custom/index.tsx @@ -1,10 +1,3 @@ -import { - CirclePlus, - WandSparkles, - Trash2, - LoaderCircle, - Pencil, -} from "lucide-react"; import { TooltipIconButton } from "@/components/ui/assistant-ui/tooltip-icon-button"; import { DropdownMenu, @@ -14,21 +7,30 @@ import { DropdownMenuSeparator, DropdownMenuTrigger, } from "@/components/ui/dropdown-menu"; -import { CustomQuickAction } from "@/types"; -import { NewCustomQuickActionDialog } from "./NewCustomQuickActionDialog"; -import { useEffect, useState } from "react"; -import { useStore } from "@/hooks/useStore"; -import { cn } from "@/lib/utils"; -import { useToast } from "@/hooks/use-toast"; import { TighterText } from "@/components/ui/header"; import { GraphInput } from "@/contexts/GraphContext"; +import { useToast } from "@/hooks/use-toast"; +import { useStore } from "@/hooks/useStore"; +import { cn } from "@/lib/utils"; +import { CustomQuickAction } from "@/types"; +import { BaseMessage, HumanMessage } from "@langchain/core/messages"; import { User } from "@supabase/supabase-js"; +import { + CirclePlus, + LoaderCircle, + Pencil, + Trash2, + WandSparkles, +} from "lucide-react"; +import { useEffect, useState } from "react"; +import { NewCustomQuickActionDialog } from "./NewCustomQuickActionDialog"; export interface CustomQuickActionsProps { isTextSelected: boolean; assistantId: string | undefined; user: User | undefined; streamMessage: (params: GraphInput) => Promise; + setMessages: React.Dispatch>; } const DropdownMenuItemWithDelete = ({ @@ -82,7 +84,7 @@ const DropdownMenuItemWithDelete = ({ }; export function CustomQuickActions(props: CustomQuickActionsProps) { - const { user, assistantId, streamMessage } = props; + const { user, assistantId, streamMessage, setMessages } = props; const { getCustomQuickActions, deleteCustomQuickAction, @@ -121,6 +123,19 @@ export function CustomQuickActions(props: CustomQuickActionsProps) { }; const handleQuickActionClick = async (id: string): Promise => { + const selectedAction = customQuickActions?.find( + (action) => action.id === id + ); + + if (selectedAction) { + setMessages((prevMessages) => [ + ...prevMessages, + new HumanMessage( + `Please use my custom quick action "${selectedAction.title}" to update my artifact` + ), + ]); + } + setOpen(false); setIsEditing(false); setIsEditingId(undefined); diff --git a/src/components/artifacts/actions_toolbar/text/LengthOptions.tsx b/src/components/artifacts/actions_toolbar/text/LengthOptions.tsx index 20f887d0..7f51cf47 100644 --- a/src/components/artifacts/actions_toolbar/text/LengthOptions.tsx +++ b/src/components/artifacts/actions_toolbar/text/LengthOptions.tsx @@ -1,18 +1,20 @@ -import { cn } from "@/lib/utils"; -import { useState } from "react"; -import { ArtifactLengthOptions } from "@/types"; +import { Slider } from "@/components/ui/slider"; import { Tooltip, TooltipContent, TooltipProvider, TooltipTrigger, } from "@/components/ui/tooltip"; -import { Slider } from "@/components/ui/slider"; import { GraphInput } from "@/contexts/GraphContext"; +import { cn } from "@/lib/utils"; +import { ArtifactLengthOptions } from "@/types"; +import { BaseMessage, HumanMessage } from "@langchain/core/messages"; +import { useState } from "react"; export interface LengthOptionsProps { streamMessage: (params: GraphInput) => Promise; handleClose: () => void; + setMessages: React.Dispatch>; } const lengthOptions = [ @@ -30,6 +32,16 @@ export function LengthOptions(props: LengthOptionsProps) { const handleSubmit = async (artifactLength: ArtifactLengthOptions) => { props.handleClose(); + const lengthMap = { + shortest: "much shorter", + short: "shorter", + long: "longer", + longest: "much longer", + }; + props.setMessages((prevMessages) => [ + ...prevMessages, + new HumanMessage(`Update my artifact to be ${lengthMap[artifactLength]}`), + ]); await streamMessage({ artifactLength, }); diff --git a/src/components/artifacts/actions_toolbar/text/ReadingLevelOptions.tsx b/src/components/artifacts/actions_toolbar/text/ReadingLevelOptions.tsx index f0da7d5d..ed633f72 100644 --- a/src/components/artifacts/actions_toolbar/text/ReadingLevelOptions.tsx +++ b/src/components/artifacts/actions_toolbar/text/ReadingLevelOptions.tsx @@ -1,3 +1,7 @@ +import { TooltipIconButton } from "@/components/ui/assistant-ui/tooltip-icon-button"; +import { GraphInput } from "@/contexts/GraphContext"; +import { ReadingLevelOptions as ReadingLevelOptionsType } from "@/types"; +import { HumanMessage } from "@langchain/core/messages"; import { Baby, GraduationCap, @@ -5,13 +9,11 @@ import { School, Swords, } from "lucide-react"; -import { ReadingLevelOptions as ReadingLevelOptionsType } from "@/types"; -import { TooltipIconButton } from "@/components/ui/assistant-ui/tooltip-icon-button"; -import { GraphInput } from "@/contexts/GraphContext"; export interface ReadingLevelOptionsProps { streamMessage: (params: GraphInput) => Promise; handleClose: () => void; + setMessages: React.Dispatch>; } export function ReadingLevelOptions(props: ReadingLevelOptionsProps) { @@ -19,6 +21,19 @@ export function ReadingLevelOptions(props: ReadingLevelOptionsProps) { const handleSubmit = async (readingLevel: ReadingLevelOptionsType) => { props.handleClose(); + const levelMap = { + phd: "PhD level", + college: "college level", + teenager: "teenager level", + child: "child level", + pirate: "pirate speak", + }; + props.setMessages((prevMessages) => [ + ...prevMessages, + new HumanMessage( + `Rewrite my artifact to be at a ${levelMap[readingLevel]}` + ), + ]); await streamMessage({ readingLevel, }); diff --git a/src/components/artifacts/actions_toolbar/text/TranslateOptions.tsx b/src/components/artifacts/actions_toolbar/text/TranslateOptions.tsx index e047735a..b1a0c026 100644 --- a/src/components/artifacts/actions_toolbar/text/TranslateOptions.tsx +++ b/src/components/artifacts/actions_toolbar/text/TranslateOptions.tsx @@ -1,17 +1,19 @@ import { - UsaFlag, ChinaFlag, + FrenchFlag, IndiaFlag, SpanishFlag, - FrenchFlag, + UsaFlag, } from "@/components/icons/flags"; import { TooltipIconButton } from "@/components/ui/assistant-ui/tooltip-icon-button"; import { GraphInput } from "@/contexts/GraphContext"; import { LanguageOptions } from "@/types"; +import { BaseMessage, HumanMessage } from "@langchain/core/messages"; export interface TranslateOptionsProps { streamMessage: (params: GraphInput) => Promise; handleClose: () => void; + setMessages: React.Dispatch>; } export function TranslateOptions(props: TranslateOptionsProps) { @@ -19,6 +21,17 @@ export function TranslateOptions(props: TranslateOptionsProps) { const handleSubmit = async (language: LanguageOptions) => { props.handleClose(); + const languageMap = { + english: "English", + mandarin: "Mandarin", + hindi: "Hindi", + spanish: "Spanish", + french: "French", + }; + props.setMessages((prevMessages) => [ + ...prevMessages, + new HumanMessage(`Translate my artifact to ${languageMap[language]}`), + ]); await streamMessage({ language, }); diff --git a/src/components/artifacts/actions_toolbar/text/index.tsx b/src/components/artifacts/actions_toolbar/text/index.tsx index a725f2fc..0a380ce0 100644 --- a/src/components/artifacts/actions_toolbar/text/index.tsx +++ b/src/components/artifacts/actions_toolbar/text/index.tsx @@ -1,16 +1,18 @@ -import { useEffect, useRef, useState } from "react"; -import { Languages, BookOpen, SlidersVertical, SmilePlus } from "lucide-react"; +import { MagicPencilSVG } from "@/components/icons/magic_pencil"; +import { TooltipIconButton } from "@/components/ui/assistant-ui/tooltip-icon-button"; +import { GraphInput } from "@/contexts/GraphContext"; import { cn } from "@/lib/utils"; +import { BaseMessage, HumanMessage } from "@langchain/core/messages"; +import { BookOpen, Languages, SlidersVertical, SmilePlus } from "lucide-react"; +import { useEffect, useRef, useState } from "react"; +import { LengthOptions } from "./LengthOptions"; import { ReadingLevelOptions } from "./ReadingLevelOptions"; import { TranslateOptions } from "./TranslateOptions"; -import { LengthOptions } from "./LengthOptions"; -import { TooltipIconButton } from "@/components/ui/assistant-ui/tooltip-icon-button"; -import { MagicPencilSVG } from "@/components/icons/magic_pencil"; -import { GraphInput } from "@/contexts/GraphContext"; type SharedComponentProps = { streamMessage: (params: GraphInput) => Promise; handleClose: () => void; + setMessages: React.Dispatch>; }; type ToolbarOption = { @@ -22,6 +24,7 @@ type ToolbarOption = { export interface ActionsToolbarProps { streamMessage: (params: GraphInput) => Promise; + setMessages: React.Dispatch>; isTextSelected: boolean; } @@ -55,7 +58,7 @@ const toolbarOptions: ToolbarOption[] = [ ]; export function ActionsToolbar(props: ActionsToolbarProps) { - const { streamMessage } = props; + const { streamMessage, setMessages } = props; const [isExpanded, setIsExpanded] = useState(false); const [activeOption, setActiveOption] = useState(null); const toolbarRef = useRef(null); @@ -90,6 +93,10 @@ export function ActionsToolbar(props: ActionsToolbarProps) { ) => { event.stopPropagation(); if (optionId === "addEmojis") { + setMessages((prevMessages) => [ + ...prevMessages, + new HumanMessage("Add emojis to my artifact"), + ]); setIsExpanded(false); setActiveOption(null); await streamMessage({