From b4b9556e2c36ac658922a1601606b7f7bdbaa752 Mon Sep 17 00:00:00 2001 From: Will Chen Date: Mon, 19 May 2025 15:38:33 -0700 Subject: [PATCH] Add a keep going suggestion (#201) --- src/components/chat/ChatInput.tsx | 254 ++++++++++++-------------- src/ipc/handlers/proposal_handlers.ts | 5 +- src/lib/schemas.ts | 7 +- 3 files changed, 126 insertions(+), 140 deletions(-) diff --git a/src/components/chat/ChatInput.tsx b/src/components/chat/ChatInput.tsx index 5e99400..0a552b8 100644 --- a/src/components/chat/ChatInput.tsx +++ b/src/components/chat/ChatInput.tsx @@ -362,10 +362,39 @@ export function ChatInput({ chatId }: { chatId?: number }) { ); } +function SuggestionButton({ + children, + onClick, + tooltipText, +}: { + onClick: () => void; + children: React.ReactNode; + tooltipText: string; +}) { + const { isStreaming } = useStreamChat(); + return ( + + + + + + {tooltipText} + + + ); +} + function SummarizeInNewChatButton() { const chatId = useAtomValue(selectedChatIdAtom); const appId = useAtomValue(selectedAppIdAtom); - const { streamMessage, isStreaming } = useStreamChat(); + const { streamMessage } = useStreamChat(); const navigate = useNavigate(); const onClick = async () => { if (!appId) { @@ -385,106 +414,71 @@ function SummarizeInNewChatButton() { } }; return ( - - - - - - -

Creating a new chat makes the AI more focused and efficient

-
-
-
+ + Summarize to new chat + ); } function RefactorFileButton({ path }: { path: string }) { const chatId = useAtomValue(selectedChatIdAtom); - const { streamMessage, isStreaming } = useStreamChat(); + const { streamMessage } = useStreamChat(); + const onClick = () => { + if (!chatId) { + console.error("No chat id found"); + return; + } + streamMessage({ + prompt: `Refactor ${path} and make it more modular`, + chatId, + redo: false, + }); + }; return ( - - - - - - -

Refactor {path} to improve maintainability

-
-
-
+ + + Refactor {path.split("/").slice(-2).join("/")} + + ); } function WriteCodeProperlyButton() { const chatId = useAtomValue(selectedChatIdAtom); - const { streamMessage, isStreaming } = useStreamChat(); + const { streamMessage } = useStreamChat(); + const onClick = () => { + if (!chatId) { + console.error("No chat id found"); + return; + } + streamMessage({ + prompt: `Write the code in the previous message in the correct format using \`\` tags!`, + chatId, + redo: false, + }); + }; return ( - - - - - - -

- Write code properly (useful when AI generates the code in the wrong - format) -

-
-
-
+ + Write code properly + ); } function RebuildButton() { const { restartApp } = useRunApp(); - const { isStreaming } = useStreamChat(); const posthog = usePostHog(); const selectedAppId = useAtomValue(selectedAppIdAtom); - const handleRebuild = useCallback(async () => { + const onClick = useCallback(async () => { if (!selectedAppId) return; posthog.capture("action:rebuild"); @@ -492,33 +486,18 @@ function RebuildButton() { }, [selectedAppId, posthog, restartApp]); return ( - - - - - - -

Rebuild the application

-
-
-
+ + Rebuild app + ); } function RestartButton() { - const { isStreaming } = useStreamChat(); const { restartApp } = useRunApp(); const posthog = usePostHog(); const selectedAppId = useAtomValue(selectedAppIdAtom); - const handleRestart = useCallback(async () => { + const onClick = useCallback(async () => { if (!selectedAppId) return; posthog.capture("action:restart"); @@ -526,54 +505,51 @@ function RestartButton() { }, [selectedAppId, posthog, restartApp]); return ( - - - - - - -

Restart the development server

-
-
-
+ + Restart app + ); } function RefreshButton() { const { refreshAppIframe } = useRunApp(); - const { isStreaming } = useStreamChat(); const posthog = usePostHog(); - const handleRefresh = useCallback(() => { + const onClick = useCallback(() => { posthog.capture("action:refresh"); refreshAppIframe(); }, [posthog, refreshAppIframe]); return ( - - - - - - -

Refresh the application preview

-
-
-
+ + Refresh app + + ); +} + +function KeepGoingButton() { + const { streamMessage } = useStreamChat(); + const chatId = useAtomValue(selectedChatIdAtom); + const onClick = () => { + if (!chatId) { + console.error("No chat id found"); + return; + } + streamMessage({ + prompt: "Keep going", + chatId, + }); + }; + return ( + + Keep going + ); } @@ -591,6 +567,8 @@ function mapActionToButton(action: SuggestedAction) { return ; case "refresh": return ; + case "keep-going": + return ; default: console.error(`Unsupported action: ${action.id}`); return ( @@ -603,8 +581,8 @@ function mapActionToButton(action: SuggestedAction) { function ActionProposalActions({ proposal }: { proposal: ActionProposal }) { return ( -
-
+
+
{proposal.actions.map((action) => mapActionToButton(action))}
diff --git a/src/ipc/handlers/proposal_handlers.ts b/src/ipc/handlers/proposal_handlers.ts index 4d9d47f..d563ab5 100644 --- a/src/ipc/handlers/proposal_handlers.ts +++ b/src/ipc/handlers/proposal_handlers.ts @@ -297,7 +297,10 @@ const getProposalHandler = async ( }); } } - if (actions.length > 0 && latestAssistantMessage) { + if (latestAssistantMessage) { + actions.push({ + id: "keep-going", + }); return { proposal: { type: "action-proposal", diff --git a/src/lib/schemas.ts b/src/lib/schemas.ts index 56a2d62..4fd0b10 100644 --- a/src/lib/schemas.ts +++ b/src/lib/schemas.ts @@ -166,7 +166,8 @@ export type SuggestedAction = | WriteCodeProperlyAction | RebuildAction | RestartAction - | RefreshAction; + | RefreshAction + | KeepGoingAction; export interface RestartAppAction { id: "restart-app"; @@ -197,6 +198,10 @@ export interface RefreshAction { id: "refresh"; } +export interface KeepGoingAction { + id: "keep-going"; +} + export interface ActionProposal { type: "action-proposal"; actions: SuggestedAction[];