@swizzy_ai/kit 1.0.0 → 1.0.2
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.md +835 -439
- package/dist/core/wizard/bungee/executor.d.ts +15 -0
- package/dist/core/wizard/bungee/executor.d.ts.map +1 -0
- package/dist/core/wizard/context-manager.d.ts +9 -0
- package/dist/core/wizard/context-manager.d.ts.map +1 -0
- package/dist/core/wizard/logger.d.ts +8 -0
- package/dist/core/wizard/logger.d.ts.map +1 -0
- package/dist/core/wizard/schema-utils.d.ts +16 -0
- package/dist/core/wizard/schema-utils.d.ts.map +1 -0
- package/dist/core/wizard/step-data-generator.d.ts +24 -0
- package/dist/core/wizard/step-data-generator.d.ts.map +1 -0
- package/dist/core/wizard/steps/base.d.ts +4 -3
- package/dist/core/wizard/steps/base.d.ts.map +1 -1
- package/dist/core/wizard/steps/compute.d.ts +2 -2
- package/dist/core/wizard/steps/compute.d.ts.map +1 -1
- package/dist/core/wizard/steps/text.d.ts +2 -2
- package/dist/core/wizard/steps/text.d.ts.map +1 -1
- package/dist/core/wizard/usage-tracker.d.ts +25 -0
- package/dist/core/wizard/usage-tracker.d.ts.map +1 -0
- package/dist/core/wizard/visualization-manager.d.ts +34 -0
- package/dist/core/wizard/visualization-manager.d.ts.map +1 -0
- package/dist/core/wizard/wizard.d.ts +39 -40
- package/dist/core/wizard/wizard.d.ts.map +1 -1
- package/dist/index.d.ts +46 -46
- package/dist/index.js +1207 -626
- package/dist/index.js.map +1 -1
- package/dist/services/client/index.d.ts +1 -0
- package/dist/services/client/index.d.ts.map +1 -1
- package/dist/services/client/providers.d.ts.map +1 -1
- package/dist/ui/wizard-visualizer.html +570 -385
- package/package.json +6 -2
|
@@ -3,479 +3,664 @@
|
|
|
3
3
|
<head>
|
|
4
4
|
<meta charset="UTF-8">
|
|
5
5
|
<meta name="viewport" content="width=device-width, initial-scale=1.0">
|
|
6
|
-
<title>
|
|
6
|
+
<title>SimEnvironment | Production v5.5</title>
|
|
7
7
|
<script src="https://cdn.tailwindcss.com"></script>
|
|
8
8
|
<link rel="stylesheet" href="https://cdnjs.cloudflare.com/ajax/libs/font-awesome/6.4.0/css/all.min.css">
|
|
9
9
|
<script src="https://cdn.jsdelivr.net/npm/marked/marked.min.js"></script>
|
|
10
|
+
|
|
10
11
|
<style>
|
|
11
12
|
:root {
|
|
12
|
-
--
|
|
13
|
-
--
|
|
14
|
-
--
|
|
15
|
-
|
|
16
|
-
|
|
17
|
-
--
|
|
18
|
-
--
|
|
19
|
-
|
|
20
|
-
--
|
|
13
|
+
--bg-deep: #050505;
|
|
14
|
+
--bg-panel: #0a0a0a;
|
|
15
|
+
--border: #222;
|
|
16
|
+
|
|
17
|
+
/* Primary Color: Electric Violet */
|
|
18
|
+
--primary: #8b5cf6;
|
|
19
|
+
--primary-dim: rgba(139, 92, 246, 0.1);
|
|
20
|
+
|
|
21
|
+
--success: #10b981;
|
|
22
|
+
--warning: #eab308;
|
|
23
|
+
--text-main: #e5e5e5;
|
|
24
|
+
--text-muted: #737373;
|
|
21
25
|
}
|
|
22
26
|
|
|
23
27
|
body {
|
|
24
|
-
background-color: var(--
|
|
25
|
-
color: var(--
|
|
26
|
-
font-family: -apple-system,
|
|
28
|
+
background-color: var(--bg-deep);
|
|
29
|
+
color: var(--text-main);
|
|
30
|
+
font-family: 'Inter', system-ui, -apple-system, sans-serif;
|
|
31
|
+
height: 100vh;
|
|
27
32
|
overflow: hidden;
|
|
33
|
+
display: flex;
|
|
34
|
+
flex-direction: column;
|
|
28
35
|
}
|
|
29
36
|
|
|
30
|
-
/*
|
|
31
|
-
|
|
32
|
-
|
|
33
|
-
|
|
34
|
-
|
|
37
|
+
/* --- LAYOUT GRID --- */
|
|
38
|
+
.app-grid {
|
|
39
|
+
display: grid;
|
|
40
|
+
grid-template-columns: 320px 1fr 320px;
|
|
41
|
+
flex: 1;
|
|
42
|
+
min-height: 0;
|
|
43
|
+
overflow: hidden;
|
|
44
|
+
width: 100%;
|
|
45
|
+
min-width: 1024px;
|
|
46
|
+
}
|
|
35
47
|
|
|
36
|
-
|
|
37
|
-
|
|
38
|
-
|
|
48
|
+
/* --- SIDEBARS --- */
|
|
49
|
+
.sidebar {
|
|
50
|
+
background: var(--bg-panel);
|
|
51
|
+
display: flex;
|
|
52
|
+
flex-direction: column;
|
|
53
|
+
height: 100%;
|
|
54
|
+
overflow: hidden;
|
|
55
|
+
z-index: 10;
|
|
56
|
+
}
|
|
57
|
+
.sidebar-left { border-right: 1px solid var(--border); }
|
|
58
|
+
.sidebar-right { border-left: 1px solid var(--border); }
|
|
59
|
+
|
|
60
|
+
.sidebar-header {
|
|
61
|
+
height: 50px;
|
|
62
|
+
min-height: 50px;
|
|
39
63
|
border-bottom: 1px solid var(--border);
|
|
64
|
+
display: flex;
|
|
65
|
+
align-items: center;
|
|
66
|
+
padding: 0 16px;
|
|
67
|
+
justify-content: space-between;
|
|
68
|
+
background: #080808;
|
|
69
|
+
}
|
|
70
|
+
|
|
71
|
+
/* --- STAGE --- */
|
|
72
|
+
.stage-container {
|
|
73
|
+
position: relative;
|
|
74
|
+
background-image:
|
|
75
|
+
linear-gradient(rgba(255, 255, 255, 0.02) 1px, transparent 1px),
|
|
76
|
+
linear-gradient(90deg, rgba(255, 255, 255, 0.02) 1px, transparent 1px);
|
|
77
|
+
background-size: 40px 40px;
|
|
78
|
+
display: flex;
|
|
79
|
+
flex-direction: column;
|
|
80
|
+
height: 100%;
|
|
81
|
+
overflow: hidden;
|
|
40
82
|
}
|
|
41
83
|
|
|
42
|
-
.
|
|
43
|
-
|
|
84
|
+
.steps-scroll-area {
|
|
85
|
+
flex: 1;
|
|
86
|
+
overflow-y: auto;
|
|
87
|
+
scroll-behavior: smooth;
|
|
88
|
+
padding: 40px 0 160px 0;
|
|
89
|
+
position: relative;
|
|
90
|
+
}
|
|
91
|
+
.steps-scroll-area::-webkit-scrollbar { display: none; }
|
|
92
|
+
|
|
93
|
+
.timeline-guide {
|
|
94
|
+
position: absolute;
|
|
95
|
+
left: 50%;
|
|
96
|
+
top: 0;
|
|
97
|
+
bottom: 0;
|
|
98
|
+
width: 1px;
|
|
99
|
+
background: linear-gradient(180deg, transparent, #222 10%, #222 90%, transparent);
|
|
100
|
+
z-index: 0;
|
|
101
|
+
transform: translateX(-50%);
|
|
102
|
+
}
|
|
44
103
|
|
|
104
|
+
/* --- STEP CARD --- */
|
|
45
105
|
.step-card {
|
|
46
|
-
|
|
106
|
+
width: 90%;
|
|
107
|
+
max-width: 650px;
|
|
108
|
+
margin: 0 auto 30px auto;
|
|
109
|
+
background: #080808;
|
|
47
110
|
border: 1px solid var(--border);
|
|
48
|
-
|
|
111
|
+
border-radius: 12px;
|
|
112
|
+
position: relative;
|
|
113
|
+
z-index: 10;
|
|
114
|
+
transition: all 0.5s cubic-bezier(0.25, 1, 0.5, 1);
|
|
115
|
+
opacity: 0.5;
|
|
116
|
+
filter: grayscale(1);
|
|
117
|
+
transform: scale(0.98);
|
|
49
118
|
}
|
|
50
|
-
|
|
51
119
|
.step-card.active {
|
|
52
|
-
|
|
53
|
-
|
|
54
|
-
transform: scale(1
|
|
120
|
+
opacity: 1;
|
|
121
|
+
filter: grayscale(0);
|
|
122
|
+
transform: scale(1);
|
|
123
|
+
border-color: var(--primary);
|
|
124
|
+
box-shadow: 0 0 0 1px var(--primary-dim), 0 20px 60px -10px rgba(0,0,0,0.8);
|
|
55
125
|
}
|
|
56
|
-
|
|
57
126
|
.step-card.completed {
|
|
58
|
-
|
|
127
|
+
opacity: 0.6;
|
|
128
|
+
border-color: #333;
|
|
129
|
+
filter: grayscale(0.5);
|
|
59
130
|
}
|
|
60
131
|
|
|
61
|
-
.
|
|
62
|
-
|
|
132
|
+
.step-badge {
|
|
133
|
+
font-size: 10px;
|
|
134
|
+
font-weight: 700;
|
|
135
|
+
letter-spacing: 0.1em;
|
|
136
|
+
padding: 4px 8px;
|
|
137
|
+
border-radius: 4px;
|
|
138
|
+
text-transform: uppercase;
|
|
139
|
+
background: #111;
|
|
140
|
+
border: 1px solid #222;
|
|
141
|
+
color: #666;
|
|
63
142
|
}
|
|
64
|
-
|
|
65
|
-
|
|
66
|
-
|
|
67
|
-
|
|
68
|
-
100% { opacity: 1; }
|
|
143
|
+
.active .step-badge {
|
|
144
|
+
background: var(--primary-dim);
|
|
145
|
+
color: var(--primary);
|
|
146
|
+
border-color: rgba(139, 92, 246, 0.3);
|
|
69
147
|
}
|
|
70
148
|
|
|
71
|
-
|
|
72
|
-
|
|
73
|
-
|
|
74
|
-
|
|
75
|
-
|
|
149
|
+
/* --- MARKDOWN & OUTPUT STYLING --- */
|
|
150
|
+
.markdown-body {
|
|
151
|
+
font-size: 13px;
|
|
152
|
+
line-height: 1.6;
|
|
153
|
+
color: #d4d4d4;
|
|
76
154
|
}
|
|
77
|
-
|
|
78
|
-
|
|
79
|
-
|
|
80
|
-
|
|
155
|
+
.markdown-body h1, .markdown-body h2, .markdown-body h3 {
|
|
156
|
+
color: #fff;
|
|
157
|
+
margin-top: 16px;
|
|
158
|
+
margin-bottom: 8px;
|
|
159
|
+
font-weight: 600;
|
|
81
160
|
}
|
|
82
|
-
|
|
83
|
-
.
|
|
84
|
-
|
|
85
|
-
|
|
86
|
-
|
|
87
|
-
|
|
161
|
+
.markdown-body h1 { font-size: 1.2em; border-bottom: 1px solid #333; padding-bottom: 4px; }
|
|
162
|
+
.markdown-body h2 { font-size: 1.1em; }
|
|
163
|
+
.markdown-body p { margin-bottom: 12px; }
|
|
164
|
+
.markdown-body ul, .markdown-body ol { padding-left: 20px; margin-bottom: 12px; }
|
|
165
|
+
.markdown-body li { margin-bottom: 4px; }
|
|
166
|
+
.markdown-body code {
|
|
167
|
+
font-family: 'JetBrains Mono', monospace;
|
|
168
|
+
background: rgba(255, 255, 255, 0.1);
|
|
169
|
+
padding: 2px 4px;
|
|
88
170
|
border-radius: 4px;
|
|
89
|
-
font-
|
|
171
|
+
font-size: 0.9em;
|
|
172
|
+
color: #eab308;
|
|
173
|
+
}
|
|
174
|
+
.markdown-body pre {
|
|
175
|
+
background: #111;
|
|
176
|
+
padding: 12px;
|
|
177
|
+
border-radius: 6px;
|
|
178
|
+
overflow-x: auto;
|
|
179
|
+
margin-bottom: 12px;
|
|
180
|
+
border: 1px solid #222;
|
|
181
|
+
}
|
|
182
|
+
.markdown-body pre code {
|
|
183
|
+
background: transparent;
|
|
184
|
+
padding: 0;
|
|
185
|
+
color: #a5f3fc;
|
|
186
|
+
font-size: 12px;
|
|
187
|
+
}
|
|
188
|
+
.markdown-body blockquote {
|
|
189
|
+
border-left: 3px solid var(--primary);
|
|
190
|
+
padding-left: 12px;
|
|
191
|
+
color: #999;
|
|
192
|
+
font-style: italic;
|
|
90
193
|
}
|
|
91
|
-
|
|
92
|
-
.badge-blue { background: rgba(0, 112, 243, 0.1); color: #0070f3; border: 1px solid rgba(0, 112, 243, 0.2); }
|
|
93
|
-
.badge-green { background: rgba(0, 223, 216, 0.1); color: #00dfd8; border: 1px solid rgba(0, 223, 216, 0.2); }
|
|
94
194
|
|
|
95
|
-
|
|
96
|
-
|
|
97
|
-
font-family: '
|
|
195
|
+
/* JSON Output specifically */
|
|
196
|
+
.json-output {
|
|
197
|
+
font-family: 'JetBrains Mono', monospace;
|
|
198
|
+
font-size: 11px;
|
|
199
|
+
color: #a7f3d0;
|
|
200
|
+
white-space: pre-wrap;
|
|
201
|
+
word-break: break-all;
|
|
98
202
|
}
|
|
99
203
|
|
|
100
|
-
|
|
101
|
-
|
|
102
|
-
|
|
103
|
-
|
|
104
|
-
border-top
|
|
105
|
-
|
|
106
|
-
|
|
204
|
+
/* --- SIM INPUTS --- */
|
|
205
|
+
.sim-container {
|
|
206
|
+
margin-top: 16px;
|
|
207
|
+
padding-top: 16px;
|
|
208
|
+
border-top: 1px dashed #222;
|
|
209
|
+
display: flex;
|
|
210
|
+
flex-direction: column;
|
|
211
|
+
gap: 12px;
|
|
107
212
|
}
|
|
108
|
-
|
|
109
|
-
@keyframes
|
|
110
|
-
|
|
213
|
+
.sim-group { opacity: 0; animation: fadeIn 0.3s forwards; position: relative; }
|
|
214
|
+
@keyframes fadeIn { to { opacity: 1; } }
|
|
215
|
+
.sim-label {
|
|
216
|
+
font-size: 9px;
|
|
217
|
+
text-transform: uppercase;
|
|
218
|
+
color: #555;
|
|
219
|
+
font-weight: 700;
|
|
220
|
+
letter-spacing: 0.05em;
|
|
221
|
+
margin-bottom: 4px;
|
|
222
|
+
display: block;
|
|
223
|
+
}
|
|
224
|
+
.sim-input {
|
|
225
|
+
background: #000;
|
|
226
|
+
border: 1px solid #333;
|
|
227
|
+
border-radius: 4px;
|
|
228
|
+
padding: 8px 12px;
|
|
229
|
+
font-family: 'Courier New', monospace;
|
|
230
|
+
font-size: 12px;
|
|
231
|
+
color: var(--primary);
|
|
232
|
+
min-height: 34px;
|
|
233
|
+
display: flex;
|
|
234
|
+
align-items: center;
|
|
235
|
+
position: relative;
|
|
236
|
+
}
|
|
237
|
+
.sim-input::after { content: 'AI Generated'; position: absolute; right: 8px; font-size: 9px; color: #333; }
|
|
238
|
+
.cursor-blink { display: inline-block; width: 6px; height: 14px; background-color: var(--primary); margin-left: 2px; animation: blink 1s step-end infinite; }
|
|
239
|
+
@keyframes blink { 50% { opacity: 0; } }
|
|
240
|
+
|
|
241
|
+
/* --- CONTROL DECK --- */
|
|
242
|
+
.control-deck {
|
|
243
|
+
position: fixed;
|
|
244
|
+
bottom: 40px;
|
|
245
|
+
left: 50%;
|
|
246
|
+
transform: translateX(-50%);
|
|
247
|
+
background: rgba(15, 15, 15, 0.95);
|
|
248
|
+
backdrop-filter: blur(16px);
|
|
249
|
+
border: 1px solid var(--border);
|
|
250
|
+
border-radius: 100px;
|
|
251
|
+
padding: 8px 16px;
|
|
252
|
+
display: flex;
|
|
253
|
+
align-items: center;
|
|
254
|
+
gap: 16px;
|
|
255
|
+
z-index: 9999;
|
|
256
|
+
box-shadow: 0 20px 50px rgba(0,0,0,0.5);
|
|
111
257
|
}
|
|
258
|
+
.deck-btn { width: 40px; height: 40px; border-radius: 50%; display: flex; align-items: center; justify-content: center; color: #666; background: transparent; border: none; cursor: pointer; transition: all 0.2s; }
|
|
259
|
+
.deck-btn:hover { color: #fff; background: rgba(255,255,255,0.05); }
|
|
260
|
+
.play-btn { width: 52px; height: 52px; border-radius: 50%; background: #fff; color: #000; display: flex; align-items: center; justify-content: center; font-size: 16px; transition: transform 0.2s; border: none; cursor: pointer; }
|
|
261
|
+
.play-btn:hover { transform: scale(1.05); }
|
|
262
|
+
|
|
263
|
+
/* --- SCROLLBARS --- */
|
|
264
|
+
.custom-scroll::-webkit-scrollbar { width: 4px; }
|
|
265
|
+
.custom-scroll::-webkit-scrollbar-track { background: transparent; }
|
|
266
|
+
.custom-scroll::-webkit-scrollbar-thumb { background: #333; border-radius: 4px; }
|
|
112
267
|
</style>
|
|
113
268
|
</head>
|
|
114
|
-
|
|
115
|
-
|
|
116
|
-
<!--
|
|
117
|
-
<header class="
|
|
118
|
-
<div class="flex items-center gap-
|
|
119
|
-
<div class="flex items-center
|
|
120
|
-
<
|
|
121
|
-
<div class="w-3 h-3 bg-black transform rotate-45"></div>
|
|
122
|
-
</div>
|
|
123
|
-
<span class="font-bold text-sm tracking-tight">WIZARD_CORE</span>
|
|
269
|
+
|
|
270
|
+
<body>
|
|
271
|
+
<!-- HEADER -->
|
|
272
|
+
<header class="h-14 border-b border-[#222] bg-[#050505] flex items-center justify-between px-6 shrink-0 z-30 relative">
|
|
273
|
+
<div class="flex items-center gap-3">
|
|
274
|
+
<div class="w-8 h-8 rounded-lg bg-white/5 border border-white/10 flex items-center justify-center">
|
|
275
|
+
<i class="fas fa-hat-wizard text-violet-400 text-xs"></i>
|
|
124
276
|
</div>
|
|
125
|
-
<div
|
|
126
|
-
|
|
127
|
-
<div class="flex
|
|
128
|
-
<
|
|
129
|
-
<span
|
|
130
|
-
</div>
|
|
131
|
-
<div class="flex flex-col">
|
|
132
|
-
<span class="text-[9px] text-neutral-600 uppercase">Rate</span>
|
|
133
|
-
<span class="text-white" id="token-rate">0/s</span>
|
|
277
|
+
<div>
|
|
278
|
+
<h1 class="text-sm font-bold text-white tracking-tight">WIZARD_CORE <span class="text-xs text-violet-500 font-mono">v5.5</span></h1>
|
|
279
|
+
<div class="flex items-center gap-2">
|
|
280
|
+
<div id="status-dot" class="w-1.5 h-1.5 rounded-full bg-neutral-600"></div>
|
|
281
|
+
<span id="header-status" class="text-[9px] font-bold text-neutral-500 uppercase tracking-widest">READY</span>
|
|
134
282
|
</div>
|
|
135
283
|
</div>
|
|
136
284
|
</div>
|
|
137
|
-
|
|
138
|
-
|
|
139
|
-
|
|
140
|
-
<
|
|
141
|
-
<span id="status-text">Ready</span>
|
|
285
|
+
<div class="flex items-center gap-6">
|
|
286
|
+
<div class="flex flex-col items-end">
|
|
287
|
+
<span class="text-[9px] text-neutral-600 uppercase font-bold">Tokens</span>
|
|
288
|
+
<span id="header-tokens" class="text-xs font-mono text-white">0</span>
|
|
142
289
|
</div>
|
|
143
|
-
<div class="h-
|
|
144
|
-
|
|
290
|
+
<div class="h-6 w-[1px] bg-neutral-800"></div>
|
|
291
|
+
<div class="flex flex-col items-end">
|
|
292
|
+
<span class="text-[9px] text-neutral-600 uppercase font-bold">Rate/s</span>
|
|
293
|
+
<span id="header-rate" class="text-xs font-mono text-violet-400">0.0</span>
|
|
145
294
|
</div>
|
|
146
295
|
</div>
|
|
147
296
|
</header>
|
|
148
297
|
|
|
149
|
-
|
|
150
|
-
|
|
151
|
-
|
|
152
|
-
|
|
153
|
-
|
|
154
|
-
|
|
298
|
+
<!-- GRID -->
|
|
299
|
+
<div class="app-grid">
|
|
300
|
+
|
|
301
|
+
<!-- LEFT: CONTEXT -->
|
|
302
|
+
<aside class="sidebar sidebar-left">
|
|
303
|
+
<div class="sidebar-header">
|
|
304
|
+
<span class="text-[10px] font-bold uppercase tracking-widest text-neutral-400">Context Memory</span>
|
|
305
|
+
<i class="fas fa-database text-neutral-600 text-xs"></i>
|
|
155
306
|
</div>
|
|
156
|
-
<div id="context-list" class="flex-1 overflow-y-auto p-4 space-y-3">
|
|
157
|
-
<!-- Context
|
|
307
|
+
<div id="context-list" class="flex-1 overflow-y-auto p-4 custom-scroll space-y-3">
|
|
308
|
+
<!-- Context injected here -->
|
|
158
309
|
</div>
|
|
159
310
|
</aside>
|
|
160
|
-
|
|
161
|
-
<!--
|
|
162
|
-
<main class="
|
|
163
|
-
<div
|
|
164
|
-
<div class="
|
|
165
|
-
|
|
166
|
-
|
|
167
|
-
|
|
168
|
-
|
|
169
|
-
|
|
311
|
+
|
|
312
|
+
<!-- CENTER: STAGE -->
|
|
313
|
+
<main class="stage-container">
|
|
314
|
+
<div id="steps-container" class="steps-scroll-area">
|
|
315
|
+
<div class="timeline-guide"></div>
|
|
316
|
+
</div>
|
|
317
|
+
<div id="control-deck" class="control-deck">
|
|
318
|
+
<button id="stop-btn" class="deck-btn hover:text-red-500"><i class="fas fa-stop"></i></button>
|
|
319
|
+
<button id="play-pause-btn" class="play-btn shadow-lg shadow-violet-500/20 text-violet-900"><i class="fas fa-play ml-1"></i></button>
|
|
320
|
+
<button id="replay-btn" class="deck-btn"><i class="fas fa-redo"></i></button>
|
|
170
321
|
</div>
|
|
171
322
|
</main>
|
|
172
323
|
|
|
173
|
-
<!--
|
|
174
|
-
<aside class="
|
|
175
|
-
<div class="
|
|
176
|
-
<
|
|
177
|
-
|
|
178
|
-
<
|
|
179
|
-
|
|
324
|
+
<!-- RIGHT: LOGS/INSTRUCT -->
|
|
325
|
+
<aside class="sidebar sidebar-right">
|
|
326
|
+
<div class="instruction-panel">
|
|
327
|
+
<div class="sidebar-header">
|
|
328
|
+
<span class="text-[10px] font-bold uppercase tracking-widest text-neutral-400">Current Instruction</span>
|
|
329
|
+
<i class="fas fa-code text-neutral-600 text-xs"></i>
|
|
330
|
+
</div>
|
|
331
|
+
<div id="current-instruction" class="instruction-content custom-scroll">
|
|
332
|
+
<p class="text-neutral-600 text-[11px]">Waiting for workflow...</p>
|
|
180
333
|
</div>
|
|
181
334
|
</div>
|
|
182
|
-
<div
|
|
183
|
-
<div class="
|
|
184
|
-
|
|
185
|
-
|
|
186
|
-
<!-- Controls -->
|
|
187
|
-
<div class="p-6 border-t border-neutral-900 bg-black">
|
|
188
|
-
<div class="flex gap-2">
|
|
189
|
-
<button id="start-btn" class="flex-1 h-10 bg-white text-black text-[12px] font-bold rounded flex items-center justify-center gap-2 hover:bg-neutral-200 transition-colors">
|
|
190
|
-
<i class="fas fa-play text-[10px]"></i> START
|
|
191
|
-
</button>
|
|
192
|
-
<button id="pause-btn" class="hidden flex-1 h-10 bg-neutral-900 text-white text-[12px] font-bold rounded border border-neutral-800 flex items-center justify-center gap-2 hover:bg-neutral-800 transition-colors">
|
|
193
|
-
<i class="fas fa-pause text-[10px]"></i> PAUSE
|
|
194
|
-
</button>
|
|
195
|
-
<button id="stop-btn" class="w-10 h-10 bg-neutral-900 text-red-500 text-[12px] rounded border border-neutral-800 flex items-center justify-center hover:bg-red-500/10 transition-colors">
|
|
196
|
-
<i class="fas fa-stop"></i>
|
|
197
|
-
</button>
|
|
198
|
-
<button id="replay-btn" class="w-10 h-10 bg-neutral-900 text-neutral-400 text-[12px] rounded border border-neutral-800 flex items-center justify-center hover:bg-neutral-800 transition-colors">
|
|
199
|
-
<i class="fas fa-redo"></i>
|
|
200
|
-
</button>
|
|
335
|
+
<div class="flex-1 flex flex-col border-t border-[#222] bg-[#030303] overflow-hidden">
|
|
336
|
+
<div class="sidebar-header">
|
|
337
|
+
<span class="text-[10px] font-bold uppercase tracking-widest text-neutral-400">System Logs</span>
|
|
338
|
+
<div class="flex gap-1"><div class="w-1.5 h-1.5 rounded-full bg-[#222]"></div><div class="w-1.5 h-1.5 rounded-full bg-[#222]"></div></div>
|
|
201
339
|
</div>
|
|
340
|
+
<div id="log-feed" class="flex-1 p-3 overflow-y-auto custom-scroll flex flex-col"></div>
|
|
202
341
|
</div>
|
|
203
342
|
</aside>
|
|
343
|
+
|
|
204
344
|
</div>
|
|
205
345
|
|
|
206
|
-
|
|
207
|
-
|
|
208
|
-
|
|
209
|
-
|
|
210
|
-
|
|
211
|
-
|
|
212
|
-
|
|
213
|
-
|
|
214
|
-
|
|
215
|
-
|
|
216
|
-
|
|
217
|
-
|
|
218
|
-
|
|
219
|
-
|
|
220
|
-
|
|
346
|
+
<script>
|
|
347
|
+
class WizardEngine {
|
|
348
|
+
constructor() {
|
|
349
|
+
this.ws = null;
|
|
350
|
+
this.steps = new Map();
|
|
351
|
+
this.context = new Map();
|
|
352
|
+
this.state = { isRunning: false, isPaused: false, totalTokens: 0, currentStepId: null, tokenRate: 0 };
|
|
353
|
+
this.init();
|
|
354
|
+
}
|
|
355
|
+
|
|
356
|
+
init() {
|
|
357
|
+
this.setupWebSocket();
|
|
358
|
+
this.setupListeners();
|
|
359
|
+
this.log("Wizard Engine V5.5 initialized.");
|
|
360
|
+
}
|
|
361
|
+
|
|
362
|
+
setupWebSocket() {
|
|
363
|
+
const protocol = location.protocol === 'https:' ? 'wss:' : 'ws:';
|
|
364
|
+
const wsUrl = `${protocol}//${location.host}`;
|
|
365
|
+
this.ws = new WebSocket(wsUrl);
|
|
366
|
+
|
|
367
|
+
this.ws.onopen = () => { this.log("Connected."); this.updateConnectionUI(true); };
|
|
368
|
+
this.ws.onmessage = (e) => this.handleMessage(JSON.parse(e.data));
|
|
369
|
+
this.ws.onerror = () => this.log("Connection failed.", "error");
|
|
370
|
+
this.ws.onclose = () => {
|
|
371
|
+
this.log("Connection lost. Retrying...", "error");
|
|
372
|
+
this.updateConnectionUI(false);
|
|
373
|
+
setTimeout(() => this.setupWebSocket(), 5000);
|
|
374
|
+
};
|
|
375
|
+
}
|
|
221
376
|
|
|
222
|
-
|
|
223
|
-
|
|
224
|
-
|
|
225
|
-
this.
|
|
377
|
+
handleMessage(data) {
|
|
378
|
+
if (data.type === 'batch') { data.messages.forEach(m => this.handleMessage(m)); return; }
|
|
379
|
+
switch(data.type) {
|
|
380
|
+
case 'wizard_start': this.initSteps(data.steps); break;
|
|
381
|
+
case 'step_update': this.updateStep(data); break;
|
|
382
|
+
case 'token_update': this.updateTokens(data); break;
|
|
383
|
+
case 'context_update': this.updateContext(data); break;
|
|
384
|
+
case 'status_update': this.updateStatus(data.status); break;
|
|
226
385
|
}
|
|
386
|
+
}
|
|
227
387
|
|
|
228
|
-
|
|
229
|
-
|
|
230
|
-
|
|
231
|
-
|
|
232
|
-
|
|
233
|
-
|
|
234
|
-
|
|
235
|
-
|
|
236
|
-
|
|
237
|
-
|
|
388
|
+
initSteps(steps) {
|
|
389
|
+
const container = document.getElementById('steps-container');
|
|
390
|
+
container.innerHTML = '<div class="timeline-guide"></div><div style="height:40px"></div>';
|
|
391
|
+
this.steps.clear();
|
|
392
|
+
const flatSteps = Array.isArray(steps[0]) ? steps[0] : steps;
|
|
393
|
+
flatSteps.forEach((step, index) => {
|
|
394
|
+
const el = this.createStepElement(step, index + 1);
|
|
395
|
+
container.appendChild(el);
|
|
396
|
+
this.steps.set(step.id, { el, data: step });
|
|
397
|
+
});
|
|
398
|
+
const spacer = document.createElement('div');
|
|
399
|
+
spacer.style.height = "120px";
|
|
400
|
+
container.appendChild(spacer);
|
|
401
|
+
}
|
|
238
402
|
|
|
239
|
-
|
|
240
|
-
|
|
241
|
-
|
|
242
|
-
|
|
403
|
+
createStepElement(step, index) {
|
|
404
|
+
const div = document.createElement('div');
|
|
405
|
+
div.id = `step-${step.id}`;
|
|
406
|
+
div.className = `step-card`;
|
|
407
|
+
div.innerHTML = `
|
|
408
|
+
<div class="px-6 py-4 border-b border-[#222] bg-white/[0.02] flex items-center justify-between">
|
|
409
|
+
<div class="flex items-center gap-3">
|
|
410
|
+
<div class="text-[10px] font-mono text-neutral-500 border border-[#333] px-1.5 rounded">${index.toString().padStart(2,'0')}</div>
|
|
411
|
+
<span class="text-xs font-bold text-neutral-300 tracking-wide">${step.id}</span>
|
|
412
|
+
</div>
|
|
413
|
+
<div class="step-badge">QUEUED</div>
|
|
414
|
+
</div>
|
|
415
|
+
<div class="p-6">
|
|
416
|
+
<div class="text-sm text-neutral-500 font-medium leading-relaxed instruction-text mb-4">
|
|
417
|
+
${step.instruction || 'Ready for processing...'}
|
|
418
|
+
</div>
|
|
419
|
+
<div class="step-content"></div>
|
|
420
|
+
</div>
|
|
421
|
+
`;
|
|
422
|
+
return div;
|
|
423
|
+
}
|
|
243
424
|
|
|
244
|
-
|
|
245
|
-
|
|
246
|
-
|
|
247
|
-
setTimeout(() => this.setupWebSocket(), 5000);
|
|
248
|
-
};
|
|
249
|
-
}
|
|
425
|
+
updateStep(data) {
|
|
426
|
+
const step = this.steps.get(data.stepId);
|
|
427
|
+
if (!step) return;
|
|
250
428
|
|
|
251
|
-
|
|
252
|
-
|
|
253
|
-
|
|
254
|
-
|
|
255
|
-
|
|
429
|
+
const { el } = step;
|
|
430
|
+
const badge = el.querySelector('.step-badge');
|
|
431
|
+
const content = el.querySelector('.step-content');
|
|
432
|
+
|
|
433
|
+
document.querySelectorAll('.step-card').forEach(c => c.classList.remove('active'));
|
|
256
434
|
|
|
257
|
-
|
|
258
|
-
|
|
259
|
-
|
|
260
|
-
|
|
261
|
-
|
|
262
|
-
|
|
435
|
+
if (data.status === 'current') {
|
|
436
|
+
el.classList.add('active');
|
|
437
|
+
el.classList.remove('completed');
|
|
438
|
+
badge.textContent = 'RUNNING';
|
|
439
|
+
|
|
440
|
+
document.getElementById('current-instruction').innerHTML = `
|
|
441
|
+
<h3>${data.stepId}</h3>
|
|
442
|
+
<p>${data.instruction || 'Processing...'}</p>
|
|
443
|
+
`;
|
|
444
|
+
|
|
445
|
+
if (data.fields && data.fields.length > 0) {
|
|
446
|
+
content.innerHTML = '<div class="sim-container"></div>';
|
|
447
|
+
this.runSimulationSequence(content.querySelector('.sim-container'), data.fields);
|
|
263
448
|
}
|
|
264
|
-
|
|
449
|
+
el.scrollIntoView({ behavior: 'smooth', block: 'center' });
|
|
450
|
+
|
|
451
|
+
} else if (data.status === 'completed') {
|
|
452
|
+
el.classList.remove('active');
|
|
453
|
+
el.classList.add('completed');
|
|
454
|
+
badge.textContent = 'DONE';
|
|
455
|
+
el.querySelectorAll('.cursor-blink').forEach(c => c.style.display = 'none');
|
|
456
|
+
|
|
457
|
+
if (data.data) {
|
|
458
|
+
let outputHtml = '';
|
|
459
|
+
let rawTextForCopy = '';
|
|
460
|
+
|
|
461
|
+
// DETERMINE FORMAT
|
|
462
|
+
if (typeof data.data === 'object') {
|
|
463
|
+
// It's an Object -> JSON Pretty Print
|
|
464
|
+
rawTextForCopy = JSON.stringify(data.data, null, 2);
|
|
465
|
+
outputHtml = `<pre class="json-output">${rawTextForCopy}</pre>`;
|
|
466
|
+
} else {
|
|
467
|
+
// It's a String
|
|
468
|
+
const strData = String(data.data).trim();
|
|
469
|
+
// Try Parsing as JSON
|
|
470
|
+
try {
|
|
471
|
+
const parsed = JSON.parse(strData);
|
|
472
|
+
rawTextForCopy = JSON.stringify(parsed, null, 2);
|
|
473
|
+
outputHtml = `<pre class="json-output">${rawTextForCopy}</pre>`;
|
|
474
|
+
} catch (e) {
|
|
475
|
+
// Not JSON -> Render as Markdown
|
|
476
|
+
rawTextForCopy = strData;
|
|
477
|
+
outputHtml = `<div class="markdown-body">${marked.parse(strData)}</div>`;
|
|
478
|
+
}
|
|
479
|
+
}
|
|
265
480
|
|
|
266
|
-
|
|
267
|
-
|
|
268
|
-
|
|
269
|
-
|
|
481
|
+
const outputWrapper = document.createElement('div');
|
|
482
|
+
outputWrapper.className = 'bg-neutral-900/50 p-4 rounded mt-4 border border-neutral-800 relative';
|
|
483
|
+
outputWrapper.innerHTML = outputHtml;
|
|
484
|
+
|
|
485
|
+
// Add Copy Button
|
|
486
|
+
const copyBtn = document.createElement('button');
|
|
487
|
+
copyBtn.className = 'absolute top-3 right-3 text-neutral-500 hover:text-white text-xs bg-[#111] p-1.5 rounded border border-[#222]';
|
|
488
|
+
copyBtn.innerHTML = '<i class="fas fa-copy"></i>';
|
|
489
|
+
copyBtn.onclick = () => {
|
|
490
|
+
navigator.clipboard.writeText(rawTextForCopy);
|
|
491
|
+
copyBtn.innerHTML = '<i class="fas fa-check text-green-400"></i>';
|
|
492
|
+
setTimeout(() => copyBtn.innerHTML = '<i class="fas fa-copy"></i>', 1000);
|
|
493
|
+
};
|
|
494
|
+
outputWrapper.appendChild(copyBtn);
|
|
270
495
|
|
|
271
|
-
|
|
272
|
-
|
|
273
|
-
|
|
274
|
-
const el = this.createStepElement(step);
|
|
275
|
-
container.appendChild(el);
|
|
276
|
-
this.steps.set(step.id, { el, data: step });
|
|
277
|
-
});
|
|
496
|
+
content.innerHTML = '';
|
|
497
|
+
content.appendChild(outputWrapper);
|
|
498
|
+
}
|
|
278
499
|
}
|
|
500
|
+
}
|
|
279
501
|
|
|
280
|
-
|
|
281
|
-
|
|
282
|
-
|
|
283
|
-
|
|
284
|
-
|
|
285
|
-
|
|
286
|
-
|
|
287
|
-
|
|
288
|
-
<
|
|
289
|
-
|
|
290
|
-
|
|
291
|
-
<div class="flex items-center">
|
|
292
|
-
<span class="text-[10px] text-neutral-600 font-mono uppercase status-label">Waiting</span>
|
|
293
|
-
<button class="replay-btn hidden text-neutral-500 hover:text-white text-xs ml-2" onclick="engine.sendMessage({ type: 'goto', stepId: '${step.id}' })"><i class="fas fa-redo"></i></button>
|
|
294
|
-
</div>
|
|
295
|
-
</div>
|
|
296
|
-
<p class="text-[12px] text-neutral-500 leading-relaxed mb-4">${step.instruction || 'Processing...'}</p>
|
|
297
|
-
<div class="step-content hidden border-t border-neutral-900 pt-4 mt-4">
|
|
298
|
-
<!-- Dynamic form fields -->
|
|
299
|
-
</div>
|
|
502
|
+
runSimulationSequence(container, fields) {
|
|
503
|
+
let delay = 0;
|
|
504
|
+
fields.forEach(field => {
|
|
505
|
+
const group = document.createElement('div');
|
|
506
|
+
group.className = 'sim-group';
|
|
507
|
+
group.style.animationDelay = `${delay}ms`;
|
|
508
|
+
|
|
509
|
+
group.innerHTML = `
|
|
510
|
+
<span class="sim-label">${field.key}</span>
|
|
511
|
+
<div class="sim-input">
|
|
512
|
+
<span class="type-target"></span><span class="cursor-blink"></span>
|
|
300
513
|
</div>
|
|
301
514
|
`;
|
|
302
|
-
|
|
303
|
-
}
|
|
515
|
+
container.appendChild(group);
|
|
304
516
|
|
|
305
|
-
|
|
306
|
-
|
|
307
|
-
|
|
308
|
-
|
|
309
|
-
|
|
310
|
-
|
|
311
|
-
|
|
312
|
-
|
|
313
|
-
|
|
314
|
-
|
|
315
|
-
|
|
316
|
-
if (
|
|
317
|
-
|
|
318
|
-
|
|
319
|
-
|
|
320
|
-
statusLabel.textContent = 'Running';
|
|
321
|
-
statusLabel.className = 'text-[10px] font-mono uppercase status-label pulse';
|
|
322
|
-
statusLabel.style.color = 'var(--accent-primary)';
|
|
323
|
-
el.querySelector('.replay-btn').classList.add('hidden');
|
|
324
|
-
this.log(`Executing: ${data.stepId} - ${data.instruction || 'Processing...'}`);
|
|
325
|
-
|
|
326
|
-
if (data.fields && data.fields.length > 0) {
|
|
327
|
-
this.createStepForm(content, data.stepId, data.fields);
|
|
328
|
-
content.classList.remove('hidden');
|
|
329
|
-
} else if (data.instruction) {
|
|
330
|
-
const instEl = document.createElement('div');
|
|
331
|
-
instEl.className = 'text-[11px] text-neutral-400 bg-neutral-900/50 p-3 rounded mt-2 border border-neutral-800';
|
|
332
|
-
instEl.innerHTML = marked.parse(data.instruction);
|
|
333
|
-
content.innerHTML = '';
|
|
334
|
-
content.appendChild(instEl);
|
|
335
|
-
content.classList.remove('hidden');
|
|
336
|
-
}
|
|
337
|
-
|
|
338
|
-
el.scrollIntoView({ behavior: 'smooth', block: 'center' });
|
|
339
|
-
} else if (data.status === 'completed') {
|
|
340
|
-
el.classList.add('completed', 'opacity-100');
|
|
341
|
-
el.classList.remove('active');
|
|
342
|
-
iconContainer.innerHTML = '<i class="fas fa-check text-[12px]"></i>';
|
|
343
|
-
iconContainer.style.borderColor = 'rgba(var(--accent-primary-rgb), 0.3)';
|
|
344
|
-
iconContainer.querySelector('i').style.color = 'var(--accent-primary)';
|
|
345
|
-
statusLabel.textContent = 'Done';
|
|
346
|
-
statusLabel.className = 'text-[10px] text-neutral-500 font-mono uppercase status-label';
|
|
347
|
-
el.querySelector('.replay-btn').classList.remove('hidden');
|
|
348
|
-
|
|
349
|
-
if (data.data) {
|
|
350
|
-
const outputEl = document.createElement('div');
|
|
351
|
-
outputEl.className = 'text-[11px] text-neutral-300 bg-neutral-900/50 p-3 rounded mt-2 border border-neutral-800 font-mono relative';
|
|
352
|
-
const preEl = document.createElement('pre');
|
|
353
|
-
preEl.className = 'whitespace-pre-wrap break-words max-h-64 overflow-y-auto';
|
|
354
|
-
preEl.textContent = typeof data.data === 'string' ? data.data : JSON.stringify(data.data, null, 2);
|
|
355
|
-
const copyBtn = document.createElement('button');
|
|
356
|
-
copyBtn.className = 'absolute top-2 right-2 text-neutral-500 hover:text-white text-xs';
|
|
357
|
-
copyBtn.innerHTML = '<i class="fas fa-copy"></i>';
|
|
358
|
-
copyBtn.onclick = () => {
|
|
359
|
-
navigator.clipboard.writeText(preEl.textContent);
|
|
360
|
-
copyBtn.innerHTML = '<i class="fas fa-check"></i>';
|
|
361
|
-
setTimeout(() => copyBtn.innerHTML = '<i class="fas fa-copy"></i>', 1000);
|
|
362
|
-
};
|
|
363
|
-
outputEl.appendChild(preEl);
|
|
364
|
-
outputEl.appendChild(copyBtn);
|
|
365
|
-
content.innerHTML = '';
|
|
366
|
-
content.appendChild(outputEl);
|
|
367
|
-
content.classList.remove('hidden');
|
|
368
|
-
}
|
|
517
|
+
setTimeout(() => {
|
|
518
|
+
this.typeWriter(group.querySelector('.type-target'), field.value || "sample_data");
|
|
519
|
+
}, delay + 300);
|
|
520
|
+
|
|
521
|
+
delay += (field.value ? field.value.length * 30 : 500) + 500;
|
|
522
|
+
});
|
|
523
|
+
}
|
|
524
|
+
|
|
525
|
+
typeWriter(element, text) {
|
|
526
|
+
let i = 0;
|
|
527
|
+
const type = () => {
|
|
528
|
+
if (i < text.length) {
|
|
529
|
+
element.textContent += text.charAt(i);
|
|
530
|
+
i++;
|
|
531
|
+
setTimeout(type, 20);
|
|
369
532
|
}
|
|
370
|
-
}
|
|
533
|
+
};
|
|
534
|
+
type();
|
|
535
|
+
}
|
|
371
536
|
|
|
372
|
-
|
|
373
|
-
|
|
374
|
-
|
|
375
|
-
this.context.set(key, value);
|
|
376
|
-
});
|
|
377
|
-
|
|
378
|
-
const list = document.getElementById('context-list');
|
|
379
|
-
list.innerHTML = '';
|
|
380
|
-
|
|
381
|
-
Object.entries(data.context).forEach(([key, value]) => {
|
|
382
|
-
const item = document.createElement('div');
|
|
383
|
-
item.className = 'p-3 bg-neutral-900 border border-neutral-800 rounded-lg group cursor-pointer hover:border-neutral-700 transition-all';
|
|
384
|
-
|
|
385
|
-
const type = Array.isArray(value) ? 'ARRAY' : typeof value;
|
|
386
|
-
const displayContent = typeof value === 'string' ? value :
|
|
387
|
-
Array.isArray(value) ? JSON.stringify(value, null, 2) :
|
|
388
|
-
JSON.stringify(value, null, 2);
|
|
389
|
-
|
|
390
|
-
item.innerHTML = `
|
|
391
|
-
<div class="flex items-center justify-between mb-1">
|
|
392
|
-
<span class="text-[11px] font-bold text-neutral-300">${key}</span>
|
|
393
|
-
<div class="flex items-center gap-1">
|
|
394
|
-
<span class="text-[9px] text-neutral-600 uppercase font-mono">${type.toUpperCase()}</span>
|
|
395
|
-
<button class="text-neutral-500 hover:text-white text-xs copy-btn" data-key="${key}">
|
|
396
|
-
<i class="fas fa-copy"></i>
|
|
397
|
-
</button>
|
|
398
|
-
</div>
|
|
399
|
-
</div>
|
|
400
|
-
<pre class="text-[10px] text-neutral-500 whitespace-pre-wrap break-words max-h-32 overflow-y-auto">${displayContent}</pre>
|
|
401
|
-
`;
|
|
402
|
-
|
|
403
|
-
item.querySelector('.copy-btn').onclick = (e) => {
|
|
404
|
-
e.stopPropagation();
|
|
405
|
-
const btn = e.target.closest('.copy-btn');
|
|
406
|
-
const key = btn.dataset.key;
|
|
407
|
-
const value = this.context.get(key);
|
|
408
|
-
const copyText = typeof value === 'string' ? value : JSON.stringify(value, null, 2);
|
|
409
|
-
navigator.clipboard.writeText(copyText);
|
|
410
|
-
btn.innerHTML = '<i class="fas fa-check"></i>';
|
|
411
|
-
setTimeout(() => btn.innerHTML = '<i class="fas fa-copy"></i>', 1000);
|
|
412
|
-
};
|
|
537
|
+
updateContext(data) {
|
|
538
|
+
this.context.clear();
|
|
539
|
+
Object.entries(data.context).forEach(([key, value]) => this.context.set(key, value));
|
|
413
540
|
|
|
414
|
-
|
|
415
|
-
|
|
416
|
-
}
|
|
541
|
+
const list = document.getElementById('context-list');
|
|
542
|
+
list.innerHTML = '';
|
|
417
543
|
|
|
418
|
-
|
|
419
|
-
|
|
420
|
-
|
|
421
|
-
|
|
422
|
-
|
|
423
|
-
|
|
424
|
-
|
|
425
|
-
if (
|
|
426
|
-
|
|
427
|
-
|
|
428
|
-
|
|
429
|
-
|
|
430
|
-
|
|
431
|
-
if (status.isStepMode) {
|
|
432
|
-
pauseBtn.innerHTML = '<i class="fas fa-step-forward text-[10px]"></i> NEXT STEP';
|
|
433
|
-
pauseBtn.onclick = () => this.sendMessage({ type: 'step_forward' });
|
|
434
|
-
} else {
|
|
435
|
-
pauseBtn.innerHTML = '<i class="fas fa-play text-[10px]"></i> RESUME';
|
|
436
|
-
pauseBtn.onclick = () => this.sendMessage({ type: 'resume' });
|
|
437
|
-
}
|
|
438
|
-
statusText.textContent = 'Paused';
|
|
544
|
+
Object.entries(data.context).forEach(([key, value]) => {
|
|
545
|
+
const item = document.createElement('div');
|
|
546
|
+
item.className = 'bg-[#0a0a0a] border border-[#222] rounded p-3 hover:border-violet-900 transition-colors group';
|
|
547
|
+
|
|
548
|
+
let typeLabel = 'OBJ';
|
|
549
|
+
let displayContent = '';
|
|
550
|
+
|
|
551
|
+
if (Array.isArray(value)) {
|
|
552
|
+
typeLabel = 'ARRAY';
|
|
553
|
+
displayContent = JSON.stringify(value, null, 2);
|
|
554
|
+
} else if (typeof value === 'object' && value !== null) {
|
|
555
|
+
typeLabel = 'JSON';
|
|
556
|
+
displayContent = JSON.stringify(value, null, 2);
|
|
439
557
|
} else {
|
|
440
|
-
|
|
441
|
-
|
|
558
|
+
typeLabel = typeof value;
|
|
559
|
+
displayContent = String(value);
|
|
442
560
|
}
|
|
443
|
-
}
|
|
444
561
|
|
|
445
|
-
|
|
446
|
-
|
|
447
|
-
|
|
448
|
-
|
|
449
|
-
|
|
450
|
-
|
|
451
|
-
|
|
452
|
-
|
|
562
|
+
item.innerHTML = `
|
|
563
|
+
<div class="flex items-center justify-between mb-2">
|
|
564
|
+
<span class="text-[11px] font-bold text-neutral-300 font-mono">${key}</span>
|
|
565
|
+
<div class="flex items-center gap-2">
|
|
566
|
+
<span class="text-[9px] text-neutral-600 uppercase font-bold bg-[#111] px-1 rounded">${typeLabel}</span>
|
|
567
|
+
<button class="text-neutral-500 hover:text-white text-xs opacity-0 group-hover:opacity-100 transition-opacity copy-btn">
|
|
568
|
+
<i class="fas fa-copy"></i>
|
|
569
|
+
</button>
|
|
570
|
+
</div>
|
|
571
|
+
</div>
|
|
572
|
+
<pre class="text-[10px] text-neutral-500 whitespace-pre-wrap break-all font-mono leading-relaxed max-h-40 overflow-y-auto custom-scroll">${displayContent}</pre>
|
|
573
|
+
`;
|
|
453
574
|
|
|
454
|
-
|
|
455
|
-
|
|
456
|
-
|
|
457
|
-
|
|
458
|
-
|
|
459
|
-
}
|
|
575
|
+
item.querySelector('.copy-btn').onclick = function() {
|
|
576
|
+
navigator.clipboard.writeText(displayContent);
|
|
577
|
+
this.innerHTML = '<i class="fas fa-check text-green-400"></i>';
|
|
578
|
+
setTimeout(() => this.innerHTML = '<i class="fas fa-copy"></i>', 1000);
|
|
579
|
+
};
|
|
460
580
|
|
|
461
|
-
|
|
462
|
-
|
|
463
|
-
|
|
464
|
-
|
|
465
|
-
|
|
581
|
+
list.appendChild(item);
|
|
582
|
+
});
|
|
583
|
+
}
|
|
584
|
+
|
|
585
|
+
updateStatus(status) {
|
|
586
|
+
this.state = { ...this.state, ...status };
|
|
587
|
+
const deck = document.getElementById('control-deck');
|
|
588
|
+
const headerStatus = document.getElementById('header-status');
|
|
589
|
+
const dot = document.getElementById('status-dot');
|
|
590
|
+
const playBtn = document.getElementById('play-pause-btn');
|
|
591
|
+
|
|
592
|
+
if (status.isRunning && !status.isPaused) {
|
|
593
|
+
deck.style.borderColor = 'var(--success)';
|
|
594
|
+
headerStatus.textContent = "RUNNING";
|
|
595
|
+
headerStatus.className = "text-[9px] font-bold text-green-500 uppercase tracking-widest";
|
|
596
|
+
dot.className = "w-1.5 h-1.5 rounded-full bg-green-500 animate-pulse";
|
|
597
|
+
playBtn.innerHTML = '<i class="fas fa-pause"></i>';
|
|
598
|
+
} else if (status.isPaused) {
|
|
599
|
+
deck.style.borderColor = 'var(--warning)';
|
|
600
|
+
headerStatus.textContent = "PAUSED";
|
|
601
|
+
headerStatus.className = "text-[9px] font-bold text-yellow-500 uppercase tracking-widest";
|
|
602
|
+
dot.className = "w-1.5 h-1.5 rounded-full bg-yellow-500";
|
|
603
|
+
playBtn.innerHTML = '<i class="fas fa-play ml-1"></i>';
|
|
604
|
+
} else {
|
|
605
|
+
deck.style.borderColor = 'var(--border)';
|
|
606
|
+
headerStatus.textContent = "READY";
|
|
607
|
+
headerStatus.className = "text-[9px] font-bold text-neutral-500 uppercase tracking-widest";
|
|
608
|
+
dot.className = "w-1.5 h-1.5 rounded-full bg-neutral-600";
|
|
609
|
+
playBtn.innerHTML = '<i class="fas fa-play ml-1"></i>';
|
|
466
610
|
}
|
|
611
|
+
}
|
|
612
|
+
|
|
613
|
+
log(msg, type = "info") {
|
|
614
|
+
const feed = document.getElementById('log-feed');
|
|
615
|
+
const line = document.createElement('div');
|
|
616
|
+
line.className = 'log-line';
|
|
617
|
+
const time = new Date().toLocaleTimeString('en-GB', { hour12: false });
|
|
618
|
+
const color = type === 'error' ? 'text-red-500' : 'text-neutral-400';
|
|
619
|
+
line.innerHTML = `<span class="log-time text-[9px] font-mono opacity-50">[${time}]</span><span class="${color}">${msg}</span>`;
|
|
620
|
+
feed.appendChild(line);
|
|
621
|
+
feed.scrollTop = feed.scrollHeight;
|
|
622
|
+
}
|
|
467
623
|
|
|
468
|
-
|
|
469
|
-
|
|
470
|
-
|
|
624
|
+
setupListeners() {
|
|
625
|
+
document.getElementById('play-pause-btn').onclick = () => {
|
|
626
|
+
if (this.state.isRunning && !this.state.isPaused) this.sendMessage({ type: 'pause' });
|
|
627
|
+
else if (this.state.isPaused) this.sendMessage({ type: 'resume' });
|
|
628
|
+
else this.sendMessage({ type: 'run' });
|
|
629
|
+
};
|
|
630
|
+
document.getElementById('stop-btn').onclick = () => this.sendMessage({ type: 'stop' });
|
|
631
|
+
document.getElementById('replay-btn').onclick = () => this.sendMessage({ type: 'resume' });
|
|
632
|
+
}
|
|
633
|
+
|
|
634
|
+
sendMessage(message) {
|
|
635
|
+
if (this.ws?.readyState === WebSocket.OPEN) {
|
|
636
|
+
this.ws.send(JSON.stringify(message));
|
|
637
|
+
this.log(`Action: ${message.type.toUpperCase()}`);
|
|
471
638
|
}
|
|
472
|
-
|
|
473
|
-
|
|
474
|
-
|
|
639
|
+
}
|
|
640
|
+
|
|
641
|
+
updateConnectionUI(connected) {
|
|
642
|
+
const dot = document.getElementById('status-dot');
|
|
643
|
+
const headerStatus = document.getElementById('header-status');
|
|
644
|
+
if (connected) {
|
|
645
|
+
headerStatus.textContent = "READY";
|
|
646
|
+
headerStatus.className = "text-[9px] font-bold text-green-500 uppercase tracking-widest";
|
|
647
|
+
dot.className = "w-1.5 h-1.5 rounded-full bg-green-500";
|
|
648
|
+
} else {
|
|
649
|
+
headerStatus.textContent = "OFFLINE";
|
|
650
|
+
headerStatus.className = "text-[9px] font-bold text-red-500 uppercase tracking-widest";
|
|
651
|
+
dot.className = "w-1.5 h-1.5 rounded-full bg-red-500";
|
|
475
652
|
}
|
|
476
653
|
}
|
|
654
|
+
|
|
655
|
+
updateTokens(data) {
|
|
656
|
+
this.state.totalTokens = data.totalTokens || 0;
|
|
657
|
+
this.state.tokenRate = data.rate || 0;
|
|
658
|
+
document.getElementById('header-tokens').textContent = this.state.totalTokens.toLocaleString();
|
|
659
|
+
document.getElementById('header-rate').textContent = this.state.tokenRate.toFixed(1);
|
|
660
|
+
}
|
|
661
|
+
}
|
|
477
662
|
|
|
478
|
-
|
|
479
|
-
|
|
663
|
+
const engine = new WizardEngine();
|
|
664
|
+
</script>
|
|
480
665
|
</body>
|
|
481
|
-
</html>
|
|
666
|
+
</html>
|