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.
@@ -1,7 +1,10 @@
1
1
  'use client'
2
2
 
3
- import { useState } from 'react'
3
+ import { useMemo, useState } from 'react'
4
+ import { MetricCard } from '@/components/metric-card'
5
+ import { PageHero } from '@/components/page-hero'
4
6
  import { QuickActions } from '@/components/quick-actions'
7
+ import { SectionFrame } from '@/components/section-frame'
5
8
 
6
9
  interface CommandInfo {
7
10
  name: string
@@ -222,209 +225,290 @@ const COMMANDS: CommandInfo[] = [
222
225
  },
223
226
  {
224
227
  name: 'dashboard',
225
- description: 'Launch the web dashboard at http://localhost:3847. Provides a visual interface for monitoring skills, evolution, frontier, and network health.',
226
- usage: 'helixevo dashboard',
228
+ description: 'Launch the web dashboard at http://localhost:3847. When a newer npm version is available, HelixEvo now auto-updates itself before opening the dashboard unless you opt out.',
229
+ usage: 'helixevo dashboard [options]',
227
230
  examples: [
228
- { cmd: 'helixevo dashboard', desc: 'Open the dashboard in your browser' },
231
+ { cmd: 'helixevo dashboard', desc: 'Auto-update to the latest version if needed, then open the dashboard' },
232
+ { cmd: 'helixevo dashboard --background', desc: 'Run the dashboard in the background after the same update check' },
233
+ { cmd: 'helixevo dashboard --no-auto-update', desc: 'Open the dashboard immediately without checking npm for updates' },
234
+ ],
235
+ options: [
236
+ { flag: '--background', desc: 'Run the dashboard detached from the terminal' },
237
+ { flag: '--stop', desc: 'Stop a background dashboard process' },
238
+ { flag: '--no-auto-update', desc: 'Skip the automatic update check before launch' },
229
239
  ],
230
240
  category: 'system',
231
241
  needsLLM: false,
232
- note: 'You are currently using the dashboard!',
242
+ note: 'You are currently using the dashboard. By default it now upgrades itself first when a newer release is available.',
233
243
  },
234
244
  ]
235
245
 
236
- const CATEGORIES: { id: string; label: string; color: string }[] = [
237
- { id: 'core', label: 'Core Workflow', color: 'var(--purple)' },
238
- { id: 'evolution', label: 'Evolution', color: 'var(--green)' },
239
- { id: 'network', label: 'Network & Research', color: 'var(--blue)' },
240
- { id: 'analysis', label: 'Analysis & Reports', color: 'var(--yellow)' },
241
- { id: 'system', label: 'System', color: 'var(--text-secondary)' },
246
+ const WORKFLOW = [
247
+ { label: 'init', desc: 'Import skills', tone: 'purple' as const },
248
+ { label: 'watch', desc: 'Capture corrections', tone: 'blue' as const },
249
+ { label: 'evolve', desc: 'Improve skills', tone: 'green' as const },
250
+ { label: 'generalize', desc: 'Abstract patterns', tone: 'purple' as const },
251
+ { label: 'graph --rebuild', desc: 'Map relationships', tone: 'yellow' as const },
252
+ { label: 'health', desc: 'Assess quality', tone: 'blue' as const },
253
+ ]
254
+
255
+ const CATEGORIES: Array<{
256
+ id: CommandInfo['category']
257
+ label: string
258
+ tone: 'neutral' | 'purple' | 'green' | 'blue' | 'yellow'
259
+ description: string
260
+ }> = [
261
+ { id: 'core', label: 'Core workflow', tone: 'purple', description: 'The commands that initialize HelixEvo and keep it learning continuously.' },
262
+ { id: 'evolution', label: 'Evolution', tone: 'green', description: 'Mutation, promotion, and specialization controls for active skill improvement.' },
263
+ { id: 'network', label: 'Network & research', tone: 'blue', description: 'Graph maintenance, discovery, and relationship mapping across the skill ecosystem.' },
264
+ { id: 'analysis', label: 'Analysis & reports', tone: 'yellow', description: 'Operational reads on system quality, trends, reports, and health.' },
265
+ { id: 'system', label: 'System', tone: 'neutral', description: 'Supporting commands for capture, dashboard access, and environment-level actions.' },
242
266
  ]
243
267
 
268
+ function toneColor(tone: 'neutral' | 'purple' | 'green' | 'blue' | 'yellow') {
269
+ if (tone === 'purple') return 'var(--purple)'
270
+ if (tone === 'green') return 'var(--green)'
271
+ if (tone === 'blue') return 'var(--blue)'
272
+ if (tone === 'yellow') return 'var(--yellow)'
273
+ return 'var(--text-secondary)'
274
+ }
275
+
244
276
  export default function CommandsPage() {
245
- const [expandedCmd, setExpandedCmd] = useState<string | null>(null)
277
+ const [expandedCmd, setExpandedCmd] = useState<string | null>('watch')
278
+
279
+ const stats = useMemo(() => {
280
+ const llmCommands = COMMANDS.filter(command => command.needsLLM).length
281
+ const runnableCommands = COMMANDS.filter(command => command.runnable).length
282
+ const optionFlags = COMMANDS.reduce((sum, command) => sum + (command.options?.length ?? 0), 0)
283
+ return { llmCommands, runnableCommands, optionFlags }
284
+ }, [])
246
285
 
247
286
  return (
248
287
  <div>
249
- <div className="page-header">
250
- <h1 className="page-title">Commands</h1>
251
- <p className="page-desc">
252
- All CLI commands available in HelixEvo click any command for details and examples, or run directly from here
253
- </p>
288
+ <PageHero
289
+ eyebrow="Command center"
290
+ title="Commands"
291
+ description="The complete HelixEvo CLI surfaceorganized by workflow, annotated by purpose, and ready to run from the dashboard when supported."
292
+ chips={[
293
+ { label: `${COMMANDS.length} commands`, tone: 'blue' },
294
+ { label: `${stats.llmCommands} need LLM access`, tone: 'purple' },
295
+ { label: `${stats.runnableCommands} runnable here`, tone: 'green' },
296
+ { label: `${stats.optionFlags} documented flags`, tone: 'yellow' },
297
+ ]}
298
+ actions={
299
+ <div className="hero-note-card">
300
+ <div className="hero-note-label">Recommended operating loop</div>
301
+ <div className="hero-note-title">Init → Watch → Evolve → Generalize → Graph → Health</div>
302
+ <div className="hero-note-copy">Use the Commands page as the practical bridge between HelixEvo’s CLI and the premium dashboard cockpit.</div>
303
+ </div>
304
+ }
305
+ />
306
+
307
+ <div className="grid-4" style={{ marginBottom: 24 }}>
308
+ <MetricCard label="CLI surface" value={COMMANDS.length} sublabel="Documented HelixEvo commands across core, evolution, network, analysis, and system layers." tone="blue" />
309
+ <MetricCard label="Live actions" value={stats.runnableCommands} sublabel="Commands with dashboard launch actions wired through the quick action system." tone="green" />
310
+ <MetricCard label="LLM-dependent" value={stats.llmCommands} sublabel="Commands that rely on model-backed evaluation, generation, or analysis." tone="purple" />
311
+ <MetricCard label="Flags documented" value={stats.optionFlags} sublabel="Total option flags surfaced across the current command reference." tone="yellow" />
254
312
  </div>
255
313
 
256
- {/* Typical workflow */}
257
- <div className="card" style={{ marginBottom: 24, padding: '16px 20px' }}>
258
- <div style={{ fontSize: 13, fontWeight: 700, color: 'var(--text)', marginBottom: 8 }}>Typical Workflow</div>
259
- <div style={{ display: 'flex', alignItems: 'center', gap: 6, flexWrap: 'wrap', fontSize: 12 }}>
260
- {[
261
- { label: 'init', desc: 'Import skills' },
262
- { label: 'watch', desc: 'Capture corrections' },
263
- { label: 'evolve', desc: 'Improve skills' },
264
- { label: 'generalize', desc: 'Abstract patterns' },
265
- { label: 'graph --rebuild', desc: 'Map relationships' },
266
- { label: 'health', desc: 'Assess quality' },
267
- ].map((step, i) => (
268
- <span key={step.label} style={{ display: 'flex', alignItems: 'center', gap: 6 }}>
269
- <span style={{
270
- background: 'var(--purple-light)', color: 'var(--purple)',
271
- padding: '4px 10px', borderRadius: 'var(--radius)',
272
- fontFamily: 'var(--font-mono)', fontWeight: 600,
314
+ <SectionFrame
315
+ eyebrow="Workflow framing"
316
+ title="Typical operating sequence"
317
+ description="A high-signal path through the CLI when standing HelixEvo up and then keeping it improving over time."
318
+ tone="purple"
319
+ >
320
+ <div style={{ display: 'flex', alignItems: 'center', gap: 8, flexWrap: 'wrap' }}>
321
+ {WORKFLOW.map((step, index) => (
322
+ <div key={step.label} style={{ display: 'flex', alignItems: 'center', gap: 8 }}>
323
+ <div style={{
324
+ display: 'inline-flex',
325
+ alignItems: 'center',
326
+ gap: 8,
327
+ padding: '10px 14px',
328
+ borderRadius: 999,
329
+ border: '1px solid var(--border)',
330
+ background: 'rgba(255,255,255,0.72)',
331
+ boxShadow: 'var(--shadow-xs)',
273
332
  }}>
274
- {step.label}
275
- </span>
276
- <span style={{ color: 'var(--text-dim)' }}>{step.desc}</span>
277
- {i < 5 && <span style={{ color: 'var(--text-muted)', margin: '0 4px' }}>&rarr;</span>}
278
- </span>
333
+ <span className={`hero-chip hero-chip-${step.tone}`}>{step.label}</span>
334
+ <span style={{ fontSize: 12, color: 'var(--text-dim)' }}>{step.desc}</span>
335
+ </div>
336
+ {index < WORKFLOW.length - 1 ? <span style={{ color: 'var(--text-muted)', fontSize: 15 }}>→</span> : null}
337
+ </div>
279
338
  ))}
280
339
  </div>
281
- </div>
340
+ </SectionFrame>
282
341
 
283
- {/* Commands by category */}
284
- {CATEGORIES.map(cat => {
285
- const cmds = COMMANDS.filter(c => c.category === cat.id)
286
- if (cmds.length === 0) return null
342
+ {CATEGORIES.map(category => {
343
+ const commands = COMMANDS.filter(command => command.category === category.id)
344
+ if (commands.length === 0) return null
287
345
 
288
346
  return (
289
- <div key={cat.id} style={{ marginBottom: 24 }}>
290
- <div style={{
291
- fontSize: 11, fontWeight: 700, color: cat.color,
292
- textTransform: 'uppercase', letterSpacing: 1.2, marginBottom: 10,
293
- }}>
294
- {cat.label}
295
- </div>
347
+ <SectionFrame
348
+ key={category.id}
349
+ eyebrow={`${commands.length} command${commands.length === 1 ? '' : 's'}`}
350
+ title={category.label}
351
+ description={category.description}
352
+ tone={category.tone}
353
+ className="section-frame-tight"
354
+ >
355
+ <div style={{ display: 'grid', gap: 12 }}>
356
+ {commands.map(command => {
357
+ const isExpanded = expandedCmd === command.name
358
+ const categoryColor = toneColor(category.tone)
296
359
 
297
- <div style={{ display: 'flex', flexDirection: 'column', gap: 8 }}>
298
- {cmds.map(cmd => {
299
- const isExpanded = expandedCmd === cmd.name
300
360
  return (
301
- <div key={cmd.name} className="card" style={{
361
+ <article key={command.name} className="card" style={{
302
362
  overflow: 'hidden',
303
- border: isExpanded ? `1px solid ${cat.color}40` : undefined,
363
+ borderColor: isExpanded ? `${categoryColor}30` : undefined,
364
+ boxShadow: isExpanded ? 'var(--shadow-md)' : undefined,
304
365
  }}>
305
- {/* Command header — clickable */}
306
- <div
307
- onClick={() => setExpandedCmd(isExpanded ? null : cmd.name)}
366
+ <button
367
+ onClick={() => setExpandedCmd(isExpanded ? null : command.name)}
308
368
  style={{
309
- padding: '12px 16px',
369
+ width: '100%',
370
+ padding: '16px 18px',
371
+ border: 'none',
372
+ background: isExpanded ? 'linear-gradient(180deg, rgba(255,255,255,0.92), rgba(245,241,236,0.82))' : 'transparent',
373
+ display: 'flex',
374
+ justifyContent: 'space-between',
375
+ alignItems: 'flex-start',
376
+ gap: 16,
310
377
  cursor: 'pointer',
311
- display: 'flex', justifyContent: 'space-between', alignItems: 'center',
378
+ textAlign: 'left',
312
379
  }}
313
380
  >
314
- <div style={{ display: 'flex', alignItems: 'center', gap: 10 }}>
315
- <code style={{
316
- fontFamily: 'var(--font-mono)', fontSize: 13, fontWeight: 700,
317
- color: cat.color,
318
- }}>
319
- {cmd.name}
320
- </code>
321
- <span style={{ fontSize: 12, color: 'var(--text-secondary)' }}>
322
- {cmd.description.split('.')[0]}
323
- </span>
324
- {cmd.needsLLM && (
325
- <span style={{
326
- fontSize: 9, fontWeight: 600, padding: '2px 6px',
327
- background: 'var(--purple-light)', color: 'var(--purple)',
328
- borderRadius: 4,
329
- }}>LLM</span>
330
- )}
381
+ <div style={{ flex: 1, minWidth: 0 }}>
382
+ <div style={{ display: 'flex', alignItems: 'center', gap: 8, flexWrap: 'wrap', marginBottom: 8 }}>
383
+ <code style={{ fontFamily: 'var(--font-mono)', fontSize: 14, fontWeight: 700, color: categoryColor }}>
384
+ {command.name}
385
+ </code>
386
+ <span className={`hero-chip hero-chip-${category.tone}`}>{category.label}</span>
387
+ {command.needsLLM ? <span className="hero-chip hero-chip-purple">LLM</span> : <span className="hero-chip hero-chip-neutral">local</span>}
388
+ {command.runnable ? <span className="hero-chip hero-chip-green">runnable</span> : null}
389
+ </div>
390
+ <div style={{ fontSize: 12.5, color: 'var(--text-secondary)', lineHeight: 1.65, maxWidth: 860 }}>
391
+ {command.description}
392
+ </div>
331
393
  </div>
332
- <span style={{
333
- color: 'var(--text-muted)', fontSize: 12,
334
- transform: isExpanded ? 'rotate(180deg)' : 'none',
335
- transition: 'transform 0.2s',
336
- }}>▼</span>
337
- </div>
338
-
339
- {/* Expanded details */}
340
- {isExpanded && (
341
394
  <div style={{
342
- padding: '0 16px 16px',
343
- borderTop: '1px solid var(--border-subtle)',
395
+ flexShrink: 0,
396
+ width: 30,
397
+ height: 30,
398
+ borderRadius: 999,
399
+ background: 'rgba(97,93,86,0.08)',
400
+ border: '1px solid var(--border)',
401
+ color: 'var(--text-muted)',
402
+ display: 'flex',
403
+ alignItems: 'center',
404
+ justifyContent: 'center',
405
+ transform: isExpanded ? 'rotate(180deg)' : 'none',
406
+ transition: 'transform 0.2s ease',
407
+ marginTop: 2,
344
408
  }}>
345
- {/* Description */}
346
- <p style={{ fontSize: 12, color: 'var(--text-secondary)', lineHeight: 1.6, marginTop: 12, marginBottom: 14 }}>
347
- {cmd.description}
348
- </p>
409
+
410
+ </div>
411
+ </button>
349
412
 
350
- {/* Usage */}
351
- <div style={{ marginBottom: 14 }}>
352
- <div style={{ fontSize: 10, fontWeight: 600, color: 'var(--text-muted)', textTransform: 'uppercase', letterSpacing: 1, marginBottom: 6 }}>Usage</div>
353
- <code style={{
354
- display: 'block', padding: '8px 12px',
355
- background: 'var(--bg-section)', borderRadius: 'var(--radius)',
356
- fontFamily: 'var(--font-mono)', fontSize: 12, color: 'var(--text)',
357
- }}>
358
- $ {cmd.usage}
359
- </code>
360
- </div>
413
+ {isExpanded ? (
414
+ <div style={{ padding: '0 18px 18px', borderTop: '1px solid var(--border-subtle)' }}>
415
+ <div className="grid-2" style={{ alignItems: 'start', gap: 16, marginTop: 16 }}>
416
+ <div style={{ display: 'grid', gap: 14 }}>
417
+ <div>
418
+ <div style={{ fontSize: 10.5, fontWeight: 700, color: 'var(--text-muted)', textTransform: 'uppercase', letterSpacing: 0.9, marginBottom: 6 }}>Usage</div>
419
+ <code style={{
420
+ display: 'block',
421
+ padding: '12px 14px',
422
+ background: 'rgba(97,93,86,0.07)',
423
+ borderRadius: 16,
424
+ border: '1px solid var(--border)',
425
+ fontFamily: 'var(--font-mono)',
426
+ fontSize: 12,
427
+ color: 'var(--text)',
428
+ }}>
429
+ $ {command.usage}
430
+ </code>
431
+ </div>
361
432
 
362
- {/* Options */}
363
- {cmd.options && cmd.options.length > 0 && (
364
- <div style={{ marginBottom: 14 }}>
365
- <div style={{ fontSize: 10, fontWeight: 600, color: 'var(--text-muted)', textTransform: 'uppercase', letterSpacing: 1, marginBottom: 6 }}>Options</div>
366
- <div style={{ display: 'flex', flexDirection: 'column', gap: 4 }}>
367
- {cmd.options.map(opt => (
368
- <div key={opt.flag} style={{ display: 'flex', gap: 12, fontSize: 12, padding: '4px 0' }}>
369
- <code style={{
370
- fontFamily: 'var(--font-mono)', color: 'var(--purple)',
371
- fontWeight: 600, minWidth: 180, flexShrink: 0,
372
- }}>{opt.flag}</code>
373
- <span style={{ color: 'var(--text-dim)' }}>{opt.desc}</span>
433
+ {command.options && command.options.length > 0 ? (
434
+ <div>
435
+ <div style={{ fontSize: 10.5, fontWeight: 700, color: 'var(--text-muted)', textTransform: 'uppercase', letterSpacing: 0.9, marginBottom: 6 }}>Options</div>
436
+ <div style={{ display: 'grid', gap: 8 }}>
437
+ {command.options.map(option => (
438
+ <div key={option.flag} style={{
439
+ padding: '10px 12px',
440
+ borderRadius: 14,
441
+ background: 'rgba(255,255,255,0.72)',
442
+ border: '1px solid var(--border)',
443
+ }}>
444
+ <code style={{ display: 'block', fontFamily: 'var(--font-mono)', color: 'var(--purple)', fontSize: 11.5, fontWeight: 700, marginBottom: 4 }}>
445
+ {option.flag}
446
+ </code>
447
+ <div style={{ fontSize: 12, color: 'var(--text-dim)', lineHeight: 1.55 }}>{option.desc}</div>
448
+ </div>
449
+ ))}
374
450
  </div>
375
- ))}
376
- </div>
377
- </div>
378
- )}
451
+ </div>
452
+ ) : null}
379
453
 
380
- {/* Examples */}
381
- <div style={{ marginBottom: cmd.runnable ? 14 : 0 }}>
382
- <div style={{ fontSize: 10, fontWeight: 600, color: 'var(--text-muted)', textTransform: 'uppercase', letterSpacing: 1, marginBottom: 6 }}>Examples</div>
383
- <div style={{ display: 'flex', flexDirection: 'column', gap: 6 }}>
384
- {cmd.examples.map((ex, i) => (
385
- <div key={i} style={{
386
- padding: '8px 12px',
387
- background: 'var(--bg-section)', borderRadius: 'var(--radius)',
454
+ {command.note ? (
455
+ <div style={{
456
+ padding: '12px 14px',
457
+ background: 'var(--yellow-light)',
458
+ border: '1px solid var(--yellow-border)',
459
+ borderRadius: 16,
460
+ color: 'var(--yellow)',
461
+ fontSize: 12,
462
+ lineHeight: 1.6,
388
463
  }}>
389
- <code style={{ fontFamily: 'var(--font-mono)', fontSize: 11, color: 'var(--text)', fontWeight: 600 }}>
390
- $ {ex.cmd}
391
- </code>
392
- <div style={{ fontSize: 11, color: 'var(--text-dim)', marginTop: 2 }}>{ex.desc}</div>
464
+ <strong style={{ display: 'block', marginBottom: 4 }}>Operational note</strong>
465
+ {command.note}
393
466
  </div>
394
- ))}
467
+ ) : null}
395
468
  </div>
396
- </div>
397
469
 
398
- {/* Note */}
399
- {cmd.note && (
400
- <div style={{
401
- padding: '8px 12px', marginBottom: cmd.runnable ? 14 : 0,
402
- background: 'var(--yellow-light)', borderRadius: 'var(--radius)',
403
- fontSize: 11, color: 'var(--yellow)', fontWeight: 500,
404
- borderLeft: '3px solid var(--yellow)',
405
- }}>
406
- {cmd.note}
407
- </div>
408
- )}
470
+ <div style={{ display: 'grid', gap: 14 }}>
471
+ <div>
472
+ <div style={{ fontSize: 10.5, fontWeight: 700, color: 'var(--text-muted)', textTransform: 'uppercase', letterSpacing: 0.9, marginBottom: 6 }}>Examples</div>
473
+ <div style={{ display: 'grid', gap: 8 }}>
474
+ {command.examples.map((example, index) => (
475
+ <div key={`${command.name}-example-${index}`} style={{
476
+ padding: '12px 14px',
477
+ borderRadius: 16,
478
+ background: 'rgba(255,255,255,0.72)',
479
+ border: '1px solid var(--border)',
480
+ }}>
481
+ <code style={{ display: 'block', fontFamily: 'var(--font-mono)', fontSize: 11.5, color: 'var(--text)', fontWeight: 700, marginBottom: 4 }}>
482
+ $ {example.cmd}
483
+ </code>
484
+ <div style={{ fontSize: 12, color: 'var(--text-dim)', lineHeight: 1.55 }}>{example.desc}</div>
485
+ </div>
486
+ ))}
487
+ </div>
488
+ </div>
409
489
 
410
- {/* Run button */}
411
- {cmd.runnable && (
412
- <QuickActions actions={[{
413
- id: cmd.runnable.command,
414
- label: cmd.runnable.label,
415
- command: cmd.runnable.command,
416
- icon: cmd.runnable.icon,
417
- color: cmd.runnable.color,
418
- description: `Run: helixevo ${cmd.name}`,
419
- }]} />
420
- )}
490
+ {command.runnable ? (
491
+ <div>
492
+ <div style={{ fontSize: 10.5, fontWeight: 700, color: 'var(--text-muted)', textTransform: 'uppercase', letterSpacing: 0.9, marginBottom: 8 }}>Launch from dashboard</div>
493
+ <QuickActions actions={[{
494
+ id: command.runnable.command,
495
+ label: command.runnable.label,
496
+ command: command.runnable.command,
497
+ icon: command.runnable.icon,
498
+ color: command.runnable.color,
499
+ description: `Run: helixevo ${command.name}`,
500
+ }]} />
501
+ </div>
502
+ ) : null}
503
+ </div>
504
+ </div>
421
505
  </div>
422
- )}
423
- </div>
506
+ ) : null}
507
+ </article>
424
508
  )
425
509
  })}
426
510
  </div>
427
- </div>
511
+ </SectionFrame>
428
512
  )
429
513
  })}
430
514
  </div>