pyre-cli 10.1.0 → 10.3.0
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/README.md +211 -494
- package/dist/{checkCmd-RKW6QGDR.js → checkCmd-WQAHAUWO.js} +1 -1
- package/dist/{chunk-GHRDW646.js → chunk-23YWCI3O.js} +375 -135
- package/dist/{service-Q74BBILO.js → chunk-KFPTD266.js} +43 -3
- package/dist/{doctor-GYHFTNZQ.js → chunk-KVUMOA6C.js} +7 -6
- package/dist/{chunk-53O2RGSL.js → chunk-QM5L43EK.js} +19 -2
- package/dist/{chunk-6UHZP4QP.js → chunk-XTOOEKLM.js} +24 -12
- package/dist/{collectors-H43PN4PS.js → collectors-JDN5Y7EV.js} +1 -1
- package/dist/{completions-JKYEJNGR.js → completions-ZVTNE52B.js} +15 -11
- package/dist/{config-GYGJXU2Q.js → config-J4YMADEF.js} +3 -1
- package/dist/doctor-LHFW4UJP.js +10 -0
- package/dist/firebaseSync-ON3RZ6KX.js +91 -0
- package/dist/index.js +4245 -736
- package/dist/monitors/platform/windows-ui.ps1 +42 -0
- package/dist/{netUsageCmd-WKBTW2YG.js → netUsageCmd-67IBZZYN.js} +2 -2
- package/dist/{pipeCmd-7REDBLBU.js → pipeCmd-2N4JPKYE.js} +1 -1
- package/dist/{prometheusCmd-PL64BLN5.js → prometheusCmd-LEUM5WCZ.js} +1 -1
- package/dist/serveCmd-L7LVJOZN.js +353 -0
- package/dist/service-7GIX3YNC.js +16 -0
- package/dist/syncCmd-42IRF633.js +246 -0
- package/dist/{topoCmd-DU2HHZNH.js → topoCmd-DZ3YS5IL.js} +1 -1
- package/dist/{watchdogCmd-UF53JPZB.js → watchdogCmd-6GR4UN6B.js} +7 -7
- package/dist/{wizard-TD7BGX6O.js → wizard-JQMQWFAW.js} +1 -1
- package/package.json +4 -3
- package/parity.md +2 -0
- package/src/completions.ts +15 -11
- package/src/easy_features.test.ts +149 -0
- package/src/firebaseSync.ts +157 -0
- package/src/formatters/html_template.ts +3086 -598
- package/src/formatters/render.ts +25 -12
- package/src/index.ts +518 -24
- package/src/live/input.ts +501 -148
- package/src/live/render.ts +163 -18
- package/src/live/state.ts +52 -2
- package/src/live/types.ts +1 -1
- package/src/monitors/collectors.ts +3 -10
- package/src/monitors/platform/windows-ui.ps1 +42 -0
- package/src/monitors/platform/windows.ts +442 -147
- package/src/monitors/types.ts +8 -0
- package/src/serveCmd.ts +17 -2
- package/src/service.ts +49 -0
- package/src/state/config.ts +48 -0
- package/src/syncCmd.ts +159 -11
- package/src/web/dashboard.ts +205 -0
- package/dist/serveCmd-2H5VLF3P.js +0 -153
- package/dist/syncCmd-A2W3QB3S.js +0 -126
package/src/live/render.ts
CHANGED
|
@@ -50,23 +50,26 @@ let _cachedGraphsVersion = -1;
|
|
|
50
50
|
let _cachedGraphsParams = '';
|
|
51
51
|
|
|
52
52
|
function tableCacheParams(): string {
|
|
53
|
-
|
|
54
|
-
|
|
55
|
-
|
|
56
|
-
|
|
57
|
-
|
|
58
|
-
|
|
59
|
-
|
|
60
|
-
|
|
61
|
-
|
|
62
|
-
|
|
63
|
-
|
|
64
|
-
|
|
65
|
-
|
|
66
|
-
|
|
67
|
-
|
|
68
|
-
|
|
69
|
-
|
|
53
|
+
const limit = processRowBudget();
|
|
54
|
+
return [
|
|
55
|
+
state.sortMode,
|
|
56
|
+
state.processFilter || '',
|
|
57
|
+
state.processSelectionIndex,
|
|
58
|
+
state.trackedPid || '',
|
|
59
|
+
state.inspectingProcess ? state.inspectingProcess.pid : '',
|
|
60
|
+
limit,
|
|
61
|
+
state.currentTheme,
|
|
62
|
+
state.activePanel,
|
|
63
|
+
state.treeView ? '1' : '0',
|
|
64
|
+
state.history.version,
|
|
65
|
+
JSON.stringify(state.visiblePanels),
|
|
66
|
+
JSON.stringify(state.panelLayout),
|
|
67
|
+
state.aiModel,
|
|
68
|
+
state.graphZoomLevel,
|
|
69
|
+
JSON.stringify(state.panelHistory.slice(-5)),
|
|
70
|
+
JSON.stringify(state.bookmarks.map(b => b.name)),
|
|
71
|
+
].join('|');
|
|
72
|
+
}
|
|
70
73
|
|
|
71
74
|
function graphsCacheParams(): string {
|
|
72
75
|
return [
|
|
@@ -162,6 +165,121 @@ function renderCustomizerOverlay(scrollOffset: number, maxVisibleItems: number):
|
|
|
162
165
|
return lines.map(l => ` ${l}`).join('\n');
|
|
163
166
|
}
|
|
164
167
|
|
|
168
|
+
function renderQuickRefOverlay(): string {
|
|
169
|
+
const headerLine = chalk.bgGreen.black.bold(' ⚡ PYRE KEYBOARD SHORTCUTS (Press ? or Esc to close) ');
|
|
170
|
+
|
|
171
|
+
const categories: Record<string, [string, string][]> = {
|
|
172
|
+
'Navigation': [
|
|
173
|
+
['1-9, 0', 'Switch to CPU/MEM/GPU/PWR/BAT/THM/NET/CONNS/TASKS/DISK panel'],
|
|
174
|
+
['P', 'Process panel'],
|
|
175
|
+
['C', 'Containers panel'],
|
|
176
|
+
['R', 'P2P panel'],
|
|
177
|
+
['A', 'Anomalies panel'],
|
|
178
|
+
['B', 'Blender renders panel'],
|
|
179
|
+
['←/→ or Tab', 'Cycle panels'],
|
|
180
|
+
['Esc', 'Back to grid / menu'],
|
|
181
|
+
],
|
|
182
|
+
'View Controls': [
|
|
183
|
+
['g', 'Toggle graphs on/off'],
|
|
184
|
+
['b', 'Cycle graph mode: spark ↔ bar'],
|
|
185
|
+
['p', 'Pause / Resume live updates'],
|
|
186
|
+
['d', 'Toggle detailed sensor mode'],
|
|
187
|
+
['t', 'Toggle tree / flat process view'],
|
|
188
|
+
['T', 'Toggle temperature unit: C ↔ F'],
|
|
189
|
+
['c', 'Open UI Customizer'],
|
|
190
|
+
],
|
|
191
|
+
'Process Actions': [
|
|
192
|
+
['/ or f', 'Filter processes (type to search)'],
|
|
193
|
+
['s', 'Cycle sort: cpu → mem → pid → user → command → state → threads → runtime'],
|
|
194
|
+
['k', 'Kill process by PID'],
|
|
195
|
+
['S', 'Send signal to process'],
|
|
196
|
+
['Space', 'Follow / unfollow selected process'],
|
|
197
|
+
['↑/↓', 'Navigate process list'],
|
|
198
|
+
['Enter', 'Inspect selected process'],
|
|
199
|
+
],
|
|
200
|
+
'Data & Export': [
|
|
201
|
+
['e', 'Export current snapshot'],
|
|
202
|
+
['l', 'Start / stop CSV logging'],
|
|
203
|
+
['f', 'Cycle export format: json → csv → tsv → html → md'],
|
|
204
|
+
['+/-', 'Increase / decrease refresh interval'],
|
|
205
|
+
],
|
|
206
|
+
'Graph Controls': [
|
|
207
|
+
['[', 'Zoom in history graph (more resolution)'],
|
|
208
|
+
[']', 'Zoom out history graph (wider window)'],
|
|
209
|
+
],
|
|
210
|
+
'Bookmarks': [
|
|
211
|
+
['Shift+M', 'Save current view as named bookmark'],
|
|
212
|
+
['M', 'Recall next bookmark (cycles through saved)'],
|
|
213
|
+
],
|
|
214
|
+
'Settings & Help': [
|
|
215
|
+
['m', 'Change AI anomaly model'],
|
|
216
|
+
['r', 'Start/stop P2P server'],
|
|
217
|
+
['?', 'Show this quick reference'],
|
|
218
|
+
[':', 'Command palette (type to run any command)'],
|
|
219
|
+
['q', 'Quit pyre'],
|
|
220
|
+
],
|
|
221
|
+
};
|
|
222
|
+
|
|
223
|
+
const lines: string[] = [headerLine, ''];
|
|
224
|
+
|
|
225
|
+
for (const [category, items] of Object.entries(categories)) {
|
|
226
|
+
lines.push(chalk.bold.cyan(` ${category}`));
|
|
227
|
+
for (const [key, desc] of items) {
|
|
228
|
+
lines.push(` ${chalk.hex('#50fa7b').bold(key.padEnd(14))} ${chalk.dim(desc)}`);
|
|
229
|
+
}
|
|
230
|
+
lines.push('');
|
|
231
|
+
}
|
|
232
|
+
|
|
233
|
+
return lines.join('\n');
|
|
234
|
+
}
|
|
235
|
+
|
|
236
|
+
function renderCommandPalette(): string {
|
|
237
|
+
const headerLine = chalk.bgMagenta.black.bold(' COMMAND PALETTE (Type to search · ↑/↓ navigate · Enter run · Esc close) ');
|
|
238
|
+
const cmds = state.paletteFilteredCommands;
|
|
239
|
+
const totalItems = cmds.length;
|
|
240
|
+
const maxVisible = Math.min(12, state.termHeight - 8);
|
|
241
|
+
const start = Math.max(0, state.paletteIndex - Math.floor(maxVisible / 2));
|
|
242
|
+
const end = Math.min(totalItems, start + maxVisible);
|
|
243
|
+
|
|
244
|
+
const lines: string[] = [headerLine, ''];
|
|
245
|
+
|
|
246
|
+
if (cmds.length === 0) {
|
|
247
|
+
lines.push(chalk.dim(' No matching commands found.'));
|
|
248
|
+
} else {
|
|
249
|
+
// Group by category
|
|
250
|
+
const byCategory = new Map<string, typeof cmds>();
|
|
251
|
+
for (const cmd of cmds.slice(start, end)) {
|
|
252
|
+
const cat = cmd.category;
|
|
253
|
+
if (!byCategory.has(cat)) byCategory.set(cat, []);
|
|
254
|
+
byCategory.get(cat)!.push(cmd);
|
|
255
|
+
}
|
|
256
|
+
|
|
257
|
+
let globalIdx = start;
|
|
258
|
+
for (const [cat, catCmds] of byCategory) {
|
|
259
|
+
lines.push(chalk.bold.dim(` ${cat}`));
|
|
260
|
+
for (const cmd of catCmds) {
|
|
261
|
+
const isSelected = globalIdx === state.paletteIndex;
|
|
262
|
+
const prefix = isSelected ? chalk.yellow('▶ ') : ' ';
|
|
263
|
+
const keyHint = chalk.dim(`[${cmd.keys}]`);
|
|
264
|
+
const label = isSelected ? chalk.bold.white(cmd.label) : chalk.dim(cmd.label);
|
|
265
|
+
lines.push(`${prefix}${keyHint} ${label}`);
|
|
266
|
+
globalIdx++;
|
|
267
|
+
}
|
|
268
|
+
lines.push('');
|
|
269
|
+
}
|
|
270
|
+
}
|
|
271
|
+
|
|
272
|
+
const filterLine = chalk.cyan(` Filter: ${state.inputBuffer}${chalk.dim('_')}`);
|
|
273
|
+
lines.push(filterLine);
|
|
274
|
+
|
|
275
|
+
return lines.join('\n');
|
|
276
|
+
}
|
|
277
|
+
|
|
278
|
+
function renderBookmarkSaveOverlay(): string {
|
|
279
|
+
const headerLine = chalk.bgYellow.black.bold(' SAVE BOOKMARK (Type a name and press Enter · Esc to cancel) ');
|
|
280
|
+
return [headerLine, '', chalk.cyan(` Bookmark name: ${state.inputBuffer}${chalk.dim('_')}`)].join('\n');
|
|
281
|
+
}
|
|
282
|
+
|
|
165
283
|
// --- frame diffing -------------------------------------------------------
|
|
166
284
|
// Instead of erasing the whole screen (`\x1b[2J`) and repainting everything
|
|
167
285
|
// on every keypress/tick, we keep the previous frame's lines around and
|
|
@@ -340,6 +458,19 @@ function render() {
|
|
|
340
458
|
|
|
341
459
|
bodyLines.push('');
|
|
342
460
|
bodyLines.push(...renderCustomizerOverlay(scrollOffset, maxVisibleItems).split('\n'));
|
|
461
|
+
} else if (state.inputMode === 'quick-ref') {
|
|
462
|
+
const refLines = renderQuickRefOverlay().split('\n');
|
|
463
|
+
const maxRefLines = Math.min(refLines.length, Math.max(10, targetBodyHeight - 2));
|
|
464
|
+
bodyLines.push('');
|
|
465
|
+
for (let i = 0; i < maxRefLines; i++) {
|
|
466
|
+
bodyLines.push(refLines[i] || '');
|
|
467
|
+
}
|
|
468
|
+
} else if (state.inputMode === 'command-palette') {
|
|
469
|
+
bodyLines.push('');
|
|
470
|
+
bodyLines.push(...renderCommandPalette().split('\n'));
|
|
471
|
+
} else if (state.inputMode === 'bookmark-save') {
|
|
472
|
+
bodyLines.push('');
|
|
473
|
+
bodyLines.push(...renderBookmarkSaveOverlay().split('\n'));
|
|
343
474
|
} else if (state.inputMode === 'filter') {
|
|
344
475
|
bodyLines.push(chalk.cyan(` Filter processes: ${state.inputBuffer}_`));
|
|
345
476
|
} else if (state.inputMode === 'kill') {
|
|
@@ -405,7 +536,21 @@ function footerLine(): string[] {
|
|
|
405
536
|
badges.push(chalk.magenta.bold(`AI:${state.aiModel}`));
|
|
406
537
|
const badgeStr = badges.join(' ') || ' ';
|
|
407
538
|
|
|
408
|
-
|
|
539
|
+
// Power user footer extras
|
|
540
|
+
const powerExtras: string[] = [];
|
|
541
|
+
if (state.bookmarks.length > 0) {
|
|
542
|
+
powerExtras.push(chalk.cyan.bold(`★ ${state.bookmarks.length} bookmarks`));
|
|
543
|
+
}
|
|
544
|
+
if (state.graphZoomLevel > 1) {
|
|
545
|
+
powerExtras.push(chalk.yellow.bold(`🔍 ${state.graphZoomLevel}x zoom`));
|
|
546
|
+
}
|
|
547
|
+
if (state.panelHistory.length > 0) {
|
|
548
|
+
powerExtras.push(chalk.green.bold(`↩ ${state.panelHistory.length} panels in history`));
|
|
549
|
+
}
|
|
550
|
+
|
|
551
|
+
const extraStr = powerExtras.join(' ') || ' ';
|
|
552
|
+
|
|
553
|
+
return [str1, str2, badgeStr + ' ' + extraStr];
|
|
409
554
|
}
|
|
410
555
|
|
|
411
556
|
function sendNotification(title: string, message: string) {
|
package/src/live/state.ts
CHANGED
|
@@ -11,7 +11,7 @@ import { History } from '../history.js';
|
|
|
11
11
|
import type { StatsData } from '../monitors/index.js';
|
|
12
12
|
import type { ExportFormat, InputMode, SortMode, GraphMode } from './types.js';
|
|
13
13
|
import type { ThemeName, VisibleItems } from '../formatters/types.js';
|
|
14
|
-
import { readConfig, type PyreConfig } from '../state/config.js';
|
|
14
|
+
import { readConfig, type PyreConfig, type PyreBookmark } from '../state/config.js';
|
|
15
15
|
|
|
16
16
|
export const SIGNAL_OPTIONS = ['SIGTERM', 'SIGKILL', 'SIGINT', 'SIGHUP', 'SIGSTOP', 'SIGCONT'] as const;
|
|
17
17
|
|
|
@@ -21,6 +21,49 @@ export { type SplashColorScheme, type SplashAnimation };
|
|
|
21
21
|
|
|
22
22
|
export const MENU_OPTIONS = ['Resume Dashboard', 'Settings (Customizer)', 'Readme', 'Credits', 'Quit pyre'] as const;
|
|
23
23
|
|
|
24
|
+
const PALETTE_COMMANDS = [
|
|
25
|
+
{ id: 'cpu', label: 'Switch to CPU panel', keys: '1', category: 'Navigation' },
|
|
26
|
+
{ id: 'mem', label: 'Switch to Memory panel', keys: '2', category: 'Navigation' },
|
|
27
|
+
{ id: 'gpu', label: 'Switch to GPU panel', keys: '3', category: 'Navigation' },
|
|
28
|
+
{ id: 'power', label: 'Switch to Power panel', keys: '4', category: 'Navigation' },
|
|
29
|
+
{ id: 'battery', label: 'Switch to Battery panel', keys: '5', category: 'Navigation' },
|
|
30
|
+
{ id: 'thermal', label: 'Switch to Thermal panel', keys: '6', category: 'Navigation' },
|
|
31
|
+
{ id: 'network', label: 'Switch to Network panel', keys: '7', category: 'Navigation' },
|
|
32
|
+
{ id: 'packets', label: 'Switch to Connections panel', keys: '8', category: 'Navigation' },
|
|
33
|
+
{ id: 'tasks', label: 'Switch to Tasks panel', keys: '9', category: 'Navigation' },
|
|
34
|
+
{ id: 'disk', label: 'Switch to Disk panel', keys: '0', category: 'Navigation' },
|
|
35
|
+
{ id: 'process', label: 'Switch to Process panel', keys: 'P', category: 'Navigation' },
|
|
36
|
+
{ id: 'containers', label: 'Switch to Containers panel', keys: 'C', category: 'Navigation' },
|
|
37
|
+
{ id: 'p2p', label: 'Switch to P2P panel', keys: 'R', category: 'Navigation' },
|
|
38
|
+
{ id: 'anomalies', label: 'Switch to Anomalies panel', keys: 'A', category: 'Navigation' },
|
|
39
|
+
{ id: 'blender', label: 'Switch to Blender panel', keys: 'B', category: 'Navigation' },
|
|
40
|
+
{ id: 'grid', label: 'Switch to Grid dashboard', keys: 'Esc', category: 'Navigation' },
|
|
41
|
+
{ id: 'graph-toggle', label: 'Toggle graphs on/off', keys: 'g', category: 'View' },
|
|
42
|
+
{ id: 'graph-mode', label: 'Cycle graph mode (spark/bar)', keys: 'b', category: 'View' },
|
|
43
|
+
{ id: 'pause', label: 'Pause / Resume dashboard', keys: 'p', category: 'View' },
|
|
44
|
+
{ id: 'detailed', label: 'Toggle detailed sensor mode', keys: 'd', category: 'View' },
|
|
45
|
+
{ id: 'tree', label: 'Toggle tree/flat process view', keys: 't', category: 'View' },
|
|
46
|
+
{ id: 'temp-unit', label: 'Toggle temperature unit (C/F)', keys: 'T', category: 'View' },
|
|
47
|
+
{ id: 'filter', label: 'Filter processes by name', keys: '/', category: 'Process' },
|
|
48
|
+
{ id: 'sort', label: 'Cycle process sort mode', keys: 's', category: 'Process' },
|
|
49
|
+
{ id: 'kill', label: 'Kill a process by PID', keys: 'k', category: 'Process' },
|
|
50
|
+
{ id: 'signal', label: 'Send signal to a process', keys: 'S', category: 'Process' },
|
|
51
|
+
{ id: 'follow', label: 'Follow selected process', keys: 'Space', category: 'Process' },
|
|
52
|
+
{ id: 'inspect', label: 'Inspect selected process', keys: 'Enter', category: 'Process' },
|
|
53
|
+
{ id: 'export', label: 'Export current snapshot', keys: 'e', category: 'Data' },
|
|
54
|
+
{ id: 'log', label: 'Start / stop CSV logging', keys: 'l', category: 'Data' },
|
|
55
|
+
{ id: 'format-cycle', label: 'Cycle export format', keys: 'f', category: 'Data' },
|
|
56
|
+
{ id: 'interval-inc', label: 'Increase refresh interval', keys: '+', category: 'Data' },
|
|
57
|
+
{ id: 'interval-dec', label: 'Decrease refresh interval', keys: '-', category: 'Data' },
|
|
58
|
+
{ id: 'customize', label: 'Open UI customizer', keys: 'c', category: 'Settings' },
|
|
59
|
+
{ id: 'ai-model', label: 'Change AI anomaly model', keys: 'm', category: 'Settings' },
|
|
60
|
+
{ id: 'bookmark-save', label: 'Save current view as bookmark', keys: 'Shift+M', category: 'Bookmarks' },
|
|
61
|
+
{ id: 'bookmark-recall', label: 'Recall next bookmark', keys: 'M', category: 'Bookmarks' },
|
|
62
|
+
{ id: 'zoom-in', label: 'Zoom in history graph', keys: '[', category: 'Graphs' },
|
|
63
|
+
{ id: 'zoom-out', label: 'Zoom out history graph', keys: ']', category: 'Graphs' },
|
|
64
|
+
{ id: 'quick-ref', label: 'Show keyboard shortcuts', keys: '?', category: 'Help' },
|
|
65
|
+
];
|
|
66
|
+
|
|
24
67
|
const config = readConfig();
|
|
25
68
|
|
|
26
69
|
const isDockerEnv = fs.existsSync('/.dockerenv') || fs.existsSync('/run/.containerenv');
|
|
@@ -150,6 +193,13 @@ const state = {
|
|
|
150
193
|
aiModel: config.aiModel || 'expert-rules-v1',
|
|
151
194
|
aiBackend: config.aiBackend || 'builtin',
|
|
152
195
|
modelSelectionIndex: 0,
|
|
196
|
+
// Power user tools state
|
|
197
|
+
bookmarks: [] as PyreBookmark[],
|
|
198
|
+
bookmarkRecallIndex: 0,
|
|
199
|
+
graphZoomLevel: 1,
|
|
200
|
+
panelHistory: [] as string[],
|
|
201
|
+
paletteIndex: 0,
|
|
202
|
+
paletteFilteredCommands: [...PALETTE_COMMANDS],
|
|
153
203
|
};
|
|
154
204
|
|
|
155
205
|
function setStatus(msg: string, ms = 3000) {
|
|
@@ -180,4 +230,4 @@ function getToggleKey(opt: string): keyof VisibleItems | null {
|
|
|
180
230
|
return map[opt] ?? null;
|
|
181
231
|
}
|
|
182
232
|
|
|
183
|
-
export { state, setStatus, getToggleKey };
|
|
233
|
+
export { state, setStatus, getToggleKey, PALETTE_COMMANDS };
|
package/src/live/types.ts
CHANGED
|
@@ -20,7 +20,7 @@ export interface LiveOptions {
|
|
|
20
20
|
|
|
21
21
|
export type ExportFormat = 'json' | 'csv' | 'tsv' | 'html' | 'md';
|
|
22
22
|
|
|
23
|
-
type InputMode = null | 'filter' | 'kill' | 'signal' | 'customizer' | 'p2p' | 'menu' | 'readme' | 'credits' | 'docker-alert' | 'ai-model';
|
|
23
|
+
type InputMode = null | 'filter' | 'kill' | 'signal' | 'customizer' | 'p2p' | 'menu' | 'readme' | 'credits' | 'docker-alert' | 'ai-model' | 'quick-ref' | 'bookmark-save' | 'command-palette';
|
|
24
24
|
|
|
25
25
|
type SortMode = 'cpu' | 'mem' | 'pid' | 'user' | 'command' | 'state' | 'threads' | 'runtime';
|
|
26
26
|
|
|
@@ -19,7 +19,7 @@ import fs from 'node:fs';
|
|
|
19
19
|
import { run } from './run.js';
|
|
20
20
|
import { getSmcMetrics, parseSuffix } from './smc.js';
|
|
21
21
|
import { resolveIp } from './dns_cache.js';
|
|
22
|
-
import type { StatsData, CpuData, MemoryData, ThermalData, BatteryData, PowerData, DiskData, NetworkData, ProcessData, GpuData, PacketData, NetworkProcess, TaskData, ContainerData, NetworkConnection, BlenderRenderData, ProtocolStats, ConnectionStateStats, RemoteHostInfo } from './types.js';
|
|
22
|
+
import type { StatsData, CpuData, MemoryData, ThermalData, BatteryData, PowerData, DiskData, NetworkData, ProcessData, GpuData, PacketData, NetworkProcess, TaskData, ContainerData, NetworkConnection, BlenderRenderData, ProtocolStats, ConnectionStateStats, RemoteHostInfo, DisplayInfo } from './types.js';
|
|
23
23
|
import { collectBlenderRenders } from './blender.js';
|
|
24
24
|
import {
|
|
25
25
|
collectLinuxSystem,
|
|
@@ -1350,15 +1350,8 @@ export async function collectTasks(limit = 12): Promise<TaskData[]> {
|
|
|
1350
1350
|
.filter((t): t is TaskData => t !== null && t.pid > 0);
|
|
1351
1351
|
} catch {
|
|
1352
1352
|
return [];
|
|
1353
|
-
|
|
1354
|
-
|
|
1355
|
-
|
|
1356
|
-
export interface DisplayInfo {
|
|
1357
|
-
name: string;
|
|
1358
|
-
resolution: string;
|
|
1359
|
-
connectionType?: string;
|
|
1360
|
-
isMain?: boolean;
|
|
1361
|
-
}
|
|
1353
|
+
}
|
|
1354
|
+
}
|
|
1362
1355
|
|
|
1363
1356
|
export async function getDisplayInfo(): Promise<DisplayInfo[]> {
|
|
1364
1357
|
if (process.platform === 'linux') return getLinuxDisplayInfo();
|
|
@@ -0,0 +1,42 @@
|
|
|
1
|
+
<#
|
|
2
|
+
.SYNOPSIS
|
|
3
|
+
Launches a native Pyre UI window on Windows using WPF WebBrowser control.
|
|
4
|
+
#>
|
|
5
|
+
param(
|
|
6
|
+
[Parameter(Mandatory=$true)]
|
|
7
|
+
[int]$Port
|
|
8
|
+
)
|
|
9
|
+
|
|
10
|
+
$ErrorActionPreference = 'Stop'
|
|
11
|
+
|
|
12
|
+
Add-Type -AssemblyName System.Windows.Forms
|
|
13
|
+
Add-Type -AssemblyName System.Drawing
|
|
14
|
+
Add-Type -AssemblyName PresentationFramework
|
|
15
|
+
|
|
16
|
+
$regPath = "HKCU:\Software\Microsoft\Internet Explorer\Main\FeatureControl\FEATURE_BROWSER_EMULATION"
|
|
17
|
+
if (-not (Test-Path $regPath)) {
|
|
18
|
+
New-Item -Path $regPath -Force | Out-Null
|
|
19
|
+
}
|
|
20
|
+
$scriptName = [System.IO.Path]::GetFileName($PSCommandPath)
|
|
21
|
+
Set-ItemProperty -Path $regPath -Name $scriptName -Value 11001 -Type DWord -ErrorAction SilentlyContinue
|
|
22
|
+
|
|
23
|
+
$form = New-Object System.Windows.Forms.Form
|
|
24
|
+
$form.Text = "Pyre Live Dashboard"
|
|
25
|
+
$form.Width = 1200
|
|
26
|
+
$form.Height = 800
|
|
27
|
+
$form.StartPosition = "CenterScreen"
|
|
28
|
+
$form.MinimumSize = New-Object System.Drawing.Size(860, 600)
|
|
29
|
+
$form.BackColor = [System.Drawing.Color]::FromArgb(10, 10, 15)
|
|
30
|
+
$form.ForeColor = [System.Drawing.Color]::FromArgb(245, 245, 247)
|
|
31
|
+
|
|
32
|
+
$browser = New-Object System.Windows.Forms.WebBrowser
|
|
33
|
+
$browser.Dock = "Fill"
|
|
34
|
+
$browser.ScriptErrorsSuppressed = $true
|
|
35
|
+
$browser.Navigate("http://localhost:$Port/")
|
|
36
|
+
$form.Controls.Add($browser)
|
|
37
|
+
|
|
38
|
+
$form.Add_Shown({
|
|
39
|
+
$form.Activate()
|
|
40
|
+
})
|
|
41
|
+
|
|
42
|
+
$form.ShowDialog()
|