@aion0/forge 0.2.19 → 0.2.20

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.
@@ -8,6 +8,7 @@ import SessionView from './SessionView';
8
8
  import NewTaskModal from './NewTaskModal';
9
9
  import SettingsModal from './SettingsModal';
10
10
  import TunnelToggle from './TunnelToggle';
11
+ import MonitorPanel from './MonitorPanel';
11
12
  import type { Task } from '@/src/types';
12
13
  import type { WebTerminalHandle } from './WebTerminal';
13
14
 
@@ -44,6 +45,7 @@ export default function Dashboard({ user }: { user: any }) {
44
45
  const [activeTaskId, setActiveTaskId] = useState<string | null>(null);
45
46
  const [showNewTask, setShowNewTask] = useState(false);
46
47
  const [showSettings, setShowSettings] = useState(false);
48
+ const [showMonitor, setShowMonitor] = useState(false);
47
49
  const [usage, setUsage] = useState<UsageSummary[]>([]);
48
50
  const [providers, setProviders] = useState<ProviderInfo[]>([]);
49
51
  const [projects, setProjects] = useState<ProjectInfo[]>([]);
@@ -200,6 +202,16 @@ export default function Dashboard({ user }: { user: any }) {
200
202
  >
201
203
  Pipelines
202
204
  </button>
205
+ <button
206
+ onClick={() => setViewMode('sessions')}
207
+ className={`text-[11px] px-2.5 py-0.5 rounded transition-colors ${
208
+ viewMode === 'sessions'
209
+ ? 'bg-[var(--bg-secondary)] text-[var(--text-primary)] shadow-sm'
210
+ : 'text-[var(--text-secondary)] hover:text-[var(--text-primary)]'
211
+ }`}
212
+ >
213
+ Sessions
214
+ </button>
203
215
  <button
204
216
  onClick={() => setViewMode('preview')}
205
217
  className={`text-[11px] px-2.5 py-0.5 rounded transition-colors ${
@@ -238,8 +250,8 @@ export default function Dashboard({ user }: { user: any }) {
238
250
  </span>
239
251
  )}
240
252
  <button
241
- onClick={() => setViewMode('sessions')}
242
- className={`text-xs ${viewMode === 'sessions' ? 'text-[var(--text-primary)]' : 'text-[var(--text-secondary)] hover:text-[var(--text-primary)]'}`}
253
+ onClick={() => setShowMonitor(true)}
254
+ className="text-xs text-[var(--text-secondary)] hover:text-[var(--text-primary)]"
243
255
  >
244
256
  Monitor
245
257
  </button>
@@ -414,6 +426,8 @@ export default function Dashboard({ user }: { user: any }) {
414
426
  />
415
427
  )}
416
428
 
429
+ {showMonitor && <MonitorPanel onClose={() => setShowMonitor(false)} />}
430
+
417
431
  {showSettings && (
418
432
  <SettingsModal onClose={() => { setShowSettings(false); fetchData(); }} />
419
433
  )}
@@ -32,16 +32,6 @@ interface Watcher {
32
32
  createdAt: string;
33
33
  }
34
34
 
35
- interface MonitorData {
36
- processes: {
37
- nextjs: { running: boolean; pid: string };
38
- terminal: { running: boolean; pid: string };
39
- telegram: { running: boolean; pid: string };
40
- tunnel: { running: boolean; pid: string; url: string };
41
- };
42
- sessions: { name: string; created: string; attached: boolean; windows: number }[];
43
- uptime: string;
44
- }
45
35
 
46
36
  export default function SessionView({
47
37
  projectName,
@@ -63,7 +53,6 @@ export default function SessionView({
63
53
  const [watchers, setWatchers] = useState<Watcher[]>([]);
64
54
  const [batchMode, setBatchMode] = useState(false);
65
55
  const [selectedIds, setSelectedIds] = useState<Map<string, Set<string>>>(new Map());
66
- const [monitor, setMonitor] = useState<MonitorData | null>(null);
67
56
  const bottomRef = useRef<HTMLDivElement>(null);
68
57
 
69
58
  // Load cached sessions tree
@@ -91,17 +80,10 @@ export default function SessionView({
91
80
  } catch {}
92
81
  }, []);
93
82
 
94
- const refreshMonitor = useCallback(() => {
95
- fetch('/api/monitor').then(r => r.json()).then(setMonitor).catch(() => {});
96
- }, []);
97
-
98
83
  useEffect(() => {
99
84
  loadTree(true);
100
85
  loadWatchers();
101
- refreshMonitor();
102
- const timer = setInterval(refreshMonitor, 5000);
103
- return () => clearInterval(timer);
104
- }, [loadTree, loadWatchers, refreshMonitor]);
86
+ }, [loadTree, loadWatchers]);
105
87
 
106
88
  // Auto-expand project if only one or if pre-selected
107
89
  useEffect(() => {
@@ -347,46 +329,6 @@ export default function SessionView({
347
329
  </div>
348
330
  )}
349
331
 
350
- {/* Monitor — always visible */}
351
- {monitor && (
352
- <div className="border-b border-[var(--border)] px-2 py-2 space-y-1.5">
353
- <div className="flex items-center justify-between">
354
- <span className="text-[9px] font-semibold text-[var(--text-secondary)] uppercase">Processes</span>
355
- {monitor.uptime && (
356
- <span className="text-[8px] text-[var(--text-secondary)]">up {monitor.uptime}</span>
357
- )}
358
- </div>
359
- {[
360
- { label: 'Next.js', ...monitor.processes.nextjs },
361
- { label: 'Terminal', ...monitor.processes.terminal },
362
- { label: 'Telegram', ...monitor.processes.telegram },
363
- { label: 'Tunnel', ...monitor.processes.tunnel },
364
- ].map(p => (
365
- <div key={p.label} className="flex items-center gap-1.5 text-[10px]">
366
- <span className={p.running ? 'text-green-400' : 'text-gray-500'}>●</span>
367
- <span className="text-[var(--text-primary)]">{p.label}</span>
368
- <span className="text-[var(--text-secondary)] font-mono ml-auto">{p.running ? `pid:${p.pid}` : 'stopped'}</span>
369
- </div>
370
- ))}
371
- {monitor.processes.tunnel.running && monitor.processes.tunnel.url && (
372
- <div className="text-[9px] text-[var(--accent)] truncate pl-4">{monitor.processes.tunnel.url}</div>
373
- )}
374
-
375
- {monitor.sessions.length > 0 && (
376
- <div className="pt-1">
377
- <span className="text-[9px] font-semibold text-[var(--text-secondary)] uppercase">Tmux ({monitor.sessions.length})</span>
378
- {monitor.sessions.map(s => (
379
- <div key={s.name} className="flex items-center gap-1.5 text-[10px] mt-0.5">
380
- <span className={s.attached ? 'text-green-400' : 'text-yellow-500'}>●</span>
381
- <span className="font-mono text-[var(--text-primary)] truncate flex-1">{s.name}</span>
382
- <span className="text-[8px] text-[var(--text-secondary)]">{s.attached ? 'attached' : 'detached'}</span>
383
- </div>
384
- ))}
385
- </div>
386
- )}
387
- </div>
388
- )}
389
-
390
332
  {/* Tree */}
391
333
  <div className="flex-1 overflow-y-auto">
392
334
  {Object.keys(sessionTree).length === 0 && (
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@aion0/forge",
3
- "version": "0.2.19",
3
+ "version": "0.2.20",
4
4
  "description": "Unified AI workflow platform — multi-model task orchestration, persistent sessions, web terminal, remote access",
5
5
  "type": "module",
6
6
  "scripts": {