@@ -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
156167Future <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