helixevo 0.2.39 → 0.2.41
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/CHANGELOG.md +26 -0
- package/dashboard/app/changelog/page.tsx +179 -54
- package/dashboard/app/commands/page.tsx +243 -159
- package/dashboard/app/evolution/page.tsx +105 -102
- package/dashboard/app/frontier/page.tsx +103 -100
- package/dashboard/app/globals.css +1105 -403
- package/dashboard/app/guide/page.tsx +48 -4
- package/dashboard/app/layout.tsx +28 -57
- package/dashboard/app/network/client.tsx +453 -269
- package/dashboard/app/network/page.tsx +12 -2
- package/dashboard/app/page.tsx +166 -185
- package/dashboard/app/projects/client.tsx +891 -509
- package/dashboard/app/research/client.tsx +180 -248
- package/dashboard/components/SkillFlowNode.tsx +86 -128
- package/dashboard/components/console-panel.tsx +25 -0
- package/dashboard/components/metric-card.tsx +45 -0
- package/dashboard/components/overview-actions.tsx +29 -40
- package/dashboard/components/page-hero.tsx +44 -0
- package/dashboard/components/quick-actions.tsx +93 -167
- package/dashboard/components/section-frame.tsx +35 -0
- package/dashboard/components/sidebar-nav.tsx +75 -0
- package/dashboard/components/update-banner.tsx +101 -145
- package/dashboard/lib/data.ts +2 -2
- package/dist/cli.js +225 -156
- package/package.json +1 -1
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
'use client'
|
|
2
2
|
|
|
3
|
-
import {
|
|
3
|
+
import { useEffect, useState } from 'react'
|
|
4
4
|
|
|
5
5
|
const REGISTRY_URL = 'https://registry.npmjs.org/helixevo/latest'
|
|
6
6
|
const CHECK_INTERVAL_MS = 60 * 60 * 1000
|
|
@@ -39,7 +39,10 @@ export function UpdateBanner({ currentVersion }: { currentVersion: string }) {
|
|
|
39
39
|
}
|
|
40
40
|
check()
|
|
41
41
|
const interval = setInterval(check, CHECK_INTERVAL_MS)
|
|
42
|
-
return () => {
|
|
42
|
+
return () => {
|
|
43
|
+
mounted = false
|
|
44
|
+
clearInterval(interval)
|
|
45
|
+
}
|
|
43
46
|
}, [currentVersion])
|
|
44
47
|
|
|
45
48
|
if (!latestVersion || dismissed) return null
|
|
@@ -56,24 +59,21 @@ export function UpdateBanner({ currentVersion }: { currentVersion: string }) {
|
|
|
56
59
|
setNewVersion(data.version)
|
|
57
60
|
setState('reloading')
|
|
58
61
|
|
|
59
|
-
// Next.js dev mode detects config change and auto-restarts.
|
|
60
|
-
// Wait for recompilation, then poll until ready, then reload.
|
|
61
62
|
let secs = 12
|
|
62
63
|
setCountdown(secs)
|
|
63
64
|
const timer = setInterval(async () => {
|
|
64
|
-
secs
|
|
65
|
+
secs -= 1
|
|
65
66
|
setCountdown(secs)
|
|
66
67
|
if (secs <= 0) {
|
|
67
68
|
clearInterval(timer)
|
|
68
|
-
// Try polling a few times before force-reloading
|
|
69
69
|
for (let i = 0; i < 10; i++) {
|
|
70
70
|
try {
|
|
71
71
|
const check = await fetch('/?_v=' + Date.now(), { cache: 'no-store' })
|
|
72
72
|
if (check.ok) break
|
|
73
73
|
} catch {}
|
|
74
|
-
await new Promise(
|
|
74
|
+
await new Promise((resolve) => setTimeout(resolve, 1500))
|
|
75
75
|
}
|
|
76
|
-
window.location.href = window.location.pathname
|
|
76
|
+
window.location.href = `${window.location.pathname}?v=${Date.now()}`
|
|
77
77
|
}
|
|
78
78
|
}, 1000)
|
|
79
79
|
} else {
|
|
@@ -86,151 +86,107 @@ export function UpdateBanner({ currentVersion }: { currentVersion: string }) {
|
|
|
86
86
|
}
|
|
87
87
|
}
|
|
88
88
|
|
|
89
|
+
const tone = state === 'reloading' ? 'var(--green-border)' : state === 'error' ? 'var(--red-border)' : 'var(--purple-border)'
|
|
90
|
+
const progress = state === 'reloading' ? `${((12 - countdown) / 12) * 100}%` : '0%'
|
|
91
|
+
|
|
89
92
|
return (
|
|
90
|
-
<div
|
|
91
|
-
|
|
92
|
-
|
|
93
|
-
|
|
94
|
-
|
|
95
|
-
|
|
96
|
-
|
|
97
|
-
|
|
98
|
-
|
|
99
|
-
|
|
100
|
-
|
|
101
|
-
|
|
102
|
-
|
|
103
|
-
|
|
104
|
-
|
|
105
|
-
|
|
106
|
-
|
|
107
|
-
|
|
108
|
-
|
|
109
|
-
|
|
110
|
-
|
|
111
|
-
|
|
112
|
-
|
|
113
|
-
|
|
114
|
-
|
|
115
|
-
|
|
116
|
-
|
|
117
|
-
|
|
118
|
-
|
|
119
|
-
|
|
120
|
-
|
|
121
|
-
|
|
122
|
-
|
|
123
|
-
|
|
124
|
-
|
|
125
|
-
|
|
126
|
-
|
|
127
|
-
borderRadius: '50%',
|
|
128
|
-
|
|
129
|
-
|
|
130
|
-
|
|
131
|
-
|
|
132
|
-
|
|
133
|
-
</svg>
|
|
134
|
-
) : (
|
|
135
|
-
<svg width="14" height="14" viewBox="0 0 24 24" fill="none" stroke="var(--purple)" strokeWidth="2.5" strokeLinecap="round" strokeLinejoin="round">
|
|
136
|
-
<path d="M12 19V5m-7 7l7-7 7 7" />
|
|
137
|
-
</svg>
|
|
138
|
-
)}
|
|
139
|
-
</div>
|
|
140
|
-
<div>
|
|
141
|
-
<div style={{ fontSize: 13, fontWeight: 700, color: 'var(--text)' }}>
|
|
142
|
-
{state === 'updating' ? 'Installing...'
|
|
143
|
-
: state === 'reloading' ? 'Reloading...'
|
|
144
|
-
: state === 'error' ? 'Update Failed'
|
|
145
|
-
: 'Update Available'}
|
|
146
|
-
</div>
|
|
147
|
-
<div style={{ fontSize: 11, color: 'var(--text-dim)' }}>
|
|
148
|
-
{state === 'reloading'
|
|
149
|
-
? <>v{newVersion} installed — refreshing in {countdown}s</>
|
|
150
|
-
: <>v{currentVersion} → <span style={{ color: 'var(--green)', fontWeight: 600 }}>v{latestVersion}</span></>
|
|
151
|
-
}
|
|
93
|
+
<div
|
|
94
|
+
style={{
|
|
95
|
+
position: 'fixed',
|
|
96
|
+
right: 18,
|
|
97
|
+
bottom: 18,
|
|
98
|
+
width: 300,
|
|
99
|
+
zIndex: 9999,
|
|
100
|
+
borderRadius: 20,
|
|
101
|
+
border: `1px solid ${tone}`,
|
|
102
|
+
background: 'linear-gradient(180deg, rgba(255,255,255,0.95), rgba(249,245,239,0.94))',
|
|
103
|
+
boxShadow: 'var(--shadow-xl)',
|
|
104
|
+
overflow: 'hidden',
|
|
105
|
+
backdropFilter: 'blur(18px)',
|
|
106
|
+
}}
|
|
107
|
+
>
|
|
108
|
+
<div style={{ padding: '14px 16px 12px' }}>
|
|
109
|
+
{(state === 'idle' || state === 'error') ? (
|
|
110
|
+
<button
|
|
111
|
+
onClick={() => setDismissed(true)}
|
|
112
|
+
style={{
|
|
113
|
+
position: 'absolute',
|
|
114
|
+
top: 10,
|
|
115
|
+
right: 12,
|
|
116
|
+
border: 'none',
|
|
117
|
+
background: 'transparent',
|
|
118
|
+
color: 'var(--text-muted)',
|
|
119
|
+
fontSize: 16,
|
|
120
|
+
cursor: 'pointer',
|
|
121
|
+
}}
|
|
122
|
+
>
|
|
123
|
+
×
|
|
124
|
+
</button>
|
|
125
|
+
) : null}
|
|
126
|
+
|
|
127
|
+
<div style={{ display: 'flex', gap: 10, alignItems: 'flex-start' }}>
|
|
128
|
+
<div style={{ width: 34, height: 34, borderRadius: 12, background: state === 'error' ? 'var(--red-light)' : state === 'reloading' ? 'var(--green-light)' : 'var(--purple-light)', display: 'flex', alignItems: 'center', justifyContent: 'center', flexShrink: 0 }}>
|
|
129
|
+
{(state === 'updating' || state === 'reloading') ? (
|
|
130
|
+
<span style={{ width: 16, height: 16, border: `2px solid ${state === 'reloading' ? 'var(--green-border)' : 'var(--purple-border)'}`, borderTopColor: state === 'reloading' ? 'var(--green)' : 'var(--purple)', borderRadius: '50%', display: 'inline-block', animation: 'updateSpin 0.8s linear infinite' }} />
|
|
131
|
+
) : state === 'error' ? (
|
|
132
|
+
<span style={{ color: 'var(--red)', fontWeight: 800 }}>!</span>
|
|
133
|
+
) : (
|
|
134
|
+
<span style={{ color: 'var(--purple)', fontWeight: 800 }}>↑</span>
|
|
135
|
+
)}
|
|
152
136
|
</div>
|
|
153
|
-
</div>
|
|
154
|
-
</div>
|
|
155
137
|
|
|
156
|
-
|
|
157
|
-
|
|
158
|
-
|
|
159
|
-
|
|
160
|
-
|
|
161
|
-
|
|
162
|
-
|
|
163
|
-
|
|
164
|
-
|
|
165
|
-
<path d="M12 19V5m-7 7l7-7 7 7" />
|
|
166
|
-
</svg>
|
|
167
|
-
Update Now
|
|
168
|
-
</button>
|
|
169
|
-
)}
|
|
170
|
-
|
|
171
|
-
{/* Updating */}
|
|
172
|
-
{state === 'updating' && (
|
|
173
|
-
<div style={{
|
|
174
|
-
padding: '9px 16px', background: 'var(--bg-section)',
|
|
175
|
-
borderRadius: 'var(--radius)', fontSize: 12,
|
|
176
|
-
color: 'var(--text-secondary)', textAlign: 'center',
|
|
177
|
-
}}>
|
|
178
|
-
Installing helixevo@latest...
|
|
179
|
-
</div>
|
|
180
|
-
)}
|
|
181
|
-
|
|
182
|
-
{/* Reloading with countdown */}
|
|
183
|
-
{state === 'reloading' && (
|
|
184
|
-
<div>
|
|
185
|
-
<div style={{
|
|
186
|
-
padding: '9px 16px', background: 'var(--green-light)',
|
|
187
|
-
borderRadius: 'var(--radius)', fontSize: 12,
|
|
188
|
-
color: 'var(--green)', textAlign: 'center', fontWeight: 600,
|
|
189
|
-
marginBottom: 8,
|
|
190
|
-
}}>
|
|
191
|
-
Dashboard will refresh automatically
|
|
192
|
-
</div>
|
|
193
|
-
{/* Progress bar */}
|
|
194
|
-
<div style={{ height: 3, background: 'var(--bg-section)', borderRadius: 2, overflow: 'hidden' }}>
|
|
195
|
-
<div style={{
|
|
196
|
-
height: '100%', background: 'var(--green)',
|
|
197
|
-
borderRadius: 2,
|
|
198
|
-
width: `${((8 - countdown) / 8) * 100}%`,
|
|
199
|
-
transition: 'width 1s linear',
|
|
200
|
-
}} />
|
|
138
|
+
<div style={{ minWidth: 0 }}>
|
|
139
|
+
<div style={{ fontSize: 13, fontWeight: 800, color: 'var(--text)' }}>
|
|
140
|
+
{state === 'updating' ? 'Installing update…' : state === 'reloading' ? 'Reloading dashboard…' : state === 'error' ? 'Update failed' : 'Update available'}
|
|
141
|
+
</div>
|
|
142
|
+
<div style={{ marginTop: 4, fontSize: 11.5, color: 'var(--text-dim)', lineHeight: 1.5 }}>
|
|
143
|
+
{state === 'reloading'
|
|
144
|
+
? <>v{newVersion} installed — refreshing in {countdown}s</>
|
|
145
|
+
: <>v{currentVersion} → <span style={{ color: 'var(--green)', fontWeight: 700 }}>v{latestVersion}</span></>}
|
|
146
|
+
</div>
|
|
201
147
|
</div>
|
|
202
148
|
</div>
|
|
203
|
-
|
|
204
|
-
|
|
205
|
-
|
|
206
|
-
|
|
207
|
-
|
|
208
|
-
|
|
209
|
-
|
|
210
|
-
|
|
211
|
-
marginBottom: 8, maxHeight: 60, overflow: 'auto',
|
|
212
|
-
}}>
|
|
213
|
-
{errorMsg}
|
|
214
|
-
</div>
|
|
215
|
-
<button onClick={handleUpdate} style={{
|
|
216
|
-
width: '100%', padding: '7px 12px',
|
|
217
|
-
background: 'var(--bg-section)', color: 'var(--text-secondary)',
|
|
218
|
-
border: '1px solid var(--border)', borderRadius: 'var(--radius)',
|
|
219
|
-
fontSize: 12, fontWeight: 600, cursor: 'pointer',
|
|
220
|
-
}}>
|
|
221
|
-
Retry
|
|
149
|
+
|
|
150
|
+
{state === 'idle' ? (
|
|
151
|
+
<button
|
|
152
|
+
onClick={handleUpdate}
|
|
153
|
+
className="badge badge-purple"
|
|
154
|
+
style={{ marginTop: 14, border: 'none', cursor: 'pointer', width: '100%', justifyContent: 'center', padding: '10px 12px' }}
|
|
155
|
+
>
|
|
156
|
+
Update now
|
|
222
157
|
</button>
|
|
223
|
-
|
|
224
|
-
|
|
158
|
+
) : null}
|
|
159
|
+
|
|
160
|
+
{state === 'updating' ? (
|
|
161
|
+
<div style={{ marginTop: 14, fontSize: 11.5, color: 'var(--text-dim)' }}>Installing <code>helixevo@latest</code> and preparing the dashboard refresh.</div>
|
|
162
|
+
) : null}
|
|
163
|
+
|
|
164
|
+
{state === 'reloading' ? (
|
|
165
|
+
<div style={{ marginTop: 14 }}>
|
|
166
|
+
<div style={{ height: 5, borderRadius: 999, background: 'rgba(97,93,86,0.14)', overflow: 'hidden' }}>
|
|
167
|
+
<div style={{ height: '100%', width: progress, background: 'linear-gradient(90deg, var(--green), var(--blue))', borderRadius: 999, transition: 'width 1s linear' }} />
|
|
168
|
+
</div>
|
|
169
|
+
</div>
|
|
170
|
+
) : null}
|
|
171
|
+
|
|
172
|
+
{state === 'error' ? (
|
|
173
|
+
<>
|
|
174
|
+
<div style={{ marginTop: 14, padding: '10px 12px', borderRadius: 12, background: 'var(--red-light)', color: 'var(--red)', fontSize: 11.5, lineHeight: 1.55 }}>
|
|
175
|
+
{errorMsg}
|
|
176
|
+
</div>
|
|
177
|
+
<button
|
|
178
|
+
onClick={handleUpdate}
|
|
179
|
+
className="badge badge-gray"
|
|
180
|
+
style={{ marginTop: 12, border: 'none', cursor: 'pointer', width: '100%', justifyContent: 'center', padding: '10px 12px' }}
|
|
181
|
+
>
|
|
182
|
+
Retry update
|
|
183
|
+
</button>
|
|
184
|
+
</>
|
|
185
|
+
) : null}
|
|
186
|
+
</div>
|
|
225
187
|
|
|
226
188
|
<style>{`
|
|
227
|
-
@keyframes
|
|
228
|
-
from { opacity: 0; transform: translateY(16px) scale(0.97); }
|
|
229
|
-
to { opacity: 1; transform: translateY(0) scale(1); }
|
|
230
|
-
}
|
|
231
|
-
@keyframes updateSpin {
|
|
232
|
-
to { transform: rotate(360deg); }
|
|
233
|
-
}
|
|
189
|
+
@keyframes updateSpin { to { transform: rotate(360deg); } }
|
|
234
190
|
`}</style>
|
|
235
191
|
</div>
|
|
236
192
|
)
|
package/dashboard/lib/data.ts
CHANGED
|
@@ -90,9 +90,9 @@ export function loadHistory(): { iterations: Iteration[] } {
|
|
|
90
90
|
}
|
|
91
91
|
|
|
92
92
|
export function loadSkillTests(): { id: string; skill: string; input: string }[] {
|
|
93
|
-
const newFile = readJsonl('skill-tests.jsonl')
|
|
93
|
+
const newFile = readJsonl<{ id: string; skill: string; input: string }>('skill-tests.jsonl')
|
|
94
94
|
if (newFile.length > 0) return newFile
|
|
95
|
-
return readJsonl('golden-cases.jsonl')
|
|
95
|
+
return readJsonl<{ id: string; skill: string; input: string }>('golden-cases.jsonl')
|
|
96
96
|
}
|
|
97
97
|
|
|
98
98
|
export function loadBuffer(): KnowledgeBuffer {
|