warp-agent 1.0.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.md +87 -0
- package/bin/warp-agent.js +69 -0
- package/package.json +40 -0
- package/public/app.js +320 -0
- package/public/camera.js +214 -0
- package/public/index.html +182 -0
- package/public/styles.css +626 -0
- package/server.js +81 -0
- package/src/jev-client.js +124 -0
- package/src/speedrun-engine.js +57 -0
package/public/camera.js
ADDED
|
@@ -0,0 +1,214 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Camera Bubble & Audio-Reactive Voice Ring Visualizer
|
|
3
|
+
* Streams user's webcam and animates an audio visualizer ring based on voice input.
|
|
4
|
+
*/
|
|
5
|
+
|
|
6
|
+
class CameraStudio {
|
|
7
|
+
constructor() {
|
|
8
|
+
this.videoEl = document.getElementById('webcamVideo');
|
|
9
|
+
this.canvasEl = document.getElementById('audioVisualizerRing');
|
|
10
|
+
this.ctx = this.canvasEl ? this.canvasEl.getContext('2d') : null;
|
|
11
|
+
this.placeholderEl = document.getElementById('cameraPlaceholder');
|
|
12
|
+
this.dockEl = document.getElementById('cameraDock');
|
|
13
|
+
|
|
14
|
+
this.camToggleBtn = document.getElementById('camToggleBtn');
|
|
15
|
+
this.micToggleBtn = document.getElementById('micToggleBtn');
|
|
16
|
+
this.dockCycleBtn = document.getElementById('dockCycleBtn');
|
|
17
|
+
|
|
18
|
+
this.stream = null;
|
|
19
|
+
this.audioCtx = null;
|
|
20
|
+
this.analyser = null;
|
|
21
|
+
this.dataArray = null;
|
|
22
|
+
this.isCamActive = false;
|
|
23
|
+
this.isMicActive = true;
|
|
24
|
+
this.dockPositions = ['dock-bottom-right', 'dock-bottom-left', 'dock-top-right'];
|
|
25
|
+
this.currentDockIndex = 0;
|
|
26
|
+
|
|
27
|
+
this.initListeners();
|
|
28
|
+
this.startSimulatedRing(); // subtle glow before mic permission
|
|
29
|
+
}
|
|
30
|
+
|
|
31
|
+
initListeners() {
|
|
32
|
+
if (this.placeholderEl) {
|
|
33
|
+
this.placeholderEl.addEventListener('click', () => this.enableWebcam());
|
|
34
|
+
}
|
|
35
|
+
if (this.camToggleBtn) {
|
|
36
|
+
this.camToggleBtn.addEventListener('click', () => this.toggleWebcam());
|
|
37
|
+
}
|
|
38
|
+
if (this.micToggleBtn) {
|
|
39
|
+
this.micToggleBtn.addEventListener('click', () => this.toggleMic());
|
|
40
|
+
}
|
|
41
|
+
if (this.dockCycleBtn) {
|
|
42
|
+
this.dockCycleBtn.addEventListener('click', () => this.cycleDockPosition());
|
|
43
|
+
}
|
|
44
|
+
}
|
|
45
|
+
|
|
46
|
+
async enableWebcam() {
|
|
47
|
+
try {
|
|
48
|
+
this.stream = await navigator.mediaDevices.getUserMedia({
|
|
49
|
+
video: { width: { ideal: 1280 }, height: { ideal: 720 } },
|
|
50
|
+
audio: true
|
|
51
|
+
});
|
|
52
|
+
|
|
53
|
+
this.videoEl.srcObject = this.stream;
|
|
54
|
+
this.isCamActive = true;
|
|
55
|
+
if (this.placeholderEl) this.placeholderEl.style.display = 'none';
|
|
56
|
+
if (this.camToggleBtn) this.camToggleBtn.classList.add('active');
|
|
57
|
+
|
|
58
|
+
this.initAudioVisualizer(this.stream);
|
|
59
|
+
} catch (err) {
|
|
60
|
+
console.warn('Webcam permission not granted or device unavailable:', err);
|
|
61
|
+
if (this.placeholderEl) {
|
|
62
|
+
this.placeholderEl.querySelector('.cam-hint').textContent = 'Camera Off (Click to Retry)';
|
|
63
|
+
}
|
|
64
|
+
}
|
|
65
|
+
}
|
|
66
|
+
|
|
67
|
+
toggleWebcam() {
|
|
68
|
+
if (!this.stream) {
|
|
69
|
+
this.enableWebcam();
|
|
70
|
+
return;
|
|
71
|
+
}
|
|
72
|
+
const videoTrack = this.stream.getVideoTracks()[0];
|
|
73
|
+
if (videoTrack) {
|
|
74
|
+
videoTrack.enabled = !videoTrack.enabled;
|
|
75
|
+
this.isCamActive = videoTrack.enabled;
|
|
76
|
+
this.camToggleBtn.classList.toggle('active', this.isCamActive);
|
|
77
|
+
this.placeholderEl.style.display = this.isCamActive ? 'none' : 'flex';
|
|
78
|
+
}
|
|
79
|
+
}
|
|
80
|
+
|
|
81
|
+
toggleMic() {
|
|
82
|
+
if (!this.stream) return;
|
|
83
|
+
const audioTrack = this.stream.getAudioTracks()[0];
|
|
84
|
+
if (audioTrack) {
|
|
85
|
+
audioTrack.enabled = !audioTrack.enabled;
|
|
86
|
+
this.isMicActive = audioTrack.enabled;
|
|
87
|
+
this.micToggleBtn.classList.toggle('active', this.isMicActive);
|
|
88
|
+
}
|
|
89
|
+
}
|
|
90
|
+
|
|
91
|
+
cycleDockPosition() {
|
|
92
|
+
this.dockEl.classList.remove(this.dockPositions[this.currentDockIndex]);
|
|
93
|
+
this.currentDockIndex = (this.currentDockIndex + 1) % this.dockPositions.length;
|
|
94
|
+
this.dockEl.classList.add(this.dockPositions[this.currentDockIndex]);
|
|
95
|
+
}
|
|
96
|
+
|
|
97
|
+
initAudioVisualizer(stream) {
|
|
98
|
+
try {
|
|
99
|
+
const AudioContext = window.AudioContext || window.webkitAudioContext;
|
|
100
|
+
this.audioCtx = new AudioContext();
|
|
101
|
+
const source = this.audioCtx.createMediaStreamSource(stream);
|
|
102
|
+
this.analyser = this.audioCtx.createAnalyser();
|
|
103
|
+
this.analyser.fftSize = 64;
|
|
104
|
+
source.connect(this.analyser);
|
|
105
|
+
|
|
106
|
+
const bufferLength = this.analyser.frequencyBinCount;
|
|
107
|
+
this.dataArray = new Uint8Array(bufferLength);
|
|
108
|
+
|
|
109
|
+
this.drawAudioRing();
|
|
110
|
+
} catch (e) {
|
|
111
|
+
console.warn('Web Audio Analyser not supported:', e);
|
|
112
|
+
}
|
|
113
|
+
}
|
|
114
|
+
|
|
115
|
+
drawAudioRing() {
|
|
116
|
+
if (!this.ctx || !this.analyser) return;
|
|
117
|
+
|
|
118
|
+
requestAnimationFrame(() => this.drawAudioRing());
|
|
119
|
+
|
|
120
|
+
this.analyser.getByteFrequencyData(this.dataArray);
|
|
121
|
+
|
|
122
|
+
const width = this.canvasEl.width;
|
|
123
|
+
const height = this.canvasEl.height;
|
|
124
|
+
const centerX = width / 2;
|
|
125
|
+
const centerY = height / 2;
|
|
126
|
+
const baseRadius = 96;
|
|
127
|
+
|
|
128
|
+
this.ctx.clearRect(0, 0, width, height);
|
|
129
|
+
|
|
130
|
+
// Calculate volume level from audio bins
|
|
131
|
+
let sum = 0;
|
|
132
|
+
for (let i = 0; i < this.dataArray.length; i++) {
|
|
133
|
+
sum += this.dataArray[i];
|
|
134
|
+
}
|
|
135
|
+
const avg = sum / this.dataArray.length; // 0 to 255
|
|
136
|
+
const volumeMultiplier = this.isMicActive ? (avg / 255) : 0;
|
|
137
|
+
|
|
138
|
+
// Draw audio-reactive radial spikes
|
|
139
|
+
const numBars = 32;
|
|
140
|
+
const angleStep = (Math.PI * 2) / numBars;
|
|
141
|
+
|
|
142
|
+
for (let i = 0; i < numBars; i++) {
|
|
143
|
+
const angle = i * angleStep;
|
|
144
|
+
const binIndex = i % this.dataArray.length;
|
|
145
|
+
const val = this.isMicActive ? (this.dataArray[binIndex] / 255) : (Math.sin(Date.now() * 0.003 + i) * 0.1 + 0.1);
|
|
146
|
+
const spikeLength = Math.max(3, val * 22);
|
|
147
|
+
|
|
148
|
+
const x1 = centerX + Math.cos(angle) * (baseRadius);
|
|
149
|
+
const y1 = centerY + Math.sin(angle) * (baseRadius);
|
|
150
|
+
const x2 = centerX + Math.cos(angle) * (baseRadius + spikeLength);
|
|
151
|
+
const y2 = centerY + Math.sin(angle) * (baseRadius + spikeLength);
|
|
152
|
+
|
|
153
|
+
this.ctx.beginPath();
|
|
154
|
+
this.ctx.moveTo(x1, y1);
|
|
155
|
+
this.ctx.lineTo(x2, y2);
|
|
156
|
+
this.ctx.lineWidth = 3;
|
|
157
|
+
this.ctx.lineCap = 'round';
|
|
158
|
+
|
|
159
|
+
// Color shifts from cyan to emerald based on voice loudness
|
|
160
|
+
this.ctx.strokeStyle = volumeMultiplier > 0.35
|
|
161
|
+
? `rgba(0, 255, 136, ${Math.min(1, 0.4 + val)})`
|
|
162
|
+
: `rgba(0, 240, 255, ${Math.min(1, 0.3 + val)})`;
|
|
163
|
+
|
|
164
|
+
this.ctx.stroke();
|
|
165
|
+
}
|
|
166
|
+
}
|
|
167
|
+
|
|
168
|
+
startSimulatedRing() {
|
|
169
|
+
// Idle glowing pulse before camera stream connects
|
|
170
|
+
const renderIdle = () => {
|
|
171
|
+
if (this.analyser) return; // Don't run once real audio is connected
|
|
172
|
+
if (!this.ctx) return;
|
|
173
|
+
|
|
174
|
+
const width = this.canvasEl.width;
|
|
175
|
+
const height = this.canvasEl.height;
|
|
176
|
+
const centerX = width / 2;
|
|
177
|
+
const centerY = height / 2;
|
|
178
|
+
const baseRadius = 96;
|
|
179
|
+
|
|
180
|
+
this.ctx.clearRect(0, 0, width, height);
|
|
181
|
+
|
|
182
|
+
const numBars = 32;
|
|
183
|
+
const angleStep = (Math.PI * 2) / numBars;
|
|
184
|
+
const t = Date.now() * 0.002;
|
|
185
|
+
|
|
186
|
+
for (let i = 0; i < numBars; i++) {
|
|
187
|
+
const angle = i * angleStep;
|
|
188
|
+
const val = (Math.sin(t + i * 0.4) + 1) * 0.5;
|
|
189
|
+
const spikeLength = 3 + val * 6;
|
|
190
|
+
|
|
191
|
+
const x1 = centerX + Math.cos(angle) * baseRadius;
|
|
192
|
+
const y1 = centerY + Math.sin(angle) * baseRadius;
|
|
193
|
+
const x2 = centerX + Math.cos(angle) * (baseRadius + spikeLength);
|
|
194
|
+
const y2 = centerY + Math.sin(angle) * (baseRadius + spikeLength);
|
|
195
|
+
|
|
196
|
+
this.ctx.beginPath();
|
|
197
|
+
this.ctx.moveTo(x1, y1);
|
|
198
|
+
this.ctx.lineTo(x2, y2);
|
|
199
|
+
this.ctx.lineWidth = 2;
|
|
200
|
+
this.ctx.lineCap = 'round';
|
|
201
|
+
this.ctx.strokeStyle = `rgba(0, 240, 255, ${0.2 + val * 0.4})`;
|
|
202
|
+
this.ctx.stroke();
|
|
203
|
+
}
|
|
204
|
+
|
|
205
|
+
requestAnimationFrame(renderIdle);
|
|
206
|
+
};
|
|
207
|
+
|
|
208
|
+
renderIdle();
|
|
209
|
+
}
|
|
210
|
+
}
|
|
211
|
+
|
|
212
|
+
document.addEventListener('DOMContentLoaded', () => {
|
|
213
|
+
window.cameraStudio = new CameraStudio();
|
|
214
|
+
});
|
|
@@ -0,0 +1,182 @@
|
|
|
1
|
+
<!DOCTYPE html>
|
|
2
|
+
<html lang="en">
|
|
3
|
+
<head>
|
|
4
|
+
<meta charset="UTF-8">
|
|
5
|
+
<meta name="viewport" content="width=device-width, initial-scale=1.0">
|
|
6
|
+
<title>WARP-AGENT // 60-FPS Autonomous Agent Studio</title>
|
|
7
|
+
<link rel="preconnect" href="https://fonts.googleapis.com">
|
|
8
|
+
<link rel="preconnect" href="https://fonts.gstatic.com" crossorigin>
|
|
9
|
+
<link href="https://fonts.googleapis.com/css2?family=Inter:wght@400;500;600;700;800;900&family=JetBrains+Mono:wght@400;500;700;800&display=swap" rel="stylesheet">
|
|
10
|
+
<link rel="stylesheet" href="styles.css">
|
|
11
|
+
</head>
|
|
12
|
+
<body>
|
|
13
|
+
<div class="studio-container" id="studioRoot">
|
|
14
|
+
<!-- Top Cyberpunk Bar -->
|
|
15
|
+
<header class="top-nav">
|
|
16
|
+
<div class="brand-cluster">
|
|
17
|
+
<div class="brand-logo">⚡</div>
|
|
18
|
+
<div>
|
|
19
|
+
<h1 class="brand-title">WARP-AGENT <span class="badge-system1">JEV SYSTEM 1 REFLEX</span></h1>
|
|
20
|
+
<p class="brand-subtitle">World's First 60-FPS Autonomous Coding Agent // Speedrun Visualizer Studio</p>
|
|
21
|
+
</div>
|
|
22
|
+
</div>
|
|
23
|
+
|
|
24
|
+
<div class="studio-controls">
|
|
25
|
+
<div class="scenario-picker">
|
|
26
|
+
<label for="taskSelect">MISSION:</label>
|
|
27
|
+
<select id="taskSelect">
|
|
28
|
+
<option value="Fix Concurrency Mutex Starvation across 20 Microservices">Fix Mutex Starvation across 20 Microservices</option>
|
|
29
|
+
<option value="Zero-Day Remote Code Execution AST Neutralization">Zero-Day RCE AST Neutralization</option>
|
|
30
|
+
<option value="Full-Stack SQL Injection Blast Radius Auto-Patch">Full-Stack SQL Injection Auto-Patch</option>
|
|
31
|
+
</select>
|
|
32
|
+
</div>
|
|
33
|
+
|
|
34
|
+
<button id="sfxToggle" class="btn-tool active" title="Toggle Procedural Audio FX">
|
|
35
|
+
<span id="sfxIcon">🔊</span> SFX: ON
|
|
36
|
+
</button>
|
|
37
|
+
|
|
38
|
+
<button id="fullscreenBtn" class="btn-tool" title="Maximize for Screen Recording">
|
|
39
|
+
⛶ STUDIO MODE
|
|
40
|
+
</button>
|
|
41
|
+
</div>
|
|
42
|
+
</header>
|
|
43
|
+
|
|
44
|
+
<!-- Speedrun Control Hero -->
|
|
45
|
+
<section class="speedrun-hero">
|
|
46
|
+
<div class="telemetry-bar">
|
|
47
|
+
<div class="stat-card">
|
|
48
|
+
<span class="stat-label">STOPWATCH</span>
|
|
49
|
+
<span class="stat-value text-cyan" id="heroStopwatch">00:00.000</span>
|
|
50
|
+
</div>
|
|
51
|
+
<div class="stat-card">
|
|
52
|
+
<span class="stat-label">WARP VELOCITY</span>
|
|
53
|
+
<span class="stat-value text-emerald" id="heroVelocity">0.0 <small>actions/s</small></span>
|
|
54
|
+
</div>
|
|
55
|
+
<div class="stat-card">
|
|
56
|
+
<span class="stat-label">AVG LATENCY</span>
|
|
57
|
+
<span class="stat-value text-yellow" id="heroLatency">0ms</span>
|
|
58
|
+
</div>
|
|
59
|
+
<div class="stat-card">
|
|
60
|
+
<span class="stat-label">AGENT SPEEDUP</span>
|
|
61
|
+
<span class="stat-value text-purple" id="heroSpeedup">100x</span>
|
|
62
|
+
</div>
|
|
63
|
+
</div>
|
|
64
|
+
|
|
65
|
+
<div class="cta-actions">
|
|
66
|
+
<button id="startRaceBtn" class="btn-warp">
|
|
67
|
+
<span class="pulse-spark"></span>
|
|
68
|
+
⚡ START 60-FPS SPEEDRUN
|
|
69
|
+
</button>
|
|
70
|
+
<button id="resetRaceBtn" class="btn-reset">
|
|
71
|
+
↺ RESET ARENA
|
|
72
|
+
</button>
|
|
73
|
+
</div>
|
|
74
|
+
</section>
|
|
75
|
+
|
|
76
|
+
<!-- The Side-by-Side Arena -->
|
|
77
|
+
<main class="arena-grid">
|
|
78
|
+
<!-- LEFT: Legacy Sluggish LLM Agent -->
|
|
79
|
+
<section class="arena-panel legacy-panel">
|
|
80
|
+
<div class="panel-header">
|
|
81
|
+
<div class="header-tag tag-legacy">
|
|
82
|
+
<span class="dot-red"></span> LEGACY 70B LLM AGENT (Devin / Claude 3.5 / GPT-4o)
|
|
83
|
+
</div>
|
|
84
|
+
<div class="panel-metrics">
|
|
85
|
+
<span id="legacyTimer" class="metric-timer">00:00.0</span>
|
|
86
|
+
<span id="legacyCost" class="metric-cost">$0.00</span>
|
|
87
|
+
</div>
|
|
88
|
+
</div>
|
|
89
|
+
|
|
90
|
+
<div class="progress-track">
|
|
91
|
+
<div id="legacyProgressBar" class="progress-bar-fill fill-red" style="width: 0%;"></div>
|
|
92
|
+
</div>
|
|
93
|
+
|
|
94
|
+
<div class="agent-status-box">
|
|
95
|
+
<div id="legacySpinner" class="spinner-idle">⏳</div>
|
|
96
|
+
<div class="status-meta">
|
|
97
|
+
<div id="legacyStatusText" class="status-heading">Awaiting Mission Launch...</div>
|
|
98
|
+
<div id="legacySubText" class="status-sub">Heavy 70B parameter inference: ~4,200ms per tool decision</div>
|
|
99
|
+
</div>
|
|
100
|
+
</div>
|
|
101
|
+
|
|
102
|
+
<div class="stream-console" id="legacyConsole">
|
|
103
|
+
<div class="log-entry log-dim">[00:00.000] Initializing LangChain / AutoGen agent loop...</div>
|
|
104
|
+
</div>
|
|
105
|
+
</section>
|
|
106
|
+
|
|
107
|
+
<!-- RIGHT: WARP-AGENT Powered by Jev System 1 -->
|
|
108
|
+
<section class="arena-panel warp-panel">
|
|
109
|
+
<div class="panel-header">
|
|
110
|
+
<div class="header-tag tag-warp">
|
|
111
|
+
<span class="dot-emerald"></span> WARP-AGENT (Jev System 1 Reflex Engine)
|
|
112
|
+
</div>
|
|
113
|
+
<div class="panel-metrics">
|
|
114
|
+
<span id="warpTimer" class="metric-timer text-emerald">00:00.000</span>
|
|
115
|
+
<span id="warpCost" class="metric-cost text-cyan">$0.0000</span>
|
|
116
|
+
</div>
|
|
117
|
+
</div>
|
|
118
|
+
|
|
119
|
+
<div class="progress-track">
|
|
120
|
+
<div id="warpProgressBar" class="progress-bar-fill fill-emerald" style="width: 0%;"></div>
|
|
121
|
+
</div>
|
|
122
|
+
|
|
123
|
+
<div class="agent-status-box warp-active-box">
|
|
124
|
+
<div class="gauge-ring">
|
|
125
|
+
<span id="warpStepCount" class="gauge-number">0/48</span>
|
|
126
|
+
</div>
|
|
127
|
+
<div class="status-meta">
|
|
128
|
+
<div id="warpStatusText" class="status-heading text-emerald">System 1 Reflex Subconscious Ready</div>
|
|
129
|
+
<div id="warpSubText" class="status-sub">Target Latency: <30ms // Zero LLM Hallucinations</div>
|
|
130
|
+
</div>
|
|
131
|
+
</div>
|
|
132
|
+
|
|
133
|
+
<div class="stream-console warp-stream" id="warpConsole">
|
|
134
|
+
<div class="log-entry log-dim">[00:00.000] Subconscious neural reflex ready for instant execution...</div>
|
|
135
|
+
</div>
|
|
136
|
+
</section>
|
|
137
|
+
</main>
|
|
138
|
+
|
|
139
|
+
<!-- Victory Overlay Modal -->
|
|
140
|
+
<div class="victory-banner" id="victoryBanner">
|
|
141
|
+
<div class="victory-content">
|
|
142
|
+
<div class="victory-badge">⚡ MISSION SPEEDRUN COMPLETED IN 1.34s</div>
|
|
143
|
+
<div class="victory-stats">
|
|
144
|
+
<div class="stat-pill"><span class="label">WARP TIME:</span> <strong>1.34s (48 Actions)</strong></div>
|
|
145
|
+
<div class="stat-pill"><span class="label">LEGACY ESTIMATE:</span> <strong class="text-red">182.4s (3+ min)</strong></div>
|
|
146
|
+
<div class="stat-pill"><span class="label">COST REDUCTION:</span> <strong class="text-emerald">99.4% SAVED ($0.0003 vs $1.44)</strong></div>
|
|
147
|
+
</div>
|
|
148
|
+
</div>
|
|
149
|
+
</div>
|
|
150
|
+
|
|
151
|
+
<!-- FLOATING WEBCAM BUBBLE FOR RECORDING -->
|
|
152
|
+
<div class="camera-dock dock-bottom-right" id="cameraDock">
|
|
153
|
+
<div class="camera-canvas-wrapper">
|
|
154
|
+
<!-- Audio Reactive Waveform Ring Canvas -->
|
|
155
|
+
<canvas id="audioVisualizerRing" width="220" height="220"></canvas>
|
|
156
|
+
|
|
157
|
+
<!-- Live Video Feed -->
|
|
158
|
+
<video id="webcamVideo" autoplay playsinline muted></video>
|
|
159
|
+
|
|
160
|
+
<!-- Placeholder when Camera is off -->
|
|
161
|
+
<div id="cameraPlaceholder" class="camera-placeholder">
|
|
162
|
+
<div class="cam-avatar">🎙️</div>
|
|
163
|
+
<div class="cam-hint">Click to Enable Camera</div>
|
|
164
|
+
</div>
|
|
165
|
+
|
|
166
|
+
<!-- Camera HUD Ring Controls -->
|
|
167
|
+
<div class="camera-controls-overlay">
|
|
168
|
+
<button id="camToggleBtn" class="cam-btn" title="Toggle Webcam">📹</button>
|
|
169
|
+
<button id="micToggleBtn" class="cam-btn active" title="Toggle Mic Visualizer">🎙️</button>
|
|
170
|
+
<button id="dockCycleBtn" class="cam-btn" title="Cycle Dock Corner">🔄</button>
|
|
171
|
+
</div>
|
|
172
|
+
</div>
|
|
173
|
+
<div class="presenter-tag">
|
|
174
|
+
<span class="live-dot"></span> PRESENTER
|
|
175
|
+
</div>
|
|
176
|
+
</div>
|
|
177
|
+
</div>
|
|
178
|
+
|
|
179
|
+
<script type="module" src="camera.js"></script>
|
|
180
|
+
<script type="module" src="app.js"></script>
|
|
181
|
+
</body>
|
|
182
|
+
</html>
|