Skip to content

Commit 5f9b6b9

Browse files
author
GitLab CI
committed
fix: serve command - shared state for tool cache, auto-refresh on navigate
1 parent 46b6b9d commit 5f9b6b9

1 file changed

Lines changed: 46 additions & 20 deletions

File tree

lib/src/cli/serve.dart

Lines changed: 46 additions & 20 deletions
Original file line numberDiff line numberDiff line change
@@ -86,7 +86,6 @@ Future<void> runServe(List<String> args) async {
8686
// Step 2: Initial tool discovery
8787
print('🔍 Scanning page for interactive elements...');
8888
var toolCache = await _discoverAndPrint(cdp);
89-
var toolCacheTime = DateTime.now();
9089

9190
// Step 3: Set up hot reload detection
9291
if (watch) {
@@ -113,16 +112,18 @@ Future<void> runServe(List<String> args) async {
113112

114113
final server = await HttpServer.bind(InternetAddress.anyIPv4, serverPort);
115114

115+
// Shared mutable state
116+
final state = _ServeState(toolCache, DateTime.now());
117+
116118
// Background: poll for DOM changes
117119
if (watch) {
118120
Timer.periodic(const Duration(seconds: 2), (timer) async {
119121
try {
120122
final changed = await _checkForChanges(cdp);
121123
if (changed) {
122-
print(
123-
'🔄 Page changed (hot reload?) — rescanning ${DateTime.now().toIso8601String()}');
124-
toolCache = await _discoverAndPrint(cdp);
125-
toolCacheTime = DateTime.now();
124+
print('🔄 Page changed (hot reload?) — rescanning...');
125+
state.tools = await _discoverAndPrint(cdp);
126+
state.updatedAt = DateTime.now();
126127
}
127128
} catch (e) {
128129
// CDP connection may drop — ignore
@@ -133,14 +134,17 @@ Future<void> runServe(List<String> args) async {
133134
await for (final request in server) {
134135
try {
135136
// Refresh tools on each request if stale (> 30s)
136-
if (DateTime.now().difference(toolCacheTime).inSeconds > 30) {
137+
if (DateTime.now().difference(state.updatedAt).inSeconds > 30) {
137138
try {
138-
toolCache = await _discoverTools(cdp);
139-
toolCacheTime = DateTime.now();
140-
} catch (_) {}
139+
state.tools = await _discoverTools(cdp);
140+
state.updatedAt = DateTime.now();
141+
} catch (e) {
142+
print(' ⚠️ Tool refresh failed: $e');
143+
}
141144
}
142-
await _handleRequest(request, cdp, toolCache);
145+
await _handleRequest(request, cdp, state);
143146
} catch (e) {
147+
print(' ❌ Request error: $e');
144148
try {
145149
request.response
146150
..statusCode = 500
@@ -152,12 +156,20 @@ Future<void> runServe(List<String> args) async {
152156
}
153157
}
154158

159+
/// Shared mutable state for the serve session
160+
class _ServeState {
161+
List<Map<String, dynamic>> tools;
162+
DateTime updatedAt;
163+
_ServeState(this.tools, this.updatedAt);
164+
}
165+
155166
/// Handle HTTP requests
156167
Future<void> _handleRequest(
157168
HttpRequest request,
158169
CdpDriver cdp,
159-
List<Map<String, dynamic>> tools,
170+
_ServeState state,
160171
) async {
172+
final tools = state.tools;
161173
final path = request.uri.path;
162174
final method = request.method;
163175
final response = request.response;
@@ -280,22 +292,36 @@ Future<void> _handleRequest(
280292
return;
281293
}
282294
print(' 🌐 Navigating to: $navUrl');
283-
final navResult = await cdp.navigate(navUrl);
284-
// Wait for page load, then re-scan
285-
await Future.delayed(const Duration(seconds: 2));
286-
response
287-
..statusCode = 200
288-
..headers.contentType = ContentType.json
289-
..write(jsonEncode(navResult));
295+
try {
296+
// Use CDP Page.navigate directly to stay on same WS connection
297+
await cdp.call('Page.navigate', {'url': navUrl});
298+
// Wait for page load
299+
await Future.delayed(const Duration(seconds: 3));
300+
// Re-setup observers and re-scan tools
301+
await _setupHotReloadDetection(cdp);
302+
state.tools = await _discoverAndPrint(cdp);
303+
state.updatedAt = DateTime.now();
304+
response
305+
..statusCode = 200
306+
..headers.contentType = ContentType.json
307+
..write(
308+
jsonEncode({'navigated': navUrl, 'tools': state.tools.length}));
309+
} catch (e) {
310+
response
311+
..statusCode = 500
312+
..headers.contentType = ContentType.json
313+
..write(jsonEncode({'error': e.toString()}));
314+
}
290315
await response.close();
291316

292317
case '/refresh':
293318
print(' 🔄 Force refresh tools');
294-
final newTools = await _discoverTools(cdp);
319+
state.tools = await _discoverAndPrint(cdp);
320+
state.updatedAt = DateTime.now();
295321
response
296322
..statusCode = 200
297323
..headers.contentType = ContentType.json
298-
..write(jsonEncode({'tools': newTools.length, 'refreshed': true}));
324+
..write(jsonEncode({'tools': state.tools.length, 'refreshed': true}));
299325
await response.close();
300326

301327
default:

0 commit comments

Comments
 (0)