meshy-node 0.4.1 → 0.4.2

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.
package/main.cjs CHANGED
@@ -33089,6 +33089,22 @@ function parseNodeSettingsSnapshot(value) {
33089
33089
  }
33090
33090
  return clone(value);
33091
33091
  }
33092
+ function parseDevTunnelHealth(value) {
33093
+ if (!isPlainObject(value)) {
33094
+ return void 0;
33095
+ }
33096
+ if (value.status !== "healthy" && value.status !== "failed" || typeof value.checkedAt !== "number" || !Number.isFinite(value.checkedAt)) {
33097
+ return void 0;
33098
+ }
33099
+ return {
33100
+ status: value.status,
33101
+ checkedAt: value.checkedAt,
33102
+ endpoint: typeof value.endpoint === "string" ? value.endpoint : void 0,
33103
+ reason: typeof value.reason === "string" ? value.reason : void 0,
33104
+ statusCode: typeof value.statusCode === "number" && Number.isFinite(value.statusCode) ? value.statusCode : void 0,
33105
+ consecutiveFailures: typeof value.consecutiveFailures === "number" && Number.isFinite(value.consecutiveFailures) ? value.consecutiveFailures : void 0
33106
+ };
33107
+ }
33092
33108
  function isClusterInfo(value) {
33093
33109
  return isPlainObject(value) && typeof value.clusterId === "string" && typeof value.createdAt === "number" && Number.isFinite(value.createdAt);
33094
33110
  }
@@ -33112,6 +33128,7 @@ function parseNodeInfo(value) {
33112
33128
  lastHeartbeat: value.lastHeartbeat,
33113
33129
  transportType: typeof value.transportType === "string" ? value.transportType : void 0,
33114
33130
  devtunnelEndpoint: typeof value.devtunnelEndpoint === "string" ? value.devtunnelEndpoint : void 0,
33131
+ devtunnelHealth: parseDevTunnelHealth(value.devtunnelHealth),
33115
33132
  dashboardOrigin: typeof value.dashboardOrigin === "string" ? value.dashboardOrigin : void 0,
33116
33133
  workDir: typeof value.workDir === "string" ? value.workDir : void 0,
33117
33134
  workDirFolders: parseStringArray(value.workDirFolders),
@@ -33515,6 +33532,24 @@ var NodeRegistry = class {
33515
33532
  }
33516
33533
  }
33517
33534
  }
33535
+ updateDevTunnelHealth(id, devtunnelHealth) {
33536
+ const node = this.nodes.get(id);
33537
+ if (node) {
33538
+ if (devtunnelHealth) {
33539
+ node.devtunnelHealth = { ...devtunnelHealth };
33540
+ } else {
33541
+ delete node.devtunnelHealth;
33542
+ }
33543
+ this.store.upsertNode(node);
33544
+ }
33545
+ if (this.selfNode && this.selfNode.id === id) {
33546
+ if (devtunnelHealth) {
33547
+ this.selfNode.devtunnelHealth = { ...devtunnelHealth };
33548
+ } else {
33549
+ delete this.selfNode.devtunnelHealth;
33550
+ }
33551
+ }
33552
+ }
33518
33553
  updateDashboardOrigin(id, dashboardOrigin) {
33519
33554
  const node = this.nodes.get(id);
33520
33555
  if (node) {
@@ -34689,17 +34724,9 @@ var HeartbeatMonitor = class {
34689
34724
  running = false;
34690
34725
  followerMissedMap = /* @__PURE__ */ new Map();
34691
34726
  followerPushReachableMap = /* @__PURE__ */ new Map();
34692
- /**
34693
- * Tracks whether a push-heartbeat has EVER succeeded for a follower.
34694
- * If push has never worked, the follower is on an unreachable network
34695
- * and should not be marked offline based on push failures alone.
34696
- */
34727
+ // Tracks whether push-heartbeat has ever succeeded for a follower.
34697
34728
  followerEverReachedMap = /* @__PURE__ */ new Map();
34698
- /**
34699
- * Last known leader endpoint — preserved across clearLeader() so
34700
- * follower keepalives can still attempt to reach the leader even
34701
- * after the follower timer fires.
34702
- */
34729
+ // Preserved across clearLeader() so follower keepalives can still reach the leader.
34703
34730
  lastKnownLeaderEndpoint = null;
34704
34731
  getQueuedMessages;
34705
34732
  messageQueue;
@@ -34922,6 +34949,7 @@ var HeartbeatMonitor = class {
34922
34949
  supportedAgents: self2.supportedAgents,
34923
34950
  devtunnelEnabled: self2.devtunnelEndpoint !== void 0,
34924
34951
  devtunnelEndpoint: self2.devtunnelEndpoint,
34952
+ devtunnelHealth: self2.devtunnelHealth,
34925
34953
  dashboardOrigin: self2.dashboardOrigin,
34926
34954
  workDirFolders: self2.workDir ? listWorkDirFolders(self2.workDir) : void 0,
34927
34955
  settingsSnapshot: this.resolveCurrentSettingsSnapshot()
@@ -34942,6 +34970,7 @@ var HeartbeatMonitor = class {
34942
34970
  workDir,
34943
34971
  devtunnelEnabled,
34944
34972
  devtunnelEndpoint,
34973
+ devtunnelHealth,
34945
34974
  dashboardOrigin,
34946
34975
  workDirFolders,
34947
34976
  settingsSnapshot
@@ -34969,6 +34998,7 @@ var HeartbeatMonitor = class {
34969
34998
  ...transportType ? { transportType } : {},
34970
34999
  ...workDir ? { workDir } : {},
34971
35000
  ...devtunnelEnabled && devtunnelEndpoint ? { devtunnelEndpoint } : {},
35001
+ ...devtunnelHealth ? { devtunnelHealth } : {},
34972
35002
  ...dashboardOrigin ? { dashboardOrigin } : {},
34973
35003
  ...workDirFolders ? { workDirFolders } : {},
34974
35004
  ...settingsSnapshot ? { settingsSnapshot } : {}
@@ -35004,6 +35034,7 @@ var HeartbeatMonitor = class {
35004
35034
  }
35005
35035
  this.nodeRegistry.updateLoad(nodeId, load);
35006
35036
  this.applyReportedDevTunnelState(nodeId, devtunnelEnabled, devtunnelEndpoint);
35037
+ this.nodeRegistry.updateDevTunnelHealth(nodeId, devtunnelEnabled === false ? void 0 : devtunnelHealth);
35007
35038
  this.nodeRegistry.updateDashboardOrigin(nodeId, dashboardOrigin);
35008
35039
  if (workDirFolders) {
35009
35040
  this.nodeRegistry.updateFolders(nodeId, workDirFolders);
@@ -35053,6 +35084,7 @@ var HeartbeatMonitor = class {
35053
35084
  workDir: self2.workDir,
35054
35085
  devtunnelEnabled: self2.devtunnelEndpoint !== void 0,
35055
35086
  devtunnelEndpoint: self2.devtunnelEndpoint,
35087
+ devtunnelHealth: self2.devtunnelHealth,
35056
35088
  dashboardOrigin: self2.dashboardOrigin,
35057
35089
  workDirFolders: self2.workDir ? listWorkDirFolders(self2.workDir) : void 0,
35058
35090
  settingsSnapshot
@@ -37760,6 +37792,9 @@ ${joinErrors.map((e) => ` - ${e}`).join("\n")}`
37760
37792
  if (self2.devtunnelEndpoint) {
37761
37793
  joinBody.devtunnelEndpoint = self2.devtunnelEndpoint;
37762
37794
  }
37795
+ if (self2.devtunnelHealth) {
37796
+ joinBody.devtunnelHealth = self2.devtunnelHealth;
37797
+ }
37763
37798
  if (self2.dashboardOrigin) {
37764
37799
  joinBody.dashboardOrigin = self2.dashboardOrigin;
37765
37800
  }
@@ -38093,6 +38128,7 @@ ${joinErrors.map((e) => ` - ${e}`).join("\n")}`
38093
38128
  workDir: currentSelf.workDir,
38094
38129
  workDirFolders: listWorkDirFolders(this.getWorkDir()),
38095
38130
  ...currentSelf.devtunnelEndpoint ? { devtunnelEndpoint: currentSelf.devtunnelEndpoint } : {},
38131
+ ...currentSelf.devtunnelHealth ? { devtunnelHealth: currentSelf.devtunnelHealth } : {},
38096
38132
  ...currentSelf.dashboardOrigin ? { dashboardOrigin: currentSelf.dashboardOrigin } : {},
38097
38133
  ...currentSelf.settingsSnapshot ? { settingsSnapshot: currentSelf.settingsSnapshot } : {}
38098
38134
  };
@@ -42945,6 +42981,14 @@ var NodeSettingsSnapshotSchema = external_exports.object({
42945
42981
  api: SystemPackageInfoSchema.optional()
42946
42982
  }).optional()
42947
42983
  });
42984
+ var DevTunnelHealthSchema = external_exports.object({
42985
+ status: external_exports.enum(["healthy", "failed"]),
42986
+ checkedAt: external_exports.number(),
42987
+ endpoint: external_exports.string().optional(),
42988
+ reason: external_exports.string().optional(),
42989
+ statusCode: external_exports.number().optional(),
42990
+ consecutiveFailures: external_exports.number().optional()
42991
+ });
42948
42992
 
42949
42993
  // ../../packages/api/src/schemas/cluster.ts
42950
42994
  var NodeInfoSchema = external_exports.object({
@@ -42959,6 +43003,7 @@ var NodeInfoSchema = external_exports.object({
42959
43003
  lastHeartbeat: external_exports.number(),
42960
43004
  transportType: external_exports.string().optional(),
42961
43005
  devtunnelEndpoint: external_exports.string().optional(),
43006
+ devtunnelHealth: DevTunnelHealthSchema.optional(),
42962
43007
  dashboardOrigin: external_exports.string().optional(),
42963
43008
  workDir: external_exports.string().optional(),
42964
43009
  workDirFolders: external_exports.array(external_exports.string()).optional(),
@@ -42995,6 +43040,7 @@ var JoinClusterBody = external_exports.object({
42995
43040
  workDir: external_exports.string().optional(),
42996
43041
  workDirFolders: external_exports.array(external_exports.string()).optional(),
42997
43042
  devtunnelEndpoint: external_exports.string().url().optional(),
43043
+ devtunnelHealth: DevTunnelHealthSchema.optional(),
42998
43044
  dashboardOrigin: external_exports.string().url().optional(),
42999
43045
  settingsSnapshot: NodeSettingsSnapshotSchema.optional(),
43000
43046
  tasks: external_exports.array(JoinTaskSchema).default([])
@@ -43039,6 +43085,7 @@ var NodeInfoSchema2 = external_exports.object({
43039
43085
  lastHeartbeat: external_exports.number(),
43040
43086
  transportType: external_exports.string().optional(),
43041
43087
  devtunnelEndpoint: external_exports.string().optional(),
43088
+ devtunnelHealth: DevTunnelHealthSchema.optional(),
43042
43089
  dashboardOrigin: external_exports.string().optional(),
43043
43090
  workDir: external_exports.string().optional(),
43044
43091
  workDirFolders: external_exports.array(external_exports.string()).optional(),
@@ -50729,6 +50776,82 @@ function buildRuntimeMetadata(storagePath) {
50729
50776
  };
50730
50777
  }
50731
50778
 
50779
+ // src/bootstrap/tunnel-health.ts
50780
+ var DEFAULT_TUNNEL_REACHABILITY_INTERVAL_MS = 6e4;
50781
+ var DEFAULT_TUNNEL_REACHABILITY_TIMEOUT_MS = 5e3;
50782
+ var DEFAULT_TUNNEL_RESTART_FAILURE_THRESHOLD = 2;
50783
+ function createTunnelReachabilityMonitor(options = {}) {
50784
+ const failureThreshold = options.failureThreshold ?? DEFAULT_TUNNEL_RESTART_FAILURE_THRESHOLD;
50785
+ const fetchImpl = options.fetchImpl ?? fetch;
50786
+ const healthPath = options.healthPath ?? "/api/system/health";
50787
+ const intervalMs = options.intervalMs ?? DEFAULT_TUNNEL_REACHABILITY_INTERVAL_MS;
50788
+ const now = options.now ?? (() => Date.now());
50789
+ const timeoutMs = options.timeoutMs ?? DEFAULT_TUNNEL_REACHABILITY_TIMEOUT_MS;
50790
+ let consecutiveFailures = 0;
50791
+ let lastCheckedAt = null;
50792
+ function recordFailure(reason, statusCode) {
50793
+ consecutiveFailures += 1;
50794
+ return {
50795
+ available: false,
50796
+ checked: true,
50797
+ consecutiveFailures,
50798
+ reason,
50799
+ shouldRestart: consecutiveFailures >= failureThreshold,
50800
+ ...statusCode !== void 0 ? { statusCode } : {}
50801
+ };
50802
+ }
50803
+ return {
50804
+ async check(endpoint) {
50805
+ const currentTime = now();
50806
+ if (lastCheckedAt !== null && currentTime - lastCheckedAt < intervalMs) {
50807
+ return {
50808
+ available: true,
50809
+ checked: false,
50810
+ consecutiveFailures,
50811
+ shouldRestart: false
50812
+ };
50813
+ }
50814
+ lastCheckedAt = currentTime;
50815
+ if (!endpoint) {
50816
+ return recordFailure("missing endpoint");
50817
+ }
50818
+ try {
50819
+ const response = await fetchWithTimeout2(fetchImpl, buildHealthUrl(endpoint, healthPath), timeoutMs);
50820
+ if (!response.ok) {
50821
+ return recordFailure(`health check returned ${response.status}`, response.status);
50822
+ }
50823
+ consecutiveFailures = 0;
50824
+ return {
50825
+ available: true,
50826
+ checked: true,
50827
+ consecutiveFailures,
50828
+ shouldRestart: false,
50829
+ statusCode: response.status
50830
+ };
50831
+ } catch (err) {
50832
+ return recordFailure(err instanceof Error ? err.message : String(err));
50833
+ }
50834
+ },
50835
+ reset() {
50836
+ consecutiveFailures = 0;
50837
+ lastCheckedAt = null;
50838
+ }
50839
+ };
50840
+ }
50841
+ function buildHealthUrl(endpoint, healthPath) {
50842
+ return new URL(healthPath, endpoint).toString();
50843
+ }
50844
+ async function fetchWithTimeout2(fetchImpl, url, timeoutMs) {
50845
+ const controller = new AbortController();
50846
+ const timer = setTimeout(() => controller.abort(), timeoutMs);
50847
+ timer.unref?.();
50848
+ try {
50849
+ return await fetchImpl(url, { method: "GET", signal: controller.signal });
50850
+ } finally {
50851
+ clearTimeout(timer);
50852
+ }
50853
+ }
50854
+
50732
50855
  // src/bootstrap/start-node.ts
50733
50856
  function createSettingsSnapshotProvider(options) {
50734
50857
  let cachedSnapshot = null;
@@ -50818,6 +50941,9 @@ function createTunnelManager(options) {
50818
50941
  let shareTransport = null;
50819
50942
  let dashboardHealthTimer = null;
50820
50943
  let nodeTunnelHealthTimer = null;
50944
+ let dashboardHealthCheckRunning = false;
50945
+ let nodeTunnelHealthCheckRunning = false;
50946
+ const nodeTunnelReachability = createTunnelReachabilityMonitor();
50821
50947
  function createDashboardTransportConfig() {
50822
50948
  return {
50823
50949
  type: "devtunnel",
@@ -50857,6 +50983,28 @@ function createTunnelManager(options) {
50857
50983
  function shouldPublishDashboardTunnel() {
50858
50984
  return authMetadata.enabled && (meshyNode.getTransportType() === "devtunnel" || meshyNode.isDevTunnelEnabled());
50859
50985
  }
50986
+ function getPublishedNodeTunnelEndpoint() {
50987
+ const self2 = meshyNode.getNodeRegistry().getSelf();
50988
+ return meshyNode.getTransportType() === "devtunnel" ? self2.endpoint : self2.devtunnelEndpoint;
50989
+ }
50990
+ function setPublishedNodeTunnelHealth(health) {
50991
+ const selfId = meshyNode.getNodeRegistry().getSelf().id;
50992
+ meshyNode.getNodeRegistry().updateDevTunnelHealth(selfId, health);
50993
+ }
50994
+ function markPublishedNodeTunnelHealthy(endpoint) {
50995
+ setPublishedNodeTunnelHealth({
50996
+ status: "healthy",
50997
+ checkedAt: Date.now(),
50998
+ ...endpoint ? { endpoint } : {}
50999
+ });
51000
+ }
51001
+ function markPublishedNodeTunnelFailed(details) {
51002
+ setPublishedNodeTunnelHealth({
51003
+ status: "failed",
51004
+ checkedAt: Date.now(),
51005
+ ...details
51006
+ });
51007
+ }
50860
51008
  async function stopDashboardTransport(reason) {
50861
51009
  if (!dashboardTransport) {
50862
51010
  if (dashboardOrigin) {
@@ -50960,31 +51108,100 @@ function createTunnelManager(options) {
50960
51108
  if (!nodeTunnelHealthTimer) {
50961
51109
  nodeTunnelHealthTimer = setInterval(() => {
50962
51110
  void (async () => {
50963
- if (!meshyNode.hasPublishedNodeTunnel()) {
51111
+ if (nodeTunnelHealthCheckRunning) {
50964
51112
  return;
50965
51113
  }
50966
- const healthy = await meshyNode.isPublishedNodeTunnelHealthy().catch(() => false);
50967
- if (healthy) {
50968
- return;
50969
- }
50970
- meshyNode.getLogger().warn("published node tunnel became unhealthy; restarting with stable id", {
50971
- mainTransportType: meshyNode.getTransportType(),
50972
- sidecarEnabled: meshyNode.isDevTunnelEnabled()
50973
- });
51114
+ nodeTunnelHealthCheckRunning = true;
50974
51115
  try {
50975
- const endpoint = await meshyNode.restartPublishedNodeTunnel();
50976
- meshyNode.getLogger().info("restarted published node tunnel", {
50977
- endpoint,
50978
- stableUrl: true,
50979
- mainTransportType: meshyNode.getTransportType(),
50980
- sidecarEnabled: meshyNode.isDevTunnelEnabled()
51116
+ if (!meshyNode.hasPublishedNodeTunnel()) {
51117
+ nodeTunnelReachability.reset();
51118
+ setPublishedNodeTunnelHealth(void 0);
51119
+ return;
51120
+ }
51121
+ const publishedEndpoint = getPublishedNodeTunnelEndpoint();
51122
+ const healthy = await meshyNode.isPublishedNodeTunnelHealthy().catch(() => false);
51123
+ if (!healthy) {
51124
+ markPublishedNodeTunnelFailed({
51125
+ endpoint: publishedEndpoint,
51126
+ reason: "devtunnel process is not running"
51127
+ });
51128
+ meshyNode.getLogger().warn("published node tunnel process became unhealthy; restarting with stable id", {
51129
+ mainTransportType: meshyNode.getTransportType(),
51130
+ sidecarEnabled: meshyNode.isDevTunnelEnabled()
51131
+ });
51132
+ try {
51133
+ const endpoint = await meshyNode.restartPublishedNodeTunnel();
51134
+ nodeTunnelReachability.reset();
51135
+ markPublishedNodeTunnelHealthy(endpoint);
51136
+ meshyNode.getLogger().info("restarted published node tunnel", {
51137
+ endpoint,
51138
+ stableUrl: true,
51139
+ mainTransportType: meshyNode.getTransportType(),
51140
+ sidecarEnabled: meshyNode.isDevTunnelEnabled()
51141
+ });
51142
+ } catch (err) {
51143
+ markPublishedNodeTunnelFailed({
51144
+ endpoint: publishedEndpoint,
51145
+ reason: err instanceof Error ? err.message : String(err)
51146
+ });
51147
+ meshyNode.getLogger().warn("failed to restart published node tunnel", {
51148
+ error: err instanceof Error ? err.message : String(err),
51149
+ mainTransportType: meshyNode.getTransportType(),
51150
+ sidecarEnabled: meshyNode.isDevTunnelEnabled()
51151
+ });
51152
+ }
51153
+ return;
51154
+ }
51155
+ const reachability = await nodeTunnelReachability.check(publishedEndpoint);
51156
+ if (!reachability.checked) {
51157
+ return;
51158
+ }
51159
+ if (reachability.available) {
51160
+ markPublishedNodeTunnelHealthy(publishedEndpoint);
51161
+ return;
51162
+ }
51163
+ markPublishedNodeTunnelFailed({
51164
+ consecutiveFailures: reachability.consecutiveFailures,
51165
+ endpoint: publishedEndpoint,
51166
+ reason: reachability.reason,
51167
+ statusCode: reachability.statusCode
50981
51168
  });
50982
- } catch (err) {
50983
- meshyNode.getLogger().warn("failed to restart published node tunnel", {
50984
- error: err instanceof Error ? err.message : String(err),
51169
+ meshyNode.getLogger().warn("published node tunnel endpoint health check failed", {
51170
+ consecutiveFailures: reachability.consecutiveFailures,
51171
+ failureThresholdReached: reachability.shouldRestart,
50985
51172
  mainTransportType: meshyNode.getTransportType(),
50986
- sidecarEnabled: meshyNode.isDevTunnelEnabled()
51173
+ reason: reachability.reason,
51174
+ sidecarEnabled: meshyNode.isDevTunnelEnabled(),
51175
+ statusCode: reachability.statusCode
50987
51176
  });
51177
+ if (!reachability.shouldRestart) {
51178
+ return;
51179
+ }
51180
+ try {
51181
+ const endpoint = await meshyNode.restartPublishedNodeTunnel();
51182
+ nodeTunnelReachability.reset();
51183
+ markPublishedNodeTunnelHealthy(endpoint);
51184
+ meshyNode.getLogger().info("restarted published node tunnel", {
51185
+ endpoint,
51186
+ stableUrl: true,
51187
+ mainTransportType: meshyNode.getTransportType(),
51188
+ sidecarEnabled: meshyNode.isDevTunnelEnabled()
51189
+ });
51190
+ } catch (err) {
51191
+ markPublishedNodeTunnelFailed({
51192
+ consecutiveFailures: reachability.consecutiveFailures,
51193
+ endpoint: publishedEndpoint,
51194
+ reason: err instanceof Error ? err.message : String(err),
51195
+ statusCode: reachability.statusCode
51196
+ });
51197
+ meshyNode.getLogger().warn("failed to restart published node tunnel", {
51198
+ error: err instanceof Error ? err.message : String(err),
51199
+ mainTransportType: meshyNode.getTransportType(),
51200
+ sidecarEnabled: meshyNode.isDevTunnelEnabled()
51201
+ });
51202
+ }
51203
+ } finally {
51204
+ nodeTunnelHealthCheckRunning = false;
50988
51205
  }
50989
51206
  })();
50990
51207
  }, config.cluster.heartbeatInterval);
@@ -50992,17 +51209,24 @@ function createTunnelManager(options) {
50992
51209
  if (!dashboardHealthTimer) {
50993
51210
  dashboardHealthTimer = setInterval(() => {
50994
51211
  void (async () => {
50995
- if (!dashboardTransport) {
51212
+ if (dashboardHealthCheckRunning) {
50996
51213
  return;
50997
51214
  }
50998
- const healthy = await dashboardTransport.isHealthy().catch(() => false);
50999
- if (healthy) {
51000
- return;
51215
+ dashboardHealthCheckRunning = true;
51216
+ try {
51217
+ if (!dashboardTransport) {
51218
+ return;
51219
+ }
51220
+ const healthy = await dashboardTransport.isHealthy().catch(() => false);
51221
+ if (!healthy) {
51222
+ meshyNode.getLogger().warn("dashboard tunnel process became unhealthy; restarting with stable id", {
51223
+ port: config.node.port
51224
+ });
51225
+ await restartDashboardTransport("healthcheck");
51226
+ }
51227
+ } finally {
51228
+ dashboardHealthCheckRunning = false;
51001
51229
  }
51002
- meshyNode.getLogger().warn("dashboard tunnel became unhealthy; restarting with stable id", {
51003
- port: config.node.port
51004
- });
51005
- await restartDashboardTransport("healthcheck");
51006
51230
  })();
51007
51231
  }, config.cluster.heartbeatInterval);
51008
51232
  }
@@ -51016,6 +51240,7 @@ function createTunnelManager(options) {
51016
51240
  clearInterval(nodeTunnelHealthTimer);
51017
51241
  nodeTunnelHealthTimer = null;
51018
51242
  }
51243
+ nodeTunnelReachability.reset();
51019
51244
  }
51020
51245
  async function stop() {
51021
51246
  stopHealthChecks();
@@ -51168,6 +51393,9 @@ async function startNode(args) {
51168
51393
  switchTransport: async (type) => {
51169
51394
  const endpoint = await meshyNode.switchTransport(type);
51170
51395
  persistNodeStartupTransport(config.storage.path, type);
51396
+ if (type !== "devtunnel" && !meshyNode.isDevTunnelEnabled()) {
51397
+ meshyNode.getNodeRegistry().updateDevTunnelHealth(meshyNode.getNodeRegistry().getSelf().id, void 0);
51398
+ }
51171
51399
  await tunnelManager.syncDashboardTransport(`switchTransport:${type}`);
51172
51400
  return endpoint;
51173
51401
  },
@@ -51180,6 +51408,9 @@ async function startNode(args) {
51180
51408
  },
51181
51409
  disableDevTunnel: async () => {
51182
51410
  await meshyNode.disableDevTunnel();
51411
+ if (meshyNode.getTransportType() !== "devtunnel") {
51412
+ meshyNode.getNodeRegistry().updateDevTunnelHealth(meshyNode.getNodeRegistry().getSelf().id, void 0);
51413
+ }
51183
51414
  persistNodeStartupTransport(
51184
51415
  config.storage.path,
51185
51416
  meshyNode.getTransportType()
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "meshy-node",
3
- "version": "0.4.1",
3
+ "version": "0.4.2",
4
4
  "private": false,
5
5
  "description": "Standalone Meshy node package with bundled runtime and dashboard assets.",
6
6
  "type": "commonjs",
@@ -1,14 +1,14 @@
1
1
  {
2
2
  "packageName": "meshy-node",
3
- "packageVersion": "0.4.1",
3
+ "packageVersion": "0.4.2",
4
4
  "packages": {
5
5
  "workspace": {
6
6
  "name": "meshy",
7
- "version": "0.4.1"
7
+ "version": "0.4.2"
8
8
  },
9
9
  "node": {
10
10
  "name": "meshy-node",
11
- "version": "0.4.1"
11
+ "version": "0.4.2"
12
12
  },
13
13
  "core": {
14
14
  "name": "@meshy/core",
@@ -25,7 +25,7 @@
25
25
  },
26
26
  "repository": {
27
27
  "url": "https://github.com/ai-microsoft/meshy",
28
- "branch": "release0_4_1",
29
- "commit": "554b574"
28
+ "branch": "TunnelRestart",
29
+ "commit": "c895cea"
30
30
  }
31
31
  }