process-watchdog 1.0.0 → 1.2.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/BUILDING.md +64 -0
- package/README.md +115 -0
- package/dashboard/watchdog.html +406 -0
- package/dist/api/routes.d.ts.map +1 -1
- package/dist/api/routes.js +45 -0
- package/dist/api/routes.js.map +1 -1
- package/dist/config.d.ts.map +1 -1
- package/dist/config.js +31 -7
- package/dist/config.js.map +1 -1
- package/dist/index.js +21 -5
- package/dist/index.js.map +1 -1
- package/dist/platform/index.d.ts.map +1 -1
- package/dist/platform/index.js +7 -1
- package/dist/platform/index.js.map +1 -1
- package/dist/platform/linux.d.ts +14 -0
- package/dist/platform/linux.d.ts.map +1 -0
- package/dist/platform/linux.js +235 -0
- package/dist/platform/linux.js.map +1 -0
- package/dist/platform/macos.d.ts +14 -0
- package/dist/platform/macos.d.ts.map +1 -0
- package/dist/platform/macos.js +255 -0
- package/dist/platform/macos.js.map +1 -0
- package/dist/plugins/plugin-loader.d.ts +1 -1
- package/dist/plugins/plugin-loader.d.ts.map +1 -1
- package/dist/plugins/plugin-loader.js +46 -1
- package/dist/plugins/plugin-loader.js.map +1 -1
- package/dist/plugins/process-guard.d.ts.map +1 -1
- package/dist/plugins/process-guard.js +0 -15
- package/dist/plugins/process-guard.js.map +1 -1
- package/dist/tray/index.d.ts +2 -0
- package/dist/tray/index.d.ts.map +1 -0
- package/dist/tray/index.js +73 -0
- package/dist/tray/index.js.map +1 -0
- package/package.json +21 -2
- package/scripts/bundle.js +38 -0
- package/src/api/routes.ts +56 -0
- package/src/config.ts +31 -7
- package/src/index.ts +21 -5
- package/src/platform/index.ts +7 -1
- package/src/platform/linux.ts +255 -0
- package/src/platform/macos.ts +259 -0
- package/src/plugins/plugin-loader.ts +66 -1
- package/src/plugins/process-guard.ts +0 -15
- package/src/tray/index.ts +86 -0
- package/src/tray/tray.ps1 +156 -0
- package/tests/plugins/cpu-monitor.test.ts +5 -5
- package/tests/plugins/disk-health.test.ts +1 -1
- package/tests/plugins/fixtures/broken-plugin.js +5 -0
- package/tests/plugins/fixtures/custom-plugin.js +36 -0
- package/tests/plugins/fixtures/named-plugin.js +31 -0
- package/tests/plugins/plugin-loader.test.ts +124 -7
- package/tests/plugins/process-guard.test.ts +1 -1
|
@@ -0,0 +1,255 @@
|
|
|
1
|
+
import { execFileSync } from 'node:child_process';
|
|
2
|
+
import * as fs from 'node:fs';
|
|
3
|
+
import * as os from 'node:os';
|
|
4
|
+
import * as path from 'node:path';
|
|
5
|
+
function run(cmd, args, timeoutMs = 60000) {
|
|
6
|
+
return execFileSync(cmd, args, { encoding: 'utf-8', timeout: timeoutMs }).trim();
|
|
7
|
+
}
|
|
8
|
+
export class MacOSPlatform {
|
|
9
|
+
async getProcesses() {
|
|
10
|
+
// ps aux columns: USER PID %CPU %MEM VSZ RSS TTY STAT START TIME COMMAND
|
|
11
|
+
const raw = run('ps', ['aux']);
|
|
12
|
+
const lines = raw.split('\n').slice(1); // skip header
|
|
13
|
+
const result = [];
|
|
14
|
+
for (const line of lines) {
|
|
15
|
+
if (!line.trim())
|
|
16
|
+
continue;
|
|
17
|
+
const parts = line.trim().split(/\s+/);
|
|
18
|
+
if (parts.length < 11)
|
|
19
|
+
continue;
|
|
20
|
+
const pid = parseInt(parts[1], 10);
|
|
21
|
+
const cpuPct = parseFloat(parts[2]) || 0;
|
|
22
|
+
const rssKB = parseInt(parts[5], 10) || 0;
|
|
23
|
+
const name = parts.slice(10).join(' ');
|
|
24
|
+
if (isNaN(pid))
|
|
25
|
+
continue;
|
|
26
|
+
result.push({
|
|
27
|
+
pid,
|
|
28
|
+
name,
|
|
29
|
+
memoryMB: Math.round(rssKB / 1024),
|
|
30
|
+
cpu: cpuPct,
|
|
31
|
+
responding: true,
|
|
32
|
+
});
|
|
33
|
+
}
|
|
34
|
+
return result;
|
|
35
|
+
}
|
|
36
|
+
async getProcessesByName(name) {
|
|
37
|
+
// pgrep -fl <name> => "<pid> <full command>"
|
|
38
|
+
let pgrepOutput = '';
|
|
39
|
+
try {
|
|
40
|
+
pgrepOutput = run('pgrep', ['-fl', name]);
|
|
41
|
+
}
|
|
42
|
+
catch {
|
|
43
|
+
// pgrep exits non-zero when no matches — that is fine
|
|
44
|
+
return [];
|
|
45
|
+
}
|
|
46
|
+
const pids = [];
|
|
47
|
+
for (const line of pgrepOutput.split('\n')) {
|
|
48
|
+
if (!line.trim())
|
|
49
|
+
continue;
|
|
50
|
+
const pid = parseInt(line.trim().split(/\s+/)[0], 10);
|
|
51
|
+
if (!isNaN(pid))
|
|
52
|
+
pids.push(pid);
|
|
53
|
+
}
|
|
54
|
+
if (pids.length === 0)
|
|
55
|
+
return [];
|
|
56
|
+
// Pull full info from ps for matched pids
|
|
57
|
+
const allProcs = await this.getProcesses();
|
|
58
|
+
return allProcs.filter((p) => pids.includes(p.pid));
|
|
59
|
+
}
|
|
60
|
+
async getListeningPids() {
|
|
61
|
+
// lsof -i -P -n -sTCP:LISTEN
|
|
62
|
+
// relevant columns: COMMAND PID USER FD TYPE DEVICE SIZE/OFF NODE NAME
|
|
63
|
+
let raw = '';
|
|
64
|
+
try {
|
|
65
|
+
raw = run('lsof', ['-i', '-P', '-n', '-sTCP:LISTEN']);
|
|
66
|
+
}
|
|
67
|
+
catch {
|
|
68
|
+
return [];
|
|
69
|
+
}
|
|
70
|
+
const pids = new Set();
|
|
71
|
+
for (const line of raw.split('\n').slice(1)) {
|
|
72
|
+
if (!line.trim())
|
|
73
|
+
continue;
|
|
74
|
+
const parts = line.trim().split(/\s+/);
|
|
75
|
+
if (parts.length < 2)
|
|
76
|
+
continue;
|
|
77
|
+
const pid = parseInt(parts[1], 10);
|
|
78
|
+
if (!isNaN(pid))
|
|
79
|
+
pids.add(pid);
|
|
80
|
+
}
|
|
81
|
+
return Array.from(pids);
|
|
82
|
+
}
|
|
83
|
+
async killProcess(pid) {
|
|
84
|
+
try {
|
|
85
|
+
run('kill', ['-9', String(pid)]);
|
|
86
|
+
return true;
|
|
87
|
+
}
|
|
88
|
+
catch {
|
|
89
|
+
return false;
|
|
90
|
+
}
|
|
91
|
+
}
|
|
92
|
+
async getMemoryInfo() {
|
|
93
|
+
// Total memory from sysctl
|
|
94
|
+
const sysctlOut = run('sysctl', ['hw.memsize']);
|
|
95
|
+
// "hw.memsize: 17179869184"
|
|
96
|
+
const totalBytes = parseInt(sysctlOut.split(':')[1]?.trim() ?? '0', 10);
|
|
97
|
+
const totalMB = Math.round(totalBytes / (1024 * 1024));
|
|
98
|
+
// Free pages from vm_stat
|
|
99
|
+
// "Pages free: 12345."
|
|
100
|
+
let freeMB = 0;
|
|
101
|
+
try {
|
|
102
|
+
const vmOut = run('vm_stat', []);
|
|
103
|
+
let freePages = 0;
|
|
104
|
+
let inactivePages = 0;
|
|
105
|
+
let pageSize = 4096;
|
|
106
|
+
// Try to get the actual page size from the header line
|
|
107
|
+
// "Mach Virtual Memory Statistics: (page size of 16384 bytes)"
|
|
108
|
+
const pageSizeMatch = vmOut.match(/page size of (\d+) bytes/);
|
|
109
|
+
if (pageSizeMatch)
|
|
110
|
+
pageSize = parseInt(pageSizeMatch[1], 10);
|
|
111
|
+
for (const line of vmOut.split('\n')) {
|
|
112
|
+
const freeMatch = line.match(/^Pages free:\s+([\d]+)/);
|
|
113
|
+
if (freeMatch)
|
|
114
|
+
freePages += parseInt(freeMatch[1], 10);
|
|
115
|
+
const inactiveMatch = line.match(/^Pages inactive:\s+([\d]+)/);
|
|
116
|
+
if (inactiveMatch)
|
|
117
|
+
inactivePages += parseInt(inactiveMatch[1], 10);
|
|
118
|
+
}
|
|
119
|
+
freeMB = Math.round(((freePages + inactivePages) * pageSize) / (1024 * 1024));
|
|
120
|
+
}
|
|
121
|
+
catch {
|
|
122
|
+
// vm_stat failed — leave freeMB as 0
|
|
123
|
+
}
|
|
124
|
+
const usedMB = totalMB - freeMB;
|
|
125
|
+
const usedPct = totalMB > 0 ? Math.round((usedMB / totalMB) * 100) : 0;
|
|
126
|
+
return { totalMB, freeMB, usedPct, pageFileUsageMB: 0 };
|
|
127
|
+
}
|
|
128
|
+
async getDiskInfo() {
|
|
129
|
+
// df -g: block size is gigabytes
|
|
130
|
+
// Filesystem 1G-blocks Used Available Capacity Mounted on
|
|
131
|
+
let raw = '';
|
|
132
|
+
try {
|
|
133
|
+
raw = run('df', ['-g']);
|
|
134
|
+
}
|
|
135
|
+
catch {
|
|
136
|
+
return [];
|
|
137
|
+
}
|
|
138
|
+
const result = [];
|
|
139
|
+
for (const line of raw.split('\n').slice(1)) {
|
|
140
|
+
if (!line.trim())
|
|
141
|
+
continue;
|
|
142
|
+
const parts = line.trim().split(/\s+/);
|
|
143
|
+
if (parts.length < 6)
|
|
144
|
+
continue;
|
|
145
|
+
const totalGB = parseInt(parts[1], 10);
|
|
146
|
+
const usedGB = parseInt(parts[2], 10);
|
|
147
|
+
const freeGB = parseInt(parts[3], 10);
|
|
148
|
+
const drive = parts[0];
|
|
149
|
+
if (isNaN(totalGB) || totalGB <= 0)
|
|
150
|
+
continue;
|
|
151
|
+
const usedPct = Math.round((usedGB / totalGB) * 100);
|
|
152
|
+
result.push({ drive, totalGB, freeGB, usedPct });
|
|
153
|
+
}
|
|
154
|
+
return result;
|
|
155
|
+
}
|
|
156
|
+
async getCpuUsage(samples, intervalMs) {
|
|
157
|
+
const result = [];
|
|
158
|
+
const count = Math.max(1, samples);
|
|
159
|
+
for (let i = 0; i < count; i++) {
|
|
160
|
+
if (i > 0) {
|
|
161
|
+
await new Promise((resolve) => setTimeout(resolve, intervalMs));
|
|
162
|
+
}
|
|
163
|
+
try {
|
|
164
|
+
// top -l <n> -n 0: take <n> samples, show 0 processes
|
|
165
|
+
// "CPU usage: 10.5% user, 5.2% sys, 84.3% idle"
|
|
166
|
+
const topOut = run('top', ['-l', '1', '-n', '0'], 30000);
|
|
167
|
+
let idlePct = 0;
|
|
168
|
+
for (const line of topOut.split('\n')) {
|
|
169
|
+
const idleMatch = line.match(/(\d+\.\d+)%\s+idle/i);
|
|
170
|
+
if (idleMatch) {
|
|
171
|
+
idlePct = parseFloat(idleMatch[1]);
|
|
172
|
+
break;
|
|
173
|
+
}
|
|
174
|
+
}
|
|
175
|
+
result.push({
|
|
176
|
+
usedPct: Math.round(100 - idlePct),
|
|
177
|
+
timestamp: new Date(),
|
|
178
|
+
});
|
|
179
|
+
}
|
|
180
|
+
catch {
|
|
181
|
+
result.push({ usedPct: 0, timestamp: new Date() });
|
|
182
|
+
}
|
|
183
|
+
}
|
|
184
|
+
return result;
|
|
185
|
+
}
|
|
186
|
+
async getStartupItems() {
|
|
187
|
+
const launchAgentsDir = path.join(os.homedir(), 'Library', 'LaunchAgents');
|
|
188
|
+
const items = [];
|
|
189
|
+
let files = [];
|
|
190
|
+
try {
|
|
191
|
+
files = fs.readdirSync(launchAgentsDir).filter((f) => f.endsWith('.plist'));
|
|
192
|
+
}
|
|
193
|
+
catch {
|
|
194
|
+
return items;
|
|
195
|
+
}
|
|
196
|
+
for (const file of files) {
|
|
197
|
+
const fullPath = path.join(launchAgentsDir, file);
|
|
198
|
+
// Extract label/program from plist — use a simple regex approach
|
|
199
|
+
// (avoid heavy dependencies; plist is XML)
|
|
200
|
+
let label = path.basename(file, '.plist');
|
|
201
|
+
let command = fullPath;
|
|
202
|
+
try {
|
|
203
|
+
const content = fs.readFileSync(fullPath, 'utf-8');
|
|
204
|
+
// Extract the Label key value
|
|
205
|
+
const labelMatch = content.match(/<key>Label<\/key>\s*<string>([^<]+)<\/string>/);
|
|
206
|
+
if (labelMatch)
|
|
207
|
+
label = labelMatch[1];
|
|
208
|
+
// Extract Program or ProgramArguments first element
|
|
209
|
+
const progMatch = content.match(/<key>Program<\/key>\s*<string>([^<]+)<\/string>/);
|
|
210
|
+
if (progMatch) {
|
|
211
|
+
command = progMatch[1];
|
|
212
|
+
}
|
|
213
|
+
else {
|
|
214
|
+
const argsMatch = content.match(/<key>ProgramArguments<\/key>\s*<array>\s*<string>([^<]+)<\/string>/);
|
|
215
|
+
if (argsMatch)
|
|
216
|
+
command = argsMatch[1];
|
|
217
|
+
}
|
|
218
|
+
}
|
|
219
|
+
catch {
|
|
220
|
+
// Failed to parse plist content — use filename-based defaults
|
|
221
|
+
}
|
|
222
|
+
items.push({
|
|
223
|
+
name: label,
|
|
224
|
+
command,
|
|
225
|
+
location: fullPath,
|
|
226
|
+
enabled: true,
|
|
227
|
+
});
|
|
228
|
+
}
|
|
229
|
+
return items;
|
|
230
|
+
}
|
|
231
|
+
async disableStartupItem(name) {
|
|
232
|
+
const launchAgentsDir = path.join(os.homedir(), 'Library', 'LaunchAgents');
|
|
233
|
+
// Accept both the label name and the filename (with or without .plist)
|
|
234
|
+
const plistName = name.endsWith('.plist') ? name : `${name}.plist`;
|
|
235
|
+
const plistPath = path.join(launchAgentsDir, plistName);
|
|
236
|
+
try {
|
|
237
|
+
execFileSync('launchctl', ['unload', plistPath], {
|
|
238
|
+
encoding: 'utf-8',
|
|
239
|
+
timeout: 30000,
|
|
240
|
+
});
|
|
241
|
+
return true;
|
|
242
|
+
}
|
|
243
|
+
catch {
|
|
244
|
+
return false;
|
|
245
|
+
}
|
|
246
|
+
}
|
|
247
|
+
getTempDirs() {
|
|
248
|
+
return [
|
|
249
|
+
'/tmp',
|
|
250
|
+
path.join(os.homedir(), 'Library', 'Caches'),
|
|
251
|
+
path.join(os.homedir(), '.npm', '_cacache'),
|
|
252
|
+
];
|
|
253
|
+
}
|
|
254
|
+
}
|
|
255
|
+
//# sourceMappingURL=macos.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"macos.js","sourceRoot":"","sources":["../../src/platform/macos.ts"],"names":[],"mappings":"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"}
|
|
@@ -1,4 +1,4 @@
|
|
|
1
1
|
import { WatchdogPlugin } from './plugin.interface.js';
|
|
2
2
|
import { WatchdogConfig } from '../config.js';
|
|
3
|
-
export declare function loadPlugins(config: WatchdogConfig): WatchdogPlugin[]
|
|
3
|
+
export declare function loadPlugins(config: WatchdogConfig, customPluginDir?: string): Promise<WatchdogPlugin[]>;
|
|
4
4
|
//# sourceMappingURL=plugin-loader.d.ts.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"plugin-loader.d.ts","sourceRoot":"","sources":["../../src/plugins/plugin-loader.ts"],"names":[],"mappings":"
|
|
1
|
+
{"version":3,"file":"plugin-loader.d.ts","sourceRoot":"","sources":["../../src/plugins/plugin-loader.ts"],"names":[],"mappings":"AAKA,OAAO,EAAE,cAAc,EAAE,MAAM,uBAAuB,CAAC;AACvD,OAAO,EAAE,cAAc,EAAE,MAAM,cAAc,CAAC;AAe9C,wBAAsB,WAAW,CAC/B,MAAM,EAAE,cAAc,EACtB,eAAe,CAAC,EAAE,MAAM,GACvB,OAAO,CAAC,cAAc,EAAE,CAAC,CAmE3B"}
|
|
@@ -1,3 +1,7 @@
|
|
|
1
|
+
import { readdirSync } from 'node:fs';
|
|
2
|
+
import { existsSync } from 'node:fs';
|
|
3
|
+
import { join } from 'node:path';
|
|
4
|
+
import os from 'node:os';
|
|
1
5
|
import { ProcessGuardPlugin } from './process-guard.js';
|
|
2
6
|
import { MemoryMonitorPlugin } from './memory-monitor.js';
|
|
3
7
|
import { DiskHealthPlugin } from './disk-health.js';
|
|
@@ -10,8 +14,9 @@ const pluginRegistry = {
|
|
|
10
14
|
'startup-optimizer': StartupOptimizerPlugin,
|
|
11
15
|
'cpu-monitor': CpuMonitorPlugin,
|
|
12
16
|
};
|
|
13
|
-
export function loadPlugins(config) {
|
|
17
|
+
export async function loadPlugins(config, customPluginDir) {
|
|
14
18
|
const plugins = [];
|
|
19
|
+
// Load built-in plugins from the registry
|
|
15
20
|
for (const [name, PluginClass] of Object.entries(pluginRegistry)) {
|
|
16
21
|
const pluginConfig = config.plugins[name];
|
|
17
22
|
if (!pluginConfig || !pluginConfig.enabled)
|
|
@@ -20,6 +25,46 @@ export function loadPlugins(config) {
|
|
|
20
25
|
plugin.configure(pluginConfig);
|
|
21
26
|
plugins.push(plugin);
|
|
22
27
|
}
|
|
28
|
+
// Load custom plugins from ~/.aidev/watchdog-plugins/ (or override for testing)
|
|
29
|
+
const resolvedCustomDir = customPluginDir ?? join(os.homedir(), '.aidev', 'watchdog-plugins');
|
|
30
|
+
if (existsSync(resolvedCustomDir)) {
|
|
31
|
+
let entries;
|
|
32
|
+
try {
|
|
33
|
+
entries = readdirSync(resolvedCustomDir).filter((f) => f.endsWith('.js'));
|
|
34
|
+
}
|
|
35
|
+
catch {
|
|
36
|
+
entries = [];
|
|
37
|
+
}
|
|
38
|
+
for (const filename of entries) {
|
|
39
|
+
const filePath = join(resolvedCustomDir, filename);
|
|
40
|
+
try {
|
|
41
|
+
// Dynamic import to support both `export default` and `export { Plugin }`
|
|
42
|
+
const mod = await import(filePath);
|
|
43
|
+
const PluginClass = mod.default ?? mod.Plugin;
|
|
44
|
+
if (typeof PluginClass !== 'function') {
|
|
45
|
+
console.warn(`[watchdog] Custom plugin "${filename}" has no default or Plugin export — skipping.`);
|
|
46
|
+
continue;
|
|
47
|
+
}
|
|
48
|
+
const plugin = new PluginClass();
|
|
49
|
+
if (typeof plugin.name !== 'string' ||
|
|
50
|
+
typeof plugin.check !== 'function' ||
|
|
51
|
+
typeof plugin.fix !== 'function' ||
|
|
52
|
+
typeof plugin.configure !== 'function') {
|
|
53
|
+
console.warn(`[watchdog] Custom plugin "${filename}" does not implement WatchdogPlugin — skipping.`);
|
|
54
|
+
continue;
|
|
55
|
+
}
|
|
56
|
+
const pluginConfig = config.plugins[plugin.name];
|
|
57
|
+
if (pluginConfig) {
|
|
58
|
+
plugin.configure(pluginConfig);
|
|
59
|
+
}
|
|
60
|
+
plugins.push(plugin);
|
|
61
|
+
console.log(`[watchdog] Loaded custom plugin: ${plugin.name} (${filename})`);
|
|
62
|
+
}
|
|
63
|
+
catch (err) {
|
|
64
|
+
console.error(`[watchdog] Failed to load custom plugin "${filename}": ${err.message}`);
|
|
65
|
+
}
|
|
66
|
+
}
|
|
67
|
+
}
|
|
23
68
|
return plugins;
|
|
24
69
|
}
|
|
25
70
|
//# sourceMappingURL=plugin-loader.js.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"plugin-loader.js","sourceRoot":"","sources":["../../src/plugins/plugin-loader.ts"],"names":[],"mappings":"
|
|
1
|
+
{"version":3,"file":"plugin-loader.js","sourceRoot":"","sources":["../../src/plugins/plugin-loader.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,WAAW,EAAE,MAAM,SAAS,CAAC;AACtC,OAAO,EAAE,UAAU,EAAE,MAAM,SAAS,CAAC;AACrC,OAAO,EAAE,IAAI,EAAE,MAAM,WAAW,CAAC;AACjC,OAAO,EAAE,MAAM,SAAS,CAAC;AAIzB,OAAO,EAAE,kBAAkB,EAAE,MAAM,oBAAoB,CAAC;AACxD,OAAO,EAAE,mBAAmB,EAAE,MAAM,qBAAqB,CAAC;AAC1D,OAAO,EAAE,gBAAgB,EAAE,MAAM,kBAAkB,CAAC;AACpD,OAAO,EAAE,sBAAsB,EAAE,MAAM,wBAAwB,CAAC;AAChE,OAAO,EAAE,gBAAgB,EAAE,MAAM,kBAAkB,CAAC;AAEpD,MAAM,cAAc,GAA6C;IAC/D,eAAe,EAAE,kBAAkB;IACnC,gBAAgB,EAAE,mBAAmB;IACrC,aAAa,EAAE,gBAAgB;IAC/B,mBAAmB,EAAE,sBAAsB;IAC3C,aAAa,EAAE,gBAAgB;CAChC,CAAC;AAEF,MAAM,CAAC,KAAK,UAAU,WAAW,CAC/B,MAAsB,EACtB,eAAwB;IAExB,MAAM,OAAO,GAAqB,EAAE,CAAC;IAErC,0CAA0C;IAC1C,KAAK,MAAM,CAAC,IAAI,EAAE,WAAW,CAAC,IAAI,MAAM,CAAC,OAAO,CAAC,cAAc,CAAC,EAAE,CAAC;QACjE,MAAM,YAAY,GAAG,MAAM,CAAC,OAAO,CAAC,IAAI,CAAC,CAAC;QAC1C,IAAI,CAAC,YAAY,IAAI,CAAC,YAAY,CAAC,OAAO;YAAE,SAAS;QACrD,MAAM,MAAM,GAAG,IAAI,WAAW,EAAE,CAAC;QACjC,MAAM,CAAC,SAAS,CAAC,YAAY,CAAC,CAAC;QAC/B,OAAO,CAAC,IAAI,CAAC,MAAM,CAAC,CAAC;IACvB,CAAC;IAED,gFAAgF;IAChF,MAAM,iBAAiB,GACrB,eAAe,IAAI,IAAI,CAAC,EAAE,CAAC,OAAO,EAAE,EAAE,QAAQ,EAAE,kBAAkB,CAAC,CAAC;IACtE,IAAI,UAAU,CAAC,iBAAiB,CAAC,EAAE,CAAC;QAClC,IAAI,OAAiB,CAAC;QACtB,IAAI,CAAC;YACH,OAAO,GAAG,WAAW,CAAC,iBAAiB,CAAC,CAAC,MAAM,CAAC,CAAC,CAAC,EAAE,EAAE,CAAC,CAAC,CAAC,QAAQ,CAAC,KAAK,CAAC,CAAC,CAAC;QAC5E,CAAC;QAAC,MAAM,CAAC;YACP,OAAO,GAAG,EAAE,CAAC;QACf,CAAC;QAED,KAAK,MAAM,QAAQ,IAAI,OAAO,EAAE,CAAC;YAC/B,MAAM,QAAQ,GAAG,IAAI,CAAC,iBAAiB,EAAE,QAAQ,CAAC,CAAC;YACnD,IAAI,CAAC;gBACH,0EAA0E;gBAC1E,MAAM,GAAG,GAAG,MAAM,MAAM,CAAC,QAAQ,CAAC,CAAC;gBACnC,MAAM,WAAW,GAA6B,GAAG,CAAC,OAAO,IAAI,GAAG,CAAC,MAAM,CAAC;gBAExE,IAAI,OAAO,WAAW,KAAK,UAAU,EAAE,CAAC;oBACtC,OAAO,CAAC,IAAI,CACV,6BAA6B,QAAQ,+CAA+C,CACrF,CAAC;oBACF,SAAS;gBACX,CAAC;gBAED,MAAM,MAAM,GAAG,IAAI,WAAW,EAAE,CAAC;gBAEjC,IACE,OAAO,MAAM,CAAC,IAAI,KAAK,QAAQ;oBAC/B,OAAO,MAAM,CAAC,KAAK,KAAK,UAAU;oBAClC,OAAO,MAAM,CAAC,GAAG,KAAK,UAAU;oBAChC,OAAO,MAAM,CAAC,SAAS,KAAK,UAAU,EACtC,CAAC;oBACD,OAAO,CAAC,IAAI,CACV,6BAA6B,QAAQ,iDAAiD,CACvF,CAAC;oBACF,SAAS;gBACX,CAAC;gBAED,MAAM,YAAY,GAAG,MAAM,CAAC,OAAO,CAAC,MAAM,CAAC,IAAI,CAAC,CAAC;gBACjD,IAAI,YAAY,EAAE,CAAC;oBACjB,MAAM,CAAC,SAAS,CAAC,YAAY,CAAC,CAAC;gBACjC,CAAC;gBAED,OAAO,CAAC,IAAI,CAAC,MAAM,CAAC,CAAC;gBACrB,OAAO,CAAC,GAAG,CAAC,oCAAoC,MAAM,CAAC,IAAI,KAAK,QAAQ,GAAG,CAAC,CAAC;YAC/E,CAAC;YAAC,OAAO,GAAG,EAAE,CAAC;gBACb,OAAO,CAAC,KAAK,CACX,4CAA4C,QAAQ,MAAO,GAAa,CAAC,OAAO,EAAE,CACnF,CAAC;YACJ,CAAC;QACH,CAAC;IACH,CAAC;IAED,OAAO,OAAO,CAAC;AACjB,CAAC"}
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"process-guard.d.ts","sourceRoot":"","sources":["../../src/plugins/process-guard.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,cAAc,EAAE,WAAW,EAAE,SAAS,EAAE,YAAY,EAAE,MAAM,uBAAuB,CAAC;AAe7F,qBAAa,kBAAmB,YAAW,cAAc;IACvD,IAAI,SAAmB;IACvB,WAAW,SAA+D;IAC1E,eAAe,SAAU;IACzB,OAAO,CAAC,MAAM,CAKZ;IAEF,SAAS,CAAC,IAAI,EAAE,YAAY,GAAG,IAAI;IAI7B,KAAK,IAAI,OAAO,CAAC,WAAW,CAAC;IAwD7B,GAAG,IAAI,OAAO,CAAC,SAAS,CAAC;
|
|
1
|
+
{"version":3,"file":"process-guard.d.ts","sourceRoot":"","sources":["../../src/plugins/process-guard.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,cAAc,EAAE,WAAW,EAAE,SAAS,EAAE,YAAY,EAAE,MAAM,uBAAuB,CAAC;AAe7F,qBAAa,kBAAmB,YAAW,cAAc;IACvD,IAAI,SAAmB;IACvB,WAAW,SAA+D;IAC1E,eAAe,SAAU;IACzB,OAAO,CAAC,MAAM,CAKZ;IAEF,SAAS,CAAC,IAAI,EAAE,YAAY,GAAG,IAAI;IAI7B,KAAK,IAAI,OAAO,CAAC,WAAW,CAAC;IAwD7B,GAAG,IAAI,OAAO,CAAC,SAAS,CAAC;CA+DhC"}
|
|
@@ -103,21 +103,6 @@ export class ProcessGuardPlugin {
|
|
|
103
103
|
actionsKept.push(`Killed ${killed}/${orphans.length} orphaned ${name} processes`);
|
|
104
104
|
}
|
|
105
105
|
}
|
|
106
|
-
// Best-effort: clean up low-CPU conhost processes (skip any that were running at snapshot time)
|
|
107
|
-
try {
|
|
108
|
-
const conhosts = await safeGetProcessesByName(platform, 'conhost');
|
|
109
|
-
for (const proc of conhosts) {
|
|
110
|
-
if (proc.cpu < 0.1 && !protectedPids.has(proc.pid)) {
|
|
111
|
-
const success = await platform.killProcess(proc.pid);
|
|
112
|
-
if (success) {
|
|
113
|
-
totalMemoryFreedMB += proc.memoryMB ?? 0;
|
|
114
|
-
}
|
|
115
|
-
}
|
|
116
|
-
}
|
|
117
|
-
}
|
|
118
|
-
catch {
|
|
119
|
-
// best-effort, ignore errors
|
|
120
|
-
}
|
|
121
106
|
// Capture after metrics (best-effort — system may be in transition after kills)
|
|
122
107
|
let afterListeningPids;
|
|
123
108
|
try {
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"process-guard.js","sourceRoot":"","sources":["../../src/plugins/process-guard.ts"],"names":[],"mappings":"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
|
|
1
|
+
{"version":3,"file":"process-guard.js","sourceRoot":"","sources":["../../src/plugins/process-guard.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../src/tray/index.ts"],"names":[],"mappings":"AAyDA,wBAAgB,SAAS,IAAI,IAAI,CA4BhC"}
|
|
@@ -0,0 +1,73 @@
|
|
|
1
|
+
import { writeFileSync, readFileSync } from 'node:fs';
|
|
2
|
+
import { join, dirname } from 'node:path';
|
|
3
|
+
import { fileURLToPath } from 'node:url';
|
|
4
|
+
import { spawn } from 'node:child_process';
|
|
5
|
+
import { tmpdir } from 'node:os';
|
|
6
|
+
// ---------------------------------------------------------------------------
|
|
7
|
+
// Resolve paths
|
|
8
|
+
// ---------------------------------------------------------------------------
|
|
9
|
+
// __dirname equivalent for ESM
|
|
10
|
+
const __filename = fileURLToPath(import.meta.url);
|
|
11
|
+
const __dirname = dirname(__filename);
|
|
12
|
+
/**
|
|
13
|
+
* Locate the compiled dist/ folder.
|
|
14
|
+
*
|
|
15
|
+
* When running from source via `tsx`: __dirname = …/src/tray → go up 2 levels
|
|
16
|
+
* When running from compiled dist/: __dirname = …/dist/tray → go up 2 levels
|
|
17
|
+
* Both cases land at the project root; dist/ is always at <root>/dist.
|
|
18
|
+
*/
|
|
19
|
+
function resolveDistDir() {
|
|
20
|
+
// Walk up two directories from src/tray or dist/tray to reach the project root
|
|
21
|
+
const projectRoot = join(__dirname, '..', '..');
|
|
22
|
+
return join(projectRoot, 'dist');
|
|
23
|
+
}
|
|
24
|
+
// ---------------------------------------------------------------------------
|
|
25
|
+
// Embed the .ps1 source relative to THIS file (works for both tsx and compiled)
|
|
26
|
+
// ---------------------------------------------------------------------------
|
|
27
|
+
/**
|
|
28
|
+
* Return the PowerShell script text.
|
|
29
|
+
* We read it from the source tree at `../../src/tray/tray.ps1` (relative to
|
|
30
|
+
* this compiled file at dist/tray/index.js) or from the same directory when
|
|
31
|
+
* running under tsx.
|
|
32
|
+
*/
|
|
33
|
+
function readTrayScript() {
|
|
34
|
+
// Try same directory first (tsx run — __dirname is src/tray)
|
|
35
|
+
const candidates = [
|
|
36
|
+
join(__dirname, 'tray.ps1'),
|
|
37
|
+
join(__dirname, '..', '..', 'src', 'tray', 'tray.ps1'),
|
|
38
|
+
];
|
|
39
|
+
for (const p of candidates) {
|
|
40
|
+
try {
|
|
41
|
+
return readFileSync(p, 'utf-8');
|
|
42
|
+
}
|
|
43
|
+
catch {
|
|
44
|
+
// try next
|
|
45
|
+
}
|
|
46
|
+
}
|
|
47
|
+
throw new Error('tray.ps1 not found. Build the project first or check src/tray/tray.ps1 exists.');
|
|
48
|
+
}
|
|
49
|
+
// ---------------------------------------------------------------------------
|
|
50
|
+
// Public API
|
|
51
|
+
// ---------------------------------------------------------------------------
|
|
52
|
+
export function startTray() {
|
|
53
|
+
const distDir = resolveDistDir();
|
|
54
|
+
const scriptText = readTrayScript();
|
|
55
|
+
const scriptPath = join(tmpdir(), 'watchdog-tray.ps1');
|
|
56
|
+
// Write the PS1 to a temp file so PowerShell can -File it
|
|
57
|
+
writeFileSync(scriptPath, scriptText, 'utf-8');
|
|
58
|
+
const child = spawn('powershell.exe', [
|
|
59
|
+
'-NoProfile',
|
|
60
|
+
'-ExecutionPolicy', 'Bypass',
|
|
61
|
+
'-File', scriptPath,
|
|
62
|
+
'-distDir', distDir,
|
|
63
|
+
], {
|
|
64
|
+
detached: true,
|
|
65
|
+
stdio: 'ignore',
|
|
66
|
+
windowStyle: 'hidden',
|
|
67
|
+
});
|
|
68
|
+
child.unref();
|
|
69
|
+
console.log(`[watchdog] System tray started (PID: ${child.pid})`);
|
|
70
|
+
console.log(`[watchdog] Monitoring dist at: ${distDir}`);
|
|
71
|
+
console.log('[watchdog] Right-click the tray icon to access the menu.');
|
|
72
|
+
}
|
|
73
|
+
//# sourceMappingURL=index.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"index.js","sourceRoot":"","sources":["../../src/tray/index.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,aAAa,EAAE,YAAY,EAAE,MAAM,SAAS,CAAC;AACtD,OAAO,EAAE,IAAI,EAAE,OAAO,EAAE,MAAM,WAAW,CAAC;AAC1C,OAAO,EAAE,aAAa,EAAE,MAAM,UAAU,CAAC;AACzC,OAAO,EAAE,KAAK,EAAE,MAAM,oBAAoB,CAAC;AAC3C,OAAO,EAAE,MAAM,EAAE,MAAM,SAAS,CAAC;AAEjC,8EAA8E;AAC9E,gBAAgB;AAChB,8EAA8E;AAE9E,+BAA+B;AAC/B,MAAM,UAAU,GAAG,aAAa,CAAC,MAAM,CAAC,IAAI,CAAC,GAAG,CAAC,CAAC;AAClD,MAAM,SAAS,GAAI,OAAO,CAAC,UAAU,CAAC,CAAC;AAEvC;;;;;;GAMG;AACH,SAAS,cAAc;IACrB,+EAA+E;IAC/E,MAAM,WAAW,GAAG,IAAI,CAAC,SAAS,EAAE,IAAI,EAAE,IAAI,CAAC,CAAC;IAChD,OAAO,IAAI,CAAC,WAAW,EAAE,MAAM,CAAC,CAAC;AACnC,CAAC;AAED,8EAA8E;AAC9E,gFAAgF;AAChF,8EAA8E;AAE9E;;;;;GAKG;AACH,SAAS,cAAc;IACrB,6DAA6D;IAC7D,MAAM,UAAU,GAAG;QACjB,IAAI,CAAC,SAAS,EAAE,UAAU,CAAC;QAC3B,IAAI,CAAC,SAAS,EAAE,IAAI,EAAE,IAAI,EAAE,KAAK,EAAE,MAAM,EAAE,UAAU,CAAC;KACvD,CAAC;IACF,KAAK,MAAM,CAAC,IAAI,UAAU,EAAE,CAAC;QAC3B,IAAI,CAAC;YACH,OAAO,YAAY,CAAC,CAAC,EAAE,OAAO,CAAC,CAAC;QAClC,CAAC;QAAC,MAAM,CAAC;YACP,WAAW;QACb,CAAC;IACH,CAAC;IACD,MAAM,IAAI,KAAK,CAAC,gFAAgF,CAAC,CAAC;AACpG,CAAC;AAED,8EAA8E;AAC9E,aAAa;AACb,8EAA8E;AAE9E,MAAM,UAAU,SAAS;IACvB,MAAM,OAAO,GAAM,cAAc,EAAE,CAAC;IACpC,MAAM,UAAU,GAAG,cAAc,EAAE,CAAC;IACpC,MAAM,UAAU,GAAG,IAAI,CAAC,MAAM,EAAE,EAAE,mBAAmB,CAAC,CAAC;IAEvD,0DAA0D;IAC1D,aAAa,CAAC,UAAU,EAAE,UAAU,EAAE,OAAO,CAAC,CAAC;IAE/C,MAAM,KAAK,GAAG,KAAK,CACjB,gBAAgB,EAChB;QACE,YAAY;QACZ,kBAAkB,EAAE,QAAQ;QAC5B,OAAO,EAAE,UAAU;QACnB,UAAU,EAAE,OAAO;KACpB,EACD;QACE,QAAQ,EAAE,IAAI;QACd,KAAK,EAAK,QAAQ;QAClB,WAAW,EAAE,QAAQ;KACS,CACjC,CAAC;IAEF,KAAK,CAAC,KAAK,EAAE,CAAC;IAEd,OAAO,CAAC,GAAG,CAAC,wCAAwC,KAAK,CAAC,GAAG,GAAG,CAAC,CAAC;IAClE,OAAO,CAAC,GAAG,CAAC,kCAAkC,OAAO,EAAE,CAAC,CAAC;IACzD,OAAO,CAAC,GAAG,CAAC,0DAA0D,CAAC,CAAC;AAC1E,CAAC"}
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "process-watchdog",
|
|
3
|
-
"version": "1.
|
|
3
|
+
"version": "1.2.0",
|
|
4
4
|
"description": "Modular PC health agent for the aidev.com.au ecosystem",
|
|
5
5
|
"type": "module",
|
|
6
6
|
"bin": {
|
|
@@ -10,7 +10,24 @@
|
|
|
10
10
|
"build": "tsc",
|
|
11
11
|
"dev": "tsx src/index.ts",
|
|
12
12
|
"test": "vitest run",
|
|
13
|
-
"test:watch": "vitest"
|
|
13
|
+
"test:watch": "vitest",
|
|
14
|
+
"bundle": "node scripts/bundle.js",
|
|
15
|
+
"build:standalone": "npm run build && npm run bundle && pkg bundle/watchdog.cjs --out-path standalone",
|
|
16
|
+
"build:standalone:win": "npm run build && npm run bundle && pkg bundle/watchdog.cjs --target node20-win-x64 --output standalone/watchdog-win.exe",
|
|
17
|
+
"build:standalone:mac": "npm run build && npm run bundle && pkg bundle/watchdog.cjs --target node20-macos-x64 --output standalone/watchdog-macos",
|
|
18
|
+
"build:standalone:linux": "npm run build && npm run bundle && pkg bundle/watchdog.cjs --target node20-linux-x64 --output standalone/watchdog-linux"
|
|
19
|
+
},
|
|
20
|
+
"pkg": {
|
|
21
|
+
"assets": [
|
|
22
|
+
"config/**/*",
|
|
23
|
+
"node_modules/better-sqlite3/build/Release/better_sqlite3.node"
|
|
24
|
+
],
|
|
25
|
+
"targets": [
|
|
26
|
+
"node20-win-x64",
|
|
27
|
+
"node20-macos-x64",
|
|
28
|
+
"node20-linux-x64"
|
|
29
|
+
],
|
|
30
|
+
"outputPath": "standalone"
|
|
14
31
|
},
|
|
15
32
|
"keywords": [],
|
|
16
33
|
"author": "",
|
|
@@ -27,6 +44,8 @@
|
|
|
27
44
|
"@types/node": "^25.6.0",
|
|
28
45
|
"@types/node-windows": "^0.1.6",
|
|
29
46
|
"@types/supertest": "^7.2.0",
|
|
47
|
+
"@yao-pkg/pkg": "^6.14.2",
|
|
48
|
+
"esbuild": "^0.28.0",
|
|
30
49
|
"supertest": "^7.2.2",
|
|
31
50
|
"tsx": "^4.21.0",
|
|
32
51
|
"typescript": "^6.0.2",
|
|
@@ -0,0 +1,38 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* esbuild bundler for standalone packaging with pkg.
|
|
3
|
+
*
|
|
4
|
+
* better-sqlite3 uses native .node bindings that cannot be bundled by esbuild
|
|
5
|
+
* or pkg directly. We mark it as external so esbuild leaves the require() call
|
|
6
|
+
* intact. pkg then picks up the .node file via the "assets" field in package.json
|
|
7
|
+
* and patches the path at runtime.
|
|
8
|
+
*
|
|
9
|
+
* node-windows is also native/platform-specific — mark as external too.
|
|
10
|
+
*/
|
|
11
|
+
|
|
12
|
+
import { build } from "esbuild";
|
|
13
|
+
import { mkdirSync } from "fs";
|
|
14
|
+
|
|
15
|
+
mkdirSync("bundle", { recursive: true });
|
|
16
|
+
|
|
17
|
+
await build({
|
|
18
|
+
entryPoints: ["dist/index.js"],
|
|
19
|
+
bundle: true,
|
|
20
|
+
platform: "node",
|
|
21
|
+
target: "node20",
|
|
22
|
+
format: "cjs",
|
|
23
|
+
outfile: "bundle/watchdog.cjs",
|
|
24
|
+
// Native addons must be left as external — they're handled as pkg assets
|
|
25
|
+
external: ["better-sqlite3", "node-windows"],
|
|
26
|
+
// Suppress warnings about dynamic require() in dependencies
|
|
27
|
+
logLevel: "warning",
|
|
28
|
+
// Allow bundling packages that use CommonJS require()
|
|
29
|
+
mainFields: ["main"],
|
|
30
|
+
conditions: ["require", "node"],
|
|
31
|
+
// Drop import.meta references — config.ts has a fallback for CJS contexts
|
|
32
|
+
define: {
|
|
33
|
+
"import.meta.url": "undefined",
|
|
34
|
+
"import.meta.dirname": "__dirname",
|
|
35
|
+
},
|
|
36
|
+
});
|
|
37
|
+
|
|
38
|
+
console.log("Bundle written to bundle/watchdog.cjs");
|
package/src/api/routes.ts
CHANGED
|
@@ -1,4 +1,7 @@
|
|
|
1
1
|
import { Router } from 'express';
|
|
2
|
+
import { writeFile, mkdir } from 'fs/promises';
|
|
3
|
+
import { join } from 'path';
|
|
4
|
+
import os from 'os';
|
|
2
5
|
import { HistoryStore } from '../store/history.js';
|
|
3
6
|
import { WatchdogPlugin, HealthStatus } from '../plugins/plugin.interface.js';
|
|
4
7
|
import { WatchdogConfig } from '../config.js';
|
|
@@ -119,5 +122,58 @@ export function createRoutes(
|
|
|
119
122
|
res.json(config);
|
|
120
123
|
});
|
|
121
124
|
|
|
125
|
+
// PUT /config — deep-merge partial config and persist to ~/.aidev/watchdog.json
|
|
126
|
+
router.put('/config', async (req, res) => {
|
|
127
|
+
const body = req.body;
|
|
128
|
+
if (!body || typeof body !== 'object' || Array.isArray(body)) {
|
|
129
|
+
res.status(400).json({ error: 'Request body must be a JSON object' });
|
|
130
|
+
return;
|
|
131
|
+
}
|
|
132
|
+
|
|
133
|
+
try {
|
|
134
|
+
// Deep-merge the incoming partial config into the live config object
|
|
135
|
+
function isPlainObject(v: unknown): v is Record<string, unknown> {
|
|
136
|
+
return typeof v === 'object' && v !== null && !Array.isArray(v);
|
|
137
|
+
}
|
|
138
|
+
|
|
139
|
+
function deepMerge(
|
|
140
|
+
target: Record<string, unknown>,
|
|
141
|
+
source: Record<string, unknown>,
|
|
142
|
+
): Record<string, unknown> {
|
|
143
|
+
const result: Record<string, unknown> = { ...target };
|
|
144
|
+
for (const key of Object.keys(source)) {
|
|
145
|
+
const src = source[key];
|
|
146
|
+
const tgt = result[key];
|
|
147
|
+
if (isPlainObject(src) && isPlainObject(tgt)) {
|
|
148
|
+
result[key] = deepMerge(tgt, src);
|
|
149
|
+
} else {
|
|
150
|
+
result[key] = src;
|
|
151
|
+
}
|
|
152
|
+
}
|
|
153
|
+
return result;
|
|
154
|
+
}
|
|
155
|
+
|
|
156
|
+
const merged = deepMerge(
|
|
157
|
+
config as unknown as Record<string, unknown>,
|
|
158
|
+
body as Record<string, unknown>,
|
|
159
|
+
) as unknown as WatchdogConfig;
|
|
160
|
+
|
|
161
|
+
// Apply the merged values back onto the live config object so GET /config
|
|
162
|
+
// reflects the change immediately (without restart)
|
|
163
|
+
Object.assign(config, merged);
|
|
164
|
+
|
|
165
|
+
// Persist user overrides to ~/.aidev/watchdog.json
|
|
166
|
+
const aidevDir = join(os.homedir(), '.aidev');
|
|
167
|
+
await mkdir(aidevDir, { recursive: true });
|
|
168
|
+
const userConfigPath = join(aidevDir, 'watchdog.json');
|
|
169
|
+
await writeFile(userConfigPath, JSON.stringify(body, null, 2), 'utf-8');
|
|
170
|
+
|
|
171
|
+
res.json(config);
|
|
172
|
+
} catch (err) {
|
|
173
|
+
const message = err instanceof Error ? err.message : String(err);
|
|
174
|
+
res.status(500).json({ error: message });
|
|
175
|
+
}
|
|
176
|
+
});
|
|
177
|
+
|
|
122
178
|
return router;
|
|
123
179
|
}
|