Skip to content

Commit bfe1411

Browse files
committed
feat(docs): pagina /docs hub documentazione — 4 tab, 36 moduli, 27 CLI, 24 API routes con dati statici
2 parents 7cbe3a0 + 77fae85 commit bfe1411

2 files changed

Lines changed: 249 additions & 0 deletions

File tree

web/app/docs/data.ts

Lines changed: 114 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,114 @@
1+
export type DocSection = { id: string; label: string }
2+
export type Module = { id: string; description: string; group: string }
3+
export type CliCmd = { cmd: string; description: string; example?: string }
4+
export type ApiRoute = { method: 'GET' | 'POST' | 'PATCH' | 'DELETE'; path: string; description: string }
5+
6+
export const SECTIONS: DocSection[] = [
7+
{ id: 'overview', label: 'Architettura' },
8+
{ id: 'modules', label: 'Moduli shared/' },
9+
{ id: 'cli', label: 'Comandi CLI' },
10+
{ id: 'api', label: 'API Routes' },
11+
]
12+
13+
export const MODULES: Module[] = [
14+
// Core
15+
{ id: 'agents', group: 'Core', description: 'Definizioni agenti, configurazione ruoli e capacità' },
16+
{ id: 'tasks', group: 'Core', description: 'Gestione task asincroni con stati queued/running/terminal' },
17+
{ id: 'sessions', group: 'Core', description: 'Sessioni conversazione multi-canale (web, CLI, Telegram)' },
18+
{ id: 'events', group: 'Core', description: 'EventBus pub/sub + SSE per notifiche real-time' },
19+
{ id: 'history', group: 'Core', description: 'Cronologia conversazioni con transcript JSONL' },
20+
// AI
21+
{ id: 'context-engine',group: 'AI', description: 'Assembla contesto AI rispettando budget token' },
22+
{ id: 'llm', group: 'AI', description: 'Client unificato per provider AI (Anthropic, OpenAI, Minimax)' },
23+
{ id: 'memory', group: 'AI', description: 'Memoria persistente agenti: soul, identity, episodic' },
24+
{ id: 'providers', group: 'AI', description: 'Configurazione e auth provider AI' },
25+
{ id: 'analytics', group: 'AI', description: 'Metriche uso API, costi token, latenza' },
26+
// Data
27+
{ id: 'backup', group: 'Dati', description: 'Backup atomico con manifest + ripristino selettivo' },
28+
{ id: 'migrations', group: 'Dati', description: 'Migrazioni schema versionate con rollback' },
29+
{ id: 'i18n', group: 'Dati', description: 'Internazionalizzazione, chiavi traduzione IT/EN' },
30+
{ id: 'data', group: 'Dati', description: 'Layer accesso dati, lettura/scrittura JSON atomica' },
31+
{ id: 'credentials', group: 'Dati', description: 'Gestione credenziali cifrate per servizi esterni' },
32+
{ id: 'secrets', group: 'Dati', description: 'Secrets cifrati AES-256 (API key, token, password)' },
33+
// Sistema
34+
{ id: 'daemon', group: 'Sistema', description: 'Processo daemon: plist (macOS), systemd (Linux)' },
35+
{ id: 'scheduler', group: 'Sistema', description: 'Job scheduler con cron expression e retry' },
36+
{ id: 'cron', group: 'Sistema', description: 'Definizioni job cron e gestione lifecycle' },
37+
{ id: 'monitoring', group: 'Sistema', description: 'CPU, memoria, heartbeat, alerter soglie' },
38+
{ id: 'logger', group: 'Sistema', description: 'Logger strutturato livelli DEBUG/INFO/WARN/ERROR' },
39+
{ id: 'rate-limiter', group: 'Sistema', description: 'Rate limiter token bucket per API esterne' },
40+
{ id: 'retry', group: 'Sistema', description: 'Circuit breaker + retry esponenziale' },
41+
{ id: 'queue', group: 'Sistema', description: 'Coda task prioritaria con concorrenza configurabile' },
42+
// Integrazione
43+
{ id: 'telegram', group: 'Integrazione', description: 'Bot Telegram: handler messaggi, webhook, polling' },
44+
{ id: 'channels', group: 'Integrazione', description: 'Canali comunicazione astratti (web/CLI/Telegram)' },
45+
{ id: 'gateway', group: 'Integrazione', description: 'Gateway API esterno con routing e auth middleware' },
46+
{ id: 'hooks', group: 'Integrazione', description: 'Hook eventi su azioni sistema (task completato, ecc.)' },
47+
{ id: 'plugins', group: 'Integrazione', description: 'Sistema plugin: discovery, caricamento, lifecycle' },
48+
{ id: 'skills', group: 'Integrazione', description: 'Skill agenti: definizione, registrazione, esecuzione' },
49+
{ id: 'tools', group: 'Integrazione', description: 'Tool AI registrati e disponibili agli agenti' },
50+
{ id: 'templates', group: 'Integrazione', description: 'Template messaggi con variabili e categorie' },
51+
{ id: 'notifications', group: 'Integrazione', description: 'Centro notifiche: read/unread, filtri, desktop' },
52+
{ id: 'docs', group: 'Integrazione', description: 'Helper generazione documentazione da sorgenti' },
53+
{ id: 'validators', group: 'Integrazione', description: 'Validatori schema JSON con report errori' },
54+
{ id: 'deploy', group: 'Integrazione', description: 'Deploy pipeline: build, push, rollback' },
55+
{ id: 'assistant', group: 'Integrazione', description: 'Assistente AI con context e upload allegati' },
56+
]
57+
58+
export const CLI_COMMANDS: CliCmd[] = [
59+
{ cmd: 'jht setup', description: 'Wizard configurazione iniziale workspace' },
60+
{ cmd: 'jht status', description: 'Stato sistema: agenti attivi, sessioni, task' },
61+
{ cmd: 'jht health', description: 'Health check 7 moduli con semafori' },
62+
{ cmd: 'jht doctor', description: 'Diagnostica config, provider, dipendenze, permessi' },
63+
{ cmd: 'jht upgrade', description: 'Verifica versione remote e aggiorna (--apply)' },
64+
{ cmd: 'jht dashboard', description: 'Avvia Next.js dev server e apre browser', example: 'jht dashboard --port 3001' },
65+
{ cmd: 'jht team start', description: 'Avvia agenti in sessioni tmux JHT-*', example: 'jht team start ALFA' },
66+
{ cmd: 'jht team stop', description: 'Ferma sessioni tmux agenti' },
67+
{ cmd: 'jht team list', description: 'Elenca sessioni tmux attive JHT-*' },
68+
{ cmd: 'jht agents', description: '8 agenti con stato tmux e conteggio task' },
69+
{ cmd: 'jht sessions', description: 'Tabella sessioni con filtri stato/tail/verbose' },
70+
{ cmd: 'jht stats', description: 'Statistiche aggregate task/API/sessioni con periodo' },
71+
{ cmd: 'jht backup', description: 'Crea/lista/ripristina backup con manifest' },
72+
{ cmd: 'jht migrate', description: 'Migrazioni v1→v4 con dry-run' },
73+
{ cmd: 'jht cache', description: 'Stats e pulizia cache/tmp/logs' },
74+
{ cmd: 'jht export', description: 'Esporta dati JSON/CSV con filtro date' },
75+
{ cmd: 'jht import', description: 'Importa dati con validazione e dry-run' },
76+
{ cmd: 'jht logs', description: 'Log con filtri livello/modulo, output colorato' },
77+
{ cmd: 'jht config', description: 'Legge e imposta valori configurazione' },
78+
{ cmd: 'jht plugins', description: 'Lista/abilita/disabilita plugin da manifest' },
79+
{ cmd: 'jht providers', description: 'Stato autenticazione Anthropic/OpenAI/Minimax' },
80+
{ cmd: 'jht context', description: 'Stato/sources/clear context-engine' },
81+
{ cmd: 'jht secrets', description: 'Gestione secrets AES-256: list/set/get/delete' },
82+
{ cmd: 'jht hooks', description: 'Lista/abilita/disabilita/show hook per evento' },
83+
{ cmd: 'jht notifications', description: 'Lista/read/clear notifiche (alias: notif)' },
84+
{ cmd: 'jht templates', description: 'Lista template per categoria, preview variabili' },
85+
{ cmd: 'jht cron', description: 'Job cron: list/enable/disable/run' },
86+
]
87+
88+
export const API_ROUTES: ApiRoute[] = [
89+
{ method: 'GET', path: '/api/agents', description: 'Lista agenti con stato sessione tmux' },
90+
{ method: 'GET', path: '/api/tasks', description: 'Task con filtro stato (queued/running/terminal)' },
91+
{ method: 'POST', path: '/api/tasks', description: 'Crea nuovo task con agentId opzionale' },
92+
{ method: 'PATCH', path: '/api/tasks', description: 'Cancella task attivo' },
93+
{ method: 'GET', path: '/api/sessions', description: 'Lista sessioni con filtro stato' },
94+
{ method: 'POST', path: '/api/sessions', description: 'Crea sessione su canale' },
95+
{ method: 'PATCH', path: '/api/sessions', description: 'Cambia stato sessione (active/paused/ended)' },
96+
{ method: 'GET', path: '/api/events', description: 'SSE stream eventi real-time' },
97+
{ method: 'GET', path: '/api/history', description: 'Conversazioni con filtro agentId' },
98+
{ method: 'POST', path: '/api/history', description: 'Crea conversazione o aggiunge messaggio' },
99+
{ method: 'DELETE', path: '/api/history', description: 'Elimina conversazione per ID' },
100+
{ method: 'GET', path: '/api/activity', description: 'Feed attività team paginato con filtro tipo' },
101+
{ method: 'GET', path: '/api/search', description: 'Ricerca globale ?q= su pagine/agenti/sessioni/task' },
102+
{ method: 'GET', path: '/api/secrets', description: 'Lista secrets con valori mascherati' },
103+
{ method: 'POST', path: '/api/secrets', description: 'Aggiunge nuovo secret cifrato' },
104+
{ method: 'DELETE', path: '/api/secrets', description: 'Elimina secret per ID' },
105+
{ method: 'GET', path: '/api/context', description: 'Stato context engine: budget, sezioni, config' },
106+
{ method: 'GET', path: '/api/preferences', description: 'Preferenze utente' },
107+
{ method: 'PATCH', path: '/api/preferences', description: 'Aggiorna preferenze (tema, lingua, notifiche)' },
108+
{ method: 'GET', path: '/api/onboarding', description: 'Stato tour onboarding' },
109+
{ method: 'POST', path: '/api/onboarding', description: 'Aggiorna step/skip/reset onboarding' },
110+
{ method: 'GET', path: '/api/hooks', description: 'Scopre hook dalla workspace' },
111+
{ method: 'GET', path: '/api/settings', description: 'Configurazione corrente' },
112+
{ method: 'PATCH', path: '/api/settings', description: 'Aggiorna settings' },
113+
{ method: 'POST', path: '/api/settings/_action', description: 'Azioni: export-data, clear-cache, reset-settings' },
114+
]

web/app/docs/page.tsx

Lines changed: 135 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,135 @@
1+
'use client'
2+
3+
import Link from 'next/link'
4+
import { useState } from 'react'
5+
import { SECTIONS, MODULES, CLI_COMMANDS, API_ROUTES } from './data'
6+
7+
const METHOD_COLOR: Record<string, string> = {
8+
GET: 'var(--color-green)', POST: 'var(--color-yellow)',
9+
PATCH: 'var(--color-orange)', DELETE: 'var(--color-red)',
10+
}
11+
12+
function OverviewSection() {
13+
const stats = [
14+
{ v: '40+', l: 'Pagine web' }, { v: '36', l: 'Moduli shared/' },
15+
{ v: '27', l: 'Comandi CLI' }, { v: '24+', l: 'API routes' },
16+
]
17+
const layers = [
18+
{ name: 'Dashboard (Next.js)', desc: '40+ pagine React, API routes, componenti UI' },
19+
{ name: 'CLI (Node.js)', desc: '27 comandi jht, wizard setup, TUI interattiva' },
20+
{ name: 'Agenti (tmux)', desc: '8 agenti specializzati in sessioni JHT-*' },
21+
{ name: 'Shared modules', desc: '36 moduli TypeScript riusabili da CLI e web' },
22+
{ name: 'Dati (~/.jht/)', desc: 'JSON atomici, backup, migrations, secrets' },
23+
]
24+
return (
25+
<div className="flex flex-col gap-6">
26+
<div className="grid grid-cols-2 gap-3 sm:grid-cols-4">
27+
{stats.map(s => (
28+
<div key={s.l} className="p-4 rounded-lg border flex flex-col gap-1" style={{ borderColor: 'var(--color-border)', background: 'var(--color-panel)' }}>
29+
<span className="text-xl font-bold text-[var(--color-green)]">{s.v}</span>
30+
<span className="text-[9px] text-[var(--color-dim)]">{s.l}</span>
31+
</div>
32+
))}
33+
</div>
34+
<div className="border border-[var(--color-border)] rounded-lg overflow-hidden bg-[var(--color-panel)]">
35+
<div className="px-5 py-3 border-b border-[var(--color-border)]">
36+
<span className="text-[10px] font-bold uppercase tracking-widest text-[var(--color-dim)]">Stack</span>
37+
</div>
38+
{layers.map((l, i) => (
39+
<div key={l.name} className={`flex items-start gap-3 px-5 py-3 ${i < layers.length - 1 ? 'border-b border-[var(--color-border)]' : ''}`}>
40+
<span className="text-[11px] font-semibold text-[var(--color-bright)] w-44 flex-shrink-0">{l.name}</span>
41+
<span className="text-[10px] text-[var(--color-dim)]">{l.desc}</span>
42+
</div>
43+
))}
44+
</div>
45+
</div>
46+
)
47+
}
48+
49+
function ModulesSection() {
50+
const groups = [...new Set(MODULES.map(m => m.group))]
51+
return (
52+
<div className="flex flex-col gap-5">
53+
{groups.map(g => (
54+
<div key={g}>
55+
<h3 className="text-[10px] font-bold uppercase tracking-widest text-[var(--color-dim)] mb-2">{g}</h3>
56+
<div className="border border-[var(--color-border)] rounded-lg overflow-hidden bg-[var(--color-panel)]">
57+
{MODULES.filter(m => m.group === g).map((m, i, arr) => (
58+
<div key={m.id} className={`flex items-start gap-3 px-5 py-2.5 ${i < arr.length - 1 ? 'border-b border-[var(--color-border)]' : ''}`}>
59+
<span className="text-[10px] font-mono text-[var(--color-green)] w-28 flex-shrink-0">{m.id}</span>
60+
<span className="text-[10px] text-[var(--color-dim)]">{m.description}</span>
61+
</div>
62+
))}
63+
</div>
64+
</div>
65+
))}
66+
</div>
67+
)
68+
}
69+
70+
function CliSection() {
71+
return (
72+
<div className="border border-[var(--color-border)] rounded-lg overflow-hidden bg-[var(--color-panel)]">
73+
{CLI_COMMANDS.map((c, i) => (
74+
<div key={c.cmd} className={`flex flex-col gap-0.5 px-5 py-2.5 ${i < CLI_COMMANDS.length - 1 ? 'border-b border-[var(--color-border)]' : ''}`}>
75+
<div className="flex items-center gap-3">
76+
<span className="text-[11px] font-mono text-[var(--color-green)] flex-shrink-0">{c.cmd}</span>
77+
<span className="text-[10px] text-[var(--color-dim)]">{c.description}</span>
78+
</div>
79+
{c.example && <span className="text-[9px] font-mono text-[var(--color-border)] pl-0">$ {c.example}</span>}
80+
</div>
81+
))}
82+
</div>
83+
)
84+
}
85+
86+
function ApiSection() {
87+
return (
88+
<div className="border border-[var(--color-border)] rounded-lg overflow-hidden bg-[var(--color-panel)]">
89+
{API_ROUTES.map((r, i) => (
90+
<div key={`${r.method}-${r.path}`} className={`flex items-center gap-3 px-5 py-2.5 ${i < API_ROUTES.length - 1 ? 'border-b border-[var(--color-border)]' : ''}`}>
91+
<span className="text-[9px] font-mono font-bold w-12 flex-shrink-0" style={{ color: METHOD_COLOR[r.method] }}>{r.method}</span>
92+
<span className="text-[10px] font-mono text-[var(--color-muted)] w-48 flex-shrink-0 truncate">{r.path}</span>
93+
<span className="text-[10px] text-[var(--color-dim)]">{r.description}</span>
94+
</div>
95+
))}
96+
</div>
97+
)
98+
}
99+
100+
const CONTENT: Record<string, React.ReactNode> = {
101+
overview: <OverviewSection />,
102+
modules: <ModulesSection />,
103+
cli: <CliSection />,
104+
api: <ApiSection />,
105+
}
106+
107+
export default function DocsPage() {
108+
const [active, setActive] = useState('overview')
109+
110+
return (
111+
<div style={{ animation: 'fade-in 0.35s ease both' }}>
112+
<div className="mb-8 pb-6 border-b border-[var(--color-border)]">
113+
<div className="flex items-center gap-2 mb-1">
114+
<Link href="/dashboard" className="text-[10px] text-[var(--color-dim)] hover:text-[var(--color-muted)] no-underline transition-colors">Dashboard</Link>
115+
<span className="text-[var(--color-border)]">/</span>
116+
<span className="text-[10px] text-[var(--color-muted)]">Docs</span>
117+
</div>
118+
<h1 className="text-2xl font-bold tracking-tight text-[var(--color-white)] mt-3">Documentazione</h1>
119+
<p className="text-[var(--color-muted)] text-[11px] mt-1">Architettura, moduli, CLI e API del Job Hunter Team.</p>
120+
<div className="flex gap-1.5 flex-wrap mt-4">
121+
{SECTIONS.map(s => (
122+
<button key={s.id} onClick={() => setActive(s.id)}
123+
className="px-3 py-1.5 rounded text-[10px] font-semibold cursor-pointer transition-all"
124+
style={{ border: `1px solid ${active === s.id ? 'var(--color-green)' : 'var(--color-border)'}`, color: active === s.id ? 'var(--color-green)' : 'var(--color-dim)', background: active === s.id ? 'rgba(0,232,122,0.08)' : 'transparent' }}>
125+
{s.label}
126+
</button>
127+
))}
128+
</div>
129+
</div>
130+
<div style={{ animation: 'fade-in 0.2s ease both' }} key={active}>
131+
{CONTENT[active]}
132+
</div>
133+
</div>
134+
)
135+
}

0 commit comments

Comments
 (0)