@@ -309,6 +309,8 @@ app.get("/setup", requireSetupAuth, (_req, res) => {
309309 <option value="openclaw.logs.tail">openclaw logs --tail N</option>
310310 <option value="openclaw.config.get">openclaw config get <path></option>
311311 <option value="openclaw.version">openclaw --version</option>
312+ <option value="openclaw.devices.list">openclaw devices list</option>
313+ <option value="openclaw.devices.approve">openclaw devices approve <requestId></option>
312314 </select>
313315 <input id="consoleArg" placeholder="Optional arg (e.g. 200, gateway.port)" style="flex: 1" />
314316 <button id="consoleRun" style="background:#0f172a">Run</button>
@@ -551,8 +553,11 @@ app.post("/setup/api/run", requireSetupAuth, async (req, res) => {
551553 if ( ok ) {
552554 // Ensure gateway token is written into config so the browser UI can authenticate reliably.
553555 // (We also enforce loopback bind since the wrapper proxies externally.)
556+ // IMPORTANT: Set both gateway.auth.token (server-side) and gateway.remote.token (client-side)
557+ // to the same value so the Control UI can connect without "token mismatch" errors.
554558 await runCmd ( OPENCLAW_NODE , clawArgs ( [ "config" , "set" , "gateway.auth.mode" , "token" ] ) ) ;
555559 await runCmd ( OPENCLAW_NODE , clawArgs ( [ "config" , "set" , "gateway.auth.token" , OPENCLAW_GATEWAY_TOKEN ] ) ) ;
560+ await runCmd ( OPENCLAW_NODE , clawArgs ( [ "config" , "set" , "gateway.remote.token" , OPENCLAW_GATEWAY_TOKEN ] ) ) ;
556561 await runCmd ( OPENCLAW_NODE , clawArgs ( [ "config" , "set" , "gateway.bind" , "loopback" ] ) ) ;
557562 await runCmd ( OPENCLAW_NODE , clawArgs ( [ "config" , "set" , "gateway.port" , String ( INTERNAL_GATEWAY_PORT ) ] ) ) ;
558563
@@ -688,6 +693,10 @@ const ALLOWED_CONSOLE_COMMANDS = new Set([
688693 "openclaw.doctor" ,
689694 "openclaw.logs.tail" ,
690695 "openclaw.config.get" ,
696+
697+ // Device management (for fixing "disconnected (1008): pairing required")
698+ "openclaw.devices.list" ,
699+ "openclaw.devices.approve" ,
691700] ) ;
692701
693702app . post ( "/setup/api/console/run" , requireSetupAuth , async ( req , res ) => {
@@ -744,6 +753,23 @@ app.post("/setup/api/console/run", requireSetupAuth, async (req, res) => {
744753 return res . status ( r . code === 0 ? 200 : 500 ) . json ( { ok : r . code === 0 , output : redactSecrets ( r . output ) } ) ;
745754 }
746755
756+ // Device management commands (for fixing "disconnected (1008): pairing required")
757+ if ( cmd === "openclaw.devices.list" ) {
758+ const r = await runCmd ( OPENCLAW_NODE , clawArgs ( [ "devices" , "list" ] ) ) ;
759+ return res . status ( r . code === 0 ? 200 : 500 ) . json ( { ok : r . code === 0 , output : redactSecrets ( r . output ) } ) ;
760+ }
761+ if ( cmd === "openclaw.devices.approve" ) {
762+ const requestId = String ( arg || "" ) . trim ( ) ;
763+ if ( ! requestId ) {
764+ return res . status ( 400 ) . json ( { ok : false , error : "Missing device request ID" } ) ;
765+ }
766+ if ( ! / ^ [ A - Z a - z 0 - 9 _ - ] + $ / . test ( requestId ) ) {
767+ return res . status ( 400 ) . json ( { ok : false , error : "Invalid device request ID" } ) ;
768+ }
769+ const r = await runCmd ( OPENCLAW_NODE , clawArgs ( [ "devices" , "approve" , requestId ] ) ) ;
770+ return res . status ( r . code === 0 ? 200 : 500 ) . json ( { ok : r . code === 0 , output : redactSecrets ( r . output ) } ) ;
771+ }
772+
747773 return res . status ( 400 ) . json ( { ok : false , error : "Unhandled command" } ) ;
748774 } catch ( err ) {
749775 return res . status ( 500 ) . json ( { ok : false , error : String ( err ) } ) ;
0 commit comments