process-watchdog 1.1.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 ADDED
@@ -0,0 +1,64 @@
1
+ # Building Standalone Installers
2
+
3
+ Process Watchdog can be packaged into self-contained executables that do not require Node.js to be installed on the target machine. The build pipeline uses **esbuild** to bundle the TypeScript output into a single CommonJS file, then **@yao-pkg/pkg** to wrap it with a Node.js runtime.
4
+
5
+ ## Prerequisites
6
+
7
+ All dependencies are already in `devDependencies` — run `npm install` once before building.
8
+
9
+ ## Build commands
10
+
11
+ | Command | Output |
12
+ |---|---|
13
+ | `npm run build:standalone:win` | `standalone/watchdog-win.exe` (Windows x64) |
14
+ | `npm run build:standalone:mac` | `standalone/watchdog-macos` (macOS x64) |
15
+ | `npm run build:standalone:linux` | `standalone/watchdog-linux` (Linux x64) |
16
+ | `npm run build:standalone` | All three targets |
17
+
18
+ Each command runs three steps automatically:
19
+
20
+ 1. **`npm run build`** — TypeScript compiler (`tsc`) compiles `src/` → `dist/`
21
+ 2. **`npm run bundle`** — esbuild bundles `dist/index.js` → `bundle/watchdog.cjs`
22
+ 3. **`pkg`** — wraps `bundle/watchdog.cjs` with a Node.js runtime into a single executable
23
+
24
+ ## Why the esbuild step?
25
+
26
+ `better-sqlite3` uses a native `.node` addon (`better_sqlite3.node`) that cannot be inlined by pkg. The esbuild step bundles everything else while leaving `better-sqlite3` and `node-windows` as external `require()` calls. pkg then carries the `.node` file as an **asset** (see `pkg.assets` in `package.json`) and patches the path at runtime so the executable finds it.
27
+
28
+ ## Native addon details
29
+
30
+ The `.node` file is embedded in the executable at:
31
+
32
+ ```
33
+ node_modules/better-sqlite3/build/Release/better_sqlite3.node
34
+ ```
35
+
36
+ pkg extracts it to a temporary directory at startup. The `pkg.assets` field in `package.json` controls which files are embedded:
37
+
38
+ ```json
39
+ "assets": [
40
+ "config/**/*",
41
+ "node_modules/better-sqlite3/build/Release/better_sqlite3.node"
42
+ ]
43
+ ```
44
+
45
+ ## Verifying the build
46
+
47
+ After a successful Windows build:
48
+
49
+ ```
50
+ ./standalone/watchdog-win.exe status
51
+ ```
52
+
53
+ The executable should print the current watchdog status without needing Node.js installed.
54
+
55
+ ## Output locations
56
+
57
+ - `bundle/` — intermediate esbuild output (gitignored)
58
+ - `standalone/` — final executables (gitignored)
59
+
60
+ Neither directory is committed to source control.
61
+
62
+ ## Cross-compilation notes
63
+
64
+ pkg downloads pre-built Node.js binaries for the target platform automatically on first use. Building a Linux or macOS binary on Windows is supported — pkg handles the download. However, native addons (`.node` files) are platform-specific: a `better_sqlite3.node` compiled on Windows will not work on Linux. For Linux/macOS targets, the addon must be compiled on that platform. Consider using CI (e.g., GitHub Actions) with platform-specific runners for production cross-platform builds.
@@ -1 +1 @@
1
- {"version":3,"file":"config.d.ts","sourceRoot":"","sources":["../src/config.ts"],"names":[],"mappings":"AAMA,MAAM,WAAW,cAAc;IAC7B,IAAI,EAAE,MAAM,CAAC;IACb,QAAQ,EAAE,MAAM,CAAC;IACjB,oBAAoB,EAAE,MAAM,CAAC;IAC7B,YAAY,EAAE;QACZ,WAAW,EAAE;YAAE,OAAO,EAAE,OAAO,CAAC;YAAC,GAAG,EAAE,MAAM,CAAA;SAAE,CAAC;QAC/C,GAAG,EAAE;YAAE,OAAO,EAAE,OAAO,CAAC;YAAC,GAAG,EAAE,MAAM,CAAA;SAAE,CAAC;KACxC,CAAC;IACF,OAAO,EAAE,MAAM,CAAC,MAAM,EAAE;QACtB,OAAO,EAAE,OAAO,CAAC;QACjB,QAAQ,EAAE,MAAM,CAAC;QACjB,OAAO,EAAE,OAAO,CAAC;QACjB,UAAU,EAAE,MAAM,CAAC,MAAM,EAAE,MAAM,CAAC,CAAC;KACpC,CAAC,CAAC;CACJ;AAED,KAAK,WAAW,CAAC,CAAC,IAAI;KACnB,CAAC,IAAI,MAAM,CAAC,CAAC,CAAC,EAAE,CAAC,CAAC,CAAC,CAAC,SAAS,MAAM,GAAG,WAAW,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC,GAAG,CAAC,CAAC,CAAC,CAAC;CAChE,CAAC;AA4BF,wBAAsB,UAAU,CAC9B,SAAS,CAAC,EAAE,WAAW,CAAC,cAAc,CAAC,GACtC,OAAO,CAAC,cAAc,CAAC,CAuBzB"}
1
+ {"version":3,"file":"config.d.ts","sourceRoot":"","sources":["../src/config.ts"],"names":[],"mappings":"AAMA,MAAM,WAAW,cAAc;IAC7B,IAAI,EAAE,MAAM,CAAC;IACb,QAAQ,EAAE,MAAM,CAAC;IACjB,oBAAoB,EAAE,MAAM,CAAC;IAC7B,YAAY,EAAE;QACZ,WAAW,EAAE;YAAE,OAAO,EAAE,OAAO,CAAC;YAAC,GAAG,EAAE,MAAM,CAAA;SAAE,CAAC;QAC/C,GAAG,EAAE;YAAE,OAAO,EAAE,OAAO,CAAC;YAAC,GAAG,EAAE,MAAM,CAAA;SAAE,CAAC;KACxC,CAAC;IACF,OAAO,EAAE,MAAM,CAAC,MAAM,EAAE;QACtB,OAAO,EAAE,OAAO,CAAC;QACjB,QAAQ,EAAE,MAAM,CAAC;QACjB,OAAO,EAAE,OAAO,CAAC;QACjB,UAAU,EAAE,MAAM,CAAC,MAAM,EAAE,MAAM,CAAC,CAAC;KACpC,CAAC,CAAC;CACJ;AAED,KAAK,WAAW,CAAC,CAAC,IAAI;KACnB,CAAC,IAAI,MAAM,CAAC,CAAC,CAAC,EAAE,CAAC,CAAC,CAAC,CAAC,SAAS,MAAM,GAAG,WAAW,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC,GAAG,CAAC,CAAC,CAAC,CAAC;CAChE,CAAC;AA+CF,wBAAsB,UAAU,CAC9B,SAAS,CAAC,EAAE,WAAW,CAAC,cAAc,CAAC,GACtC,OAAO,CAAC,cAAc,CAAC,CA4BzB"}
package/dist/config.js CHANGED
@@ -20,15 +20,39 @@ function deepMerge(target, source) {
20
20
  }
21
21
  return result;
22
22
  }
23
- const __filename = fileURLToPath(import.meta.url);
24
- const __dirname = dirname(__filename);
25
- // src/config.ts lives in <project-root>/src/, so project root is one level up
26
- const PROJECT_ROOT = resolve(__dirname, '..');
23
+ // Support both ESM (import.meta.url) and CJS (__dirname) contexts
24
+ const _dirname = typeof import.meta?.url === 'string'
25
+ ? dirname(fileURLToPath(import.meta.url))
26
+ : (typeof __dirname !== 'undefined' ? __dirname : process.cwd());
27
+ // src/config.ts lives in <project-root>/src/ (or dist/), so project root is one level up
28
+ const PROJECT_ROOT = resolve(_dirname, '..');
29
+ // Embedded default config (used as fallback when config/default.json is not on disk,
30
+ // e.g. in standalone pkg builds where the file isn't bundled)
31
+ const EMBEDDED_DEFAULTS = {
32
+ port: 3400, logLevel: 'info', historyRetentionDays: 30,
33
+ integrations: {
34
+ totalRecall: { enabled: false, url: 'https://recall.aidev.com.au' },
35
+ mah: { enabled: false, url: 'https://mah.aidev.com.au' },
36
+ },
37
+ plugins: {
38
+ 'process-guard': { enabled: true, interval: 300000, autoFix: true, thresholds: { node: 50, cmd: 20, bash: 10 } },
39
+ 'memory-monitor': { enabled: true, interval: 120000, autoFix: false, thresholds: { warningPct: 85, criticalPct: 95 } },
40
+ 'disk-health': { enabled: true, interval: 1800000, autoFix: true, thresholds: { warningPct: 80, criticalPct: 90, tempFileAgeDays: 7 } },
41
+ 'startup-optimizer': { enabled: true, interval: 0, autoFix: false, thresholds: {} },
42
+ 'cpu-monitor': { enabled: true, interval: 120000, autoFix: false, thresholds: { warningPct: 80, warningDurationMin: 5, criticalPct: 95, criticalDurationMin: 2 } },
43
+ },
44
+ };
27
45
  export async function loadConfig(overrides) {
28
- // 1. Read config/default.json from the project root
46
+ // 1. Read config/default.json from disk, fall back to embedded defaults
47
+ let config;
29
48
  const defaultPath = join(PROJECT_ROOT, 'config', 'default.json');
30
- const defaultRaw = await readFile(defaultPath, 'utf-8');
31
- let config = JSON.parse(defaultRaw);
49
+ if (existsSync(defaultPath)) {
50
+ const defaultRaw = await readFile(defaultPath, 'utf-8');
51
+ config = JSON.parse(defaultRaw);
52
+ }
53
+ else {
54
+ config = structuredClone(EMBEDDED_DEFAULTS);
55
+ }
32
56
  // 2. Read ~/.aidev/watchdog.json if it exists
33
57
  const userConfigPath = join(os.homedir(), '.aidev', 'watchdog.json');
34
58
  if (existsSync(userConfigPath)) {
@@ -1 +1 @@
1
- {"version":3,"file":"config.js","sourceRoot":"","sources":["../src/config.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,QAAQ,EAAE,MAAM,aAAa,CAAC;AACvC,OAAO,EAAE,UAAU,EAAE,MAAM,IAAI,CAAC;AAChC,OAAO,EAAE,aAAa,EAAE,MAAM,KAAK,CAAC;AACpC,OAAO,EAAE,OAAO,EAAE,OAAO,EAAE,IAAI,EAAE,MAAM,MAAM,CAAC;AAC9C,OAAO,EAAE,MAAM,IAAI,CAAC;AAsBpB,SAAS,aAAa,CAAC,KAAc;IACnC,OAAO,OAAO,KAAK,KAAK,QAAQ,IAAI,KAAK,KAAK,IAAI,IAAI,CAAC,KAAK,CAAC,OAAO,CAAC,KAAK,CAAC,CAAC;AAC9E,CAAC;AAED,SAAS,SAAS,CAChB,MAAS,EACT,MAA+B;IAE/B,MAAM,MAAM,GAA4B,EAAE,GAAG,MAAM,EAAE,CAAC;IACtD,KAAK,MAAM,GAAG,IAAI,MAAM,CAAC,IAAI,CAAC,MAAM,CAAC,EAAE,CAAC;QACtC,MAAM,MAAM,GAAG,MAAM,CAAC,GAAG,CAAC,CAAC;QAC3B,MAAM,MAAM,GAAG,MAAM,CAAC,GAAG,CAAC,CAAC;QAC3B,IAAI,aAAa,CAAC,MAAM,CAAC,IAAI,aAAa,CAAC,MAAM,CAAC,EAAE,CAAC;YACnD,MAAM,CAAC,GAAG,CAAC,GAAG,SAAS,CAAC,MAAM,EAAE,MAAM,CAAC,CAAC;QAC1C,CAAC;aAAM,CAAC;YACN,MAAM,CAAC,GAAG,CAAC,GAAG,MAAM,CAAC;QACvB,CAAC;IACH,CAAC;IACD,OAAO,MAAW,CAAC;AACrB,CAAC;AAED,MAAM,UAAU,GAAG,aAAa,CAAC,MAAM,CAAC,IAAI,CAAC,GAAG,CAAC,CAAC;AAClD,MAAM,SAAS,GAAG,OAAO,CAAC,UAAU,CAAC,CAAC;AACtC,8EAA8E;AAC9E,MAAM,YAAY,GAAG,OAAO,CAAC,SAAS,EAAE,IAAI,CAAC,CAAC;AAE9C,MAAM,CAAC,KAAK,UAAU,UAAU,CAC9B,SAAuC;IAEvC,oDAAoD;IACpD,MAAM,WAAW,GAAG,IAAI,CAAC,YAAY,EAAE,QAAQ,EAAE,cAAc,CAAC,CAAC;IACjE,MAAM,UAAU,GAAG,MAAM,QAAQ,CAAC,WAAW,EAAE,OAAO,CAAC,CAAC;IACxD,IAAI,MAAM,GAAG,IAAI,CAAC,KAAK,CAAC,UAAU,CAAmB,CAAC;IAEtD,8CAA8C;IAC9C,MAAM,cAAc,GAAG,IAAI,CAAC,EAAE,CAAC,OAAO,EAAE,EAAE,QAAQ,EAAE,eAAe,CAAC,CAAC;IACrE,IAAI,UAAU,CAAC,cAAc,CAAC,EAAE,CAAC;QAC/B,MAAM,OAAO,GAAG,MAAM,QAAQ,CAAC,cAAc,EAAE,OAAO,CAAC,CAAC;QACxD,MAAM,UAAU,GAAG,IAAI,CAAC,KAAK,CAAC,OAAO,CAA4B,CAAC;QAClE,MAAM,GAAG,SAAS,CAAC,MAA4C,EAAE,UAAU,CAA8B,CAAC;IAC5G,CAAC;IAED,4BAA4B;IAC5B,IAAI,SAAS,EAAE,CAAC;QACd,MAAM,GAAG,SAAS,CAChB,MAA4C,EAC5C,SAAoC,CACR,CAAC;IACjC,CAAC;IAED,OAAO,MAAM,CAAC;AAChB,CAAC"}
1
+ {"version":3,"file":"config.js","sourceRoot":"","sources":["../src/config.ts"],"names":[],"mappings":"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"}
package/dist/index.js CHANGED
@@ -199,5 +199,21 @@ program
199
199
  process.exit(1);
200
200
  }
201
201
  });
202
+ // ---------------------------------------------------------------------------
203
+ // watchdog tray
204
+ // ---------------------------------------------------------------------------
205
+ program
206
+ .command('tray')
207
+ .description('Start system tray health indicator (Windows NotifyIcon via PowerShell)')
208
+ .action(async () => {
209
+ try {
210
+ const { startTray } = await import('./tray/index.js');
211
+ startTray();
212
+ }
213
+ catch (err) {
214
+ console.error('[watchdog] tray failed:', err.message);
215
+ process.exit(1);
216
+ }
217
+ });
202
218
  program.parseAsync(process.argv);
203
219
  //# sourceMappingURL=index.js.map
package/dist/index.js.map CHANGED
@@ -1 +1 @@
1
- {"version":3,"file":"index.js","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"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"}
1
+ {"version":3,"file":"index.js","sourceRoot":"","sources":["../src/index.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.1.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/config.ts CHANGED
@@ -45,18 +45,42 @@ function deepMerge<T extends Record<string, unknown>>(
45
45
  return result as T;
46
46
  }
47
47
 
48
- const __filename = fileURLToPath(import.meta.url);
49
- const __dirname = dirname(__filename);
50
- // src/config.ts lives in <project-root>/src/, so project root is one level up
51
- const PROJECT_ROOT = resolve(__dirname, '..');
48
+ // Support both ESM (import.meta.url) and CJS (__dirname) contexts
49
+ const _dirname = typeof import.meta?.url === 'string'
50
+ ? dirname(fileURLToPath(import.meta.url))
51
+ : (typeof __dirname !== 'undefined' ? __dirname : process.cwd());
52
+ // src/config.ts lives in <project-root>/src/ (or dist/), so project root is one level up
53
+ const PROJECT_ROOT = resolve(_dirname, '..');
54
+
55
+ // Embedded default config (used as fallback when config/default.json is not on disk,
56
+ // e.g. in standalone pkg builds where the file isn't bundled)
57
+ const EMBEDDED_DEFAULTS: WatchdogConfig = {
58
+ port: 3400, logLevel: 'info', historyRetentionDays: 30,
59
+ integrations: {
60
+ totalRecall: { enabled: false, url: 'https://recall.aidev.com.au' },
61
+ mah: { enabled: false, url: 'https://mah.aidev.com.au' },
62
+ },
63
+ plugins: {
64
+ 'process-guard': { enabled: true, interval: 300000, autoFix: true, thresholds: { node: 50, cmd: 20, bash: 10 } },
65
+ 'memory-monitor': { enabled: true, interval: 120000, autoFix: false, thresholds: { warningPct: 85, criticalPct: 95 } },
66
+ 'disk-health': { enabled: true, interval: 1800000, autoFix: true, thresholds: { warningPct: 80, criticalPct: 90, tempFileAgeDays: 7 } },
67
+ 'startup-optimizer': { enabled: true, interval: 0, autoFix: false, thresholds: {} },
68
+ 'cpu-monitor': { enabled: true, interval: 120000, autoFix: false, thresholds: { warningPct: 80, warningDurationMin: 5, criticalPct: 95, criticalDurationMin: 2 } },
69
+ },
70
+ };
52
71
 
53
72
  export async function loadConfig(
54
73
  overrides?: DeepPartial<WatchdogConfig>,
55
74
  ): Promise<WatchdogConfig> {
56
- // 1. Read config/default.json from the project root
75
+ // 1. Read config/default.json from disk, fall back to embedded defaults
76
+ let config: WatchdogConfig;
57
77
  const defaultPath = join(PROJECT_ROOT, 'config', 'default.json');
58
- const defaultRaw = await readFile(defaultPath, 'utf-8');
59
- let config = JSON.parse(defaultRaw) as WatchdogConfig;
78
+ if (existsSync(defaultPath)) {
79
+ const defaultRaw = await readFile(defaultPath, 'utf-8');
80
+ config = JSON.parse(defaultRaw) as WatchdogConfig;
81
+ } else {
82
+ config = structuredClone(EMBEDDED_DEFAULTS);
83
+ }
60
84
 
61
85
  // 2. Read ~/.aidev/watchdog.json if it exists
62
86
  const userConfigPath = join(os.homedir(), '.aidev', 'watchdog.json');
package/src/index.ts CHANGED
@@ -225,4 +225,20 @@ program
225
225
  }
226
226
  });
227
227
 
228
+ // ---------------------------------------------------------------------------
229
+ // watchdog tray
230
+ // ---------------------------------------------------------------------------
231
+ program
232
+ .command('tray')
233
+ .description('Start system tray health indicator (Windows NotifyIcon via PowerShell)')
234
+ .action(async () => {
235
+ try {
236
+ const { startTray } = await import('./tray/index.js');
237
+ startTray();
238
+ } catch (err) {
239
+ console.error('[watchdog] tray failed:', (err as Error).message);
240
+ process.exit(1);
241
+ }
242
+ });
243
+
228
244
  program.parseAsync(process.argv);
@@ -0,0 +1,86 @@
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
+ // ---------------------------------------------------------------------------
8
+ // Resolve paths
9
+ // ---------------------------------------------------------------------------
10
+
11
+ // __dirname equivalent for ESM
12
+ const __filename = fileURLToPath(import.meta.url);
13
+ const __dirname = dirname(__filename);
14
+
15
+ /**
16
+ * Locate the compiled dist/ folder.
17
+ *
18
+ * When running from source via `tsx`: __dirname = …/src/tray → go up 2 levels
19
+ * When running from compiled dist/: __dirname = …/dist/tray → go up 2 levels
20
+ * Both cases land at the project root; dist/ is always at <root>/dist.
21
+ */
22
+ function resolveDistDir(): string {
23
+ // Walk up two directories from src/tray or dist/tray to reach the project root
24
+ const projectRoot = join(__dirname, '..', '..');
25
+ return join(projectRoot, 'dist');
26
+ }
27
+
28
+ // ---------------------------------------------------------------------------
29
+ // Embed the .ps1 source relative to THIS file (works for both tsx and compiled)
30
+ // ---------------------------------------------------------------------------
31
+
32
+ /**
33
+ * Return the PowerShell script text.
34
+ * We read it from the source tree at `../../src/tray/tray.ps1` (relative to
35
+ * this compiled file at dist/tray/index.js) or from the same directory when
36
+ * running under tsx.
37
+ */
38
+ function readTrayScript(): string {
39
+ // Try same directory first (tsx run — __dirname is src/tray)
40
+ const candidates = [
41
+ join(__dirname, 'tray.ps1'),
42
+ join(__dirname, '..', '..', 'src', 'tray', 'tray.ps1'),
43
+ ];
44
+ for (const p of candidates) {
45
+ try {
46
+ return readFileSync(p, 'utf-8');
47
+ } catch {
48
+ // try next
49
+ }
50
+ }
51
+ throw new Error('tray.ps1 not found. Build the project first or check src/tray/tray.ps1 exists.');
52
+ }
53
+
54
+ // ---------------------------------------------------------------------------
55
+ // Public API
56
+ // ---------------------------------------------------------------------------
57
+
58
+ export function startTray(): void {
59
+ const distDir = resolveDistDir();
60
+ const scriptText = readTrayScript();
61
+ const scriptPath = join(tmpdir(), 'watchdog-tray.ps1');
62
+
63
+ // Write the PS1 to a temp file so PowerShell can -File it
64
+ writeFileSync(scriptPath, scriptText, 'utf-8');
65
+
66
+ const child = spawn(
67
+ 'powershell.exe',
68
+ [
69
+ '-NoProfile',
70
+ '-ExecutionPolicy', 'Bypass',
71
+ '-File', scriptPath,
72
+ '-distDir', distDir,
73
+ ],
74
+ {
75
+ detached: true,
76
+ stdio: 'ignore',
77
+ windowStyle: 'hidden',
78
+ } as Parameters<typeof spawn>[2],
79
+ );
80
+
81
+ child.unref();
82
+
83
+ console.log(`[watchdog] System tray started (PID: ${child.pid})`);
84
+ console.log(`[watchdog] Monitoring dist at: ${distDir}`);
85
+ console.log('[watchdog] Right-click the tray icon to access the menu.');
86
+ }
@@ -0,0 +1,156 @@
1
+ # Process Watchdog — System Tray Icon
2
+ # Invoked by: watchdog tray
3
+ # Args: $distDir (path to compiled dist folder)
4
+ param(
5
+ [Parameter(Mandatory = $true)]
6
+ [string]$distDir
7
+ )
8
+
9
+ Add-Type -AssemblyName System.Windows.Forms
10
+ Add-Type -AssemblyName System.Drawing
11
+
12
+ # ---------------------------------------------------------------------------
13
+ # Helper: run `node dist/index.js <cmd>` and return stdout lines
14
+ # ---------------------------------------------------------------------------
15
+ function Invoke-Watchdog {
16
+ param([string]$Cmd)
17
+ $nodeExe = (Get-Command node -ErrorAction SilentlyContinue)?.Source
18
+ if (-not $nodeExe) { return @("node not found in PATH") }
19
+ $indexJs = Join-Path $distDir "index.js"
20
+ $lines = & $nodeExe $indexJs $Cmd 2>&1
21
+ return $lines
22
+ }
23
+
24
+ # ---------------------------------------------------------------------------
25
+ # Build tray icon
26
+ # ---------------------------------------------------------------------------
27
+ $tray = New-Object System.Windows.Forms.NotifyIcon
28
+ $tray.Text = "Process Watchdog"
29
+ $tray.Icon = [System.Drawing.SystemIcons]::Information
30
+ $tray.Visible = $true
31
+
32
+ # ---------------------------------------------------------------------------
33
+ # Context menu
34
+ # ---------------------------------------------------------------------------
35
+ $menu = New-Object System.Windows.Forms.ContextMenuStrip
36
+
37
+ # Status label (disabled — display only)
38
+ $itemStatus = New-Object System.Windows.Forms.ToolStripMenuItem
39
+ $itemStatus.Text = "Status: Initialising…"
40
+ $itemStatus.Enabled = $false
41
+ $null = $menu.Items.Add($itemStatus)
42
+
43
+ $null = $menu.Items.Add((New-Object System.Windows.Forms.ToolStripSeparator))
44
+
45
+ # Check Now
46
+ $itemCheck = New-Object System.Windows.Forms.ToolStripMenuItem
47
+ $itemCheck.Text = "Check Now"
48
+ $itemCheck.Add_Click({
49
+ $lines = Invoke-Watchdog "check"
50
+ $output = ($lines -join "`n").Trim()
51
+ if (-not $output) { $output = "(no output)" }
52
+ [System.Windows.Forms.MessageBox]::Show(
53
+ $output,
54
+ "Process Watchdog — Check Results",
55
+ [System.Windows.Forms.MessageBoxButtons]::OK,
56
+ [System.Windows.Forms.MessageBoxIcon]::Information
57
+ ) | Out-Null
58
+ })
59
+ $null = $menu.Items.Add($itemCheck)
60
+
61
+ # Fix Issues
62
+ $itemFix = New-Object System.Windows.Forms.ToolStripMenuItem
63
+ $itemFix.Text = "Fix Issues"
64
+ $itemFix.Add_Click({
65
+ $lines = Invoke-Watchdog "fix"
66
+ $output = ($lines -join "`n").Trim()
67
+ if (-not $output) { $output = "(no output)" }
68
+ [System.Windows.Forms.MessageBox]::Show(
69
+ $output,
70
+ "Process Watchdog — Fix Results",
71
+ [System.Windows.Forms.MessageBoxButtons]::OK,
72
+ [System.Windows.Forms.MessageBoxIcon]::Information
73
+ ) | Out-Null
74
+ })
75
+ $null = $menu.Items.Add($itemFix)
76
+
77
+ # Open Dashboard
78
+ $itemDash = New-Object System.Windows.Forms.ToolStripMenuItem
79
+ $itemDash.Text = "Open Dashboard"
80
+ $itemDash.Add_Click({
81
+ Start-Process "http://localhost:3400"
82
+ })
83
+ $null = $menu.Items.Add($itemDash)
84
+
85
+ $null = $menu.Items.Add((New-Object System.Windows.Forms.ToolStripSeparator))
86
+
87
+ # Exit
88
+ $itemExit = New-Object System.Windows.Forms.ToolStripMenuItem
89
+ $itemExit.Text = "Exit"
90
+ $itemExit.Add_Click({
91
+ $tray.Visible = $false
92
+ $tray.Dispose()
93
+ [System.Windows.Forms.Application]::Exit()
94
+ })
95
+ $null = $menu.Items.Add($itemExit)
96
+
97
+ $tray.ContextMenuStrip = $menu
98
+
99
+ # ---------------------------------------------------------------------------
100
+ # Health-polling timer (every 60 s)
101
+ # ---------------------------------------------------------------------------
102
+ $script:lastStatus = ""
103
+
104
+ function Update-TrayStatus {
105
+ try {
106
+ $lines = Invoke-Watchdog "status"
107
+ $hasCrit = $lines | Where-Object { $_ -match '\[CRIT\]' }
108
+ $hasWarn = $lines | Where-Object { $_ -match '\[WARN\]' }
109
+
110
+ if ($hasCrit) {
111
+ $tray.Icon = [System.Drawing.SystemIcons]::Error
112
+ $itemStatus.Text = "Status: CRITICAL"
113
+ if ($script:lastStatus -ne "CRITICAL") {
114
+ $tray.ShowBalloonTip(
115
+ 5000,
116
+ "Process Watchdog",
117
+ "Critical issues detected! Click 'Fix Issues' to resolve.",
118
+ [System.Windows.Forms.ToolTipIcon]::Error
119
+ )
120
+ }
121
+ $script:lastStatus = "CRITICAL"
122
+ } elseif ($hasWarn) {
123
+ $tray.Icon = [System.Drawing.SystemIcons]::Warning
124
+ $itemStatus.Text = "Status: Warning"
125
+ if ($script:lastStatus -ne "WARNING") {
126
+ $tray.ShowBalloonTip(
127
+ 4000,
128
+ "Process Watchdog",
129
+ "Warning: some checks need attention.",
130
+ [System.Windows.Forms.ToolTipIcon]::Warning
131
+ )
132
+ }
133
+ $script:lastStatus = "WARNING"
134
+ } else {
135
+ $tray.Icon = [System.Drawing.SystemIcons]::Information
136
+ $itemStatus.Text = "Status: Healthy"
137
+ $script:lastStatus = "HEALTHY"
138
+ }
139
+ } catch {
140
+ $tray.Icon = [System.Drawing.SystemIcons]::Question
141
+ $itemStatus.Text = "Status: Check failed"
142
+ }
143
+ }
144
+
145
+ $timer = New-Object System.Windows.Forms.Timer
146
+ $timer.Interval = 60000 # 60 seconds
147
+ $timer.Add_Tick({ Update-TrayStatus })
148
+ $timer.Start()
149
+
150
+ # Run an immediate check so the icon is correct on startup
151
+ Update-TrayStatus
152
+
153
+ # ---------------------------------------------------------------------------
154
+ # Run the Windows message loop (blocks until Application::Exit is called)
155
+ # ---------------------------------------------------------------------------
156
+ [System.Windows.Forms.Application]::Run()