mirror of https://github.com/kortix-ai/suna.git
wip
This commit is contained in:
parent
61bb4c11ae
commit
b52fbcafb0
|
@ -8,7 +8,6 @@ from typing import AsyncGenerator, Optional, Dict, Any
|
|||
import sys
|
||||
from agent.prompt import INSTRUCTIONS
|
||||
|
||||
|
||||
async def run_agent(thread_id: str, stream: bool = True, thread_manager: Optional[ThreadManager] = None):
|
||||
"""Run the development agent with specified configuration."""
|
||||
|
||||
|
|
|
@ -1,57 +0,0 @@
|
|||
// Add audio effects to the page
|
||||
document.addEventListener('DOMContentLoaded', () => {
|
||||
// Create audio context
|
||||
const AudioContext = window.AudioContext || window.webkitAudioContext;
|
||||
const audioCtx = new AudioContext();
|
||||
|
||||
// Button click sound
|
||||
const button = document.querySelector('.glow-button');
|
||||
button.addEventListener('click', () => {
|
||||
playClickSound();
|
||||
});
|
||||
|
||||
// Letter hover sound
|
||||
const letters = document.querySelectorAll('.letter');
|
||||
letters.forEach(letter => {
|
||||
letter.addEventListener('mouseenter', () => {
|
||||
playHoverSound(Math.random() * 200 + 600); // Random frequency for variety
|
||||
});
|
||||
});
|
||||
|
||||
// Function to play click sound
|
||||
function playClickSound() {
|
||||
const oscillator = audioCtx.createOscillator();
|
||||
const gainNode = audioCtx.createGain();
|
||||
|
||||
oscillator.connect(gainNode);
|
||||
gainNode.connect(audioCtx.destination);
|
||||
|
||||
oscillator.type = 'sine';
|
||||
oscillator.frequency.setValueAtTime(400, audioCtx.currentTime);
|
||||
oscillator.frequency.exponentialRampToValueAtTime(20, audioCtx.currentTime + 0.3);
|
||||
|
||||
gainNode.gain.setValueAtTime(0.3, audioCtx.currentTime);
|
||||
gainNode.gain.exponentialRampToValueAtTime(0.01, audioCtx.currentTime + 0.3);
|
||||
|
||||
oscillator.start();
|
||||
oscillator.stop(audioCtx.currentTime + 0.3);
|
||||
}
|
||||
|
||||
// Function to play hover sound
|
||||
function playHoverSound(frequency) {
|
||||
const oscillator = audioCtx.createOscillator();
|
||||
const gainNode = audioCtx.createGain();
|
||||
|
||||
oscillator.connect(gainNode);
|
||||
gainNode.connect(audioCtx.destination);
|
||||
|
||||
oscillator.type = 'sine';
|
||||
oscillator.frequency.setValueAtTime(frequency, audioCtx.currentTime);
|
||||
|
||||
gainNode.gain.setValueAtTime(0.1, audioCtx.currentTime);
|
||||
gainNode.gain.exponentialRampToValueAtTime(0.01, audioCtx.currentTime + 0.1);
|
||||
|
||||
oscillator.start();
|
||||
oscillator.stop(audioCtx.currentTime + 0.1);
|
||||
}
|
||||
});
|
|
@ -1,38 +0,0 @@
|
|||
// Custom cursor effect
|
||||
document.addEventListener('DOMContentLoaded', () => {
|
||||
const cursor = document.querySelector('.custom-cursor');
|
||||
|
||||
document.addEventListener('mousemove', (e) => {
|
||||
cursor.style.left = e.clientX + 'px';
|
||||
cursor.style.top = e.clientY + 'px';
|
||||
});
|
||||
|
||||
// Expand cursor when hovering over interactive elements
|
||||
const interactiveElements = document.querySelectorAll('.glow-button, .letter');
|
||||
interactiveElements.forEach(el => {
|
||||
el.addEventListener('mouseenter', () => {
|
||||
cursor.style.width = '40px';
|
||||
cursor.style.height = '40px';
|
||||
cursor.style.backgroundColor = 'rgba(233, 69, 96, 0.2)';
|
||||
cursor.style.mixBlendMode = 'normal';
|
||||
});
|
||||
|
||||
el.addEventListener('mouseleave', () => {
|
||||
cursor.style.width = '20px';
|
||||
cursor.style.height = '20px';
|
||||
cursor.style.backgroundColor = 'transparent';
|
||||
cursor.style.mixBlendMode = 'difference';
|
||||
});
|
||||
});
|
||||
|
||||
// Hide cursor when leaving the window
|
||||
document.addEventListener('mouseout', (e) => {
|
||||
if (e.relatedTarget === null) {
|
||||
cursor.style.opacity = '0';
|
||||
}
|
||||
});
|
||||
|
||||
document.addEventListener('mouseover', () => {
|
||||
cursor.style.opacity = '1';
|
||||
});
|
||||
});
|
|
@ -1,52 +0,0 @@
|
|||
<!DOCTYPE html>
|
||||
<html lang="en">
|
||||
<head>
|
||||
<meta charset="UTF-8">
|
||||
<meta name="viewport" content="width=device-width, initial-scale=1.0">
|
||||
<title>Fancy Hello World</title>
|
||||
<link rel="stylesheet" href="styles.css">
|
||||
<link rel="stylesheet" href="https://cdnjs.cloudflare.com/ajax/libs/font-awesome/6.4.0/css/all.min.css">
|
||||
<link href="https://fonts.googleapis.com/css2?family=Poppins:wght@300;400;600;700&display=swap" rel="stylesheet">
|
||||
</head>
|
||||
<body>
|
||||
<div class="container">
|
||||
<div class="hello-world">
|
||||
<h1 class="title">
|
||||
<span class="letter">H</span>
|
||||
<span class="letter">e</span>
|
||||
<span class="letter">l</span>
|
||||
<span class="letter">l</span>
|
||||
<span class="letter">o</span>
|
||||
<span class="letter space"></span>
|
||||
<span class="letter">W</span>
|
||||
<span class="letter">o</span>
|
||||
<span class="letter">r</span>
|
||||
<span class="letter">l</span>
|
||||
<span class="letter">d</span>
|
||||
<span class="letter">!</span>
|
||||
</h1>
|
||||
<div class="subtitle">Welcome to my fancy webpage</div>
|
||||
</div>
|
||||
|
||||
<div class="floating-icons">
|
||||
<i class="fas fa-star"></i>
|
||||
<i class="fas fa-heart"></i>
|
||||
<i class="fas fa-code"></i>
|
||||
<i class="fas fa-rocket"></i>
|
||||
<i class="fas fa-magic"></i>
|
||||
<i class="fas fa-star"></i>
|
||||
<i class="fas fa-heart"></i>
|
||||
<i class="fas fa-code"></i>
|
||||
</div>
|
||||
|
||||
<button class="glow-button">Click Me!</button>
|
||||
</div>
|
||||
|
||||
<script src="script.js"></script>
|
||||
<script src="audio.js"></script>
|
||||
<script src="cursor.js"></script>
|
||||
|
||||
<!-- Add a custom cursor -->
|
||||
<div class="custom-cursor"></div>
|
||||
</body>
|
||||
</html>
|
|
@ -1,192 +0,0 @@
|
|||
// Set animation delay for each letter
|
||||
document.querySelectorAll('.letter').forEach((letter, index) => {
|
||||
letter.style.setProperty('--i', index);
|
||||
});
|
||||
|
||||
// Create floating icons randomly
|
||||
const floatingIcons = document.querySelector('.floating-icons');
|
||||
const icons = floatingIcons.querySelectorAll('i');
|
||||
|
||||
icons.forEach(icon => {
|
||||
// Random position
|
||||
const startPositionX = Math.random() * 100;
|
||||
const startDelay = Math.random() * 10;
|
||||
const duration = 10 + Math.random() * 20;
|
||||
const scale = 0.5 + Math.random() * 1.5;
|
||||
|
||||
icon.style.left = `${startPositionX}%`;
|
||||
icon.style.animationDuration = `${duration}s`;
|
||||
icon.style.animationDelay = `${startDelay}s`;
|
||||
icon.style.fontSize = `${scale}rem`;
|
||||
});
|
||||
|
||||
// Add click event to the button
|
||||
const button = document.querySelector('.glow-button');
|
||||
button.addEventListener('click', () => {
|
||||
// Create explosion effect
|
||||
for (let i = 0; i < 30; i++) {
|
||||
createParticle();
|
||||
}
|
||||
});
|
||||
|
||||
function createParticle() {
|
||||
const particle = document.createElement('div');
|
||||
particle.classList.add('particle');
|
||||
|
||||
// Random styles
|
||||
const size = Math.random() * 15 + 5;
|
||||
const color = `hsl(${Math.random() * 360}, 70%, 60%)`;
|
||||
const angle = Math.random() * Math.PI * 2;
|
||||
const velocity = 1 + Math.random() * 3;
|
||||
const posX = Math.cos(angle) * velocity;
|
||||
const posY = Math.sin(angle) * velocity;
|
||||
|
||||
// Apply styles
|
||||
particle.style.width = `${size}px`;
|
||||
particle.style.height = `${size}px`;
|
||||
particle.style.background = color;
|
||||
particle.style.borderRadius = '50%';
|
||||
particle.style.position = 'absolute';
|
||||
particle.style.top = '50%';
|
||||
particle.style.left = '50%';
|
||||
particle.style.transform = 'translate(-50%, -50%)';
|
||||
particle.style.pointerEvents = 'none';
|
||||
|
||||
document.querySelector('.container').appendChild(particle);
|
||||
|
||||
// Animate the particle
|
||||
let positionX = 0;
|
||||
let positionY = 0;
|
||||
let opacity = 1;
|
||||
let scale = 1;
|
||||
|
||||
const animate = () => {
|
||||
if (opacity <= 0) {
|
||||
particle.remove();
|
||||
return;
|
||||
}
|
||||
|
||||
positionX += posX;
|
||||
positionY += posY;
|
||||
opacity -= 0.02;
|
||||
scale += 0.02;
|
||||
|
||||
particle.style.transform = `translate(calc(-50% + ${positionX}px), calc(-50% + ${positionY}px)) scale(${scale})`;
|
||||
particle.style.opacity = opacity;
|
||||
|
||||
requestAnimationFrame(animate);
|
||||
};
|
||||
|
||||
requestAnimationFrame(animate);
|
||||
}
|
||||
|
||||
// Add some interactivity to the page
|
||||
document.addEventListener('mousemove', (e) => {
|
||||
const mouseX = e.clientX / window.innerWidth;
|
||||
const mouseY = e.clientY / window.innerHeight;
|
||||
|
||||
document.body.style.background = `linear-gradient(
|
||||
135deg,
|
||||
hsl(240, 20%, 15%),
|
||||
hsl(${220 + mouseX * 40}, 30%, 20%),
|
||||
hsl(${200 + mouseY * 60}, 40%, 25%)
|
||||
)`;
|
||||
|
||||
// Make the title follow the cursor slightly
|
||||
const title = document.querySelector('.title');
|
||||
title.style.transform = `translateX(${(mouseX - 0.5) * 20}px) translateY(${(mouseY - 0.5) * 10}px)`;
|
||||
});
|
||||
|
||||
// Add a typing effect to the subtitle
|
||||
const subtitle = document.querySelector('.subtitle');
|
||||
const subtitleText = subtitle.textContent;
|
||||
subtitle.textContent = '';
|
||||
subtitle.style.opacity = '1';
|
||||
|
||||
let charIndex = 0;
|
||||
function typeSubtitle() {
|
||||
if (charIndex < subtitleText.length) {
|
||||
subtitle.textContent += subtitleText.charAt(charIndex);
|
||||
charIndex++;
|
||||
setTimeout(typeSubtitle, 100);
|
||||
}
|
||||
}
|
||||
|
||||
// Start typing after a delay
|
||||
setTimeout(typeSubtitle, 1500);
|
||||
|
||||
// Add a confetti explosion when the page loads
|
||||
window.addEventListener('load', () => {
|
||||
setTimeout(() => {
|
||||
for (let i = 0; i < 50; i++) {
|
||||
createParticle(true);
|
||||
}
|
||||
}, 1000);
|
||||
});
|
||||
|
||||
// Modify the createParticle function to allow for initial explosion
|
||||
function createParticle(isInitial = false) {
|
||||
const particle = document.createElement('div');
|
||||
particle.classList.add('particle');
|
||||
|
||||
// Random styles
|
||||
const size = Math.random() * 15 + 5;
|
||||
const color = `hsl(${Math.random() * 360}, 70%, 60%)`;
|
||||
const angle = Math.random() * Math.PI * 2;
|
||||
const velocity = 1 + Math.random() * 3;
|
||||
const posX = Math.cos(angle) * velocity;
|
||||
const posY = Math.sin(angle) * velocity;
|
||||
|
||||
// Apply styles
|
||||
particle.style.width = `${size}px`;
|
||||
particle.style.height = `${size}px`;
|
||||
particle.style.background = color;
|
||||
particle.style.borderRadius = isInitial ? `${Math.random() * 50}%` : '50%';
|
||||
|
||||
document.querySelector('.container').appendChild(particle);
|
||||
|
||||
// Set initial position
|
||||
let startX = 50;
|
||||
let startY = 50;
|
||||
|
||||
if (isInitial) {
|
||||
// For initial explosion, start from the center of the screen
|
||||
startX = window.innerWidth / 2;
|
||||
startY = window.innerHeight / 2;
|
||||
particle.style.top = `${startY}px`;
|
||||
particle.style.left = `${startX}px`;
|
||||
} else {
|
||||
// For button click, start from the button
|
||||
const button = document.querySelector('.glow-button');
|
||||
const buttonRect = button.getBoundingClientRect();
|
||||
startX = buttonRect.left + buttonRect.width / 2;
|
||||
startY = buttonRect.top + buttonRect.height / 2;
|
||||
particle.style.top = `${startY}px`;
|
||||
particle.style.left = `${startX}px`;
|
||||
}
|
||||
|
||||
// Animate the particle
|
||||
let positionX = 0;
|
||||
let positionY = 0;
|
||||
let opacity = 1;
|
||||
let scale = 1;
|
||||
|
||||
const animate = () => {
|
||||
if (opacity <= 0) {
|
||||
particle.remove();
|
||||
return;
|
||||
}
|
||||
|
||||
positionX += posX;
|
||||
positionY += posY;
|
||||
opacity -= 0.02;
|
||||
scale += 0.02;
|
||||
|
||||
particle.style.transform = `translate(${positionX}px, ${positionY}px) scale(${scale})`;
|
||||
particle.style.opacity = opacity;
|
||||
|
||||
requestAnimationFrame(animate);
|
||||
};
|
||||
|
||||
requestAnimationFrame(animate);
|
||||
}
|
|
@ -1,197 +0,0 @@
|
|||
* {
|
||||
margin: 0;
|
||||
padding: 0;
|
||||
box-sizing: border-box;
|
||||
}
|
||||
|
||||
body {
|
||||
font-family: 'Poppins', sans-serif;
|
||||
background: linear-gradient(135deg, #1a1a2e, #16213e, #0f3460);
|
||||
color: #fff;
|
||||
height: 100vh;
|
||||
display: flex;
|
||||
justify-content: center;
|
||||
align-items: center;
|
||||
overflow: hidden;
|
||||
position: relative;
|
||||
}
|
||||
|
||||
.container {
|
||||
text-align: center;
|
||||
padding: 2rem;
|
||||
position: relative;
|
||||
z-index: 1;
|
||||
}
|
||||
|
||||
.hello-world {
|
||||
margin-bottom: 3rem;
|
||||
}
|
||||
|
||||
.title {
|
||||
font-size: 5rem;
|
||||
font-weight: 700;
|
||||
margin-bottom: 1rem;
|
||||
display: flex;
|
||||
justify-content: center;
|
||||
}
|
||||
|
||||
.letter {
|
||||
display: inline-block;
|
||||
animation: bounce 1s ease infinite;
|
||||
animation-delay: calc(0.1s * var(--i));
|
||||
transform-origin: bottom;
|
||||
}
|
||||
|
||||
.space {
|
||||
width: 1rem;
|
||||
}
|
||||
|
||||
@keyframes bounce {
|
||||
0%, 100% {
|
||||
transform: translateY(0);
|
||||
}
|
||||
50% {
|
||||
transform: translateY(-20px);
|
||||
}
|
||||
}
|
||||
|
||||
.subtitle {
|
||||
font-size: 1.5rem;
|
||||
font-weight: 300;
|
||||
opacity: 0;
|
||||
animation: fadeIn 2s ease forwards 1s;
|
||||
}
|
||||
|
||||
@keyframes fadeIn {
|
||||
from {
|
||||
opacity: 0;
|
||||
transform: translateY(20px);
|
||||
}
|
||||
to {
|
||||
opacity: 1;
|
||||
transform: translateY(0);
|
||||
}
|
||||
}
|
||||
|
||||
.floating-icons {
|
||||
position: absolute;
|
||||
top: 0;
|
||||
left: 0;
|
||||
width: 100%;
|
||||
height: 100%;
|
||||
pointer-events: none;
|
||||
}
|
||||
|
||||
.floating-icons i {
|
||||
position: absolute;
|
||||
color: rgba(255, 255, 255, 0.3);
|
||||
animation: float 15s linear infinite;
|
||||
}
|
||||
|
||||
@keyframes float {
|
||||
0% {
|
||||
transform: translateY(100vh) scale(0);
|
||||
opacity: 0;
|
||||
}
|
||||
10% {
|
||||
opacity: 1;
|
||||
}
|
||||
90% {
|
||||
opacity: 1;
|
||||
}
|
||||
100% {
|
||||
transform: translateY(-100px) scale(1.5);
|
||||
opacity: 0;
|
||||
}
|
||||
}
|
||||
|
||||
.glow-button {
|
||||
background: none;
|
||||
border: 2px solid #e94560;
|
||||
color: #e94560;
|
||||
padding: 0.8rem 2rem;
|
||||
font-size: 1.2rem;
|
||||
border-radius: 50px;
|
||||
cursor: pointer;
|
||||
position: relative;
|
||||
overflow: hidden;
|
||||
transition: all 0.3s ease;
|
||||
font-family: 'Poppins', sans-serif;
|
||||
z-index: 1;
|
||||
margin-top: 2rem;
|
||||
}
|
||||
|
||||
.glow-button:hover {
|
||||
color: white;
|
||||
box-shadow: 0 0 20px #e94560;
|
||||
}
|
||||
|
||||
.glow-button::before {
|
||||
content: '';
|
||||
position: absolute;
|
||||
top: 0;
|
||||
left: 0;
|
||||
width: 0%;
|
||||
height: 100%;
|
||||
background-color: #e94560;
|
||||
transition: all 0.3s ease;
|
||||
z-index: -1;
|
||||
}
|
||||
|
||||
.glow-button:hover::before {
|
||||
width: 100%;
|
||||
}
|
||||
|
||||
/* Particle effect for button */
|
||||
.particle {
|
||||
position: absolute;
|
||||
pointer-events: none;
|
||||
z-index: 99;
|
||||
}
|
||||
|
||||
/* Add a cool text shadow effect to title */
|
||||
.title {
|
||||
text-shadow: 0 0 10px rgba(233, 69, 96, 0.5);
|
||||
}
|
||||
|
||||
/* Add a subtle pulse effect to the button */
|
||||
@keyframes pulse {
|
||||
0% {
|
||||
box-shadow: 0 0 0 0 rgba(233, 69, 96, 0.7);
|
||||
}
|
||||
70% {
|
||||
box-shadow: 0 0 0 10px rgba(233, 69, 96, 0);
|
||||
}
|
||||
100% {
|
||||
box-shadow: 0 0 0 0 rgba(233, 69, 96, 0);
|
||||
}
|
||||
}
|
||||
|
||||
.glow-button {
|
||||
animation: pulse 2s infinite;
|
||||
}
|
||||
|
||||
/* Custom cursor */
|
||||
.custom-cursor {
|
||||
position: fixed;
|
||||
width: 20px;
|
||||
height: 20px;
|
||||
border: 2px solid #e94560;
|
||||
border-radius: 50%;
|
||||
pointer-events: none;
|
||||
transform: translate(-50%, -50%);
|
||||
z-index: 9999;
|
||||
transition: width 0.2s, height 0.2s, background-color 0.2s;
|
||||
mix-blend-mode: difference;
|
||||
}
|
||||
|
||||
/* Add responsive design */
|
||||
@media (max-width: 768px) {
|
||||
.title {
|
||||
font-size: 3rem;
|
||||
}
|
||||
|
||||
.subtitle {
|
||||
font-size: 1.2rem;
|
||||
}
|
||||
}
|
|
@ -55,7 +55,6 @@ function DashboardContent() {
|
|||
onSubmit={handleSubmit}
|
||||
loading={isSubmitting}
|
||||
placeholder="Ask anything..."
|
||||
minHeight="min-h-[100px]"
|
||||
value={inputValue}
|
||||
onChange={setInputValue}
|
||||
/>
|
||||
|
|
|
@ -5,24 +5,15 @@ import { useRouter } from 'next/navigation';
|
|||
import { useAuth } from '@/context/auth-context';
|
||||
import { Button } from '@/components/ui/button';
|
||||
import { ArrowDown } from 'lucide-react';
|
||||
import { getProject, getThread, addMessage, getMessages, startAgent, stopAgent, getAgentStatus, streamAgent, getAgentRuns } from '@/lib/api';
|
||||
import { addMessage, getMessages, startAgent, stopAgent, getAgentStatus, streamAgent, getAgentRuns } from '@/lib/api';
|
||||
import { toast } from 'sonner';
|
||||
import { Project } from '@/lib/types';
|
||||
import { Skeleton } from "@/components/ui/skeleton";
|
||||
import { ChatInput } from '@/components/chat-input';
|
||||
|
||||
// Define a type for the params to make React.use() work properly
|
||||
type ThreadParams = { id: string; threadId: string };
|
||||
|
||||
// Define types for the API responses
|
||||
interface ApiThread {
|
||||
thread_id: string;
|
||||
messages: Array<{
|
||||
role: string;
|
||||
content: string;
|
||||
}>;
|
||||
created_at: string;
|
||||
}
|
||||
|
||||
|
||||
interface ApiMessage {
|
||||
role: string;
|
||||
|
@ -46,8 +37,6 @@ export default function ThreadPage({ params }: { params: Promise<ThreadParams> }
|
|||
|
||||
const { user, isLoading: isAuthLoading } = useAuth();
|
||||
const router = useRouter();
|
||||
const [project, setProject] = useState<Project | null>(null);
|
||||
const [thread, setThread] = useState<ApiThread | null>(null);
|
||||
const [messages, setMessages] = useState<ApiMessage[]>([]);
|
||||
const [newMessage, setNewMessage] = useState('');
|
||||
const [isLoading, setIsLoading] = useState(true);
|
||||
|
@ -175,7 +164,7 @@ export default function ThreadPage({ params }: { params: Promise<ThreadParams> }
|
|||
|
||||
// Store cleanup function
|
||||
streamCleanupRef.current = cleanup;
|
||||
}, [threadId]);
|
||||
}, [threadId, streamContent]);
|
||||
|
||||
useEffect(() => {
|
||||
if (!isAuthLoading && !user) {
|
||||
|
@ -198,12 +187,12 @@ export default function ThreadPage({ params }: { params: Promise<ThreadParams> }
|
|||
}
|
||||
|
||||
// Load project data
|
||||
const projectData = await getProject(projectId) as unknown as Project;
|
||||
setProject(projectData);
|
||||
// const projectData = await getProject(projectId) as unknown as Project;
|
||||
// setProject(projectData);
|
||||
|
||||
// Load thread data
|
||||
const threadData = await getThread(threadId) as unknown as ApiThread;
|
||||
setThread(threadData);
|
||||
// const threadData = await getThread(threadId) as unknown as ApiThread;
|
||||
// setThread(threadData);
|
||||
|
||||
// Load messages
|
||||
const messagesData = await getMessages(threadId) as unknown as ApiMessage[];
|
||||
|
@ -372,13 +361,11 @@ export default function ThreadPage({ params }: { params: Promise<ThreadParams> }
|
|||
|
||||
// Adjust textarea height based on content
|
||||
useEffect(() => {
|
||||
const textarea = textareaRef.current;
|
||||
if (!textarea) return;
|
||||
|
||||
const adjustHeight = () => {
|
||||
textarea.style.height = 'auto';
|
||||
const newHeight = Math.min(textarea.scrollHeight, 200); // Max height of 200px
|
||||
textarea.style.height = `${newHeight}px`;
|
||||
if (textareaRef.current) {
|
||||
textareaRef.current.style.height = 'auto';
|
||||
textareaRef.current.style.height = `${textareaRef.current.scrollHeight}px`;
|
||||
}
|
||||
};
|
||||
|
||||
adjustHeight();
|
||||
|
@ -388,17 +375,17 @@ export default function ThreadPage({ params }: { params: Promise<ThreadParams> }
|
|||
return () => window.removeEventListener('resize', adjustHeight);
|
||||
}, [newMessage]);
|
||||
|
||||
// Handle keyboard shortcuts
|
||||
const handleKeyDown = (e: React.KeyboardEvent<HTMLTextAreaElement>) => {
|
||||
// Send on Enter (without Shift)
|
||||
if (e.key === 'Enter' && !e.shiftKey) {
|
||||
e.preventDefault();
|
||||
// // Handle keyboard shortcuts
|
||||
// const handleKeyDown = (e: React.KeyboardEvent<HTMLTextAreaElement>) => {
|
||||
// // Send on Enter (without Shift)
|
||||
// if (e.key === 'Enter' && !e.shiftKey) {
|
||||
// e.preventDefault();
|
||||
|
||||
if (newMessage.trim() && !isSending && agentStatus !== 'running') {
|
||||
handleSubmitMessage(newMessage);
|
||||
}
|
||||
}
|
||||
};
|
||||
// if (newMessage.trim() && !isSending && agentStatus !== 'running') {
|
||||
// handleSubmitMessage(newMessage);
|
||||
// }
|
||||
// }
|
||||
// };
|
||||
|
||||
// Check if user has scrolled up from bottom
|
||||
const handleScroll = () => {
|
||||
|
|
|
@ -177,7 +177,7 @@ export function AppSidebar({ ...props }: React.ComponentProps<typeof Sidebar>) {
|
|||
strokeWidth="2"
|
||||
strokeLinecap="round"
|
||||
strokeLinejoin="round"
|
||||
className="mr-2.5 h-6 w-6 text-black transition-transform duration-200 group-hover/logo:scale-110"
|
||||
className="mr-2.5 h-5 w-5 text-black transition-transform duration-200 group-hover/logo:scale-110"
|
||||
>
|
||||
<path d="M15 6v12a3 3 0 1 0 3-3H6a3 3 0 1 0 3 3V6a3 3 0 1 0-3 3h12a3 3 0 1 0-3-3" />
|
||||
</svg>
|
||||
|
|
|
@ -6,7 +6,6 @@ import { MainNav } from '@/components/main-nav';
|
|||
import { AppSidebar } from "@/components/app-sidebar"
|
||||
import { SiteHeader } from "@/components/site-header"
|
||||
import { SidebarInset, SidebarProvider } from "@/components/ui/sidebar"
|
||||
import { Skeleton } from "@/components/ui/skeleton"
|
||||
|
||||
export function LayoutContent({ children }: { children: React.ReactNode }) {
|
||||
const pathname = usePathname();
|
||||
|
|
|
@ -33,7 +33,7 @@ export function MainNav() {
|
|||
toast.success('Successfully logged out');
|
||||
router.push('/auth/login');
|
||||
router.refresh();
|
||||
} catch (error) {
|
||||
} catch {
|
||||
toast.error('Failed to log out. Please try again.');
|
||||
}
|
||||
};
|
||||
|
|
|
@ -50,7 +50,7 @@ export function NavUser({
|
|||
toast.success('Successfully logged out')
|
||||
router.push('/auth/login')
|
||||
router.refresh()
|
||||
} catch (error) {
|
||||
} catch {
|
||||
toast.error('Failed to log out. Please try again.')
|
||||
}
|
||||
}
|
||||
|
|
Loading…
Reference in New Issue