@tekdi/coding-analytics 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/dist/batcher.d.ts +15 -0
- package/dist/batcher.d.ts.map +1 -0
- package/dist/batcher.js +90 -0
- package/dist/batcher.js.map +1 -0
- package/dist/claude-hooks-receiver.d.ts +16 -0
- package/dist/claude-hooks-receiver.d.ts.map +1 -0
- package/dist/claude-hooks-receiver.js +145 -0
- package/dist/claude-hooks-receiver.js.map +1 -0
- package/dist/cli.d.ts +3 -0
- package/dist/cli.d.ts.map +1 -0
- package/dist/cli.js +314 -0
- package/dist/cli.js.map +1 -0
- package/dist/config.d.ts +50 -0
- package/dist/config.d.ts.map +1 -0
- package/dist/config.js +119 -0
- package/dist/config.js.map +1 -0
- package/dist/enricher.d.ts +28 -0
- package/dist/enricher.d.ts.map +1 -0
- package/dist/enricher.js +258 -0
- package/dist/enricher.js.map +1 -0
- package/dist/flusher.d.ts +10 -0
- package/dist/flusher.d.ts.map +1 -0
- package/dist/flusher.js +89 -0
- package/dist/flusher.js.map +1 -0
- package/dist/health-monitor.d.ts +35 -0
- package/dist/health-monitor.d.ts.map +1 -0
- package/dist/health-monitor.js +187 -0
- package/dist/health-monitor.js.map +1 -0
- package/dist/hooks-listener.d.ts +23 -0
- package/dist/hooks-listener.d.ts.map +1 -0
- package/dist/hooks-listener.js +168 -0
- package/dist/hooks-listener.js.map +1 -0
- package/dist/install-service.d.ts +15 -0
- package/dist/install-service.d.ts.map +1 -0
- package/dist/install-service.js +218 -0
- package/dist/install-service.js.map +1 -0
- package/dist/local-storage.d.ts +19 -0
- package/dist/local-storage.d.ts.map +1 -0
- package/dist/local-storage.js +152 -0
- package/dist/local-storage.js.map +1 -0
- package/dist/logger.d.ts +3 -0
- package/dist/logger.d.ts.map +1 -0
- package/dist/logger.js +59 -0
- package/dist/logger.js.map +1 -0
- package/dist/queue.d.ts +22 -0
- package/dist/queue.d.ts.map +1 -0
- package/dist/queue.js +102 -0
- package/dist/queue.js.map +1 -0
- package/package.json +49 -0
|
@@ -0,0 +1,15 @@
|
|
|
1
|
+
import { Config } from './config';
|
|
2
|
+
import { EnrichedEvent } from './enricher';
|
|
3
|
+
export declare class EventBatcher {
|
|
4
|
+
private posthog;
|
|
5
|
+
private batch;
|
|
6
|
+
private flushTimer;
|
|
7
|
+
private config;
|
|
8
|
+
private localStorage;
|
|
9
|
+
constructor(config: Config);
|
|
10
|
+
add(event: EnrichedEvent): Promise<void>;
|
|
11
|
+
flush(): Promise<void>;
|
|
12
|
+
private resetTimer;
|
|
13
|
+
shutdown(): Promise<void>;
|
|
14
|
+
}
|
|
15
|
+
//# sourceMappingURL=batcher.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"batcher.d.ts","sourceRoot":"","sources":["../batcher.ts"],"names":[],"mappings":"AACA,OAAO,EAAE,MAAM,EAAE,MAAM,UAAU,CAAC;AAClC,OAAO,EAAE,aAAa,EAAE,MAAM,YAAY,CAAC;AAI3C,qBAAa,YAAY;IACvB,OAAO,CAAC,OAAO,CAAwB;IACvC,OAAO,CAAC,KAAK,CAAuB;IACpC,OAAO,CAAC,UAAU,CAA+B;IACjD,OAAO,CAAC,MAAM,CAAS;IACvB,OAAO,CAAC,YAAY,CAAe;gBAEvB,MAAM,EAAE,MAAM;IAapB,GAAG,CAAC,KAAK,EAAE,aAAa,GAAG,OAAO,CAAC,IAAI,CAAC;IAUxC,KAAK,IAAI,OAAO,CAAC,IAAI,CAAC;IA0C5B,OAAO,CAAC,UAAU;IAYZ,QAAQ,IAAI,OAAO,CAAC,IAAI,CAAC;CAWhC"}
|
package/dist/batcher.js
ADDED
|
@@ -0,0 +1,90 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
+
exports.EventBatcher = void 0;
|
|
4
|
+
const posthog_node_1 = require("posthog-node");
|
|
5
|
+
const local_storage_1 = require("./local-storage");
|
|
6
|
+
const logger_1 = require("./logger");
|
|
7
|
+
class EventBatcher {
|
|
8
|
+
constructor(config) {
|
|
9
|
+
this.posthog = null;
|
|
10
|
+
this.batch = [];
|
|
11
|
+
this.flushTimer = null;
|
|
12
|
+
this.config = config;
|
|
13
|
+
this.localStorage = new local_storage_1.LocalStorage(config);
|
|
14
|
+
if (config.posthog.apiKey) {
|
|
15
|
+
this.posthog = new posthog_node_1.PostHog(config.posthog.apiKey, {
|
|
16
|
+
host: config.posthog.host,
|
|
17
|
+
});
|
|
18
|
+
}
|
|
19
|
+
else {
|
|
20
|
+
logger_1.logger.warn('PostHog API key not configured');
|
|
21
|
+
}
|
|
22
|
+
}
|
|
23
|
+
async add(event) {
|
|
24
|
+
this.batch.push(event);
|
|
25
|
+
if (this.batch.length >= this.config.posthog.batchSize) {
|
|
26
|
+
await this.flush();
|
|
27
|
+
}
|
|
28
|
+
else {
|
|
29
|
+
this.resetTimer();
|
|
30
|
+
}
|
|
31
|
+
}
|
|
32
|
+
async flush() {
|
|
33
|
+
if (this.batch.length === 0) {
|
|
34
|
+
return;
|
|
35
|
+
}
|
|
36
|
+
const eventsToSend = [...this.batch];
|
|
37
|
+
this.batch = [];
|
|
38
|
+
try {
|
|
39
|
+
if (!this.posthog) {
|
|
40
|
+
throw new Error('PostHog not configured');
|
|
41
|
+
}
|
|
42
|
+
// Send to PostHog
|
|
43
|
+
for (const event of eventsToSend) {
|
|
44
|
+
this.posthog.capture({
|
|
45
|
+
distinctId: event.distinct_id,
|
|
46
|
+
event: event.event,
|
|
47
|
+
properties: event.properties,
|
|
48
|
+
timestamp: new Date(event.timestamp),
|
|
49
|
+
});
|
|
50
|
+
}
|
|
51
|
+
// Flush to ensure events are sent
|
|
52
|
+
await this.posthog.flush();
|
|
53
|
+
logger_1.logger.debug('Events sent to PostHog', { count: eventsToSend.length });
|
|
54
|
+
}
|
|
55
|
+
catch (error) {
|
|
56
|
+
logger_1.logger.error('Failed to send events to PostHog', { error });
|
|
57
|
+
// Fallback to local storage
|
|
58
|
+
if (this.config.storage.fallbackToLocal) {
|
|
59
|
+
try {
|
|
60
|
+
await this.localStorage.store(eventsToSend);
|
|
61
|
+
logger_1.logger.info('Events stored locally for retry', { count: eventsToSend.length });
|
|
62
|
+
}
|
|
63
|
+
catch (storageError) {
|
|
64
|
+
logger_1.logger.error('Failed to store events locally', { error: storageError });
|
|
65
|
+
}
|
|
66
|
+
}
|
|
67
|
+
}
|
|
68
|
+
}
|
|
69
|
+
resetTimer() {
|
|
70
|
+
if (this.flushTimer) {
|
|
71
|
+
clearTimeout(this.flushTimer);
|
|
72
|
+
}
|
|
73
|
+
this.flushTimer = setTimeout(() => {
|
|
74
|
+
this.flush().catch(error => {
|
|
75
|
+
logger_1.logger.error('Failed to flush events', { error });
|
|
76
|
+
});
|
|
77
|
+
}, this.config.posthog.flushInterval);
|
|
78
|
+
}
|
|
79
|
+
async shutdown() {
|
|
80
|
+
if (this.flushTimer) {
|
|
81
|
+
clearTimeout(this.flushTimer);
|
|
82
|
+
}
|
|
83
|
+
await this.flush();
|
|
84
|
+
if (this.posthog) {
|
|
85
|
+
await this.posthog.shutdown();
|
|
86
|
+
}
|
|
87
|
+
}
|
|
88
|
+
}
|
|
89
|
+
exports.EventBatcher = EventBatcher;
|
|
90
|
+
//# sourceMappingURL=batcher.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"batcher.js","sourceRoot":"","sources":["../batcher.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1,16 @@
|
|
|
1
|
+
export declare class ClaudeHooksReceiver {
|
|
2
|
+
private enricher;
|
|
3
|
+
private batcher;
|
|
4
|
+
private config;
|
|
5
|
+
constructor();
|
|
6
|
+
private getEnricher;
|
|
7
|
+
private getBatcher;
|
|
8
|
+
/** Fast path: map → filter → queue. Exits in <5ms. No network, no git. */
|
|
9
|
+
queueEvent(hookType: string, eventData: any): Promise<void>;
|
|
10
|
+
handleEvent(hookType: string, eventData: any): Promise<void>;
|
|
11
|
+
shutdown(): Promise<void>;
|
|
12
|
+
private mapEvent;
|
|
13
|
+
private applyPrivacyFilters;
|
|
14
|
+
private redactSecrets;
|
|
15
|
+
}
|
|
16
|
+
//# sourceMappingURL=claude-hooks-receiver.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"claude-hooks-receiver.d.ts","sourceRoot":"","sources":["../claude-hooks-receiver.ts"],"names":[],"mappings":"AAOA,qBAAa,mBAAmB;IAE9B,OAAO,CAAC,QAAQ,CAAyB;IACzC,OAAO,CAAC,OAAO,CAA6B;IAC5C,OAAO,CAAC,MAAM,CAAS;;IAMvB,OAAO,CAAC,WAAW;IAKnB,OAAO,CAAC,UAAU;IAKlB,0EAA0E;IACpE,UAAU,CAAC,QAAQ,EAAE,MAAM,EAAE,SAAS,EAAE,GAAG,GAAG,OAAO,CAAC,IAAI,CAAC;IAU3D,WAAW,CAAC,QAAQ,EAAE,MAAM,EAAE,SAAS,EAAE,GAAG,GAAG,OAAO,CAAC,IAAI,CAAC;IAoB5D,QAAQ,IAAI,OAAO,CAAC,IAAI,CAAC;IAI/B,OAAO,CAAC,QAAQ;IA6EhB,OAAO,CAAC,mBAAmB;IAU3B,OAAO,CAAC,aAAa;CAStB"}
|
|
@@ -0,0 +1,145 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
+
exports.ClaudeHooksReceiver = void 0;
|
|
4
|
+
const enricher_1 = require("./enricher");
|
|
5
|
+
const batcher_1 = require("./batcher");
|
|
6
|
+
const config_1 = require("./config");
|
|
7
|
+
const logger_1 = require("./logger");
|
|
8
|
+
const queue_1 = require("./queue");
|
|
9
|
+
class ClaudeHooksReceiver {
|
|
10
|
+
constructor() {
|
|
11
|
+
// Lazy — only created if handleEvent (direct send) is used
|
|
12
|
+
this.enricher = null;
|
|
13
|
+
this.batcher = null;
|
|
14
|
+
this.config = config_1.Config.load();
|
|
15
|
+
}
|
|
16
|
+
getEnricher() {
|
|
17
|
+
if (!this.enricher)
|
|
18
|
+
this.enricher = new enricher_1.Enricher(this.config);
|
|
19
|
+
return this.enricher;
|
|
20
|
+
}
|
|
21
|
+
getBatcher() {
|
|
22
|
+
if (!this.batcher)
|
|
23
|
+
this.batcher = new batcher_1.EventBatcher(this.config);
|
|
24
|
+
return this.batcher;
|
|
25
|
+
}
|
|
26
|
+
/** Fast path: map → filter → queue. Exits in <5ms. No network, no git. */
|
|
27
|
+
async queueEvent(hookType, eventData) {
|
|
28
|
+
const event = this.mapEvent(hookType, eventData);
|
|
29
|
+
if (!event) {
|
|
30
|
+
logger_1.logger.warn('Unknown Claude hook type', { hookType });
|
|
31
|
+
return;
|
|
32
|
+
}
|
|
33
|
+
new queue_1.Queue().append(this.applyPrivacyFilters(event));
|
|
34
|
+
logger_1.logger.debug('Claude event queued', { hookType });
|
|
35
|
+
}
|
|
36
|
+
async handleEvent(hookType, eventData) {
|
|
37
|
+
try {
|
|
38
|
+
logger_1.logger.debug('Received Claude hook event', { hookType, eventData });
|
|
39
|
+
const event = this.mapEvent(hookType, eventData);
|
|
40
|
+
if (!event) {
|
|
41
|
+
logger_1.logger.warn('Unknown Claude hook type', { hookType });
|
|
42
|
+
return;
|
|
43
|
+
}
|
|
44
|
+
const filteredEvent = this.applyPrivacyFilters(event);
|
|
45
|
+
const enrichedEvent = await this.getEnricher().enrich(filteredEvent);
|
|
46
|
+
await this.getBatcher().add(enrichedEvent);
|
|
47
|
+
logger_1.logger.debug('Claude event processed', { event: enrichedEvent.event });
|
|
48
|
+
}
|
|
49
|
+
catch (error) {
|
|
50
|
+
logger_1.logger.error('Failed to handle Claude hook event', { error, hookType });
|
|
51
|
+
}
|
|
52
|
+
}
|
|
53
|
+
async shutdown() {
|
|
54
|
+
if (this.batcher)
|
|
55
|
+
await this.batcher.shutdown();
|
|
56
|
+
}
|
|
57
|
+
mapEvent(hookType, data) {
|
|
58
|
+
const timestamp = new Date().toISOString();
|
|
59
|
+
switch (hookType) {
|
|
60
|
+
case 'SessionStart':
|
|
61
|
+
return {
|
|
62
|
+
type: 'claude_session_started',
|
|
63
|
+
data: {
|
|
64
|
+
session_id: data.session_id,
|
|
65
|
+
transcript_path: data.transcript_path,
|
|
66
|
+
},
|
|
67
|
+
timestamp,
|
|
68
|
+
provider: 'claude',
|
|
69
|
+
};
|
|
70
|
+
case 'UserPromptSubmit':
|
|
71
|
+
return {
|
|
72
|
+
type: 'claude_prompt_submitted',
|
|
73
|
+
data: {
|
|
74
|
+
session_id: data.session_id,
|
|
75
|
+
prompt: this.config.capture.prompts ? data.prompt : '[redacted]',
|
|
76
|
+
prompt_length: data.prompt?.length ?? 0,
|
|
77
|
+
},
|
|
78
|
+
timestamp,
|
|
79
|
+
provider: 'claude',
|
|
80
|
+
};
|
|
81
|
+
case 'PostToolUse':
|
|
82
|
+
return {
|
|
83
|
+
type: 'claude_tool_used',
|
|
84
|
+
data: {
|
|
85
|
+
session_id: data.session_id,
|
|
86
|
+
tool_name: data.tool_name,
|
|
87
|
+
tool_input: this.config.capture.prompts ? data.tool_input : undefined,
|
|
88
|
+
// non-zero exit code signals an error
|
|
89
|
+
exit_code: data.tool_response?.exit_code ?? null,
|
|
90
|
+
},
|
|
91
|
+
timestamp,
|
|
92
|
+
provider: 'claude',
|
|
93
|
+
};
|
|
94
|
+
case 'SubagentStart':
|
|
95
|
+
return {
|
|
96
|
+
type: 'claude_subagent_started',
|
|
97
|
+
data: {
|
|
98
|
+
session_id: data.session_id,
|
|
99
|
+
},
|
|
100
|
+
timestamp,
|
|
101
|
+
provider: 'claude',
|
|
102
|
+
};
|
|
103
|
+
case 'SubagentStop':
|
|
104
|
+
return {
|
|
105
|
+
type: 'claude_subagent_stopped',
|
|
106
|
+
data: {
|
|
107
|
+
session_id: data.session_id,
|
|
108
|
+
},
|
|
109
|
+
timestamp,
|
|
110
|
+
provider: 'claude',
|
|
111
|
+
};
|
|
112
|
+
case 'Stop':
|
|
113
|
+
return {
|
|
114
|
+
type: 'claude_session_stopped',
|
|
115
|
+
data: {
|
|
116
|
+
session_id: data.session_id,
|
|
117
|
+
stop_hook_active: data.stop_hook_active ?? false,
|
|
118
|
+
},
|
|
119
|
+
timestamp,
|
|
120
|
+
provider: 'claude',
|
|
121
|
+
};
|
|
122
|
+
default:
|
|
123
|
+
return null;
|
|
124
|
+
}
|
|
125
|
+
}
|
|
126
|
+
applyPrivacyFilters(event) {
|
|
127
|
+
if (!this.config.privacy.redactSecrets)
|
|
128
|
+
return event;
|
|
129
|
+
if (event.data.prompt) {
|
|
130
|
+
event.data.prompt = this.redactSecrets(event.data.prompt);
|
|
131
|
+
}
|
|
132
|
+
return event;
|
|
133
|
+
}
|
|
134
|
+
redactSecrets(text) {
|
|
135
|
+
text = text.replace(/api[_-]?key[s]?['"]?\s*[:=]\s*['"]?([A-Za-z0-9_-]{20,})/gi, 'api_key=[REDACTED]');
|
|
136
|
+
text = text.replace(/Bearer\s+([A-Za-z0-9_-]{20,})/gi, 'Bearer [REDACTED]');
|
|
137
|
+
text = text.replace(/eyJ[A-Za-z0-9_-]+\.eyJ[A-Za-z0-9_-]+\.[A-Za-z0-9_-]+/g, '[JWT_REDACTED]');
|
|
138
|
+
text = text.replace(/password['"]?\s*[:=]\s*['"]?([^\s'"]+)/gi, 'password=[REDACTED]');
|
|
139
|
+
text = text.replace(/(postgres|mysql|mongodb):\/\/[^@]+@/g, '$1://[USER]:[PASSWORD]@');
|
|
140
|
+
text = text.replace(/AKIA[0-9A-Z]{16}/g, '[AWS_KEY_REDACTED]');
|
|
141
|
+
return text;
|
|
142
|
+
}
|
|
143
|
+
}
|
|
144
|
+
exports.ClaudeHooksReceiver = ClaudeHooksReceiver;
|
|
145
|
+
//# sourceMappingURL=claude-hooks-receiver.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"claude-hooks-receiver.js","sourceRoot":"","sources":["../claude-hooks-receiver.ts"],"names":[],"mappings":";;;AAAA,yCAAsC;AACtC,uCAAyC;AACzC,qCAAkC;AAClC,qCAAkC;AAElC,mCAAgC;AAEhC,MAAa,mBAAmB;IAM9B;QALA,2DAA2D;QACnD,aAAQ,GAAoB,IAAI,CAAC;QACjC,YAAO,GAAwB,IAAI,CAAC;QAI1C,IAAI,CAAC,MAAM,GAAG,eAAM,CAAC,IAAI,EAAE,CAAC;IAC9B,CAAC;IAEO,WAAW;QACjB,IAAI,CAAC,IAAI,CAAC,QAAQ;YAAE,IAAI,CAAC,QAAQ,GAAG,IAAI,mBAAQ,CAAC,IAAI,CAAC,MAAM,CAAC,CAAC;QAC9D,OAAO,IAAI,CAAC,QAAQ,CAAC;IACvB,CAAC;IAEO,UAAU;QAChB,IAAI,CAAC,IAAI,CAAC,OAAO;YAAE,IAAI,CAAC,OAAO,GAAG,IAAI,sBAAY,CAAC,IAAI,CAAC,MAAM,CAAC,CAAC;QAChE,OAAO,IAAI,CAAC,OAAO,CAAC;IACtB,CAAC;IAED,0EAA0E;IAC1E,KAAK,CAAC,UAAU,CAAC,QAAgB,EAAE,SAAc;QAC/C,MAAM,KAAK,GAAG,IAAI,CAAC,QAAQ,CAAC,QAAQ,EAAE,SAAS,CAAC,CAAC;QACjD,IAAI,CAAC,KAAK,EAAE,CAAC;YACX,eAAM,CAAC,IAAI,CAAC,0BAA0B,EAAE,EAAE,QAAQ,EAAE,CAAC,CAAC;YACtD,OAAO;QACT,CAAC;QACD,IAAI,aAAK,EAAE,CAAC,MAAM,CAAC,IAAI,CAAC,mBAAmB,CAAC,KAAK,CAAC,CAAC,CAAC;QACpD,eAAM,CAAC,KAAK,CAAC,qBAAqB,EAAE,EAAE,QAAQ,EAAE,CAAC,CAAC;IACpD,CAAC;IAED,KAAK,CAAC,WAAW,CAAC,QAAgB,EAAE,SAAc;QAChD,IAAI,CAAC;YACH,eAAM,CAAC,KAAK,CAAC,4BAA4B,EAAE,EAAE,QAAQ,EAAE,SAAS,EAAE,CAAC,CAAC;YAEpE,MAAM,KAAK,GAAG,IAAI,CAAC,QAAQ,CAAC,QAAQ,EAAE,SAAS,CAAC,CAAC;YACjD,IAAI,CAAC,KAAK,EAAE,CAAC;gBACX,eAAM,CAAC,IAAI,CAAC,0BAA0B,EAAE,EAAE,QAAQ,EAAE,CAAC,CAAC;gBACtD,OAAO;YACT,CAAC;YAED,MAAM,aAAa,GAAG,IAAI,CAAC,mBAAmB,CAAC,KAAK,CAAC,CAAC;YACtD,MAAM,aAAa,GAAG,MAAM,IAAI,CAAC,WAAW,EAAE,CAAC,MAAM,CAAC,aAAa,CAAC,CAAC;YACrE,MAAM,IAAI,CAAC,UAAU,EAAE,CAAC,GAAG,CAAC,aAAa,CAAC,CAAC;YAE3C,eAAM,CAAC,KAAK,CAAC,wBAAwB,EAAE,EAAE,KAAK,EAAE,aAAa,CAAC,KAAK,EAAE,CAAC,CAAC;QACzE,CAAC;QAAC,OAAO,KAAK,EAAE,CAAC;YACf,eAAM,CAAC,KAAK,CAAC,oCAAoC,EAAE,EAAE,KAAK,EAAE,QAAQ,EAAE,CAAC,CAAC;QAC1E,CAAC;IACH,CAAC;IAED,KAAK,CAAC,QAAQ;QACZ,IAAI,IAAI,CAAC,OAAO;YAAE,MAAM,IAAI,CAAC,OAAO,CAAC,QAAQ,EAAE,CAAC;IAClD,CAAC;IAEO,QAAQ,CAAC,QAAgB,EAAE,IAAS;QAC1C,MAAM,SAAS,GAAG,IAAI,IAAI,EAAE,CAAC,WAAW,EAAE,CAAC;QAE3C,QAAQ,QAAQ,EAAE,CAAC;YACjB,KAAK,cAAc;gBACjB,OAAO;oBACL,IAAI,EAAE,wBAAwB;oBAC9B,IAAI,EAAE;wBACJ,UAAU,EAAE,IAAI,CAAC,UAAU;wBAC3B,eAAe,EAAE,IAAI,CAAC,eAAe;qBACtC;oBACD,SAAS;oBACT,QAAQ,EAAE,QAAQ;iBACnB,CAAC;YAEJ,KAAK,kBAAkB;gBACrB,OAAO;oBACL,IAAI,EAAE,yBAAyB;oBAC/B,IAAI,EAAE;wBACJ,UAAU,EAAE,IAAI,CAAC,UAAU;wBAC3B,MAAM,EAAE,IAAI,CAAC,MAAM,CAAC,OAAO,CAAC,OAAO,CAAC,CAAC,CAAC,IAAI,CAAC,MAAM,CAAC,CAAC,CAAC,YAAY;wBAChE,aAAa,EAAE,IAAI,CAAC,MAAM,EAAE,MAAM,IAAI,CAAC;qBACxC;oBACD,SAAS;oBACT,QAAQ,EAAE,QAAQ;iBACnB,CAAC;YAEJ,KAAK,aAAa;gBAChB,OAAO;oBACL,IAAI,EAAE,kBAAkB;oBACxB,IAAI,EAAE;wBACJ,UAAU,EAAE,IAAI,CAAC,UAAU;wBAC3B,SAAS,EAAE,IAAI,CAAC,SAAS;wBACzB,UAAU,EAAE,IAAI,CAAC,MAAM,CAAC,OAAO,CAAC,OAAO,CAAC,CAAC,CAAC,IAAI,CAAC,UAAU,CAAC,CAAC,CAAC,SAAS;wBACrE,sCAAsC;wBACtC,SAAS,EAAE,IAAI,CAAC,aAAa,EAAE,SAAS,IAAI,IAAI;qBACjD;oBACD,SAAS;oBACT,QAAQ,EAAE,QAAQ;iBACnB,CAAC;YAEJ,KAAK,eAAe;gBAClB,OAAO;oBACL,IAAI,EAAE,yBAAyB;oBAC/B,IAAI,EAAE;wBACJ,UAAU,EAAE,IAAI,CAAC,UAAU;qBAC5B;oBACD,SAAS;oBACT,QAAQ,EAAE,QAAQ;iBACnB,CAAC;YAEJ,KAAK,cAAc;gBACjB,OAAO;oBACL,IAAI,EAAE,yBAAyB;oBAC/B,IAAI,EAAE;wBACJ,UAAU,EAAE,IAAI,CAAC,UAAU;qBAC5B;oBACD,SAAS;oBACT,QAAQ,EAAE,QAAQ;iBACnB,CAAC;YAEJ,KAAK,MAAM;gBACT,OAAO;oBACL,IAAI,EAAE,wBAAwB;oBAC9B,IAAI,EAAE;wBACJ,UAAU,EAAE,IAAI,CAAC,UAAU;wBAC3B,gBAAgB,EAAE,IAAI,CAAC,gBAAgB,IAAI,KAAK;qBACjD;oBACD,SAAS;oBACT,QAAQ,EAAE,QAAQ;iBACnB,CAAC;YAEJ;gBACE,OAAO,IAAI,CAAC;QAChB,CAAC;IACH,CAAC;IAEO,mBAAmB,CAAC,KAAgB;QAC1C,IAAI,CAAC,IAAI,CAAC,MAAM,CAAC,OAAO,CAAC,aAAa;YAAE,OAAO,KAAK,CAAC;QAErD,IAAI,KAAK,CAAC,IAAI,CAAC,MAAM,EAAE,CAAC;YACtB,KAAK,CAAC,IAAI,CAAC,MAAM,GAAG,IAAI,CAAC,aAAa,CAAC,KAAK,CAAC,IAAI,CAAC,MAAM,CAAC,CAAC;QAC5D,CAAC;QAED,OAAO,KAAK,CAAC;IACf,CAAC;IAEO,aAAa,CAAC,IAAY;QAChC,IAAI,GAAG,IAAI,CAAC,OAAO,CAAC,2DAA2D,EAAE,oBAAoB,CAAC,CAAC;QACvG,IAAI,GAAG,IAAI,CAAC,OAAO,CAAC,iCAAiC,EAAE,mBAAmB,CAAC,CAAC;QAC5E,IAAI,GAAG,IAAI,CAAC,OAAO,CAAC,uDAAuD,EAAE,gBAAgB,CAAC,CAAC;QAC/F,IAAI,GAAG,IAAI,CAAC,OAAO,CAAC,0CAA0C,EAAE,qBAAqB,CAAC,CAAC;QACvF,IAAI,GAAG,IAAI,CAAC,OAAO,CAAC,sCAAsC,EAAE,yBAAyB,CAAC,CAAC;QACvF,IAAI,GAAG,IAAI,CAAC,OAAO,CAAC,mBAAmB,EAAE,oBAAoB,CAAC,CAAC;QAC/D,OAAO,IAAI,CAAC;IACd,CAAC;CACF;AAvJD,kDAuJC"}
|
package/dist/cli.d.ts
ADDED
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"cli.d.ts","sourceRoot":"","sources":["../cli.ts"],"names":[],"mappings":""}
|
package/dist/cli.js
ADDED
|
@@ -0,0 +1,314 @@
|
|
|
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 hooks_listener_1 = require("./hooks-listener");
|
|
39
|
+
const claude_hooks_receiver_1 = require("./claude-hooks-receiver");
|
|
40
|
+
const config_1 = require("./config");
|
|
41
|
+
const health_monitor_1 = require("./health-monitor");
|
|
42
|
+
const logger_1 = require("./logger");
|
|
43
|
+
const install_service_1 = require("./install-service");
|
|
44
|
+
const flusher_1 = require("./flusher");
|
|
45
|
+
const fs = __importStar(require("fs"));
|
|
46
|
+
const path = __importStar(require("path"));
|
|
47
|
+
const program = new commander_1.Command();
|
|
48
|
+
program
|
|
49
|
+
.name('coding-analytics')
|
|
50
|
+
.description('Monitor Cursor and Claude Code usage and send analytics to PostHog')
|
|
51
|
+
.version('1.0.0');
|
|
52
|
+
// ── Cursor hook (fast path → queue) ──────────────────────────────────────────
|
|
53
|
+
program
|
|
54
|
+
.command('hook <event-type>')
|
|
55
|
+
.description('Process a Cursor hook event (called by Cursor, writes to queue)')
|
|
56
|
+
.option('--data <json>', 'Event data as JSON')
|
|
57
|
+
.action(async (eventType, options) => {
|
|
58
|
+
try {
|
|
59
|
+
const eventData = options.data ? JSON.parse(options.data) : {};
|
|
60
|
+
const listener = new hooks_listener_1.HooksListener();
|
|
61
|
+
await listener.queueEvent(eventType, eventData);
|
|
62
|
+
}
|
|
63
|
+
catch (error) {
|
|
64
|
+
logger_1.logger.error('Failed to queue Cursor hook event', { error, eventType });
|
|
65
|
+
process.exit(1);
|
|
66
|
+
}
|
|
67
|
+
});
|
|
68
|
+
// ── Claude Code hook (fast path → queue, reads stdin) ────────────────────────
|
|
69
|
+
program
|
|
70
|
+
.command('claude-hook <hook-type>')
|
|
71
|
+
.description('Process a Claude Code hook event (called by Claude Code, reads stdin)')
|
|
72
|
+
.action(async (hookType) => {
|
|
73
|
+
try {
|
|
74
|
+
const raw = await readStdin();
|
|
75
|
+
const eventData = raw ? JSON.parse(raw) : {};
|
|
76
|
+
const receiver = new claude_hooks_receiver_1.ClaudeHooksReceiver();
|
|
77
|
+
await receiver.queueEvent(hookType, eventData);
|
|
78
|
+
}
|
|
79
|
+
catch (error) {
|
|
80
|
+
logger_1.logger.error('Failed to queue Claude hook event', { error, hookType });
|
|
81
|
+
process.exit(1);
|
|
82
|
+
}
|
|
83
|
+
});
|
|
84
|
+
// ── Flush (called by cron every 5 min) ───────────────────────────────────────
|
|
85
|
+
program
|
|
86
|
+
.command('flush')
|
|
87
|
+
.description('Enrich and send queued events to PostHog (run by cron)')
|
|
88
|
+
.action(async () => {
|
|
89
|
+
try {
|
|
90
|
+
const flusher = new flusher_1.Flusher();
|
|
91
|
+
const result = await flusher.flush();
|
|
92
|
+
if (result.processed > 0 || result.failed > 0) {
|
|
93
|
+
console.log(`Flushed: ${result.processed} sent, ${result.failed} failed`);
|
|
94
|
+
}
|
|
95
|
+
}
|
|
96
|
+
catch (error) {
|
|
97
|
+
logger_1.logger.error('Flush failed', { error });
|
|
98
|
+
process.exit(1);
|
|
99
|
+
}
|
|
100
|
+
});
|
|
101
|
+
// ── Config ────────────────────────────────────────────────────────────────────
|
|
102
|
+
program
|
|
103
|
+
.command('config')
|
|
104
|
+
.description('Configure coding-analytics')
|
|
105
|
+
.option('--posthog-key <key>', 'Set PostHog API key')
|
|
106
|
+
.option('--posthog-host <url>', 'Set PostHog host')
|
|
107
|
+
.option('--edit', 'Open config file in editor')
|
|
108
|
+
.option('--show', 'Show current configuration')
|
|
109
|
+
.action(async (options) => {
|
|
110
|
+
const config = config_1.Config.load();
|
|
111
|
+
if (options.posthogKey) {
|
|
112
|
+
config.posthog.apiKey = options.posthogKey;
|
|
113
|
+
config.save();
|
|
114
|
+
console.log('✓ PostHog API key updated');
|
|
115
|
+
}
|
|
116
|
+
if (options.posthogHost) {
|
|
117
|
+
config.posthog.host = options.posthogHost;
|
|
118
|
+
config.save();
|
|
119
|
+
console.log('✓ PostHog host updated');
|
|
120
|
+
}
|
|
121
|
+
if (options.edit) {
|
|
122
|
+
const configPath = config_1.Config.getConfigPath();
|
|
123
|
+
const editor = process.env.EDITOR || 'nano';
|
|
124
|
+
const { spawn } = require('child_process');
|
|
125
|
+
spawn(editor, [configPath], { stdio: 'inherit' });
|
|
126
|
+
}
|
|
127
|
+
if (options.show || (!options.posthogKey && !options.posthogHost && !options.edit)) {
|
|
128
|
+
console.log('Current configuration:');
|
|
129
|
+
console.log(JSON.stringify(config.toJSON(), null, 2));
|
|
130
|
+
}
|
|
131
|
+
});
|
|
132
|
+
// ── Install hooks ─────────────────────────────────────────────────────────────
|
|
133
|
+
program
|
|
134
|
+
.command('install-hooks')
|
|
135
|
+
.description('Install hooks configuration and flush cron')
|
|
136
|
+
.option('--provider <provider>', 'Provider to install: cursor, claude, all', 'all')
|
|
137
|
+
.action(async (options) => {
|
|
138
|
+
try {
|
|
139
|
+
const installer = new install_service_1.InstallService();
|
|
140
|
+
const provider = options.provider;
|
|
141
|
+
if (provider === 'cursor' || provider === 'all') {
|
|
142
|
+
await installer.installHooks();
|
|
143
|
+
console.log('✓ Cursor hooks installed');
|
|
144
|
+
}
|
|
145
|
+
if (provider === 'claude' || provider === 'all') {
|
|
146
|
+
await installer.installClaudeHooks();
|
|
147
|
+
console.log('✓ Claude Code hooks installed');
|
|
148
|
+
}
|
|
149
|
+
try {
|
|
150
|
+
install_service_1.InstallService.installCron();
|
|
151
|
+
console.log('✓ Flush cron installed (every 5 min)');
|
|
152
|
+
}
|
|
153
|
+
catch (cronError) {
|
|
154
|
+
console.warn(`⚠ Cron not installed: ${cronError.message}`);
|
|
155
|
+
}
|
|
156
|
+
console.log('\nNext steps:');
|
|
157
|
+
if (provider === 'cursor' || provider === 'all')
|
|
158
|
+
console.log(' - Restart Cursor');
|
|
159
|
+
if (provider === 'claude' || provider === 'all')
|
|
160
|
+
console.log(' - Restart Claude Code');
|
|
161
|
+
console.log('\nRun: coding-analytics status');
|
|
162
|
+
}
|
|
163
|
+
catch (error) {
|
|
164
|
+
logger_1.logger.error('Failed to install hooks', { error });
|
|
165
|
+
console.error('✗ Failed to install hooks:', error.message);
|
|
166
|
+
process.exit(1);
|
|
167
|
+
}
|
|
168
|
+
});
|
|
169
|
+
// ── Uninstall hooks ───────────────────────────────────────────────────────────
|
|
170
|
+
program
|
|
171
|
+
.command('uninstall-hooks')
|
|
172
|
+
.description('Remove hooks configuration and flush cron')
|
|
173
|
+
.option('--provider <provider>', 'Provider to uninstall: cursor, claude, all', 'all')
|
|
174
|
+
.action(async (options) => {
|
|
175
|
+
try {
|
|
176
|
+
const installer = new install_service_1.InstallService();
|
|
177
|
+
const provider = options.provider;
|
|
178
|
+
if (provider === 'cursor' || provider === 'all') {
|
|
179
|
+
await installer.uninstallHooks();
|
|
180
|
+
console.log('✓ Cursor hooks uninstalled');
|
|
181
|
+
}
|
|
182
|
+
if (provider === 'claude' || provider === 'all') {
|
|
183
|
+
await installer.uninstallClaudeHooks();
|
|
184
|
+
console.log('✓ Claude Code hooks uninstalled');
|
|
185
|
+
}
|
|
186
|
+
// Only remove cron if both providers are uninstalled
|
|
187
|
+
if (provider === 'all') {
|
|
188
|
+
install_service_1.InstallService.uninstallCron();
|
|
189
|
+
console.log('✓ Flush cron removed');
|
|
190
|
+
}
|
|
191
|
+
}
|
|
192
|
+
catch (error) {
|
|
193
|
+
logger_1.logger.error('Failed to uninstall hooks', { error });
|
|
194
|
+
console.error('✗ Failed to uninstall hooks:', error.message);
|
|
195
|
+
process.exit(1);
|
|
196
|
+
}
|
|
197
|
+
});
|
|
198
|
+
// ── Status ────────────────────────────────────────────────────────────────────
|
|
199
|
+
program
|
|
200
|
+
.command('status')
|
|
201
|
+
.description('Check coding-analytics status')
|
|
202
|
+
.action(async () => {
|
|
203
|
+
const health = new health_monitor_1.HealthMonitor();
|
|
204
|
+
const status = await health.check();
|
|
205
|
+
const c = status.checks;
|
|
206
|
+
const tick = (v) => v ? '✓' : '✗';
|
|
207
|
+
console.log('\n=== Coding Analytics Status ===\n');
|
|
208
|
+
console.log(`Overall: ${tick(status.status === 'healthy')} ${status.status}`);
|
|
209
|
+
console.log('\nHooks & Infrastructure:');
|
|
210
|
+
console.log(` Cursor Hooks: ${tick(c.cursorHooks)} ${c.cursorHooks ? 'Installed' : 'Not installed'}`);
|
|
211
|
+
console.log(` Claude Hooks: ${tick(c.claudeHooks)} ${c.claudeHooks ? 'Installed' : 'Not installed'}`);
|
|
212
|
+
console.log(` Flush Cron: ${tick(c.cron)} ${c.cron ? 'Installed (every 5 min)' : 'Not installed — run: coding-analytics install-hooks'}`);
|
|
213
|
+
console.log(` Queue: ${c.queueSize} event(s) pending`);
|
|
214
|
+
console.log('\nBackend:');
|
|
215
|
+
console.log(` PostHog: ${tick(c.posthog)} ${c.posthog ? 'Connected' : 'Disconnected'}`);
|
|
216
|
+
console.log(` Local Storage: ${tick(c.localStorage)} ${c.localStorage ? 'OK' : 'Error'}`);
|
|
217
|
+
console.log(` Last Event: ${c.lastEvent || 'Never'}`);
|
|
218
|
+
console.log('\nAuth IDs:');
|
|
219
|
+
console.log(` Claude: ${c.authIds.claude ?? '(not found)'}`);
|
|
220
|
+
console.log(` Cursor: ${c.authIds.cursor ?? '(not found)'}`);
|
|
221
|
+
console.log('');
|
|
222
|
+
});
|
|
223
|
+
// ── Test ──────────────────────────────────────────────────────────────────────
|
|
224
|
+
program
|
|
225
|
+
.command('test')
|
|
226
|
+
.description('Test PostHog connection')
|
|
227
|
+
.action(async () => {
|
|
228
|
+
const health = new health_monitor_1.HealthMonitor();
|
|
229
|
+
console.log('Testing PostHog connection...');
|
|
230
|
+
const connected = await health.testPostHog();
|
|
231
|
+
if (connected) {
|
|
232
|
+
console.log('✓ Connected to PostHog successfully');
|
|
233
|
+
}
|
|
234
|
+
else {
|
|
235
|
+
console.error('✗ Failed to connect to PostHog');
|
|
236
|
+
console.log('\nTroubleshooting:');
|
|
237
|
+
console.log('1. Check your API key: coding-analytics config --show');
|
|
238
|
+
console.log('2. Verify PostHog host is correct');
|
|
239
|
+
console.log('3. Check network connectivity');
|
|
240
|
+
process.exit(1);
|
|
241
|
+
}
|
|
242
|
+
});
|
|
243
|
+
// ── Events ────────────────────────────────────────────────────────────────────
|
|
244
|
+
program
|
|
245
|
+
.command('events')
|
|
246
|
+
.description('View recent sent events (from local fallback storage)')
|
|
247
|
+
.option('--recent [count]', 'Show N most recent events', '10')
|
|
248
|
+
.option('--provider <provider>', 'Filter by provider: cursor, claude', '')
|
|
249
|
+
.action(async (options) => {
|
|
250
|
+
const { LocalStorage } = await Promise.resolve().then(() => __importStar(require('./local-storage')));
|
|
251
|
+
const storage = new LocalStorage();
|
|
252
|
+
const count = parseInt(options.recent, 10);
|
|
253
|
+
let events = await storage.getRecent(count);
|
|
254
|
+
if (options.provider) {
|
|
255
|
+
events = events.filter(e => e.properties?.provider === options.provider);
|
|
256
|
+
}
|
|
257
|
+
console.log(`\n=== Recent ${count} Events ===\n`);
|
|
258
|
+
events.forEach((event, i) => {
|
|
259
|
+
const providerTag = event.properties?.provider ? ` [${event.properties.provider}]` : '';
|
|
260
|
+
console.log(`${i + 1}. ${event.event}${providerTag} - ${event.timestamp}`);
|
|
261
|
+
console.log(` ${JSON.stringify(event.properties, null, 2)}`);
|
|
262
|
+
console.log('');
|
|
263
|
+
});
|
|
264
|
+
});
|
|
265
|
+
// ── Logs ──────────────────────────────────────────────────────────────────────
|
|
266
|
+
program
|
|
267
|
+
.command('logs')
|
|
268
|
+
.description('View coding-analytics logs')
|
|
269
|
+
.option('--tail', 'Follow logs in real-time')
|
|
270
|
+
.option('--lines [count]', 'Number of lines to show', '50')
|
|
271
|
+
.action((options) => {
|
|
272
|
+
const logPath = path.join(config_1.Config.getDataDir(), 'logs', 'coding-analytics.log');
|
|
273
|
+
if (!fs.existsSync(logPath)) {
|
|
274
|
+
console.log('No logs found');
|
|
275
|
+
return;
|
|
276
|
+
}
|
|
277
|
+
const { spawn } = require('child_process');
|
|
278
|
+
if (options.tail) {
|
|
279
|
+
spawn('tail', ['-f', logPath], { stdio: 'inherit' });
|
|
280
|
+
}
|
|
281
|
+
else {
|
|
282
|
+
spawn('tail', ['-n', options.lines, logPath], { stdio: 'inherit' });
|
|
283
|
+
}
|
|
284
|
+
});
|
|
285
|
+
// ── Retry ─────────────────────────────────────────────────────────────────────
|
|
286
|
+
program
|
|
287
|
+
.command('retry')
|
|
288
|
+
.description('Retry events that failed to send to PostHog (from local fallback storage)')
|
|
289
|
+
.action(async () => {
|
|
290
|
+
const { LocalStorage } = await Promise.resolve().then(() => __importStar(require('./local-storage')));
|
|
291
|
+
const storage = new LocalStorage();
|
|
292
|
+
console.log('Retrying failed events...');
|
|
293
|
+
const result = await storage.retryFailed();
|
|
294
|
+
console.log(`✓ Successfully sent ${result.success} events`);
|
|
295
|
+
if (result.failed > 0) {
|
|
296
|
+
console.log(`✗ Failed to send ${result.failed} events`);
|
|
297
|
+
}
|
|
298
|
+
});
|
|
299
|
+
// ── Helpers ───────────────────────────────────────────────────────────────────
|
|
300
|
+
function readStdin() {
|
|
301
|
+
return new Promise((resolve) => {
|
|
302
|
+
if (process.stdin.isTTY) {
|
|
303
|
+
resolve('');
|
|
304
|
+
return;
|
|
305
|
+
}
|
|
306
|
+
let data = '';
|
|
307
|
+
process.stdin.setEncoding('utf-8');
|
|
308
|
+
process.stdin.on('data', chunk => { data += chunk; });
|
|
309
|
+
process.stdin.on('end', () => resolve(data.trim()));
|
|
310
|
+
process.stdin.on('error', () => resolve(''));
|
|
311
|
+
});
|
|
312
|
+
}
|
|
313
|
+
program.parse();
|
|
314
|
+
//# sourceMappingURL=cli.js.map
|
package/dist/cli.js.map
ADDED
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"cli.js","sourceRoot":"","sources":["../cli.ts"],"names":[],"mappings":"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"}
|