Spaces:
Sleeping
Sleeping
cleaned up the codebase
Browse files- api/supabase_client.py +3 -3
- frontend/src/App.jsx +82 -112
- scripts/reset_db.sql +24 -0
api/supabase_client.py
CHANGED
|
@@ -259,13 +259,13 @@ def test_client():
|
|
| 259 |
|
| 260 |
# Health check
|
| 261 |
if client.health_check():
|
| 262 |
-
print("
|
| 263 |
else:
|
| 264 |
-
print("
|
| 265 |
|
| 266 |
# Try to get runs
|
| 267 |
runs = client.get_all_runs()
|
| 268 |
-
print(f"
|
| 269 |
|
| 270 |
except ValueError as e:
|
| 271 |
print(f"Configuration error: {e}")
|
|
|
|
| 259 |
|
| 260 |
# Health check
|
| 261 |
if client.health_check():
|
| 262 |
+
print("[OK] Connection healthy")
|
| 263 |
else:
|
| 264 |
+
print("[FAIL] Connection failed")
|
| 265 |
|
| 266 |
# Try to get runs
|
| 267 |
runs = client.get_all_runs()
|
| 268 |
+
print(f"[OK] Retrieved {len(runs)} runs")
|
| 269 |
|
| 270 |
except ValueError as e:
|
| 271 |
print(f"Configuration error: {e}")
|
frontend/src/App.jsx
CHANGED
|
@@ -14,14 +14,6 @@ function App() {
|
|
| 14 |
const [activeTab, setActiveTab] = useState('dashboard')
|
| 15 |
const [terminalLogs, setTerminalLogs] = useState([])
|
| 16 |
const [isTerminalConnected, setIsTerminalConnected] = useState(false)
|
| 17 |
-
const [darkMode, setDarkMode] = useState(() => {
|
| 18 |
-
const saved = localStorage.getItem('darkMode')
|
| 19 |
-
return saved ? JSON.parse(saved) : false
|
| 20 |
-
})
|
| 21 |
-
|
| 22 |
-
useEffect(() => {
|
| 23 |
-
localStorage.setItem('darkMode', JSON.stringify(darkMode))
|
| 24 |
-
}, [darkMode])
|
| 25 |
|
| 26 |
useEffect(() => {
|
| 27 |
fetchRuns()
|
|
@@ -86,11 +78,11 @@ function App() {
|
|
| 86 |
const actions = runDetail.actions || []
|
| 87 |
actions.forEach((action, i) => {
|
| 88 |
const actionEmoji = {
|
| 89 |
-
'swap': '
|
| 90 |
-
'provide_liquidity': '
|
| 91 |
-
'propose_alliance': '
|
| 92 |
-
'do_nothing': '
|
| 93 |
-
}[action.action_type] || '
|
| 94 |
|
| 95 |
logs.push(`%c[AGENT]%c ${action.agent_name} > Turn ${action.turn}: ${actionEmoji} ${action.action_type}`)
|
| 96 |
if (action.reasoning) {
|
|
@@ -122,48 +114,36 @@ function App() {
|
|
| 122 |
}
|
| 123 |
|
| 124 |
return (
|
| 125 |
-
<div className=
|
| 126 |
{/* Header */}
|
| 127 |
-
<header className=
|
| 128 |
<div className="max-w-6xl mx-auto flex justify-between items-center">
|
| 129 |
<div className="flex items-center gap-3">
|
| 130 |
-
<svg width="36" height="36" viewBox="0 0 100 100" className=
|
| 131 |
-
<circle cx="50" cy="50" r="45" fill="currentColor" className=
|
| 132 |
<circle cx="35" cy="45" r="12" className="text-green-500"/>
|
| 133 |
<circle cx="65" cy="45" r="12" className="text-green-500"/>
|
| 134 |
<circle cx="50" cy="70" r="12" className="text-green-500"/>
|
| 135 |
-
<line x1="35" y1="45" x2="65" y2="45" stroke="currentColor" strokeWidth="4" className=
|
| 136 |
-
<line x1="35" y1="45" x2="50" y2="70" stroke="currentColor" strokeWidth="4" className=
|
| 137 |
-
<line x1="65" y1="45" x2="50" y2="70" stroke="currentColor" strokeWidth="4" className=
|
| 138 |
</svg>
|
| 139 |
-
<h1 className=
|
| 140 |
-
</div>
|
| 141 |
-
<div className="flex gap-4 items-center">
|
| 142 |
-
<span className={`text-sm ${trends ? 'text-green-500' : 'text-red-500'}`}>
|
| 143 |
-
{trends ? 'Connected' : 'Disconnected'}
|
| 144 |
-
</span>
|
| 145 |
-
<button
|
| 146 |
-
onClick={() => setDarkMode(!darkMode)}
|
| 147 |
-
className={`px-3 py-1.5 rounded text-sm ${
|
| 148 |
-
darkMode
|
| 149 |
-
? 'bg-slate-700 text-white hover:bg-slate-600'
|
| 150 |
-
: 'bg-slate-200 text-slate-800 hover:bg-slate-300'
|
| 151 |
-
}`}
|
| 152 |
-
>
|
| 153 |
-
{darkMode ? 'Light' : 'Dark'}
|
| 154 |
-
</button>
|
| 155 |
</div>
|
|
|
|
|
|
|
|
|
|
| 156 |
</div>
|
| 157 |
</header>
|
| 158 |
|
| 159 |
{/* Tabs */}
|
| 160 |
-
<div className=
|
| 161 |
<button
|
| 162 |
onClick={() => setActiveTab('dashboard')}
|
| 163 |
className={`pb-3 px-4 text-sm font-medium border-b-2 transition-colors ${
|
| 164 |
activeTab === 'dashboard'
|
| 165 |
-
?
|
| 166 |
-
:
|
| 167 |
}`}
|
| 168 |
>
|
| 169 |
Dashboard
|
|
@@ -172,8 +152,8 @@ function App() {
|
|
| 172 |
onClick={() => setActiveTab('terminal')}
|
| 173 |
className={`pb-3 px-4 text-sm font-medium border-b-2 transition-colors ${
|
| 174 |
activeTab === 'terminal'
|
| 175 |
-
?
|
| 176 |
-
:
|
| 177 |
}`}
|
| 178 |
>
|
| 179 |
Terminal
|
|
@@ -184,19 +164,15 @@ function App() {
|
|
| 184 |
{activeTab === 'dashboard' ? (
|
| 185 |
<>
|
| 186 |
{/* Refresh Section */}
|
| 187 |
-
<section className=
|
| 188 |
<div className="flex justify-between items-center">
|
| 189 |
-
<h2 className=
|
| 190 |
<button
|
| 191 |
onClick={() => {
|
| 192 |
fetchRuns()
|
| 193 |
fetchTrends()
|
| 194 |
}}
|
| 195 |
-
className=
|
| 196 |
-
darkMode
|
| 197 |
-
? 'bg-slate-700 text-white hover:bg-slate-600'
|
| 198 |
-
: 'bg-slate-800 text-white hover:bg-slate-700'
|
| 199 |
-
}`}
|
| 200 |
>
|
| 201 |
Refresh
|
| 202 |
</button>
|
|
@@ -205,65 +181,65 @@ function App() {
|
|
| 205 |
|
| 206 |
{/* Trends Section */}
|
| 207 |
{trends && (
|
| 208 |
-
<section className=
|
| 209 |
-
<h2 className=
|
| 210 |
<div className="grid grid-cols-4 gap-4">
|
| 211 |
-
<div className=
|
| 212 |
-
<div className=
|
| 213 |
-
<div className=
|
| 214 |
</div>
|
| 215 |
-
<div className=
|
| 216 |
-
<div className=
|
| 217 |
-
<div className=
|
| 218 |
</div>
|
| 219 |
-
<div className=
|
| 220 |
-
<div className=
|
| 221 |
-
<div className=
|
| 222 |
</div>
|
| 223 |
-
<div className=
|
| 224 |
-
<div className=
|
| 225 |
-
<div className=
|
| 226 |
</div>
|
| 227 |
</div>
|
| 228 |
</section>
|
| 229 |
)}
|
| 230 |
|
| 231 |
{/* Runs List */}
|
| 232 |
-
<section className=
|
| 233 |
-
<h2 className=
|
| 234 |
{runs.length === 0 ? (
|
| 235 |
-
<p className=
|
| 236 |
) : (
|
| 237 |
<div className="overflow-x-auto">
|
| 238 |
<table className="w-full">
|
| 239 |
<thead>
|
| 240 |
-
<tr className=
|
| 241 |
-
<th className=
|
| 242 |
-
<th className=
|
| 243 |
-
<th className=
|
| 244 |
-
<th className=
|
| 245 |
</tr>
|
| 246 |
</thead>
|
| 247 |
<tbody>
|
| 248 |
{runs.map((run) => (
|
| 249 |
-
<tr key={run.id} className=
|
| 250 |
-
<td className=
|
| 251 |
<td className="py-2 px-3">
|
| 252 |
<span className={`px-2 py-1 rounded text-xs ${
|
| 253 |
run.status === 'completed'
|
| 254 |
-
?
|
| 255 |
-
:
|
| 256 |
}`}>
|
| 257 |
{run.status}
|
| 258 |
</span>
|
| 259 |
</td>
|
| 260 |
-
<td className=
|
| 261 |
{new Date(run.start_time).toLocaleString()}
|
| 262 |
</td>
|
| 263 |
<td className="py-2 px-3">
|
| 264 |
<button
|
| 265 |
onClick={() => selectRun(run.id)}
|
| 266 |
-
className=
|
| 267 |
>
|
| 268 |
View
|
| 269 |
</button>
|
|
@@ -278,53 +254,53 @@ function App() {
|
|
| 278 |
|
| 279 |
{/* Run Detail */}
|
| 280 |
{selectedRun && (
|
| 281 |
-
<section className=
|
| 282 |
<div className="flex justify-between items-center mb-4">
|
| 283 |
-
<h2 className=
|
| 284 |
-
<button onClick={() => setSelectedRun(null)} className=
|
| 285 |
Close
|
| 286 |
</button>
|
| 287 |
</div>
|
| 288 |
|
| 289 |
{selectedRun.metrics && (
|
| 290 |
<div className="grid grid-cols-3 gap-4 mb-6">
|
| 291 |
-
<div className=
|
| 292 |
-
<div className=
|
| 293 |
-
<div className=
|
| 294 |
</div>
|
| 295 |
-
<div className=
|
| 296 |
-
<div className=
|
| 297 |
-
<div className=
|
| 298 |
</div>
|
| 299 |
-
<div className=
|
| 300 |
-
<div className=
|
| 301 |
-
<div className=
|
| 302 |
</div>
|
| 303 |
</div>
|
| 304 |
)}
|
| 305 |
|
| 306 |
-
<h3 className=
|
| 307 |
<div className="overflow-x-auto">
|
| 308 |
<table className="w-full">
|
| 309 |
<thead>
|
| 310 |
-
<tr className=
|
| 311 |
-
<th className=
|
| 312 |
-
<th className=
|
| 313 |
-
<th className=
|
| 314 |
-
<th className=
|
| 315 |
-
<th className=
|
| 316 |
</tr>
|
| 317 |
</thead>
|
| 318 |
<tbody>
|
| 319 |
{(selectedRun.agents || []).map((agent, i) => (
|
| 320 |
-
<tr key={i} className=
|
| 321 |
-
<td className=
|
| 322 |
-
<td className=
|
| 323 |
-
<td className=
|
| 324 |
<td className={`py-2 px-3 ${agent.profit >= 0 ? 'text-green-500' : 'text-red-500'}`}>
|
| 325 |
{agent.profit?.toFixed(2)}
|
| 326 |
</td>
|
| 327 |
-
<td className=
|
| 328 |
</tr>
|
| 329 |
))}
|
| 330 |
</tbody>
|
|
@@ -335,9 +311,9 @@ function App() {
|
|
| 335 |
</>
|
| 336 |
) : (
|
| 337 |
/* Terminal Tab - Retro Style */
|
| 338 |
-
<div className=
|
| 339 |
<div className="flex justify-between items-center mb-4">
|
| 340 |
-
<h2 className=
|
| 341 |
<div className="flex gap-4 items-center">
|
| 342 |
<span className={`flex items-center gap-2 text-sm ${isTerminalConnected ? 'text-green-500' : 'text-red-500'}`}>
|
| 343 |
<span className={`w-2 h-2 rounded-full ${isTerminalConnected ? 'bg-green-500' : 'bg-red-500'}`}></span>
|
|
@@ -345,11 +321,7 @@ function App() {
|
|
| 345 |
</span>
|
| 346 |
<button
|
| 347 |
onClick={() => fetchLatestRunForTerminal()}
|
| 348 |
-
className=
|
| 349 |
-
darkMode
|
| 350 |
-
? 'bg-slate-700 text-white hover:bg-slate-600'
|
| 351 |
-
: 'bg-slate-200 text-slate-800 hover:bg-slate-300'
|
| 352 |
-
}`}
|
| 353 |
>
|
| 354 |
Load Latest
|
| 355 |
</button>
|
|
@@ -357,10 +329,8 @@ function App() {
|
|
| 357 |
</div>
|
| 358 |
|
| 359 |
{/* Retro Terminal */}
|
| 360 |
-
<div className=
|
| 361 |
-
|
| 362 |
-
}`}>
|
| 363 |
-
<pre className={`${darkMode ? 'text-green-400' : 'text-green-400'}`}>
|
| 364 |
{terminalLogs.length === 0 ? (
|
| 365 |
<span className="opacity-50">No simulation data loaded. Click "Load Latest" to view agent activity.</span>
|
| 366 |
) : (
|
|
@@ -382,7 +352,7 @@ function App() {
|
|
| 382 |
</pre>
|
| 383 |
</div>
|
| 384 |
|
| 385 |
-
<div className=
|
| 386 |
Tip: Select a run from the Dashboard to view its terminal logs
|
| 387 |
</div>
|
| 388 |
</div>
|
|
|
|
| 14 |
const [activeTab, setActiveTab] = useState('dashboard')
|
| 15 |
const [terminalLogs, setTerminalLogs] = useState([])
|
| 16 |
const [isTerminalConnected, setIsTerminalConnected] = useState(false)
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 17 |
|
| 18 |
useEffect(() => {
|
| 19 |
fetchRuns()
|
|
|
|
| 78 |
const actions = runDetail.actions || []
|
| 79 |
actions.forEach((action, i) => {
|
| 80 |
const actionEmoji = {
|
| 81 |
+
'swap': '<->',
|
| 82 |
+
'provide_liquidity': '~',
|
| 83 |
+
'propose_alliance': '=',
|
| 84 |
+
'do_nothing': 'z'
|
| 85 |
+
}[action.action_type] || '.'
|
| 86 |
|
| 87 |
logs.push(`%c[AGENT]%c ${action.agent_name} > Turn ${action.turn}: ${actionEmoji} ${action.action_type}`)
|
| 88 |
if (action.reasoning) {
|
|
|
|
| 114 |
}
|
| 115 |
|
| 116 |
return (
|
| 117 |
+
<div className="min-h-screen bg-slate-900">
|
| 118 |
{/* Header */}
|
| 119 |
+
<header className="bg-slate-800 border-slate-700 border-b px-6 py-4">
|
| 120 |
<div className="max-w-6xl mx-auto flex justify-between items-center">
|
| 121 |
<div className="flex items-center gap-3">
|
| 122 |
+
<svg width="36" height="36" viewBox="0 0 100 100" className="opacity-90">
|
| 123 |
+
<circle cx="50" cy="50" r="45" fill="currentColor" className="text-slate-700"/>
|
| 124 |
<circle cx="35" cy="45" r="12" className="text-green-500"/>
|
| 125 |
<circle cx="65" cy="45" r="12" className="text-green-500"/>
|
| 126 |
<circle cx="50" cy="70" r="12" className="text-green-500"/>
|
| 127 |
+
<line x1="35" y1="45" x2="65" y2="45" stroke="currentColor" strokeWidth="4" className="text-slate-800"/>
|
| 128 |
+
<line x1="35" y1="45" x2="50" y2="70" stroke="currentColor" strokeWidth="4" className="text-slate-800"/>
|
| 129 |
+
<line x1="65" y1="45" x2="50" y2="70" stroke="currentColor" strokeWidth="4" className="text-slate-800"/>
|
| 130 |
</svg>
|
| 131 |
+
<h1 className="text-xl font-semibold text-white">DeFi Agent Arena</h1>
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 132 |
</div>
|
| 133 |
+
<span className={`text-sm ${trends ? 'text-green-500' : 'text-red-500'}`}>
|
| 134 |
+
{trends ? 'Connected' : 'Disconnected'}
|
| 135 |
+
</span>
|
| 136 |
</div>
|
| 137 |
</header>
|
| 138 |
|
| 139 |
{/* Tabs */}
|
| 140 |
+
<div className="max-w-6xl mx-auto px-6 pt-6 flex gap-4 border-b border-slate-700">
|
| 141 |
<button
|
| 142 |
onClick={() => setActiveTab('dashboard')}
|
| 143 |
className={`pb-3 px-4 text-sm font-medium border-b-2 transition-colors ${
|
| 144 |
activeTab === 'dashboard'
|
| 145 |
+
? 'border-green-500 text-white'
|
| 146 |
+
: 'border-transparent text-slate-400 hover:text-white'
|
| 147 |
}`}
|
| 148 |
>
|
| 149 |
Dashboard
|
|
|
|
| 152 |
onClick={() => setActiveTab('terminal')}
|
| 153 |
className={`pb-3 px-4 text-sm font-medium border-b-2 transition-colors ${
|
| 154 |
activeTab === 'terminal'
|
| 155 |
+
? 'border-green-500 text-white'
|
| 156 |
+
: 'border-transparent text-slate-400 hover:text-white'
|
| 157 |
}`}
|
| 158 |
>
|
| 159 |
Terminal
|
|
|
|
| 164 |
{activeTab === 'dashboard' ? (
|
| 165 |
<>
|
| 166 |
{/* Refresh Section */}
|
| 167 |
+
<section className="bg-slate-800 border-slate-700 rounded-lg border p-6 mb-8">
|
| 168 |
<div className="flex justify-between items-center">
|
| 169 |
+
<h2 className="text-lg font-medium text-white">Simulation Data</h2>
|
| 170 |
<button
|
| 171 |
onClick={() => {
|
| 172 |
fetchRuns()
|
| 173 |
fetchTrends()
|
| 174 |
}}
|
| 175 |
+
className="px-6 py-2 rounded bg-slate-700 text-white hover:bg-slate-600"
|
|
|
|
|
|
|
|
|
|
|
|
|
| 176 |
>
|
| 177 |
Refresh
|
| 178 |
</button>
|
|
|
|
| 181 |
|
| 182 |
{/* Trends Section */}
|
| 183 |
{trends && (
|
| 184 |
+
<section className="bg-slate-800 border-slate-700 rounded-lg border p-6 mb-8">
|
| 185 |
+
<h2 className="text-lg font-medium text-white mb-4">Trends</h2>
|
| 186 |
<div className="grid grid-cols-4 gap-4">
|
| 187 |
+
<div className="bg-slate-700 rounded p-4">
|
| 188 |
+
<div className="text-sm text-slate-400">Total Runs</div>
|
| 189 |
+
<div className="text-2xl font-semibold text-white">{trends.run_count}</div>
|
| 190 |
</div>
|
| 191 |
+
<div className="bg-slate-700 rounded p-4">
|
| 192 |
+
<div className="text-sm text-slate-400">Avg Profit</div>
|
| 193 |
+
<div className="text-2xl font-semibold text-white">{trends.avg_profit?.toFixed(2) || 0}</div>
|
| 194 |
</div>
|
| 195 |
+
<div className="bg-slate-700 rounded p-4">
|
| 196 |
+
<div className="text-sm text-slate-400">Avg Inequality</div>
|
| 197 |
+
<div className="text-2xl font-semibold text-white">{(trends.avg_gini * 100).toFixed(1)}%</div>
|
| 198 |
</div>
|
| 199 |
+
<div className="bg-slate-700 rounded p-4">
|
| 200 |
+
<div className="text-sm text-slate-400">Profit Trend</div>
|
| 201 |
+
<div className="text-2xl font-semibold text-white capitalize">{trends.profit_trend}</div>
|
| 202 |
</div>
|
| 203 |
</div>
|
| 204 |
</section>
|
| 205 |
)}
|
| 206 |
|
| 207 |
{/* Runs List */}
|
| 208 |
+
<section className="bg-slate-800 border-slate-700 rounded-lg border p-6 mb-8">
|
| 209 |
+
<h2 className="text-lg font-medium text-white mb-4">Runs</h2>
|
| 210 |
{runs.length === 0 ? (
|
| 211 |
+
<p className="text-slate-400">No runs yet.</p>
|
| 212 |
) : (
|
| 213 |
<div className="overflow-x-auto">
|
| 214 |
<table className="w-full">
|
| 215 |
<thead>
|
| 216 |
+
<tr className="border-b border-slate-700 text-left">
|
| 217 |
+
<th className="py-2 px-3 text-sm font-medium text-slate-400">Run</th>
|
| 218 |
+
<th className="py-2 px-3 text-sm font-medium text-slate-400">Status</th>
|
| 219 |
+
<th className="py-2 px-3 text-sm font-medium text-slate-400">Started</th>
|
| 220 |
+
<th className="py-2 px-3 text-sm font-medium text-slate-400">Action</th>
|
| 221 |
</tr>
|
| 222 |
</thead>
|
| 223 |
<tbody>
|
| 224 |
{runs.map((run) => (
|
| 225 |
+
<tr key={run.id} className="border-b border-slate-700">
|
| 226 |
+
<td className="py-2 px-3 text-white">#{run.run_number}</td>
|
| 227 |
<td className="py-2 px-3">
|
| 228 |
<span className={`px-2 py-1 rounded text-xs ${
|
| 229 |
run.status === 'completed'
|
| 230 |
+
? 'bg-green-900 text-green-300'
|
| 231 |
+
: 'bg-yellow-900 text-yellow-300'
|
| 232 |
}`}>
|
| 233 |
{run.status}
|
| 234 |
</span>
|
| 235 |
</td>
|
| 236 |
+
<td className="py-2 px-3 text-sm text-slate-400">
|
| 237 |
{new Date(run.start_time).toLocaleString()}
|
| 238 |
</td>
|
| 239 |
<td className="py-2 px-3">
|
| 240 |
<button
|
| 241 |
onClick={() => selectRun(run.id)}
|
| 242 |
+
className="text-sm text-blue-400 hover:text-blue-300"
|
| 243 |
>
|
| 244 |
View
|
| 245 |
</button>
|
|
|
|
| 254 |
|
| 255 |
{/* Run Detail */}
|
| 256 |
{selectedRun && (
|
| 257 |
+
<section className="bg-slate-800 border-slate-700 rounded-lg border p-6">
|
| 258 |
<div className="flex justify-between items-center mb-4">
|
| 259 |
+
<h2 className="text-lg font-medium text-white">Run Details</h2>
|
| 260 |
+
<button onClick={() => setSelectedRun(null)} className="text-slate-400 hover:text-white">
|
| 261 |
Close
|
| 262 |
</button>
|
| 263 |
</div>
|
| 264 |
|
| 265 |
{selectedRun.metrics && (
|
| 266 |
<div className="grid grid-cols-3 gap-4 mb-6">
|
| 267 |
+
<div className="bg-slate-700 rounded p-4">
|
| 268 |
+
<div className="text-sm text-slate-400">Gini Coefficient</div>
|
| 269 |
+
<div className="text-xl font-semibold text-white">{selectedRun.metrics.gini_coefficient?.toFixed(4)}</div>
|
| 270 |
</div>
|
| 271 |
+
<div className="bg-slate-700 rounded p-4">
|
| 272 |
+
<div className="text-sm text-slate-400">Avg Profit</div>
|
| 273 |
+
<div className="text-xl font-semibold text-white">{selectedRun.metrics.avg_agent_profit?.toFixed(2)}</div>
|
| 274 |
</div>
|
| 275 |
+
<div className="bg-slate-700 rounded p-4">
|
| 276 |
+
<div className="text-sm text-slate-400">Cooperation Rate</div>
|
| 277 |
+
<div className="text-xl font-semibold text-white">{selectedRun.metrics.cooperation_rate?.toFixed(2)}</div>
|
| 278 |
</div>
|
| 279 |
</div>
|
| 280 |
)}
|
| 281 |
|
| 282 |
+
<h3 className="font-medium text-white mb-3">Agents</h3>
|
| 283 |
<div className="overflow-x-auto">
|
| 284 |
<table className="w-full">
|
| 285 |
<thead>
|
| 286 |
+
<tr className="border-b border-slate-700 text-left">
|
| 287 |
+
<th className="py-2 px-3 text-sm font-medium text-slate-400">Agent</th>
|
| 288 |
+
<th className="py-2 px-3 text-sm font-medium text-slate-400">Token A</th>
|
| 289 |
+
<th className="py-2 px-3 text-sm font-medium text-slate-400">Token B</th>
|
| 290 |
+
<th className="py-2 px-3 text-sm font-medium text-slate-400">Profit</th>
|
| 291 |
+
<th className="py-2 px-3 text-sm font-medium text-slate-400">Strategy</th>
|
| 292 |
</tr>
|
| 293 |
</thead>
|
| 294 |
<tbody>
|
| 295 |
{(selectedRun.agents || []).map((agent, i) => (
|
| 296 |
+
<tr key={i} className="border-b border-slate-700">
|
| 297 |
+
<td className="py-2 px-3 text-white">{agent.name}</td>
|
| 298 |
+
<td className="py-2 px-3 text-slate-300">{agent.token_a?.toFixed(2)}</td>
|
| 299 |
+
<td className="py-2 px-3 text-slate-300">{agent.token_b?.toFixed(2)}</td>
|
| 300 |
<td className={`py-2 px-3 ${agent.profit >= 0 ? 'text-green-500' : 'text-red-500'}`}>
|
| 301 |
{agent.profit?.toFixed(2)}
|
| 302 |
</td>
|
| 303 |
+
<td className="py-2 px-3 text-slate-300">{agent.strategy}</td>
|
| 304 |
</tr>
|
| 305 |
))}
|
| 306 |
</tbody>
|
|
|
|
| 311 |
</>
|
| 312 |
) : (
|
| 313 |
/* Terminal Tab - Retro Style */
|
| 314 |
+
<div className="bg-slate-800 border-slate-700 rounded-lg border p-6">
|
| 315 |
<div className="flex justify-between items-center mb-4">
|
| 316 |
+
<h2 className="text-lg font-medium text-white">Agent Terminal</h2>
|
| 317 |
<div className="flex gap-4 items-center">
|
| 318 |
<span className={`flex items-center gap-2 text-sm ${isTerminalConnected ? 'text-green-500' : 'text-red-500'}`}>
|
| 319 |
<span className={`w-2 h-2 rounded-full ${isTerminalConnected ? 'bg-green-500' : 'bg-red-500'}`}></span>
|
|
|
|
| 321 |
</span>
|
| 322 |
<button
|
| 323 |
onClick={() => fetchLatestRunForTerminal()}
|
| 324 |
+
className="px-4 py-1.5 rounded text-sm bg-slate-700 text-white hover:bg-slate-600"
|
|
|
|
|
|
|
|
|
|
|
|
|
| 325 |
>
|
| 326 |
Load Latest
|
| 327 |
</button>
|
|
|
|
| 329 |
</div>
|
| 330 |
|
| 331 |
{/* Retro Terminal */}
|
| 332 |
+
<div className="font-mono text-sm p-4 rounded-lg overflow-y-auto max-h-[600px] bg-slate-950">
|
| 333 |
+
<pre className="text-green-400">
|
|
|
|
|
|
|
| 334 |
{terminalLogs.length === 0 ? (
|
| 335 |
<span className="opacity-50">No simulation data loaded. Click "Load Latest" to view agent activity.</span>
|
| 336 |
) : (
|
|
|
|
| 352 |
</pre>
|
| 353 |
</div>
|
| 354 |
|
| 355 |
+
<div className="mt-4 text-xs text-slate-500">
|
| 356 |
Tip: Select a run from the Dashboard to view its terminal logs
|
| 357 |
</div>
|
| 358 |
</div>
|
scripts/reset_db.sql
ADDED
|
@@ -0,0 +1,24 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 1 |
+
-- Wipe all test data and reset for public launch
|
| 2 |
+
-- Run this in Supabase SQL Editor
|
| 3 |
+
|
| 4 |
+
-- 1. Delete all data (order matters due to foreign keys)
|
| 5 |
+
DELETE FROM run_metrics;
|
| 6 |
+
DELETE FROM actions;
|
| 7 |
+
DELETE FROM pool_states;
|
| 8 |
+
DELETE FROM agent_states;
|
| 9 |
+
DELETE FROM agent_learning;
|
| 10 |
+
DELETE FROM runs;
|
| 11 |
+
|
| 12 |
+
-- 2. Reset sequence (PostgreSQL)
|
| 13 |
+
ALTER SEQUENCE runs_id_seq RESTART WITH 1;
|
| 14 |
+
|
| 15 |
+
-- 3. Verify
|
| 16 |
+
SELECT COUNT(*) as remaining_runs FROM runs;
|
| 17 |
+
|
| 18 |
+
-- 4. Insert a placeholder run to start fresh
|
| 19 |
+
INSERT INTO runs (run_number, status, config)
|
| 20 |
+
VALUES (0, 'completed', '{"initialized": true}'::jsonb)
|
| 21 |
+
ON CONFLICT DO NOTHING;
|
| 22 |
+
|
| 23 |
+
-- 5. Get next run number (should be 1)
|
| 24 |
+
SELECT get_next_run_number() as next_run;
|