diff --git a/src/tui/tui.test.ts b/src/tui/tui.test.ts index 1f90313499df..1d728a1047eb 100644 --- a/src/tui/tui.test.ts +++ b/src/tui/tui.test.ts @@ -346,11 +346,24 @@ describe("resolveInitialTuiAgentId", () => { }); describe("resolveGatewayDisconnectState", () => { - it("returns pairing recovery guidance when disconnect reason requires pairing", () => { + it("returns scope-upgrade recovery guidance when disconnect reason requires pairing", () => { const state = resolveGatewayDisconnectState("gateway closed (1008): pairing required"); expect(state.connectionStatus).toContain("pairing required"); - expect(state.activityStatus).toBe("pairing required: run openclaw devices list"); - expect(state.pairingHint).toContain("openclaw devices list"); + expect(state.activityStatus).toBe("device approval needed: preview latest request"); + expect(state.pairingHint).toContain("openclaw devices approve --latest"); + expect(state.pairingHint).toContain("openclaw devices approve "); + expect(state.pairingHint).toContain("--token"); + // Must steer users to `devices`, not the unrelated chat-DM `pairing` command. + expect(state.pairingHint).not.toContain("openclaw pairing"); + }); + + it("returns the same guidance when the gateway reports a pending scope upgrade", () => { + const state = resolveGatewayDisconnectState( + "gateway closed (1008): scope upgrade pending approval", + ); + expect(state.activityStatus).toBe("device approval needed: preview latest request"); + expect(state.pairingHint).toContain("openclaw devices approve --latest"); + expect(state.pairingHint).toContain("openclaw devices approve "); }); it("falls back to idle for generic disconnect reasons", () => { diff --git a/src/tui/tui.ts b/src/tui/tui.ts index 0effaa3507ff..369636c5db17 100644 --- a/src/tui/tui.ts +++ b/src/tui/tui.ts @@ -230,12 +230,15 @@ export function resolveGatewayDisconnectState(reason?: string): { pairingHint?: string; } { const reasonLabel = reason?.trim() ? reason.trim() : "closed"; - if (/pairing required/i.test(reasonLabel)) { + // Covers both "pairing required" and a pending "scope upgrade" for a paired device. + if (/pairing required|scope upgrade/i.test(reasonLabel)) { return { connectionStatus: `gateway disconnected: ${reasonLabel}`, - activityStatus: "pairing required: run openclaw devices list", + activityStatus: "device approval needed: preview latest request", pairingHint: - "Pairing required. Run `openclaw devices list`, approve your request ID, then reconnect.", + "Device approval needed. Run `openclaw devices approve --latest` to preview the pending request, " + + "then rerun the printed `openclaw devices approve ` command " + + "(reuse `--token` or other auth flags if needed), then reconnect.", }; } return {