@agentstrack/collector 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.
- package/CHANGELOG.md +168 -0
- package/LICENSE +202 -0
- package/README.md +779 -0
- package/dist/adapters/account.d.ts +22 -0
- package/dist/adapters/account.js +142 -0
- package/dist/adapters/account.js.map +1 -0
- package/dist/adapters/claude.d.ts +49 -0
- package/dist/adapters/claude.js +259 -0
- package/dist/adapters/claude.js.map +1 -0
- package/dist/adapters/codex.d.ts +64 -0
- package/dist/adapters/codex.js +350 -0
- package/dist/adapters/codex.js.map +1 -0
- package/dist/adapters/opencode.d.ts +79 -0
- package/dist/adapters/opencode.js +338 -0
- package/dist/adapters/opencode.js.map +1 -0
- package/dist/adapters/types.d.ts +97 -0
- package/dist/adapters/types.js +20 -0
- package/dist/adapters/types.js.map +1 -0
- package/dist/cli.d.ts +2 -0
- package/dist/cli.js +450 -0
- package/dist/cli.js.map +1 -0
- package/dist/commands/service.d.ts +3 -0
- package/dist/commands/service.js +86 -0
- package/dist/commands/service.js.map +1 -0
- package/dist/config.d.ts +67 -0
- package/dist/config.js +97 -0
- package/dist/config.js.map +1 -0
- package/dist/daemon.d.ts +57 -0
- package/dist/daemon.js +368 -0
- package/dist/daemon.js.map +1 -0
- package/dist/git/commits.d.ts +34 -0
- package/dist/git/commits.js +85 -0
- package/dist/git/commits.js.map +1 -0
- package/dist/git/repo.d.ts +36 -0
- package/dist/git/repo.js +141 -0
- package/dist/git/repo.js.map +1 -0
- package/dist/index.d.ts +12 -0
- package/dist/index.js +12 -0
- package/dist/index.js.map +1 -0
- package/dist/privacy/mode.d.ts +11 -0
- package/dist/privacy/mode.js +17 -0
- package/dist/privacy/mode.js.map +1 -0
- package/dist/privacy/paths.d.ts +11 -0
- package/dist/privacy/paths.js +30 -0
- package/dist/privacy/paths.js.map +1 -0
- package/dist/privacy/pipeline.d.ts +26 -0
- package/dist/privacy/pipeline.js +112 -0
- package/dist/privacy/pipeline.js.map +1 -0
- package/dist/privacy/redact.d.ts +29 -0
- package/dist/privacy/redact.js +58 -0
- package/dist/privacy/redact.js.map +1 -0
- package/dist/queue/spool.d.ts +47 -0
- package/dist/queue/spool.js +152 -0
- package/dist/queue/spool.js.map +1 -0
- package/dist/queue/tailer.d.ts +25 -0
- package/dist/queue/tailer.js +48 -0
- package/dist/queue/tailer.js.map +1 -0
- package/dist/schema.d.ts +76 -0
- package/dist/schema.js +46 -0
- package/dist/schema.js.map +1 -0
- package/dist/sessions/title.d.ts +2 -0
- package/dist/sessions/title.js +11 -0
- package/dist/sessions/title.js.map +1 -0
- package/dist/transport/client.d.ts +76 -0
- package/dist/transport/client.js +80 -0
- package/dist/transport/client.js.map +1 -0
- package/package.json +42 -0
package/dist/cli.js
ADDED
|
@@ -0,0 +1,450 @@
|
|
|
1
|
+
#!/usr/bin/env node
|
|
2
|
+
import { Command } from 'commander';
|
|
3
|
+
import pc from 'picocolors';
|
|
4
|
+
import { existsSync, readFileSync, unlinkSync, writeFileSync } from 'node:fs';
|
|
5
|
+
import { hostname, platform, arch } from 'node:os';
|
|
6
|
+
import { stringify } from 'yaml';
|
|
7
|
+
import { CONFIG_PATH, LOG_PATH, PID_PATH, SPOOL_PATH, loadConfig, saveConfig, Config, configExists, } from './config.js';
|
|
8
|
+
import { Collector, VERSION, buildAdapters, errorMessage, listTranscripts, log } from './daemon.js';
|
|
9
|
+
import { ApiClient } from './transport/client.js';
|
|
10
|
+
import { Spool } from './queue/spool.js';
|
|
11
|
+
import { installService, uninstallService, servicePath } from './commands/service.js';
|
|
12
|
+
import { clampPrivacyMode } from './privacy/mode.js';
|
|
13
|
+
const program = new Command();
|
|
14
|
+
program
|
|
15
|
+
.name('agentstrack')
|
|
16
|
+
.description('Privacy-first telemetry collector for AI coding agents')
|
|
17
|
+
.version(VERSION);
|
|
18
|
+
// ------------------------------------------------------------------ login
|
|
19
|
+
program
|
|
20
|
+
.command('login')
|
|
21
|
+
.description('Authenticate this device with an AgentsTrack API key')
|
|
22
|
+
.argument('<api-key>', 'API key from your dashboard (Settings → API keys)')
|
|
23
|
+
.option('--api-url <url>', 'AgentsTrack API base URL (for self-hosted instances)')
|
|
24
|
+
.option('--label <name>', 'friendly name for this device in the dashboard')
|
|
25
|
+
.action(async (apiKey, options) => {
|
|
26
|
+
const existing = configExists() ? loadConfig() : Config.parse({});
|
|
27
|
+
const config = {
|
|
28
|
+
...existing,
|
|
29
|
+
api_url: options.apiUrl ?? existing.api_url,
|
|
30
|
+
api_key: apiKey,
|
|
31
|
+
// A new key may belong to a different org, so re-register.
|
|
32
|
+
collector_id: undefined,
|
|
33
|
+
};
|
|
34
|
+
const client = new ApiClient({ apiUrl: config.api_url, apiKey });
|
|
35
|
+
try {
|
|
36
|
+
const adapters = buildAdapters(config);
|
|
37
|
+
const agents = await Promise.all(adapters.map(async (a) => ({ agent: a.id, version: (await a.detect()).version })));
|
|
38
|
+
const result = await client.registerCollector({
|
|
39
|
+
hostname: hostname(),
|
|
40
|
+
label: options.label,
|
|
41
|
+
os: platform(),
|
|
42
|
+
arch: arch(),
|
|
43
|
+
version: VERSION,
|
|
44
|
+
privacy_mode: config.privacy.mode,
|
|
45
|
+
agents,
|
|
46
|
+
});
|
|
47
|
+
config.collector_id = result.collector_id;
|
|
48
|
+
// The org policy is a ceiling. A developer who chose a stricter mode
|
|
49
|
+
// keeps it — login must never widen what leaves this machine.
|
|
50
|
+
const effectiveMode = clampPrivacyMode(config.privacy.mode, result.privacy_mode);
|
|
51
|
+
config.privacy = { ...config.privacy, mode: effectiveMode };
|
|
52
|
+
saveConfig(config);
|
|
53
|
+
console.log(pc.green('✓') + ` Logged in and registered this device.`);
|
|
54
|
+
console.log(` Collector: ${pc.dim(result.collector_id)}`);
|
|
55
|
+
console.log(` Privacy: ${pc.bold(effectiveMode)}` +
|
|
56
|
+
(effectiveMode !== result.privacy_mode
|
|
57
|
+
? pc.dim(` (your local setting; org allows ${result.privacy_mode})`)
|
|
58
|
+
: ''));
|
|
59
|
+
console.log(` Config: ${pc.dim(CONFIG_PATH)}`);
|
|
60
|
+
console.log(`\nNext: ${pc.cyan('agentstrack start')}`);
|
|
61
|
+
}
|
|
62
|
+
catch (error) {
|
|
63
|
+
console.error(pc.red('✗') + ` Login failed: ${errorMessage(error)}`);
|
|
64
|
+
console.error(pc.dim(' Check the key, and --api-url if you self-host.'));
|
|
65
|
+
process.exitCode = 1;
|
|
66
|
+
}
|
|
67
|
+
});
|
|
68
|
+
program
|
|
69
|
+
.command('logout')
|
|
70
|
+
.description('Remove the stored API key from this device')
|
|
71
|
+
.option('--purge', 'also delete the local spool of unsent events')
|
|
72
|
+
.action((options) => {
|
|
73
|
+
if (!configExists()) {
|
|
74
|
+
console.log('Not logged in.');
|
|
75
|
+
return;
|
|
76
|
+
}
|
|
77
|
+
const config = loadConfig();
|
|
78
|
+
saveConfig({ ...config, api_key: undefined, collector_id: undefined });
|
|
79
|
+
if (options.purge) {
|
|
80
|
+
// Destructive and deliberate: unsent telemetry is discarded, not queued
|
|
81
|
+
// for the next login.
|
|
82
|
+
try {
|
|
83
|
+
for (const suffix of ['', '-wal', '-shm'])
|
|
84
|
+
unlinkSync(`${SPOOL_PATH}${suffix}`);
|
|
85
|
+
}
|
|
86
|
+
catch {
|
|
87
|
+
// Some journal files may not exist; removing the main db is what counts.
|
|
88
|
+
}
|
|
89
|
+
console.log(pc.green('✓') + ' Logged out and purged the local spool.');
|
|
90
|
+
return;
|
|
91
|
+
}
|
|
92
|
+
console.log(pc.green('✓') + ' Logged out. Queued events are kept in the spool.');
|
|
93
|
+
});
|
|
94
|
+
// ------------------------------------------------------------------ run
|
|
95
|
+
program
|
|
96
|
+
.command('start')
|
|
97
|
+
.description('Start collecting (installs a background service unless --foreground)')
|
|
98
|
+
.option('-f, --foreground', 'run in this terminal instead of as a service')
|
|
99
|
+
.action(async (options) => {
|
|
100
|
+
const config = requireLogin();
|
|
101
|
+
if (!options.foreground) {
|
|
102
|
+
const cliPath = new URL(import.meta.url).pathname;
|
|
103
|
+
const target = installService(process.execPath, cliPath);
|
|
104
|
+
console.log(pc.green('✓') + ` Collector service installed and started.`);
|
|
105
|
+
console.log(` Unit: ${pc.dim(target)}`);
|
|
106
|
+
console.log(` Logs: ${pc.dim(LOG_PATH)}`);
|
|
107
|
+
console.log(`\nCheck it: ${pc.cyan('agentstrack status')}`);
|
|
108
|
+
return;
|
|
109
|
+
}
|
|
110
|
+
writeFileSync(PID_PATH, String(process.pid));
|
|
111
|
+
const collector = new Collector(config);
|
|
112
|
+
const shutdown = () => {
|
|
113
|
+
console.log('\nStopping…');
|
|
114
|
+
collector.stop();
|
|
115
|
+
try {
|
|
116
|
+
unlinkSync(PID_PATH);
|
|
117
|
+
}
|
|
118
|
+
catch {
|
|
119
|
+
// Already gone.
|
|
120
|
+
}
|
|
121
|
+
process.exit(0);
|
|
122
|
+
};
|
|
123
|
+
process.on('SIGINT', shutdown);
|
|
124
|
+
process.on('SIGTERM', shutdown);
|
|
125
|
+
console.log(pc.green('▶') + ' Collector running. Ctrl-C to stop.');
|
|
126
|
+
await collector.start();
|
|
127
|
+
});
|
|
128
|
+
program
|
|
129
|
+
.command('stop')
|
|
130
|
+
.description('Stop the collector and remove its background service')
|
|
131
|
+
.action(() => {
|
|
132
|
+
const unit = uninstallService();
|
|
133
|
+
if (existsSync(PID_PATH)) {
|
|
134
|
+
const pid = Number(readFileSync(PID_PATH, 'utf8'));
|
|
135
|
+
try {
|
|
136
|
+
process.kill(pid, 'SIGTERM');
|
|
137
|
+
}
|
|
138
|
+
catch {
|
|
139
|
+
// Process already exited.
|
|
140
|
+
}
|
|
141
|
+
try {
|
|
142
|
+
unlinkSync(PID_PATH);
|
|
143
|
+
}
|
|
144
|
+
catch {
|
|
145
|
+
// Already gone.
|
|
146
|
+
}
|
|
147
|
+
}
|
|
148
|
+
console.log(pc.green('✓') + (unit ? ` Service removed (${unit}).` : ' Collector stopped.'));
|
|
149
|
+
});
|
|
150
|
+
// ------------------------------------------------------------------ inspect
|
|
151
|
+
program
|
|
152
|
+
.command('status')
|
|
153
|
+
.description('Show collector health, queue depth and detected agents')
|
|
154
|
+
.option('--json', 'machine-readable output')
|
|
155
|
+
.action(async (options) => {
|
|
156
|
+
if (options.json) {
|
|
157
|
+
const config = configExists() ? loadConfig() : null;
|
|
158
|
+
const spool = new Spool(SPOOL_PATH);
|
|
159
|
+
const depth = spool.depth();
|
|
160
|
+
spool.close();
|
|
161
|
+
const agents = config
|
|
162
|
+
? await Promise.all(buildAdapters(config).map(async (a) => ({ agent: a.id, ...(await a.health()) })))
|
|
163
|
+
: [];
|
|
164
|
+
console.log(JSON.stringify({
|
|
165
|
+
version: VERSION,
|
|
166
|
+
configured: Boolean(config),
|
|
167
|
+
logged_in: Boolean(config?.api_key),
|
|
168
|
+
api_url: config?.api_url ?? null,
|
|
169
|
+
collector_id: config?.collector_id ?? null,
|
|
170
|
+
privacy_mode: config?.privacy.mode ?? null,
|
|
171
|
+
queue_depth: depth,
|
|
172
|
+
running: isRunning(),
|
|
173
|
+
service_installed: existsSync(servicePath()),
|
|
174
|
+
agents,
|
|
175
|
+
}, null, 2));
|
|
176
|
+
if (!config?.api_key)
|
|
177
|
+
process.exitCode = 1;
|
|
178
|
+
return;
|
|
179
|
+
}
|
|
180
|
+
if (!configExists()) {
|
|
181
|
+
console.log(pc.yellow('!') + ' Not configured. Run: ' + pc.cyan('agentstrack login <api-key>'));
|
|
182
|
+
return;
|
|
183
|
+
}
|
|
184
|
+
const config = loadConfig();
|
|
185
|
+
const spool = new Spool(SPOOL_PATH);
|
|
186
|
+
const depth = spool.depth();
|
|
187
|
+
spool.close();
|
|
188
|
+
console.log(pc.bold('AgentsTrack collector') + pc.dim(` v${VERSION}`));
|
|
189
|
+
console.log(` Logged in: ${config.api_key ? pc.green('yes') : pc.red('no')}`);
|
|
190
|
+
console.log(` API: ${config.api_url}`);
|
|
191
|
+
console.log(` Collector: ${config.collector_id ?? pc.dim('not registered')}`);
|
|
192
|
+
console.log(` Privacy: ${pc.bold(config.privacy.mode)}`);
|
|
193
|
+
console.log(` Queue depth: ${depth === 0 ? pc.green('0') : pc.yellow(String(depth))}`);
|
|
194
|
+
console.log(` Service: ${existsSync(servicePath()) ? pc.green('installed') : pc.dim('not installed')}`);
|
|
195
|
+
console.log(` Running: ${isRunning() ? pc.green('yes') : pc.yellow('no')}`);
|
|
196
|
+
console.log('\n' + pc.bold('Agents'));
|
|
197
|
+
for (const adapter of buildAdapters(config)) {
|
|
198
|
+
const health = await adapter.health();
|
|
199
|
+
const mark = health.healthy ? pc.green('✓') : pc.red('✗');
|
|
200
|
+
// "sessions" rather than "transcripts": OpenCode keeps rows in a database,
|
|
201
|
+
// not one file per session, and the count means the same thing either way.
|
|
202
|
+
console.log(` ${mark} ${adapter.id.padEnd(14)} ${health.healthy ? `${health.filesTracked} sessions` : health.error ?? 'unavailable'}`);
|
|
203
|
+
}
|
|
204
|
+
});
|
|
205
|
+
program
|
|
206
|
+
.command('doctor')
|
|
207
|
+
.description('Diagnose setup problems')
|
|
208
|
+
.option('--json', 'machine-readable output (paste this into a bug report)')
|
|
209
|
+
.action(async (options) => {
|
|
210
|
+
if (options.json) {
|
|
211
|
+
process.exitCode = (await doctorJson()) ? 0 : 1;
|
|
212
|
+
return;
|
|
213
|
+
}
|
|
214
|
+
let problems = 0;
|
|
215
|
+
const check = (ok, label, hint) => {
|
|
216
|
+
console.log(` ${ok ? pc.green('✓') : pc.red('✗')} ${label}`);
|
|
217
|
+
if (!ok && hint)
|
|
218
|
+
console.log(` ${pc.dim(hint)}`);
|
|
219
|
+
if (!ok)
|
|
220
|
+
problems += 1;
|
|
221
|
+
};
|
|
222
|
+
console.log(pc.bold('Configuration'));
|
|
223
|
+
check(configExists(), `config exists at ${CONFIG_PATH}`, 'Run: agentstrack login <api-key>');
|
|
224
|
+
if (!configExists()) {
|
|
225
|
+
process.exitCode = 1;
|
|
226
|
+
return;
|
|
227
|
+
}
|
|
228
|
+
const config = loadConfig();
|
|
229
|
+
check(Boolean(config.api_key), 'API key present', 'Run: agentstrack login <api-key>');
|
|
230
|
+
check(Boolean(config.collector_id), 'device registered', 'Run: agentstrack login <api-key> again');
|
|
231
|
+
console.log('\n' + pc.bold('Agents'));
|
|
232
|
+
for (const adapter of buildAdapters(config)) {
|
|
233
|
+
const detection = await adapter.detect();
|
|
234
|
+
check(detection.installed, `${adapter.id} sessions found`, detection.note);
|
|
235
|
+
if (!detection.installed)
|
|
236
|
+
continue;
|
|
237
|
+
if (detection.watchPaths.length > 0) {
|
|
238
|
+
const files = detection.watchPaths.flatMap((p) => listTranscripts(p));
|
|
239
|
+
console.log(` ${pc.dim(`${files.length} file(s) modified in the last 7 days`)}`);
|
|
240
|
+
}
|
|
241
|
+
else {
|
|
242
|
+
// A database-backed adapter has no files to count; name the source instead
|
|
243
|
+
// of reporting a confident zero.
|
|
244
|
+
const health = await adapter.health();
|
|
245
|
+
console.log(` ${pc.dim(`${health.filesTracked} session(s) in ${detection.note ?? 'the agent database'}`)}`);
|
|
246
|
+
}
|
|
247
|
+
}
|
|
248
|
+
console.log('\n' + pc.bold('Connectivity'));
|
|
249
|
+
if (config.api_key) {
|
|
250
|
+
const client = new ApiClient({ apiUrl: config.api_url, apiKey: config.api_key, timeoutMs: 10_000 });
|
|
251
|
+
try {
|
|
252
|
+
const server = await client.getConfig();
|
|
253
|
+
check(true, `API reachable at ${config.api_url}`);
|
|
254
|
+
console.log(` ${pc.dim(`org privacy mode: ${server.privacy_mode}, retention ${server.retention_days}d`)}`);
|
|
255
|
+
}
|
|
256
|
+
catch (error) {
|
|
257
|
+
check(false, `API reachable at ${config.api_url}`, errorMessage(error));
|
|
258
|
+
}
|
|
259
|
+
}
|
|
260
|
+
console.log('\n' + pc.bold('Queue'));
|
|
261
|
+
const spool = new Spool(SPOOL_PATH);
|
|
262
|
+
const depth = spool.depth();
|
|
263
|
+
spool.close();
|
|
264
|
+
check(depth < 10_000, `queue depth ${depth}`, 'A large backlog means uploads are failing — check the log.');
|
|
265
|
+
console.log(` ${pc.dim(`log: ${LOG_PATH}`)}`);
|
|
266
|
+
console.log('\n' + (problems === 0 ? pc.green('No problems found.') : pc.red(`${problems} problem(s) found.`)));
|
|
267
|
+
if (problems > 0)
|
|
268
|
+
process.exitCode = 1;
|
|
269
|
+
});
|
|
270
|
+
// ------------------------------------------------------------------ config
|
|
271
|
+
program
|
|
272
|
+
.command('config')
|
|
273
|
+
.description('Show the current configuration (the API key is masked)')
|
|
274
|
+
.option('--path', 'print the config file path and exit')
|
|
275
|
+
.option('--show-effective', 'include values filled in from defaults')
|
|
276
|
+
.action((options) => {
|
|
277
|
+
if (options.path) {
|
|
278
|
+
console.log(CONFIG_PATH);
|
|
279
|
+
return;
|
|
280
|
+
}
|
|
281
|
+
if (options.showEffective) {
|
|
282
|
+
// loadConfig() already applies every zod default, so this is the config
|
|
283
|
+
// the collector actually runs with — not just what is on disk.
|
|
284
|
+
const effective = configExists() ? loadConfig() : Config.parse({});
|
|
285
|
+
console.log(stringify({ ...effective, api_key: effective.api_key ? '***masked***' : undefined }));
|
|
286
|
+
return;
|
|
287
|
+
}
|
|
288
|
+
if (!configExists()) {
|
|
289
|
+
console.log(pc.yellow('!') + ' No config yet. Run: ' + pc.cyan('agentstrack login <api-key>'));
|
|
290
|
+
return;
|
|
291
|
+
}
|
|
292
|
+
const config = loadConfig();
|
|
293
|
+
console.log(stringify({ ...config, api_key: config.api_key ? '***masked***' : undefined }));
|
|
294
|
+
});
|
|
295
|
+
program
|
|
296
|
+
.command('sync')
|
|
297
|
+
.description('Upload any queued events now and exit')
|
|
298
|
+
.option('--dry-run', 'show what would be uploaded without sending anything')
|
|
299
|
+
.option('--print', 'with --dry-run, print the full event bodies')
|
|
300
|
+
.action(async (options) => {
|
|
301
|
+
const config = requireLogin();
|
|
302
|
+
if (options.dryRun) {
|
|
303
|
+
// The privacy claim made verifiable: this is exactly what would leave
|
|
304
|
+
// the machine, after redaction, with nothing sent.
|
|
305
|
+
const spool = new Spool(SPOOL_PATH);
|
|
306
|
+
const pending = spool.peek(config.upload.batch_size);
|
|
307
|
+
spool.close();
|
|
308
|
+
if (pending.length === 0) {
|
|
309
|
+
console.log(pc.green('✓') + ' Nothing queued — nothing would be sent.');
|
|
310
|
+
return;
|
|
311
|
+
}
|
|
312
|
+
console.log(`${pending.length} event(s) would be sent to ${config.api_url}:\n`);
|
|
313
|
+
if (options.print) {
|
|
314
|
+
for (const item of pending)
|
|
315
|
+
console.log(JSON.stringify(item.event, null, 2));
|
|
316
|
+
}
|
|
317
|
+
else {
|
|
318
|
+
const byType = new Map();
|
|
319
|
+
for (const item of pending) {
|
|
320
|
+
byType.set(item.event.event_type, (byType.get(item.event.event_type) ?? 0) + 1);
|
|
321
|
+
}
|
|
322
|
+
for (const [type, count] of [...byType].sort((a, b) => b[1] - a[1])) {
|
|
323
|
+
console.log(` ${String(count).padStart(5)} ${type}`);
|
|
324
|
+
}
|
|
325
|
+
console.log(pc.dim('\n Re-run with --print to see the full event bodies.'));
|
|
326
|
+
}
|
|
327
|
+
return;
|
|
328
|
+
}
|
|
329
|
+
const collector = new Collector(config);
|
|
330
|
+
const before = collector.queueDepth();
|
|
331
|
+
if (before === 0) {
|
|
332
|
+
console.log(pc.green('✓') + ' Queue is already empty.');
|
|
333
|
+
collector.stop();
|
|
334
|
+
return;
|
|
335
|
+
}
|
|
336
|
+
console.log(`Uploading ${before} queued events…`);
|
|
337
|
+
await collector.flush();
|
|
338
|
+
const after = collector.queueDepth();
|
|
339
|
+
collector.stop();
|
|
340
|
+
console.log(after === 0
|
|
341
|
+
? pc.green('✓') + ` Uploaded ${before} events.`
|
|
342
|
+
: pc.yellow('!') + ` ${after} events still queued — see ${LOG_PATH}`);
|
|
343
|
+
if (after > 0)
|
|
344
|
+
process.exitCode = 1;
|
|
345
|
+
});
|
|
346
|
+
program
|
|
347
|
+
.command('service')
|
|
348
|
+
.description('Manage the background service')
|
|
349
|
+
.argument('<action>', 'install | uninstall')
|
|
350
|
+
.action((action) => {
|
|
351
|
+
if (action === 'install') {
|
|
352
|
+
requireLogin();
|
|
353
|
+
const cliPath = new URL(import.meta.url).pathname;
|
|
354
|
+
console.log(pc.green('✓') + ` Installed: ${installService(process.execPath, cliPath)}`);
|
|
355
|
+
}
|
|
356
|
+
else if (action === 'uninstall') {
|
|
357
|
+
const removed = uninstallService();
|
|
358
|
+
console.log(removed ? pc.green('✓') + ` Removed: ${removed}` : 'No service installed.');
|
|
359
|
+
}
|
|
360
|
+
else {
|
|
361
|
+
console.error(pc.red('✗') + ' Unknown action. Use: install | uninstall');
|
|
362
|
+
process.exitCode = 1;
|
|
363
|
+
}
|
|
364
|
+
});
|
|
365
|
+
/** True when a foreground collector holds the pid file. */
|
|
366
|
+
function isRunning() {
|
|
367
|
+
if (!existsSync(PID_PATH))
|
|
368
|
+
return false;
|
|
369
|
+
const pid = Number(readFileSync(PID_PATH, 'utf8'));
|
|
370
|
+
if (!Number.isInteger(pid) || pid <= 0)
|
|
371
|
+
return false;
|
|
372
|
+
try {
|
|
373
|
+
// Signal 0 tests for existence without touching the process.
|
|
374
|
+
process.kill(pid, 0);
|
|
375
|
+
return true;
|
|
376
|
+
}
|
|
377
|
+
catch {
|
|
378
|
+
return false; // stale pid file
|
|
379
|
+
}
|
|
380
|
+
}
|
|
381
|
+
/** Structured diagnostics — this is what bug reports ask for. */
|
|
382
|
+
async function doctorJson() {
|
|
383
|
+
const configured = configExists();
|
|
384
|
+
const config = configured ? loadConfig() : null;
|
|
385
|
+
const spool = new Spool(SPOOL_PATH);
|
|
386
|
+
const depth = spool.depth();
|
|
387
|
+
spool.close();
|
|
388
|
+
const agents = config
|
|
389
|
+
? await Promise.all(buildAdapters(config).map(async (a) => {
|
|
390
|
+
const [detection, health] = await Promise.all([a.detect(), a.health()]);
|
|
391
|
+
return {
|
|
392
|
+
agent: a.id,
|
|
393
|
+
installed: detection.installed,
|
|
394
|
+
healthy: health.healthy,
|
|
395
|
+
files_tracked: health.filesTracked,
|
|
396
|
+
note: detection.note ?? health.error ?? null,
|
|
397
|
+
};
|
|
398
|
+
}))
|
|
399
|
+
: [];
|
|
400
|
+
let api = { reachable: false };
|
|
401
|
+
if (config?.api_key) {
|
|
402
|
+
try {
|
|
403
|
+
const server = await new ApiClient({
|
|
404
|
+
apiUrl: config.api_url,
|
|
405
|
+
apiKey: config.api_key,
|
|
406
|
+
timeoutMs: 10_000,
|
|
407
|
+
}).getConfig();
|
|
408
|
+
api = { reachable: true, privacy_mode: server.privacy_mode };
|
|
409
|
+
}
|
|
410
|
+
catch (error) {
|
|
411
|
+
api = { reachable: false, error: errorMessage(error) };
|
|
412
|
+
}
|
|
413
|
+
}
|
|
414
|
+
const report = {
|
|
415
|
+
version: VERSION,
|
|
416
|
+
node: process.version,
|
|
417
|
+
platform: `${platform()}-${arch()}`,
|
|
418
|
+
configured,
|
|
419
|
+
logged_in: Boolean(config?.api_key),
|
|
420
|
+
collector_id: config?.collector_id ?? null,
|
|
421
|
+
privacy_mode: config?.privacy.mode ?? null,
|
|
422
|
+
api_url: config?.api_url ?? null,
|
|
423
|
+
api,
|
|
424
|
+
queue_depth: depth,
|
|
425
|
+
running: isRunning(),
|
|
426
|
+
service_installed: existsSync(servicePath()),
|
|
427
|
+
agents,
|
|
428
|
+
log_path: LOG_PATH,
|
|
429
|
+
};
|
|
430
|
+
console.log(JSON.stringify(report, null, 2));
|
|
431
|
+
return (configured && Boolean(config?.api_key) && api.reachable && agents.some((a) => a.installed));
|
|
432
|
+
}
|
|
433
|
+
function requireLogin() {
|
|
434
|
+
if (!configExists()) {
|
|
435
|
+
console.error(pc.red('✗') + ' Not logged in. Run: ' + pc.cyan('agentstrack login <api-key>'));
|
|
436
|
+
process.exit(1);
|
|
437
|
+
}
|
|
438
|
+
const config = loadConfig();
|
|
439
|
+
if (!config.api_key) {
|
|
440
|
+
console.error(pc.red('✗') + ' No API key. Run: ' + pc.cyan('agentstrack login <api-key>'));
|
|
441
|
+
process.exit(1);
|
|
442
|
+
}
|
|
443
|
+
return config;
|
|
444
|
+
}
|
|
445
|
+
program.parseAsync(process.argv).catch((error) => {
|
|
446
|
+
console.error(pc.red('✗') + ` ${errorMessage(error)}`);
|
|
447
|
+
log(`CLI error: ${errorMessage(error)}`);
|
|
448
|
+
process.exit(1);
|
|
449
|
+
});
|
|
450
|
+
//# sourceMappingURL=cli.js.map
|
package/dist/cli.js.map
ADDED
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"cli.js","sourceRoot":"","sources":["../src/cli.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1,86 @@
|
|
|
1
|
+
import { execFileSync } from 'node:child_process';
|
|
2
|
+
import { existsSync, mkdirSync, unlinkSync, writeFileSync } from 'node:fs';
|
|
3
|
+
import { homedir, platform } from 'node:os';
|
|
4
|
+
import { join } from 'node:path';
|
|
5
|
+
import { CONFIG_DIR, LOG_PATH } from '../config.js';
|
|
6
|
+
/**
|
|
7
|
+
* Background service installation.
|
|
8
|
+
*
|
|
9
|
+
* Uses the platform's own supervisor rather than a bespoke daemon: launchd and
|
|
10
|
+
* systemd already handle restart-on-crash, start-at-login and log rotation, so
|
|
11
|
+
* writing our own process manager would be strictly worse.
|
|
12
|
+
*/
|
|
13
|
+
const LABEL = 'ai.agentstrack.collector';
|
|
14
|
+
export function servicePath() {
|
|
15
|
+
return platform() === 'darwin'
|
|
16
|
+
? join(homedir(), 'Library', 'LaunchAgents', `${LABEL}.plist`)
|
|
17
|
+
: join(homedir(), '.config', 'systemd', 'user', 'agentstrack.service');
|
|
18
|
+
}
|
|
19
|
+
export function installService(nodePath, cliPath) {
|
|
20
|
+
const target = servicePath();
|
|
21
|
+
mkdirSync(join(target, '..'), { recursive: true });
|
|
22
|
+
if (platform() === 'darwin') {
|
|
23
|
+
writeFileSync(target, `<?xml version="1.0" encoding="UTF-8"?>
|
|
24
|
+
<!DOCTYPE plist PUBLIC "-//Apple//DTD PLIST 1.0//EN" "http://www.apple.com/DTDs/PropertyList-1.0.dtd">
|
|
25
|
+
<plist version="1.0">
|
|
26
|
+
<dict>
|
|
27
|
+
<key>Label</key><string>${LABEL}</string>
|
|
28
|
+
<key>ProgramArguments</key>
|
|
29
|
+
<array>
|
|
30
|
+
<string>${nodePath}</string>
|
|
31
|
+
<string>${cliPath}</string>
|
|
32
|
+
<string>start</string>
|
|
33
|
+
<string>--foreground</string>
|
|
34
|
+
</array>
|
|
35
|
+
<key>RunAtLoad</key><true/>
|
|
36
|
+
<key>KeepAlive</key><true/>
|
|
37
|
+
<key>WorkingDirectory</key><string>${CONFIG_DIR}</string>
|
|
38
|
+
<key>StandardOutPath</key><string>${LOG_PATH}</string>
|
|
39
|
+
<key>StandardErrorPath</key><string>${LOG_PATH}</string>
|
|
40
|
+
</dict>
|
|
41
|
+
</plist>
|
|
42
|
+
`, 'utf8');
|
|
43
|
+
try {
|
|
44
|
+
execFileSync('launchctl', ['unload', target], { stdio: 'ignore' });
|
|
45
|
+
}
|
|
46
|
+
catch {
|
|
47
|
+
// Not previously loaded — expected on first install.
|
|
48
|
+
}
|
|
49
|
+
execFileSync('launchctl', ['load', target], { stdio: 'ignore' });
|
|
50
|
+
return target;
|
|
51
|
+
}
|
|
52
|
+
writeFileSync(target, `[Unit]
|
|
53
|
+
Description=AgentsTrack collector
|
|
54
|
+
After=network-online.target
|
|
55
|
+
|
|
56
|
+
[Service]
|
|
57
|
+
Type=simple
|
|
58
|
+
ExecStart=${nodePath} ${cliPath} start --foreground
|
|
59
|
+
Restart=always
|
|
60
|
+
RestartSec=10
|
|
61
|
+
WorkingDirectory=${CONFIG_DIR}
|
|
62
|
+
|
|
63
|
+
[Install]
|
|
64
|
+
WantedBy=default.target
|
|
65
|
+
`, 'utf8');
|
|
66
|
+
execFileSync('systemctl', ['--user', 'daemon-reload'], { stdio: 'ignore' });
|
|
67
|
+
execFileSync('systemctl', ['--user', 'enable', '--now', 'agentstrack.service'], { stdio: 'ignore' });
|
|
68
|
+
return target;
|
|
69
|
+
}
|
|
70
|
+
export function uninstallService() {
|
|
71
|
+
const target = servicePath();
|
|
72
|
+
if (!existsSync(target))
|
|
73
|
+
return null;
|
|
74
|
+
try {
|
|
75
|
+
if (platform() === 'darwin')
|
|
76
|
+
execFileSync('launchctl', ['unload', target], { stdio: 'ignore' });
|
|
77
|
+
else
|
|
78
|
+
execFileSync('systemctl', ['--user', 'disable', '--now', 'agentstrack.service'], { stdio: 'ignore' });
|
|
79
|
+
}
|
|
80
|
+
catch {
|
|
81
|
+
// Removing the unit file is what matters; the supervisor may already be stopped.
|
|
82
|
+
}
|
|
83
|
+
unlinkSync(target);
|
|
84
|
+
return target;
|
|
85
|
+
}
|
|
86
|
+
//# sourceMappingURL=service.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"service.js","sourceRoot":"","sources":["../../src/commands/service.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,YAAY,EAAE,MAAM,oBAAoB,CAAC;AAClD,OAAO,EAAE,UAAU,EAAE,SAAS,EAAE,UAAU,EAAE,aAAa,EAAE,MAAM,SAAS,CAAC;AAC3E,OAAO,EAAE,OAAO,EAAE,QAAQ,EAAE,MAAM,SAAS,CAAC;AAC5C,OAAO,EAAE,IAAI,EAAE,MAAM,WAAW,CAAC;AACjC,OAAO,EAAE,UAAU,EAAE,QAAQ,EAAE,MAAM,cAAc,CAAC;AAEpD;;;;;;GAMG;AACH,MAAM,KAAK,GAAG,0BAA0B,CAAC;AAEzC,MAAM,UAAU,WAAW;IACzB,OAAO,QAAQ,EAAE,KAAK,QAAQ;QAC5B,CAAC,CAAC,IAAI,CAAC,OAAO,EAAE,EAAE,SAAS,EAAE,cAAc,EAAE,GAAG,KAAK,QAAQ,CAAC;QAC9D,CAAC,CAAC,IAAI,CAAC,OAAO,EAAE,EAAE,SAAS,EAAE,SAAS,EAAE,MAAM,EAAE,qBAAqB,CAAC,CAAC;AAC3E,CAAC;AAED,MAAM,UAAU,cAAc,CAAC,QAAgB,EAAE,OAAe;IAC9D,MAAM,MAAM,GAAG,WAAW,EAAE,CAAC;IAC7B,SAAS,CAAC,IAAI,CAAC,MAAM,EAAE,IAAI,CAAC,EAAE,EAAE,SAAS,EAAE,IAAI,EAAE,CAAC,CAAC;IAEnD,IAAI,QAAQ,EAAE,KAAK,QAAQ,EAAE,CAAC;QAC5B,aAAa,CACX,MAAM,EACN;;;;4BAIsB,KAAK;;;cAGnB,QAAQ;cACR,OAAO;;;;;;uCAMkB,UAAU;sCACX,QAAQ;wCACN,QAAQ;;;CAG/C,EACK,MAAM,CACP,CAAC;QACF,IAAI,CAAC;YACH,YAAY,CAAC,WAAW,EAAE,CAAC,QAAQ,EAAE,MAAM,CAAC,EAAE,EAAE,KAAK,EAAE,QAAQ,EAAE,CAAC,CAAC;QACrE,CAAC;QAAC,MAAM,CAAC;YACP,qDAAqD;QACvD,CAAC;QACD,YAAY,CAAC,WAAW,EAAE,CAAC,MAAM,EAAE,MAAM,CAAC,EAAE,EAAE,KAAK,EAAE,QAAQ,EAAE,CAAC,CAAC;QACjE,OAAO,MAAM,CAAC;IAChB,CAAC;IAED,aAAa,CACX,MAAM,EACN;;;;;;YAMQ,QAAQ,IAAI,OAAO;;;mBAGZ,UAAU;;;;CAI5B,EACG,MAAM,CACP,CAAC;IACF,YAAY,CAAC,WAAW,EAAE,CAAC,QAAQ,EAAE,eAAe,CAAC,EAAE,EAAE,KAAK,EAAE,QAAQ,EAAE,CAAC,CAAC;IAC5E,YAAY,CAAC,WAAW,EAAE,CAAC,QAAQ,EAAE,QAAQ,EAAE,OAAO,EAAE,qBAAqB,CAAC,EAAE,EAAE,KAAK,EAAE,QAAQ,EAAE,CAAC,CAAC;IACrG,OAAO,MAAM,CAAC;AAChB,CAAC;AAED,MAAM,UAAU,gBAAgB;IAC9B,MAAM,MAAM,GAAG,WAAW,EAAE,CAAC;IAC7B,IAAI,CAAC,UAAU,CAAC,MAAM,CAAC;QAAE,OAAO,IAAI,CAAC;IAErC,IAAI,CAAC;QACH,IAAI,QAAQ,EAAE,KAAK,QAAQ;YAAE,YAAY,CAAC,WAAW,EAAE,CAAC,QAAQ,EAAE,MAAM,CAAC,EAAE,EAAE,KAAK,EAAE,QAAQ,EAAE,CAAC,CAAC;;YAC3F,YAAY,CAAC,WAAW,EAAE,CAAC,QAAQ,EAAE,SAAS,EAAE,OAAO,EAAE,qBAAqB,CAAC,EAAE,EAAE,KAAK,EAAE,QAAQ,EAAE,CAAC,CAAC;IAC7G,CAAC;IAAC,MAAM,CAAC;QACP,iFAAiF;IACnF,CAAC;IACD,UAAU,CAAC,MAAM,CAAC,CAAC;IACnB,OAAO,MAAM,CAAC;AAChB,CAAC"}
|
package/dist/config.d.ts
ADDED
|
@@ -0,0 +1,67 @@
|
|
|
1
|
+
import { z } from 'zod';
|
|
2
|
+
export declare const CONFIG_DIR: string;
|
|
3
|
+
export declare const CONFIG_PATH: string;
|
|
4
|
+
export declare const SPOOL_PATH: string;
|
|
5
|
+
export declare const LOG_PATH: string;
|
|
6
|
+
export declare const PID_PATH: string;
|
|
7
|
+
/**
|
|
8
|
+
* On-disk config. Shape follows BLUEPRINT §9.4 so the documented example is
|
|
9
|
+
* literally valid.
|
|
10
|
+
*/
|
|
11
|
+
export declare const Config: z.ZodObject<{
|
|
12
|
+
api_url: z.ZodDefault<z.ZodString>;
|
|
13
|
+
api_key: z.ZodOptional<z.ZodString>;
|
|
14
|
+
collector_id: z.ZodOptional<z.ZodString>;
|
|
15
|
+
privacy: z.ZodPrefault<z.ZodObject<{
|
|
16
|
+
mode: z.ZodDefault<z.ZodEnum<{
|
|
17
|
+
metadata: "metadata";
|
|
18
|
+
analytics: "analytics";
|
|
19
|
+
full: "full";
|
|
20
|
+
}>>;
|
|
21
|
+
prompts: z.ZodDefault<z.ZodEnum<{
|
|
22
|
+
full: "full";
|
|
23
|
+
never: "never";
|
|
24
|
+
local_summary_only: "local_summary_only";
|
|
25
|
+
}>>;
|
|
26
|
+
code_content: z.ZodDefault<z.ZodEnum<{
|
|
27
|
+
full: "full";
|
|
28
|
+
never: "never";
|
|
29
|
+
}>>;
|
|
30
|
+
file_paths: z.ZodDefault<z.ZodEnum<{
|
|
31
|
+
never: "never";
|
|
32
|
+
relative: "relative";
|
|
33
|
+
absolute: "absolute";
|
|
34
|
+
}>>;
|
|
35
|
+
shell_arguments: z.ZodDefault<z.ZodEnum<{
|
|
36
|
+
full: "full";
|
|
37
|
+
never: "never";
|
|
38
|
+
redact_secrets: "redact_secrets";
|
|
39
|
+
}>>;
|
|
40
|
+
excluded_projects: z.ZodDefault<z.ZodArray<z.ZodString>>;
|
|
41
|
+
}, z.core.$strip>>;
|
|
42
|
+
tracking: z.ZodPrefault<z.ZodObject<{
|
|
43
|
+
idle_timeout_seconds: z.ZodDefault<z.ZodNumber>;
|
|
44
|
+
git_metadata: z.ZodDefault<z.ZodBoolean>;
|
|
45
|
+
process_metrics: z.ZodDefault<z.ZodBoolean>;
|
|
46
|
+
agents: z.ZodDefault<z.ZodArray<z.ZodString>>;
|
|
47
|
+
}, z.core.$strip>>;
|
|
48
|
+
upload: z.ZodPrefault<z.ZodObject<{
|
|
49
|
+
batch_size: z.ZodDefault<z.ZodNumber>;
|
|
50
|
+
interval_seconds: z.ZodDefault<z.ZodNumber>;
|
|
51
|
+
max_retries: z.ZodDefault<z.ZodNumber>;
|
|
52
|
+
}, z.core.$strip>>;
|
|
53
|
+
}, z.core.$strip>;
|
|
54
|
+
export type Config = z.infer<typeof Config>;
|
|
55
|
+
export declare function loadConfig(): Config;
|
|
56
|
+
export declare function saveConfig(config: Config): void;
|
|
57
|
+
/**
|
|
58
|
+
* Creates ~/.agentstrack as owner-only.
|
|
59
|
+
*
|
|
60
|
+
* The directory holds an API key, a spool of telemetry and a log. At the
|
|
61
|
+
* default umask those are world-readable, which on a shared host hands every
|
|
62
|
+
* other user a developer's session history.
|
|
63
|
+
*/
|
|
64
|
+
export declare function ensureConfigDir(): void;
|
|
65
|
+
export declare function configExists(): boolean;
|
|
66
|
+
/** Documented starting point, written on `agentstrack login`. */
|
|
67
|
+
export declare const DEFAULT_CONFIG_COMMENT = "# AgentsTrack collector configuration\n# Docs: https://github.com/agentstrack/collector#configuration\n#\n# privacy.mode:\n# metadata - counts and timings only; no titles, no prompts, no code\n# analytics - adds locally generated session titles; raw content discarded\n# full - uploads prompt text (opt-in, off by default)\n";
|