@@ -7,15 +7,19 @@ import { MACHINE_METADATA } from "./constants.js";
77import { EventCache } from "./eventCache.js" ;
88import { createHmac } from "crypto" ;
99import { machineId } from "node-machine-id" ;
10+ import { DeferredPromise } from "../deferred-promise.js" ;
1011
1112type EventResult = {
1213 success : boolean ;
1314 error ?: Error ;
1415} ;
1516
17+ export const DEVICE_ID_TIMEOUT = 3000 ;
18+
1619export class Telemetry {
1720 private isBufferingEvents : boolean = true ;
18- private resolveDeviceId : ( deviceId : string ) => void = ( ) => { } ;
21+ /** Resolves when the device ID is retrieved or timeout occurs */
22+ public deviceIdPromise : DeferredPromise < string > | undefined ;
1923
2024 private constructor (
2125 private readonly session : Session ,
@@ -25,7 +29,7 @@ export class Telemetry {
2529
2630 static create (
2731 session : Session ,
28- commonProperties : CommonProperties = MACHINE_METADATA ,
32+ commonProperties : CommonProperties = { ... MACHINE_METADATA } ,
2933 eventCache : EventCache = EventCache . getInstance ( )
3034 ) : Telemetry {
3135 const instance = new Telemetry ( session , commonProperties , eventCache ) ;
@@ -35,55 +39,42 @@ export class Telemetry {
3539 }
3640
3741 private async start ( ) : Promise < void > {
38- this . commonProperties . device_id = await this . getDeviceId ( ) ;
42+ this . deviceIdPromise = DeferredPromise . fromPromise ( this . getDeviceId ( ) ) ;
43+ this . commonProperties . device_id = await this . deviceIdPromise ;
3944
4045 this . isBufferingEvents = false ;
41- await this . emitEvents ( this . eventCache . getEvents ( ) ) ;
4246 }
4347
4448 public async close ( ) : Promise < void > {
45- this . resolveDeviceId ( "unknown" ) ;
49+ this . deviceIdPromise ?. resolve ( "unknown" ) ;
4650 this . isBufferingEvents = false ;
4751 await this . emitEvents ( this . eventCache . getEvents ( ) ) ;
4852 }
4953
50- private async machineIdWithTimeout ( ) : Promise < string > {
51- try {
52- return Promise . race < string > ( [
53- machineId ( true ) ,
54- new Promise < string > ( ( resolve , reject ) => {
55- this . resolveDeviceId = resolve ;
56- setTimeout ( ( ) => {
57- reject ( new Error ( "Timeout getting machine ID" ) ) ;
58- } , 3000 ) ;
59- } ) ,
60- ] ) ;
61- } catch ( error ) {
62- logger . debug ( LogId . telemetryMachineIdFailure , "telemetry" , `Error getting machine ID: ${ String ( error ) } ` ) ;
63- return "unknown" ;
64- }
65- }
66-
6754 /**
6855 * @returns A hashed, unique identifier for the running device or `undefined` if not known.
6956 */
7057 private async getDeviceId ( ) : Promise < string > {
71- if ( this . commonProperties . device_id ) {
72- return this . commonProperties . device_id ;
73- }
74-
75- // Create a hashed format from the all uppercase version of the machine ID
76- // to match it exactly with the denisbrodbeck/machineid library that Atlas CLI uses.
58+ try {
59+ if ( this . commonProperties . device_id ) {
60+ return this . commonProperties . device_id ;
61+ }
7762
78- const originalId = ( await this . machineIdWithTimeout ( ) ) . toUpperCase ( ) ;
63+ const originalId = await DeferredPromise . fromPromise ( machineId ( true ) , { timeout : DEVICE_ID_TIMEOUT } ) ;
7964
80- const hmac = createHmac ( "sha256" , originalId ) ;
65+ // Create a hashed format from the all uppercase version of the machine ID
66+ // to match it exactly with the denisbrodbeck/machineid library that Atlas CLI uses.
67+ const hmac = createHmac ( "sha256" , originalId . toUpperCase ( ) ) ;
8168
82- /** This matches the message used to create the hashes in Atlas CLI */
83- const DEVICE_ID_HASH_MESSAGE = "atlascli" ;
69+ /** This matches the message used to create the hashes in Atlas CLI */
70+ const DEVICE_ID_HASH_MESSAGE = "atlascli" ;
8471
85- hmac . update ( DEVICE_ID_HASH_MESSAGE ) ;
86- return hmac . digest ( "hex" ) ;
72+ hmac . update ( DEVICE_ID_HASH_MESSAGE ) ;
73+ return hmac . digest ( "hex" ) ;
74+ } catch ( error ) {
75+ logger . debug ( LogId . telemetryMachineIdFailure , "telemetry" , String ( error ) ) ;
76+ return "unknown" ;
77+ }
8778 }
8879
8980 /**
@@ -134,6 +125,7 @@ export class Telemetry {
134125 public getCommonProperties ( ) : CommonProperties {
135126 return {
136127 ...this . commonProperties ,
128+ device_id : this . commonProperties . device_id ,
137129 mcp_client_version : this . session . agentRunner ?. version ,
138130 mcp_client_name : this . session . agentRunner ?. name ,
139131 session_id : this . session . sessionId ,
0 commit comments