clawdoctor 0.1.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 (78) hide show
  1. package/README.md +112 -0
  2. package/dist/alerters/telegram.d.ts +21 -0
  3. package/dist/alerters/telegram.d.ts.map +1 -0
  4. package/dist/alerters/telegram.js +87 -0
  5. package/dist/alerters/telegram.js.map +1 -0
  6. package/dist/config.d.ts +42 -0
  7. package/dist/config.d.ts.map +1 -0
  8. package/dist/config.js +77 -0
  9. package/dist/config.js.map +1 -0
  10. package/dist/daemon.d.ts +21 -0
  11. package/dist/daemon.d.ts.map +1 -0
  12. package/dist/daemon.js +172 -0
  13. package/dist/daemon.js.map +1 -0
  14. package/dist/healers/base.d.ts +15 -0
  15. package/dist/healers/base.d.ts.map +1 -0
  16. package/dist/healers/base.js +25 -0
  17. package/dist/healers/base.js.map +1 -0
  18. package/dist/healers/cron.d.ts +6 -0
  19. package/dist/healers/cron.d.ts.map +1 -0
  20. package/dist/healers/cron.js +26 -0
  21. package/dist/healers/cron.js.map +1 -0
  22. package/dist/healers/process.d.ts +6 -0
  23. package/dist/healers/process.d.ts.map +1 -0
  24. package/dist/healers/process.js +67 -0
  25. package/dist/healers/process.js.map +1 -0
  26. package/dist/index.d.ts +3 -0
  27. package/dist/index.d.ts.map +1 -0
  28. package/dist/index.js +283 -0
  29. package/dist/index.js.map +1 -0
  30. package/dist/store.d.ts +22 -0
  31. package/dist/store.d.ts.map +1 -0
  32. package/dist/store.js +97 -0
  33. package/dist/store.js.map +1 -0
  34. package/dist/test/config.test.d.ts +2 -0
  35. package/dist/test/config.test.d.ts.map +1 -0
  36. package/dist/test/config.test.js +90 -0
  37. package/dist/test/config.test.js.map +1 -0
  38. package/dist/test/store.test.d.ts +2 -0
  39. package/dist/test/store.test.d.ts.map +1 -0
  40. package/dist/test/store.test.js +89 -0
  41. package/dist/test/store.test.js.map +1 -0
  42. package/dist/test/telegram.test.d.ts +2 -0
  43. package/dist/test/telegram.test.d.ts.map +1 -0
  44. package/dist/test/telegram.test.js +107 -0
  45. package/dist/test/telegram.test.js.map +1 -0
  46. package/dist/test/watchers.test.d.ts +2 -0
  47. package/dist/test/watchers.test.d.ts.map +1 -0
  48. package/dist/test/watchers.test.js +194 -0
  49. package/dist/test/watchers.test.js.map +1 -0
  50. package/dist/utils.d.ts +18 -0
  51. package/dist/utils.d.ts.map +1 -0
  52. package/dist/utils.js +62 -0
  53. package/dist/utils.js.map +1 -0
  54. package/dist/watchers/auth.d.ts +10 -0
  55. package/dist/watchers/auth.d.ts.map +1 -0
  56. package/dist/watchers/auth.js +79 -0
  57. package/dist/watchers/auth.js.map +1 -0
  58. package/dist/watchers/base.d.ts +22 -0
  59. package/dist/watchers/base.d.ts.map +1 -0
  60. package/dist/watchers/base.js +39 -0
  61. package/dist/watchers/base.js.map +1 -0
  62. package/dist/watchers/cost.d.ts +9 -0
  63. package/dist/watchers/cost.d.ts.map +1 -0
  64. package/dist/watchers/cost.js +151 -0
  65. package/dist/watchers/cost.js.map +1 -0
  66. package/dist/watchers/cron.d.ts +7 -0
  67. package/dist/watchers/cron.d.ts.map +1 -0
  68. package/dist/watchers/cron.js +79 -0
  69. package/dist/watchers/cron.js.map +1 -0
  70. package/dist/watchers/gateway.d.ts +7 -0
  71. package/dist/watchers/gateway.d.ts.map +1 -0
  72. package/dist/watchers/gateway.js +33 -0
  73. package/dist/watchers/gateway.js.map +1 -0
  74. package/dist/watchers/session.d.ts +7 -0
  75. package/dist/watchers/session.d.ts.map +1 -0
  76. package/dist/watchers/session.js +112 -0
  77. package/dist/watchers/session.js.map +1 -0
  78. package/package.json +46 -0
@@ -0,0 +1,89 @@
1
+ "use strict";
2
+ var __importDefault = (this && this.__importDefault) || function (mod) {
3
+ return (mod && mod.__esModule) ? mod : { "default": mod };
4
+ };
5
+ Object.defineProperty(exports, "__esModule", { value: true });
6
+ const node_test_1 = require("node:test");
7
+ const strict_1 = __importDefault(require("node:assert/strict"));
8
+ const fs_1 = __importDefault(require("fs"));
9
+ const path_1 = __importDefault(require("path"));
10
+ const os_1 = __importDefault(require("os"));
11
+ const better_sqlite3_1 = __importDefault(require("better-sqlite3"));
12
+ const tmpDir = fs_1.default.mkdtempSync(path_1.default.join(os_1.default.tmpdir(), 'clawdoctor-store-test-'));
13
+ const dbPath = path_1.default.join(tmpDir, 'events.db');
14
+ // Minimal in-process store test that doesn't rely on the module's global path
15
+ (0, node_test_1.describe)('EventStore (in-process)', () => {
16
+ let db;
17
+ (0, node_test_1.before)(() => {
18
+ db = new better_sqlite3_1.default(dbPath);
19
+ db.pragma('journal_mode = WAL');
20
+ db.exec(`
21
+ CREATE TABLE IF NOT EXISTS events (
22
+ id INTEGER PRIMARY KEY AUTOINCREMENT,
23
+ timestamp TEXT NOT NULL,
24
+ watcher TEXT NOT NULL,
25
+ severity TEXT NOT NULL,
26
+ event_type TEXT NOT NULL,
27
+ message TEXT NOT NULL,
28
+ details TEXT,
29
+ action_taken TEXT,
30
+ action_result TEXT,
31
+ created_at TEXT DEFAULT (datetime('now'))
32
+ );
33
+ `);
34
+ });
35
+ (0, node_test_1.after)(() => {
36
+ db.close();
37
+ fs_1.default.rmSync(tmpDir, { recursive: true, force: true });
38
+ });
39
+ (0, node_test_1.it)('inserts an event', () => {
40
+ const stmt = db.prepare(`
41
+ INSERT INTO events (timestamp, watcher, severity, event_type, message)
42
+ VALUES (?, ?, ?, ?, ?)
43
+ `);
44
+ const result = stmt.run(new Date().toISOString(), 'GatewayWatcher', 'critical', 'gateway_down', 'Gateway not found');
45
+ strict_1.default.ok(result.lastInsertRowid > 0);
46
+ });
47
+ (0, node_test_1.it)('retrieves inserted events', () => {
48
+ const rows = db.prepare('SELECT * FROM events ORDER BY id DESC').all();
49
+ strict_1.default.ok(rows.length >= 1);
50
+ const row = rows[0];
51
+ strict_1.default.equal(row.watcher, 'GatewayWatcher');
52
+ strict_1.default.equal(row.severity, 'critical');
53
+ strict_1.default.equal(row.event_type, 'gateway_down');
54
+ });
55
+ (0, node_test_1.it)('stores and retrieves JSON details', () => {
56
+ const details = JSON.stringify({ pids: [1234, 5678], host: 'devbox' });
57
+ db.prepare(`
58
+ INSERT INTO events (timestamp, watcher, severity, event_type, message, details)
59
+ VALUES (?, ?, ?, ?, ?, ?)
60
+ `).run(new Date().toISOString(), 'CronWatcher', 'error', 'cron_error', 'Cron failed', details);
61
+ const row = db.prepare(`SELECT * FROM events WHERE watcher = 'CronWatcher' LIMIT 1`).get();
62
+ strict_1.default.ok(row);
63
+ const parsed = JSON.parse(row.details);
64
+ strict_1.default.deepEqual(parsed.pids, [1234, 5678]);
65
+ strict_1.default.equal(parsed.host, 'devbox');
66
+ });
67
+ (0, node_test_1.it)('prunes old events', () => {
68
+ // Insert an old-looking event by overriding created_at
69
+ db.prepare(`
70
+ INSERT INTO events (timestamp, watcher, severity, event_type, message, created_at)
71
+ VALUES (?, ?, ?, ?, ?, datetime('now', '-30 days'))
72
+ `).run(new Date().toISOString(), 'TestWatcher', 'info', 'old_event', 'Old event');
73
+ const before = db.prepare('SELECT COUNT(*) as count FROM events').get().count;
74
+ const result = db.prepare(`
75
+ DELETE FROM events WHERE created_at < datetime('now', '-' || ? || ' days')
76
+ `).run(7);
77
+ const after = db.prepare('SELECT COUNT(*) as count FROM events').get().count;
78
+ strict_1.default.ok(result.changes >= 1);
79
+ strict_1.default.ok(after < before);
80
+ });
81
+ (0, node_test_1.it)('filters events by watcher', () => {
82
+ const rows = db.prepare(`SELECT * FROM events WHERE watcher = 'GatewayWatcher'`).all();
83
+ strict_1.default.ok(rows.length >= 1);
84
+ for (const row of rows) {
85
+ strict_1.default.equal(row.watcher, 'GatewayWatcher');
86
+ }
87
+ });
88
+ });
89
+ //# sourceMappingURL=store.test.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"store.test.js","sourceRoot":"","sources":["../../src/test/store.test.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,2 @@
1
+ export {};
2
+ //# sourceMappingURL=telegram.test.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"telegram.test.d.ts","sourceRoot":"","sources":["../../src/test/telegram.test.ts"],"names":[],"mappings":""}
@@ -0,0 +1,107 @@
1
+ "use strict";
2
+ var __importDefault = (this && this.__importDefault) || function (mod) {
3
+ return (mod && mod.__esModule) ? mod : { "default": mod };
4
+ };
5
+ Object.defineProperty(exports, "__esModule", { value: true });
6
+ const node_test_1 = require("node:test");
7
+ const strict_1 = __importDefault(require("node:assert/strict"));
8
+ const telegram_js_1 = require("../alerters/telegram.js");
9
+ const config_js_1 = require("../config.js");
10
+ function makeConfig(overrides = {}) {
11
+ return {
12
+ ...config_js_1.DEFAULT_CONFIG,
13
+ alerts: {
14
+ telegram: {
15
+ enabled: true,
16
+ botToken: 'test-token',
17
+ chatId: '123456',
18
+ ...overrides,
19
+ },
20
+ },
21
+ };
22
+ }
23
+ (0, node_test_1.describe)('TelegramAlerter', () => {
24
+ (0, node_test_1.it)('formatMessage includes watcher name and message', () => {
25
+ const alerter = new telegram_js_1.TelegramAlerter(makeConfig());
26
+ const result = {
27
+ ok: false,
28
+ severity: 'critical',
29
+ event_type: 'gateway_down',
30
+ message: 'Gateway process not found',
31
+ };
32
+ const msg = alerter.formatMessage({ watcher: 'GatewayWatcher', result });
33
+ strict_1.default.ok(msg.includes('GatewayWatcher'));
34
+ strict_1.default.ok(msg.includes('Gateway process not found'));
35
+ });
36
+ (0, node_test_1.it)('formatMessage uses 🔴 for critical', () => {
37
+ const alerter = new telegram_js_1.TelegramAlerter(makeConfig());
38
+ const result = { ok: false, severity: 'critical', event_type: 'gateway_down', message: 'Down' };
39
+ const msg = alerter.formatMessage({ watcher: 'GatewayWatcher', result });
40
+ strict_1.default.ok(msg.includes('🔴'));
41
+ });
42
+ (0, node_test_1.it)('formatMessage uses 🟢 for info/ok', () => {
43
+ const alerter = new telegram_js_1.TelegramAlerter(makeConfig());
44
+ const result = { ok: true, severity: 'info', event_type: 'gateway_running', message: 'All good' };
45
+ const msg = alerter.formatMessage({ watcher: 'GatewayWatcher', result });
46
+ strict_1.default.ok(msg.includes('🟢'));
47
+ });
48
+ (0, node_test_1.it)('formatMessage uses 🟡 for warning', () => {
49
+ const alerter = new telegram_js_1.TelegramAlerter(makeConfig());
50
+ const result = { ok: false, severity: 'warning', event_type: 'cron_overdue', message: 'Cron overdue' };
51
+ const msg = alerter.formatMessage({ watcher: 'CronWatcher', result });
52
+ strict_1.default.ok(msg.includes('🟡'));
53
+ });
54
+ (0, node_test_1.it)('formatMessage includes heal result when provided', () => {
55
+ const alerter = new telegram_js_1.TelegramAlerter(makeConfig());
56
+ const result = { ok: false, severity: 'critical', event_type: 'gateway_down', message: 'Down' };
57
+ const msg = alerter.formatMessage({
58
+ watcher: 'GatewayWatcher',
59
+ result,
60
+ healResult: { success: true, action: 'openclaw gateway restart', message: 'Back online' },
61
+ });
62
+ strict_1.default.ok(msg.includes('openclaw gateway restart'));
63
+ strict_1.default.ok(msg.includes('Back online'));
64
+ });
65
+ (0, node_test_1.it)('formatMessage includes time and host', () => {
66
+ const alerter = new telegram_js_1.TelegramAlerter(makeConfig());
67
+ const result = { ok: false, severity: 'error', event_type: 'err', message: 'Err' };
68
+ const msg = alerter.formatMessage({ watcher: 'TestWatcher', result });
69
+ strict_1.default.ok(msg.includes('UTC'));
70
+ });
71
+ (0, node_test_1.it)('shouldAlert returns true for error/critical/warning', () => {
72
+ const alerter = new telegram_js_1.TelegramAlerter(makeConfig());
73
+ for (const severity of ['warning', 'error', 'critical']) {
74
+ const result = { ok: false, severity, event_type: 'test', message: 'test' };
75
+ strict_1.default.equal(alerter.shouldAlert(result), true);
76
+ }
77
+ });
78
+ (0, node_test_1.it)('shouldAlert returns false for info', () => {
79
+ const alerter = new telegram_js_1.TelegramAlerter(makeConfig());
80
+ const result = { ok: true, severity: 'info', event_type: 'ok', message: 'ok' };
81
+ strict_1.default.equal(alerter.shouldAlert(result), false);
82
+ });
83
+ (0, node_test_1.it)('rate limiting prevents duplicate alerts within 5 minutes', async () => {
84
+ // We test the rate-limit logic indirectly by checking lastAlertTime tracking
85
+ const alerter = new telegram_js_1.TelegramAlerter(makeConfig({ enabled: false })); // disabled so no real HTTP
86
+ // Access private field via cast for testing
87
+ const alerterAny = alerter;
88
+ strict_1.default.equal(alerterAny.isRateLimited('GatewayWatcher'), false);
89
+ alerterAny.markAlerted('GatewayWatcher');
90
+ strict_1.default.equal(alerterAny.isRateLimited('GatewayWatcher'), true);
91
+ });
92
+ (0, node_test_1.it)('sendAlert returns false when telegram is disabled', async () => {
93
+ const config = makeConfig({ enabled: false });
94
+ const alerter = new telegram_js_1.TelegramAlerter(config);
95
+ const result = { ok: false, severity: 'critical', event_type: 'down', message: 'Down' };
96
+ const sent = await alerter.sendAlert({ watcher: 'GatewayWatcher', result });
97
+ strict_1.default.equal(sent, false);
98
+ });
99
+ (0, node_test_1.it)('sendAlert returns false when botToken is empty', async () => {
100
+ const config = makeConfig({ enabled: true, botToken: '', chatId: '123' });
101
+ const alerter = new telegram_js_1.TelegramAlerter(config);
102
+ const result = { ok: false, severity: 'critical', event_type: 'down', message: 'Down' };
103
+ const sent = await alerter.sendAlert({ watcher: 'GatewayWatcher', result });
104
+ strict_1.default.equal(sent, false);
105
+ });
106
+ });
107
+ //# sourceMappingURL=telegram.test.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"telegram.test.js","sourceRoot":"","sources":["../../src/test/telegram.test.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,2 @@
1
+ export {};
2
+ //# sourceMappingURL=watchers.test.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"watchers.test.d.ts","sourceRoot":"","sources":["../../src/test/watchers.test.ts"],"names":[],"mappings":""}
@@ -0,0 +1,194 @@
1
+ "use strict";
2
+ var __importDefault = (this && this.__importDefault) || function (mod) {
3
+ return (mod && mod.__esModule) ? mod : { "default": mod };
4
+ };
5
+ Object.defineProperty(exports, "__esModule", { value: true });
6
+ const node_test_1 = require("node:test");
7
+ const strict_1 = __importDefault(require("node:assert/strict"));
8
+ const fs_1 = __importDefault(require("fs"));
9
+ const path_1 = __importDefault(require("path"));
10
+ const os_1 = __importDefault(require("os"));
11
+ const config_js_1 = require("../config.js");
12
+ const gateway_js_1 = require("../watchers/gateway.js");
13
+ const cron_js_1 = require("../watchers/cron.js");
14
+ const session_js_1 = require("../watchers/session.js");
15
+ const cost_js_1 = require("../watchers/cost.js");
16
+ const tmpDir = fs_1.default.mkdtempSync(path_1.default.join(os_1.default.tmpdir(), 'clawdoctor-watchers-test-'));
17
+ function makeConfig(openclawPath = tmpDir) {
18
+ return { ...config_js_1.DEFAULT_CONFIG, openclawPath };
19
+ }
20
+ (0, node_test_1.describe)('GatewayWatcher', () => {
21
+ (0, node_test_1.it)('returns a WatchResult array', async () => {
22
+ const watcher = new gateway_js_1.GatewayWatcher(makeConfig());
23
+ const results = await watcher.check();
24
+ strict_1.default.ok(Array.isArray(results));
25
+ strict_1.default.ok(results.length >= 1);
26
+ strict_1.default.ok('ok' in results[0]);
27
+ strict_1.default.ok('severity' in results[0]);
28
+ strict_1.default.ok('message' in results[0]);
29
+ });
30
+ (0, node_test_1.it)('result severity is valid', async () => {
31
+ const watcher = new gateway_js_1.GatewayWatcher(makeConfig());
32
+ const results = await watcher.check();
33
+ const validSeverities = ['info', 'warning', 'error', 'critical'];
34
+ for (const result of results) {
35
+ strict_1.default.ok(validSeverities.includes(result.severity), `Invalid severity: ${result.severity}`);
36
+ }
37
+ });
38
+ });
39
+ (0, node_test_1.describe)('CronWatcher', () => {
40
+ (0, node_test_1.before)(() => {
41
+ fs_1.default.mkdirSync(path_1.default.join(tmpDir, 'cron'), { recursive: true });
42
+ });
43
+ (0, node_test_1.it)('returns ok when no cron files exist', async () => {
44
+ const watcher = new cron_js_1.CronWatcher(makeConfig());
45
+ const results = await watcher.check();
46
+ strict_1.default.ok(results.length >= 1);
47
+ strict_1.default.ok(results.some(r => r.event_type === 'cron_no_file' || r.event_type === 'cron_none_enabled' || r.ok));
48
+ });
49
+ (0, node_test_1.it)('detects cron error state', async () => {
50
+ const jobsFile = path_1.default.join(tmpDir, 'cron', 'jobs.json');
51
+ fs_1.default.writeFileSync(jobsFile, JSON.stringify({
52
+ version: 1,
53
+ jobs: [{
54
+ id: 'test-1',
55
+ name: 'test-cron',
56
+ enabled: true,
57
+ schedule: { kind: 'cron', expr: '* * * * *' },
58
+ state: {
59
+ lastRunAtMs: Date.now(),
60
+ lastRunStatus: 'error',
61
+ consecutiveErrors: 3,
62
+ },
63
+ }],
64
+ }));
65
+ const watcher = new cron_js_1.CronWatcher(makeConfig());
66
+ const results = await watcher.check();
67
+ const errorResult = results.find(r => r.event_type === 'cron_consecutive_errors');
68
+ strict_1.default.ok(errorResult, `Expected cron_consecutive_errors, got: ${results.map(r => r.event_type).join(', ')}`);
69
+ strict_1.default.equal(errorResult.severity, 'error');
70
+ fs_1.default.unlinkSync(jobsFile);
71
+ });
72
+ (0, node_test_1.it)('detects overdue cron', async () => {
73
+ const jobsFile = path_1.default.join(tmpDir, 'cron', 'jobs.json');
74
+ const twoHoursAgo = Date.now() - 2 * 3600 * 1000;
75
+ fs_1.default.writeFileSync(jobsFile, JSON.stringify({
76
+ version: 1,
77
+ jobs: [{
78
+ id: 'test-2',
79
+ name: 'overdue-cron',
80
+ enabled: true,
81
+ schedule: { kind: 'cron', expr: '*/5 * * * *' },
82
+ state: {
83
+ nextRunAtMs: twoHoursAgo,
84
+ lastRunAtMs: twoHoursAgo - 300000,
85
+ lastRunStatus: 'ok',
86
+ consecutiveErrors: 0,
87
+ },
88
+ }],
89
+ }));
90
+ const watcher = new cron_js_1.CronWatcher(makeConfig());
91
+ const results = await watcher.check();
92
+ const overdueResult = results.find(r => r.event_type === 'cron_overdue');
93
+ strict_1.default.ok(overdueResult, `Expected cron_overdue, got: ${results.map(r => r.event_type).join(', ')}`);
94
+ fs_1.default.unlinkSync(jobsFile);
95
+ });
96
+ (0, node_test_1.it)('passes healthy cron', async () => {
97
+ const jobsFile = path_1.default.join(tmpDir, 'cron', 'jobs.json');
98
+ fs_1.default.writeFileSync(jobsFile, JSON.stringify({
99
+ version: 1,
100
+ jobs: [{
101
+ id: 'test-3',
102
+ name: 'healthy-cron',
103
+ enabled: true,
104
+ schedule: { kind: 'cron', expr: '0 * * * *' },
105
+ state: {
106
+ nextRunAtMs: Date.now() + 3600000,
107
+ lastRunAtMs: Date.now() - 1800000,
108
+ lastRunStatus: 'ok',
109
+ consecutiveErrors: 0,
110
+ lastDeliveryStatus: 'delivered',
111
+ },
112
+ }],
113
+ }));
114
+ const watcher = new cron_js_1.CronWatcher(makeConfig());
115
+ const results = await watcher.check();
116
+ const okResult = results.find(r => r.event_type === 'cron_all_ok');
117
+ strict_1.default.ok(okResult, `Expected cron_all_ok, got: ${results.map(r => r.event_type + ':' + r.message).join(', ')}`);
118
+ fs_1.default.unlinkSync(jobsFile);
119
+ });
120
+ });
121
+ (0, node_test_1.describe)('SessionWatcher', () => {
122
+ (0, node_test_1.before)(() => {
123
+ fs_1.default.mkdirSync(path_1.default.join(tmpDir, 'agents', 'test-agent', 'sessions'), { recursive: true });
124
+ });
125
+ (0, node_test_1.it)('returns ok when no recent sessions', async () => {
126
+ const watcher = new session_js_1.SessionWatcher(makeConfig());
127
+ const results = await watcher.check();
128
+ strict_1.default.ok(results.length >= 1);
129
+ strict_1.default.ok(results.some(r => r.ok));
130
+ });
131
+ (0, node_test_1.it)('detects session errors', async () => {
132
+ const sessionFile = path_1.default.join(tmpDir, 'agents', 'test-agent', 'sessions', 'session-err.jsonl');
133
+ const entries = [
134
+ { type: 'start', timestamp: new Date().toISOString() },
135
+ { type: 'error', error: 'API rate limit exceeded', timestamp: new Date().toISOString() },
136
+ ];
137
+ fs_1.default.writeFileSync(sessionFile, entries.map(e => JSON.stringify(e)).join('\n'));
138
+ const watcher = new session_js_1.SessionWatcher(makeConfig());
139
+ const results = await watcher.check();
140
+ const errorResult = results.find(r => r.event_type === 'session_error');
141
+ strict_1.default.ok(errorResult, `Expected session_error, got: ${results.map(r => r.event_type).join(', ')}`);
142
+ fs_1.default.unlinkSync(sessionFile);
143
+ });
144
+ (0, node_test_1.it)('detects aborted sessions', async () => {
145
+ const sessionFile = path_1.default.join(tmpDir, 'agents', 'test-agent', 'sessions', 'session-abort.jsonl');
146
+ const entries = [
147
+ { type: 'start', timestamp: new Date().toISOString() },
148
+ { status: 'aborted', timestamp: new Date().toISOString() },
149
+ ];
150
+ fs_1.default.writeFileSync(sessionFile, entries.map(e => JSON.stringify(e)).join('\n'));
151
+ const watcher = new session_js_1.SessionWatcher(makeConfig());
152
+ const results = await watcher.check();
153
+ const abortResult = results.find(r => r.event_type === 'session_aborted');
154
+ strict_1.default.ok(abortResult, `Expected session_aborted, got: ${results.map(r => r.event_type).join(', ')}`);
155
+ fs_1.default.unlinkSync(sessionFile);
156
+ });
157
+ });
158
+ (0, node_test_1.describe)('CostWatcher', () => {
159
+ (0, node_test_1.before)(() => {
160
+ fs_1.default.mkdirSync(path_1.default.join(tmpDir, 'agents', 'cost-agent', 'sessions'), { recursive: true });
161
+ });
162
+ (0, node_test_1.it)('returns ok with no sessions', async () => {
163
+ const watcher = new cost_js_1.CostWatcher(makeConfig());
164
+ const results = await watcher.check();
165
+ strict_1.default.ok(results.length >= 1);
166
+ strict_1.default.ok(results.some(r => r.ok));
167
+ });
168
+ (0, node_test_1.it)('detects cost anomaly', async () => {
169
+ const sessionsDir = path_1.default.join(tmpDir, 'agents', 'cost-agent', 'sessions');
170
+ // Create 5 cheap historical sessions (mtime well in the past)
171
+ for (let i = 0; i < 5; i++) {
172
+ const file = path_1.default.join(sessionsDir, `session-cheap-${i}.jsonl`);
173
+ const entry = { usage: { input_tokens: 100, output_tokens: 50, cost_usd: 0.001 } };
174
+ fs_1.default.writeFileSync(file, JSON.stringify(entry));
175
+ // Backdate mtime to 2 hours ago
176
+ const t = new Date(Date.now() - 2 * 3600 * 1000);
177
+ fs_1.default.utimesSync(file, t, t);
178
+ }
179
+ // Create one very expensive recent session
180
+ const expensiveFile = path_1.default.join(sessionsDir, 'session-expensive.jsonl');
181
+ fs_1.default.writeFileSync(expensiveFile, JSON.stringify({ usage: { cost_usd: 10.0 } }));
182
+ // Leave mtime as now (recent)
183
+ const watcher = new cost_js_1.CostWatcher(makeConfig());
184
+ const results = await watcher.check();
185
+ const anomaly = results.find(r => r.event_type === 'cost_anomaly');
186
+ strict_1.default.ok(anomaly, `Expected cost_anomaly, got: ${results.map(r => r.event_type + ':' + r.message).join(', ')}`);
187
+ // Cleanup
188
+ fs_1.default.readdirSync(sessionsDir).forEach(f => fs_1.default.unlinkSync(path_1.default.join(sessionsDir, f)));
189
+ });
190
+ });
191
+ (0, node_test_1.after)(() => {
192
+ fs_1.default.rmSync(tmpDir, { recursive: true, force: true });
193
+ });
194
+ //# sourceMappingURL=watchers.test.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"watchers.test.js","sourceRoot":"","sources":["../../src/test/watchers.test.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,18 @@
1
+ export declare function nowIso(): string;
2
+ export declare function nowUtcDisplay(): string;
3
+ export declare function hostname(): string;
4
+ export declare function runCommand(cmd: string, args?: string[]): {
5
+ stdout: string;
6
+ stderr: string;
7
+ status: number;
8
+ };
9
+ export declare function runShell(cmd: string): {
10
+ stdout: string;
11
+ stderr: string;
12
+ ok: boolean;
13
+ };
14
+ export declare function fileAgeSeconds(mtime: Date): number;
15
+ export declare function sleep(ms: number): Promise<void>;
16
+ export declare function formatBytes(bytes: number): string;
17
+ export declare function truncate(str: string, maxLen: number): string;
18
+ //# sourceMappingURL=utils.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"utils.d.ts","sourceRoot":"","sources":["../src/utils.ts"],"names":[],"mappings":"AAGA,wBAAgB,MAAM,IAAI,MAAM,CAE/B;AAED,wBAAgB,aAAa,IAAI,MAAM,CAEtC;AAED,wBAAgB,QAAQ,IAAI,MAAM,CAEjC;AAED,wBAAgB,UAAU,CAAC,GAAG,EAAE,MAAM,EAAE,IAAI,GAAE,MAAM,EAAO,GAAG;IAAE,MAAM,EAAE,MAAM,CAAC;IAAC,MAAM,EAAE,MAAM,CAAC;IAAC,MAAM,EAAE,MAAM,CAAA;CAAE,CAO/G;AAED,wBAAgB,QAAQ,CAAC,GAAG,EAAE,MAAM,GAAG;IAAE,MAAM,EAAE,MAAM,CAAC;IAAC,MAAM,EAAE,MAAM,CAAC;IAAC,EAAE,EAAE,OAAO,CAAA;CAAE,CAQrF;AAED,wBAAgB,cAAc,CAAC,KAAK,EAAE,IAAI,GAAG,MAAM,CAElD;AAED,wBAAgB,KAAK,CAAC,EAAE,EAAE,MAAM,GAAG,OAAO,CAAC,IAAI,CAAC,CAE/C;AAED,wBAAgB,WAAW,CAAC,KAAK,EAAE,MAAM,GAAG,MAAM,CAIjD;AAED,wBAAgB,QAAQ,CAAC,GAAG,EAAE,MAAM,EAAE,MAAM,EAAE,MAAM,GAAG,MAAM,CAG5D"}
package/dist/utils.js ADDED
@@ -0,0 +1,62 @@
1
+ "use strict";
2
+ var __importDefault = (this && this.__importDefault) || function (mod) {
3
+ return (mod && mod.__esModule) ? mod : { "default": mod };
4
+ };
5
+ Object.defineProperty(exports, "__esModule", { value: true });
6
+ exports.nowIso = nowIso;
7
+ exports.nowUtcDisplay = nowUtcDisplay;
8
+ exports.hostname = hostname;
9
+ exports.runCommand = runCommand;
10
+ exports.runShell = runShell;
11
+ exports.fileAgeSeconds = fileAgeSeconds;
12
+ exports.sleep = sleep;
13
+ exports.formatBytes = formatBytes;
14
+ exports.truncate = truncate;
15
+ const child_process_1 = require("child_process");
16
+ const os_1 = __importDefault(require("os"));
17
+ function nowIso() {
18
+ return new Date().toISOString();
19
+ }
20
+ function nowUtcDisplay() {
21
+ return new Date().toISOString().replace('T', ' ').slice(0, 16) + ' UTC';
22
+ }
23
+ function hostname() {
24
+ return os_1.default.hostname();
25
+ }
26
+ function runCommand(cmd, args = []) {
27
+ const result = (0, child_process_1.spawnSync)(cmd, args, { encoding: 'utf-8', timeout: 15000 });
28
+ return {
29
+ stdout: result.stdout ?? '',
30
+ stderr: result.stderr ?? '',
31
+ status: result.status ?? -1,
32
+ };
33
+ }
34
+ function runShell(cmd) {
35
+ try {
36
+ const stdout = (0, child_process_1.execSync)(cmd, { encoding: 'utf-8', timeout: 15000, stdio: ['pipe', 'pipe', 'pipe'] });
37
+ return { stdout, stderr: '', ok: true };
38
+ }
39
+ catch (err) {
40
+ const e = err;
41
+ return { stdout: e.stdout ?? '', stderr: e.stderr ?? '', ok: false };
42
+ }
43
+ }
44
+ function fileAgeSeconds(mtime) {
45
+ return (Date.now() - mtime.getTime()) / 1000;
46
+ }
47
+ function sleep(ms) {
48
+ return new Promise(resolve => setTimeout(resolve, ms));
49
+ }
50
+ function formatBytes(bytes) {
51
+ if (bytes < 1024)
52
+ return `${bytes}B`;
53
+ if (bytes < 1024 * 1024)
54
+ return `${(bytes / 1024).toFixed(1)}KB`;
55
+ return `${(bytes / (1024 * 1024)).toFixed(1)}MB`;
56
+ }
57
+ function truncate(str, maxLen) {
58
+ if (str.length <= maxLen)
59
+ return str;
60
+ return str.slice(0, maxLen - 3) + '...';
61
+ }
62
+ //# sourceMappingURL=utils.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"utils.js","sourceRoot":"","sources":["../src/utils.ts"],"names":[],"mappings":";;;;;AAGA,wBAEC;AAED,sCAEC;AAED,4BAEC;AAED,gCAOC;AAED,4BAQC;AAED,wCAEC;AAED,sBAEC;AAED,kCAIC;AAED,4BAGC;AAnDD,iDAAoD;AACpD,4CAAoB;AAEpB,SAAgB,MAAM;IACpB,OAAO,IAAI,IAAI,EAAE,CAAC,WAAW,EAAE,CAAC;AAClC,CAAC;AAED,SAAgB,aAAa;IAC3B,OAAO,IAAI,IAAI,EAAE,CAAC,WAAW,EAAE,CAAC,OAAO,CAAC,GAAG,EAAE,GAAG,CAAC,CAAC,KAAK,CAAC,CAAC,EAAE,EAAE,CAAC,GAAG,MAAM,CAAC;AAC1E,CAAC;AAED,SAAgB,QAAQ;IACtB,OAAO,YAAE,CAAC,QAAQ,EAAE,CAAC;AACvB,CAAC;AAED,SAAgB,UAAU,CAAC,GAAW,EAAE,OAAiB,EAAE;IACzD,MAAM,MAAM,GAAG,IAAA,yBAAS,EAAC,GAAG,EAAE,IAAI,EAAE,EAAE,QAAQ,EAAE,OAAO,EAAE,OAAO,EAAE,KAAK,EAAE,CAAC,CAAC;IAC3E,OAAO;QACL,MAAM,EAAE,MAAM,CAAC,MAAM,IAAI,EAAE;QAC3B,MAAM,EAAE,MAAM,CAAC,MAAM,IAAI,EAAE;QAC3B,MAAM,EAAE,MAAM,CAAC,MAAM,IAAI,CAAC,CAAC;KAC5B,CAAC;AACJ,CAAC;AAED,SAAgB,QAAQ,CAAC,GAAW;IAClC,IAAI,CAAC;QACH,MAAM,MAAM,GAAG,IAAA,wBAAQ,EAAC,GAAG,EAAE,EAAE,QAAQ,EAAE,OAAO,EAAE,OAAO,EAAE,KAAK,EAAE,KAAK,EAAE,CAAC,MAAM,EAAE,MAAM,EAAE,MAAM,CAAC,EAAE,CAAC,CAAC;QACrG,OAAO,EAAE,MAAM,EAAE,MAAM,EAAE,EAAE,EAAE,EAAE,EAAE,IAAI,EAAE,CAAC;IAC1C,CAAC;IAAC,OAAO,GAAY,EAAE,CAAC;QACtB,MAAM,CAAC,GAAG,GAA2C,CAAC;QACtD,OAAO,EAAE,MAAM,EAAE,CAAC,CAAC,MAAM,IAAI,EAAE,EAAE,MAAM,EAAE,CAAC,CAAC,MAAM,IAAI,EAAE,EAAE,EAAE,EAAE,KAAK,EAAE,CAAC;IACvE,CAAC;AACH,CAAC;AAED,SAAgB,cAAc,CAAC,KAAW;IACxC,OAAO,CAAC,IAAI,CAAC,GAAG,EAAE,GAAG,KAAK,CAAC,OAAO,EAAE,CAAC,GAAG,IAAI,CAAC;AAC/C,CAAC;AAED,SAAgB,KAAK,CAAC,EAAU;IAC9B,OAAO,IAAI,OAAO,CAAC,OAAO,CAAC,EAAE,CAAC,UAAU,CAAC,OAAO,EAAE,EAAE,CAAC,CAAC,CAAC;AACzD,CAAC;AAED,SAAgB,WAAW,CAAC,KAAa;IACvC,IAAI,KAAK,GAAG,IAAI;QAAE,OAAO,GAAG,KAAK,GAAG,CAAC;IACrC,IAAI,KAAK,GAAG,IAAI,GAAG,IAAI;QAAE,OAAO,GAAG,CAAC,KAAK,GAAG,IAAI,CAAC,CAAC,OAAO,CAAC,CAAC,CAAC,IAAI,CAAC;IACjE,OAAO,GAAG,CAAC,KAAK,GAAG,CAAC,IAAI,GAAG,IAAI,CAAC,CAAC,CAAC,OAAO,CAAC,CAAC,CAAC,IAAI,CAAC;AACnD,CAAC;AAED,SAAgB,QAAQ,CAAC,GAAW,EAAE,MAAc;IAClD,IAAI,GAAG,CAAC,MAAM,IAAI,MAAM;QAAE,OAAO,GAAG,CAAC;IACrC,OAAO,GAAG,CAAC,KAAK,CAAC,CAAC,EAAE,MAAM,GAAG,CAAC,CAAC,GAAG,KAAK,CAAC;AAC1C,CAAC"}
@@ -0,0 +1,10 @@
1
+ import { BaseWatcher, WatchResult } from './base.js';
2
+ export declare class AuthWatcher extends BaseWatcher {
3
+ readonly name = "AuthWatcher";
4
+ readonly defaultInterval = 60;
5
+ check(): Promise<WatchResult[]>;
6
+ private readJournalLogs;
7
+ private readLogFiles;
8
+ private analyzeLines;
9
+ }
10
+ //# sourceMappingURL=auth.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"auth.d.ts","sourceRoot":"","sources":["../../src/watchers/auth.ts"],"names":[],"mappings":"AACA,OAAO,EAAE,WAAW,EAAE,WAAW,EAAE,MAAM,WAAW,CAAC;AAerD,qBAAa,WAAY,SAAQ,WAAW;IAC1C,QAAQ,CAAC,IAAI,iBAAiB;IAC9B,QAAQ,CAAC,eAAe,MAAM;IAExB,KAAK,IAAI,OAAO,CAAC,WAAW,EAAE,CAAC;IAmBrC,OAAO,CAAC,eAAe;IAYvB,OAAO,CAAC,YAAY;IAoBpB,OAAO,CAAC,YAAY;CAqBrB"}
@@ -0,0 +1,79 @@
1
+ "use strict";
2
+ Object.defineProperty(exports, "__esModule", { value: true });
3
+ exports.AuthWatcher = void 0;
4
+ const child_process_1 = require("child_process");
5
+ const base_js_1 = require("./base.js");
6
+ const AUTH_PATTERNS = [
7
+ /401/,
8
+ /403/,
9
+ /token expired/i,
10
+ /auth failed/i,
11
+ /unauthorized/i,
12
+ /authentication error/i,
13
+ /invalid token/i,
14
+ /permission denied/i,
15
+ ];
16
+ const MAX_LOG_LINES = 200;
17
+ class AuthWatcher extends base_js_1.BaseWatcher {
18
+ name = 'AuthWatcher';
19
+ defaultInterval = 60;
20
+ async check() {
21
+ const results = [];
22
+ // Try to read from systemd journal
23
+ const journalLines = this.readJournalLogs();
24
+ if (journalLines !== null) {
25
+ return this.analyzeLines(journalLines, 'systemd journal');
26
+ }
27
+ // Try to find gateway log files
28
+ const logLines = this.readLogFiles();
29
+ if (logLines !== null) {
30
+ return this.analyzeLines(logLines, 'log file');
31
+ }
32
+ results.push(this.ok('No gateway logs accessible for auth check', 'auth_no_logs'));
33
+ return results;
34
+ }
35
+ readJournalLogs() {
36
+ try {
37
+ const output = (0, child_process_1.execSync)('journalctl -u openclaw-gateway --since "5 minutes ago" --no-pager -q 2>/dev/null', { encoding: 'utf-8', timeout: 5000 });
38
+ return output.split('\n').slice(-MAX_LOG_LINES);
39
+ }
40
+ catch {
41
+ return null;
42
+ }
43
+ }
44
+ readLogFiles() {
45
+ const logPaths = [
46
+ `${this.config.openclawPath}/logs/gateway.log`,
47
+ `${this.config.openclawPath}/gateway.log`,
48
+ ];
49
+ for (const logPath of logPaths) {
50
+ try {
51
+ const output = (0, child_process_1.execSync)(`tail -n ${MAX_LOG_LINES} "${logPath}" 2>/dev/null`, {
52
+ encoding: 'utf-8',
53
+ timeout: 3000,
54
+ });
55
+ return output.split('\n');
56
+ }
57
+ catch {
58
+ continue;
59
+ }
60
+ }
61
+ return null;
62
+ }
63
+ analyzeLines(lines, source) {
64
+ const matches = [];
65
+ for (const line of lines) {
66
+ if (AUTH_PATTERNS.some(pattern => pattern.test(line))) {
67
+ matches.push(line.trim());
68
+ }
69
+ }
70
+ if (matches.length === 0) {
71
+ return [this.ok(`No auth failures detected in ${source}`, 'auth_ok')];
72
+ }
73
+ return [
74
+ this.error(`${matches.length} auth failure(s) detected in ${source}`, 'auth_failure', { count: matches.length, samples: matches.slice(0, 3) }),
75
+ ];
76
+ }
77
+ }
78
+ exports.AuthWatcher = AuthWatcher;
79
+ //# sourceMappingURL=auth.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"auth.js","sourceRoot":"","sources":["../../src/watchers/auth.ts"],"names":[],"mappings":"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"}