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.
Files changed (52) hide show
  1. package/BUILDING.md +64 -0
  2. package/README.md +115 -0
  3. package/dashboard/watchdog.html +406 -0
  4. package/dist/api/routes.d.ts.map +1 -1
  5. package/dist/api/routes.js +45 -0
  6. package/dist/api/routes.js.map +1 -1
  7. package/dist/config.d.ts.map +1 -1
  8. package/dist/config.js +31 -7
  9. package/dist/config.js.map +1 -1
  10. package/dist/index.js +21 -5
  11. package/dist/index.js.map +1 -1
  12. package/dist/platform/index.d.ts.map +1 -1
  13. package/dist/platform/index.js +7 -1
  14. package/dist/platform/index.js.map +1 -1
  15. package/dist/platform/linux.d.ts +14 -0
  16. package/dist/platform/linux.d.ts.map +1 -0
  17. package/dist/platform/linux.js +235 -0
  18. package/dist/platform/linux.js.map +1 -0
  19. package/dist/platform/macos.d.ts +14 -0
  20. package/dist/platform/macos.d.ts.map +1 -0
  21. package/dist/platform/macos.js +255 -0
  22. package/dist/platform/macos.js.map +1 -0
  23. package/dist/plugins/plugin-loader.d.ts +1 -1
  24. package/dist/plugins/plugin-loader.d.ts.map +1 -1
  25. package/dist/plugins/plugin-loader.js +46 -1
  26. package/dist/plugins/plugin-loader.js.map +1 -1
  27. package/dist/plugins/process-guard.d.ts.map +1 -1
  28. package/dist/plugins/process-guard.js +0 -15
  29. package/dist/plugins/process-guard.js.map +1 -1
  30. package/dist/tray/index.d.ts +2 -0
  31. package/dist/tray/index.d.ts.map +1 -0
  32. package/dist/tray/index.js +73 -0
  33. package/dist/tray/index.js.map +1 -0
  34. package/package.json +21 -2
  35. package/scripts/bundle.js +38 -0
  36. package/src/api/routes.ts +56 -0
  37. package/src/config.ts +31 -7
  38. package/src/index.ts +21 -5
  39. package/src/platform/index.ts +7 -1
  40. package/src/platform/linux.ts +255 -0
  41. package/src/platform/macos.ts +259 -0
  42. package/src/plugins/plugin-loader.ts +66 -1
  43. package/src/plugins/process-guard.ts +0 -15
  44. package/src/tray/index.ts +86 -0
  45. package/src/tray/tray.ps1 +156 -0
  46. package/tests/plugins/cpu-monitor.test.ts +5 -5
  47. package/tests/plugins/disk-health.test.ts +1 -1
  48. package/tests/plugins/fixtures/broken-plugin.js +5 -0
  49. package/tests/plugins/fixtures/custom-plugin.js +36 -0
  50. package/tests/plugins/fixtures/named-plugin.js +31 -0
  51. package/tests/plugins/plugin-loader.test.ts +124 -7
  52. 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":"AAAA,OAAO,EAAE,cAAc,EAAE,MAAM,uBAAuB,CAAC;AACvD,OAAO,EAAE,cAAc,EAAE,MAAM,cAAc,CAAC;AAe9C,wBAAgB,WAAW,CAAC,MAAM,EAAE,cAAc,GAAG,cAAc,EAAE,CAUpE"}
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":"AAEA,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,UAAU,WAAW,CAAC,MAAsB;IAChD,MAAM,OAAO,GAAqB,EAAE,CAAC;IACrC,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;IACD,OAAO,OAAO,CAAC;AACjB,CAAC"}
1
+ {"version":3,"file":"plugin-loader.js","sourceRoot":"","sources":["../../src/plugins/plugin-loader.ts"],"names":[],"mappings":"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"}
@@ -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;CA8EhC"}
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,2 @@
1
+ export declare function startTray(): void;
2
+ //# sourceMappingURL=index.d.ts.map
@@ -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.0.0",
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
  }