clawatch 1.0.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/LICENSE ADDED
@@ -0,0 +1,21 @@
1
+ MIT License
2
+
3
+ Copyright (c) 2026 GENWAY AI
4
+
5
+ Permission is hereby granted, free of charge, to any person obtaining a copy
6
+ of this software and associated documentation files (the "Software"), to deal
7
+ in the Software without restriction, including without limitation the rights
8
+ to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
9
+ copies of the Software, and to permit persons to whom the Software is
10
+ furnished to do so, subject to the following conditions:
11
+
12
+ The above copyright notice and this permission notice shall be included in all
13
+ copies or substantial portions of the Software.
14
+
15
+ THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
16
+ IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
17
+ FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
18
+ AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
19
+ LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
20
+ OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
21
+ SOFTWARE.
package/README.md ADDED
@@ -0,0 +1,75 @@
1
+ # clawatch
2
+
3
+ > Observability & monitoring for AI agents. Datadog for your AI team.
4
+
5
+ **ClaWatch** tracks your [OpenClaw](https://openclaw.ai) agents in real-time — costs, tokens, sessions, errors — and alerts you when things go wrong.
6
+
7
+ ## Install
8
+
9
+ ```bash
10
+ npm install -g clawatch
11
+ ```
12
+
13
+ ## Quick Start
14
+
15
+ ```bash
16
+ # Detect agents and configure
17
+ clawatch init
18
+
19
+ # Start monitoring daemon
20
+ clawatch start
21
+
22
+ # Check status
23
+ clawatch status
24
+
25
+ # View logs
26
+ clawatch logs
27
+
28
+ # Stop monitoring
29
+ clawatch stop
30
+ ```
31
+
32
+ ## What It Monitors
33
+
34
+ - **Costs** — Per-agent, per-session, per-model cost tracking (USD)
35
+ - **Tokens** — Input, output, cache read/write breakdown
36
+ - **Sessions** — Active sessions with human-readable titles
37
+ - **Errors** — Tool failures, stuck agents, error spikes
38
+ - **Heartbeats** — Agent liveness detection
39
+
40
+ ## How It Works
41
+
42
+ ClaWatch runs a lightweight daemon that watches your `~/.openclaw` directory for new session data. It parses JSONL session files in real-time and reports metrics to the ClaWatch backend.
43
+
44
+ ```
45
+ ~/.openclaw/agents/*/sessions/*.jsonl → clawatch daemon → ClaWatch API → Dashboard + Alerts
46
+ ```
47
+
48
+ ## Configuration
49
+
50
+ Config is stored at `~/.clawatch/config.json`:
51
+
52
+ ```json
53
+ {
54
+ "backendUrl": "http://localhost:3001",
55
+ "openclawDir": "~/.openclaw",
56
+ "agents": ["anas", "dor", "ofek"]
57
+ }
58
+ ```
59
+
60
+ ## Dashboard
61
+
62
+ View your agents at [clawatch.dev](https://clawatch.dev) or run the dashboard locally.
63
+
64
+ ## Alerts
65
+
66
+ Get notified via Telegram when:
67
+ - An agent gets stuck (no heartbeat for 5+ minutes)
68
+ - Error rate spikes
69
+ - Cost exceeds threshold
70
+
71
+ More channels coming: Slack, Discord, email, PagerDuty.
72
+
73
+ ## License
74
+
75
+ MIT — [GENWAY AI](https://genway.ai)
package/dist/api.d.ts ADDED
@@ -0,0 +1,11 @@
1
+ export interface AgentEvent {
2
+ agentId: string;
3
+ agentName: string;
4
+ host: string;
5
+ type: 'heartbeat' | 'cost' | 'status_change' | 'error';
6
+ data?: Record<string, unknown>;
7
+ timestamp: string;
8
+ }
9
+ export declare function postEvent(backendUrl: string, event: AgentEvent): Promise<void>;
10
+ export declare function postEvents(backendUrl: string, events: AgentEvent[]): Promise<void[]>;
11
+ //# sourceMappingURL=api.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"api.d.ts","sourceRoot":"","sources":["../src/api.ts"],"names":[],"mappings":"AAIA,MAAM,WAAW,UAAU;IACzB,OAAO,EAAE,MAAM,CAAC;IAChB,SAAS,EAAE,MAAM,CAAC;IAClB,IAAI,EAAE,MAAM,CAAC;IACb,IAAI,EAAE,WAAW,GAAG,MAAM,GAAG,eAAe,GAAG,OAAO,CAAC;IACvD,IAAI,CAAC,EAAE,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,CAAC;IAC/B,SAAS,EAAE,MAAM,CAAC;CACnB;AAED,wBAAgB,SAAS,CAAC,UAAU,EAAE,MAAM,EAAE,KAAK,EAAE,UAAU,GAAG,OAAO,CAAC,IAAI,CAAC,CAqC9E;AAED,wBAAgB,UAAU,CAAC,UAAU,EAAE,MAAM,EAAE,MAAM,EAAE,UAAU,EAAE,GAAG,OAAO,CAAC,IAAI,EAAE,CAAC,CAEpF"}
package/dist/api.js ADDED
@@ -0,0 +1,77 @@
1
+ "use strict";
2
+ var __createBinding = (this && this.__createBinding) || (Object.create ? (function(o, m, k, k2) {
3
+ if (k2 === undefined) k2 = k;
4
+ var desc = Object.getOwnPropertyDescriptor(m, k);
5
+ if (!desc || ("get" in desc ? !m.__esModule : desc.writable || desc.configurable)) {
6
+ desc = { enumerable: true, get: function() { return m[k]; } };
7
+ }
8
+ Object.defineProperty(o, k2, desc);
9
+ }) : (function(o, m, k, k2) {
10
+ if (k2 === undefined) k2 = k;
11
+ o[k2] = m[k];
12
+ }));
13
+ var __setModuleDefault = (this && this.__setModuleDefault) || (Object.create ? (function(o, v) {
14
+ Object.defineProperty(o, "default", { enumerable: true, value: v });
15
+ }) : function(o, v) {
16
+ o["default"] = v;
17
+ });
18
+ var __importStar = (this && this.__importStar) || (function () {
19
+ var ownKeys = function(o) {
20
+ ownKeys = Object.getOwnPropertyNames || function (o) {
21
+ var ar = [];
22
+ for (var k in o) if (Object.prototype.hasOwnProperty.call(o, k)) ar[ar.length] = k;
23
+ return ar;
24
+ };
25
+ return ownKeys(o);
26
+ };
27
+ return function (mod) {
28
+ if (mod && mod.__esModule) return mod;
29
+ var result = {};
30
+ if (mod != null) for (var k = ownKeys(mod), i = 0; i < k.length; i++) if (k[i] !== "default") __createBinding(result, mod, k[i]);
31
+ __setModuleDefault(result, mod);
32
+ return result;
33
+ };
34
+ })();
35
+ Object.defineProperty(exports, "__esModule", { value: true });
36
+ exports.postEvent = postEvent;
37
+ exports.postEvents = postEvents;
38
+ const http = __importStar(require("http"));
39
+ const https = __importStar(require("https"));
40
+ const url_1 = require("url");
41
+ function postEvent(backendUrl, event) {
42
+ return new Promise((resolve, reject) => {
43
+ const url = new url_1.URL('/api/events', backendUrl);
44
+ const body = JSON.stringify(event);
45
+ const mod = url.protocol === 'https:' ? https : http;
46
+ const req = mod.request(url, {
47
+ method: 'POST',
48
+ headers: {
49
+ 'Content-Type': 'application/json',
50
+ 'Content-Length': Buffer.byteLength(body),
51
+ },
52
+ timeout: 10000,
53
+ }, (res) => {
54
+ let data = '';
55
+ res.on('data', (chunk) => (data += chunk));
56
+ res.on('end', () => {
57
+ if (res.statusCode && res.statusCode >= 200 && res.statusCode < 300) {
58
+ resolve();
59
+ }
60
+ else {
61
+ reject(new Error(`HTTP ${res.statusCode}: ${data}`));
62
+ }
63
+ });
64
+ });
65
+ req.on('error', reject);
66
+ req.on('timeout', () => {
67
+ req.destroy();
68
+ reject(new Error('Request timeout'));
69
+ });
70
+ req.write(body);
71
+ req.end();
72
+ });
73
+ }
74
+ function postEvents(backendUrl, events) {
75
+ return Promise.all(events.map((e) => postEvent(backendUrl, e)));
76
+ }
77
+ //# sourceMappingURL=api.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"api.js","sourceRoot":"","sources":["../src/api.ts"],"names":[],"mappings":";;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;AAaA,8BAqCC;AAED,gCAEC;AAtDD,2CAA6B;AAC7B,6CAA+B;AAC/B,6BAA0B;AAW1B,SAAgB,SAAS,CAAC,UAAkB,EAAE,KAAiB;IAC7D,OAAO,IAAI,OAAO,CAAC,CAAC,OAAO,EAAE,MAAM,EAAE,EAAE;QACrC,MAAM,GAAG,GAAG,IAAI,SAAG,CAAC,aAAa,EAAE,UAAU,CAAC,CAAC;QAC/C,MAAM,IAAI,GAAG,IAAI,CAAC,SAAS,CAAC,KAAK,CAAC,CAAC;QACnC,MAAM,GAAG,GAAG,GAAG,CAAC,QAAQ,KAAK,QAAQ,CAAC,CAAC,CAAC,KAAK,CAAC,CAAC,CAAC,IAAI,CAAC;QAErD,MAAM,GAAG,GAAG,GAAG,CAAC,OAAO,CACrB,GAAG,EACH;YACE,MAAM,EAAE,MAAM;YACd,OAAO,EAAE;gBACP,cAAc,EAAE,kBAAkB;gBAClC,gBAAgB,EAAE,MAAM,CAAC,UAAU,CAAC,IAAI,CAAC;aAC1C;YACD,OAAO,EAAE,KAAK;SACf,EACD,CAAC,GAAG,EAAE,EAAE;YACN,IAAI,IAAI,GAAG,EAAE,CAAC;YACd,GAAG,CAAC,EAAE,CAAC,MAAM,EAAE,CAAC,KAAK,EAAE,EAAE,CAAC,CAAC,IAAI,IAAI,KAAK,CAAC,CAAC,CAAC;YAC3C,GAAG,CAAC,EAAE,CAAC,KAAK,EAAE,GAAG,EAAE;gBACjB,IAAI,GAAG,CAAC,UAAU,IAAI,GAAG,CAAC,UAAU,IAAI,GAAG,IAAI,GAAG,CAAC,UAAU,GAAG,GAAG,EAAE,CAAC;oBACpE,OAAO,EAAE,CAAC;gBACZ,CAAC;qBAAM,CAAC;oBACN,MAAM,CAAC,IAAI,KAAK,CAAC,QAAQ,GAAG,CAAC,UAAU,KAAK,IAAI,EAAE,CAAC,CAAC,CAAC;gBACvD,CAAC;YACH,CAAC,CAAC,CAAC;QACL,CAAC,CACF,CAAC;QAEF,GAAG,CAAC,EAAE,CAAC,OAAO,EAAE,MAAM,CAAC,CAAC;QACxB,GAAG,CAAC,EAAE,CAAC,SAAS,EAAE,GAAG,EAAE;YACrB,GAAG,CAAC,OAAO,EAAE,CAAC;YACd,MAAM,CAAC,IAAI,KAAK,CAAC,iBAAiB,CAAC,CAAC,CAAC;QACvC,CAAC,CAAC,CAAC;QACH,GAAG,CAAC,KAAK,CAAC,IAAI,CAAC,CAAC;QAChB,GAAG,CAAC,GAAG,EAAE,CAAC;IACZ,CAAC,CAAC,CAAC;AACL,CAAC;AAED,SAAgB,UAAU,CAAC,UAAkB,EAAE,MAAoB;IACjE,OAAO,OAAO,CAAC,GAAG,CAAC,MAAM,CAAC,GAAG,CAAC,CAAC,CAAC,EAAE,EAAE,CAAC,SAAS,CAAC,UAAU,EAAE,CAAC,CAAC,CAAC,CAAC,CAAC;AAClE,CAAC"}
package/dist/cli.d.ts ADDED
@@ -0,0 +1,3 @@
1
+ #!/usr/bin/env node
2
+ export {};
3
+ //# sourceMappingURL=cli.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"cli.d.ts","sourceRoot":"","sources":["../src/cli.ts"],"names":[],"mappings":""}
package/dist/cli.js ADDED
@@ -0,0 +1,230 @@
1
+ #!/usr/bin/env node
2
+ "use strict";
3
+ var __createBinding = (this && this.__createBinding) || (Object.create ? (function(o, m, k, k2) {
4
+ if (k2 === undefined) k2 = k;
5
+ var desc = Object.getOwnPropertyDescriptor(m, k);
6
+ if (!desc || ("get" in desc ? !m.__esModule : desc.writable || desc.configurable)) {
7
+ desc = { enumerable: true, get: function() { return m[k]; } };
8
+ }
9
+ Object.defineProperty(o, k2, desc);
10
+ }) : (function(o, m, k, k2) {
11
+ if (k2 === undefined) k2 = k;
12
+ o[k2] = m[k];
13
+ }));
14
+ var __setModuleDefault = (this && this.__setModuleDefault) || (Object.create ? (function(o, v) {
15
+ Object.defineProperty(o, "default", { enumerable: true, value: v });
16
+ }) : function(o, v) {
17
+ o["default"] = v;
18
+ });
19
+ var __importStar = (this && this.__importStar) || (function () {
20
+ var ownKeys = function(o) {
21
+ ownKeys = Object.getOwnPropertyNames || function (o) {
22
+ var ar = [];
23
+ for (var k in o) if (Object.prototype.hasOwnProperty.call(o, k)) ar[ar.length] = k;
24
+ return ar;
25
+ };
26
+ return ownKeys(o);
27
+ };
28
+ return function (mod) {
29
+ if (mod && mod.__esModule) return mod;
30
+ var result = {};
31
+ if (mod != null) for (var k = ownKeys(mod), i = 0; i < k.length; i++) if (k[i] !== "default") __createBinding(result, mod, k[i]);
32
+ __setModuleDefault(result, mod);
33
+ return result;
34
+ };
35
+ })();
36
+ Object.defineProperty(exports, "__esModule", { value: true });
37
+ const commander_1 = require("commander");
38
+ const chalk = require("chalk");
39
+ const fs = __importStar(require("fs"));
40
+ const path = __importStar(require("path"));
41
+ const os = __importStar(require("os"));
42
+ const child_process_1 = require("child_process");
43
+ const config_1 = require("./config");
44
+ const program = new commander_1.Command();
45
+ program
46
+ .name('clawatch')
47
+ .description('ClaWatch CLI - Monitor OpenClaw agents')
48
+ .version('1.0.0');
49
+ program
50
+ .command('init')
51
+ .description('Initialize ClaWatch configuration')
52
+ .option('--backend <url>', 'Backend URL', 'http://localhost:3001')
53
+ .action((opts) => {
54
+ const openclawDir = path.join(os.homedir(), '.openclaw');
55
+ if (!fs.existsSync(openclawDir)) {
56
+ console.log(chalk.red(`OpenClaw directory not found: ${openclawDir}`));
57
+ process.exit(1);
58
+ }
59
+ const agentsDir = path.join(openclawDir, 'agents');
60
+ const agents = fs.existsSync(agentsDir)
61
+ ? fs.readdirSync(agentsDir).filter((name) => {
62
+ const sessionsDir = path.join(agentsDir, name, 'sessions');
63
+ return fs.existsSync(sessionsDir);
64
+ })
65
+ : [];
66
+ const config = {
67
+ openclawDir,
68
+ backendUrl: opts.backend,
69
+ apiKey: '',
70
+ scanIntervalMs: 60000,
71
+ };
72
+ (0, config_1.saveConfig)(config);
73
+ console.log(chalk.green('ClaWatch initialized!'));
74
+ console.log(` Config: ${config_1.paths.config}`);
75
+ console.log(` OpenClaw: ${openclawDir}`);
76
+ console.log(` Backend: ${config.backendUrl}`);
77
+ console.log(` Agents found: ${agents.length} (${agents.join(', ')})`);
78
+ });
79
+ program
80
+ .command('start')
81
+ .description('Start the ClaWatch daemon')
82
+ .action(() => {
83
+ (0, config_1.ensureDir)();
84
+ if (!(0, config_1.configExists)()) {
85
+ console.log(chalk.red('Not initialized. Run: clawatch init'));
86
+ process.exit(1);
87
+ }
88
+ // Check if already running
89
+ if (fs.existsSync(config_1.paths.pid)) {
90
+ const pid = parseInt(fs.readFileSync(config_1.paths.pid, 'utf-8').trim(), 10);
91
+ try {
92
+ process.kill(pid, 0);
93
+ console.log(chalk.yellow(`Daemon already running (PID: ${pid})`));
94
+ process.exit(0);
95
+ }
96
+ catch {
97
+ // PID stale, remove it
98
+ fs.unlinkSync(config_1.paths.pid);
99
+ }
100
+ }
101
+ const daemonPath = path.join(__dirname, 'daemon.js');
102
+ const child = (0, child_process_1.fork)(daemonPath, [], {
103
+ detached: true,
104
+ stdio: ['ignore', 'ignore', 'ignore', 'ipc'],
105
+ });
106
+ if (child.pid) {
107
+ fs.writeFileSync(config_1.paths.pid, String(child.pid));
108
+ child.unref();
109
+ child.disconnect();
110
+ console.log(chalk.green(`Daemon started (PID: ${child.pid})`));
111
+ console.log(` Logs: ${config_1.paths.log}`);
112
+ }
113
+ else {
114
+ console.log(chalk.red('Failed to start daemon'));
115
+ process.exit(1);
116
+ }
117
+ });
118
+ program
119
+ .command('stop')
120
+ .description('Stop the ClaWatch daemon')
121
+ .action(() => {
122
+ if (!fs.existsSync(config_1.paths.pid)) {
123
+ console.log(chalk.yellow('No daemon running'));
124
+ process.exit(0);
125
+ }
126
+ const pid = parseInt(fs.readFileSync(config_1.paths.pid, 'utf-8').trim(), 10);
127
+ try {
128
+ process.kill(pid, 'SIGTERM');
129
+ fs.unlinkSync(config_1.paths.pid);
130
+ console.log(chalk.green(`Daemon stopped (PID: ${pid})`));
131
+ }
132
+ catch {
133
+ fs.unlinkSync(config_1.paths.pid);
134
+ console.log(chalk.yellow('Daemon was not running (stale PID removed)'));
135
+ }
136
+ });
137
+ program
138
+ .command('status')
139
+ .description('Show ClaWatch status')
140
+ .action(() => {
141
+ if (!(0, config_1.configExists)()) {
142
+ console.log(chalk.red('Not initialized. Run: clawatch init'));
143
+ process.exit(1);
144
+ }
145
+ const config = (0, config_1.loadConfig)();
146
+ // Daemon status
147
+ let daemonRunning = false;
148
+ let daemonPid = 0;
149
+ if (fs.existsSync(config_1.paths.pid)) {
150
+ daemonPid = parseInt(fs.readFileSync(config_1.paths.pid, 'utf-8').trim(), 10);
151
+ try {
152
+ process.kill(daemonPid, 0);
153
+ daemonRunning = true;
154
+ }
155
+ catch {
156
+ daemonRunning = false;
157
+ }
158
+ }
159
+ // Agent stats
160
+ const agentsDir = path.join(config.openclawDir, 'agents');
161
+ let agentCount = 0;
162
+ let sessionCount = 0;
163
+ let latestEvent = '';
164
+ if (fs.existsSync(agentsDir)) {
165
+ const agents = fs.readdirSync(agentsDir).filter((name) => {
166
+ return fs.existsSync(path.join(agentsDir, name, 'sessions'));
167
+ });
168
+ agentCount = agents.length;
169
+ for (const agent of agents) {
170
+ const sessionsDir = path.join(agentsDir, agent, 'sessions');
171
+ const files = fs.readdirSync(sessionsDir).filter((f) => f.endsWith('.jsonl'));
172
+ sessionCount += files.length;
173
+ for (const file of files) {
174
+ const stat = fs.statSync(path.join(sessionsDir, file));
175
+ const mtime = stat.mtime.toISOString();
176
+ if (mtime > latestEvent)
177
+ latestEvent = mtime;
178
+ }
179
+ }
180
+ }
181
+ console.log(chalk.bold('ClaWatch Status'));
182
+ console.log('─'.repeat(40));
183
+ console.log(` Daemon: ${daemonRunning ? chalk.green(`running (PID: ${daemonPid})`) : chalk.red('stopped')}`);
184
+ console.log(` Backend: ${config.backendUrl}`);
185
+ console.log(` Agents: ${agentCount}`);
186
+ console.log(` Sessions: ${sessionCount}`);
187
+ console.log(` Last event: ${latestEvent || 'none'}`);
188
+ // Check backend connectivity
189
+ const http = require('http');
190
+ const url = new (require('url').URL)('/api/events', config.backendUrl);
191
+ let replied = false;
192
+ const req = http.get(url, { timeout: 3000 }, (res) => {
193
+ if (!replied) {
194
+ replied = true;
195
+ const ok = res.statusCode && res.statusCode < 500;
196
+ console.log(` Connection: ${ok ? chalk.green('ok') : chalk.yellow(`HTTP ${res.statusCode}`)}`);
197
+ }
198
+ res.resume();
199
+ });
200
+ req.on('error', () => {
201
+ if (!replied) {
202
+ replied = true;
203
+ console.log(` Connection: ${chalk.red('unreachable')}`);
204
+ }
205
+ });
206
+ req.on('timeout', () => {
207
+ if (!replied) {
208
+ replied = true;
209
+ req.destroy();
210
+ console.log(` Connection: ${chalk.red('timeout')}`);
211
+ }
212
+ });
213
+ });
214
+ program
215
+ .command('logs')
216
+ .description('Tail daemon logs')
217
+ .option('-n <lines>', 'Number of lines', '50')
218
+ .action((opts) => {
219
+ if (!fs.existsSync(config_1.paths.log)) {
220
+ console.log(chalk.yellow('No log file yet'));
221
+ process.exit(0);
222
+ }
223
+ const content = fs.readFileSync(config_1.paths.log, 'utf-8');
224
+ const lines = content.trim().split('\n');
225
+ const n = parseInt(opts.n || opts.N || '50', 10);
226
+ const tail = lines.slice(-n);
227
+ console.log(tail.join('\n'));
228
+ });
229
+ program.parse();
230
+ //# sourceMappingURL=cli.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"cli.js","sourceRoot":"","sources":["../src/cli.ts"],"names":[],"mappings":";;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;AAEA,yCAAoC;AACpC,+BAAgC;AAChC,uCAAyB;AACzB,2CAA6B;AAC7B,uCAAyB;AACzB,iDAAqC;AACrC,qCAAkG;AAElG,MAAM,OAAO,GAAG,IAAI,mBAAO,EAAE,CAAC;AAE9B,OAAO;KACJ,IAAI,CAAC,UAAU,CAAC;KAChB,WAAW,CAAC,wCAAwC,CAAC;KACrD,OAAO,CAAC,OAAO,CAAC,CAAC;AAEpB,OAAO;KACJ,OAAO,CAAC,MAAM,CAAC;KACf,WAAW,CAAC,mCAAmC,CAAC;KAChD,MAAM,CAAC,iBAAiB,EAAE,aAAa,EAAE,uBAAuB,CAAC;KACjE,MAAM,CAAC,CAAC,IAAI,EAAE,EAAE;IACf,MAAM,WAAW,GAAG,IAAI,CAAC,IAAI,CAAC,EAAE,CAAC,OAAO,EAAE,EAAE,WAAW,CAAC,CAAC;IAEzD,IAAI,CAAC,EAAE,CAAC,UAAU,CAAC,WAAW,CAAC,EAAE,CAAC;QAChC,OAAO,CAAC,GAAG,CAAC,KAAK,CAAC,GAAG,CAAC,iCAAiC,WAAW,EAAE,CAAC,CAAC,CAAC;QACvE,OAAO,CAAC,IAAI,CAAC,CAAC,CAAC,CAAC;IAClB,CAAC;IAED,MAAM,SAAS,GAAG,IAAI,CAAC,IAAI,CAAC,WAAW,EAAE,QAAQ,CAAC,CAAC;IACnD,MAAM,MAAM,GAAG,EAAE,CAAC,UAAU,CAAC,SAAS,CAAC;QACrC,CAAC,CAAC,EAAE,CAAC,WAAW,CAAC,SAAS,CAAC,CAAC,MAAM,CAAC,CAAC,IAAI,EAAE,EAAE;YACxC,MAAM,WAAW,GAAG,IAAI,CAAC,IAAI,CAAC,SAAS,EAAE,IAAI,EAAE,UAAU,CAAC,CAAC;YAC3D,OAAO,EAAE,CAAC,UAAU,CAAC,WAAW,CAAC,CAAC;QACpC,CAAC,CAAC;QACJ,CAAC,CAAC,EAAE,CAAC;IAEP,MAAM,MAAM,GAAmB;QAC7B,WAAW;QACX,UAAU,EAAE,IAAI,CAAC,OAAO;QACxB,MAAM,EAAE,EAAE;QACV,cAAc,EAAE,KAAK;KACtB,CAAC;IAEF,IAAA,mBAAU,EAAC,MAAM,CAAC,CAAC;IAEnB,OAAO,CAAC,GAAG,CAAC,KAAK,CAAC,KAAK,CAAC,uBAAuB,CAAC,CAAC,CAAC;IAClD,OAAO,CAAC,GAAG,CAAC,aAAa,cAAK,CAAC,MAAM,EAAE,CAAC,CAAC;IACzC,OAAO,CAAC,GAAG,CAAC,eAAe,WAAW,EAAE,CAAC,CAAC;IAC1C,OAAO,CAAC,GAAG,CAAC,cAAc,MAAM,CAAC,UAAU,EAAE,CAAC,CAAC;IAC/C,OAAO,CAAC,GAAG,CAAC,mBAAmB,MAAM,CAAC,MAAM,KAAK,MAAM,CAAC,IAAI,CAAC,IAAI,CAAC,GAAG,CAAC,CAAC;AACzE,CAAC,CAAC,CAAC;AAEL,OAAO;KACJ,OAAO,CAAC,OAAO,CAAC;KAChB,WAAW,CAAC,2BAA2B,CAAC;KACxC,MAAM,CAAC,GAAG,EAAE;IACX,IAAA,kBAAS,GAAE,CAAC;IAEZ,IAAI,CAAC,IAAA,qBAAY,GAAE,EAAE,CAAC;QACpB,OAAO,CAAC,GAAG,CAAC,KAAK,CAAC,GAAG,CAAC,qCAAqC,CAAC,CAAC,CAAC;QAC9D,OAAO,CAAC,IAAI,CAAC,CAAC,CAAC,CAAC;IAClB,CAAC;IAED,2BAA2B;IAC3B,IAAI,EAAE,CAAC,UAAU,CAAC,cAAK,CAAC,GAAG,CAAC,EAAE,CAAC;QAC7B,MAAM,GAAG,GAAG,QAAQ,CAAC,EAAE,CAAC,YAAY,CAAC,cAAK,CAAC,GAAG,EAAE,OAAO,CAAC,CAAC,IAAI,EAAE,EAAE,EAAE,CAAC,CAAC;QACrE,IAAI,CAAC;YACH,OAAO,CAAC,IAAI,CAAC,GAAG,EAAE,CAAC,CAAC,CAAC;YACrB,OAAO,CAAC,GAAG,CAAC,KAAK,CAAC,MAAM,CAAC,gCAAgC,GAAG,GAAG,CAAC,CAAC,CAAC;YAClE,OAAO,CAAC,IAAI,CAAC,CAAC,CAAC,CAAC;QAClB,CAAC;QAAC,MAAM,CAAC;YACP,uBAAuB;YACvB,EAAE,CAAC,UAAU,CAAC,cAAK,CAAC,GAAG,CAAC,CAAC;QAC3B,CAAC;IACH,CAAC;IAED,MAAM,UAAU,GAAG,IAAI,CAAC,IAAI,CAAC,SAAS,EAAE,WAAW,CAAC,CAAC;IACrD,MAAM,KAAK,GAAG,IAAA,oBAAI,EAAC,UAAU,EAAE,EAAE,EAAE;QACjC,QAAQ,EAAE,IAAI;QACd,KAAK,EAAE,CAAC,QAAQ,EAAE,QAAQ,EAAE,QAAQ,EAAE,KAAK,CAAC;KAC7C,CAAC,CAAC;IAEH,IAAI,KAAK,CAAC,GAAG,EAAE,CAAC;QACd,EAAE,CAAC,aAAa,CAAC,cAAK,CAAC,GAAG,EAAE,MAAM,CAAC,KAAK,CAAC,GAAG,CAAC,CAAC,CAAC;QAC/C,KAAK,CAAC,KAAK,EAAE,CAAC;QACd,KAAK,CAAC,UAAU,EAAE,CAAC;QACnB,OAAO,CAAC,GAAG,CAAC,KAAK,CAAC,KAAK,CAAC,wBAAwB,KAAK,CAAC,GAAG,GAAG,CAAC,CAAC,CAAC;QAC/D,OAAO,CAAC,GAAG,CAAC,WAAW,cAAK,CAAC,GAAG,EAAE,CAAC,CAAC;IACtC,CAAC;SAAM,CAAC;QACN,OAAO,CAAC,GAAG,CAAC,KAAK,CAAC,GAAG,CAAC,wBAAwB,CAAC,CAAC,CAAC;QACjD,OAAO,CAAC,IAAI,CAAC,CAAC,CAAC,CAAC;IAClB,CAAC;AACH,CAAC,CAAC,CAAC;AAEL,OAAO;KACJ,OAAO,CAAC,MAAM,CAAC;KACf,WAAW,CAAC,0BAA0B,CAAC;KACvC,MAAM,CAAC,GAAG,EAAE;IACX,IAAI,CAAC,EAAE,CAAC,UAAU,CAAC,cAAK,CAAC,GAAG,CAAC,EAAE,CAAC;QAC9B,OAAO,CAAC,GAAG,CAAC,KAAK,CAAC,MAAM,CAAC,mBAAmB,CAAC,CAAC,CAAC;QAC/C,OAAO,CAAC,IAAI,CAAC,CAAC,CAAC,CAAC;IAClB,CAAC;IAED,MAAM,GAAG,GAAG,QAAQ,CAAC,EAAE,CAAC,YAAY,CAAC,cAAK,CAAC,GAAG,EAAE,OAAO,CAAC,CAAC,IAAI,EAAE,EAAE,EAAE,CAAC,CAAC;IACrE,IAAI,CAAC;QACH,OAAO,CAAC,IAAI,CAAC,GAAG,EAAE,SAAS,CAAC,CAAC;QAC7B,EAAE,CAAC,UAAU,CAAC,cAAK,CAAC,GAAG,CAAC,CAAC;QACzB,OAAO,CAAC,GAAG,CAAC,KAAK,CAAC,KAAK,CAAC,wBAAwB,GAAG,GAAG,CAAC,CAAC,CAAC;IAC3D,CAAC;IAAC,MAAM,CAAC;QACP,EAAE,CAAC,UAAU,CAAC,cAAK,CAAC,GAAG,CAAC,CAAC;QACzB,OAAO,CAAC,GAAG,CAAC,KAAK,CAAC,MAAM,CAAC,4CAA4C,CAAC,CAAC,CAAC;IAC1E,CAAC;AACH,CAAC,CAAC,CAAC;AAEL,OAAO;KACJ,OAAO,CAAC,QAAQ,CAAC;KACjB,WAAW,CAAC,sBAAsB,CAAC;KACnC,MAAM,CAAC,GAAG,EAAE;IACX,IAAI,CAAC,IAAA,qBAAY,GAAE,EAAE,CAAC;QACpB,OAAO,CAAC,GAAG,CAAC,KAAK,CAAC,GAAG,CAAC,qCAAqC,CAAC,CAAC,CAAC;QAC9D,OAAO,CAAC,IAAI,CAAC,CAAC,CAAC,CAAC;IAClB,CAAC;IAED,MAAM,MAAM,GAAG,IAAA,mBAAU,GAAE,CAAC;IAE5B,gBAAgB;IAChB,IAAI,aAAa,GAAG,KAAK,CAAC;IAC1B,IAAI,SAAS,GAAG,CAAC,CAAC;IAClB,IAAI,EAAE,CAAC,UAAU,CAAC,cAAK,CAAC,GAAG,CAAC,EAAE,CAAC;QAC7B,SAAS,GAAG,QAAQ,CAAC,EAAE,CAAC,YAAY,CAAC,cAAK,CAAC,GAAG,EAAE,OAAO,CAAC,CAAC,IAAI,EAAE,EAAE,EAAE,CAAC,CAAC;QACrE,IAAI,CAAC;YACH,OAAO,CAAC,IAAI,CAAC,SAAS,EAAE,CAAC,CAAC,CAAC;YAC3B,aAAa,GAAG,IAAI,CAAC;QACvB,CAAC;QAAC,MAAM,CAAC;YACP,aAAa,GAAG,KAAK,CAAC;QACxB,CAAC;IACH,CAAC;IAED,cAAc;IACd,MAAM,SAAS,GAAG,IAAI,CAAC,IAAI,CAAC,MAAM,CAAC,WAAW,EAAE,QAAQ,CAAC,CAAC;IAC1D,IAAI,UAAU,GAAG,CAAC,CAAC;IACnB,IAAI,YAAY,GAAG,CAAC,CAAC;IACrB,IAAI,WAAW,GAAG,EAAE,CAAC;IAErB,IAAI,EAAE,CAAC,UAAU,CAAC,SAAS,CAAC,EAAE,CAAC;QAC7B,MAAM,MAAM,GAAG,EAAE,CAAC,WAAW,CAAC,SAAS,CAAC,CAAC,MAAM,CAAC,CAAC,IAAI,EAAE,EAAE;YACvD,OAAO,EAAE,CAAC,UAAU,CAAC,IAAI,CAAC,IAAI,CAAC,SAAS,EAAE,IAAI,EAAE,UAAU,CAAC,CAAC,CAAC;QAC/D,CAAC,CAAC,CAAC;QACH,UAAU,GAAG,MAAM,CAAC,MAAM,CAAC;QAE3B,KAAK,MAAM,KAAK,IAAI,MAAM,EAAE,CAAC;YAC3B,MAAM,WAAW,GAAG,IAAI,CAAC,IAAI,CAAC,SAAS,EAAE,KAAK,EAAE,UAAU,CAAC,CAAC;YAC5D,MAAM,KAAK,GAAG,EAAE,CAAC,WAAW,CAAC,WAAW,CAAC,CAAC,MAAM,CAAC,CAAC,CAAC,EAAE,EAAE,CAAC,CAAC,CAAC,QAAQ,CAAC,QAAQ,CAAC,CAAC,CAAC;YAC9E,YAAY,IAAI,KAAK,CAAC,MAAM,CAAC;YAE7B,KAAK,MAAM,IAAI,IAAI,KAAK,EAAE,CAAC;gBACzB,MAAM,IAAI,GAAG,EAAE,CAAC,QAAQ,CAAC,IAAI,CAAC,IAAI,CAAC,WAAW,EAAE,IAAI,CAAC,CAAC,CAAC;gBACvD,MAAM,KAAK,GAAG,IAAI,CAAC,KAAK,CAAC,WAAW,EAAE,CAAC;gBACvC,IAAI,KAAK,GAAG,WAAW;oBAAE,WAAW,GAAG,KAAK,CAAC;YAC/C,CAAC;QACH,CAAC;IACH,CAAC;IAED,OAAO,CAAC,GAAG,CAAC,KAAK,CAAC,IAAI,CAAC,iBAAiB,CAAC,CAAC,CAAC;IAC3C,OAAO,CAAC,GAAG,CAAC,GAAG,CAAC,MAAM,CAAC,EAAE,CAAC,CAAC,CAAC;IAC5B,OAAO,CAAC,GAAG,CAAC,kBAAkB,aAAa,CAAC,CAAC,CAAC,KAAK,CAAC,KAAK,CAAC,iBAAiB,SAAS,GAAG,CAAC,CAAC,CAAC,CAAC,KAAK,CAAC,GAAG,CAAC,SAAS,CAAC,EAAE,CAAC,CAAC;IACnH,OAAO,CAAC,GAAG,CAAC,kBAAkB,MAAM,CAAC,UAAU,EAAE,CAAC,CAAC;IACnD,OAAO,CAAC,GAAG,CAAC,kBAAkB,UAAU,EAAE,CAAC,CAAC;IAC5C,OAAO,CAAC,GAAG,CAAC,kBAAkB,YAAY,EAAE,CAAC,CAAC;IAC9C,OAAO,CAAC,GAAG,CAAC,kBAAkB,WAAW,IAAI,MAAM,EAAE,CAAC,CAAC;IAEvD,6BAA6B;IAC7B,MAAM,IAAI,GAAG,OAAO,CAAC,MAAM,CAAC,CAAC;IAC7B,MAAM,GAAG,GAAG,IAAI,CAAC,OAAO,CAAC,KAAK,CAAC,CAAC,GAAG,CAAC,CAAC,aAAa,EAAE,MAAM,CAAC,UAAU,CAAC,CAAC;IACvE,IAAI,OAAO,GAAG,KAAK,CAAC;IACpB,MAAM,GAAG,GAAG,IAAI,CAAC,GAAG,CAAC,GAAG,EAAE,EAAE,OAAO,EAAE,IAAI,EAAE,EAAE,CAAC,GAAQ,EAAE,EAAE;QACxD,IAAI,CAAC,OAAO,EAAE,CAAC;YACb,OAAO,GAAG,IAAI,CAAC;YACf,MAAM,EAAE,GAAG,GAAG,CAAC,UAAU,IAAI,GAAG,CAAC,UAAU,GAAG,GAAG,CAAC;YAClD,OAAO,CAAC,GAAG,CAAC,kBAAkB,EAAE,CAAC,CAAC,CAAC,KAAK,CAAC,KAAK,CAAC,IAAI,CAAC,CAAC,CAAC,CAAC,KAAK,CAAC,MAAM,CAAC,QAAQ,GAAG,CAAC,UAAU,EAAE,CAAC,EAAE,CAAC,CAAC;QACnG,CAAC;QACD,GAAG,CAAC,MAAM,EAAE,CAAC;IACf,CAAC,CAAC,CAAC;IACH,GAAG,CAAC,EAAE,CAAC,OAAO,EAAE,GAAG,EAAE;QACnB,IAAI,CAAC,OAAO,EAAE,CAAC;YACb,OAAO,GAAG,IAAI,CAAC;YACf,OAAO,CAAC,GAAG,CAAC,kBAAkB,KAAK,CAAC,GAAG,CAAC,aAAa,CAAC,EAAE,CAAC,CAAC;QAC5D,CAAC;IACH,CAAC,CAAC,CAAC;IACH,GAAG,CAAC,EAAE,CAAC,SAAS,EAAE,GAAG,EAAE;QACrB,IAAI,CAAC,OAAO,EAAE,CAAC;YACb,OAAO,GAAG,IAAI,CAAC;YACf,GAAG,CAAC,OAAO,EAAE,CAAC;YACd,OAAO,CAAC,GAAG,CAAC,kBAAkB,KAAK,CAAC,GAAG,CAAC,SAAS,CAAC,EAAE,CAAC,CAAC;QACxD,CAAC;IACH,CAAC,CAAC,CAAC;AACL,CAAC,CAAC,CAAC;AAEL,OAAO;KACJ,OAAO,CAAC,MAAM,CAAC;KACf,WAAW,CAAC,kBAAkB,CAAC;KAC/B,MAAM,CAAC,YAAY,EAAE,iBAAiB,EAAE,IAAI,CAAC;KAC7C,MAAM,CAAC,CAAC,IAAI,EAAE,EAAE;IACf,IAAI,CAAC,EAAE,CAAC,UAAU,CAAC,cAAK,CAAC,GAAG,CAAC,EAAE,CAAC;QAC9B,OAAO,CAAC,GAAG,CAAC,KAAK,CAAC,MAAM,CAAC,iBAAiB,CAAC,CAAC,CAAC;QAC7C,OAAO,CAAC,IAAI,CAAC,CAAC,CAAC,CAAC;IAClB,CAAC;IAED,MAAM,OAAO,GAAG,EAAE,CAAC,YAAY,CAAC,cAAK,CAAC,GAAG,EAAE,OAAO,CAAC,CAAC;IACpD,MAAM,KAAK,GAAG,OAAO,CAAC,IAAI,EAAE,CAAC,KAAK,CAAC,IAAI,CAAC,CAAC;IACzC,MAAM,CAAC,GAAG,QAAQ,CAAC,IAAI,CAAC,CAAC,IAAI,IAAI,CAAC,CAAC,IAAI,IAAI,EAAE,EAAE,CAAC,CAAC;IACjD,MAAM,IAAI,GAAG,KAAK,CAAC,KAAK,CAAC,CAAC,CAAC,CAAC,CAAC;IAC7B,OAAO,CAAC,GAAG,CAAC,IAAI,CAAC,IAAI,CAAC,IAAI,CAAC,CAAC,CAAC;AAC/B,CAAC,CAAC,CAAC;AAEL,OAAO,CAAC,KAAK,EAAE,CAAC"}
@@ -0,0 +1,4 @@
1
+ import { ClaWatchConfig } from './config';
2
+ export declare function startCollector(cfg: ClaWatchConfig): Promise<void>;
3
+ export declare function stopCollector(): void;
4
+ //# sourceMappingURL=collector.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"collector.d.ts","sourceRoot":"","sources":["../src/collector.ts"],"names":[],"mappings":"AAGA,OAAO,EAAE,cAAc,EAAS,MAAM,UAAU,CAAC;AAqNjD,wBAAsB,cAAc,CAAC,GAAG,EAAE,cAAc,GAAG,OAAO,CAAC,IAAI,CAAC,CAcvE;AAED,wBAAgB,aAAa,IAAI,IAAI,CAcpC"}
@@ -0,0 +1,249 @@
1
+ "use strict";
2
+ var __createBinding = (this && this.__createBinding) || (Object.create ? (function(o, m, k, k2) {
3
+ if (k2 === undefined) k2 = k;
4
+ var desc = Object.getOwnPropertyDescriptor(m, k);
5
+ if (!desc || ("get" in desc ? !m.__esModule : desc.writable || desc.configurable)) {
6
+ desc = { enumerable: true, get: function() { return m[k]; } };
7
+ }
8
+ Object.defineProperty(o, k2, desc);
9
+ }) : (function(o, m, k, k2) {
10
+ if (k2 === undefined) k2 = k;
11
+ o[k2] = m[k];
12
+ }));
13
+ var __setModuleDefault = (this && this.__setModuleDefault) || (Object.create ? (function(o, v) {
14
+ Object.defineProperty(o, "default", { enumerable: true, value: v });
15
+ }) : function(o, v) {
16
+ o["default"] = v;
17
+ });
18
+ var __importStar = (this && this.__importStar) || (function () {
19
+ var ownKeys = function(o) {
20
+ ownKeys = Object.getOwnPropertyNames || function (o) {
21
+ var ar = [];
22
+ for (var k in o) if (Object.prototype.hasOwnProperty.call(o, k)) ar[ar.length] = k;
23
+ return ar;
24
+ };
25
+ return ownKeys(o);
26
+ };
27
+ return function (mod) {
28
+ if (mod && mod.__esModule) return mod;
29
+ var result = {};
30
+ if (mod != null) for (var k = ownKeys(mod), i = 0; i < k.length; i++) if (k[i] !== "default") __createBinding(result, mod, k[i]);
31
+ __setModuleDefault(result, mod);
32
+ return result;
33
+ };
34
+ })();
35
+ Object.defineProperty(exports, "__esModule", { value: true });
36
+ exports.startCollector = startCollector;
37
+ exports.stopCollector = stopCollector;
38
+ const fs = __importStar(require("fs"));
39
+ const path = __importStar(require("path"));
40
+ const chokidar = __importStar(require("chokidar"));
41
+ const config_1 = require("./config");
42
+ const api_1 = require("./api");
43
+ const parser_1 = require("./parser");
44
+ let offsets = {};
45
+ let config;
46
+ let watcher = null;
47
+ let gatewayWatcher = null;
48
+ let heartbeatInterval = null;
49
+ let activeAgents = new Set();
50
+ function log(msg) {
51
+ const line = `[${new Date().toISOString()}] ${msg}\n`;
52
+ fs.appendFileSync(config_1.paths.log, line);
53
+ }
54
+ function loadOffsets() {
55
+ if (fs.existsSync(config_1.paths.offsets)) {
56
+ try {
57
+ offsets = JSON.parse(fs.readFileSync(config_1.paths.offsets, 'utf-8'));
58
+ }
59
+ catch {
60
+ offsets = {};
61
+ }
62
+ }
63
+ }
64
+ function saveOffsets() {
65
+ fs.writeFileSync(config_1.paths.offsets, JSON.stringify(offsets, null, 2));
66
+ }
67
+ function extractAgentId(filePath) {
68
+ // Path: .../agents/<agentId>/sessions/<file>.jsonl
69
+ const parts = filePath.split(path.sep);
70
+ const agentsIdx = parts.indexOf('agents');
71
+ if (agentsIdx >= 0 && agentsIdx + 1 < parts.length) {
72
+ return parts[agentsIdx + 1];
73
+ }
74
+ return null;
75
+ }
76
+ async function sendEvent(event) {
77
+ try {
78
+ await (0, api_1.postEvent)(config.backendUrl, event);
79
+ }
80
+ catch (err) {
81
+ const msg = err instanceof Error ? err.message : String(err);
82
+ log(`Failed to send event: ${msg}`);
83
+ }
84
+ }
85
+ async function processLines(lines, agentId) {
86
+ for (const line of lines) {
87
+ const event = (0, parser_1.parseLine)(line);
88
+ if (!event)
89
+ continue;
90
+ const apiEvents = (0, parser_1.mapEventToApiEvents)(event, agentId);
91
+ for (const apiEvent of apiEvents) {
92
+ await sendEvent(apiEvent);
93
+ }
94
+ }
95
+ }
96
+ async function readNewLines(filePath) {
97
+ const agentId = extractAgentId(filePath);
98
+ if (!agentId)
99
+ return;
100
+ activeAgents.add(agentId);
101
+ let stat;
102
+ try {
103
+ stat = fs.statSync(filePath);
104
+ }
105
+ catch {
106
+ return;
107
+ }
108
+ const currentOffset = offsets[filePath] || 0;
109
+ if (stat.size <= currentOffset)
110
+ return;
111
+ const fd = fs.openSync(filePath, 'r');
112
+ const buffer = Buffer.alloc(stat.size - currentOffset);
113
+ fs.readSync(fd, buffer, 0, buffer.length, currentOffset);
114
+ fs.closeSync(fd);
115
+ const content = buffer.toString('utf-8');
116
+ const lines = content.split('\n').filter((l) => l.trim());
117
+ if (lines.length > 0) {
118
+ log(`Processing ${lines.length} new lines from ${path.basename(filePath)} (agent: ${agentId})`);
119
+ await processLines(lines, agentId);
120
+ }
121
+ offsets[filePath] = stat.size;
122
+ saveOffsets();
123
+ }
124
+ async function initialScan() {
125
+ const agentsDir = path.join(config.openclawDir, 'agents');
126
+ if (!fs.existsSync(agentsDir)) {
127
+ log(`Agents directory not found: ${agentsDir}`);
128
+ return;
129
+ }
130
+ const agents = fs.readdirSync(agentsDir).filter((name) => {
131
+ const sessionsDir = path.join(agentsDir, name, 'sessions');
132
+ return fs.existsSync(sessionsDir) && fs.statSync(path.join(agentsDir, name)).isDirectory();
133
+ });
134
+ log(`Found ${agents.length} agents: ${agents.join(', ')}`);
135
+ for (const agentId of agents) {
136
+ activeAgents.add(agentId);
137
+ const sessionsDir = path.join(agentsDir, agentId, 'sessions');
138
+ const files = fs.readdirSync(sessionsDir).filter((f) => f.endsWith('.jsonl'));
139
+ for (const file of files) {
140
+ const filePath = path.join(sessionsDir, file);
141
+ await readNewLines(filePath);
142
+ }
143
+ }
144
+ log(`Initial scan complete. ${activeAgents.size} agents, offsets tracked for ${Object.keys(offsets).length} files`);
145
+ }
146
+ function startFileWatcher() {
147
+ const pattern = path.join(config.openclawDir, 'agents', '*', 'sessions', '*.jsonl');
148
+ log(`Watching: ${pattern}`);
149
+ watcher = chokidar.watch(pattern, {
150
+ persistent: true,
151
+ ignoreInitial: true,
152
+ awaitWriteFinish: { stabilityThreshold: 500, pollInterval: 100 },
153
+ });
154
+ watcher.on('add', async (filePath) => {
155
+ log(`New file detected: ${path.basename(filePath)}`);
156
+ await readNewLines(filePath);
157
+ });
158
+ watcher.on('change', async (filePath) => {
159
+ await readNewLines(filePath);
160
+ });
161
+ watcher.on('error', (err) => {
162
+ log(`Watcher error: ${err.message}`);
163
+ });
164
+ }
165
+ function startGatewayWatcher() {
166
+ const errLog = path.join(config.openclawDir, 'logs', 'gateway.err.log');
167
+ if (!fs.existsSync(errLog)) {
168
+ log(`Gateway error log not found: ${errLog}`);
169
+ return;
170
+ }
171
+ let errOffset = 0;
172
+ try {
173
+ errOffset = fs.statSync(errLog).size;
174
+ }
175
+ catch {
176
+ // start from beginning
177
+ }
178
+ gatewayWatcher = chokidar.watch(errLog, {
179
+ persistent: true,
180
+ ignoreInitial: true,
181
+ });
182
+ gatewayWatcher.on('change', async () => {
183
+ try {
184
+ const stat = fs.statSync(errLog);
185
+ if (stat.size <= errOffset)
186
+ return;
187
+ const fd = fs.openSync(errLog, 'r');
188
+ const buffer = Buffer.alloc(stat.size - errOffset);
189
+ fs.readSync(fd, buffer, 0, buffer.length, errOffset);
190
+ fs.closeSync(fd);
191
+ const lines = buffer.toString('utf-8').split('\n').filter((l) => l.trim());
192
+ for (const line of lines) {
193
+ const event = (0, parser_1.parseGatewayError)(line, 'gateway');
194
+ if (event) {
195
+ await sendEvent(event);
196
+ }
197
+ }
198
+ errOffset = stat.size;
199
+ }
200
+ catch (err) {
201
+ const msg = err instanceof Error ? err.message : String(err);
202
+ log(`Gateway watcher error: ${msg}`);
203
+ }
204
+ });
205
+ log('Gateway error log watcher started');
206
+ }
207
+ function startHeartbeat() {
208
+ const os = require('os');
209
+ heartbeatInterval = setInterval(async () => {
210
+ for (const agentId of activeAgents) {
211
+ await sendEvent({
212
+ agentId,
213
+ agentName: agentId,
214
+ host: os.hostname(),
215
+ type: 'heartbeat',
216
+ timestamp: new Date().toISOString(),
217
+ });
218
+ }
219
+ log(`Heartbeat sent for ${activeAgents.size} agents`);
220
+ }, config.scanIntervalMs);
221
+ }
222
+ async function startCollector(cfg) {
223
+ config = cfg;
224
+ log('=== ClaWatch Collector Starting ===');
225
+ log(`Backend: ${config.backendUrl}`);
226
+ log(`OpenClaw dir: ${config.openclawDir}`);
227
+ loadOffsets();
228
+ await initialScan();
229
+ startFileWatcher();
230
+ startGatewayWatcher();
231
+ startHeartbeat();
232
+ log('Collector running. Watching for changes...');
233
+ }
234
+ function stopCollector() {
235
+ if (watcher) {
236
+ watcher.close();
237
+ watcher = null;
238
+ }
239
+ if (gatewayWatcher) {
240
+ gatewayWatcher.close();
241
+ gatewayWatcher = null;
242
+ }
243
+ if (heartbeatInterval) {
244
+ clearInterval(heartbeatInterval);
245
+ heartbeatInterval = null;
246
+ }
247
+ log('Collector stopped');
248
+ }
249
+ //# sourceMappingURL=collector.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"collector.js","sourceRoot":"","sources":["../src/collector.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,18 @@
1
+ export interface ClaWatchConfig {
2
+ openclawDir: string;
3
+ backendUrl: string;
4
+ apiKey: string;
5
+ scanIntervalMs: number;
6
+ }
7
+ export declare const paths: {
8
+ dir: string;
9
+ config: string;
10
+ pid: string;
11
+ log: string;
12
+ offsets: string;
13
+ };
14
+ export declare function ensureDir(): void;
15
+ export declare function loadConfig(): ClaWatchConfig;
16
+ export declare function saveConfig(config: ClaWatchConfig): void;
17
+ export declare function configExists(): boolean;
18
+ //# sourceMappingURL=config.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"config.d.ts","sourceRoot":"","sources":["../src/config.ts"],"names":[],"mappings":"AAIA,MAAM,WAAW,cAAc;IAC7B,WAAW,EAAE,MAAM,CAAC;IACpB,UAAU,EAAE,MAAM,CAAC;IACnB,MAAM,EAAE,MAAM,CAAC;IACf,cAAc,EAAE,MAAM,CAAC;CACxB;AAQD,eAAO,MAAM,KAAK;;;;;;CAMjB,CAAC;AASF,wBAAgB,SAAS,IAAI,IAAI,CAIhC;AAED,wBAAgB,UAAU,IAAI,cAAc,CAM3C;AAED,wBAAgB,UAAU,CAAC,MAAM,EAAE,cAAc,GAAG,IAAI,CAGvD;AAED,wBAAgB,YAAY,IAAI,OAAO,CAEtC"}
package/dist/config.js ADDED
@@ -0,0 +1,81 @@
1
+ "use strict";
2
+ var __createBinding = (this && this.__createBinding) || (Object.create ? (function(o, m, k, k2) {
3
+ if (k2 === undefined) k2 = k;
4
+ var desc = Object.getOwnPropertyDescriptor(m, k);
5
+ if (!desc || ("get" in desc ? !m.__esModule : desc.writable || desc.configurable)) {
6
+ desc = { enumerable: true, get: function() { return m[k]; } };
7
+ }
8
+ Object.defineProperty(o, k2, desc);
9
+ }) : (function(o, m, k, k2) {
10
+ if (k2 === undefined) k2 = k;
11
+ o[k2] = m[k];
12
+ }));
13
+ var __setModuleDefault = (this && this.__setModuleDefault) || (Object.create ? (function(o, v) {
14
+ Object.defineProperty(o, "default", { enumerable: true, value: v });
15
+ }) : function(o, v) {
16
+ o["default"] = v;
17
+ });
18
+ var __importStar = (this && this.__importStar) || (function () {
19
+ var ownKeys = function(o) {
20
+ ownKeys = Object.getOwnPropertyNames || function (o) {
21
+ var ar = [];
22
+ for (var k in o) if (Object.prototype.hasOwnProperty.call(o, k)) ar[ar.length] = k;
23
+ return ar;
24
+ };
25
+ return ownKeys(o);
26
+ };
27
+ return function (mod) {
28
+ if (mod && mod.__esModule) return mod;
29
+ var result = {};
30
+ if (mod != null) for (var k = ownKeys(mod), i = 0; i < k.length; i++) if (k[i] !== "default") __createBinding(result, mod, k[i]);
31
+ __setModuleDefault(result, mod);
32
+ return result;
33
+ };
34
+ })();
35
+ Object.defineProperty(exports, "__esModule", { value: true });
36
+ exports.paths = void 0;
37
+ exports.ensureDir = ensureDir;
38
+ exports.loadConfig = loadConfig;
39
+ exports.saveConfig = saveConfig;
40
+ exports.configExists = configExists;
41
+ const fs = __importStar(require("fs"));
42
+ const path = __importStar(require("path"));
43
+ const os = __importStar(require("os"));
44
+ const CLAWATCH_DIR = path.join(os.homedir(), '.clawatch');
45
+ const CONFIG_PATH = path.join(CLAWATCH_DIR, 'config.json');
46
+ const PID_PATH = path.join(CLAWATCH_DIR, 'clawatch.pid');
47
+ const LOG_PATH = path.join(CLAWATCH_DIR, 'daemon.log');
48
+ const OFFSETS_PATH = path.join(CLAWATCH_DIR, 'offsets.json');
49
+ exports.paths = {
50
+ dir: CLAWATCH_DIR,
51
+ config: CONFIG_PATH,
52
+ pid: PID_PATH,
53
+ log: LOG_PATH,
54
+ offsets: OFFSETS_PATH,
55
+ };
56
+ const DEFAULT_CONFIG = {
57
+ openclawDir: path.join(os.homedir(), '.openclaw'),
58
+ backendUrl: 'http://localhost:3001',
59
+ apiKey: '',
60
+ scanIntervalMs: 60000,
61
+ };
62
+ function ensureDir() {
63
+ if (!fs.existsSync(CLAWATCH_DIR)) {
64
+ fs.mkdirSync(CLAWATCH_DIR, { recursive: true });
65
+ }
66
+ }
67
+ function loadConfig() {
68
+ if (!fs.existsSync(CONFIG_PATH)) {
69
+ return DEFAULT_CONFIG;
70
+ }
71
+ const raw = fs.readFileSync(CONFIG_PATH, 'utf-8');
72
+ return { ...DEFAULT_CONFIG, ...JSON.parse(raw) };
73
+ }
74
+ function saveConfig(config) {
75
+ ensureDir();
76
+ fs.writeFileSync(CONFIG_PATH, JSON.stringify(config, null, 2) + '\n');
77
+ }
78
+ function configExists() {
79
+ return fs.existsSync(CONFIG_PATH);
80
+ }
81
+ //# sourceMappingURL=config.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"config.js","sourceRoot":"","sources":["../src/config.ts"],"names":[],"mappings":";;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;AAgCA,8BAIC;AAED,gCAMC;AAED,gCAGC;AAED,oCAEC;AArDD,uCAAyB;AACzB,2CAA6B;AAC7B,uCAAyB;AASzB,MAAM,YAAY,GAAG,IAAI,CAAC,IAAI,CAAC,EAAE,CAAC,OAAO,EAAE,EAAE,WAAW,CAAC,CAAC;AAC1D,MAAM,WAAW,GAAG,IAAI,CAAC,IAAI,CAAC,YAAY,EAAE,aAAa,CAAC,CAAC;AAC3D,MAAM,QAAQ,GAAG,IAAI,CAAC,IAAI,CAAC,YAAY,EAAE,cAAc,CAAC,CAAC;AACzD,MAAM,QAAQ,GAAG,IAAI,CAAC,IAAI,CAAC,YAAY,EAAE,YAAY,CAAC,CAAC;AACvD,MAAM,YAAY,GAAG,IAAI,CAAC,IAAI,CAAC,YAAY,EAAE,cAAc,CAAC,CAAC;AAEhD,QAAA,KAAK,GAAG;IACnB,GAAG,EAAE,YAAY;IACjB,MAAM,EAAE,WAAW;IACnB,GAAG,EAAE,QAAQ;IACb,GAAG,EAAE,QAAQ;IACb,OAAO,EAAE,YAAY;CACtB,CAAC;AAEF,MAAM,cAAc,GAAmB;IACrC,WAAW,EAAE,IAAI,CAAC,IAAI,CAAC,EAAE,CAAC,OAAO,EAAE,EAAE,WAAW,CAAC;IACjD,UAAU,EAAE,uBAAuB;IACnC,MAAM,EAAE,EAAE;IACV,cAAc,EAAE,KAAK;CACtB,CAAC;AAEF,SAAgB,SAAS;IACvB,IAAI,CAAC,EAAE,CAAC,UAAU,CAAC,YAAY,CAAC,EAAE,CAAC;QACjC,EAAE,CAAC,SAAS,CAAC,YAAY,EAAE,EAAE,SAAS,EAAE,IAAI,EAAE,CAAC,CAAC;IAClD,CAAC;AACH,CAAC;AAED,SAAgB,UAAU;IACxB,IAAI,CAAC,EAAE,CAAC,UAAU,CAAC,WAAW,CAAC,EAAE,CAAC;QAChC,OAAO,cAAc,CAAC;IACxB,CAAC;IACD,MAAM,GAAG,GAAG,EAAE,CAAC,YAAY,CAAC,WAAW,EAAE,OAAO,CAAC,CAAC;IAClD,OAAO,EAAE,GAAG,cAAc,EAAE,GAAG,IAAI,CAAC,KAAK,CAAC,GAAG,CAAC,EAAE,CAAC;AACnD,CAAC;AAED,SAAgB,UAAU,CAAC,MAAsB;IAC/C,SAAS,EAAE,CAAC;IACZ,EAAE,CAAC,aAAa,CAAC,WAAW,EAAE,IAAI,CAAC,SAAS,CAAC,MAAM,EAAE,IAAI,EAAE,CAAC,CAAC,GAAG,IAAI,CAAC,CAAC;AACxE,CAAC;AAED,SAAgB,YAAY;IAC1B,OAAO,EAAE,CAAC,UAAU,CAAC,WAAW,CAAC,CAAC;AACpC,CAAC"}
@@ -0,0 +1,2 @@
1
+ export {};
2
+ //# sourceMappingURL=daemon.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"daemon.d.ts","sourceRoot":"","sources":["../src/daemon.ts"],"names":[],"mappings":""}
package/dist/daemon.js ADDED
@@ -0,0 +1,25 @@
1
+ "use strict";
2
+ Object.defineProperty(exports, "__esModule", { value: true });
3
+ const config_1 = require("./config");
4
+ const collector_1 = require("./collector");
5
+ (0, config_1.ensureDir)();
6
+ process.on('SIGTERM', () => {
7
+ (0, collector_1.stopCollector)();
8
+ process.exit(0);
9
+ });
10
+ process.on('SIGINT', () => {
11
+ (0, collector_1.stopCollector)();
12
+ process.exit(0);
13
+ });
14
+ process.on('uncaughtException', (err) => {
15
+ const fs = require('fs');
16
+ fs.appendFileSync(config_1.paths.log, `[${new Date().toISOString()}] UNCAUGHT: ${err.message}\n${err.stack}\n`);
17
+ process.exit(1);
18
+ });
19
+ const config = (0, config_1.loadConfig)();
20
+ (0, collector_1.startCollector)(config).catch((err) => {
21
+ const fs = require('fs');
22
+ fs.appendFileSync(config_1.paths.log, `[${new Date().toISOString()}] FATAL: ${err.message}\n`);
23
+ process.exit(1);
24
+ });
25
+ //# sourceMappingURL=daemon.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"daemon.js","sourceRoot":"","sources":["../src/daemon.ts"],"names":[],"mappings":";;AAAA,qCAAwD;AACxD,2CAA4D;AAE5D,IAAA,kBAAS,GAAE,CAAC;AAEZ,OAAO,CAAC,EAAE,CAAC,SAAS,EAAE,GAAG,EAAE;IACzB,IAAA,yBAAa,GAAE,CAAC;IAChB,OAAO,CAAC,IAAI,CAAC,CAAC,CAAC,CAAC;AAClB,CAAC,CAAC,CAAC;AAEH,OAAO,CAAC,EAAE,CAAC,QAAQ,EAAE,GAAG,EAAE;IACxB,IAAA,yBAAa,GAAE,CAAC;IAChB,OAAO,CAAC,IAAI,CAAC,CAAC,CAAC,CAAC;AAClB,CAAC,CAAC,CAAC;AAEH,OAAO,CAAC,EAAE,CAAC,mBAAmB,EAAE,CAAC,GAAG,EAAE,EAAE;IACtC,MAAM,EAAE,GAAG,OAAO,CAAC,IAAI,CAAC,CAAC;IACzB,EAAE,CAAC,cAAc,CAAC,cAAK,CAAC,GAAG,EAAE,IAAI,IAAI,IAAI,EAAE,CAAC,WAAW,EAAE,eAAe,GAAG,CAAC,OAAO,KAAK,GAAG,CAAC,KAAK,IAAI,CAAC,CAAC;IACvG,OAAO,CAAC,IAAI,CAAC,CAAC,CAAC,CAAC;AAClB,CAAC,CAAC,CAAC;AAEH,MAAM,MAAM,GAAG,IAAA,mBAAU,GAAE,CAAC;AAC5B,IAAA,0BAAc,EAAC,MAAM,CAAC,CAAC,KAAK,CAAC,CAAC,GAAG,EAAE,EAAE;IACnC,MAAM,EAAE,GAAG,OAAO,CAAC,IAAI,CAAC,CAAC;IACzB,EAAE,CAAC,cAAc,CAAC,cAAK,CAAC,GAAG,EAAE,IAAI,IAAI,IAAI,EAAE,CAAC,WAAW,EAAE,YAAY,GAAG,CAAC,OAAO,IAAI,CAAC,CAAC;IACtF,OAAO,CAAC,IAAI,CAAC,CAAC,CAAC,CAAC;AAClB,CAAC,CAAC,CAAC"}
@@ -0,0 +1,39 @@
1
+ import { AgentEvent } from './api';
2
+ interface SessionEvent {
3
+ type: 'session';
4
+ id: string;
5
+ timestamp: string;
6
+ cwd?: string;
7
+ }
8
+ interface MessageEvent {
9
+ type: 'message';
10
+ timestamp: string;
11
+ message?: {
12
+ role?: string;
13
+ model?: string;
14
+ usage?: {
15
+ input?: number;
16
+ output?: number;
17
+ cacheRead?: number;
18
+ cacheWrite?: number;
19
+ totalTokens?: number;
20
+ cost?: {
21
+ input?: number;
22
+ output?: number;
23
+ cacheRead?: number;
24
+ cacheWrite?: number;
25
+ total?: number;
26
+ };
27
+ };
28
+ };
29
+ }
30
+ type JsonlEvent = SessionEvent | MessageEvent | {
31
+ type: string;
32
+ timestamp?: string;
33
+ [key: string]: unknown;
34
+ };
35
+ export declare function parseLine(line: string): JsonlEvent | null;
36
+ export declare function mapEventToApiEvents(event: JsonlEvent, agentId: string): AgentEvent[];
37
+ export declare function parseGatewayError(line: string, agentId: string): AgentEvent | null;
38
+ export {};
39
+ //# sourceMappingURL=parser.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"parser.d.ts","sourceRoot":"","sources":["../src/parser.ts"],"names":[],"mappings":"AACA,OAAO,EAAE,UAAU,EAAE,MAAM,OAAO,CAAC;AAInC,UAAU,YAAY;IACpB,IAAI,EAAE,SAAS,CAAC;IAChB,EAAE,EAAE,MAAM,CAAC;IACX,SAAS,EAAE,MAAM,CAAC;IAClB,GAAG,CAAC,EAAE,MAAM,CAAC;CACd;AAED,UAAU,YAAY;IACpB,IAAI,EAAE,SAAS,CAAC;IAChB,SAAS,EAAE,MAAM,CAAC;IAClB,OAAO,CAAC,EAAE;QACR,IAAI,CAAC,EAAE,MAAM,CAAC;QACd,KAAK,CAAC,EAAE,MAAM,CAAC;QACf,KAAK,CAAC,EAAE;YACN,KAAK,CAAC,EAAE,MAAM,CAAC;YACf,MAAM,CAAC,EAAE,MAAM,CAAC;YAChB,SAAS,CAAC,EAAE,MAAM,CAAC;YACnB,UAAU,CAAC,EAAE,MAAM,CAAC;YACpB,WAAW,CAAC,EAAE,MAAM,CAAC;YACrB,IAAI,CAAC,EAAE;gBACL,KAAK,CAAC,EAAE,MAAM,CAAC;gBACf,MAAM,CAAC,EAAE,MAAM,CAAC;gBAChB,SAAS,CAAC,EAAE,MAAM,CAAC;gBACnB,UAAU,CAAC,EAAE,MAAM,CAAC;gBACpB,KAAK,CAAC,EAAE,MAAM,CAAC;aAChB,CAAC;SACH,CAAC;KACH,CAAC;CACH;AAED,KAAK,UAAU,GAAG,YAAY,GAAG,YAAY,GAAG;IAAE,IAAI,EAAE,MAAM,CAAC;IAAC,SAAS,CAAC,EAAE,MAAM,CAAC;IAAC,CAAC,GAAG,EAAE,MAAM,GAAG,OAAO,CAAA;CAAE,CAAC;AAE7G,wBAAgB,SAAS,CAAC,IAAI,EAAE,MAAM,GAAG,UAAU,GAAG,IAAI,CAQzD;AAED,wBAAgB,mBAAmB,CAAC,KAAK,EAAE,UAAU,EAAE,OAAO,EAAE,MAAM,GAAG,UAAU,EAAE,CA6CpF;AAED,wBAAgB,iBAAiB,CAAC,IAAI,EAAE,MAAM,EAAE,OAAO,EAAE,MAAM,GAAG,UAAU,GAAG,IAAI,CAYlF"}
package/dist/parser.js ADDED
@@ -0,0 +1,107 @@
1
+ "use strict";
2
+ var __createBinding = (this && this.__createBinding) || (Object.create ? (function(o, m, k, k2) {
3
+ if (k2 === undefined) k2 = k;
4
+ var desc = Object.getOwnPropertyDescriptor(m, k);
5
+ if (!desc || ("get" in desc ? !m.__esModule : desc.writable || desc.configurable)) {
6
+ desc = { enumerable: true, get: function() { return m[k]; } };
7
+ }
8
+ Object.defineProperty(o, k2, desc);
9
+ }) : (function(o, m, k, k2) {
10
+ if (k2 === undefined) k2 = k;
11
+ o[k2] = m[k];
12
+ }));
13
+ var __setModuleDefault = (this && this.__setModuleDefault) || (Object.create ? (function(o, v) {
14
+ Object.defineProperty(o, "default", { enumerable: true, value: v });
15
+ }) : function(o, v) {
16
+ o["default"] = v;
17
+ });
18
+ var __importStar = (this && this.__importStar) || (function () {
19
+ var ownKeys = function(o) {
20
+ ownKeys = Object.getOwnPropertyNames || function (o) {
21
+ var ar = [];
22
+ for (var k in o) if (Object.prototype.hasOwnProperty.call(o, k)) ar[ar.length] = k;
23
+ return ar;
24
+ };
25
+ return ownKeys(o);
26
+ };
27
+ return function (mod) {
28
+ if (mod && mod.__esModule) return mod;
29
+ var result = {};
30
+ if (mod != null) for (var k = ownKeys(mod), i = 0; i < k.length; i++) if (k[i] !== "default") __createBinding(result, mod, k[i]);
31
+ __setModuleDefault(result, mod);
32
+ return result;
33
+ };
34
+ })();
35
+ Object.defineProperty(exports, "__esModule", { value: true });
36
+ exports.parseLine = parseLine;
37
+ exports.mapEventToApiEvents = mapEventToApiEvents;
38
+ exports.parseGatewayError = parseGatewayError;
39
+ const os = __importStar(require("os"));
40
+ const HOST = os.hostname();
41
+ function parseLine(line) {
42
+ const trimmed = line.trim();
43
+ if (!trimmed)
44
+ return null;
45
+ try {
46
+ return JSON.parse(trimmed);
47
+ }
48
+ catch {
49
+ return null;
50
+ }
51
+ }
52
+ function mapEventToApiEvents(event, agentId) {
53
+ const agentName = agentId;
54
+ const timestamp = event.timestamp || new Date().toISOString();
55
+ const results = [];
56
+ if (event.type === 'session') {
57
+ results.push({
58
+ agentId,
59
+ agentName,
60
+ host: HOST,
61
+ type: 'status_change',
62
+ data: { status: 'running' },
63
+ timestamp,
64
+ });
65
+ }
66
+ if (event.type === 'message') {
67
+ const msg = event.message;
68
+ if (msg?.usage?.cost?.total !== undefined) {
69
+ results.push({
70
+ agentId,
71
+ agentName,
72
+ host: HOST,
73
+ type: 'cost',
74
+ data: {
75
+ costUsd: msg.usage.cost.total,
76
+ tokenCount: msg.usage.totalTokens || 0,
77
+ model: msg.model || 'unknown',
78
+ },
79
+ timestamp,
80
+ });
81
+ }
82
+ if (msg?.role === 'assistant') {
83
+ results.push({
84
+ agentId,
85
+ agentName,
86
+ host: HOST,
87
+ type: 'heartbeat',
88
+ timestamp,
89
+ });
90
+ }
91
+ }
92
+ return results;
93
+ }
94
+ function parseGatewayError(line, agentId) {
95
+ const trimmed = line.trim();
96
+ if (!trimmed)
97
+ return null;
98
+ return {
99
+ agentId,
100
+ agentName: agentId,
101
+ host: HOST,
102
+ type: 'error',
103
+ data: { error: trimmed },
104
+ timestamp: new Date().toISOString(),
105
+ };
106
+ }
107
+ //# sourceMappingURL=parser.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"parser.js","sourceRoot":"","sources":["../src/parser.ts"],"names":[],"mappings":";;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;AAqCA,8BAQC;AAED,kDA6CC;AAED,8CAYC;AA1GD,uCAAyB;AAGzB,MAAM,IAAI,GAAG,EAAE,CAAC,QAAQ,EAAE,CAAC;AAkC3B,SAAgB,SAAS,CAAC,IAAY;IACpC,MAAM,OAAO,GAAG,IAAI,CAAC,IAAI,EAAE,CAAC;IAC5B,IAAI,CAAC,OAAO;QAAE,OAAO,IAAI,CAAC;IAC1B,IAAI,CAAC;QACH,OAAO,IAAI,CAAC,KAAK,CAAC,OAAO,CAAC,CAAC;IAC7B,CAAC;IAAC,MAAM,CAAC;QACP,OAAO,IAAI,CAAC;IACd,CAAC;AACH,CAAC;AAED,SAAgB,mBAAmB,CAAC,KAAiB,EAAE,OAAe;IACpE,MAAM,SAAS,GAAG,OAAO,CAAC;IAC1B,MAAM,SAAS,GAAG,KAAK,CAAC,SAAS,IAAI,IAAI,IAAI,EAAE,CAAC,WAAW,EAAE,CAAC;IAC9D,MAAM,OAAO,GAAiB,EAAE,CAAC;IAEjC,IAAI,KAAK,CAAC,IAAI,KAAK,SAAS,EAAE,CAAC;QAC7B,OAAO,CAAC,IAAI,CAAC;YACX,OAAO;YACP,SAAS;YACT,IAAI,EAAE,IAAI;YACV,IAAI,EAAE,eAAe;YACrB,IAAI,EAAE,EAAE,MAAM,EAAE,SAAS,EAAE;YAC3B,SAAS;SACV,CAAC,CAAC;IACL,CAAC;IAED,IAAI,KAAK,CAAC,IAAI,KAAK,SAAS,EAAE,CAAC;QAC7B,MAAM,GAAG,GAAI,KAAsB,CAAC,OAAO,CAAC;QAC5C,IAAI,GAAG,EAAE,KAAK,EAAE,IAAI,EAAE,KAAK,KAAK,SAAS,EAAE,CAAC;YAC1C,OAAO,CAAC,IAAI,CAAC;gBACX,OAAO;gBACP,SAAS;gBACT,IAAI,EAAE,IAAI;gBACV,IAAI,EAAE,MAAM;gBACZ,IAAI,EAAE;oBACJ,OAAO,EAAE,GAAG,CAAC,KAAK,CAAC,IAAI,CAAC,KAAK;oBAC7B,UAAU,EAAE,GAAG,CAAC,KAAK,CAAC,WAAW,IAAI,CAAC;oBACtC,KAAK,EAAE,GAAG,CAAC,KAAK,IAAI,SAAS;iBAC9B;gBACD,SAAS;aACV,CAAC,CAAC;QACL,CAAC;QAED,IAAI,GAAG,EAAE,IAAI,KAAK,WAAW,EAAE,CAAC;YAC9B,OAAO,CAAC,IAAI,CAAC;gBACX,OAAO;gBACP,SAAS;gBACT,IAAI,EAAE,IAAI;gBACV,IAAI,EAAE,WAAW;gBACjB,SAAS;aACV,CAAC,CAAC;QACL,CAAC;IACH,CAAC;IAED,OAAO,OAAO,CAAC;AACjB,CAAC;AAED,SAAgB,iBAAiB,CAAC,IAAY,EAAE,OAAe;IAC7D,MAAM,OAAO,GAAG,IAAI,CAAC,IAAI,EAAE,CAAC;IAC5B,IAAI,CAAC,OAAO;QAAE,OAAO,IAAI,CAAC;IAE1B,OAAO;QACL,OAAO;QACP,SAAS,EAAE,OAAO;QAClB,IAAI,EAAE,IAAI;QACV,IAAI,EAAE,OAAO;QACb,IAAI,EAAE,EAAE,KAAK,EAAE,OAAO,EAAE;QACxB,SAAS,EAAE,IAAI,IAAI,EAAE,CAAC,WAAW,EAAE;KACpC,CAAC;AACJ,CAAC"}
package/package.json ADDED
@@ -0,0 +1,53 @@
1
+ {
2
+ "name": "clawatch",
3
+ "version": "1.0.0",
4
+ "description": "Observability & monitoring for AI agents. Track costs, tokens, sessions, and get alerts when things go wrong.",
5
+ "author": "GENWAY AI <hello@genway.ai>",
6
+ "license": "MIT",
7
+ "homepage": "https://clawatch.dev",
8
+ "repository": {
9
+ "type": "git",
10
+ "url": "git+https://github.com/GENWAY-AI/clawatch.git",
11
+ "directory": "cli"
12
+ },
13
+ "bugs": {
14
+ "url": "https://github.com/GENWAY-AI/clawatch/issues"
15
+ },
16
+ "keywords": [
17
+ "ai",
18
+ "agents",
19
+ "observability",
20
+ "monitoring",
21
+ "openclaw",
22
+ "llm",
23
+ "cost-tracking",
24
+ "opentelemetry"
25
+ ],
26
+ "main": "dist/cli.js",
27
+ "bin": {
28
+ "clawatch": "./dist/cli.js"
29
+ },
30
+ "files": [
31
+ "dist/**/*",
32
+ "README.md",
33
+ "LICENSE"
34
+ ],
35
+ "engines": {
36
+ "node": ">=18"
37
+ },
38
+ "scripts": {
39
+ "build": "tsc",
40
+ "dev": "tsc --watch",
41
+ "start": "node dist/cli.js",
42
+ "prepublishOnly": "npm run build"
43
+ },
44
+ "dependencies": {
45
+ "chalk": "^4.1.2",
46
+ "chokidar": "^3.6.0",
47
+ "commander": "^12.1.0"
48
+ },
49
+ "devDependencies": {
50
+ "@types/node": "^20.14.0",
51
+ "typescript": "^5.5.0"
52
+ }
53
+ }