295 lines
8.8 KiB
HTML
295 lines
8.8 KiB
HTML
<!DOCTYPE html>
|
|
<html lang="pt-BR">
|
|
|
|
<head>
|
|
<meta charset="UTF-8">
|
|
<meta name="viewport" content="width=device-width, initial-scale=1.0">
|
|
<title>Teste de Streaming A2A</title>
|
|
<link rel="icon" href="data:,">
|
|
<style>
|
|
:root {
|
|
--primary-color: #2563eb;
|
|
--secondary-color: #1e40af;
|
|
--background-color: #f8fafc;
|
|
--text-color: #1e293b;
|
|
--border-color: #e2e8f0;
|
|
}
|
|
|
|
* {
|
|
margin: 0;
|
|
padding: 0;
|
|
box-sizing: border-box;
|
|
}
|
|
|
|
body {
|
|
font-family: 'Segoe UI', Tahoma, Geneva, Verdana, sans-serif;
|
|
background-color: var(--background-color);
|
|
color: var(--text-color);
|
|
line-height: 1.6;
|
|
padding: 20px;
|
|
}
|
|
|
|
.container {
|
|
max-width: 800px;
|
|
margin: 0 auto;
|
|
background: white;
|
|
border-radius: 8px;
|
|
box-shadow: 0 2px 4px rgba(0, 0, 0, 0.1);
|
|
padding: 20px;
|
|
}
|
|
|
|
h1 {
|
|
color: var(--primary-color);
|
|
margin-bottom: 20px;
|
|
text-align: center;
|
|
}
|
|
|
|
.form-group {
|
|
margin-bottom: 20px;
|
|
}
|
|
|
|
label {
|
|
display: block;
|
|
margin-bottom: 5px;
|
|
font-weight: 600;
|
|
}
|
|
|
|
input[type="text"] {
|
|
width: 100%;
|
|
padding: 10px;
|
|
border: 1px solid var(--border-color);
|
|
border-radius: 4px;
|
|
font-size: 16px;
|
|
}
|
|
|
|
button {
|
|
background-color: var(--primary-color);
|
|
color: white;
|
|
border: none;
|
|
padding: 10px 20px;
|
|
border-radius: 4px;
|
|
cursor: pointer;
|
|
font-size: 16px;
|
|
transition: background-color 0.3s;
|
|
}
|
|
|
|
button:hover {
|
|
background-color: var(--secondary-color);
|
|
}
|
|
|
|
.chat-container {
|
|
margin-top: 20px;
|
|
border: 1px solid var(--border-color);
|
|
border-radius: 4px;
|
|
height: 400px;
|
|
overflow-y: auto;
|
|
padding: 10px;
|
|
}
|
|
|
|
.message {
|
|
margin-bottom: 10px;
|
|
padding: 10px;
|
|
border-radius: 4px;
|
|
max-width: 80%;
|
|
}
|
|
|
|
.user-message {
|
|
background-color: #e3f2fd;
|
|
margin-left: auto;
|
|
}
|
|
|
|
.agent-message {
|
|
background-color: #f3f4f6;
|
|
}
|
|
|
|
.status-message {
|
|
background-color: #fef3c7;
|
|
text-align: center;
|
|
font-style: italic;
|
|
}
|
|
|
|
.error-message {
|
|
background-color: #fee2e2;
|
|
color: #dc2626;
|
|
}
|
|
|
|
.controls {
|
|
display: flex;
|
|
gap: 10px;
|
|
margin-top: 20px;
|
|
}
|
|
|
|
.status {
|
|
margin-top: 10px;
|
|
padding: 10px;
|
|
border-radius: 4px;
|
|
background-color: #f3f4f6;
|
|
font-size: 14px;
|
|
}
|
|
</style>
|
|
</head>
|
|
|
|
<body>
|
|
<div class="container">
|
|
<h1>Teste de Streaming A2A</h1>
|
|
|
|
<div class="form-group">
|
|
<label for="agentId">Agent ID:</label>
|
|
<input type="text" id="agentId" placeholder="Digite o ID do agente">
|
|
</div>
|
|
|
|
<div class="form-group">
|
|
<label for="apiKey">API Key:</label>
|
|
<input type="text" id="apiKey" placeholder="Digite sua API Key">
|
|
</div>
|
|
|
|
<div class="form-group">
|
|
<label for="message">Mensagem:</label>
|
|
<input type="text" id="message" placeholder="Digite sua mensagem">
|
|
</div>
|
|
|
|
<div class="controls">
|
|
<button onclick="startStreaming()">Iniciar Streaming</button>
|
|
<button onclick="stopStreaming()">Parar Streaming</button>
|
|
</div>
|
|
|
|
<div class="status" id="connectionStatus">
|
|
Status: Não conectado
|
|
</div>
|
|
|
|
<div class="chat-container" id="chatContainer">
|
|
<!-- Mensagens serão adicionadas aqui -->
|
|
</div>
|
|
</div>
|
|
|
|
<script>
|
|
let controller = null;
|
|
const chatContainer = document.getElementById('chatContainer');
|
|
const statusElement = document.getElementById('connectionStatus');
|
|
|
|
function addMessage(content, type = 'agent') {
|
|
const messageDiv = document.createElement('div');
|
|
messageDiv.className = `message ${type}-message`;
|
|
messageDiv.textContent = content;
|
|
chatContainer.appendChild(messageDiv);
|
|
chatContainer.scrollTop = chatContainer.scrollHeight;
|
|
}
|
|
|
|
function updateStatus(status) {
|
|
statusElement.textContent = `Status: ${status}`;
|
|
}
|
|
|
|
async function startStreaming() {
|
|
const agentId = document.getElementById('agentId').value;
|
|
const apiKey = document.getElementById('apiKey').value;
|
|
const message = document.getElementById('message').value;
|
|
|
|
if (!agentId || !apiKey || !message) {
|
|
alert('Por favor, preencha todos os campos');
|
|
return;
|
|
}
|
|
|
|
// Limpa o chat
|
|
chatContainer.innerHTML = '';
|
|
addMessage('Iniciando conexão...', 'status');
|
|
|
|
// Configura o payload
|
|
const payload = {
|
|
jsonrpc: "2.0",
|
|
id: "1",
|
|
method: "tasks/sendSubscribe",
|
|
params: {
|
|
id: "test-task",
|
|
message: {
|
|
role: "user",
|
|
parts: [{
|
|
type: "text",
|
|
text: message
|
|
}]
|
|
}
|
|
}
|
|
};
|
|
|
|
try {
|
|
// Cria um novo AbortController para controlar o streaming
|
|
controller = new AbortController();
|
|
const signal = controller.signal;
|
|
|
|
// Faz a requisição POST com streaming
|
|
const response = await fetch(
|
|
`http://${window.location.host}/api/v1/agents/${agentId}/tasks/sendSubscribe`, {
|
|
method: 'POST',
|
|
headers: {
|
|
'Content-Type': 'application/json',
|
|
'Accept': 'text/event-stream',
|
|
'X-API-Key': apiKey
|
|
},
|
|
body: JSON.stringify(payload),
|
|
signal
|
|
});
|
|
|
|
if (!response.ok) {
|
|
throw new Error(`HTTP error! status: ${response.status}`);
|
|
}
|
|
|
|
updateStatus('Conectado');
|
|
addMessage('Conexão estabelecida', 'status');
|
|
|
|
// Lê o stream de dados
|
|
const reader = response.body.getReader();
|
|
const decoder = new TextDecoder();
|
|
|
|
while (true) {
|
|
const {
|
|
done,
|
|
value
|
|
} = await reader.read();
|
|
if (done) break;
|
|
|
|
// Decodifica o chunk de dados
|
|
const chunk = decoder.decode(value);
|
|
|
|
// Processa cada linha do chunk
|
|
const lines = chunk.split('\n');
|
|
for (const line of lines) {
|
|
if (line.startsWith('data:')) {
|
|
try {
|
|
const data = JSON.parse(line.slice(5));
|
|
|
|
if (data.state) {
|
|
// Evento de status
|
|
addMessage(`Estado: ${data.state}`, 'status');
|
|
} else if (data.content) {
|
|
// Evento de conteúdo
|
|
addMessage(data.content, 'agent');
|
|
}
|
|
} catch (error) {
|
|
addMessage('Erro ao processar mensagem: ' + error, 'error');
|
|
}
|
|
}
|
|
}
|
|
}
|
|
|
|
} catch (error) {
|
|
if (error.name === 'AbortError') {
|
|
updateStatus('Desconectado');
|
|
addMessage('Conexão encerrada pelo usuário', 'status');
|
|
} else {
|
|
updateStatus('Erro');
|
|
addMessage('Erro ao iniciar streaming: ' + error.message, 'error');
|
|
}
|
|
}
|
|
}
|
|
|
|
function stopStreaming() {
|
|
if (controller) {
|
|
controller.abort();
|
|
controller = null;
|
|
updateStatus('Desconectado');
|
|
addMessage('Conexão encerrada', 'status');
|
|
}
|
|
}
|
|
</script>
|
|
</body>
|
|
|
|
</html> |