Skip to content

Commit de96904

Browse files
authored
Merge 2fa8fef into e21ff32
2 parents e21ff32 + 2fa8fef commit de96904

5 files changed

Lines changed: 30 additions & 4 deletions

File tree

flutter_app/lib/constants.dart

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,6 @@
11
class AppConstants {
22
static const String appName = 'OpenClaw';
3-
static const String version = '1.8.6';
3+
static const String version = '1.8.7';
44
static const String packageName = 'com.nxg.openclawproot';
55

66
/// Matches ANSI escape sequences (e.g. color codes in terminal output).

flutter_app/lib/services/node_service.dart

Lines changed: 22 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -135,6 +135,7 @@ class NodeService {
135135
/// Resolve the gateway auth token from available sources:
136136
/// 1. Manually entered token (for remote gateways)
137137
/// 2. Dashboard URL fragment (for local gateway)
138+
/// 3. openclaw.json config file (source of truth — fallback when URL is stale or missing)
138139
Future<String?> _readGatewayToken() async {
139140
final prefs = PreferencesService();
140141
await prefs.init();
@@ -156,6 +157,24 @@ class NodeService {
156157
}
157158
}
158159

160+
// 3. Read directly from openclaw.json — the source of truth (#94).
161+
// This catches the case where dashboardUrl was cleared before a gateway
162+
// restart (GatewayService.start() nulls it out) but the config file still
163+
// holds the authoritative token, preventing token_missing reconnect loops.
164+
try {
165+
final raw = await NativeBridge.readRootfsFile('root/.openclaw/openclaw.json');
166+
if (raw != null) {
167+
final config = jsonDecode(raw) as Map<String, dynamic>;
168+
final token = config['gateway']?['auth']?['token'];
169+
if (token is String && token.isNotEmpty) {
170+
_log('[NODE] Gateway token read from openclaw.json config');
171+
return token;
172+
}
173+
}
174+
} catch (e) {
175+
_log('[NODE] Could not read token from openclaw.json: $e');
176+
}
177+
159178
_log('[NODE] No gateway token available');
160179
return null;
161180
}
@@ -256,6 +275,9 @@ class NodeService {
256275
}
257276

258277
void _onConnected(NodeFrame frame) {
278+
// Reset backoff only after a fully authenticated connection so that repeated
279+
// auth failures (e.g. token_missing) still produce growing retry delays (#94).
280+
_ws.resetReconnectAttempt();
259281
_updateState(_state.copyWith(
260282
status: NodeStatus.paired,
261283
connectedAt: DateTime.now(),

flutter_app/lib/services/node_ws_service.dart

Lines changed: 5 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -35,14 +35,18 @@ class NodeWsService {
3535
await _doConnect();
3636
}
3737

38+
/// Reset the reconnect backoff counter. Call this only once the gateway
39+
/// has fully authenticated the connection (not just the TCP handshake),
40+
/// so that repeated auth failures still produce a growing backoff delay.
41+
void resetReconnectAttempt() => _reconnectAttempt = 0;
42+
3843
Future<void> _doConnect() async {
3944
if (_url == null) return;
4045

4146
try {
4247
_channel = WebSocketChannel.connect(Uri.parse(_url!));
4348
await _channel!.ready;
4449
_connected = true;
45-
_reconnectAttempt = 0;
4650
_lastActivity = DateTime.now();
4751

4852
_startPing();

flutter_app/pubspec.yaml

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,7 @@
11
name: openclaw
22
description: OpenClaw AI Gateway for Android - standalone, no Termux required.
33
publish_to: 'none'
4-
version: 1.8.6+17
4+
version: 1.8.7+18
55

66
environment:
77
sdk: '>=3.2.0 <4.0.0'

package.json

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,6 @@
11
{
22
"name": "openclaw-termux",
3-
"version": "1.8.6",
3+
"version": "1.8.7",
44
"description": "OpenClaw AI Gateway for Android Termux with Bionic Bypass",
55
"main": "lib/index.js",
66
"type": "module",

0 commit comments

Comments
 (0)