SeaWolf-AI commited on
Commit
d7b487b
·
verified ·
1 Parent(s): d19126a

Update index.html

Browse files
Files changed (1) hide show
  1. index.html +541 -530
index.html CHANGED
@@ -3,607 +3,618 @@
3
  <head>
4
  <meta charset="UTF-8">
5
  <meta name="viewport" content="width=device-width, initial-scale=1.0">
6
- <title>SOMA Pre-AGI · Metacognitive Document Engine</title>
 
 
7
  <link href="https://fonts.googleapis.com/css2?family=Sora:wght@300;400;500;600;700;800&family=JetBrains+Mono:wght@400;500;600;700&display=swap" rel="stylesheet">
8
  <style>
9
  *{margin:0;padding:0;box-sizing:border-box;}
10
  :root{
11
- --bg:#f8f9fc;--bg2:#f0f2f8;--surface:#ffffff;--surface2:#f5f6fa;
12
- --border:#e2e5f0;--border2:#c7cce0;
13
- --text:#0f172a;--text2:#475569;--muted:#94a3b8;--muted2:#cbd5e1;
14
- --shadow:0 4px 16px rgba(15,23,42,.06),0 1px 3px rgba(15,23,42,.08);
15
  --shadow-sm:0 1px 3px rgba(15,23,42,.04),0 1px 2px rgba(15,23,42,.06);
 
16
  --shadow-lg:0 12px 40px rgba(15,23,42,.08),0 4px 12px rgba(15,23,42,.06);
17
- --ac:#6366f1;--ac2:#4f46e5;--ac-bg:rgba(99,102,241,.06);
18
- --re:#0EA5E9;--st:#16A34A;--ar:#DC2626;--ev:#D97706;--im:#7C3AED;
19
- --re-bg:#EFF8FF;--st-bg:#F0FDF4;--ar-bg:#FFF5F5;--ev-bg:#FFFBEB;--im-bg:#F5F3FF;
20
- --radius:14px;--radius-sm:10px;
 
21
  --font:'Sora',sans-serif;--mono:'JetBrains Mono',monospace;
22
  --tr:0.22s cubic-bezier(0.4,0,0.2,1);
23
  }
24
- html,body{height:100%;overflow:hidden;font-family:var(--font);background:var(--bg);color:var(--text);font-size:13px;-webkit-font-smoothing:antialiased;}
25
- body::before{content:"";position:fixed;inset:0;z-index:0;pointer-events:none;
26
- background:radial-gradient(ellipse 70% 45% at 15% 8%,rgba(99,102,241,.05),transparent 55%),
27
- radial-gradient(ellipse 55% 35% at 85% 92%,rgba(13,148,136,.04),transparent 50%);}
28
- ::-webkit-scrollbar{width:4px;height:4px;}
29
  ::-webkit-scrollbar-track{background:transparent;}
30
- ::-webkit-scrollbar-thumb{background:rgba(99,102,241,.2);border-radius:10px;}
31
- ::selection{background:rgba(99,102,241,.12);}
32
-
33
- @keyframes fadeIn{from{opacity:0;transform:translateY(6px)}to{opacity:1;transform:none}}
 
 
 
 
 
 
 
 
 
 
 
 
 
 
34
  @keyframes shimmer{0%,100%{background-position:0%}50%{background-position:100%}}
35
- @keyframes pulse{0%,100%{opacity:1;transform:scale(1)}50%{opacity:.4;transform:scale(.8)}}
36
- @keyframes spin{to{transform:rotate(360deg)}}
37
- @keyframes glow{0%,100%{box-shadow:0 0 8px var(--ac)}50%{box-shadow:0 0 20px var(--ac)}}
38
-
39
- /* TOPBAR */
40
- .topbar{position:fixed;top:0;left:0;right:0;z-index:1000;height:48px;display:flex;align-items:center;gap:12px;padding:0 20px;
41
- background:rgba(255,255,255,.85);backdrop-filter:blur(12px);border-bottom:1px solid var(--border);box-shadow:var(--shadow-sm);}
42
- .topbar-logo{font-family:var(--mono);font-size:11px;font-weight:800;letter-spacing:2px;
43
- background:linear-gradient(135deg,var(--re),var(--st),var(--ar),var(--ev),var(--im));background-size:300%;
44
- animation:shimmer 6s ease-in-out infinite;-webkit-background-clip:text;-webkit-text-fill-color:transparent;}
45
- .topbar-sub{font-size:9.5px;color:var(--muted);font-family:var(--mono);letter-spacing:.3px;}
46
- .topbar-sep{width:1px;height:22px;background:var(--border);margin:0 2px;}
47
- .topbar-badge{display:flex;align-items:center;gap:5px;background:var(--surface2);border:1px solid var(--border);
48
- border-radius:20px;padding:3px 10px;font-family:var(--mono);font-size:8.5px;color:var(--text2);font-weight:600;}
49
- .topbar-badge .pulse-dot{width:5px;height:5px;border-radius:50%;animation:pulse 2s infinite;}
50
- .chip{display:inline-flex;align-items:center;gap:4px;padding:3px 10px;border-radius:20px;font-family:var(--mono);font-size:8.5px;font-weight:600;}
51
- .chip-idle{background:var(--surface2);color:var(--muted);border:1px solid var(--border);}
52
- .chip-run{background:var(--ac-bg);color:var(--ac);border:1px solid rgba(99,102,241,.3);animation:glow 2s infinite;}
53
- .chip-done{background:rgba(22,163,74,.08);color:#16a34a;border:1px solid rgba(22,163,74,.3);}
54
- .chip-err{background:rgba(220,38,38,.08);color:#DC2626;border:1px solid rgba(220,38,38,.3);}
55
- .ml-auto{margin-left:auto;}
56
- .topbar-clock{font-family:var(--mono);font-size:9px;color:var(--muted);letter-spacing:.5px;}
57
-
58
- /* LAYOUT */
59
- .main-layout{position:fixed;top:48px;left:0;right:0;bottom:44px;display:grid;
60
- grid-template-columns:220px 1fr 230px;gap:0;overflow:hidden;z-index:1;}
61
-
62
- /* PANELS */
63
- .panel-left,.panel-right{background:var(--surface);border-right:1px solid var(--border);overflow-y:auto;padding:12px;}
64
- .panel-right{border-right:none;border-left:1px solid var(--border);}
65
- .panel-center{display:flex;flex-direction:column;overflow:hidden;background:var(--bg);}
66
- .panel-section{margin-bottom:14px;padding-bottom:12px;border-bottom:1px solid var(--border);}
67
- .panel-section:last-child{border-bottom:none;}
68
- .panel-heading{font-family:var(--mono);font-size:8.5px;font-weight:700;letter-spacing:1.5px;text-transform:uppercase;color:var(--muted);margin-bottom:10px;}
69
-
70
- /* AGENT CARDS */
71
- .agent-card{padding:10px 12px;border-radius:var(--radius-sm);border:1px solid var(--border);margin-bottom:6px;transition:var(--tr);cursor:default;position:relative;overflow:hidden;}
72
- .agent-card::before{content:'';position:absolute;inset:0;opacity:0;transition:opacity .3s;pointer-events:none;}
73
- .agent-card.active{border-color:var(--ac);box-shadow:0 0 0 2px rgba(99,102,241,.15);}
74
- .agent-card.re::before{background:linear-gradient(135deg,rgba(14,165,233,.06),transparent);}
75
- .agent-card.st::before{background:linear-gradient(135deg,rgba(22,163,74,.06),transparent);}
76
- .agent-card.ar::before{background:linear-gradient(135deg,rgba(220,38,38,.06),transparent);}
77
- .agent-card.ev::before{background:linear-gradient(135deg,rgba(217,119,6,.06),transparent);}
78
- .agent-card.im::before{background:linear-gradient(135deg,rgba(124,58,237,.06),transparent);}
79
- .agent-card.active::before{opacity:1;}
80
- .agent-top{display:flex;align-items:center;gap:8px;}
81
- .agent-emoji{font-size:18px;width:28px;text-align:center;}
82
- .agent-name{font-family:var(--mono);font-size:10px;font-weight:700;letter-spacing:.5px;}
83
- .agent-name.re{color:var(--re);}.agent-name.st{color:var(--st);}.agent-name.ar{color:var(--ar);}.agent-name.ev{color:var(--ev);}.agent-name.im{color:var(--im);}
84
- .agent-role{font-size:9px;color:var(--muted);}
85
- .agent-status{margin-left:auto;font-family:var(--mono);font-size:8px;font-weight:700;letter-spacing:.5px;padding:2px 8px;border-radius:10px;}
86
- .agent-status.idle{background:var(--surface2);color:var(--muted2);}
87
- .agent-status.run{background:var(--ac-bg);color:var(--ac);}
88
- .agent-status.done{background:rgba(22,163,74,.08);color:#16a34a;}
89
- .flow-line{text-align:center;padding:2px 0;font-size:10px;color:var(--muted2);display:flex;align-items:center;justify-content:center;gap:6px;}
90
- .flow-arrow{color:var(--ac);font-weight:700;}
91
-
92
- /* SEARCH COUNTER */
93
- .sc-bar-wrap{height:4px;background:var(--surface2);border-radius:2px;margin-top:6px;overflow:hidden;}
94
- .sc-bar{height:100%;background:linear-gradient(90deg,var(--re),var(--ac));border-radius:2px;width:0;transition:width .5s;}
95
- .sc-label{font-family:var(--mono);font-size:8px;color:var(--muted);text-transform:uppercase;letter-spacing:1px;font-weight:600;}
96
- .sc-value{font-family:var(--mono);font-size:20px;font-weight:800;color:var(--ac);}
97
- .sc-max{font-family:var(--mono);font-size:10px;color:var(--muted);}
98
 
99
  /* TABS */
100
- .tab-nav{display:flex;gap:0;border-bottom:1.5px solid var(--border);background:var(--surface);padding:0 16px;}
101
- .tab-btn{padding:10px 18px;font-family:var(--mono);font-size:10px;font-weight:600;color:var(--muted);border:none;background:none;
102
- cursor:pointer;border-bottom:2px solid transparent;transition:var(--tr);letter-spacing:.3px;}
103
- .tab-btn:hover{color:var(--text);background:var(--ac-bg);}
104
- .tab-btn.active{color:var(--ac);border-bottom-color:var(--ac);background:var(--ac-bg);}
105
- .tab-content{display:none;flex:1;overflow:hidden;flex-direction:column;}
106
- .tab-content.active{display:flex;}
107
-
108
- /* PROMPT TAB */
109
- .prompt-area{padding:16px;border-bottom:1px solid var(--border);background:var(--surface);}
110
- .prompt-label{font-family:var(--mono);font-size:9px;font-weight:700;letter-spacing:1px;text-transform:uppercase;color:var(--muted);margin-bottom:8px;display:flex;align-items:center;gap:6px;}
111
- .prompt-wrap{position:relative;}
112
- .prompt-input{width:100%;padding:12px 14px;border:1.5px solid var(--border);border-radius:var(--radius-sm);font-family:var(--font);font-size:12.5px;
113
- color:var(--text);background:var(--surface);resize:none;outline:none;transition:var(--tr);line-height:1.6;}
114
- .prompt-input:focus{border-color:var(--ac);box-shadow:0 0 0 3px rgba(99,102,241,.08);}
115
- .btn-row{display:flex;gap:8px;margin-top:10px;align-items:center;}
116
- .btn{display:inline-flex;align-items:center;gap:6px;padding:8px 18px;border:1.5px solid var(--border);border-radius:var(--radius-sm);
117
- font-family:var(--mono);font-size:10px;font-weight:600;cursor:pointer;transition:var(--tr);letter-spacing:.3px;}
118
- .btn-primary{background:linear-gradient(135deg,var(--ac),var(--ac2));color:#fff;border-color:transparent;box-shadow:0 3px 12px rgba(99,102,241,.2);}
119
- .btn-primary:hover{box-shadow:0 6px 20px rgba(99,102,241,.3);transform:translateY(-1px);}
120
- .btn-primary.running{background:linear-gradient(135deg,#DC2626,#B91C1C);}
121
- .btn-secondary{background:var(--surface);color:var(--text2);}
122
- .btn-secondary:hover{background:var(--ac-bg);border-color:rgba(99,102,241,.3);color:var(--ac);}
123
- .btn-success{background:linear-gradient(135deg,#16a34a,#15803d);color:#fff;border-color:transparent;}
124
- .spinner{width:12px;height:12px;border:2px solid rgba(255,255,255,.3);border-top-color:#fff;border-radius:50%;display:none;}
125
- .spinner.visible{display:inline-block;animation:spin .8s linear infinite;}
126
- .example-btn{display:block;width:100%;text-align:left;padding:8px 12px;margin-bottom:5px;border:1px solid var(--border);border-radius:8px;
127
- background:var(--surface);font-size:11px;color:var(--text2);cursor:pointer;transition:var(--tr);line-height:1.5;}
128
- .example-btn:hover{border-color:var(--ac);background:var(--ac-bg);color:var(--ac);}
129
- .api-warn{display:none;padding:8px 12px;background:rgba(217,119,6,.06);border:1px solid rgba(217,119,6,.2);border-radius:8px;
130
- font-size:10px;color:#B45309;margin-bottom:8px;}
131
-
132
- /* STREAM */
133
- .stream-wrap{flex:1;display:flex;flex-direction:column;overflow:hidden;}
134
- .stream-header{display:flex;align-items:center;gap:8px;padding:10px 16px;border-bottom:1px solid var(--border);background:var(--surface);}
135
- .stream-box{flex:1;overflow-y:auto;padding:16px;font-family:var(--mono);font-size:11px;line-height:1.8;color:var(--text2);
136
- background:linear-gradient(180deg,var(--bg),var(--surface2));white-space:pre-wrap;word-break:break-word;}
137
- .stream-empty{color:var(--muted);font-style:italic;}
138
-
139
- /* DOC */
140
- .doc-wrap{flex:1;display:flex;flex-direction:column;overflow:hidden;padding:16px;}
141
- .doc-toolbar{display:flex;align-items:center;gap:8px;margin-bottom:10px;}
142
- .doc-area{flex:1;overflow-y:auto;padding:20px;background:var(--surface);border:1px solid var(--border);border-radius:var(--radius);
143
- font-size:12.5px;line-height:1.9;color:var(--text);box-shadow:var(--shadow-sm);white-space:pre-wrap;word-break:break-word;}
144
- .doc-empty{color:var(--muted);text-align:center;padding:60px 20px;font-size:13px;}
145
-
146
- /* LOG */
147
- .log-wrap{flex:1;display:flex;flex-direction:column;overflow:hidden;padding:16px;}
148
- .log-box{flex:1;overflow-y:auto;padding:12px;background:var(--surface);border:1px solid var(--border);border-radius:var(--radius);
149
- font-family:var(--mono);font-size:10px;line-height:1.7;color:var(--text2);white-space:pre-wrap;}
150
-
151
- /* SETTINGS */
152
- .setting-item{margin-bottom:14px;}
153
- .setting-label{font-size:11px;color:var(--text2);display:flex;justify-content:space-between;margin-bottom:6px;}
154
- .setting-val{font-family:var(--mono);font-weight:700;color:var(--ac);}
155
- input[type=range]{width:100%;accent-color:var(--ac);height:4px;}
156
- .pipeline-flow{display:flex;align-items:center;gap:4px;flex-wrap:wrap;padding:6px 0;}
157
- .pf-node{width:28px;height:28px;border-radius:50%;display:flex;align-items:center;justify-content:center;font-size:14px;
158
- border:2px solid var(--border);background:var(--surface);transition:var(--tr);}
159
- .pf-node.active{border-color:var(--ac);box-shadow:0 0 0 3px rgba(99,102,241,.15);transform:scale(1.15);}
160
- .pf-arrow{font-size:10px;color:var(--muted2);}
161
- .dl-area{padding:10px 0;}
162
- .dl-filename{font-family:var(--mono);font-size:10px;color:var(--text2);margin-bottom:8px;padding:6px 10px;background:var(--surface2);border-radius:6px;border:1px solid var(--border);}
163
- .dl-status{font-family:var(--mono);font-size:9px;color:var(--muted);margin-top:6px;}
164
- .dl-status.ok{color:#16a34a;}.dl-status.err{color:#DC2626;}
165
-
166
- /* SEARCH FEED */
167
- .search-feed{position:fixed;bottom:44px;left:0;width:220px;height:140px;overflow-y:auto;
168
- background:var(--surface);border-top:1px solid var(--border);border-right:1px solid var(--border);z-index:2;padding:8px 10px;}
169
- .search-feed-h{font-family:var(--mono);font-size:8px;font-weight:700;letter-spacing:1px;text-transform:uppercase;color:var(--muted);
170
- margin-bottom:6px;display:flex;align-items:center;gap:5px;}
171
- .sf-item{font-family:var(--mono);font-size:9px;color:var(--text2);padding:3px 0;display:flex;gap:6px;border-bottom:1px solid rgba(0,0,0,.03);animation:fadeIn .3s;}
172
- .sf-num{color:var(--muted);min-width:24px;}.sf-text{color:var(--text2);overflow:hidden;text-overflow:ellipsis;white-space:nowrap;}
173
-
174
- /* STATS BAR */
175
- .stats-bar{position:fixed;bottom:0;left:0;right:0;height:44px;z-index:1000;display:flex;align-items:center;gap:0;
176
- background:rgba(255,255,255,.9);backdrop-filter:blur(12px);border-top:1px solid var(--border);padding:0 16px;}
177
- .stat-box{flex:1;text-align:center;padding:4px 0;}
178
- .stat-val{font-family:var(--mono);font-size:13px;font-weight:800;}
179
- .stat-val.re{color:var(--re);}.stat-val.st{color:var(--st);}.stat-val.ar{color:var(--ar);}.stat-val.ev{color:var(--ev);}.stat-val.im{color:var(--im);}.stat-val.gray{color:var(--muted);}
180
- .stat-label{font-size:8px;color:var(--muted);font-family:var(--mono);letter-spacing:.3px;}
181
-
182
- /* TOAST */
183
- .toast{position:fixed;bottom:60px;left:50%;transform:translateX(-50%) translateY(20px);opacity:0;padding:10px 24px;
184
- background:var(--text);color:#fff;border-radius:var(--radius-sm);font-family:var(--mono);font-size:11px;font-weight:500;
185
- box-shadow:var(--shadow-lg);transition:all .3s;z-index:9999;pointer-events:none;}
186
- .toast.visible{opacity:1;transform:translateX(-50%) translateY(0);}
187
- .toast.ok{background:#16a34a;}.toast.err{background:#DC2626;}
188
-
189
- /* DIAGRAM */
190
- .meta-diagram{display:flex;flex-direction:column;gap:4px;margin-top:8px;font-family:var(--mono);font-size:9px;}
191
- .md-row{display:flex;align-items:center;gap:6px;padding:2px 0;}
192
- .md-arrow{color:var(--ac);font-weight:700;font-size:10px;}
193
- .md-label{color:var(--muted);font-size:8px;margin-left:auto;}
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
194
  </style>
195
  </head>
196
  <body>
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
197
 
198
- <!-- TOPBAR -->
199
- <div class="topbar">
200
- <div class="topbar-logo">SOMA PRE-AGI</div>
201
- <div class="topbar-sep"></div>
202
- <div class="topbar-sub">Metacognitive Document Engine</div>
203
- <div class="topbar-sep"></div>
204
- <div class="topbar-badge"><div class="pulse-dot" style="background:var(--ac)"></div>EMERGENCE MATRIX v1.0</div>
205
- <div class="topbar-sep"></div>
206
- <div class="chip chip-idle" id="pipelineChip">● IDLE</div>
207
- <div class="ml-auto"></div>
208
- <div class="topbar-clock" id="clock"></div>
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
209
  </div>
210
 
211
- <div class="main-layout">
212
-
213
- <!-- LEFT PANEL -->
214
- <div class="panel-left">
215
- <div class="panel-section">
216
- <div class="panel-heading">Agent Pipeline</div>
 
 
217
 
218
- <div class="agent-card re" id="card-水">
219
- <div class="agent-top">
220
- <span class="agent-emoji">🔍</span>
221
- <div><div class="agent-name re">RESEARCH</div><div class="agent-role">탐색 · 정보수집</div></div>
222
- <div class="agent-status idle" id="st-水">IDLE</div>
223
- </div>
224
- </div>
225
- <div class="flow-line"><span class="flow-arrow"></span><span style="font-size:7px;color:var(--muted2)">PIPE</span></div>
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
226
 
227
- <div class="agent-card st" id="card-木">
228
- <div class="agent-top">
229
- <span class="agent-emoji">🧩</span>
230
- <div><div class="agent-name st">STRUCTURE</div><div class="agent-role">설계 · 구조화</div></div>
231
- <div class="agent-status idle" id="st-木">IDLE</div>
232
- </div>
233
- </div>
234
- <div class="flow-line"><span class="flow-arrow">↓</span><span style="font-size:7px;color:var(--muted2)">PIPE</span></div>
 
 
235
 
236
- <div class="agent-card ar" id="card-">
237
- <div class="agent-top">
238
- <span class="agent-emoji">🔬</span>
239
- <div><div class="agent-name ar">ARGUMENT</div><div class="agent-role">논증 · 검증</div></div>
240
- <div class="agent-status idle" id="st-火">IDLE</div>
241
- </div>
242
- </div>
243
- <div class="flow-line"><span class="flow-arrow">↓</span><span style="font-size:7px;color:var(--muted2)">PIPE</span></div>
244
 
245
- <div class="agent-card ev" id="card-土">
246
- <div class="agent-top">
247
- <span class="agent-emoji">📐</span>
248
- <div><div class="agent-name ev">EVIDENCE</div><div class="agent-role">통합 · 실체화</div></div>
249
- <div class="agent-status idle" id="st-">IDLE</div>
250
- </div>
 
 
 
251
  </div>
252
- <div class="flow-line"><span class="flow-arrow">↓</span><span style="font-size:7px;color:var(--muted2)">PIPE</span></div>
253
-
254
- <div class="agent-card im" id="card-">
255
- <div class="agent-top">
256
- <span class="agent-emoji">🧠</span>
257
- <div><div class="agent-name im">IMPACT</div><div class="agent-role">메타인지 · 정제</div></div>
258
- <div class="agent-status idle" id="st-金">IDLE</div>
259
- </div>
260
  </div>
261
  </div>
 
 
262
 
263
- <div class="panel-section">
264
- <div class="panel-heading">Search Progress</div>
 
 
265
  <div>
266
- <div class="sc-label">검색 횟수</div>
267
- <div style="display:flex;align-items:baseline;gap:4px;">
268
- <div class="sc-value" id="searchCount">0</div>
269
- <div class="sc-max" id="searchMax">/ 20</div>
270
- </div>
271
- <div class="sc-bar-wrap"><div class="sc-bar" id="scBar"></div></div>
272
  </div>
273
- </div>
274
-
275
- <div class="panel-section">
276
- <div class="panel-heading">Pipeline Timer</div>
277
- <div style="font-family:var(--mono);font-size:10px;color:var(--muted);display:flex;flex-direction:column;gap:5px;">
278
- <div style="display:flex;justify-content:space-between;"><span>시작</span><span id="pipeStart" style="color:var(--text2)">–</span></div>
279
- <div style="display:flex;justify-content:space-between;"><span>경과</span><span id="pipeElapsed" style="color:var(--ac)">–</span></div>
280
- <div style="display:flex;justify-content:space-between;"><span>단계</span><span id="pipeStage" style="color:var(--text2)">–</span></div>
281
  </div>
282
  </div>
 
283
  </div>
284
 
285
- <!-- CENTER -->
286
- <div class="panel-center">
287
- <div class="tab-nav">
288
- <button class="tab-btn active" onclick="switchTab('prompt',this)">📝 Input</button>
289
- <button class="tab-btn" onclick="switchTab('stream',this)">⚡ Stream</button>
290
- <button class="tab-btn" onclick="switchTab('doc',this)">📄 Document</button>
291
- <button class="tab-btn" onclick="switchTab('log',this)">🧬 Log</button>
292
- </div>
293
-
294
- <!-- TAB: Input -->
295
- <div class="tab-content active" id="tab-prompt">
296
- <div class="prompt-area">
297
- <div class="prompt-label"><span style="width:6px;height:6px;border-radius:50%;background:var(--re);display:inline-block;"></span> Document Generation Prompt</div>
298
- <div class="api-warn" id="apiWarn">⚠ FIREWORKS_API_KEY 또는 BRAVE_API_KEY 환경변수를 Space Secrets에 설정하세요.</div>
299
- <div class="prompt-wrap">
300
- <textarea class="prompt-input" id="promptInput" rows="4"
301
- placeholder="예: 온라인 예금중개 서비스 제도화 추진 방안에 대한 정책 보고서를 작성해주세요."></textarea>
302
- </div>
303
- <div class="btn-row">
304
- <button class="btn btn-primary" id="runBtn" onclick="runPipeline()">
305
- <div class="spinner" id="btnSpinner"></div>
306
- <span id="btnLabel">🚀 SOMA 실행</span>
307
- </button>
308
- <button class="btn btn-secondary" onclick="resetAll()">↺ 초기화</button>
309
- <div style="margin-left:auto;font-family:var(--mono);font-size:9px;color:var(--muted);">
310
- Search <span id="labelMax">20</span> · Temp <span id="labelTemp">0.6</span>
311
- </div>
312
- </div>
313
  </div>
314
- <div style="padding:14px;overflow-y:auto;flex:1;">
315
- <div style="font-family:var(--mono);font-size:8.5px;font-weight:700;letter-spacing:1.5px;text-transform:uppercase;color:var(--muted);margin-bottom:10px;">📌 Example Prompts</div>
316
- <button class="example-btn" onclick="setExample(this)">온라인 예금중개 서비스 제도화 추진 방안에 대한 정책 보고서를 작성해주세요.</button>
317
- <button class="example-btn" onclick="setExample(this)">인공지능 기반 공공서비스 혁신 전략 수립 보고서를 작성해주세요.</button>
318
- <button class="example-btn" onclick="setExample(this)">탄소중립 실현을 위한 에너지 전환 정책 로드맵을 작성해주세요.</button>
319
- <button class="example-btn" onclick="setExample(this)">AI 보안 유망기업 육성 지원사업 공모 제안서를 작성해주세요.</button>
320
- <button class="example-btn" onclick="setExample(this)">스마트시티 구축을 위한 데이터 거버넌스 체계 구축 방안을 작성해주세요.</button>
321
-
322
- <div style="font-family:var(--mono);font-size:8.5px;font-weight:700;letter-spacing:1.5px;text-transform:uppercase;color:var(--muted);margin:16px 0 10px;">🔗 Cross-Check Relations</div>
323
- <div class="meta-diagram">
324
- <div class="md-row"><span>🧠 IMPACT</span><span class="md-arrow">→</span><span>🧩 STRUCTURE</span><span class="md-label">구조 비평</span></div>
325
- <div class="md-row"><span>🧩 STRUCTURE</span><span class="md-arrow">→</span><span>📐 EVIDENCE</span><span class="md-label">통합 가이드</span></div>
326
- <div class="md-row"><span>📐 EVIDENCE</span><span class="md-arrow">→</span><span>🔍 RESEARCH</span><span class="md-label">데이터 요청</span></div>
327
- <div class="md-row"><span>🔍 RESEARCH</span><span class="md-arrow">→</span><span>🔬 ARGUMENT</span><span class="md-label">출처 검증</span></div>
328
- <div class="md-row"><span>🔬 ARGUMENT</span><span class="md-arrow">→</span><span>🧠 IMPACT</span><span class="md-label">정제 견제</span></div>
329
- </div>
330
  </div>
331
  </div>
 
 
332
 
333
- <!-- TAB: Stream -->
334
- <div class="tab-content" id="tab-stream">
335
- <div class="stream-wrap">
336
- <div class="stream-header">
337
- <div class="chip chip-idle" id="streamBadge">Agent Idle</div>
338
- <div style="font-family:var(--mono);font-size:9px;color:var(--muted);" id="streamAgentLabel"></div>
339
- <div style="margin-left:auto;"><button class="btn btn-secondary" style="padding:4px 10px;font-size:9px;" onclick="clearStream()">Clear</button></div>
340
- </div>
341
- <div class="stream-box" id="streamBox"><span class="stream-empty">SOMA 파이프라인을 실행하면 에이전트 실시간 출력이 여기에 표시됩니다.</span></div>
342
- </div>
343
- </div>
344
 
345
- <!-- TAB: Document -->
346
- <div class="tab-content" id="tab-doc">
347
- <div class="doc-wrap">
348
- <div class="doc-toolbar">
349
- <div style="font-family:var(--mono);font-size:9px;color:var(--muted);font-weight:700;letter-spacing:1px;text-transform:uppercase;">🧠 IMPACT Final Document</div>
350
- <div style="margin-left:auto;display:flex;gap:8px;">
351
- <button class="btn btn-secondary" style="padding:5px 12px;font-size:9px;" onclick="copyDoc()">📋 Copy</button>
352
- <button class="btn btn-success" style="padding:5px 12px;font-size:9px;" id="hmlBtn" onclick="downloadHml()">📥 HWPX</button>
353
- </div>
354
- </div>
355
- <div class="doc-area" id="docArea"><div class="doc-empty">📄 문서가 생성되면 여기에 표시됩니다.<br><br>SOMA 파이프라인을 실행하세요.</div></div>
356
- <div style="font-family:var(--mono);font-size:9px;color:var(--muted);padding:4px 0;">ℹ 생성된 .hwpx 파일은 한글(HWP)에서 더블클릭으로 열 수 있습니다.</div>
 
 
 
357
  </div>
358
  </div>
359
-
360
- <!-- TAB: Log -->
361
- <div class="tab-content" id="tab-log">
362
- <div class="log-wrap">
363
- <div style="display:flex;align-items:center;gap:8px;margin-bottom:8px;">
364
- <div style="font-family:var(--mono);font-size:9px;color:var(--muted);font-weight:700;letter-spacing:1px;text-transform:uppercase;">🧬 Agent Pipeline Log</div>
365
- <button class="btn btn-secondary" style="padding:4px 10px;font-size:9px;margin-left:auto;" onclick="clearLog()">Clear</button>
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
366
  </div>
367
- <div class="log-box" id="logBox">에이전트 로그가 여기에 기록됩니다.</div>
368
  </div>
369
  </div>
370
  </div>
371
 
372
- <!-- RIGHT PANEL -->
373
- <div class="panel-right">
374
- <div class="panel-section">
375
- <div class="panel-heading">Settings</div>
376
- <div class="setting-item">
377
- <div class="setting-label">🔍 최대 검색 횟수 <span class="setting-val" id="valSearch">20</span></div>
378
- <input type="range" min="5" max="100" step="5" value="20" id="sliderSearch" oninput="updateSlider('Search',this.value)">
379
- </div>
380
- <div class="setting-item">
381
- <div class="setting-label">🌡 Temperature <span class="setting-val" id="valTemp">0.6</span></div>
382
- <input type="range" min="0.1" max="1.0" step="0.05" value="0.6" id="sliderTemp" oninput="updateSlider('Temp',this.value)">
383
- </div>
384
- </div>
 
 
 
385
 
386
- <div class="panel-section">
387
- <div class="panel-heading">Pipeline Flow</div>
388
- <div class="pipeline-flow">
389
- <div class="pf-node" id="ss-水">🔍</div><div class="pf-arrow">→</div>
390
- <div class="pf-node" id="ss-木">🧩</div><div class="pf-arrow">→</div>
391
- <div class="pf-node" id="ss-火">🔬</div><div class="pf-arrow"></div>
392
- <div class="pf-node" id="ss-">📐</div><div class="pf-arrow">→</div>
393
- <div class="pf-node" id="ss-">🧠</div>
394
  </div>
395
- <div style="margin-top:8px;font-size:9px;color:var(--muted);line-height:1.7;font-family:var(--mono);">
396
- Pipeline: RES→STR→ARG→EVI→IMP<br>
397
- Cross: IMP⊸STR · STR⊸EVI · EVI⊸RES
 
398
  </div>
399
  </div>
 
 
400
 
401
- <div class="panel-section">
402
- <div class="panel-heading">HWPX Download</div>
403
- <div class="dl-area">
404
- <div class="dl-filename" id="dlFilename">파일 없음</div>
405
- <button class="btn btn-success" style="width:100%;justify-content:center;" id="dlBtn" onclick="downloadHml()" disabled>📥 HWPX 다운로드</button>
406
- <div class="dl-status" id="dlStatus">문서 생성 사용 가능합니다.</div>
407
- <a id="dlLink"></a>
408
- </div>
 
 
 
 
409
  </div>
410
-
411
- <div class="panel-section">
412
- <div class="panel-heading">Backend URL</div>
413
- <div><input id="backendUrl" type="text" style="width:100%;padding:6px 8px;border:1px solid var(--border);border-radius:6px;font-family:var(--mono);font-size:10px;background:var(--surface2);color:var(--text);outline:none;" placeholder="https://your-space.hf.space" value="">
414
- <div style="color:var(--muted2);font-size:8px;margin-top:4px;font-family:var(--mono);">HF Space URL (비워두면 동일 오리진)</div></div>
 
 
 
 
415
  </div>
 
416
 
417
- <div class="panel-section">
418
- <div class="panel-heading">Agent Layers</div>
419
- <div style="font-size:9.5px;color:var(--text2);line-height:2;font-family:var(--mono);">
420
- <div style="display:flex;align-items:center;gap:6px;"><span style="width:7px;height:7px;border-radius:50%;background:var(--re);display:inline-block;"></span>RESEARCH: Brave Search</div>
421
- <div style="display:flex;align-items:center;gap:6px;"><span style="width:7px;height:7px;border-radius:50%;background:var(--st);display:inline-block;"></span>STRUCTURE: 문서 설계</div>
422
- <div style="display:flex;align-items:center;gap:6px;"><span style="width:7px;height:7px;border-radius:50%;background:var(--ar);display:inline-block;"></span>ARGUMENT: 팩트체크</div>
423
- <div style="display:flex;align-items:center;gap:6px;"><span style="width:7px;height:7px;border-radius:50%;background:var(--ev);display:inline-block;"></span>EVIDENCE: 문서 통합</div>
424
- <div style="display:flex;align-items:center;gap:6px;"><span style="width:7px;height:7px;border-radius:50%;background:var(--im);display:inline-block;"></span>IMPACT: 메타인지 정제</div>
425
- </div>
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
426
  </div>
427
  </div>
428
 
 
 
 
 
 
 
429
  </div>
430
 
431
- <!-- SEARCH FEED -->
432
- <div class="search-feed" id="searchFeed">
433
- <div class="search-feed-h"><span style="width:5px;height:5px;border-radius:50%;background:var(--re);display:inline-block;"></span> Search Log</div>
434
- <div id="searchFeedList"></div>
435
- </div>
436
-
437
- <!-- STATS BAR -->
438
- <div class="stats-bar">
439
- <div class="stat-box"><div class="stat-val re" id="statSearch">0</div><div class="stat-label">🔍 Searches</div></div>
440
- <div class="stat-box"><div class="stat-val st" id="statAgent">–</div><div class="stat-label">🤖 Agent</div></div>
441
- <div class="stat-box"><div class="stat-val ev" id="statTokens">0</div><div class="stat-label">📝 Length</div></div>
442
- <div class="stat-box"><div class="stat-val gray" id="statTime">–</div><div class="stat-label">⏱ Elapsed</div></div>
443
- <div class="stat-box"><div class="stat-val im" id="statStatus">IDLE</div><div class="stat-label">📡 Pipeline</div></div>
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
444
  </div>
445
 
446
- <div class="toast" id="toast"></div>
447
 
 
448
  <script>
449
- let running=false,eventSource=null,pipeStartTime=null,elapsedTimer=null,totalSearchCount=0,maxSearchCount=20,streamText='',logText='',finalDoc='',lastHmlPath='';
450
- const OHAENG=['水','木','火','土','金'];
451
- const OHAENG_CLASS={'水':'re','木':'st','火':'ar','土':'ev','金':'im'};
452
- const OHAENG_LABEL={'水':'RESEARCH','木':'STRUCTURE','火':'ARGUMENT','土':'EVIDENCE','金':'IMPACT'};
453
- const OHAENG_EMOJI={'水':'🔍','木':'🧩','火':'🔬','土':'📐','金':'🧠'};
454
-
455
- function updateClock(){const d=new Date();document.getElementById('clock').textContent=d.toISOString().slice(0,16).replace('T',' ')+' KST';}
456
- setInterval(updateClock,1000);updateClock();
457
-
458
- function switchTab(id,btn){
459
- document.querySelectorAll('.tab-content').forEach(t=>t.classList.remove('active'));
460
- document.querySelectorAll('.tab-btn').forEach(b=>b.classList.remove('active'));
461
- document.getElementById('tab-'+id).classList.add('active');
462
- if(btn)btn.classList.add('active');
463
- }
464
- function updateSlider(key,val){
465
- document.getElementById('val'+key).textContent=val;
466
- if(key==='Search'){maxSearchCount=parseInt(val);document.getElementById('searchMax').textContent='/ '+val;document.getElementById('labelMax').textContent=val;}
467
- if(key==='Temp')document.getElementById('labelTemp').textContent=val;
468
- }
469
- function setExample(btn){document.getElementById('promptInput').value=btn.textContent.trim();document.getElementById('promptInput').focus();}
470
-
471
- function activateAgent(agent){
472
- OHAENG.forEach(a=>{
473
- document.getElementById('card-'+a).classList.remove('active');
474
- document.getElementById('ss-'+a).classList.remove('active');
475
- if(a===agent){
476
- document.getElementById('card-'+a).classList.add('active');
477
- document.getElementById('ss-'+a).classList.add('active');
478
- const st=document.getElementById('st-'+a);st.className='agent-status run';st.textContent='● RUN';
479
- }
480
- });
481
- document.getElementById('statAgent').textContent=OHAENG_LABEL[agent]||agent;
482
- document.getElementById('pipeStage').textContent=OHAENG_LABEL[agent]||agent;
483
- const badge=document.getElementById('streamBadge');
484
- badge.className='chip chip-run';badge.textContent='● '+(OHAENG_LABEL[agent]||agent)+' Processing';
485
- document.getElementById('streamAgentLabel').textContent='Search: '+totalSearchCount+'/'+maxSearchCount;
486
- }
487
- function completeAgent(agent){const st=document.getElementById('st-'+agent);if(st){st.className='agent-status done';st.textContent='✓ DONE';}}
488
- function resetAgents(){OHAENG.forEach(a=>{document.getElementById('card-'+a).classList.remove('active');document.getElementById('ss-'+a).classList.remove('active');const st=document.getElementById('st-'+a);st.className='agent-status idle';st.textContent='IDLE';});}
489
-
490
- function addSearchFeed(num,text,cls='re'){
491
- const list=document.getElementById('searchFeedList');
492
- const item=document.createElement('div');item.className='sf-item';
493
- item.innerHTML=`<span class="sf-num">${String(num).padStart(3,'0')}</span><span class="sf-text">${escapeHtml(text.slice(0,60))}</span>`;
494
- list.insertBefore(item,list.firstChild);if(list.children.length>60)list.removeChild(list.lastChild);
495
  }
496
- function escapeHtml(t){return t.replace(/&/g,'&amp;').replace(/</g,'&lt;').replace(/>/g,'&gt;');}
497
 
498
- function appendStream(text,agent){
499
- const box=document.getElementById('streamBox');
500
- const empty=box.querySelector('.stream-empty');if(empty)empty.remove();
501
- streamText+=text;document.getElementById('statTokens').textContent=streamText.length.toLocaleString();
502
- const span=document.createElement('span');span.textContent=text;box.appendChild(span);box.scrollTop=box.scrollHeight;
503
- }
504
- function clearStream(){document.getElementById('streamBox').innerHTML='<span class="stream-empty">스트림이 지워졌습니다.</span>';streamText='';}
505
- function clearLog(){document.getElementById('logBox').textContent='';logText='';}
506
-
507
- function showFinalDoc(text){
508
- finalDoc=text;document.getElementById('docArea').textContent=text;
509
- document.querySelectorAll('.tab-btn').forEach(b=>b.classList.remove('active'));
510
- document.querySelectorAll('.tab-content').forEach(t=>t.classList.remove('active'));
511
- document.getElementById('tab-doc').classList.add('active');
512
- document.querySelectorAll('.tab-btn')[2].classList.add('active');
513
- document.getElementById('dlBtn').disabled=false;
514
- document.getElementById('dlFilename').textContent='문서.hwpx';
515
- document.getElementById('dlStatus').className='dl-status ok';document.getElementById('dlStatus').textContent='✓ HWPX 생성 준비 완료';
 
 
 
 
 
 
 
516
  }
517
 
518
- function updateProgress(){
519
- const pct=maxSearchCount>0?Math.min(100,(totalSearchCount/maxSearchCount)*100):0;
520
- document.getElementById('scBar').style.width=pct+'%';document.getElementById('searchCount').textContent=totalSearchCount;document.getElementById('statSearch').textContent=totalSearchCount;
521
- }
522
- function startElapsed(){
523
- pipeStartTime=Date.now();document.getElementById('pipeStart').textContent=new Date().toLocaleTimeString('ko-KR',{hour:'2-digit',minute:'2-digit',second:'2-digit'});
524
- elapsedTimer=setInterval(()=>{const sec=Math.floor((Date.now()-pipeStartTime)/1000);const m=Math.floor(sec/60),s=sec%60;const str=(m>0?m+'m ':'')+s+'s';document.getElementById('pipeElapsed').textContent=str;document.getElementById('statTime').textContent=str;},1000);
525
- }
526
- function stopElapsed(){if(elapsedTimer){clearInterval(elapsedTimer);elapsedTimer=null;}}
527
- function setStatus(label,cls='idle'){const chip=document.getElementById('pipelineChip');chip.className='chip chip-'+cls;chip.textContent=label;document.getElementById('statStatus').textContent=label.replace(/^. /,'');}
528
- function showToast(msg,cls=''){const t=document.getElementById('toast');t.textContent=msg;t.className='toast visible '+cls;setTimeout(()=>{t.className='toast';},3000);}
529
-
530
- function getBackendUrl(){return document.getElementById('backendUrl').value.trim()||'';}
531
-
532
- function runPipeline(){
533
- if(running){stopPipeline();return;}
534
- const prompt=document.getElementById('promptInput').value.trim();
535
- if(!prompt){showToast('⚠ 프롬프트를 입력하세요.','err');return;}
536
- running=true;streamText='';totalSearchCount=0;lastHmlPath='';finalDoc='';
537
- document.getElementById('streamBox').innerHTML='';document.getElementById('docArea').innerHTML='<div class="doc-empty">Generating...</div>';
538
- document.getElementById('searchFeedList').innerHTML='';document.getElementById('logBox').textContent='';
539
- document.getElementById('dlBtn').disabled=true;document.getElementById('dlFilename').textContent='파일 없음';
540
- document.getElementById('dlStatus').className='dl-status';document.getElementById('dlStatus').textContent='문서 생성 후 사용 가능합니다.';
541
- resetAgents();updateProgress();startElapsed();setStatus('● RUNNING','run');
542
- document.getElementById('btnLabel').textContent='⛔ Stop';document.getElementById('btnSpinner').classList.add('visible');document.getElementById('runBtn').classList.add('running');
543
- switchTab('stream',document.querySelectorAll('.tab-btn')[1]);
544
- const base=getBackendUrl(),url=base+'/soma/run';
545
- fetch(url,{method:'POST',headers:{'Content-Type':'application/json'},body:JSON.stringify({prompt,max_search:parseInt(document.getElementById('sliderSearch').value),temperature:parseFloat(document.getElementById('sliderTemp').value)})})
546
- .then(res=>{if(!res.ok)throw new Error('Server error: '+res.status);const reader=res.body.getReader(),decoder=new TextDecoder();let buf='',currentAgent='';
547
- function read(){reader.read().then(({done,value})=>{if(done){onPipelineDone();return;}buf+=decoder.decode(value,{stream:true});const lines=buf.split('\n');buf=lines.pop();
548
- lines.forEach(line=>{if(line.startsWith('data: ')){try{const evt=JSON.parse(line.slice(6));handleEvent(evt,currentAgent);if(evt.active)currentAgent=evt.active;}catch(e){}}});read();}).catch(err=>{onPipelineError(err.message);});}read();})
549
- .catch(err=>{onPipelineError(err.message);});
550
  }
551
 
552
- function handleEvent(evt,prevAgent){
553
- if(evt.done){if(evt.final_doc)showFinalDoc(evt.final_doc);if(evt.search_count)totalSearchCount=evt.search_count;updateProgress();onPipelineDone();return;}
554
- if(evt.active&&evt.active!==prevAgent){if(prevAgent)completeAgent(prevAgent);activateAgent(evt.active);}
555
- if(evt.stream)appendStream(evt.stream,evt.active);
556
- if(evt.search_count!==undefined&&evt.search_count!==totalSearchCount){totalSearchCount=evt.search_count;updateProgress();document.getElementById('streamAgentLabel').textContent='Search: '+totalSearchCount+'/'+maxSearchCount;}
557
- if(evt.new_search)addSearchFeed(totalSearchCount,evt.new_search,evt.active==='火'?'ar':'re');
558
- if(evt.log_line){logText+=evt.log_line+'\n';const lb=document.getElementById('logBox');lb.textContent=logText;lb.scrollTop=lb.scrollHeight;}
559
- if(evt.final_doc&&!evt.done)finalDoc=evt.final_doc;
 
 
 
560
  }
561
 
562
- function onPipelineDone(){
563
- running=false;stopElapsed();OHAENG.forEach(a=>completeAgent(a));setStatus('✓ DONE','done');
564
- document.getElementById('btnLabel').textContent='🚀 SOMA 실행';document.getElementById('btnSpinner').classList.remove('visible');document.getElementById('runBtn').classList.remove('running');
565
- document.getElementById('streamBadge').className='chip chip-done';document.getElementById('streamBadge').textContent='✓ Pipeline Complete';
566
- if(finalDoc){showFinalDoc(finalDoc);document.getElementById('dlBtn').disabled=false;}
567
- showToast('✅ SOMA 파이프라인 완료!','ok');
568
- }
569
- function onPipelineError(msg){
570
- running=false;stopElapsed();setStatus('✗ ERROR','err');
571
- document.getElementById('btnLabel').textContent='🚀 SOMA 실행';document.getElementById('btnSpinner').classList.remove('visible');document.getElementById('runBtn').classList.remove('running');
572
- showToast('❌ Error: '+msg,'err');appendStream('\n\n[ERROR] '+msg,null);
573
- }
574
- function stopPipeline(){running=false;if(eventSource){eventSource.close();eventSource=null;}stopElapsed();setStatus('■ STOPPED','idle');
575
- document.getElementById('btnLabel').textContent='🚀 SOMA 실행';document.getElementById('btnSpinner').classList.remove('visible');document.getElementById('runBtn').classList.remove('running');showToast('⛔ Pipeline stopped.');}
576
-
577
- function resetAll(){
578
- stopPipeline();resetAgents();totalSearchCount=0;streamText='';finalDoc='';lastHmlPath='';updateProgress();
579
- document.getElementById('streamBox').innerHTML='<span class="stream-empty">초기화되었습니다.</span>';
580
- document.getElementById('docArea').innerHTML='<div class="doc-empty">📄 문서가 생성되면 여기에 표시됩니다.</div>';
581
- document.getElementById('logBox').textContent='';document.getElementById('searchFeedList').innerHTML='';
582
- document.getElementById('pipeStart').textContent='–';document.getElementById('pipeElapsed').textContent='–';document.getElementById('pipeStage').textContent='–';
583
- document.getElementById('statTokens').textContent='0';document.getElementById('statTime').textContent='–';document.getElementById('statAgent').textContent='–';document.getElementById('statStatus').textContent='IDLE';
584
- document.getElementById('pipelineChip').className='chip chip-idle';document.getElementById('pipelineChip').textContent='● IDLE';
585
- document.getElementById('streamBadge').className='chip chip-idle';document.getElementById('streamBadge').textContent='Agent Idle';document.getElementById('streamAgentLabel').textContent='';
586
- document.getElementById('dlBtn').disabled=true;document.getElementById('dlFilename').textContent='파일 없음';
587
- document.getElementById('dlStatus').className='dl-status';document.getElementById('dlStatus').textContent='문서 생성 후 사용 가능합니다.';
588
- switchTab('prompt',document.querySelector('.tab-btn'));
589
  }
590
 
591
- function copyDoc(){if(!finalDoc){showToast('복사할 문서가 없습니다.','err');return;}navigator.clipboard.writeText(finalDoc).then(()=>{showToast('📋 클립보드에 복사되었습니다.','ok');});}
592
-
593
- async function downloadHml(){
594
- if(!finalDoc){showToast('문서를 먼저 생성하세요.','err');return;}
595
- document.getElementById('dlStatus').className='dl-status';document.getElementById('dlStatus').textContent='HWPX 변환 중...';
596
- const base=getBackendUrl();
597
- try{
598
- const res=await fetch(base+'/soma/hml',{method:'POST',headers:{'Content-Type':'application/json'},body:JSON.stringify({content:finalDoc})});
599
- if(!res.ok)throw new Error(await res.text());const data=await res.json();
600
- if(data.file_url){const a=document.getElementById('dlLink');a.href=base+data.file_url;a.download=data.filename||'문서.hwpx';a.click();
601
- document.getElementById('dlFilename').textContent=data.filename||'문서.hwpx';document.getElementById('dlStatus').className='dl-status ok';document.getElementById('dlStatus').textContent='✓ HWPX 다운로드 완료';showToast('✅ HWPX 파일을 다운로드합니다.','ok');
602
- }else{const blob=new Blob([finalDoc],{type:'text/xml;charset=utf-8'});const url=URL.createObjectURL(blob);const a=document.getElementById('dlLink');a.href=url;a.download='soma_document.hwpx';a.click();URL.revokeObjectURL(url);
603
- document.getElementById('dlStatus').className='dl-status ok';document.getElementById('dlStatus').textContent='✓ XML로 저장됨';}
604
- }catch(e){const blob=new Blob([finalDoc],{type:'text/plain;charset=utf-8'});const url=URL.createObjectURL(blob);const a=document.getElementById('dlLink');a.href=url;a.download='soma_document.txt';a.click();URL.revokeObjectURL(url);
605
- document.getElementById('dlStatus').className='dl-status err';document.getElementById('dlStatus').textContent='⚠ 텍스트로 저장됨 (서버 오류)';}
606
- }
607
  </script>
608
  </body>
609
- </html>
 
3
  <head>
4
  <meta charset="UTF-8">
5
  <meta name="viewport" content="width=device-width, initial-scale=1.0">
6
+ <title>World Model Bench (WM Bench) 2026 — Embodied AI Benchmark</title>
7
+ <meta name="description" content="The first benchmark measuring cognitive abilities of World Models. Beyond FID — Measuring Intelligence, Not Just Motion. By VIDRAFT / FINAL Bench Family.">
8
+ <meta name="keywords" content="world model benchmark, embodied AI, WM Bench, VIDRAFT, PROMETHEUS, cognitive AI, embodied intelligence, motion generation, AI benchmark 2026">
9
  <link href="https://fonts.googleapis.com/css2?family=Sora:wght@300;400;500;600;700;800&family=JetBrains+Mono:wght@400;500;600;700&display=swap" rel="stylesheet">
10
  <style>
11
  *{margin:0;padding:0;box-sizing:border-box;}
12
  :root{
13
+ --bg:#f8f9fc;--bg2:#f0f2f8;--surface:#ffffff;--surface-alt:#f5f6fa;
14
+ --border:#e2e5f0;--border-hover:#c7cce0;
 
 
15
  --shadow-sm:0 1px 3px rgba(15,23,42,.04),0 1px 2px rgba(15,23,42,.06);
16
+ --shadow:0 4px 16px rgba(15,23,42,.06),0 1px 3px rgba(15,23,42,.08);
17
  --shadow-lg:0 12px 40px rgba(15,23,42,.08),0 4px 12px rgba(15,23,42,.06);
18
+ --text:#0f172a;--text-sec:#475569;--text-muted:#94a3b8;
19
+ --ac:#e8593c;--ac2:#c94a2e;--ac-bg:rgba(232,89,60,.06);
20
+ --p1:#7b8fd4;--p2:#e8593c;--p3:#d4a044;
21
+ --teal:#0d9488;--green:#16a34a;--rose:#e11d48;--amber:#d97706;
22
+ --radius:16px;--radius-sm:10px;
23
  --font:'Sora',sans-serif;--mono:'JetBrains Mono',monospace;
24
  --tr:0.22s cubic-bezier(0.4,0,0.2,1);
25
  }
26
+ html{scroll-behavior:smooth;}
27
+ body{font-family:var(--font);background:var(--bg);color:var(--text);min-height:100vh;-webkit-font-smoothing:antialiased;font-size:13px;}
28
+ ::-webkit-scrollbar{width:5px;height:4px;}
 
 
29
  ::-webkit-scrollbar-track{background:transparent;}
30
+ ::-webkit-scrollbar-thumb{background:rgba(232,89,60,.2);border-radius:10px;}
31
+ ::-webkit-scrollbar-thumb:hover{background:rgba(232,89,60,.4);}
32
+ ::selection{background:rgba(232,89,60,.12);}
33
+ body::before{content:"";position:fixed;inset:0;z-index:0;pointer-events:none;
34
+ background:radial-gradient(ellipse 70% 45% at 15% 8%,rgba(232,89,60,.04),transparent 55%),
35
+ radial-gradient(ellipse 55% 35% at 85% 92%,rgba(212,160,68,.04),transparent 50%);}
36
+ .wrap{position:relative;z-index:1;max-width:1400px;margin:0 auto;padding:22px 16px 70px;}
37
+
38
+ /* HEADER */
39
+ header{text-align:center;margin-bottom:20px;animation:fadeIn .6s ease-out;}
40
+ @keyframes fadeIn{from{opacity:0;transform:translateY(-10px)}to{opacity:1;transform:translateY(0)}}
41
+ .badge-row{display:flex;align-items:center;justify-content:center;gap:8px;margin-bottom:10px;flex-wrap:wrap;}
42
+ .badge{display:inline-flex;align-items:center;gap:6px;background:var(--surface);border:1px solid var(--border);border-radius:100px;padding:4px 14px;font-family:var(--mono);font-size:9px;font-weight:600;letter-spacing:2px;text-transform:uppercase;color:var(--ac);box-shadow:var(--shadow-sm);}
43
+ .pulse{width:5px;height:5px;border-radius:50%;background:var(--ac);animation:p 2s infinite;}
44
+ @keyframes p{0%,100%{opacity:1;transform:scale(1)}50%{opacity:.4;transform:scale(.8)}}
45
+ h1{font-size:clamp(20px,3vw,38px);font-weight:800;line-height:1.1;letter-spacing:-1.5px;margin-bottom:6px;
46
+ background:linear-gradient(135deg,#1e1b4b 10%,#e8593c 50%,#d4a044 90%);background-size:200%;
47
+ -webkit-background-clip:text;-webkit-text-fill-color:transparent;animation:shimmer 6s ease-in-out infinite;}
48
  @keyframes shimmer{0%,100%{background-position:0%}50%{background-position:100%}}
49
+ .sub{color:var(--text-muted);font-size:10px;line-height:1.8;}
50
+ .sub b{color:var(--text-sec);font-weight:600;-webkit-text-fill-color:var(--text-sec);}
51
+
52
+ /* STATS */
53
+ .stats{display:flex;flex-wrap:wrap;gap:7px;justify-content:center;margin-bottom:16px;}
54
+ .st{background:var(--surface);border:1px solid var(--border);border-radius:var(--radius-sm);padding:8px 14px;text-align:center;min-width:80px;box-shadow:var(--shadow-sm);transition:var(--tr);}
55
+ .st:hover{box-shadow:var(--shadow);border-color:var(--border-hover);}
56
+ .stn{font-family:var(--mono);font-size:15px;font-weight:700;color:var(--ac);}
57
+ .stl{font-size:8.5px;color:var(--text-muted);margin-top:2px;text-transform:uppercase;letter-spacing:.5px;}
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
58
 
59
  /* TABS */
60
+ .tab-bar{display:flex;gap:0;border-bottom:1px solid var(--border);background:var(--surface);border-radius:var(--radius-sm) var(--radius-sm) 0 0;overflow-x:auto;box-shadow:var(--shadow-sm);}
61
+ .tab{padding:10px 20px;font-size:10.5px;font-family:var(--mono);font-weight:600;color:var(--text-muted);cursor:pointer;border-bottom:2px solid transparent;transition:var(--tr);user-select:none;white-space:nowrap;letter-spacing:.3px;flex-shrink:0;}
62
+ .tab:hover{color:var(--text);background:var(--ac-bg);}
63
+ .tab.on{color:var(--ac);border-bottom-color:var(--ac);background:var(--ac-bg);}
64
+ .tpane{display:none;padding-top:14px;}
65
+ .tpane.on{display:block;}
66
+
67
+ /* TABLE */
68
+ .tw{background:var(--surface);border:1px solid var(--border);border-radius:var(--radius);overflow-x:auto;box-shadow:var(--shadow);}
69
+ table{width:100%;border-collapse:collapse;font-size:11px;}
70
+ thead{background:var(--surface-alt);}
71
+ thead tr:last-child{border-bottom:2px solid var(--border);}
72
+ th{padding:8px 6px;text-align:center;font-size:8px;font-family:var(--mono);text-transform:uppercase;letter-spacing:.3px;color:var(--text-muted);white-space:nowrap;cursor:pointer;user-select:none;vertical-align:bottom;line-height:1.6;font-weight:600;}
73
+ th.c-model{text-align:left;padding-left:12px;min-width:180px;position:sticky;left:0;background:var(--surface-alt);z-index:2;}
74
+ th:hover,th.on{color:var(--ac);}
75
+ .sa{opacity:.5;font-size:6px;margin-left:2px;}
76
+ tbody tr{border-bottom:1px solid var(--border);transition:background var(--tr);}
77
+ tbody tr:last-child{border-bottom:none;}
78
+ tbody tr:hover{background:rgba(232,89,60,.02);}
79
+ tbody tr.hl{background:rgba(22,163,74,.025);}
80
+ tbody tr.hidden{display:none;}
81
+ td{padding:8px 6px;text-align:center;vertical-align:middle;}
82
+ td.c-model{text-align:left;padding-left:12px;position:sticky;left:0;background:var(--surface);z-index:1;}
83
+ tbody tr:hover td.c-model{background:rgba(232,89,60,.02);}
84
+
85
+ /* MODEL CELL */
86
+ .mc{display:flex;flex-direction:column;gap:2px;}
87
+ .mn{font-weight:700;font-size:12px;color:var(--text);display:flex;align-items:center;gap:4px;}
88
+ .mp{font-size:8px;color:var(--text-muted);font-family:var(--mono);}
89
+
90
+ /* SCORE CELL */
91
+ .sc{display:flex;flex-direction:column;align-items:center;gap:2px;}
92
+ .sn{font-family:var(--mono);font-size:11px;font-weight:700;}
93
+ .sb{width:36px;height:3px;background:var(--border);border-radius:2px;overflow:hidden;}
94
+ .sf{height:100%;border-radius:2px;}
95
+
96
+ /* GRADE BADGE */
97
+ .gr{display:inline-block;padding:2px 7px;border-radius:5px;font-family:var(--mono);font-size:9px;font-weight:800;}
98
+ .gr-S{background:rgba(255,215,0,.15);color:#b8860b;border:1px solid rgba(255,215,0,.4);}
99
+ .gr-A{background:rgba(192,192,192,.15);color:#708090;border:1px solid rgba(192,192,192,.4);}
100
+ .gr-B{background:rgba(205,127,50,.15);color:#8b6914;border:1px solid rgba(205,127,50,.4);}
101
+ .gr-C{background:rgba(99,102,241,.1);color:#4f46e5;border:1px solid rgba(99,102,241,.2);}
102
+ .gr-D{background:rgba(100,116,139,.1);color:#64748b;border:1px solid rgba(100,116,139,.2);}
103
+ .gr-F{background:rgba(225,29,72,.1);color:#e11d48;border:1px solid rgba(225,29,72,.2);}
104
+
105
+ /* TRACK BADGE */
106
+ .tb{display:inline-block;padding:1.5px 6px;border-radius:4px;font-family:var(--mono);font-size:8px;font-weight:700;}
107
+ .tb-C{background:rgba(22,163,74,.1);color:#16a34a;border:1px solid rgba(22,163,74,.2);}
108
+ .tb-B{background:rgba(99,102,241,.1);color:#6366f1;border:1px solid rgba(99,102,241,.2);}
109
+ .tb-A{background:rgba(100,116,139,.1);color:#64748b;border:1px solid rgba(100,116,139,.2);}
110
+
111
+ /* PILLAR COLS */
112
+ .p1-col{background:rgba(123,143,212,.03);}
113
+ .p2-col{background:rgba(232,89,60,.03);}
114
+ .p3-col{background:rgba(212,160,68,.03);}
115
+
116
+ /* CARDS */
117
+ .card{background:var(--surface);border:1px solid var(--border);border-radius:var(--radius);padding:18px;box-shadow:var(--shadow-sm);transition:var(--tr);}
118
+ .card:hover{box-shadow:var(--shadow);border-color:var(--border-hover);}
119
+ .card h3{font-size:11px;font-family:var(--mono);font-weight:700;color:var(--ac);text-transform:uppercase;letter-spacing:.8px;margin-bottom:4px;}
120
+ .card p{font-size:9.5px;color:var(--text-muted);line-height:1.7;margin-bottom:10px;}
121
+ .grid2{display:grid;grid-template-columns:1fr 1fr;gap:12px;}
122
+ .grid3{display:grid;grid-template-columns:1fr 1fr 1fr;gap:12px;}
123
+
124
+ /* BAR CHARTS */
125
+ .bar-row{display:flex;align-items:center;gap:8px;margin-bottom:6px;}
126
+ .bar-label{font-size:9px;font-family:var(--mono);color:var(--text-sec);width:180px;flex-shrink:0;white-space:nowrap;overflow:hidden;text-overflow:ellipsis;}
127
+ .bar-track{flex:1;height:8px;background:var(--bg2);border-radius:4px;overflow:hidden;}
128
+ .bar-fill{height:100%;border-radius:4px;transition:width .8s cubic-bezier(.4,0,.2,1);}
129
+ .bar-val{font-size:9px;font-family:var(--mono);font-weight:700;color:var(--text);width:36px;text-align:right;flex-shrink:0;}
130
+
131
+ /* PILLAR BOXES */
132
+ .pillar-box{border-radius:var(--radius-sm);padding:14px 16px;border:1px solid var(--border);}
133
+ .pillar-p1{background:linear-gradient(135deg,rgba(123,143,212,.08),rgba(123,143,212,.03));border-color:rgba(123,143,212,.25);}
134
+ .pillar-p2{background:linear-gradient(135deg,rgba(232,89,60,.08),rgba(232,89,60,.03));border-color:rgba(232,89,60,.25);}
135
+ .pillar-p3{background:linear-gradient(135deg,rgba(212,160,68,.08),rgba(212,160,68,.03));border-color:rgba(212,160,68,.25);}
136
+
137
+ /* LEGEND */
138
+ .leg{margin-top:12px;display:flex;flex-wrap:wrap;gap:10px;align-items:center;}
139
+ .lt{font-size:8.5px;font-family:var(--mono);color:var(--text-muted);text-transform:uppercase;letter-spacing:.8px;font-weight:600;}
140
+ .li{display:flex;align-items:center;gap:3px;font-size:9.5px;color:var(--text-sec);}
141
+ .ld{width:7px;height:7px;border-radius:50%;}
142
+
143
+ /* INSIGHT BOX */
144
+ .insight{padding:10px 14px;background:var(--ac-bg);border-radius:8px;border-left:3px solid var(--ac);font-size:9px;color:var(--text-sec);line-height:1.7;}
145
+ .insight b{color:var(--ac);}
146
+
147
+ /* MODAL */
148
+ .modal-overlay{display:none;position:fixed;inset:0;background:rgba(15,23,42,.5);z-index:1000;justify-content:center;align-items:center;backdrop-filter:blur(4px);}
149
+ .modal-overlay.open{display:flex;}
150
+ .modal-box{background:var(--surface);border:1px solid var(--border);border-radius:var(--radius);padding:24px;max-width:640px;width:92%;max-height:85vh;overflow-y:auto;box-shadow:var(--shadow-lg);position:relative;animation:modalIn .2s ease;}
151
+ @keyframes modalIn{from{opacity:0;transform:scale(.95)}to{opacity:1;transform:scale(1)}}
152
+ .modal-close{position:absolute;top:12px;right:16px;background:none;border:none;font-size:20px;cursor:pointer;color:var(--text-muted);}
153
+ .modal-close:hover{color:var(--text);}
154
+
155
+ /* DARK MODE */
156
+ body.dark{--bg:#0f172a;--bg2:#1e293b;--surface:#1e293b;--surface-alt:#334155;
157
+ --border:#334155;--border-hover:#475569;--text:#e2e8f0;--text-sec:#94a3b8;--text-muted:#64748b;
158
+ --shadow-sm:0 1px 3px rgba(0,0,0,.3);--shadow:0 4px 16px rgba(0,0,0,.3);--shadow-lg:0 12px 40px rgba(0,0,0,.4);}
159
+ body.dark th.c-model,body.dark td.c-model{background:var(--surface)!important;}
160
+ body.dark thead{background:var(--surface-alt)!important;}
161
+
162
+ /* MOBILE */
163
+ @media(max-width:768px){
164
+ .wrap{padding:10px 8px 40px;}
165
+ h1{font-size:20px!important;}
166
+ .tab-bar{flex-wrap:nowrap;}
167
+ .grid2,.grid3{grid-template-columns:1fr!important;}
168
+ th.c-model,td.c-model{position:static!important;}
169
+ }
170
  </style>
171
  </head>
172
  <body>
173
+ <div class="wrap">
174
+
175
+ <!-- ===== HEADER ===== -->
176
+ <header>
177
+ <div class="badge-row">
178
+ <div class="badge"><div class="pulse"></div>LIVE · 2026.03 · v1.0</div>
179
+ <button onclick="document.body.classList.toggle('dark');localStorage.setItem('wm-dark',document.body.classList.contains('dark'));this.textContent=document.body.classList.contains('dark')?'☀️ Light':'🌙 Dark'"
180
+ style="background:var(--surface);border:1px solid var(--border);border-radius:20px;padding:4px 14px;font-size:10px;font-family:var(--mono);color:var(--text-sec);cursor:pointer;font-weight:700;transition:all .2s;box-shadow:var(--shadow-sm)">🌙 Dark</button>
181
+ <div style="display:flex;gap:4px">
182
+ <a href="https://huggingface.co/datasets/VIDraft/WorldModelBench" target="_blank"
183
+ style="display:inline-flex;align-items:center;gap:4px;background:linear-gradient(135deg,#ff9d00,#ffcd00);color:#1a1a2e;font-family:var(--mono);font-size:8px;font-weight:800;padding:3px 10px;border-radius:14px;text-decoration:none;box-shadow:0 1px 3px rgba(255,157,0,.3)">🤗 HF Dataset</a>
184
+ <a href="https://huggingface.co/spaces/FINAL-Bench/all-bench-leaderboard" target="_blank"
185
+ style="display:inline-flex;align-items:center;gap:4px;background:linear-gradient(135deg,#7c3aed,#6366f1);color:#fff;font-family:var(--mono);font-size:8px;font-weight:800;padding:3px 10px;border-radius:14px;text-decoration:none">🏆 ALL Bench</a>
186
+ <a href="https://huggingface.co/spaces/FINAL-Bench/Leaderboard" target="_blank"
187
+ style="display:inline-flex;align-items:center;gap:4px;background:linear-gradient(135deg,#0d9488,#059669);color:#fff;font-family:var(--mono);font-size:8px;font-weight:800;padding:3px 10px;border-radius:14px;text-decoration:none">🧬 FINAL Bench</a>
188
+ </div>
189
+ </div>
190
 
191
+ <h1>🔥 World Model Bench 2026</h1>
192
+ <p class="sub" style="margin-bottom:8px">
193
+ <b>Beyond FID — Measuring Intelligence, Not Just Motion.</b> The first benchmark for evaluating <b>cognitive abilities</b> of World Models in Embodied Intelligence.<br>
194
+ 3 Pillars · 10 Categories · 100 Scenarios · Automatic Scoring · Part of <b>FINAL Bench Family</b> by VIDRAFT
195
+ </p>
196
+
197
+ <div style="display:inline-flex;align-items:center;gap:8px;background:linear-gradient(135deg,rgba(232,89,60,.06),rgba(212,160,68,.04));border:1px solid var(--border);border-radius:10px;padding:6px 14px;margin-bottom:8px;font-size:9px;line-height:1.6">
198
+ <span style="font-family:var(--mono);font-weight:700;color:var(--ac)">WM Score = P1(250) + P2(450) + P3(300)</span>
199
+ <span style="color:var(--text-muted)"></span>
200
+ <span style="color:var(--text-sec)">👁 Perception · 🧠 Cognition · 🔥 Embodiment</span>
201
+ <span style="color:var(--text-muted)"></span>
202
+ <span>
203
+ <span style="color:#b8860b;font-weight:700">S</span><span style="color:var(--text-muted)">≥900</span> &nbsp;
204
+ <span style="color:#708090;font-weight:700">A</span><span style="color:var(--text-muted)">≥750</span> &nbsp;
205
+ <span style="color:#8b6914;font-weight:700">B</span><span style="color:var(--text-muted)">≥600</span> &nbsp;
206
+ <span style="color:#4f46e5;font-weight:700">C</span><span style="color:var(--text-muted)">≥400</span>
207
+ </span>
208
+ </div>
209
+ </header>
210
+
211
+ <!-- ===== STATS ===== -->
212
+ <div class="stats">
213
+ <div class="st"><div class="stn">1</div><div class="stl">Models</div></div>
214
+ <div class="st"><div class="stn">3</div><div class="stl">Pillars</div></div>
215
+ <div class="st"><div class="stn">10</div><div class="stl">Categories</div></div>
216
+ <div class="st"><div class="stn">100</div><div class="stl">Scenarios</div></div>
217
+ <div class="st"><div class="stn" style="color:var(--green)">726</div><div class="stl">Top Score</div></div>
218
+ <div class="st"><div class="stn">1000</div><div class="stl">Max Score</div></div>
219
  </div>
220
 
221
+ <!-- ===== TABS ===== -->
222
+ <div class="tab-bar">
223
+ <div class="tab on" onclick="showTab('lb',this)">🏆 Leaderboard</div>
224
+ <div class="tab" onclick="showTab('cats',this)">📊 Categories</div>
225
+ <div class="tab" onclick="showTab('structure',this)">📐 Structure</div>
226
+ <div class="tab" onclick="showTab('submit',this)">📝 Submit</div>
227
+ <div class="tab" onclick="showTab('about',this)">ℹ️ About</div>
228
+ </div>
229
 
230
+ <!-- ===== TAB: LEADERBOARD ===== -->
231
+ <div id="lb" class="tpane on">
232
+ <div class="tw">
233
+ <table>
234
+ <thead>
235
+ <tr>
236
+ <th class="c-model" style="text-align:left">Model</th>
237
+ <th onclick="srt(0)" title="WM Score (0~1000)">WM Score<span class="sa"></span></th>
238
+ <th>Grade</th>
239
+ <th onclick="srt(1)" class="p1-col" title="👁 Perception (0~250)">👁 인식<span class="sa">↕</span></th>
240
+ <th onclick="srt(2)" class="p2-col" title="🧠 Cognition (0~450)">🧠 인지<span class="sa">↕</span></th>
241
+ <th onclick="srt(3)" class="p3-col" title="🔥 Embodiment (0~300)">🔥 구현<span class="sa">↕</span></th>
242
+ <th onclick="srt(4)" title="FPS">FPS<span class="sa">↕</span></th>
243
+ <th onclick="srt(5)" title="Cognitive Latency (ms)">Lat(ms)<span class="sa">↕</span></th>
244
+ <th>Track</th>
245
+ <th>Brain</th>
246
+ <th>Motion</th>
247
+ <th>GPU</th>
248
+ </tr>
249
+ </thead>
250
+ <tbody id="LB_BODY"></tbody>
251
+ </table>
252
+ </div>
253
 
254
+ <div class="leg">
255
+ <span class="lt">Grade:</span>
256
+ <div class="li"><div class="ld" style="background:#b8860b"></div>S≥900</div>
257
+ <div class="li"><div class="ld" style="background:#708090"></div>A≥750</div>
258
+ <div class="li"><div class="ld" style="background:#8b6914"></div>B≥600</div>
259
+ <div class="li"><div class="ld" style="background:#4f46e5"></div>C≥400</div>
260
+ <div class="li"><div class="ld" style="background:#64748b"></div>D≥200</div>
261
+ <div class="li"><div class="ld" style="background:#e11d48"></div>F&lt;200</div>
262
+ <span style="font-family:var(--mono);font-size:8.5px;color:var(--green);margin-left:10px">✓ Track C = Live Demo Verified</span>
263
+ </div>
264
 
265
+ <div style="margin-top:16px;padding:12px 16px;background:var(--surface);border:1px solid var(--border);border-radius:var(--radius-sm);font-size:9px;color:var(--text-sec);line-height:1.7">
266
+ <b style="color:var(--ac)">Track A</b> = Text-Only · 최대 750점 &nbsp;│&nbsp;
267
+ <b style="color:#6366f1">Track B</b> = Text + Performance · 최대 1000점 &nbsp;│&nbsp;
268
+ <b style="color:var(--green)">Track C</b> = Live Demo + Verified · 최대 1000점 + ✓
269
+ </div>
270
+ </div>
 
 
271
 
272
+ <!-- ===== TAB: CATEGORIES ===== -->
273
+ <div id="cats" class="tpane">
274
+ <!-- P1 -->
275
+ <div class="pillar-box pillar-p1" style="margin-bottom:12px">
276
+ <div style="display:flex;align-items:center;gap:10px;margin-bottom:12px">
277
+ <span style="font-size:1.6rem">👁</span>
278
+ <div>
279
+ <div style="font-size:12px;font-weight:800;color:var(--p1)">P1 · Perception (인식)</div>
280
+ <div style="font-size:9px;color:var(--text-muted);font-family:var(--mono)">비중 25% · 최대 250점 · 환경을 얼마나 정확하게 인식하는가</div>
281
  </div>
282
+ <div style="margin-left:auto;text-align:right">
283
+ <div style="font-family:var(--mono);font-size:22px;font-weight:800;color:var(--p1)">140</div>
284
+ <div style="font-size:8px;color:var(--text-muted)">PROMETHEUS / 250</div>
 
 
 
 
 
285
  </div>
286
  </div>
287
+ <div id="bars-p1"></div>
288
+ </div>
289
 
290
+ <!-- P2 -->
291
+ <div class="pillar-box pillar-p2" style="margin-bottom:12px">
292
+ <div style="display:flex;align-items:center;gap:10px;margin-bottom:12px">
293
+ <span style="font-size:1.6rem">🧠</span>
294
  <div>
295
+ <div style="font-size:12px;font-weight:800;color:var(--p2)">P2 · Cognition (인지)</div>
296
+ <div style="font-size:9px;color:var(--text-muted);font-family:var(--mono)">비중 45% · 최대 450점 · 인식 정보로 얼마나 지능적으로 판단하는가</div>
 
 
 
 
297
  </div>
298
+ <div style="margin-left:auto;text-align:right">
299
+ <div style="font-family:var(--mono);font-size:22px;font-weight:800;color:var(--p2)">390</div>
300
+ <div style="font-size:8px;color:var(--text-muted)">PROMETHEUS / 450</div>
 
 
 
 
 
301
  </div>
302
  </div>
303
+ <div id="bars-p2"></div>
304
  </div>
305
 
306
+ <!-- P3 -->
307
+ <div class="pillar-box pillar-p3" style="margin-bottom:12px">
308
+ <div style="display:flex;align-items:center;gap:10px;margin-bottom:12px">
309
+ <span style="font-size:1.6rem">🔥</span>
310
+ <div>
311
+ <div style="font-size:12px;font-weight:800;color:var(--p3)">P3 · Embodiment (구현)</div>
312
+ <div style="font-size:9px;color:var(--text-muted);font-family:var(--mono)">비중 30% · 최대 300점 · 판단이 얼마나 자연스럽게 신체로 표현되는가</div>
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
313
  </div>
314
+ <div style="margin-left:auto;text-align:right">
315
+ <div style="font-family:var(--mono);font-size:22px;font-weight:800;color:var(--p3)">196</div>
316
+ <div style="font-size:8px;color:var(--text-muted)">PROMETHEUS / 300</div>
 
 
 
 
 
 
 
 
 
 
 
 
 
317
  </div>
318
  </div>
319
+ <div id="bars-p3"></div>
320
+ </div>
321
 
322
+ <div class="insight">
323
+ <b>왜 Cognition이 45%인가?</b><br>
324
+ 기존 월드모델 벤치마크(HumanML3D, BABEL)는 모션 품질(FID)만 측정한다. 기존 모델들은 "인식"과 "모션"은 있지만 "판단"이 없다.
325
+ WM Bench는 예측·위협차별·감정에스컬레이션·맥락기억·위협해제 — 어떤 기존 벤치마크도 측정하지 않는 능력을 가장 높은 비중으로 평가한다.
326
+ </div>
327
+ </div>
 
 
 
 
 
328
 
329
+ <!-- ===== TAB: STRUCTURE ===== -->
330
+ <div id="structure" class="tpane">
331
+ <div class="grid2" style="margin-bottom:14px">
332
+ <div class="card">
333
+ <h3>입출력 포맷</h3>
334
+ <p>모든 참가 모델은 동일한 텍스트 인터페이스로 평가됩니다. 3D 환경 불필요.</p>
335
+ <div style="background:var(--bg2);border-radius:8px;padding:12px;font-family:var(--mono);font-size:9px;color:var(--text-sec);line-height:1.9">
336
+ <div style="color:var(--text-muted);margin-bottom:4px">INPUT: scene_context JSON</div>
337
+ <div style="color:var(--text)">{</div>
338
+ <div style="color:var(--text);padding-left:12px">"walls": {"left": 3.0, "right": null},</div>
339
+ <div style="color:var(--text);padding-left:12px">"npc_type": "beast", "npc_distance": 4.5</div>
340
+ <div style="color:var(--text)">}</div>
341
+ <div style="margin-top:8px;color:var(--text-muted)">OUTPUT: 2줄 필수</div>
342
+ <div style="color:var(--p2)">PREDICT: left=danger(wall), right=safe, fwd=danger(beast)</div>
343
+ <div style="color:var(--p3)">MOTION: a person sprinting right in desperate terror</div>
344
  </div>
345
  </div>
346
+ <div class="card">
347
+ <h3>채점 원칙</h3>
348
+ <p>모든 채점은 정량적이며 결정론적입니다. 주관적 판단 0%.</p>
349
+ <div style="display:flex;flex-direction:column;gap:7px">
350
+ <div style="display:flex;align-items:flex-start;gap:8px;font-size:9px">
351
+ <span style="color:var(--green);font-weight:700;flex-shrink:0"></span>
352
+ <span style="color:var(--text-sec)"><b>정량적</b> — 키워드 파싱 + 수치 비교, 주관 판단 없음</span>
353
+ </div>
354
+ <div style="display:flex;align-items:flex-start;gap:8px;font-size:9px">
355
+ <span style="color:var(--green);font-weight:700;flex-shrink:0">✓</span>
356
+ <span style="color:var(--text-sec)"><b>결정론적</b> — 동일 입력 → 동일 점수 (temperature=0.0)</span>
357
+ </div>
358
+ <div style="display:flex;align-items:flex-start;gap:8px;font-size:9px">
359
+ <span style="color:var(--green);font-weight:700;flex-shrink:0">✓</span>
360
+ <span style="color:var(--text-sec)"><b>제3자 재현</b> — 채점 코드 전체 공개</span>
361
+ </div>
362
+ <div style="display:flex;align-items:flex-start;gap:8px;font-size:9px">
363
+ <span style="color:var(--green);font-weight:700;flex-shrink:0">✓</span>
364
+ <span style="color:var(--text-sec)"><b>3D 불필요</b> — API 하나면 어떤 모델도 참여 가능</span>
365
+ </div>
366
+ <div style="display:flex;align-items:flex-start;gap:8px;font-size:9px">
367
+ <span style="color:var(--green);font-weight:700;flex-shrink:0">✓</span>
368
+ <span style="color:var(--text-sec)"><b>셀프 평가 아님</b> — 우리 채점기가 판정</span>
369
  </div>
 
370
  </div>
371
  </div>
372
  </div>
373
 
374
+ <!-- 10 카테고리 -->
375
+ <div class="tw" style="margin-bottom:14px">
376
+ <table>
377
+ <thead>
378
+ <tr>
379
+ <th style="text-align:left;padding-left:12px;min-width:60px">Cat</th>
380
+ <th style="text-align:left;min-width:180px">카테고리</th>
381
+ <th style="text-align:left">Pillar</th>
382
+ <th>만점</th>
383
+ <th style="text-align:left">세계 최초?</th>
384
+ <th style="text-align:left;min-width:220px">측정 내용</th>
385
+ </tr>
386
+ </thead>
387
+ <tbody id="CAT_TABLE"></tbody>
388
+ </table>
389
+ </div>
390
 
391
+ <!-- FINAL Bench Family -->
392
+ <div class="card">
393
+ <h3>FINAL Bench Family</h3>
394
+ <div style="display:flex;gap:12px;flex-wrap:wrap">
395
+ <div style="flex:1;min-width:200px;padding:12px;background:var(--bg);border-radius:8px;border:1px solid var(--border)">
396
+ <div style="font-size:10px;font-weight:800;color:#7c3aed;margin-bottom:4px">🧬 FINAL Bench</div>
397
+ <div style="font-size:9px;color:var(--text-sec);line-height:1.6">텍스트 AGI 측정 · 글로벌 데이터셋 5위<br>언론 4곳 보도 (2026.02)</div>
398
+ <a href="https://huggingface.co/datasets/FINAL-Bench/Metacognitive" target="_blank" style="font-size:8px;color:#7c3aed;font-family:var(--mono)">↗ 바로가기</a>
399
  </div>
400
+ <div style="flex:1;min-width:200px;padding:12px;background:linear-gradient(135deg,rgba(232,89,60,.06),rgba(212,160,68,.04));border-radius:8px;border:1px solid rgba(232,89,60,.2)">
401
+ <div style="font-size:10px;font-weight:800;color:var(--ac);margin-bottom:4px">🔥 WM Bench <span style="font-size:7px;background:var(--ac);color:#fff;padding:1px 5px;border-radius:4px">NEW</span></div>
402
+ <div style="font-size:9px;color:var(--text-sec);line-height:1.6">체화 AGI (월드모델) 측정 · 세계 최초<br>인지 능력 정량 평가</div>
403
+ <span style="font-size:8px;color:var(--ac);font-family:var(--mono)">← 현재 페이지</span>
404
  </div>
405
  </div>
406
+ </div>
407
+ </div>
408
 
409
+ <!-- ===== TAB: SUBMIT ===== -->
410
+ <div id="submit" class="tpane">
411
+ <div class="grid2" style="margin-bottom:14px">
412
+ <div class="card">
413
+ <h3>📤 Track A Text Only</h3>
414
+ <p>가장 간단. LLM, 기반 시스템 등 모두 참여 가능. 최대 750점.</p>
415
+ <ol style="font-size:9.5px;color:var(--text-sec);line-height:2;padding-left:16px">
416
+ <li>OpenAI-compatible API 엔드포인트 준비</li>
417
+ <li><code style="background:var(--bg2);padding:1px 4px;border-radius:3px;font-family:var(--mono)">wm_bench_dataset.json</code> 100 시나리오 응답</li>
418
+ <li>PREDICT + MOTION 2줄 포맷 출력</li>
419
+ <li>결과 JSON을 HF Discussion에 제출</li>
420
+ </ol>
421
  </div>
422
+ <div class="card">
423
+ <h3>🎯 Track B/C — Full Evaluation</h3>
424
+ <p>Track A + 성능 메트릭 or 라이브 데모. 최대 1000점.</p>
425
+ <ol style="font-size:9.5px;color:var(--text-sec);line-height:2;padding-left:16px">
426
+ <li>Track A 완료</li>
427
+ <li>FPS, Latency, GPU 메트릭 측정</li>
428
+ <li>Track C: 실제 동작 데모 URL 포함</li>
429
+ <li>HF Discussion에 전체 JSON 제출</li>
430
+ </ol>
431
  </div>
432
+ </div>
433
 
434
+ <div class="card" style="margin-bottom:14px">
435
+ <h3>제출 JSON 형식</h3>
436
+ <div style="background:var(--bg2);border-radius:8px;padding:14px;font-family:var(--mono);font-size:9px;color:var(--text-sec);line-height:1.8;overflow-x:auto">
437
+ <pre style="margin:0">{
438
+ "benchmark": "WM Bench v1.0",
439
+ "model_name": "YourModel v1.0",
440
+ "organization": "YourOrg",
441
+ "track": "A",
442
+ "wm_score": 0,
443
+ "grade": "?",
444
+ "fps": 0,
445
+ "cognitive_latency_ms": 0,
446
+ "gpu": "NVIDIA A100",
447
+ "pillar_scores": {
448
+ "P1_perception": 0,
449
+ "P2_cognition": 0,
450
+ "P3_embodiment": 0
451
+ },
452
+ "category_scores": {
453
+ "C01":0,"C02":0,"C03":0,"C04":0,"C05":0,
454
+ "C06":0,"C07":0,"C08":0,"C09":0,"C10":0
455
+ },
456
+ "paper_url": "",
457
+ "demo_url": ""
458
+ }</pre>
459
  </div>
460
  </div>
461
 
462
+ <div style="text-align:center;padding:16px">
463
+ <a href="https://huggingface.co/datasets/VIDraft/WorldModelBench/discussions" target="_blank"
464
+ style="display:inline-flex;align-items:center;gap:6px;background:linear-gradient(135deg,var(--ac),var(--ac2));color:#fff;font-family:var(--mono);font-size:11px;font-weight:800;padding:10px 24px;border-radius:20px;text-decoration:none;box-shadow:0 4px 14px rgba(232,89,60,.3)">
465
+ 📝 Submit Your Model →
466
+ </a>
467
+ </div>
468
  </div>
469
 
470
+ <!-- ===== TAB: ABOUT ===== -->
471
+ <div id="about" class="tpane">
472
+ <div style="display:grid;grid-template-columns:repeat(auto-fill,minmax(260px,1fr));gap:10px">
473
+ <div class="card">
474
+ <h3>🔥 WM Bench란?</h3>
475
+ <p>기존 벤치마크(HumanML3D, BABEL)는 모션 품질(FID)만 측정한다. WM Bench는 월드모델의 <b>인지 능력</b>을 측정하는 세계 최초의 벤치마크입니다.</p>
476
+ </div>
477
+ <div class="card">
478
+ <h3>🧬 세계 최초 측정 항목</h3>
479
+ <p>C05 자율 감정 에스컬레이션, C10 신체 교체 확장성은 선행 연구가 전무한 항목입니다. C03·C04·C06·C07·C08도 WM Bench가 최초로 정의합니다.</p>
480
+ </div>
481
+ <div class="card">
482
+ <h3>📊 VIDRAFT PROMETHEUS</h3>
483
+ <p>현재 기준점(Baseline). Kimi K2.5 두뇌 + FloodDiffusion Tiny 모션. L40S 48GB GPU. 47 FPS. WM Score 726/1000 (B등급).</p>
484
+ </div>
485
+ <div class="card">
486
+ <h3>📋 버전 이력</h3>
487
+ <p style="font-family:var(--mono);font-size:9px;line-height:2;color:var(--text-sec)">
488
+ v1.0 (2026.03) — 최초 공개<br>
489
+ 100 시나리오 · 자동 채점<br>
490
+ 3 Tracks · 10 Categories<br>
491
+ PROMETHEUS 기준점 등록
492
+ </p>
493
+ </div>
494
+ <div class="card">
495
+ <h3>📄 인용</h3>
496
+ <div style="background:var(--bg2);border-radius:6px;padding:10px;font-family:var(--mono);font-size:8.5px;color:var(--text-sec);line-height:1.8">
497
+ @dataset{wmbench2026,<br>
498
+ &nbsp; title={World Model Bench},<br>
499
+ &nbsp; author={Kim Taebong},<br>
500
+ &nbsp; year={2026},<br>
501
+ &nbsp; publisher={VIDRAFT}<br>
502
+ }
503
+ </div>
504
+ </div>
505
+ <div class="card">
506
+ <h3>⚖️ 라이센스</h3>
507
+ <p>데이터셋: <b>CC-BY-SA-4.0</b><br>채점 코드: <b>Apache 2.0</b><br>자유롭게 사용·인용 가능. 단 출처 명시 필수.</p>
508
+ </div>
509
+ </div>
510
  </div>
511
 
512
+ </div><!-- /wrap -->
513
 
514
+ <!-- ===== DATA ===== -->
515
  <script>
516
+ const LB_DATA = [
517
+ {
518
+ model:"VIDRAFT PROMETHEUS v1.0", org:"VIDRAFT", date:"2026-03",
519
+ wm:726, grade:"B",
520
+ p1:140, p2:390, p3:196,
521
+ fps:47.0, lat:3100, track:"C",
522
+ brain:"Kimi K2.5", motion:"FloodDiffusion Tiny", gpu:"L40S 48GB",
523
+ cats:{C01:65,C02:75,C03:85,C04:90,C05:85,C06:60,C07:70,C08:80,C09:85,C10:35}
524
+ }
525
+ ];
526
+
527
+ const CAT_DATA = [
528
+ {id:"C01",name:"환경 인식 정확도",pillar:"P1",max:100,score:65,first:"",desc:"주변 벽·장애물·지형을 정확히 파악"},
529
+ {id:"C02",name:"개체 인식 및 분류",pillar:"P1",max:100,score:75,first:"",desc:"NPC를 맹수/사람/환경으로 정확히 분류"},
530
+ {id:"C03",name:"예측 기반 추론",pillar:"P2",max:100,score:85,first:"✦",desc:"4방향 미래 결과 예측 → 최선 선택"},
531
+ {id:"C04",name:"위협 유형별 차별 반응",pillar:"P2",max:100,score:90,first:"✦",desc:"맹수→전력질주 vs 사람→걸어서 회피"},
532
+ {id:"C05",name:"자율 감정 에스컬레이션",pillar:"P2",max:100,score:85,first:"✦✦",desc:"위협 지속 시 감정 자율 격화"},
533
+ {id:"C06",name:"맥락 기억 및 활용",pillar:"P2",max:100,score:60,first:"✦",desc:"이전 실패 기억 → 다음 판단 반영"},
534
+ {id:"C07",name:"위협 해제 후 적응",pillar:"P2",max:100,score:70,first:"✦",desc:"위협 소멸 후 서서히 정상화+경계"},
535
+ {id:"C08",name:"모션 감정 표현력",pillar:"P3",max:100,score:80,first:"✦",desc:"판단 감정이 모션에 반영되는 풍부함"},
536
+ {id:"C09",name:"실시간 인지-행동 성능",pillar:"P3",max:100,score:85,first:"",desc:"인지 루프 FPS + 지연시간"},
537
+ {id:"C10",name:"신체 교체 확장성",pillar:"P3",max:100,score:35,first:"✦✦",desc:"동일 두뇌로 다른 신체(로봇/드론) 적용"},
538
+ ];
539
+
540
+ const PILLAR_COLOR = {P1:"#7b8fd4",P2:"#e8593c",P3:"#d4a044"};
541
+
542
+ function gradeClass(g){return `gr gr-${g}`;}
543
+ function trackClass(t){return `tb tb-${t}`;}
544
+ function scoreBar(v,max,color){
545
+ const pct=Math.round(v/max*100);
546
+ return `<div class="sc"><div class="sn" style="color:${color}">${v}</div><div class="sb"><div class="sf" style="width:${pct}%;background:${color}"></div></div></div>`;
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
547
  }
 
548
 
549
+ function renderLB(){
550
+ const tb=document.getElementById('LB_BODY');
551
+ tb.innerHTML=LB_DATA.map((r,i)=>`
552
+ <tr class="${i===0?'hl':''}">
553
+ <td class="c-model">
554
+ <div class="mc">
555
+ <div class="mn">
556
+ <span style="display:inline-flex;align-items:center;justify-content:center;width:20px;height:20px;border-radius:6px;background:linear-gradient(135deg,#e8593c,#d4a044);color:#fff;font-size:9px;font-weight:800;flex-shrink:0">${i+1}</span>
557
+ ${r.model}
558
+ </div>
559
+ <div class="mp">${r.org} · ${r.date}</div>
560
+ </div>
561
+ </td>
562
+ <td>${scoreBar(r.wm,1000,'#e8593c')}</td>
563
+ <td><span class="${gradeClass(r.grade)}">${r.grade}</span></td>
564
+ <td class="p1-col">${scoreBar(r.p1,250,PILLAR_COLOR.P1)}</td>
565
+ <td class="p2-col">${scoreBar(r.p2,450,PILLAR_COLOR.P2)}</td>
566
+ <td class="p3-col">${scoreBar(r.p3,300,PILLAR_COLOR.P3)}</td>
567
+ <td><span style="font-family:var(--mono);font-size:11px;font-weight:700">${r.fps}</span></td>
568
+ <td><span style="font-family:var(--mono);font-size:11px;font-weight:700">${r.lat.toLocaleString()}</span></td>
569
+ <td><span class="${trackClass(r.track)}">${r.track} ✓</span></td>
570
+ <td><span style="font-size:9px;color:var(--text-sec)">${r.brain}</span></td>
571
+ <td><span style="font-size:9px;color:var(--text-sec)">${r.motion}</span></td>
572
+ <td><span style="font-size:9px;color:var(--text-muted)">${r.gpu}</span></td>
573
+ </tr>`).join('');
574
  }
575
 
576
+ function renderBars(){
577
+ ['P1','P2','P3'].forEach(p=>{
578
+ const el=document.getElementById(`bars-${p.toLowerCase()}`);
579
+ const cats=CAT_DATA.filter(c=>c.pillar===p);
580
+ el.innerHTML=cats.map(c=>`
581
+ <div class="bar-row">
582
+ <div class="bar-label">${c.id} · ${c.name}</div>
583
+ <div class="bar-track"><div class="bar-fill" style="width:${c.score}%;background:${PILLAR_COLOR[p]}"></div></div>
584
+ <div class="bar-val" style="color:${PILLAR_COLOR[p]}">${c.score}</div>
585
+ </div>`).join('');
586
+ });
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
587
  }
588
 
589
+ function renderCatTable(){
590
+ const tb=document.getElementById('CAT_TABLE');
591
+ tb.innerHTML=CAT_DATA.map(c=>`
592
+ <tr>
593
+ <td class="c-model" style="font-family:var(--mono);font-weight:700;color:${PILLAR_COLOR[c.pillar]}">${c.id}</td>
594
+ <td style="text-align:left;font-weight:600">${c.name}</td>
595
+ <td style="text-align:left"><span style="font-size:9px;font-family:var(--mono);color:${PILLAR_COLOR[c.pillar]}">${c.pillar}</span></td>
596
+ <td><span style="font-family:var(--mono);font-weight:700">${c.max}</span></td>
597
+ <td style="text-align:left">${c.first?`<span style="font-size:9px;font-weight:700;color:var(--ac)">${c.first} 세계최초</span>`:''}</td>
598
+ <td style="text-align:left;font-size:9.5px;color:var(--text-sec)">${c.desc}</td>
599
+ </tr>`).join('');
600
  }
601
 
602
+ function showTab(id,el){
603
+ document.querySelectorAll('.tpane').forEach(p=>p.classList.remove('on'));
604
+ document.querySelectorAll('.tab').forEach(t=>t.classList.remove('on'));
605
+ document.getElementById(id).classList.add('on');
606
+ el.classList.add('on');
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
607
  }
608
 
609
+ // dark mode persist
610
+ (function(){
611
+ if(localStorage.getItem('wm-dark')==='true') document.body.classList.add('dark');
612
+ })();
613
+
614
+ // init
615
+ renderLB();
616
+ renderBars();
617
+ renderCatTable();
 
 
 
 
 
 
 
618
  </script>
619
  </body>
620
+ </html>