@@ -7,15 +7,19 @@ import { MACHINE_METADATA } from "./constants.js";
7
7
import { EventCache } from "./eventCache.js" ;
8
8
import { createHmac } from "crypto" ;
9
9
import { machineId } from "node-machine-id" ;
10
+ import { DeferredPromise } from "../deferred-promise.js" ;
10
11
11
12
type EventResult = {
12
13
success : boolean ;
13
14
error ?: Error ;
14
15
} ;
15
16
17
+ export const DEVICE_ID_TIMEOUT = 3000 ;
18
+
16
19
export class Telemetry {
17
20
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 ;
19
23
20
24
private constructor (
21
25
private readonly session : Session ,
@@ -25,7 +29,7 @@ export class Telemetry {
25
29
26
30
static create (
27
31
session : Session ,
28
- commonProperties : CommonProperties = MACHINE_METADATA ,
32
+ commonProperties : CommonProperties = { ... MACHINE_METADATA } ,
29
33
eventCache : EventCache = EventCache . getInstance ( )
30
34
) : Telemetry {
31
35
const instance = new Telemetry ( session , commonProperties , eventCache ) ;
@@ -35,55 +39,42 @@ export class Telemetry {
35
39
}
36
40
37
41
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 ;
39
44
40
45
this . isBufferingEvents = false ;
41
- await this . emitEvents ( this . eventCache . getEvents ( ) ) ;
42
46
}
43
47
44
48
public async close ( ) : Promise < void > {
45
- this . resolveDeviceId ( "unknown" ) ;
49
+ this . deviceIdPromise ?. resolve ( "unknown" ) ;
46
50
this . isBufferingEvents = false ;
47
51
await this . emitEvents ( this . eventCache . getEvents ( ) ) ;
48
52
}
49
53
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
-
67
54
/**
68
55
* @returns A hashed, unique identifier for the running device or `undefined` if not known.
69
56
*/
70
57
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
+ }
77
62
78
- const originalId = ( await this . machineIdWithTimeout ( ) ) . toUpperCase ( ) ;
63
+ const originalId = await DeferredPromise . fromPromise ( machineId ( true ) , { timeout : DEVICE_ID_TIMEOUT } ) ;
79
64
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 ( ) ) ;
81
68
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" ;
84
71
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
+ }
87
78
}
88
79
89
80
/**
@@ -134,6 +125,7 @@ export class Telemetry {
134
125
public getCommonProperties ( ) : CommonProperties {
135
126
return {
136
127
...this . commonProperties ,
128
+ device_id : this . commonProperties . device_id ,
137
129
mcp_client_version : this . session . agentRunner ?. version ,
138
130
mcp_client_name : this . session . agentRunner ?. name ,
139
131
session_id : this . session . sessionId ,
0 commit comments