|
|
<!DOCTYPE html> |
|
|
<html lang="ko"> |
|
|
<head> |
|
|
<meta charset="UTF-8"> |
|
|
<meta name="viewport" content="width=device-width, initial-scale=1.0"> |
|
|
<title>멀티 에이전트 채팅 시스템</title> |
|
|
<script src="https://cdn.tailwindcss.com"></script> |
|
|
<link rel="stylesheet" href="https://cdnjs.cloudflare.com/ajax/libs/font-awesome/6.4.0/css/all.min.css"> |
|
|
<style> |
|
|
.agent-card:hover { |
|
|
transform: translateY(-5px); |
|
|
box-shadow: 0 10px 25px rgba(0, 0, 0, 0.1); |
|
|
} |
|
|
.message-animation { |
|
|
animation: fadeIn 0.3s ease-out; |
|
|
} |
|
|
@keyframes fadeIn { |
|
|
from { opacity: 0; transform: translateY(10px); } |
|
|
to { opacity: 1; transform: translateY(0); } |
|
|
} |
|
|
.typing-indicator { |
|
|
display: inline-flex; |
|
|
align-items: center; |
|
|
} |
|
|
.typing-dot { |
|
|
width: 8px; |
|
|
height: 8px; |
|
|
background-color: #9CA3AF; |
|
|
border-radius: 50%; |
|
|
margin: 0 2px; |
|
|
animation: typingAnimation 1.4s infinite ease-in-out; |
|
|
} |
|
|
.typing-dot:nth-child(1) { animation-delay: 0s; } |
|
|
.typing-dot:nth-child(2) { animation-delay: 0.2s; } |
|
|
.typing-dot:nth-child(3) { animation-delay: 0.4s; } |
|
|
@keyframes typingAnimation { |
|
|
0%, 60%, 100% { transform: translateY(0); } |
|
|
30% { transform: translateY(-5px); } |
|
|
} |
|
|
</style> |
|
|
</head> |
|
|
<body class="bg-gray-100 font-sans"> |
|
|
<div class="container mx-auto px-4 py-8 max-w-7xl"> |
|
|
<header class="mb-8 text-center"> |
|
|
<h1 class="text-4xl font-bold text-indigo-800 mb-2">멀티 에이전트 채팅 시스템</h1> |
|
|
<p class="text-gray-600">여러 AI 에이전트와 동시에 대화하며 다양한 관점을 경험하세요</p> |
|
|
</header> |
|
|
|
|
|
<div class="flex flex-col lg:flex-row gap-6"> |
|
|
|
|
|
<div class="w-full lg:w-1/4 bg-white rounded-xl shadow-md p-4 h-fit"> |
|
|
<h2 class="text-xl font-semibold text-gray-800 mb-4">에이전트 선택</h2> |
|
|
<div class="space-y-3"> |
|
|
<div class="agent-card bg-indigo-50 p-4 rounded-lg cursor-pointer transition-all duration-300 border border-indigo-100" |
|
|
onclick="selectAgent('analyst')" data-agent="analyst"> |
|
|
<div class="flex items-center"> |
|
|
<div class="w-10 h-10 rounded-full bg-indigo-200 flex items-center justify-center mr-3"> |
|
|
<i class="fas fa-chart-line text-indigo-600"></i> |
|
|
</div> |
|
|
<div> |
|
|
<h3 class="font-medium text-indigo-800">분석가 알렉스</h3> |
|
|
<p class="text-xs text-gray-500">데이터 분석 전문가</p> |
|
|
</div> |
|
|
</div> |
|
|
</div> |
|
|
|
|
|
<div class="agent-card bg-green-50 p-4 rounded-lg cursor-pointer transition-all duration-300 border border-green-100" |
|
|
onclick="selectAgent('creative')" data-agent="creative"> |
|
|
<div class="flex items-center"> |
|
|
<div class="w-10 h-10 rounded-full bg-green-200 flex items-center justify-center mr-3"> |
|
|
<i class="fas fa-paint-brush text-green-600"></i> |
|
|
</div> |
|
|
<div> |
|
|
<h3 class="font-medium text-green-800">크리에이터 클로이</h3> |
|
|
<p class="text-xs text-gray-500">창의적 아이디어 생성기</p> |
|
|
</div> |
|
|
</div> |
|
|
</div> |
|
|
|
|
|
<div class="agent-card bg-red-50 p-4 rounded-lg cursor-pointer transition-all duration-300 border border-red-100" |
|
|
onclick="selectAgent('debater')" data-agent="debater"> |
|
|
<div class="flex items-center"> |
|
|
<div class="w-10 h-10 rounded-full bg-red-200 flex items-center justify-center mr-3"> |
|
|
<i class="fas fa-comments text-red-600"></i> |
|
|
</div> |
|
|
<div> |
|
|
<h3 class="font-medium text-red-800">토론가 데이빗</h3> |
|
|
<p class="text-xs text-gray-500">논리적 토론 전문가</p> |
|
|
</div> |
|
|
</div> |
|
|
</div> |
|
|
|
|
|
<div class="agent-card bg-yellow-50 p-4 rounded-lg cursor-pointer transition-all duration-300 border border-yellow-100" |
|
|
onclick="selectAgent('advisor')" data-agent="advisor"> |
|
|
<div class="flex items-center"> |
|
|
<div class="w-10 h-10 rounded-full bg-yellow-200 flex items-center justify-center mr-3"> |
|
|
<i class="fas fa-lightbulb text-yellow-600"></i> |
|
|
</div> |
|
|
<div> |
|
|
<h3 class="font-medium text-yellow-800">조언가 제시카</h3> |
|
|
<p class="text-xs text-gray-500">전략적 조언 제공자</p> |
|
|
</div> |
|
|
</div> |
|
|
</div> |
|
|
</div> |
|
|
|
|
|
<div class="mt-6"> |
|
|
<h3 class="text-sm font-semibold text-gray-700 mb-2">시스템 설정</h3> |
|
|
<div class="flex items-center justify-between mb-2"> |
|
|
<span class="text-sm text-gray-600">에이전트 간 상호작용</span> |
|
|
<label class="relative inline-flex items-center cursor-pointer"> |
|
|
<input type="checkbox" id="agentInteraction" class="sr-only peer" checked> |
|
|
<div class="w-11 h-6 bg-gray-200 peer-focus:outline-none peer-focus:ring-4 peer-focus:ring-indigo-300 rounded-full peer peer-checked:after:translate-x-full peer-checked:after:border-white after:content-[''] after:absolute after:top-[2px] after:left-[2px] after:bg-white after:border-gray-300 after:border after:rounded-full after:h-5 after:w-5 after:transition-all peer-checked:bg-indigo-600"></div> |
|
|
</label> |
|
|
</div> |
|
|
<div class="flex items-center justify-between"> |
|
|
<span class="text-sm text-gray-600">실시간 반응</span> |
|
|
<label class="relative inline-flex items-center cursor-pointer"> |
|
|
<input type="checkbox" id="realtimeResponse" class="sr-only peer" checked> |
|
|
<div class="w-11 h-6 bg-gray-200 peer-focus:outline-none peer-focus:ring-4 peer-focus:ring-indigo-300 rounded-full peer peer-checked:after:translate-x-full peer-checked:after:border-white after:content-[''] after:absolute after:top-[2px] after:left-[2px] after:bg-white after:border-gray-300 after:border after:rounded-full after:h-5 after:w-5 after:transition-all peer-checked:bg-indigo-600"></div> |
|
|
</label> |
|
|
</div> |
|
|
</div> |
|
|
</div> |
|
|
|
|
|
|
|
|
<div class="w-full lg:w-3/4 flex flex-col"> |
|
|
|
|
|
<div class="bg-white rounded-xl shadow-md p-4 mb-4"> |
|
|
<div class="flex flex-wrap gap-3" id="selectedAgentsContainer"> |
|
|
<div class="text-sm text-gray-500">에이전트를 선택하세요 (복수 선택 가능)</div> |
|
|
</div> |
|
|
</div> |
|
|
|
|
|
|
|
|
<div class="flex-1 bg-white rounded-xl shadow-md p-4 mb-4 overflow-y-auto" id="chatContainer" style="min-height: 400px;"> |
|
|
<div class="text-center text-gray-500 py-10" id="welcomeMessage"> |
|
|
<i class="fas fa-robot text-4xl text-indigo-300 mb-3"></i> |
|
|
<p class="text-lg">멀티 에이전트 채팅 시스템에 오신 것을 환영합니다!</p> |
|
|
<p class="text-sm mt-2">왼쪽에서 대화할 에이전트를 선택해 주세요.</p> |
|
|
</div> |
|
|
<div id="chatMessages" class="space-y-4 hidden"></div> |
|
|
</div> |
|
|
|
|
|
|
|
|
<div class="bg-white rounded-xl shadow-md p-4"> |
|
|
<div class="flex items-center"> |
|
|
<input type="text" id="userInput" placeholder="메시지를 입력하세요..." |
|
|
class="flex-1 border border-gray-300 rounded-l-lg py-2 px-4 focus:outline-none focus:ring-2 focus:ring-indigo-500 focus:border-transparent"> |
|
|
<button onclick="sendMessage()" class="bg-indigo-600 text-white py-2 px-6 rounded-r-lg hover:bg-indigo-700 transition duration-300"> |
|
|
<i class="fas fa-paper-plane"></i> |
|
|
</button> |
|
|
</div> |
|
|
<div class="flex justify-between mt-2"> |
|
|
<div class="text-xs text-gray-500"> |
|
|
<span id="charCount">0</span>/500 |
|
|
</div> |
|
|
<div class="flex space-x-2"> |
|
|
<button class="text-gray-500 hover:text-indigo-600" title="파일 첨부"> |
|
|
<i class="fas fa-paperclip"></i> |
|
|
</button> |
|
|
<button class="text-gray-500 hover:text-indigo-600" title="음성 입력"> |
|
|
<i class="fas fa-microphone"></i> |
|
|
</button> |
|
|
</div> |
|
|
</div> |
|
|
</div> |
|
|
</div> |
|
|
</div> |
|
|
</div> |
|
|
|
|
|
<script> |
|
|
|
|
|
let selectedAgents = []; |
|
|
let conversationHistory = []; |
|
|
|
|
|
|
|
|
const agents = { |
|
|
analyst: { |
|
|
name: "분석가 알렉스", |
|
|
color: "indigo", |
|
|
icon: "chart-line", |
|
|
description: "데이터 분석 전문가", |
|
|
personality: "저는 데이터와 사실에 기반한 분석을 제공합니다. 감정보다는 숫자와 통계를 신뢰합니다." |
|
|
}, |
|
|
creative: { |
|
|
name: "크리에이터 클로이", |
|
|
color: "green", |
|
|
icon: "paint-brush", |
|
|
description: "창의적 아이디어 생성기", |
|
|
personality: "상상력이 풍부하고 독창적인 아이디어를 제공하는 것이 제 강점입니다. 틀에 얽매이지 않는 사고를 좋아해요!" |
|
|
}, |
|
|
debater: { |
|
|
name: "토론가 데이빗", |
|
|
color: "red", |
|
|
icon: "comments", |
|
|
description: "논리적 토론 전문가", |
|
|
personality: "논리적 오류를 찾아내고 다양한 관점에서 문제를 바라보는 것을 좋아합니다. 강한 주장도 두려워하지 않아요." |
|
|
}, |
|
|
advisor: { |
|
|
name: "조언가 제시카", |
|
|
color: "yellow", |
|
|
icon: "lightbulb", |
|
|
description: "전략적 조언 제공자", |
|
|
personality: "실용적이고 실행 가능한 조언을 제공하는 것을 좋아합니다. 장기적인 관점에서 문제를 해결하는 데 집중합니다." |
|
|
} |
|
|
}; |
|
|
|
|
|
|
|
|
function selectAgent(agentId) { |
|
|
const agentCard = document.querySelector(`[data-agent="${agentId}"]`); |
|
|
|
|
|
if (selectedAgents.includes(agentId)) { |
|
|
|
|
|
selectedAgents = selectedAgents.filter(id => id !== agentId); |
|
|
agentCard.classList.remove(`border-${agents[agentId].color}-300`, `ring-2`, `ring-${agents[agentId].color}-300`); |
|
|
} else { |
|
|
|
|
|
selectedAgents.push(agentId); |
|
|
agentCard.classList.add(`border-${agents[agentId].color}-300`, `ring-2`, `ring-${agents[agentId].color}-300`); |
|
|
} |
|
|
|
|
|
updateSelectedAgentsUI(); |
|
|
} |
|
|
|
|
|
|
|
|
function updateSelectedAgentsUI() { |
|
|
const container = document.getElementById('selectedAgentsContainer'); |
|
|
|
|
|
if (selectedAgents.length === 0) { |
|
|
container.innerHTML = '<div class="text-sm text-gray-500">에이전트를 선택하세요 (복수 선택 가능)</div>'; |
|
|
document.getElementById('welcomeMessage').classList.remove('hidden'); |
|
|
document.getElementById('chatMessages').classList.add('hidden'); |
|
|
return; |
|
|
} |
|
|
|
|
|
container.innerHTML = ''; |
|
|
selectedAgents.forEach(agentId => { |
|
|
const agent = agents[agentId]; |
|
|
const badge = document.createElement('div'); |
|
|
badge.className = `flex items-center bg-${agent.color}-100 text-${agent.color}-800 px-3 py-1 rounded-full text-sm`; |
|
|
badge.innerHTML = ` |
|
|
<i class="fas fa-${agent.icon} mr-1"></i> |
|
|
${agent.name} |
|
|
`; |
|
|
container.appendChild(badge); |
|
|
}); |
|
|
|
|
|
document.getElementById('welcomeMessage').classList.add('hidden'); |
|
|
document.getElementById('chatMessages').classList.remove('hidden'); |
|
|
} |
|
|
|
|
|
|
|
|
function sendMessage() { |
|
|
const userInput = document.getElementById('userInput'); |
|
|
const message = userInput.value.trim(); |
|
|
|
|
|
if (message === '' || selectedAgents.length === 0) return; |
|
|
|
|
|
|
|
|
addMessage('user', '당신', 'gray', 'user', message); |
|
|
userInput.value = ''; |
|
|
updateCharCount(); |
|
|
|
|
|
|
|
|
scrollChatToBottom(); |
|
|
|
|
|
|
|
|
simulateAgentResponses(message); |
|
|
} |
|
|
|
|
|
|
|
|
function simulateAgentResponses(userMessage) { |
|
|
const interactionEnabled = document.getElementById('agentInteraction').checked; |
|
|
const realtimeEnabled = document.getElementById('realtimeResponse').checked; |
|
|
|
|
|
|
|
|
conversationHistory.push({ |
|
|
sender: 'user', |
|
|
message: userMessage, |
|
|
timestamp: new Date().toISOString() |
|
|
}); |
|
|
|
|
|
|
|
|
selectedAgents.forEach((agentId, index) => { |
|
|
const agent = agents[agentId]; |
|
|
|
|
|
|
|
|
setTimeout(() => { |
|
|
|
|
|
if (interactionEnabled && index > 0) { |
|
|
const previousAgentId = selectedAgents[index-1]; |
|
|
const previousAgent = agents[previousAgentId]; |
|
|
|
|
|
|
|
|
const response = generateInteractiveResponse(agentId, previousAgentId, userMessage); |
|
|
addMessage('agent', agent.name, agent.color, agentId, response); |
|
|
|
|
|
|
|
|
conversationHistory.push({ |
|
|
sender: agentId, |
|
|
message: response, |
|
|
timestamp: new Date().toISOString() |
|
|
}); |
|
|
} else { |
|
|
|
|
|
const response = generateAgentResponse(agentId, userMessage); |
|
|
|
|
|
|
|
|
if (realtimeEnabled) { |
|
|
showTypingIndicator(agentId); |
|
|
|
|
|
setTimeout(() => { |
|
|
removeTypingIndicator(agentId); |
|
|
addMessage('agent', agent.name, agent.color, agentId, response); |
|
|
|
|
|
|
|
|
conversationHistory.push({ |
|
|
sender: agentId, |
|
|
message: response, |
|
|
timestamp: new Date().toISOString() |
|
|
}); |
|
|
|
|
|
scrollChatToBottom(); |
|
|
}, 1500 + Math.random() * 1000); |
|
|
} else { |
|
|
addMessage('agent', agent.name, agent.color, agentId, response); |
|
|
|
|
|
|
|
|
conversationHistory.push({ |
|
|
sender: agentId, |
|
|
message: response, |
|
|
timestamp: new Date().toISOString() |
|
|
}); |
|
|
|
|
|
scrollChatToBottom(); |
|
|
} |
|
|
} |
|
|
}, index * 500); |
|
|
}); |
|
|
} |
|
|
|
|
|
|
|
|
function generateAgentResponse(agentId, userMessage) { |
|
|
const agent = agents[agentId]; |
|
|
const responses = { |
|
|
analyst: [ |
|
|
`제가 분석한 결과, "${userMessage}"라는 주제는 몇 가지 핵심 요소로 나눌 수 있습니다. 첫째, 데이터 상으로는...`, |
|
|
`흥미로운 질문입니다. 제가 최근에 본 연구에 따르면, 이와 관련된 통계는...`, |
|
|
`저는 이 문제를 정량적으로 접근하는 것을 선호합니다. 측정 가능한 지표로 보면...` |
|
|
], |
|
|
creative: [ |
|
|
`와, "${userMessage}"라니 정말 영감을 주는 주제네요! 제 상상력이 즉시 활활 타오르는군요. 만약 우리가...`, |
|
|
`이 주제로 이런 아이디어는 어떨까요? [창의적인 제안]. 물론 이건 시작일 뿐이고 더 발전시킬 수 있어요!`, |
|
|
`제 머릿속에 재미있는 이미지가 떠오르네요. 이 주제를 색다른 각도에서 보면...` |
|
|
], |
|
|
debater: [ |
|
|
`논리적으로 접근해보자면, "${userMessage}"에 대한 주장에는 몇 가지 논점이 있습니다. 첫째로...`, |
|
|
`반대 의견을 제시해도 될까요? 왜냐하면... 물론 다른 관점도 있습니다.`, |
|
|
`이 문제를 양면에서 바라보는 것이 중요합니다. 한편으로는... 하지만 다른 한편으로는...` |
|
|
], |
|
|
advisor: [ |
|
|
`실용적인 조언을 드리자면, "${userMessage}"에 대해 다음 단계를 고려해보세요: 1) ... 2) ...`, |
|
|
`장기적인 관점에서, 이 문제를 해결하기 위한 전략은... 단기적으로는...`, |
|
|
`제 경험상, 이런 유형의 문제에는 이러한 접근 방식이 효과적이었습니다...` |
|
|
] |
|
|
}; |
|
|
|
|
|
|
|
|
const randomIndex = Math.floor(Math.random() * responses[agentId].length); |
|
|
return responses[agentId][randomIndex]; |
|
|
} |
|
|
|
|
|
|
|
|
function generateInteractiveResponse(agentId, previousAgentId, userMessage) { |
|
|
const agent = agents[agentId]; |
|
|
const previousAgent = agents[previousAgentId]; |
|
|
|
|
|
|
|
|
const interactionResponses = { |
|
|
analyst_creative: [ |
|
|
`[${previousAgent.name}]님의 창의적인 아이디어에 데이터를 더해보겠습니다. 통계적으로 보면 그 아이디어는...`, |
|
|
`창의성과 데이터는 좋은 조합입니다. ${previousAgent.name}님의 제안을 분석해보니...` |
|
|
], |
|
|
creative_debater: [ |
|
|
`[${previousAgent.name}]님의 논점은 흥미롭지만, 조금 더 파격적인 접근은 어떨까요? 예를 들어...`, |
|
|
`토론을 더 생동감 있게 만들기 위해 제안을 드리자면...` |
|
|
], |
|
|
debater_advisor: [ |
|
|
`[${previousAgent.name}]님의 논리적 지적은 타당합니다. 이를 바탕으로 실행 가능한 계획을 세운다면...`, |
|
|
`토론 내용을 실전에 적용하기 위한 구체적인 단계는...` |
|
|
], |
|
|
advisor_analyst: [ |
|
|
`[${previousAgent.name}]님의 조언을 데이터로 검증해보았습니다. 결과는...`, |
|
|
`전략적 제안을 수치화해보니 몇 가지 흥미로운 점이 발견되었습니다...` |
|
|
] |
|
|
}; |
|
|
|
|
|
const key = `${previousAgentId}_${agentId}`; |
|
|
if (interactionResponses[key]) { |
|
|
const randomIndex = Math.floor(Math.random() * interactionResponses[key].length); |
|
|
return interactionResponses[key][randomIndex]; |
|
|
} else { |
|
|
|
|
|
return generateAgentResponse(agentId, userMessage); |
|
|
} |
|
|
} |
|
|
|
|
|
|
|
|
function addMessage(sender, name, color, agentId, message) { |
|
|
const chatMessages = document.getElementById('chatMessages'); |
|
|
const messageDiv = document.createElement('div'); |
|
|
messageDiv.className = `message-animation flex ${sender === 'user' ? 'justify-end' : 'justify-start'}`; |
|
|
|
|
|
if (sender === 'user') { |
|
|
messageDiv.innerHTML = ` |
|
|
<div class="max-w-xs md:max-w-md lg:max-w-lg bg-gray-100 rounded-xl p-3"> |
|
|
<div class="text-xs text-gray-500 mb-1">${name}</div> |
|
|
<p>${message}</p> |
|
|
</div> |
|
|
`; |
|
|
} else { |
|
|
messageDiv.innerHTML = ` |
|
|
<div class="flex items-start"> |
|
|
<div class="w-8 h-8 rounded-full bg-${color}-200 flex items-center justify-center mr-2"> |
|
|
<i class="fas fa-${agents[agentId].icon} text-${color}-600"></i> |
|
|
</div> |
|
|
<div class="max-w-xs md:max-w-md lg:max-w-lg bg-${color}-50 rounded-xl p-3"> |
|
|
<div class="flex items-center"> |
|
|
<span class="font-medium text-${color}-800 mr-2">${name}</span> |
|
|
<span class="text-xs text-gray-500">${agents[agentId].description}</span> |
|
|
</div> |
|
|
<p class="mt-1">${message}</p> |
|
|
</div> |
|
|
</div> |
|
|
`; |
|
|
} |
|
|
|
|
|
chatMessages.appendChild(messageDiv); |
|
|
scrollChatToBottom(); |
|
|
} |
|
|
|
|
|
|
|
|
function showTypingIndicator(agentId) { |
|
|
const chatMessages = document.getElementById('chatMessages'); |
|
|
const agent = agents[agentId]; |
|
|
|
|
|
const typingDiv = document.createElement('div'); |
|
|
typingDiv.className = `flex justify-start typing-indicator-${agentId}`; |
|
|
typingDiv.innerHTML = ` |
|
|
<div class="flex items-start"> |
|
|
<div class="w-8 h-8 rounded-full bg-${agent.color}-200 flex items-center justify-center mr-2"> |
|
|
<i class="fas fa-${agent.icon} text-${agent.color}-600"></i> |
|
|
</div> |
|
|
<div class="bg-${agent.color}-50 rounded-xl p-3"> |
|
|
<div class="flex items-center"> |
|
|
<span class="font-medium text-${agent.color}-800 mr-2">${agent.name}</span> |
|
|
<span class="text-xs text-gray-500">${agent.description}</span> |
|
|
</div> |
|
|
<div class="typing-indicator mt-1"> |
|
|
<div class="typing-dot"></div> |
|
|
<div class="typing-dot"></div> |
|
|
<div class="typing-dot"></div> |
|
|
</div> |
|
|
</div> |
|
|
</div> |
|
|
`; |
|
|
|
|
|
chatMessages.appendChild(typingDiv); |
|
|
scrollChatToBottom(); |
|
|
} |
|
|
|
|
|
|
|
|
function removeTypingIndicator(agentId) { |
|
|
const indicators = document.querySelectorAll(`.typing-indicator-${agentId}`); |
|
|
indicators.forEach(indicator => indicator.remove()); |
|
|
} |
|
|
|
|
|
|
|
|
function scrollChatToBottom() { |
|
|
const chatContainer = document.getElementById('chatContainer'); |
|
|
chatContainer.scrollTop = chatContainer.scrollHeight; |
|
|
} |
|
|
|
|
|
|
|
|
document.getElementById('userInput').addEventListener('input', function() { |
|
|
updateCharCount(); |
|
|
}); |
|
|
|
|
|
function updateCharCount() { |
|
|
const input = document.getElementById('userInput'); |
|
|
const charCount = document.getElementById('charCount'); |
|
|
const count = input.value.length; |
|
|
charCount.textContent = count; |
|
|
|
|
|
if (count > 400) { |
|
|
charCount.classList.add('text-red-500'); |
|
|
charCount.classList.remove('text-gray-500'); |
|
|
} else { |
|
|
charCount.classList.remove('text-red-500'); |
|
|
charCount.classList.add('text-gray-500'); |
|
|
} |
|
|
} |
|
|
|
|
|
|
|
|
document.getElementById('userInput').addEventListener('keypress', function(e) { |
|
|
if (e.key === 'Enter') { |
|
|
sendMessage(); |
|
|
} |
|
|
}); |
|
|
</script> |
|
|
<p style="border-radius: 8px; text-align: center; font-size: 12px; color: #fff; margin-top: 16px;position: fixed; left: 8px; bottom: 8px; z-index: 10; background: rgba(0, 0, 0, 0.8); padding: 4px 8px;">Made with <img src="https://enzostvs-deepsite.hf.space/logo.svg" alt="DeepSite Logo" style="width: 16px; height: 16px; vertical-align: middle;display:inline-block;margin-right:3px;filter:brightness(0) invert(1);"><a href="https://enzostvs-deepsite.hf.space" style="color: #fff;text-decoration: underline;" target="_blank" >DeepSite</a> - 🧬 <a href="https://enzostvs-deepsite.hf.space?remix=appleorangejuice/multi-agent-chat" style="color: #fff;text-decoration: underline;" target="_blank" >Remix</a></p></body> |
|
|
</html> |