From a8f0da8ae86ade404f16638e566b9a7da0028496 Mon Sep 17 00:00:00 2001 From: marko-kraemer Date: Thu, 17 Apr 2025 14:19:52 +0100 Subject: [PATCH] generateThreadName server action --- frontend/src/app/dashboard/page.tsx | 3 +- .../thread/tool-call-side-panel.tsx | 74 +++++++++---------- frontend/src/lib/actions/threads.ts | 59 +++++++++++++++ frontend/src/lib/api.ts | 58 --------------- 4 files changed, 98 insertions(+), 96 deletions(-) create mode 100644 frontend/src/lib/actions/threads.ts diff --git a/frontend/src/app/dashboard/page.tsx b/frontend/src/app/dashboard/page.tsx index 0c03fdd1..6a6bf875 100644 --- a/frontend/src/app/dashboard/page.tsx +++ b/frontend/src/app/dashboard/page.tsx @@ -4,7 +4,8 @@ import React, { useState, Suspense } from 'react'; import { Skeleton } from "@/components/ui/skeleton"; import { useRouter } from 'next/navigation'; import { ChatInput } from '@/components/thread/chat-input'; -import { createProject, addUserMessage, startAgent, createThread, generateThreadName } from "@/lib/api"; +import { createProject, addUserMessage, startAgent, createThread } from "@/lib/api"; +import { generateThreadName } from "@/lib/actions/threads"; function DashboardContent() { const [inputValue, setInputValue] = useState(""); diff --git a/frontend/src/components/thread/tool-call-side-panel.tsx b/frontend/src/components/thread/tool-call-side-panel.tsx index e9479230..0fb61c16 100644 --- a/frontend/src/components/thread/tool-call-side-panel.tsx +++ b/frontend/src/components/thread/tool-call-side-panel.tsx @@ -1223,43 +1223,6 @@ export function ToolCallSidePanel({
- {/* Navigation Controls - Conditionally Rendered */} - {showNavigation && ( -
-
- - Step {currentIndex + 1} of {totalPairs} - -
- - -
-
- onNavigate(value[0])} // onValueChange gives an array - /> -
- )} - {content ? ( // ---- Render Historical Pair ---- 'type' in content && content.type === 'historical' ? ( @@ -1367,6 +1330,43 @@ export function ToolCallSidePanel({ )}
+ {/* Navigation Controls moved to bottom, just above TodoPanel */} + {showNavigation && ( +
+
+ + Step {currentIndex + 1} of {totalPairs} + +
+ + +
+
+ onNavigate(value[0])} // onValueChange gives an array + /> +
+ )} + {/* Todo Panel at the bottom of side panel */} {sandboxId && ( => { + try { + // Default name in case the API fails + const defaultName = message.trim().length > 50 + ? message.trim().substring(0, 47) + "..." + : message.trim(); + + // OpenAI API key should be stored in an environment variable + const apiKey = process.env.OPENAI_API_KEY; + + if (!apiKey) { + console.error('OpenAI API key not found'); + return defaultName; + } + + const response = await fetch('https://api.openai.com/v1/chat/completions', { + method: 'POST', + headers: { + 'Content-Type': 'application/json', + 'Authorization': `Bearer ${apiKey}` + }, + body: JSON.stringify({ + model: 'gpt-4o-mini', + messages: [ + { + role: 'system', + content: 'You are a helpful assistant that generates extremely concise titles (2-4 words maximum) for chat threads based on the user\'s message. Respond with only the title, no other text or punctuation.' + }, + { + role: 'user', + content: `Generate an extremely brief title (2-4 words only) for a chat thread that starts with this message: "${message}"` + } + ], + max_tokens: 20, + temperature: 0.7 + }) + }); + + if (!response.ok) { + const errorData = await response.text(); + console.error('OpenAI API error:', errorData); + return defaultName; + } + + const data = await response.json(); + const generatedName = data.choices[0]?.message?.content?.trim(); + + // Return the generated name or default if empty + return generatedName || defaultName; + } catch (error) { + console.error('Error generating thread name:', error); + // Fall back to using a truncated version of the message + return message.trim().length > 50 + ? message.trim().substring(0, 47) + "..." + : message.trim(); + } +}; \ No newline at end of file diff --git a/frontend/src/lib/api.ts b/frontend/src/lib/api.ts index fe9267ef..9bfff556 100644 --- a/frontend/src/lib/api.ts +++ b/frontend/src/lib/api.ts @@ -848,62 +848,4 @@ export const getSandboxFileContent = async (sandboxId: string, path: string): Pr console.error('Failed to get sandbox file content:', error); throw error; } -}; - -export const generateThreadName = async (message: string): Promise => { - try { - // Default name in case the API fails - const defaultName = message.trim().length > 50 - ? message.trim().substring(0, 47) + "..." - : message.trim(); - - // OpenAI API key should be stored in an environment variable - const apiKey = process.env.NEXT_PUBLIC_OPENAI_API_KEY; - - if (!apiKey) { - console.error('OpenAI API key not found'); - return defaultName; - } - - const response = await fetch('https://api.openai.com/v1/chat/completions', { - method: 'POST', - headers: { - 'Content-Type': 'application/json', - 'Authorization': `Bearer ${apiKey}` - }, - body: JSON.stringify({ - model: 'gpt-4o-mini', - messages: [ - { - role: 'system', - content: 'You are a helpful assistant that generates extremely concise titles (2-4 words maximum) for chat threads based on the user\'s message. Respond with only the title, no other text or punctuation.' - }, - { - role: 'user', - content: `Generate an extremely brief title (2-4 words only) for a chat thread that starts with this message: "${message}"` - } - ], - max_tokens: 20, - temperature: 0.7 - }) - }); - - if (!response.ok) { - const errorData = await response.text(); - console.error('OpenAI API error:', errorData); - return defaultName; - } - - const data = await response.json(); - const generatedName = data.choices[0]?.message?.content?.trim(); - - // Return the generated name or default if empty - return generatedName || defaultName; - } catch (error) { - console.error('Error generating thread name:', error); - // Fall back to using a truncated version of the message - return message.trim().length > 50 - ? message.trim().substring(0, 47) + "..." - : message.trim(); - } }; \ No newline at end of file