@agent-relay/telemetry 2.0.5

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.
@@ -0,0 +1,19 @@
1
+ /**
2
+ * PostHog telemetry client singleton.
3
+ */
4
+ import { getAnonymousId } from './config.js';
5
+ import type { TelemetryEventName, TelemetryEventMap } from './events.js';
6
+ export declare function initTelemetry(options?: {
7
+ showNotice?: boolean;
8
+ }): void;
9
+ export declare function track<E extends TelemetryEventName>(event: E, properties?: TelemetryEventMap[E]): void;
10
+ export declare function shutdown(): Promise<void>;
11
+ export declare function isEnabled(): boolean;
12
+ export { getAnonymousId };
13
+ export declare function getStatus(): {
14
+ enabled: boolean;
15
+ disabledByEnv: boolean;
16
+ anonymousId: string;
17
+ notifiedAt: string | undefined;
18
+ };
19
+ //# sourceMappingURL=client.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"client.d.ts","sourceRoot":"","sources":["../src/client.ts"],"names":[],"mappings":"AAAA;;GAEG;AAOH,OAAO,EAEL,cAAc,EAKf,MAAM,aAAa,CAAC;AACrB,OAAO,KAAK,EAEV,kBAAkB,EAClB,iBAAiB,EAClB,MAAM,aAAa,CAAC;AA8DrB,wBAAgB,aAAa,CAAC,OAAO,GAAE;IAAE,UAAU,CAAC,EAAE,OAAO,CAAA;CAAO,GAAG,IAAI,CAqB1E;AAED,wBAAgB,KAAK,CAAC,CAAC,SAAS,kBAAkB,EAChD,KAAK,EAAE,CAAC,EACR,UAAU,CAAC,EAAE,iBAAiB,CAAC,CAAC,CAAC,GAChC,IAAI,CAWN;AAED,wBAAsB,QAAQ,IAAI,OAAO,CAAC,IAAI,CAAC,CAa9C;AAED,wBAAgB,SAAS,IAAI,OAAO,CAEnC;AAED,OAAO,EAAE,cAAc,EAAE,CAAC;AAE1B,wBAAgB,SAAS,IAAI;IAC3B,OAAO,EAAE,OAAO,CAAC;IACjB,aAAa,EAAE,OAAO,CAAC;IACvB,WAAW,EAAE,MAAM,CAAC;IACpB,UAAU,EAAE,MAAM,GAAG,SAAS,CAAC;CAChC,CAQA"}
package/dist/client.js ADDED
@@ -0,0 +1,125 @@
1
+ /**
2
+ * PostHog telemetry client singleton.
3
+ */
4
+ import { PostHog } from 'posthog-node';
5
+ import os from 'node:os';
6
+ import fs from 'node:fs';
7
+ import path from 'node:path';
8
+ import { fileURLToPath } from 'node:url';
9
+ import { isTelemetryEnabled, getAnonymousId, wasNotified, markNotified, isDisabledByEnv, loadPrefs, } from './config.js';
10
+ import { getPostHogConfig } from './posthog-config.js';
11
+ let client = null;
12
+ let commonProps = null;
13
+ let anonymousId = null;
14
+ let initialized = false;
15
+ function findPackageJson(startDir) {
16
+ let dir = startDir;
17
+ while (dir !== path.dirname(dir)) {
18
+ const candidate = path.join(dir, 'package.json');
19
+ if (fs.existsSync(candidate)) {
20
+ return candidate;
21
+ }
22
+ dir = path.dirname(dir);
23
+ }
24
+ return null;
25
+ }
26
+ function getVersion() {
27
+ try {
28
+ const __filename = fileURLToPath(import.meta.url);
29
+ const __dirname = path.dirname(__filename);
30
+ const packageJsonPath = findPackageJson(__dirname);
31
+ if (packageJsonPath) {
32
+ const pkg = JSON.parse(fs.readFileSync(packageJsonPath, 'utf-8'));
33
+ return pkg.version || 'unknown';
34
+ }
35
+ }
36
+ catch {
37
+ // Fall through
38
+ }
39
+ return 'unknown';
40
+ }
41
+ function buildCommonProperties() {
42
+ return {
43
+ agent_relay_version: getVersion(),
44
+ os: process.platform,
45
+ os_version: os.release(),
46
+ node_version: process.version.slice(1),
47
+ arch: process.arch,
48
+ };
49
+ }
50
+ function showFirstRunNotice() {
51
+ if (wasNotified())
52
+ return;
53
+ if (isDisabledByEnv()) {
54
+ markNotified();
55
+ return;
56
+ }
57
+ console.log('');
58
+ console.log('Agent Relay collects anonymous usage data to improve the product.');
59
+ console.log('Run `agent-relay telemetry disable` to opt out.');
60
+ console.log('Learn more: https://agent-relay.com/telemetry');
61
+ console.log('');
62
+ markNotified();
63
+ }
64
+ export function initTelemetry(options = {}) {
65
+ if (initialized)
66
+ return;
67
+ initialized = true;
68
+ if (options.showNotice !== false) {
69
+ showFirstRunNotice();
70
+ }
71
+ if (!isTelemetryEnabled())
72
+ return;
73
+ const posthogConfig = getPostHogConfig();
74
+ if (!posthogConfig)
75
+ return;
76
+ client = new PostHog(posthogConfig.apiKey, {
77
+ host: posthogConfig.host,
78
+ flushAt: 10,
79
+ flushInterval: 10000,
80
+ });
81
+ commonProps = buildCommonProperties();
82
+ anonymousId = getAnonymousId();
83
+ }
84
+ export function track(event, properties) {
85
+ if (!client || !commonProps || !anonymousId)
86
+ return;
87
+ client.capture({
88
+ distinctId: anonymousId,
89
+ event,
90
+ properties: {
91
+ ...commonProps,
92
+ ...properties,
93
+ },
94
+ });
95
+ }
96
+ export async function shutdown() {
97
+ if (!client)
98
+ return;
99
+ try {
100
+ await client.shutdown();
101
+ }
102
+ catch {
103
+ // Ignore
104
+ }
105
+ finally {
106
+ client = null;
107
+ commonProps = null;
108
+ anonymousId = null;
109
+ initialized = false;
110
+ }
111
+ }
112
+ export function isEnabled() {
113
+ return isTelemetryEnabled();
114
+ }
115
+ export { getAnonymousId };
116
+ export function getStatus() {
117
+ const prefs = loadPrefs();
118
+ return {
119
+ enabled: isTelemetryEnabled(),
120
+ disabledByEnv: isDisabledByEnv(),
121
+ anonymousId: prefs.anonymousId,
122
+ notifiedAt: prefs.notifiedAt,
123
+ };
124
+ }
125
+ //# sourceMappingURL=client.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"client.js","sourceRoot":"","sources":["../src/client.ts"],"names":[],"mappings":"AAAA;;GAEG;AAEH,OAAO,EAAE,OAAO,EAAE,MAAM,cAAc,CAAC;AACvC,OAAO,EAAE,MAAM,SAAS,CAAC;AACzB,OAAO,EAAE,MAAM,SAAS,CAAC;AACzB,OAAO,IAAI,MAAM,WAAW,CAAC;AAC7B,OAAO,EAAE,aAAa,EAAE,MAAM,UAAU,CAAC;AACzC,OAAO,EACL,kBAAkB,EAClB,cAAc,EACd,WAAW,EACX,YAAY,EACZ,eAAe,EACf,SAAS,GACV,MAAM,aAAa,CAAC;AAMrB,OAAO,EAAE,gBAAgB,EAAE,MAAM,qBAAqB,CAAC;AAEvD,IAAI,MAAM,GAAmB,IAAI,CAAC;AAClC,IAAI,WAAW,GAA4B,IAAI,CAAC;AAChD,IAAI,WAAW,GAAkB,IAAI,CAAC;AACtC,IAAI,WAAW,GAAG,KAAK,CAAC;AAExB,SAAS,eAAe,CAAC,QAAgB;IACvC,IAAI,GAAG,GAAG,QAAQ,CAAC;IACnB,OAAO,GAAG,KAAK,IAAI,CAAC,OAAO,CAAC,GAAG,CAAC,EAAE,CAAC;QACjC,MAAM,SAAS,GAAG,IAAI,CAAC,IAAI,CAAC,GAAG,EAAE,cAAc,CAAC,CAAC;QACjD,IAAI,EAAE,CAAC,UAAU,CAAC,SAAS,CAAC,EAAE,CAAC;YAC7B,OAAO,SAAS,CAAC;QACnB,CAAC;QACD,GAAG,GAAG,IAAI,CAAC,OAAO,CAAC,GAAG,CAAC,CAAC;IAC1B,CAAC;IACD,OAAO,IAAI,CAAC;AACd,CAAC;AAED,SAAS,UAAU;IACjB,IAAI,CAAC;QACH,MAAM,UAAU,GAAG,aAAa,CAAC,MAAM,CAAC,IAAI,CAAC,GAAG,CAAC,CAAC;QAClD,MAAM,SAAS,GAAG,IAAI,CAAC,OAAO,CAAC,UAAU,CAAC,CAAC;QAC3C,MAAM,eAAe,GAAG,eAAe,CAAC,SAAS,CAAC,CAAC;QACnD,IAAI,eAAe,EAAE,CAAC;YACpB,MAAM,GAAG,GAAG,IAAI,CAAC,KAAK,CAAC,EAAE,CAAC,YAAY,CAAC,eAAe,EAAE,OAAO,CAAC,CAAC,CAAC;YAClE,OAAO,GAAG,CAAC,OAAO,IAAI,SAAS,CAAC;QAClC,CAAC;IACH,CAAC;IAAC,MAAM,CAAC;QACP,eAAe;IACjB,CAAC;IACD,OAAO,SAAS,CAAC;AACnB,CAAC;AAED,SAAS,qBAAqB;IAC5B,OAAO;QACL,mBAAmB,EAAE,UAAU,EAAE;QACjC,EAAE,EAAE,OAAO,CAAC,QAAQ;QACpB,UAAU,EAAE,EAAE,CAAC,OAAO,EAAE;QACxB,YAAY,EAAE,OAAO,CAAC,OAAO,CAAC,KAAK,CAAC,CAAC,CAAC;QACtC,IAAI,EAAE,OAAO,CAAC,IAAI;KACnB,CAAC;AACJ,CAAC;AAED,SAAS,kBAAkB;IACzB,IAAI,WAAW,EAAE;QAAE,OAAO;IAE1B,IAAI,eAAe,EAAE,EAAE,CAAC;QACtB,YAAY,EAAE,CAAC;QACf,OAAO;IACT,CAAC;IAED,OAAO,CAAC,GAAG,CAAC,EAAE,CAAC,CAAC;IAChB,OAAO,CAAC,GAAG,CAAC,mEAAmE,CAAC,CAAC;IACjF,OAAO,CAAC,GAAG,CAAC,iDAAiD,CAAC,CAAC;IAC/D,OAAO,CAAC,GAAG,CAAC,+CAA+C,CAAC,CAAC;IAC7D,OAAO,CAAC,GAAG,CAAC,EAAE,CAAC,CAAC;IAEhB,YAAY,EAAE,CAAC;AACjB,CAAC;AAED,MAAM,UAAU,aAAa,CAAC,UAAoC,EAAE;IAClE,IAAI,WAAW;QAAE,OAAO;IACxB,WAAW,GAAG,IAAI,CAAC;IAEnB,IAAI,OAAO,CAAC,UAAU,KAAK,KAAK,EAAE,CAAC;QACjC,kBAAkB,EAAE,CAAC;IACvB,CAAC;IAED,IAAI,CAAC,kBAAkB,EAAE;QAAE,OAAO;IAElC,MAAM,aAAa,GAAG,gBAAgB,EAAE,CAAC;IACzC,IAAI,CAAC,aAAa;QAAE,OAAO;IAE3B,MAAM,GAAG,IAAI,OAAO,CAAC,aAAa,CAAC,MAAM,EAAE;QACzC,IAAI,EAAE,aAAa,CAAC,IAAI;QACxB,OAAO,EAAE,EAAE;QACX,aAAa,EAAE,KAAK;KACrB,CAAC,CAAC;IAEH,WAAW,GAAG,qBAAqB,EAAE,CAAC;IACtC,WAAW,GAAG,cAAc,EAAE,CAAC;AACjC,CAAC;AAED,MAAM,UAAU,KAAK,CACnB,KAAQ,EACR,UAAiC;IAEjC,IAAI,CAAC,MAAM,IAAI,CAAC,WAAW,IAAI,CAAC,WAAW;QAAE,OAAO;IAEpD,MAAM,CAAC,OAAO,CAAC;QACb,UAAU,EAAE,WAAW;QACvB,KAAK;QACL,UAAU,EAAE;YACV,GAAG,WAAW;YACd,GAAG,UAAU;SACd;KACF,CAAC,CAAC;AACL,CAAC;AAED,MAAM,CAAC,KAAK,UAAU,QAAQ;IAC5B,IAAI,CAAC,MAAM;QAAE,OAAO;IAEpB,IAAI,CAAC;QACH,MAAM,MAAM,CAAC,QAAQ,EAAE,CAAC;IAC1B,CAAC;IAAC,MAAM,CAAC;QACP,SAAS;IACX,CAAC;YAAS,CAAC;QACT,MAAM,GAAG,IAAI,CAAC;QACd,WAAW,GAAG,IAAI,CAAC;QACnB,WAAW,GAAG,IAAI,CAAC;QACnB,WAAW,GAAG,KAAK,CAAC;IACtB,CAAC;AACH,CAAC;AAED,MAAM,UAAU,SAAS;IACvB,OAAO,kBAAkB,EAAE,CAAC;AAC9B,CAAC;AAED,OAAO,EAAE,cAAc,EAAE,CAAC;AAE1B,MAAM,UAAU,SAAS;IAMvB,MAAM,KAAK,GAAG,SAAS,EAAE,CAAC;IAC1B,OAAO;QACL,OAAO,EAAE,kBAAkB,EAAE;QAC7B,aAAa,EAAE,eAAe,EAAE;QAChC,WAAW,EAAE,KAAK,CAAC,WAAW;QAC9B,UAAU,EAAE,KAAK,CAAC,UAAU;KAC7B,CAAC;AACJ,CAAC"}
@@ -0,0 +1,23 @@
1
+ /**
2
+ * Telemetry preference storage (~/.agent-relay/telemetry.json)
3
+ */
4
+ export interface TelemetryPrefs {
5
+ enabled: boolean;
6
+ notifiedAt?: string;
7
+ anonymousId: string;
8
+ }
9
+ export declare function getPrefsPath(): string;
10
+ export declare function loadPrefs(): TelemetryPrefs;
11
+ export declare function savePrefs(prefs: TelemetryPrefs): void;
12
+ export declare function isDisabledByEnv(): boolean;
13
+ /**
14
+ * Check if telemetry is enabled.
15
+ * Priority: env var > stored pref > default (enabled)
16
+ */
17
+ export declare function isTelemetryEnabled(): boolean;
18
+ export declare function enableTelemetry(): void;
19
+ export declare function disableTelemetry(): void;
20
+ export declare function markNotified(): void;
21
+ export declare function wasNotified(): boolean;
22
+ export declare function getAnonymousId(): string;
23
+ //# sourceMappingURL=config.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"config.d.ts","sourceRoot":"","sources":["../src/config.ts"],"names":[],"mappings":"AAAA;;GAEG;AAOH,MAAM,WAAW,cAAc;IAC7B,OAAO,EAAE,OAAO,CAAC;IACjB,UAAU,CAAC,EAAE,MAAM,CAAC;IACpB,WAAW,EAAE,MAAM,CAAC;CACrB;AAED,wBAAgB,YAAY,IAAI,MAAM,CAIrC;AAED,wBAAgB,SAAS,IAAI,cAAc,CA2B1C;AAED,wBAAgB,SAAS,CAAC,KAAK,EAAE,cAAc,GAAG,IAAI,CAUrD;AAED,wBAAgB,eAAe,IAAI,OAAO,CAGzC;AAED;;;GAGG;AACH,wBAAgB,kBAAkB,IAAI,OAAO,CAK5C;AAED,wBAAgB,eAAe,IAAI,IAAI,CAItC;AAED,wBAAgB,gBAAgB,IAAI,IAAI,CAIvC;AAED,wBAAgB,YAAY,IAAI,IAAI,CAInC;AAED,wBAAgB,WAAW,IAAI,OAAO,CAErC;AAED,wBAAgB,cAAc,IAAI,MAAM,CAEvC"}
package/dist/config.js ADDED
@@ -0,0 +1,84 @@
1
+ /**
2
+ * Telemetry preference storage (~/.agent-relay/telemetry.json)
3
+ */
4
+ import fs from 'node:fs';
5
+ import path from 'node:path';
6
+ import os from 'node:os';
7
+ import { createAnonymousId } from './machine-id.js';
8
+ export function getPrefsPath() {
9
+ const configDir = process.env.AGENT_RELAY_DATA_DIR ||
10
+ path.join(os.homedir(), '.agent-relay');
11
+ return path.join(configDir, 'telemetry.json');
12
+ }
13
+ export function loadPrefs() {
14
+ const prefsPath = getPrefsPath();
15
+ try {
16
+ if (fs.existsSync(prefsPath)) {
17
+ const content = fs.readFileSync(prefsPath, 'utf-8');
18
+ const prefs = JSON.parse(content);
19
+ if (!prefs.anonymousId) {
20
+ prefs.anonymousId = createAnonymousId();
21
+ savePrefs(prefs);
22
+ }
23
+ return {
24
+ enabled: prefs.enabled ?? true,
25
+ notifiedAt: prefs.notifiedAt,
26
+ anonymousId: prefs.anonymousId,
27
+ };
28
+ }
29
+ }
30
+ catch {
31
+ // Fall through to defaults
32
+ }
33
+ return {
34
+ enabled: true,
35
+ anonymousId: createAnonymousId(),
36
+ };
37
+ }
38
+ export function savePrefs(prefs) {
39
+ const prefsPath = getPrefsPath();
40
+ const configDir = path.dirname(prefsPath);
41
+ try {
42
+ fs.mkdirSync(configDir, { recursive: true });
43
+ fs.writeFileSync(prefsPath, JSON.stringify(prefs, null, 2), 'utf-8');
44
+ }
45
+ catch (err) {
46
+ console.error('[telemetry] Failed to save preferences:', err);
47
+ }
48
+ }
49
+ export function isDisabledByEnv() {
50
+ const envValue = process.env.AGENT_RELAY_TELEMETRY_DISABLED;
51
+ return envValue === '1' || envValue === 'true';
52
+ }
53
+ /**
54
+ * Check if telemetry is enabled.
55
+ * Priority: env var > stored pref > default (enabled)
56
+ */
57
+ export function isTelemetryEnabled() {
58
+ if (isDisabledByEnv()) {
59
+ return false;
60
+ }
61
+ return loadPrefs().enabled;
62
+ }
63
+ export function enableTelemetry() {
64
+ const prefs = loadPrefs();
65
+ prefs.enabled = true;
66
+ savePrefs(prefs);
67
+ }
68
+ export function disableTelemetry() {
69
+ const prefs = loadPrefs();
70
+ prefs.enabled = false;
71
+ savePrefs(prefs);
72
+ }
73
+ export function markNotified() {
74
+ const prefs = loadPrefs();
75
+ prefs.notifiedAt = new Date().toISOString();
76
+ savePrefs(prefs);
77
+ }
78
+ export function wasNotified() {
79
+ return loadPrefs().notifiedAt !== undefined;
80
+ }
81
+ export function getAnonymousId() {
82
+ return loadPrefs().anonymousId;
83
+ }
84
+ //# sourceMappingURL=config.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"config.js","sourceRoot":"","sources":["../src/config.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,53 @@
1
+ /**
2
+ * Telemetry event definitions (PostHog naming: snake_case, present tense)
3
+ */
4
+ export type ActionSource = 'human_cli' | 'human_dashboard' | 'agent' | 'protocol';
5
+ export type ReleaseReason = 'explicit' | 'crash' | 'timeout' | 'shutdown';
6
+ export interface CommonProperties {
7
+ agent_relay_version: string;
8
+ os: string;
9
+ os_version: string;
10
+ node_version: string;
11
+ arch: string;
12
+ }
13
+ export interface DaemonStartEvent {
14
+ }
15
+ export interface DaemonStopEvent {
16
+ uptime_seconds: number;
17
+ agent_spawn_count: number;
18
+ }
19
+ export interface AgentSpawnEvent {
20
+ cli: string;
21
+ spawn_source: ActionSource;
22
+ has_task: boolean;
23
+ is_shadow: boolean;
24
+ }
25
+ export interface AgentReleaseEvent {
26
+ cli: string;
27
+ release_reason: ReleaseReason;
28
+ lifetime_seconds: number;
29
+ release_source: ActionSource;
30
+ }
31
+ export interface AgentCrashEvent {
32
+ cli: string;
33
+ lifetime_seconds: number;
34
+ exit_code?: number;
35
+ }
36
+ export interface MessageSendEvent {
37
+ is_broadcast: boolean;
38
+ has_thread: boolean;
39
+ }
40
+ export interface CliCommandRunEvent {
41
+ command_name: string;
42
+ }
43
+ export type TelemetryEventName = 'daemon_start' | 'daemon_stop' | 'agent_spawn' | 'agent_release' | 'agent_crash' | 'message_send' | 'cli_command_run';
44
+ export interface TelemetryEventMap {
45
+ daemon_start: DaemonStartEvent;
46
+ daemon_stop: DaemonStopEvent;
47
+ agent_spawn: AgentSpawnEvent;
48
+ agent_release: AgentReleaseEvent;
49
+ agent_crash: AgentCrashEvent;
50
+ message_send: MessageSendEvent;
51
+ cli_command_run: CliCommandRunEvent;
52
+ }
53
+ //# sourceMappingURL=events.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"events.d.ts","sourceRoot":"","sources":["../src/events.ts"],"names":[],"mappings":"AAAA;;GAEG;AAEH,MAAM,MAAM,YAAY,GAAG,WAAW,GAAG,iBAAiB,GAAG,OAAO,GAAG,UAAU,CAAC;AAClF,MAAM,MAAM,aAAa,GAAG,UAAU,GAAG,OAAO,GAAG,SAAS,GAAG,UAAU,CAAC;AAE1E,MAAM,WAAW,gBAAgB;IAC/B,mBAAmB,EAAE,MAAM,CAAC;IAC5B,EAAE,EAAE,MAAM,CAAC;IACX,UAAU,EAAE,MAAM,CAAC;IACnB,YAAY,EAAE,MAAM,CAAC;IACrB,IAAI,EAAE,MAAM,CAAC;CACd;AAED,MAAM,WAAW,gBAAgB;CAAG;AAEpC,MAAM,WAAW,eAAe;IAC9B,cAAc,EAAE,MAAM,CAAC;IACvB,iBAAiB,EAAE,MAAM,CAAC;CAC3B;AAED,MAAM,WAAW,eAAe;IAC9B,GAAG,EAAE,MAAM,CAAC;IACZ,YAAY,EAAE,YAAY,CAAC;IAC3B,QAAQ,EAAE,OAAO,CAAC;IAClB,SAAS,EAAE,OAAO,CAAC;CACpB;AAED,MAAM,WAAW,iBAAiB;IAChC,GAAG,EAAE,MAAM,CAAC;IACZ,cAAc,EAAE,aAAa,CAAC;IAC9B,gBAAgB,EAAE,MAAM,CAAC;IACzB,cAAc,EAAE,YAAY,CAAC;CAC9B;AAED,MAAM,WAAW,eAAe;IAC9B,GAAG,EAAE,MAAM,CAAC;IACZ,gBAAgB,EAAE,MAAM,CAAC;IACzB,SAAS,CAAC,EAAE,MAAM,CAAC;CACpB;AAED,MAAM,WAAW,gBAAgB;IAC/B,YAAY,EAAE,OAAO,CAAC;IACtB,UAAU,EAAE,OAAO,CAAC;CACrB;AAED,MAAM,WAAW,kBAAkB;IACjC,YAAY,EAAE,MAAM,CAAC;CACtB;AAED,MAAM,MAAM,kBAAkB,GAC1B,cAAc,GACd,aAAa,GACb,aAAa,GACb,eAAe,GACf,aAAa,GACb,cAAc,GACd,iBAAiB,CAAC;AAEtB,MAAM,WAAW,iBAAiB;IAChC,YAAY,EAAE,gBAAgB,CAAC;IAC/B,WAAW,EAAE,eAAe,CAAC;IAC7B,WAAW,EAAE,eAAe,CAAC;IAC7B,aAAa,EAAE,iBAAiB,CAAC;IACjC,WAAW,EAAE,eAAe,CAAC;IAC7B,YAAY,EAAE,gBAAgB,CAAC;IAC/B,eAAe,EAAE,kBAAkB,CAAC;CACrC"}
package/dist/events.js ADDED
@@ -0,0 +1,5 @@
1
+ /**
2
+ * Telemetry event definitions (PostHog naming: snake_case, present tense)
3
+ */
4
+ export {};
5
+ //# sourceMappingURL=events.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"events.js","sourceRoot":"","sources":["../src/events.ts"],"names":[],"mappings":"AAAA;;GAEG"}
@@ -0,0 +1,8 @@
1
+ /**
2
+ * @agent-relay/telemetry - Anonymous usage analytics (opt-out via env or CLI)
3
+ */
4
+ export { initTelemetry, track, shutdown, isEnabled, getAnonymousId, getStatus, } from './client.js';
5
+ export { isTelemetryEnabled, enableTelemetry, disableTelemetry, wasNotified, markNotified, loadPrefs, savePrefs, getPrefsPath, isDisabledByEnv, type TelemetryPrefs, } from './config.js';
6
+ export type { CommonProperties, ActionSource, ReleaseReason, DaemonStartEvent, DaemonStopEvent, AgentSpawnEvent, AgentReleaseEvent, AgentCrashEvent, MessageSendEvent, CliCommandRunEvent, TelemetryEventName, TelemetryEventMap, } from './events.js';
7
+ export { loadMachineId, createAnonymousId, getMachineIdPath, } from './machine-id.js';
8
+ //# sourceMappingURL=index.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"AAAA;;GAEG;AAEH,OAAO,EACL,aAAa,EACb,KAAK,EACL,QAAQ,EACR,SAAS,EACT,cAAc,EACd,SAAS,GACV,MAAM,aAAa,CAAC;AAErB,OAAO,EACL,kBAAkB,EAClB,eAAe,EACf,gBAAgB,EAChB,WAAW,EACX,YAAY,EACZ,SAAS,EACT,SAAS,EACT,YAAY,EACZ,eAAe,EACf,KAAK,cAAc,GACpB,MAAM,aAAa,CAAC;AAErB,YAAY,EACV,gBAAgB,EAChB,YAAY,EACZ,aAAa,EACb,gBAAgB,EAChB,eAAe,EACf,eAAe,EACf,iBAAiB,EACjB,eAAe,EACf,gBAAgB,EAChB,kBAAkB,EAClB,kBAAkB,EAClB,iBAAiB,GAClB,MAAM,aAAa,CAAC;AAErB,OAAO,EACL,aAAa,EACb,iBAAiB,EACjB,gBAAgB,GACjB,MAAM,iBAAiB,CAAC"}
package/dist/index.js ADDED
@@ -0,0 +1,7 @@
1
+ /**
2
+ * @agent-relay/telemetry - Anonymous usage analytics (opt-out via env or CLI)
3
+ */
4
+ export { initTelemetry, track, shutdown, isEnabled, getAnonymousId, getStatus, } from './client.js';
5
+ export { isTelemetryEnabled, enableTelemetry, disableTelemetry, wasNotified, markNotified, loadPrefs, savePrefs, getPrefsPath, isDisabledByEnv, } from './config.js';
6
+ export { loadMachineId, createAnonymousId, getMachineIdPath, } from './machine-id.js';
7
+ //# sourceMappingURL=index.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"index.js","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"AAAA;;GAEG;AAEH,OAAO,EACL,aAAa,EACb,KAAK,EACL,QAAQ,EACR,SAAS,EACT,cAAc,EACd,SAAS,GACV,MAAM,aAAa,CAAC;AAErB,OAAO,EACL,kBAAkB,EAClB,eAAe,EACf,gBAAgB,EAChB,WAAW,EACX,YAAY,EACZ,SAAS,EACT,SAAS,EACT,YAAY,EACZ,eAAe,GAEhB,MAAM,aAAa,CAAC;AAiBrB,OAAO,EACL,aAAa,EACb,iBAAiB,EACjB,gBAAgB,GACjB,MAAM,iBAAiB,CAAC"}
@@ -0,0 +1,12 @@
1
+ /**
2
+ * Machine ID utilities for anonymous user identification.
3
+ * Uses existing machine-id file at ~/.local/share/agent-relay/machine-id
4
+ */
5
+ export declare function getMachineIdPath(): string;
6
+ /**
7
+ * Load or generate machine ID using atomic file creation to avoid race conditions.
8
+ */
9
+ export declare function loadMachineId(): string;
10
+ /** SHA256 hash of machine ID, truncated to 16 chars */
11
+ export declare function createAnonymousId(): string;
12
+ //# sourceMappingURL=machine-id.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"machine-id.d.ts","sourceRoot":"","sources":["../src/machine-id.ts"],"names":[],"mappings":"AAAA;;;GAGG;AAOH,wBAAgB,gBAAgB,IAAI,MAAM,CAIzC;AAED;;GAEG;AACH,wBAAgB,aAAa,IAAI,MAAM,CAkCtC;AAED,uDAAuD;AACvD,wBAAgB,iBAAiB,IAAI,MAAM,CAM1C"}
@@ -0,0 +1,58 @@
1
+ /**
2
+ * Machine ID utilities for anonymous user identification.
3
+ * Uses existing machine-id file at ~/.local/share/agent-relay/machine-id
4
+ */
5
+ import { createHash, randomBytes } from 'node:crypto';
6
+ import fs from 'node:fs';
7
+ import path from 'node:path';
8
+ import os from 'node:os';
9
+ export function getMachineIdPath() {
10
+ const dataDir = process.env.AGENT_RELAY_DATA_DIR ||
11
+ path.join(os.homedir(), '.local', 'share', 'agent-relay');
12
+ return path.join(dataDir, 'machine-id');
13
+ }
14
+ /**
15
+ * Load or generate machine ID using atomic file creation to avoid race conditions.
16
+ */
17
+ export function loadMachineId() {
18
+ const machineIdPath = getMachineIdPath();
19
+ try {
20
+ return fs.readFileSync(machineIdPath, 'utf-8').trim();
21
+ }
22
+ catch (readErr) {
23
+ if (readErr.code !== 'ENOENT') {
24
+ return `${os.hostname()}-${Date.now().toString(36)}`;
25
+ }
26
+ try {
27
+ const dataDir = path.dirname(machineIdPath);
28
+ fs.mkdirSync(dataDir, { recursive: true });
29
+ const machineId = `${os.hostname()}-${randomBytes(8).toString('hex')}`;
30
+ // O_CREAT | O_EXCL fails if file exists - prevents race condition
31
+ const fd = fs.openSync(machineIdPath, fs.constants.O_CREAT | fs.constants.O_EXCL | fs.constants.O_WRONLY, 0o600);
32
+ fs.writeSync(fd, machineId);
33
+ fs.closeSync(fd);
34
+ return machineId;
35
+ }
36
+ catch (writeErr) {
37
+ // Another process created the file first
38
+ if (writeErr.code === 'EEXIST') {
39
+ try {
40
+ return fs.readFileSync(machineIdPath, 'utf-8').trim();
41
+ }
42
+ catch {
43
+ // Fall through
44
+ }
45
+ }
46
+ return `${os.hostname()}-${Date.now().toString(36)}`;
47
+ }
48
+ }
49
+ }
50
+ /** SHA256 hash of machine ID, truncated to 16 chars */
51
+ export function createAnonymousId() {
52
+ const machineId = loadMachineId();
53
+ return createHash('sha256')
54
+ .update(machineId)
55
+ .digest('hex')
56
+ .substring(0, 16);
57
+ }
58
+ //# sourceMappingURL=machine-id.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"machine-id.js","sourceRoot":"","sources":["../src/machine-id.ts"],"names":[],"mappings":"AAAA;;;GAGG;AAEH,OAAO,EAAE,UAAU,EAAE,WAAW,EAAE,MAAM,aAAa,CAAC;AACtD,OAAO,EAAE,MAAM,SAAS,CAAC;AACzB,OAAO,IAAI,MAAM,WAAW,CAAC;AAC7B,OAAO,EAAE,MAAM,SAAS,CAAC;AAEzB,MAAM,UAAU,gBAAgB;IAC9B,MAAM,OAAO,GAAG,OAAO,CAAC,GAAG,CAAC,oBAAoB;QAC9C,IAAI,CAAC,IAAI,CAAC,EAAE,CAAC,OAAO,EAAE,EAAE,QAAQ,EAAE,OAAO,EAAE,aAAa,CAAC,CAAC;IAC5D,OAAO,IAAI,CAAC,IAAI,CAAC,OAAO,EAAE,YAAY,CAAC,CAAC;AAC1C,CAAC;AAED;;GAEG;AACH,MAAM,UAAU,aAAa;IAC3B,MAAM,aAAa,GAAG,gBAAgB,EAAE,CAAC;IAEzC,IAAI,CAAC;QACH,OAAO,EAAE,CAAC,YAAY,CAAC,aAAa,EAAE,OAAO,CAAC,CAAC,IAAI,EAAE,CAAC;IACxD,CAAC;IAAC,OAAO,OAAgB,EAAE,CAAC;QAC1B,IAAK,OAAiC,CAAC,IAAI,KAAK,QAAQ,EAAE,CAAC;YACzD,OAAO,GAAG,EAAE,CAAC,QAAQ,EAAE,IAAI,IAAI,CAAC,GAAG,EAAE,CAAC,QAAQ,CAAC,EAAE,CAAC,EAAE,CAAC;QACvD,CAAC;QAED,IAAI,CAAC;YACH,MAAM,OAAO,GAAG,IAAI,CAAC,OAAO,CAAC,aAAa,CAAC,CAAC;YAC5C,EAAE,CAAC,SAAS,CAAC,OAAO,EAAE,EAAE,SAAS,EAAE,IAAI,EAAE,CAAC,CAAC;YAE3C,MAAM,SAAS,GAAG,GAAG,EAAE,CAAC,QAAQ,EAAE,IAAI,WAAW,CAAC,CAAC,CAAC,CAAC,QAAQ,CAAC,KAAK,CAAC,EAAE,CAAC;YAEvE,kEAAkE;YAClE,MAAM,EAAE,GAAG,EAAE,CAAC,QAAQ,CAAC,aAAa,EAAE,EAAE,CAAC,SAAS,CAAC,OAAO,GAAG,EAAE,CAAC,SAAS,CAAC,MAAM,GAAG,EAAE,CAAC,SAAS,CAAC,QAAQ,EAAE,KAAK,CAAC,CAAC;YACjH,EAAE,CAAC,SAAS,CAAC,EAAE,EAAE,SAAS,CAAC,CAAC;YAC5B,EAAE,CAAC,SAAS,CAAC,EAAE,CAAC,CAAC;YAEjB,OAAO,SAAS,CAAC;QACnB,CAAC;QAAC,OAAO,QAAiB,EAAE,CAAC;YAC3B,yCAAyC;YACzC,IAAK,QAAkC,CAAC,IAAI,KAAK,QAAQ,EAAE,CAAC;gBAC1D,IAAI,CAAC;oBACH,OAAO,EAAE,CAAC,YAAY,CAAC,aAAa,EAAE,OAAO,CAAC,CAAC,IAAI,EAAE,CAAC;gBACxD,CAAC;gBAAC,MAAM,CAAC;oBACP,eAAe;gBACjB,CAAC;YACH,CAAC;YACD,OAAO,GAAG,EAAE,CAAC,QAAQ,EAAE,IAAI,IAAI,CAAC,GAAG,EAAE,CAAC,QAAQ,CAAC,EAAE,CAAC,EAAE,CAAC;QACvD,CAAC;IACH,CAAC;AACH,CAAC;AAED,uDAAuD;AACvD,MAAM,UAAU,iBAAiB;IAC/B,MAAM,SAAS,GAAG,aAAa,EAAE,CAAC;IAClC,OAAO,UAAU,CAAC,QAAQ,CAAC;SACxB,MAAM,CAAC,SAAS,CAAC;SACjB,MAAM,CAAC,KAAK,CAAC;SACb,SAAS,CAAC,CAAC,EAAE,EAAE,CAAC,CAAC;AACtB,CAAC"}
@@ -0,0 +1,16 @@
1
+ /**
2
+ * PostHog configuration.
3
+ *
4
+ * Environment variables:
5
+ * POSTHOG_API_KEY - Override API key (any environment)
6
+ * POSTHOG_HOST - Override host URL
7
+ *
8
+ * Key selection:
9
+ * 1. POSTHOG_API_KEY (if set, always used)
10
+ * 3. PROD_API_KEY (fallback)
11
+ */
12
+ export declare function getPostHogConfig(): {
13
+ apiKey: string;
14
+ host: string;
15
+ } | null;
16
+ //# sourceMappingURL=posthog-config.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"posthog-config.d.ts","sourceRoot":"","sources":["../src/posthog-config.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;GAUG;AAcH,wBAAgB,gBAAgB,IAAI;IAAE,MAAM,EAAE,MAAM,CAAC;IAAC,IAAI,EAAE,MAAM,CAAA;CAAE,GAAG,IAAI,CAc1E"}
@@ -0,0 +1,33 @@
1
+ /**
2
+ * PostHog configuration.
3
+ *
4
+ * Environment variables:
5
+ * POSTHOG_API_KEY - Override API key (any environment)
6
+ * POSTHOG_HOST - Override host URL
7
+ *
8
+ * Key selection:
9
+ * 1. POSTHOG_API_KEY (if set, always used)
10
+ * 3. PROD_API_KEY (fallback)
11
+ */
12
+ // =============================================================================
13
+ // Configure your PostHog production key here
14
+ // =============================================================================
15
+ /** Production PostHog API key (write-only, safe for client-side) */
16
+ const PROD_API_KEY = 'phc_2uDu01GtnLABJpVkWw4ri1OgScLU90aEmXmDjufGdqr';
17
+ const HOST = 'https://us.i.posthog.com';
18
+ // =============================================================================
19
+ // Exports
20
+ // =============================================================================
21
+ export function getPostHogConfig() {
22
+ const host = process.env.POSTHOG_HOST || HOST;
23
+ // Explicit override for any environment
24
+ if (process.env.POSTHOG_API_KEY) {
25
+ return { apiKey: process.env.POSTHOG_API_KEY, host };
26
+ }
27
+ // Fallback to production key
28
+ if (!PROD_API_KEY) {
29
+ return null;
30
+ }
31
+ return { apiKey: PROD_API_KEY, host };
32
+ }
33
+ //# sourceMappingURL=posthog-config.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"posthog-config.js","sourceRoot":"","sources":["../src/posthog-config.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;GAUG;AAEH,gFAAgF;AAChF,6CAA6C;AAC7C,gFAAgF;AAEhF,oEAAoE;AACpE,MAAM,YAAY,GAAG,iDAAiD,CAAC;AACvE,MAAM,IAAI,GAAG,0BAA0B,CAAC;AAExC,gFAAgF;AAChF,UAAU;AACV,gFAAgF;AAEhF,MAAM,UAAU,gBAAgB;IAC9B,MAAM,IAAI,GAAG,OAAO,CAAC,GAAG,CAAC,YAAY,IAAI,IAAI,CAAC;IAE9C,wCAAwC;IACxC,IAAI,OAAO,CAAC,GAAG,CAAC,eAAe,EAAE,CAAC;QAChC,OAAO,EAAE,MAAM,EAAE,OAAO,CAAC,GAAG,CAAC,eAAe,EAAE,IAAI,EAAE,CAAC;IACvD,CAAC;IAED,6BAA6B;IAC7B,IAAI,CAAC,YAAY,EAAE,CAAC;QAClB,OAAO,IAAI,CAAC;IACd,CAAC;IAED,OAAO,EAAE,MAAM,EAAE,YAAY,EAAE,IAAI,EAAE,CAAC;AACxC,CAAC"}
package/package.json ADDED
@@ -0,0 +1,41 @@
1
+ {
2
+ "name": "@agent-relay/telemetry",
3
+ "version": "2.0.5",
4
+ "description": "Anonymous telemetry for Agent Relay usage analytics",
5
+ "type": "module",
6
+ "main": "dist/index.js",
7
+ "types": "dist/index.d.ts",
8
+ "exports": {
9
+ ".": {
10
+ "types": "./dist/index.d.ts",
11
+ "import": "./dist/index.js",
12
+ "default": "./dist/index.js"
13
+ }
14
+ },
15
+ "files": [
16
+ "dist",
17
+ "README.md"
18
+ ],
19
+ "scripts": {
20
+ "build": "tsc",
21
+ "clean": "rm -rf dist",
22
+ "test": "vitest run",
23
+ "test:watch": "vitest"
24
+ },
25
+ "dependencies": {
26
+ "posthog-node": "^4.0.1"
27
+ },
28
+ "devDependencies": {
29
+ "@types/node": "^22.19.3",
30
+ "typescript": "^5.9.3",
31
+ "vitest": "^3.0.0"
32
+ },
33
+ "publishConfig": {
34
+ "access": "public"
35
+ },
36
+ "repository": {
37
+ "type": "git",
38
+ "url": "git+https://github.com/AgentWorkforce/relay.git",
39
+ "directory": "packages/telemetry"
40
+ }
41
+ }