@@ -11,6 +11,10 @@ import type {
1111} from "@okcode/contracts" ;
1212import NodeWebSocket from "ws" ;
1313import { serverBuildInfo } from "./buildInfo.ts" ;
14+ import {
15+ generateOpenclawDeviceIdentity ,
16+ signOpenclawDeviceChallenge ,
17+ } from "./openclaw/deviceAuth.ts" ;
1418
1519const OPENCLAW_TEST_CONNECT_TIMEOUT_MS = 10_000 ;
1620const OPENCLAW_TEST_RPC_TIMEOUT_MS = 10_000 ;
@@ -578,6 +582,7 @@ export async function runOpenclawGatewayTest(
578582 } ;
579583
580584 let parsedUrlForHints : URL | null = null ;
585+ const testDeviceIdentity = generateOpenclawDeviceIdentity ( ) ;
581586
582587 const waitForGatewayEvent = (
583588 socket : NodeWebSocket ,
@@ -783,29 +788,51 @@ export async function runOpenclawGatewayTest(
783788 }
784789 } ) ;
785790
786- const buildConnectParams = ( sharedSecret : string | undefined ) : Record < string , unknown > => ( {
787- minProtocol : OPENCLAW_PROTOCOL_VERSION ,
788- maxProtocol : OPENCLAW_PROTOCOL_VERSION ,
789- client : {
790- id : "okcode" ,
791- version : serverBuildInfo . version ,
792- platform :
793- process . platform === "darwin"
794- ? "macos"
795- : process . platform === "win32"
796- ? "windows"
797- : process . platform ,
798- mode : "operator" ,
799- } ,
800- role : "operator" ,
801- scopes : [ ...OPENCLAW_OPERATOR_SCOPES ] ,
802- caps : [ ] ,
803- commands : [ ] ,
804- permissions : { } ,
805- locale : Intl . DateTimeFormat ( ) . resolvedOptions ( ) . locale || "en-US" ,
806- userAgent : `okcode/${ serverBuildInfo . version } ` ,
807- ...( sharedSecret ? { auth : { password : sharedSecret } } : { } ) ,
808- } ) ;
791+ const buildConnectParams = (
792+ sharedSecret : string | undefined ,
793+ challenge : Record < string , unknown > | undefined ,
794+ ) : Record < string , unknown > => {
795+ const nonce =
796+ typeof challenge ?. nonce === "string" && challenge . nonce . length > 0 ? challenge . nonce : "" ;
797+ const signedAt =
798+ typeof challenge ?. ts === "number" && Number . isFinite ( challenge . ts )
799+ ? challenge . ts
800+ : Date . now ( ) ;
801+ const authToken = sharedSecret ?? "" ;
802+ const signedDevice = signOpenclawDeviceChallenge ( testDeviceIdentity , {
803+ clientId : "okcode" ,
804+ clientMode : "operator" ,
805+ role : "operator" ,
806+ scopes : [ ...OPENCLAW_OPERATOR_SCOPES ] ,
807+ token : authToken ,
808+ nonce,
809+ signedAt,
810+ } ) ;
811+ return {
812+ minProtocol : OPENCLAW_PROTOCOL_VERSION ,
813+ maxProtocol : OPENCLAW_PROTOCOL_VERSION ,
814+ client : {
815+ id : "okcode" ,
816+ version : serverBuildInfo . version ,
817+ platform :
818+ process . platform === "darwin"
819+ ? "macos"
820+ : process . platform === "win32"
821+ ? "windows"
822+ : process . platform ,
823+ mode : "operator" ,
824+ } ,
825+ role : "operator" ,
826+ scopes : [ ...OPENCLAW_OPERATOR_SCOPES ] ,
827+ caps : [ ] ,
828+ commands : [ ] ,
829+ permissions : { } ,
830+ locale : Intl . DateTimeFormat ( ) . resolvedOptions ( ) . locale || "en-US" ,
831+ userAgent : `okcode/${ serverBuildInfo . version } ` ,
832+ ...( authToken . length > 0 ? { auth : { token : authToken } } : { } ) ,
833+ device : signedDevice ,
834+ } ;
835+ } ;
809836
810837 try {
811838 const urlStart = Date . now ( ) ;
@@ -907,13 +934,13 @@ export async function runOpenclawGatewayTest(
907934
908935 const handshakeStart = Date . now ( ) ;
909936 try {
910- await waitForGatewayEvent ( ws , "connect.challenge" ) ;
937+ const challenge = await waitForGatewayEvent ( ws , "connect.challenge" ) ;
911938 captureEarlyGatewayEvents = false ;
912939 earlyGatewayEvents . length = 0 ;
913940 const connectResult = await sendGatewayRequest (
914941 ws ,
915942 "connect" ,
916- buildConnectParams ( sharedSecret ) ,
943+ buildConnectParams ( sharedSecret , challenge ) ,
917944 ) ;
918945 if ( connectResult . error ) {
919946 const detail = formatGatewayError ( connectResult . error ) ;
0 commit comments