300 lines
7.8 KiB
HTML
300 lines
7.8 KiB
HTML
<!DOCTYPE html>
|
|
<html lang="en">
|
|
<head>
|
|
<meta charset="UTF-8">
|
|
<meta name="viewport" content="width=device-width, initial-scale=1.0">
|
|
<title>Realtime Demo</title>
|
|
<style>
|
|
* {
|
|
margin: 0;
|
|
padding: 0;
|
|
box-sizing: border-box;
|
|
}
|
|
|
|
body {
|
|
font-family: -apple-system, BlinkMacSystemFont, 'Segoe UI', Roboto, sans-serif;
|
|
background: #f8f9fa;
|
|
height: 100vh;
|
|
display: flex;
|
|
flex-direction: column;
|
|
}
|
|
|
|
.header {
|
|
background: white;
|
|
padding: 1rem;
|
|
border-bottom: 1px solid #e1e5e9;
|
|
display: flex;
|
|
justify-content: space-between;
|
|
align-items: center;
|
|
}
|
|
|
|
.connect-btn {
|
|
padding: 0.5rem 1rem;
|
|
border: none;
|
|
border-radius: 6px;
|
|
cursor: pointer;
|
|
font-weight: 500;
|
|
transition: background-color 0.2s;
|
|
}
|
|
|
|
.connect-btn.disconnected {
|
|
background: #0066cc;
|
|
color: white;
|
|
}
|
|
|
|
.connect-btn.connected {
|
|
background: #dc3545;
|
|
color: white;
|
|
}
|
|
|
|
.connect-btn:hover {
|
|
opacity: 0.9;
|
|
}
|
|
|
|
.main {
|
|
flex: 1;
|
|
display: flex;
|
|
gap: 1rem;
|
|
padding: 1rem;
|
|
height: calc(100vh - 80px);
|
|
}
|
|
|
|
.messages-pane {
|
|
flex: 2;
|
|
background: white;
|
|
border-radius: 8px;
|
|
display: flex;
|
|
flex-direction: column;
|
|
overflow: hidden;
|
|
}
|
|
|
|
.messages-header {
|
|
padding: 1rem;
|
|
border-bottom: 1px solid #e1e5e9;
|
|
font-weight: 600;
|
|
}
|
|
|
|
.messages-content {
|
|
flex: 1;
|
|
overflow-y: auto;
|
|
padding: 1rem;
|
|
}
|
|
|
|
.message {
|
|
margin-bottom: 1rem;
|
|
display: flex;
|
|
}
|
|
|
|
.message.user {
|
|
justify-content: flex-end;
|
|
}
|
|
|
|
.message.assistant {
|
|
justify-content: flex-start;
|
|
}
|
|
|
|
.message-bubble {
|
|
max-width: 70%;
|
|
padding: 0.75rem 1rem;
|
|
border-radius: 18px;
|
|
word-wrap: break-word;
|
|
}
|
|
|
|
.message.user .message-bubble {
|
|
background: #0066cc;
|
|
color: white;
|
|
}
|
|
|
|
.message.assistant .message-bubble {
|
|
background: #f1f3f4;
|
|
color: #333;
|
|
}
|
|
|
|
.right-column {
|
|
flex: 1;
|
|
display: flex;
|
|
flex-direction: column;
|
|
gap: 1rem;
|
|
}
|
|
|
|
.events-pane {
|
|
flex: 2;
|
|
background: white;
|
|
border-radius: 8px;
|
|
display: flex;
|
|
flex-direction: column;
|
|
overflow: hidden;
|
|
}
|
|
|
|
.tools-pane {
|
|
flex: 1;
|
|
background: white;
|
|
border-radius: 8px;
|
|
display: flex;
|
|
flex-direction: column;
|
|
overflow: hidden;
|
|
}
|
|
|
|
.events-header, .tools-header {
|
|
padding: 1rem;
|
|
border-bottom: 1px solid #e1e5e9;
|
|
font-weight: 600;
|
|
}
|
|
|
|
.events-content, .tools-content {
|
|
flex: 1;
|
|
overflow-y: auto;
|
|
padding: 0.5rem;
|
|
}
|
|
|
|
.event {
|
|
border: 1px solid #e1e5e9;
|
|
border-radius: 6px;
|
|
margin-bottom: 0.5rem;
|
|
}
|
|
|
|
.event-header {
|
|
padding: 0.75rem;
|
|
background: #f8f9fa;
|
|
cursor: pointer;
|
|
display: flex;
|
|
justify-content: space-between;
|
|
align-items: center;
|
|
font-family: monospace;
|
|
font-size: 0.85rem;
|
|
}
|
|
|
|
.event-header:hover {
|
|
background: #e9ecef;
|
|
}
|
|
|
|
.tools-content .event-header {
|
|
cursor: default;
|
|
font-family: -apple-system, BlinkMacSystemFont, 'Segoe UI', Roboto, sans-serif;
|
|
}
|
|
|
|
.tools-content .event-header.handoff {
|
|
background: #f3e8ff;
|
|
border-left: 4px solid #8b5cf6;
|
|
}
|
|
|
|
.tools-content .event-header.tool {
|
|
background: #fef3e2;
|
|
border-left: 4px solid #f59e0b;
|
|
}
|
|
|
|
.event-content {
|
|
padding: 0.75rem;
|
|
background: white;
|
|
border-top: 1px solid #e1e5e9;
|
|
font-family: monospace;
|
|
font-size: 0.8rem;
|
|
white-space: pre-wrap;
|
|
max-height: 200px;
|
|
overflow-y: auto;
|
|
}
|
|
|
|
.event-content.collapsed {
|
|
display: none;
|
|
}
|
|
|
|
.controls {
|
|
padding: 1rem;
|
|
border-top: 1px solid #e1e5e9;
|
|
background: #f8f9fa;
|
|
display: flex;
|
|
gap: 0.5rem;
|
|
align-items: center;
|
|
}
|
|
|
|
.mute-btn {
|
|
padding: 0.5rem 1rem;
|
|
border: none;
|
|
border-radius: 6px;
|
|
cursor: pointer;
|
|
font-weight: 500;
|
|
transition: all 0.2s;
|
|
}
|
|
|
|
.mute-btn.unmuted {
|
|
background: #28a745;
|
|
color: white;
|
|
}
|
|
|
|
.mute-btn.muted {
|
|
background: #dc3545;
|
|
color: white;
|
|
}
|
|
|
|
.mute-btn.active {
|
|
animation: pulse 1s infinite;
|
|
}
|
|
|
|
@keyframes pulse {
|
|
0% { opacity: 1; }
|
|
50% { opacity: 0.7; }
|
|
100% { opacity: 1; }
|
|
}
|
|
|
|
.status {
|
|
font-size: 0.9rem;
|
|
color: #6c757d;
|
|
}
|
|
|
|
.connected {
|
|
color: #28a745;
|
|
}
|
|
|
|
.disconnected {
|
|
color: #dc3545;
|
|
}
|
|
</style>
|
|
</head>
|
|
<body>
|
|
<div class="header">
|
|
<h1>Realtime Demo</h1>
|
|
<button id="connectBtn" class="connect-btn disconnected">Connect</button>
|
|
</div>
|
|
|
|
<div class="main">
|
|
<div class="messages-pane">
|
|
<div class="messages-header">
|
|
Conversation
|
|
</div>
|
|
<div id="messagesContent" class="messages-content">
|
|
<!-- Messages will appear here -->
|
|
</div>
|
|
<div class="controls">
|
|
<button id="muteBtn" class="mute-btn unmuted" disabled>🎤 Mic On</button>
|
|
<input id="imagePrompt" type="text" placeholder="Optional prompt for image" style="flex: 1; padding: 0.5rem; border: 1px solid #e1e5e9; border-radius: 6px;" />
|
|
<input id="imageInput" type="file" accept="image/*" aria-hidden="true" style="position:absolute;left:-9999px;width:1px;height:1px;opacity:0;" />
|
|
<button id="imageBtn" type="button" class="mute-btn unmuted" style="background:#6f42c1; user-select:none;">🖼️ Send Image</button>
|
|
<span id="status" class="status disconnected">Disconnected</span>
|
|
</div>
|
|
</div>
|
|
|
|
<div class="right-column">
|
|
<div class="events-pane">
|
|
<div class="events-header">
|
|
Event stream
|
|
</div>
|
|
<div id="eventsContent" class="events-content">
|
|
<!-- Events will appear here -->
|
|
</div>
|
|
</div>
|
|
|
|
<div class="tools-pane">
|
|
<div class="tools-header">
|
|
Tools & Handoffs
|
|
</div>
|
|
<div id="toolsContent" class="tools-content">
|
|
<!-- Tools and handoffs will appear here -->
|
|
</div>
|
|
</div>
|
|
</div>
|
|
</div>
|
|
|
|
<script src="app.js"></script>
|
|
</body>
|
|
</html>
|