AE-Shree commited on
Commit
7186ef8
·
1 Parent(s): 0b1db59

Final Change

Browse files
frontend/dist/index.html CHANGED
@@ -4,7 +4,7 @@
4
  <meta charset="UTF-8" />
5
  <meta name="viewport" content="width=device-width, initial-scale=1.0" />
6
  <title>CLM Dashboard</title>
7
- <script type="module" crossorigin src="/assets/index-DPHOn9DW.js"></script>
8
  <link rel="stylesheet" crossorigin href="/assets/index-DHB-7DK0.css">
9
  </head>
10
  <body style="margin:0;background:#f1f5f9">
 
4
  <meta charset="UTF-8" />
5
  <meta name="viewport" content="width=device-width, initial-scale=1.0" />
6
  <title>CLM Dashboard</title>
7
+ <script type="module" crossorigin src="/assets/index-CPBwWvcP.js"></script>
8
  <link rel="stylesheet" crossorigin href="/assets/index-DHB-7DK0.css">
9
  </head>
10
  <body style="margin:0;background:#f1f5f9">
frontend/src/App.jsx CHANGED
@@ -18,7 +18,7 @@ class ErrorBoundary extends React.Component {
18
  <div style={{ background: '#fef2f2', border: '1px solid #fca5a5',
19
  borderRadius: 12, padding: 24, margin: 24, fontFamily: 'system-ui,sans-serif' }}>
20
  <div style={{ fontSize: 18, fontWeight: 800, color: '#dc2626', marginBottom: 8 }}>
21
- ⚠️ The dashboard hit a render error
22
  </div>
23
  <div style={{ fontSize: 13, color: '#7f1d1d', marginBottom: 12,
24
  fontFamily: 'monospace', background: '#fff', padding: 12, borderRadius: 8,
@@ -28,7 +28,7 @@ class ErrorBoundary extends React.Component {
28
  <button onClick={() => this.setState({ error: null })}
29
  style={{ background: '#dc2626', color: '#fff', border: 'none',
30
  borderRadius: 8, padding: '10px 18px', fontWeight: 700, cursor: 'pointer' }}>
31
- Reset Dashboard
32
  </button>
33
  </div>
34
  )
@@ -38,51 +38,74 @@ class ErrorBoundary extends React.Component {
38
  }
39
 
40
  export default function App() {
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
41
  return (
42
- <div style={{ minHeight: '100vh', background: '#f1f5f9', fontFamily: 'system-ui,sans-serif' }}>
43
- {/* ── Header ── */}
 
 
44
  <header style={{
45
- background: '#0f172a', position: 'sticky', top: 0, zIndex: 20,
46
  display: 'flex', alignItems: 'center', gap: 32, padding: '0 24px',
47
- boxShadow: '0 1px 3px rgba(0,0,0,.4)',
 
48
  }}>
49
- <div style={{ padding: '14px 0', whiteSpace: 'nowrap' }}>
50
- <span style={{ fontSize: 19, fontWeight: 800, color: '#fff', letterSpacing: '-0.5px' }}>
51
- 🧠 CLM
 
52
  </span>
53
- <span style={{ fontSize: 12, color: '#64748b', marginLeft: 10 }}>
54
- Cognitive Load Manager · OpenEnv
55
  </span>
56
  </div>
57
 
58
- <div style={{ flex: 1, display: 'flex', alignItems: 'center' }}>
59
- <span style={{ fontSize: 13, color: '#6366f1', fontWeight: 700,
60
- background: '#1e293b', borderRadius: 8, padding: '8px 16px' }}>
61
- 🎮 Live Episode
62
- </span>
63
- </div>
 
64
 
65
  <a href="/docs" target="_blank" rel="noreferrer"
66
- style={{ fontSize: 12, color: '#475569', textDecoration: 'none',
67
- padding: '6px 12px', border: '1px solid #334155', borderRadius: 6,
68
  whiteSpace: 'nowrap' }}>
69
- API Docs
70
  </a>
71
  </header>
72
 
73
- {/* ── Banner ── */}
74
  <div style={{
75
- background: 'linear-gradient(135deg,#4f46e5 0%,#0ea5e9 100%)',
76
  padding: '10px 24px', textAlign: 'center', fontSize: 13, color: '#fff',
77
  }}>
78
- 🤖 AI agent plays live — press <b>Play Episode</b> to start streaming.
79
- Switch to <b>🎮 Manual</b> to control the agent yourself.
80
  </div>
81
 
82
- {/* ── Content ── */}
83
  <main style={{ maxWidth: 1400, margin: '0 auto', padding: 24 }}>
84
  <ErrorBoundary>
85
- <Dashboard />
86
  </ErrorBoundary>
87
  </main>
88
  </div>
 
18
  <div style={{ background: '#fef2f2', border: '1px solid #fca5a5',
19
  borderRadius: 12, padding: 24, margin: 24, fontFamily: 'system-ui,sans-serif' }}>
20
  <div style={{ fontSize: 18, fontWeight: 800, color: '#dc2626', marginBottom: 8 }}>
21
+ The dashboard hit a render error
22
  </div>
23
  <div style={{ fontSize: 13, color: '#7f1d1d', marginBottom: 12,
24
  fontFamily: 'monospace', background: '#fff', padding: 12, borderRadius: 8,
 
28
  <button onClick={() => this.setState({ error: null })}
29
  style={{ background: '#dc2626', color: '#fff', border: 'none',
30
  borderRadius: 8, padding: '10px 18px', fontWeight: 700, cursor: 'pointer' }}>
31
+ Reset Dashboard
32
  </button>
33
  </div>
34
  )
 
38
  }
39
 
40
  export default function App() {
41
+ const [theme, setTheme] = React.useState(() => {
42
+ if (typeof window === 'undefined') return 'light'
43
+ return localStorage.getItem('clm-theme') || 'light'
44
+ })
45
+
46
+ React.useEffect(() => {
47
+ try { localStorage.setItem('clm-theme', theme) } catch {}
48
+ }, [theme])
49
+
50
+ const isDark = theme === 'dark'
51
+ const palette = isDark
52
+ ? { bg: '#0b1220', headerBg: '#0f172a', headerBorder: '#1e293b',
53
+ text: '#e2e8f0', subText: '#94a3b8', border: '#334155',
54
+ bannerFrom: '#1e3a8a', bannerTo: '#0c4a6e' }
55
+ : { bg: '#f1f5f9', headerBg: '#ffffff', headerBorder: '#e2e8f0',
56
+ text: '#0f172a', subText: '#64748b', border: '#cbd5e1',
57
+ bannerFrom: '#4f46e5', bannerTo: '#0ea5e9' }
58
+
59
  return (
60
+ <div style={{ minHeight: '100vh', background: palette.bg,
61
+ fontFamily: 'system-ui,sans-serif', color: palette.text,
62
+ transition: 'background .25s ease, color .25s ease' }}>
63
+ {/* Header */}
64
  <header style={{
65
+ background: palette.headerBg, position: 'sticky', top: 0, zIndex: 20,
66
  display: 'flex', alignItems: 'center', gap: 32, padding: '0 24px',
67
+ borderBottom: `1px solid ${palette.headerBorder}`,
68
+ boxShadow: isDark ? '0 1px 3px rgba(0,0,0,.5)' : '0 1px 3px rgba(15,23,42,.06)',
69
  }}>
70
+ <div style={{ padding: '14px 0', whiteSpace: 'nowrap', flex: 1 }}>
71
+ <span style={{ fontSize: 18, fontWeight: 800, color: palette.text,
72
+ letterSpacing: '-0.4px' }}>
73
+ Cognitive Load Manager
74
  </span>
75
+ <span style={{ fontSize: 12, color: palette.subText, marginLeft: 10 }}>
76
+ OpenEnv
77
  </span>
78
  </div>
79
 
80
+ <button onClick={() => setTheme(isDark ? 'light' : 'dark')}
81
+ style={{ fontSize: 12, color: palette.text, background: 'transparent',
82
+ padding: '6px 14px', border: `1px solid ${palette.border}`,
83
+ borderRadius: 6, cursor: 'pointer', fontWeight: 600,
84
+ whiteSpace: 'nowrap' }}>
85
+ {isDark ? 'Light' : 'Dark'} mode
86
+ </button>
87
 
88
  <a href="/docs" target="_blank" rel="noreferrer"
89
+ style={{ fontSize: 12, color: palette.subText, textDecoration: 'none',
90
+ padding: '6px 12px', border: `1px solid ${palette.border}`, borderRadius: 6,
91
  whiteSpace: 'nowrap' }}>
92
+ API Docs
93
  </a>
94
  </header>
95
 
96
+ {/* Banner */}
97
  <div style={{
98
+ background: `linear-gradient(135deg,${palette.bannerFrom} 0%,${palette.bannerTo} 100%)`,
99
  padding: '10px 24px', textAlign: 'center', fontSize: 13, color: '#fff',
100
  }}>
101
+ AI agent plays live — press <b>Play Episode</b> to start streaming.
102
+ Switch to <b>Manual</b> to control the agent yourself.
103
  </div>
104
 
105
+ {/* Content */}
106
  <main style={{ maxWidth: 1400, margin: '0 auto', padding: 24 }}>
107
  <ErrorBoundary>
108
+ <Dashboard isDark={isDark} />
109
  </ErrorBoundary>
110
  </main>
111
  </div>
frontend/src/components/Dashboard.jsx CHANGED
@@ -122,7 +122,7 @@ function ScoringFormulaCard() {
122
 
123
  <div style={{ marginBottom:16 }}>
124
  <div style={{ fontSize:14, fontWeight:800, color:'#0f172a', marginBottom:4 }}>
125
- 🏆 Reward Scoring Formula
126
  </div>
127
  <div style={{ fontSize:11, color:'#64748b' }}>
128
  Each action is scored on 5 dimensions. Weights reflect cognitive-load research priorities.
@@ -318,7 +318,7 @@ export default function Dashboard() {
318
  // When the server closes the stream after a clean episode end, the browser
319
  // fires onerror. Ignore it — only show an error for genuine disconnects.
320
  if (episodeDone.current) return
321
- setError('Stream disconnected. Check backend is running, then press Play again.')
322
  setStreaming(false)
323
  es.close(); esRef.current = null
324
  }
@@ -347,7 +347,7 @@ export default function Dashboard() {
347
  if (!r.ok) throw new Error(`HTTP ${r.status}`)
348
  const d = await r.json()
349
  setSession(d.session_id); setObs(d.observation)
350
- setManLogs([{ type: 'system', msg: `Episode started (${difficulty})` }])
351
  } catch (err) {
352
  setError(err.message)
353
  } finally { setLoading(false) }
@@ -373,7 +373,7 @@ export default function Dashboard() {
373
  if (d.done) {
374
  setManLogs(prev => [...prev, {
375
  type: 'system',
376
- msg: `Done. Final score: ${d.info?.final_score?.toFixed(4) ?? 'N/A'}`,
377
  }])
378
  setSession(null)
379
  setManDone(true)
@@ -410,7 +410,7 @@ export default function Dashboard() {
410
  marginBottom: 16, flexWrap: 'wrap' }}>
411
  {/* Mode toggle */}
412
  <div style={{ display: 'flex', background: '#e2e8f0', borderRadius: 10, padding: 3 }}>
413
- {[['stream', '🤖 Auto-Play'], ['manual', '🎮 Manual']].map(([id, lbl]) => (
414
  <button key={id} onClick={() => setMode(id)}
415
  style={{ padding: '7px 14px', borderRadius: 8, border: 'none',
416
  background: mode === id ? '#fff' : 'transparent',
@@ -437,13 +437,13 @@ export default function Dashboard() {
437
  ? <button onClick={stopStream}
438
  style={{ background: '#ef4444', color: '#fff', border: 'none',
439
  borderRadius: 8, padding: '8px 20px', fontWeight: 700,
440
- fontSize: 13, cursor: 'pointer' }}>Stop</button>
441
  : !streamDone && (
442
  <button onClick={() => startStream()}
443
  style={{ background: '#6366f1', color: '#fff', border: 'none',
444
  borderRadius: 8, padding: '8px 20px', fontWeight: 700,
445
  fontSize: 13, cursor: 'pointer' }}>
446
- Play Episode
447
  </button>
448
  )
449
  ) : (
@@ -452,7 +452,7 @@ export default function Dashboard() {
452
  style={{ background: loading ? '#94a3b8' : '#6366f1', color: '#fff',
453
  border: 'none', borderRadius: 8, padding: '8px 20px', fontWeight: 700,
454
  fontSize: 13, cursor: loading ? 'not-allowed' : 'pointer' }}>
455
- {loading ? 'Loading…' : sessionId ? 'Reset' : 'Start'}
456
  </button>
457
  )
458
  )}
@@ -469,7 +469,7 @@ export default function Dashboard() {
469
  <span style={{ fontSize: 13, fontWeight: 700, color: '#16a34a',
470
  background: '#f0fdf4', border: '1px solid #bbf7d0', borderRadius: 8,
471
  padding: '6px 14px' }}>
472
- Episode #{episodeCount} Complete
473
  {typeof finalScore === 'number' ? ` · Score: ${finalScore.toFixed(4)}` : ''}
474
  </span>
475
  )}
@@ -480,10 +480,10 @@ export default function Dashboard() {
480
  <div style={{ background: '#fef2f2', border: '1px solid #fca5a5',
481
  borderRadius: 10, padding: '10px 14px', marginBottom: 14,
482
  fontSize: 13, color: '#dc2626' }}>
483
- ⚠️ {error}&ensp;
484
  <button onClick={() => setError(null)}
485
  style={{ background: 'none', border: 'none', cursor: 'pointer',
486
- color: '#dc2626', fontWeight: 700 }}></button>
487
  </div>
488
  )}
489
 
@@ -492,7 +492,7 @@ export default function Dashboard() {
492
  <div key={i} style={{ background: '#fffbeb', border: '1px solid #fcd34d',
493
  borderRadius: 10, padding: '10px 14px', marginBottom: 10,
494
  fontSize: 13, color: '#92400e', fontWeight: 600 }}>
495
- Schema Drift @ step {d.step}: {d.message}
496
  </div>
497
  ))}
498
 
@@ -509,7 +509,7 @@ export default function Dashboard() {
509
  }}>
510
  <div>
511
  <div style={{ fontSize: 18, fontWeight: 900, color: '#fff', letterSpacing: '-0.3px' }}>
512
- Episode #{episodeCount} Complete
513
  </div>
514
  <div style={{ fontSize: 12, color: '#d1fae5', marginTop: 2 }}>
515
  Final results frozen below — all charts and task data preserved
@@ -557,7 +557,7 @@ export default function Dashboard() {
557
  <div style={card()}>
558
  <div style={section}>Reward / Step</div>
559
  <LineChart data={rewardTrace} color="#6366f1" height={130}
560
- label="Press Play Episode to start" />
561
  {rewardTrace.length > 0 && (
562
  <div style={{ display: 'flex', justifyContent: 'space-between',
563
  fontSize: 11, color: '#64748b', marginTop: 6 }}>
@@ -619,7 +619,7 @@ export default function Dashboard() {
619
  <div style={{ fontSize: 10, color: '#94a3b8', marginTop: 2 }}>
620
  {(t.progress * 100).toFixed(0)}%
621
  {t.deadline ? ` · deadline: step ${t.deadline}` : ''}
622
- {t.is_interrupted ? ' ' : ''}
623
  </div>
624
  </div>
625
  )
@@ -680,7 +680,7 @@ export default function Dashboard() {
680
  display: 'flex', alignItems: 'center', gap: 16, flexWrap: 'wrap',
681
  }}>
682
  <div style={{ fontSize: 18, fontWeight: 900, color: '#fff' }}>
683
- Manual Episode Complete
684
  </div>
685
  <div style={{ fontSize: 12, color: '#c7d2fe' }}>
686
  All results frozen — task log and reward chart preserved below
@@ -715,7 +715,7 @@ export default function Dashboard() {
715
  <div style={section}>Task Queue</div>
716
  {manTasks.length === 0 && (
717
  <div style={{ color: '#cbd5e1', fontSize: 13, textAlign: 'center', padding: 24 }}>
718
- Press Start to begin
719
  </div>
720
  )}
721
  {manTasks.map(task => {
@@ -761,12 +761,12 @@ export default function Dashboard() {
761
  style={{ flex: 1, padding: 9, borderRadius: 8,
762
  border: '1px solid #e2e8f0', background: '#f0fdf4',
763
  color: '#16a34a', fontWeight: 700, cursor: 'pointer', fontSize: 13 }}>
764
- Break</button>
765
  <button onClick={() => handleAction('delay')}
766
  style={{ flex: 1, padding: 9, borderRadius: 8,
767
  border: '1px solid #e2e8f0', background: '#f8fafc',
768
  color: '#64748b', fontWeight: 700, cursor: 'pointer', fontSize: 13 }}>
769
- Delay</button>
770
  </div>
771
  )}
772
  </div>
 
122
 
123
  <div style={{ marginBottom:16 }}>
124
  <div style={{ fontSize:14, fontWeight:800, color:'#0f172a', marginBottom:4 }}>
125
+ Reward Scoring Formula
126
  </div>
127
  <div style={{ fontSize:11, color:'#64748b' }}>
128
  Each action is scored on 5 dimensions. Weights reflect cognitive-load research priorities.
 
318
  // When the server closes the stream after a clean episode end, the browser
319
  // fires onerror. Ignore it — only show an error for genuine disconnects.
320
  if (episodeDone.current) return
321
+ setError('Stream disconnected. Check backend is running, then press Play again.')
322
  setStreaming(false)
323
  es.close(); esRef.current = null
324
  }
 
347
  if (!r.ok) throw new Error(`HTTP ${r.status}`)
348
  const d = await r.json()
349
  setSession(d.session_id); setObs(d.observation)
350
+ setManLogs([{ type: 'system', msg: `Episode started (${difficulty})` }])
351
  } catch (err) {
352
  setError(err.message)
353
  } finally { setLoading(false) }
 
373
  if (d.done) {
374
  setManLogs(prev => [...prev, {
375
  type: 'system',
376
+ msg: `Done. Final score: ${d.info?.final_score?.toFixed(4) ?? 'N/A'}`,
377
  }])
378
  setSession(null)
379
  setManDone(true)
 
410
  marginBottom: 16, flexWrap: 'wrap' }}>
411
  {/* Mode toggle */}
412
  <div style={{ display: 'flex', background: '#e2e8f0', borderRadius: 10, padding: 3 }}>
413
+ {[['stream', 'Auto-Play'], ['manual', 'Manual']].map(([id, lbl]) => (
414
  <button key={id} onClick={() => setMode(id)}
415
  style={{ padding: '7px 14px', borderRadius: 8, border: 'none',
416
  background: mode === id ? '#fff' : 'transparent',
 
437
  ? <button onClick={stopStream}
438
  style={{ background: '#ef4444', color: '#fff', border: 'none',
439
  borderRadius: 8, padding: '8px 20px', fontWeight: 700,
440
+ fontSize: 13, cursor: 'pointer' }}>Stop</button>
441
  : !streamDone && (
442
  <button onClick={() => startStream()}
443
  style={{ background: '#6366f1', color: '#fff', border: 'none',
444
  borderRadius: 8, padding: '8px 20px', fontWeight: 700,
445
  fontSize: 13, cursor: 'pointer' }}>
446
+ Play Episode
447
  </button>
448
  )
449
  ) : (
 
452
  style={{ background: loading ? '#94a3b8' : '#6366f1', color: '#fff',
453
  border: 'none', borderRadius: 8, padding: '8px 20px', fontWeight: 700,
454
  fontSize: 13, cursor: loading ? 'not-allowed' : 'pointer' }}>
455
+ {loading ? 'Loading…' : sessionId ? 'Reset' : 'Start'}
456
  </button>
457
  )
458
  )}
 
469
  <span style={{ fontSize: 13, fontWeight: 700, color: '#16a34a',
470
  background: '#f0fdf4', border: '1px solid #bbf7d0', borderRadius: 8,
471
  padding: '6px 14px' }}>
472
+ Episode #{episodeCount} Complete
473
  {typeof finalScore === 'number' ? ` · Score: ${finalScore.toFixed(4)}` : ''}
474
  </span>
475
  )}
 
480
  <div style={{ background: '#fef2f2', border: '1px solid #fca5a5',
481
  borderRadius: 10, padding: '10px 14px', marginBottom: 14,
482
  fontSize: 13, color: '#dc2626' }}>
483
+ {error}&ensp;
484
  <button onClick={() => setError(null)}
485
  style={{ background: 'none', border: 'none', cursor: 'pointer',
486
+ color: '#dc2626', fontWeight: 700 }}>x</button>
487
  </div>
488
  )}
489
 
 
492
  <div key={i} style={{ background: '#fffbeb', border: '1px solid #fcd34d',
493
  borderRadius: 10, padding: '10px 14px', marginBottom: 10,
494
  fontSize: 13, color: '#92400e', fontWeight: 600 }}>
495
+ Schema Drift @ step {d.step}: {d.message}
496
  </div>
497
  ))}
498
 
 
509
  }}>
510
  <div>
511
  <div style={{ fontSize: 18, fontWeight: 900, color: '#fff', letterSpacing: '-0.3px' }}>
512
+ Episode #{episodeCount} Complete
513
  </div>
514
  <div style={{ fontSize: 12, color: '#d1fae5', marginTop: 2 }}>
515
  Final results frozen below — all charts and task data preserved
 
557
  <div style={card()}>
558
  <div style={section}>Reward / Step</div>
559
  <LineChart data={rewardTrace} color="#6366f1" height={130}
560
+ label="Press Play Episode to start" />
561
  {rewardTrace.length > 0 && (
562
  <div style={{ display: 'flex', justifyContent: 'space-between',
563
  fontSize: 11, color: '#64748b', marginTop: 6 }}>
 
619
  <div style={{ fontSize: 10, color: '#94a3b8', marginTop: 2 }}>
620
  {(t.progress * 100).toFixed(0)}%
621
  {t.deadline ? ` · deadline: step ${t.deadline}` : ''}
622
+ {t.is_interrupted ? ' (interrupted)' : ''}
623
  </div>
624
  </div>
625
  )
 
680
  display: 'flex', alignItems: 'center', gap: 16, flexWrap: 'wrap',
681
  }}>
682
  <div style={{ fontSize: 18, fontWeight: 900, color: '#fff' }}>
683
+ Manual Episode Complete
684
  </div>
685
  <div style={{ fontSize: 12, color: '#c7d2fe' }}>
686
  All results frozen — task log and reward chart preserved below
 
715
  <div style={section}>Task Queue</div>
716
  {manTasks.length === 0 && (
717
  <div style={{ color: '#cbd5e1', fontSize: 13, textAlign: 'center', padding: 24 }}>
718
+ Press Start to begin
719
  </div>
720
  )}
721
  {manTasks.map(task => {
 
761
  style={{ flex: 1, padding: 9, borderRadius: 8,
762
  border: '1px solid #e2e8f0', background: '#f0fdf4',
763
  color: '#16a34a', fontWeight: 700, cursor: 'pointer', fontSize: 13 }}>
764
+ Break</button>
765
  <button onClick={() => handleAction('delay')}
766
  style={{ flex: 1, padding: 9, borderRadius: 8,
767
  border: '1px solid #e2e8f0', background: '#f8fafc',
768
  color: '#64748b', fontWeight: 700, cursor: 'pointer', fontSize: 13 }}>
769
+ Delay</button>
770
  </div>
771
  )}
772
  </div>