@mindstudio-ai/local-model-tunnel 0.5.54 → 0.5.56

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
@@ -2169,19 +2169,16 @@ var ClientRegistry = class {
2169
2169
  return this.clients.get(id);
2170
2170
  }
2171
2171
  /**
2172
- * Get the preferred client for C&C commands.
2173
- * Prefers idle iframe clients, falls back to any idle client.
2174
- * Skips clients that are already executing a command.
2172
+ * Get the client for automation commands. Only the sandbox-owned headless
2173
+ * Chrome executes automation; iframe / standalone clients exist solely for
2174
+ * live preview and never receive command dispatches.
2175
2175
  */
2176
2176
  getCommandTarget() {
2177
- let fallback = null;
2178
2177
  for (const client of this.clients.values()) {
2179
2178
  if (client.activeCommandId) continue;
2180
- if (client.mode === "mirror") continue;
2181
- if (client.mode === "iframe") return client;
2182
- if (!fallback) fallback = client;
2179
+ if (client.mode === "headless") return client;
2183
2180
  }
2184
- return fallback;
2181
+ return null;
2185
2182
  }
2186
2183
  /** Get all connected mirror viewer clients (for relaying mirror events). */
2187
2184
  getMirrorClients() {
@@ -2383,15 +2380,22 @@ var DevProxy = class _DevProxy {
2383
2380
  }
2384
2381
  /**
2385
2382
  * Send a broadcast message to all connected browser clients.
2383
+ *
2384
+ * Headless (sandbox-owned) clients are skipped by default — they're
2385
+ * automation targets whose lifecycle is managed by `BrowserSupervisor`
2386
+ * and they shouldn't be hit by reload-all signals meant for live-preview
2387
+ * iframes. Pass `{ includeHeadless: true }` to override.
2386
2388
  */
2387
- broadcastToClients(action, payload) {
2389
+ broadcastToClients(action, payload, opts = {}) {
2388
2390
  const msg = JSON.stringify({ type: "broadcast", action, payload });
2389
2391
  const clients = this.clients.getAll();
2392
+ const targets = opts.includeHeadless ? clients : clients.filter((c) => c.mode !== "headless");
2390
2393
  log.info("proxy", "Broadcasting to browser clients", {
2391
2394
  action,
2392
- clientCount: clients.length
2395
+ clientCount: targets.length,
2396
+ skippedHeadless: clients.length - targets.length
2393
2397
  });
2394
- for (const client of clients) {
2398
+ for (const client of targets) {
2395
2399
  try {
2396
2400
  client.ws.send(msg);
2397
2401
  } catch {
@@ -2403,7 +2407,10 @@ var DevProxy = class _DevProxy {
2403
2407
  this.handleRequest(req, res);
2404
2408
  });
2405
2409
  this.wss = new WebSocketServer({ noServer: true });
2406
- this.wss.on("connection", (ws) => this.handleWsConnection(ws));
2410
+ this.wss.on(
2411
+ "connection",
2412
+ (ws, req) => this.handleWsConnection(ws, req)
2413
+ );
2407
2414
  server.on("upgrade", (req, socket, head) => {
2408
2415
  if (req.url === "/__mindstudio_dev__/ws") {
2409
2416
  this.wss.handleUpgrade(req, socket, head, (ws) => {
@@ -2486,8 +2493,10 @@ var DevProxy = class _DevProxy {
2486
2493
  // ---------------------------------------------------------------------------
2487
2494
  // WebSocket connection handler
2488
2495
  // ---------------------------------------------------------------------------
2489
- handleWsConnection(ws) {
2496
+ handleWsConnection(ws, req) {
2490
2497
  let clientId = null;
2498
+ const remoteAddr = req.socket.remoteAddress ?? "";
2499
+ const isLoopback = remoteAddr === "127.0.0.1" || remoteAddr === "::1" || remoteAddr === "::ffff:127.0.0.1";
2491
2500
  const helloTimeout = setTimeout(() => {
2492
2501
  if (!clientId) {
2493
2502
  log.warn(
@@ -2510,14 +2519,24 @@ var DevProxy = class _DevProxy {
2510
2519
  return;
2511
2520
  }
2512
2521
  clearTimeout(helloTimeout);
2513
- const mode = msg.mode === "iframe" ? "iframe" : msg.mode === "mirror" ? "mirror" : "standalone";
2522
+ const helloUrl = String(msg.url || "");
2523
+ const isSandboxBrowser = isLoopback && msg.sandbox === true;
2524
+ const mode = isSandboxBrowser ? "headless" : msg.mode === "iframe" ? "iframe" : msg.mode === "mirror" ? "mirror" : "standalone";
2525
+ log.debug("proxy", "WS hello received", {
2526
+ remoteAddr,
2527
+ isLoopback,
2528
+ helloMode: msg.mode,
2529
+ helloSandbox: msg.sandbox,
2530
+ helloUrl,
2531
+ resolvedMode: mode
2532
+ });
2514
2533
  const viewport = msg.viewport || {
2515
2534
  w: 0,
2516
2535
  h: 0
2517
2536
  };
2518
2537
  clientId = this.clients.add(ws, {
2519
2538
  mode,
2520
- url: String(msg.url || ""),
2539
+ url: helloUrl,
2521
2540
  viewport,
2522
2541
  mirror: !!msg.mirror
2523
2542
  });
@@ -3255,7 +3274,8 @@ function getWebInterfaceConfig(appConfig, cwd = process.cwd()) {
3255
3274
  }
3256
3275
  return {
3257
3276
  devPort: typeof web.devPort === "number" ? web.devPort : void 0,
3258
- devCommand: typeof web.devCommand === "string" ? web.devCommand : void 0
3277
+ devCommand: typeof web.devCommand === "string" ? web.devCommand : void 0,
3278
+ defaultPreviewMode: web.defaultPreviewMode === "mobile" ? "mobile" : web.defaultPreviewMode === "desktop" ? "desktop" : void 0
3259
3279
  };
3260
3280
  } catch {
3261
3281
  return null;
@@ -3444,4 +3464,4 @@ export {
3444
3464
  watchTableFiles,
3445
3465
  watchConfigFile
3446
3466
  };
3447
- //# sourceMappingURL=chunk-7XPEELY3.js.map
3467
+ //# sourceMappingURL=chunk-ERAJTIOM.js.map