pyre-cli 10.3.0 → 10.4.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 +41 -0
- package/dist/{alertChannels-TPSQIJ7S.js → alertChannels-MNX4XH6J.js} +1 -0
- package/dist/{anomaliesCmd-25OFKYPK.js → anomaliesCmd-HHTY5LYL.js} +2 -0
- package/dist/benchGitCmd-HIXUC5EK.js +87 -0
- package/dist/{benchmarkCmd-A3ETK6VY.js → benchmarkCmd-B7DLP2VC.js} +2 -0
- package/dist/{blender-FGH3ASEQ.js → blender-6ZX5SPYC.js} +3 -1
- package/dist/{brewHealth-P2GW5Y5C.js → brewHealth-VFW33QB3.js} +1 -0
- package/dist/budgetCmd-TGO3RYLN.js +11 -0
- package/dist/{buildCmd-CDPZ2ZFA.js → buildCmd-E7KUCFYG.js} +3 -1
- package/dist/{checkCmd-WQAHAUWO.js → checkCmd-QLYTP77Y.js} +5 -3
- package/dist/chunk-3RG5ZIWI.js +10 -0
- package/dist/{chunk-VIACN2RU.js → chunk-FYCBGUTW.js} +41 -19
- package/dist/chunk-JH7P6KLN.js +143 -0
- package/dist/{chunk-QM5L43EK.js → chunk-LDJB5V4N.js} +5 -1
- package/dist/chunk-NMGQVRCA.js +111 -0
- package/dist/chunk-OCL7P7N7.js +936 -0
- package/dist/{chunk-23YWCI3O.js → chunk-QEH4LR6P.js} +28 -686
- package/dist/{chunk-KVUMOA6C.js → chunk-RKPGPVTO.js} +77 -4
- package/dist/chunk-UF3XQ3R3.js +3800 -0
- package/dist/{collectors-JDN5Y7EV.js → collectors-V7SCIIDH.js} +5 -3
- package/dist/{completions-ZVTNE52B.js → completions-FTPXDSR2.js} +44 -3
- package/dist/{config-J4YMADEF.js → config-5WW5M63G.js} +2 -1
- package/dist/containersCmd-FSMYOBG2.js +84 -0
- package/dist/{doctor-LHFW4UJP.js → doctor-O4DIAMHK.js} +3 -2
- package/dist/{explainCmd-MF6PIMLW.js → explainCmd-7PBPA7O5.js} +1 -0
- package/dist/{extensions-XJGHG7X3.js → extensions-QQEV7U3D.js} +1 -0
- package/dist/{firebaseSync-ON3RZ6KX.js → firebaseSync-LRN67UTV.js} +2 -0
- package/dist/flightRecorder-GJIAQOXC.js +162 -0
- package/dist/index.js +736 -4125
- package/dist/inspectCmd-5FXJBJTK.js +137 -0
- package/dist/menu-AJFGDLBP.js +1233 -0
- package/dist/monitors/platform/windows-ui.ps1 +31 -29
- package/dist/{netUsageCmd-67IBZZYN.js → netUsageCmd-JP6YKBPF.js} +7 -5
- package/dist/optimizeCmd-WZKLFYZU.js +1110 -0
- package/dist/{pipeCmd-2N4JPKYE.js → pipeCmd-CPK6FVKB.js} +5 -3
- package/dist/playbookCmd-FRROIEXR.js +145 -0
- package/dist/{profileProcCmd-N4H6MCBT.js → profileProcCmd-5Y3733E7.js} +64 -13
- package/dist/{prometheus-5BL5PVLC.js → prometheus-CYNUR3QT.js} +1 -0
- package/dist/{prometheusCmd-LEUM5WCZ.js → prometheusCmd-G2CSEZRQ.js} +5 -3
- package/dist/{replayCmd-Z3PYXY7V.js → replayCmd-ODB5SPOQ.js} +25 -6
- package/dist/{run-HOGQDDTA.js → run-UJQYT2TO.js} +1 -0
- package/dist/{serveCmd-L7LVJOZN.js → serveCmd-KDPWLVQI.js} +5 -3
- package/dist/{service-7GIX3YNC.js → service-LIYYR3UI.js} +1 -0
- package/dist/{smartCmd-ODWKSFNG.js → smartCmd-2BJJ37GV.js} +130 -5
- package/dist/statuslineCmd-EUKYRR2G.js +75 -0
- package/dist/{stressCmd-MFXMFXYX.js → stressCmd-GKHGY26X.js} +2 -0
- package/dist/{syncCmd-42IRF633.js → syncCmd-MIBFKX24.js} +16 -5
- package/dist/topoCmd-RTXQJ6XA.js +189 -0
- package/dist/{updateCheck-52X6LJG5.js → updateCheck-LJHEMG3G.js} +2 -0
- package/dist/{watchdogCmd-6GR4UN6B.js → watchdogCmd-XM6OPTKM.js} +41 -6
- package/dist/{wizard-JQMQWFAW.js → wizard-PRDOJROQ.js} +2 -1
- package/package.json +2 -2
- package/src/benchGitCmd.ts +110 -0
- package/src/budgetCmd.ts +199 -0
- package/src/completions.ts +42 -3
- package/src/containersCmd.ts +106 -0
- package/src/doctor.ts +86 -6
- package/src/easy_features.test.ts +83 -0
- package/src/flightRecorder.ts +214 -0
- package/src/index.ts +181 -8
- package/src/inspectCmd.ts +165 -0
- package/src/live/input.ts +70 -3
- package/src/live/render.ts +1 -1
- package/src/live/state.ts +2 -1
- package/src/menu/commands.ts +754 -0
- package/src/menu/index.ts +358 -0
- package/src/menu/render.ts +272 -0
- package/src/menu/types.ts +63 -0
- package/src/menu.test.ts +110 -0
- package/src/monitors/blender.ts +49 -19
- package/src/monitors/buildTracker.ts +72 -54
- package/src/monitors/platform/windows-ui.ps1 +31 -29
- package/src/monitors/platform/windows.ts +613 -280
- package/src/optimizeCmd.ts +1248 -0
- package/src/platform.test.ts +135 -0
- package/src/playbookCmd.ts +156 -0
- package/src/power_features.test.ts +251 -0
- package/src/profileProcCmd.ts +68 -21
- package/src/replayCmd.ts +15 -6
- package/src/smartCmd.ts +149 -10
- package/src/state/config.ts +13 -0
- package/src/statuslineCmd.ts +87 -0
- package/src/syncCmd.ts +12 -0
- package/src/topoCmd.ts +83 -50
- package/src/watchdogCmd.ts +40 -3
- package/src/xbar.ts +195 -17
- package/dist/chunk-M73HCQD2.js +0 -95
- package/dist/topoCmd-DZ3YS5IL.js +0 -148
|
@@ -15,10 +15,12 @@ import {
|
|
|
15
15
|
collectThermal,
|
|
16
16
|
getDisplayInfo,
|
|
17
17
|
getTimeMachineStatus
|
|
18
|
-
} from "./chunk-
|
|
19
|
-
import "./chunk-
|
|
20
|
-
import "./chunk-
|
|
18
|
+
} from "./chunk-QEH4LR6P.js";
|
|
19
|
+
import "./chunk-NMGQVRCA.js";
|
|
20
|
+
import "./chunk-FYCBGUTW.js";
|
|
21
|
+
import "./chunk-OCL7P7N7.js";
|
|
21
22
|
import "./chunk-MZO5QKUR.js";
|
|
23
|
+
import "./chunk-3RG5ZIWI.js";
|
|
22
24
|
export {
|
|
23
25
|
collectAll,
|
|
24
26
|
collectBattery,
|
|
@@ -1,3 +1,5 @@
|
|
|
1
|
+
import "./chunk-3RG5ZIWI.js";
|
|
2
|
+
|
|
1
3
|
// src/completions.ts
|
|
2
4
|
function generateZshCompletions() {
|
|
3
5
|
return `#compdef pyre
|
|
@@ -5,6 +7,16 @@ function generateZshCompletions() {
|
|
|
5
7
|
_pyre() {
|
|
6
8
|
local -a commands
|
|
7
9
|
commands=(
|
|
10
|
+
'menu:Interactive TUI command center and tools navigator'
|
|
11
|
+
'tui:Alias for menu'
|
|
12
|
+
'launcher:Alias for menu'
|
|
13
|
+
'playbook:Execute sequenced multi-step macro recipes'
|
|
14
|
+
'flight:Forensic flight recorder black box'
|
|
15
|
+
'run:Performance budgeting runner for CI/CD gates'
|
|
16
|
+
'bench-git:Cross-branch git performance differ'
|
|
17
|
+
'statusline:Headless terminal statusline string'
|
|
18
|
+
'inspect:Process deep-dive inspector'
|
|
19
|
+
'containers:Container and micro-VM telemetry'
|
|
8
20
|
'live:Start interactive live monitoring dashboard'
|
|
9
21
|
'info:Display static system overview'
|
|
10
22
|
'doctor:Run system permissions and diagnostic checks'
|
|
@@ -16,6 +28,7 @@ _pyre() {
|
|
|
16
28
|
'ssh:Stream metrics over SSH'
|
|
17
29
|
'bench:Benchmark command while logging system stats'
|
|
18
30
|
'completions:Generate shell completion scripts'
|
|
31
|
+
'optimize:Mac optimizer (quit idle apps, memory, caches, trash, startup, dns)'
|
|
19
32
|
)
|
|
20
33
|
|
|
21
34
|
_arguments -s \\
|
|
@@ -58,8 +71,8 @@ _pyre_completions() {
|
|
|
58
71
|
COMPREPLY=()
|
|
59
72
|
cur="\${COMP_WORDS[COMP_CWORD]}"
|
|
60
73
|
prev="\${COMP_WORDS[COMP_CWORD-1]}"
|
|
61
|
-
commands="live info doctor web ui launch config p2p ssh bench completions"
|
|
62
|
-
opts="--json --html --md --csv --tsv --detailed --theme --interval --once --out --export-dir --log --tree --sort --packets --limit --alert-cpu --alert-temp --temp-unit"
|
|
74
|
+
commands="menu tui launcher playbook flight run bench-git statusline inspect containers live info doctor web ui launch config p2p ssh bench completions optimize"
|
|
75
|
+
opts="--json --html --md --csv --tsv --detailed --theme --interval --once --out --export-dir --log --tree --sort --packets --limit --alert-cpu --alert-temp --temp-unit --idle --keep --yes --force --clean --empty --dry-run --auto-quit -m --menu -i --interactive --budget-cpu --budget-mem --budget-time --markdown --nice --format"
|
|
63
76
|
|
|
64
77
|
case "${prev}" in
|
|
65
78
|
--theme)
|
|
@@ -82,6 +95,22 @@ _pyre_completions() {
|
|
|
82
95
|
COMPREPLY=( $(compgen -W "server connect" -- ${cur}) )
|
|
83
96
|
return 0
|
|
84
97
|
;;
|
|
98
|
+
optimize)
|
|
99
|
+
COMPREPLY=( $(compgen -W "apps track memory caches trash startup dns protect unprotect help" -- ${cur}) )
|
|
100
|
+
return 0
|
|
101
|
+
;;
|
|
102
|
+
playbook)
|
|
103
|
+
COMPREPLY=( $(compgen -W "run list audit clean triage bench" -- ${cur}) )
|
|
104
|
+
return 0
|
|
105
|
+
;;
|
|
106
|
+
flight)
|
|
107
|
+
COMPREPLY=( $(compgen -W "dump status record" -- ${cur}) )
|
|
108
|
+
return 0
|
|
109
|
+
;;
|
|
110
|
+
statusline)
|
|
111
|
+
COMPREPLY=( $(compgen -W "tmux starship json pango plain" -- ${cur}) )
|
|
112
|
+
return 0
|
|
113
|
+
;;
|
|
85
114
|
esac
|
|
86
115
|
|
|
87
116
|
if [[ ${cur} == -* ]] ; then
|
|
@@ -98,6 +127,16 @@ complete -F _pyre_completions pyre
|
|
|
98
127
|
function generateFishCompletions() {
|
|
99
128
|
return `# fish completion for pyre
|
|
100
129
|
|
|
130
|
+
complete -c pyre -n "__fish_use_subcommand" -a menu -d "Interactive TUI command center and tools navigator"
|
|
131
|
+
complete -c pyre -n "__fish_use_subcommand" -a tui -d "Alias for menu"
|
|
132
|
+
complete -c pyre -n "__fish_use_subcommand" -a launcher -d "Alias for menu"
|
|
133
|
+
complete -c pyre -n "__fish_use_subcommand" -a playbook -d "Execute sequenced multi-step macro recipes"
|
|
134
|
+
complete -c pyre -n "__fish_use_subcommand" -a flight -d "Forensic flight recorder black box"
|
|
135
|
+
complete -c pyre -n "__fish_use_subcommand" -a run -d "Performance budgeting runner for CI/CD gates"
|
|
136
|
+
complete -c pyre -n "__fish_use_subcommand" -a bench-git -d "Cross-branch git performance differ"
|
|
137
|
+
complete -c pyre -n "__fish_use_subcommand" -a statusline -d "Headless terminal statusline string"
|
|
138
|
+
complete -c pyre -n "__fish_use_subcommand" -a inspect -d "Process deep-dive inspector"
|
|
139
|
+
complete -c pyre -n "__fish_use_subcommand" -a containers -d "Container and micro-VM telemetry"
|
|
101
140
|
complete -c pyre -n "__fish_use_subcommand" -a live -d "Start interactive live monitoring dashboard"
|
|
102
141
|
complete -c pyre -n "__fish_use_subcommand" -a info -d "Display static system overview"
|
|
103
142
|
complete -c pyre -n "__fish_use_subcommand" -a doctor -d "Run system diagnostics"
|
|
@@ -107,6 +146,8 @@ complete -c pyre -n "__fish_use_subcommand" -a launch -d "Launch Activity Monito
|
|
|
107
146
|
complete -c pyre -n "__fish_use_subcommand" -a config -d "Show or reset configuration options"
|
|
108
147
|
complete -c pyre -n "__fish_use_subcommand" -a p2p -d "P2P streaming mode"
|
|
109
148
|
complete -c pyre -n "__fish_use_subcommand" -a completions -d "Generate shell completions"
|
|
149
|
+
complete -c pyre -n "__fish_use_subcommand" -a optimize -d "Mac optimizer: quit idle apps, clean caches"
|
|
150
|
+
complete -c pyre -n "__fish_seen_subcommand_from optimize" -a "apps track memory caches trash startup dns protect unprotect help"
|
|
110
151
|
|
|
111
152
|
complete -c pyre -l json -s j -d "Output snapshot as JSON"
|
|
112
153
|
complete -c pyre -l html -d "Output snapshot as HTML"
|
|
@@ -123,7 +164,7 @@ function generatePowerShellCompletions() {
|
|
|
123
164
|
return `# PowerShell completion for pyre
|
|
124
165
|
Register-ArgumentCompleter -Native -CommandName pyre -ScriptBlock {
|
|
125
166
|
param($wordToComplete, $commandAst, $cursorPosition)
|
|
126
|
-
$commands = @('live', 'check', 'pipe', 'stress', 'ui', 'launch', 'web', 'ssh', 'fleet', 'bench', 'benchmark', 'anomalies', 'doctor', 'extensions', 'brew', 'update', 'profile', 'config', 'history', 'diff', 'info', 'completions', 'p2p', 'blender', 'prometheus', 'smart', 'replay', 'explain')
|
|
167
|
+
$commands = @('menu', 'tui', 'launcher', 'playbook', 'flight', 'run', 'bench-git', 'statusline', 'inspect', 'containers', 'live', 'check', 'pipe', 'stress', 'ui', 'launch', 'web', 'ssh', 'fleet', 'bench', 'benchmark', 'anomalies', 'doctor', 'extensions', 'brew', 'update', 'profile', 'config', 'history', 'diff', 'info', 'completions', 'p2p', 'blender', 'prometheus', 'smart', 'replay', 'explain', 'optimize')
|
|
127
168
|
$options = @('--json', '--html', '--md', '--csv', '--tsv', '--detailed', '--theme', '--interval', '--once', '--out', '--export-dir', '--log', '--tree', '--sort', '--packets', '--limit', '--alert-cpu', '--alert-temp', '--temp-unit', '--plain', '--help', '--version')
|
|
128
169
|
|
|
129
170
|
$elements = $commandAst.CommandElements
|
|
@@ -0,0 +1,84 @@
|
|
|
1
|
+
import "./chunk-3RG5ZIWI.js";
|
|
2
|
+
|
|
3
|
+
// src/containersCmd.ts
|
|
4
|
+
import { execSync } from "child_process";
|
|
5
|
+
import chalk from "chalk";
|
|
6
|
+
function detectContainerEngine() {
|
|
7
|
+
try {
|
|
8
|
+
execSync("docker --version", { stdio: "ignore" });
|
|
9
|
+
return "docker";
|
|
10
|
+
} catch {
|
|
11
|
+
try {
|
|
12
|
+
execSync("podman --version", { stdio: "ignore" });
|
|
13
|
+
return "podman";
|
|
14
|
+
} catch {
|
|
15
|
+
return null;
|
|
16
|
+
}
|
|
17
|
+
}
|
|
18
|
+
}
|
|
19
|
+
function collectContainerStats() {
|
|
20
|
+
const engine = detectContainerEngine();
|
|
21
|
+
if (!engine) return [];
|
|
22
|
+
try {
|
|
23
|
+
const raw = execSync(`${engine} stats --no-stream --format "{{.ID}} {{.Name}} {{.CPUPerc}} {{.MemUsage}} {{.MemPerc}} {{.NetIO}}" 2>/dev/null`, {
|
|
24
|
+
encoding: "utf-8",
|
|
25
|
+
timeout: 3e3
|
|
26
|
+
});
|
|
27
|
+
const lines = raw.trim().split("\n").filter(Boolean);
|
|
28
|
+
const stats = [];
|
|
29
|
+
for (const l of lines) {
|
|
30
|
+
const parts = l.split(" ");
|
|
31
|
+
if (parts.length >= 6) {
|
|
32
|
+
stats.push({
|
|
33
|
+
id: parts[0]?.trim() || "",
|
|
34
|
+
name: parts[1]?.trim() || "",
|
|
35
|
+
engine,
|
|
36
|
+
cpuPct: parts[2]?.trim() || "0%",
|
|
37
|
+
memUsage: parts[3]?.trim() || "0B",
|
|
38
|
+
memPct: parts[4]?.trim() || "0%",
|
|
39
|
+
netIO: parts[5]?.trim() || "0B/0B"
|
|
40
|
+
});
|
|
41
|
+
}
|
|
42
|
+
}
|
|
43
|
+
return stats;
|
|
44
|
+
} catch {
|
|
45
|
+
return [];
|
|
46
|
+
}
|
|
47
|
+
}
|
|
48
|
+
async function runContainersCommand(opts) {
|
|
49
|
+
const stats = collectContainerStats();
|
|
50
|
+
const engine = detectContainerEngine();
|
|
51
|
+
if (opts?.json) {
|
|
52
|
+
console.log(JSON.stringify({ engine: engine || "none", containers: stats }, null, 2));
|
|
53
|
+
return;
|
|
54
|
+
}
|
|
55
|
+
console.log(chalk.bold("\n \u{1F525} pyre containers \u2014 Container & Micro-VM Telemetry\n"));
|
|
56
|
+
if (!engine) {
|
|
57
|
+
console.log(chalk.yellow(" No container engine (Docker / Podman) detected in PATH."));
|
|
58
|
+
console.log(chalk.dim(" Install Docker or Podman to enable container performance telemetry.\n"));
|
|
59
|
+
return;
|
|
60
|
+
}
|
|
61
|
+
if (stats.length === 0) {
|
|
62
|
+
console.log(chalk.dim(` Engine: ${engine} (Active, 0 running containers detected)
|
|
63
|
+
`));
|
|
64
|
+
return;
|
|
65
|
+
}
|
|
66
|
+
console.log(chalk.dim(` Engine: ${engine} (${stats.length} active containers)
|
|
67
|
+
`));
|
|
68
|
+
console.log(` ${"ID".padEnd(14)} ${"Name".padEnd(24)} ${"CPU %".padEnd(10)} ${"Memory Usage".padEnd(22)} ${"Net I/O"}`);
|
|
69
|
+
console.log(chalk.dim(" \u2500".repeat(40)));
|
|
70
|
+
for (const c of stats) {
|
|
71
|
+
const idCol = chalk.dim(c.id.padEnd(14));
|
|
72
|
+
const nameCol = chalk.bold.cyan(c.name.slice(0, 22).padEnd(24));
|
|
73
|
+
const cpuCol = chalk.yellow(c.cpuPct.padEnd(10));
|
|
74
|
+
const memCol = chalk.magenta(`${c.memUsage} (${c.memPct})`.padEnd(22));
|
|
75
|
+
const netCol = chalk.dim(c.netIO);
|
|
76
|
+
console.log(` ${idCol} ${nameCol} ${cpuCol} ${memCol} ${netCol}`);
|
|
77
|
+
}
|
|
78
|
+
console.log();
|
|
79
|
+
}
|
|
80
|
+
export {
|
|
81
|
+
collectContainerStats,
|
|
82
|
+
detectContainerEngine,
|
|
83
|
+
runContainersCommand
|
|
84
|
+
};
|
|
@@ -1,9 +1,10 @@
|
|
|
1
1
|
import {
|
|
2
2
|
printDoctorReport,
|
|
3
3
|
runDoctor
|
|
4
|
-
} from "./chunk-
|
|
4
|
+
} from "./chunk-RKPGPVTO.js";
|
|
5
5
|
import "./chunk-MZO5QKUR.js";
|
|
6
|
-
import "./chunk-
|
|
6
|
+
import "./chunk-LDJB5V4N.js";
|
|
7
|
+
import "./chunk-3RG5ZIWI.js";
|
|
7
8
|
export {
|
|
8
9
|
printDoctorReport,
|
|
9
10
|
runDoctor
|
|
@@ -0,0 +1,162 @@
|
|
|
1
|
+
import {
|
|
2
|
+
collectAll
|
|
3
|
+
} from "./chunk-QEH4LR6P.js";
|
|
4
|
+
import "./chunk-NMGQVRCA.js";
|
|
5
|
+
import "./chunk-FYCBGUTW.js";
|
|
6
|
+
import "./chunk-OCL7P7N7.js";
|
|
7
|
+
import "./chunk-MZO5QKUR.js";
|
|
8
|
+
import "./chunk-3RG5ZIWI.js";
|
|
9
|
+
|
|
10
|
+
// src/flightRecorder.ts
|
|
11
|
+
import fs from "fs";
|
|
12
|
+
import path from "path";
|
|
13
|
+
import chalk from "chalk";
|
|
14
|
+
var FlightRecorder = class {
|
|
15
|
+
buffer = [];
|
|
16
|
+
maxFrames;
|
|
17
|
+
constructor(maxFrames = 600) {
|
|
18
|
+
this.maxFrames = maxFrames;
|
|
19
|
+
}
|
|
20
|
+
push(frame) {
|
|
21
|
+
if (this.buffer.length >= this.maxFrames) {
|
|
22
|
+
this.buffer.shift();
|
|
23
|
+
}
|
|
24
|
+
this.buffer.push(frame);
|
|
25
|
+
}
|
|
26
|
+
size() {
|
|
27
|
+
return this.buffer.length;
|
|
28
|
+
}
|
|
29
|
+
getFrames() {
|
|
30
|
+
return [...this.buffer];
|
|
31
|
+
}
|
|
32
|
+
clear() {
|
|
33
|
+
this.buffer = [];
|
|
34
|
+
}
|
|
35
|
+
generateReport() {
|
|
36
|
+
const frames = this.getFrames();
|
|
37
|
+
let peakCpu = 0;
|
|
38
|
+
let peakMem = 0;
|
|
39
|
+
let peakTemp = void 0;
|
|
40
|
+
let highestCpuProc = void 0;
|
|
41
|
+
let highestMemProc = void 0;
|
|
42
|
+
for (const f of frames) {
|
|
43
|
+
if (f.cpu.usage > peakCpu) peakCpu = f.cpu.usage;
|
|
44
|
+
if (f.memory.usagePercent > peakMem) peakMem = f.memory.usagePercent;
|
|
45
|
+
if (f.cpu.temp !== void 0) {
|
|
46
|
+
if (peakTemp === void 0 || f.cpu.temp > peakTemp) peakTemp = f.cpu.temp;
|
|
47
|
+
}
|
|
48
|
+
for (const p of f.topProcesses) {
|
|
49
|
+
if (!highestCpuProc || p.cpu > highestCpuProc.cpu) {
|
|
50
|
+
highestCpuProc = { name: p.name, pid: p.pid, cpu: p.cpu };
|
|
51
|
+
}
|
|
52
|
+
if (!highestMemProc || p.mem > highestMemProc.mem) {
|
|
53
|
+
highestMemProc = { name: p.name, pid: p.pid, mem: p.mem };
|
|
54
|
+
}
|
|
55
|
+
}
|
|
56
|
+
}
|
|
57
|
+
const timeSpanSec = frames.length > 1 ? Math.round((new Date(frames[frames.length - 1].timestamp).getTime() - new Date(frames[0].timestamp).getTime()) / 1e3) : 0;
|
|
58
|
+
return {
|
|
59
|
+
generatedAt: (/* @__PURE__ */ new Date()).toISOString(),
|
|
60
|
+
frameCount: frames.length,
|
|
61
|
+
timeSpanSec,
|
|
62
|
+
summary: {
|
|
63
|
+
peakCpuUsage: peakCpu,
|
|
64
|
+
peakMemUsage: peakMem,
|
|
65
|
+
peakTempC: peakTemp,
|
|
66
|
+
highestCpuProcess: highestCpuProc,
|
|
67
|
+
highestMemProcess: highestMemProc
|
|
68
|
+
},
|
|
69
|
+
frames
|
|
70
|
+
};
|
|
71
|
+
}
|
|
72
|
+
dump(outDir) {
|
|
73
|
+
const report = this.generateReport();
|
|
74
|
+
const targetDir = outDir || path.join(process.cwd(), "pyre-exports");
|
|
75
|
+
if (!fs.existsSync(targetDir)) {
|
|
76
|
+
fs.mkdirSync(targetDir, { recursive: true });
|
|
77
|
+
}
|
|
78
|
+
const filename = `pyre-flight-${Date.now()}.json`;
|
|
79
|
+
const fullPath = path.join(targetDir, filename);
|
|
80
|
+
fs.writeFileSync(fullPath, JSON.stringify(report, null, 2), "utf-8");
|
|
81
|
+
return fullPath;
|
|
82
|
+
}
|
|
83
|
+
};
|
|
84
|
+
var globalFlightRecorder = new FlightRecorder(600);
|
|
85
|
+
async function captureCurrentFlightFrame() {
|
|
86
|
+
const data = await collectAll();
|
|
87
|
+
const sortedProcs = [...data.processes || []].sort((a, b) => b.cpu - a.cpu).slice(0, 5);
|
|
88
|
+
return {
|
|
89
|
+
timestamp: (/* @__PURE__ */ new Date()).toISOString(),
|
|
90
|
+
cpu: {
|
|
91
|
+
usage: data.cpu.usage,
|
|
92
|
+
temp: data.cpu.temperature,
|
|
93
|
+
loadAvg: data.cpu.loadAvg || []
|
|
94
|
+
},
|
|
95
|
+
memory: {
|
|
96
|
+
usagePercent: data.memory.usagePercent,
|
|
97
|
+
usedBytes: data.memory.used,
|
|
98
|
+
totalBytes: data.memory.total
|
|
99
|
+
},
|
|
100
|
+
network: {
|
|
101
|
+
rxPackets: data.network.rxPackets,
|
|
102
|
+
txPackets: data.network.txPackets
|
|
103
|
+
},
|
|
104
|
+
topProcesses: sortedProcs.map((p) => ({
|
|
105
|
+
pid: p.pid,
|
|
106
|
+
name: p.command,
|
|
107
|
+
cpu: p.cpu,
|
|
108
|
+
mem: p.mem
|
|
109
|
+
}))
|
|
110
|
+
};
|
|
111
|
+
}
|
|
112
|
+
async function runFlightCommand(subcommand = "dump", opts) {
|
|
113
|
+
if (subcommand === "status") {
|
|
114
|
+
const size = globalFlightRecorder.size();
|
|
115
|
+
console.log(chalk.bold("\n \u{1F525} pyre Flight Recorder Status\n"));
|
|
116
|
+
console.log(` Buffer Frames: ${chalk.green(size)} / 600`);
|
|
117
|
+
console.log(` RAM Footprint: ~${(size * 1.5 / 1024).toFixed(2)} MB`);
|
|
118
|
+
console.log(chalk.dim(" Run `pyre flight dump` to generate a post-mortem forensic file.\n"));
|
|
119
|
+
return;
|
|
120
|
+
}
|
|
121
|
+
if (subcommand === "record") {
|
|
122
|
+
const durationSec = opts?.duration || 10;
|
|
123
|
+
console.log(chalk.bold(`
|
|
124
|
+
\u{1F525} Sampling Flight Recorder for ${durationSec}s...
|
|
125
|
+
`));
|
|
126
|
+
for (let i = 0; i < durationSec; i++) {
|
|
127
|
+
const frame = await captureCurrentFlightFrame();
|
|
128
|
+
globalFlightRecorder.push(frame);
|
|
129
|
+
process.stdout.write(`\r Sampled frame ${i + 1}/${durationSec}...`);
|
|
130
|
+
await new Promise((r) => setTimeout(r, 1e3));
|
|
131
|
+
}
|
|
132
|
+
console.log("\n");
|
|
133
|
+
const file2 = globalFlightRecorder.dump(opts?.out);
|
|
134
|
+
console.log(chalk.green(` \u2714 Flight recording saved to: ${file2}
|
|
135
|
+
`));
|
|
136
|
+
return;
|
|
137
|
+
}
|
|
138
|
+
if (globalFlightRecorder.size() === 0) {
|
|
139
|
+
const frame = await captureCurrentFlightFrame();
|
|
140
|
+
globalFlightRecorder.push(frame);
|
|
141
|
+
}
|
|
142
|
+
const file = globalFlightRecorder.dump(opts?.out);
|
|
143
|
+
const report = globalFlightRecorder.generateReport();
|
|
144
|
+
console.log(chalk.bold("\n \u{1F525} pyre Flight Recorder \u2014 Forensic Dump\n"));
|
|
145
|
+
console.log(chalk.dim(` Output File: ${file}`));
|
|
146
|
+
console.log(` Frames: ${chalk.bold(report.frameCount)}`);
|
|
147
|
+
console.log(` Peak CPU: ${chalk.yellow(report.summary.peakCpuUsage.toFixed(1) + "%")}`);
|
|
148
|
+
console.log(` Peak Memory: ${chalk.magenta(report.summary.peakMemUsage.toFixed(1) + "%")}`);
|
|
149
|
+
if (report.summary.peakTempC !== void 0) {
|
|
150
|
+
console.log(` Peak Temp: ${chalk.red(report.summary.peakTempC.toFixed(1) + "\xB0C")}`);
|
|
151
|
+
}
|
|
152
|
+
if (report.summary.highestCpuProcess) {
|
|
153
|
+
console.log(` Top CPU Proc: ${chalk.cyan(report.summary.highestCpuProcess.name)} (PID: ${report.summary.highestCpuProcess.pid}, ${report.summary.highestCpuProcess.cpu.toFixed(1)}%)`);
|
|
154
|
+
}
|
|
155
|
+
console.log();
|
|
156
|
+
}
|
|
157
|
+
export {
|
|
158
|
+
FlightRecorder,
|
|
159
|
+
captureCurrentFlightFrame,
|
|
160
|
+
globalFlightRecorder,
|
|
161
|
+
runFlightCommand
|
|
162
|
+
};
|