GitHub Actions commited on
Commit
48ecfd2
·
1 Parent(s): f08047d

fix(node): replace 131 UTF-8 curly quotes with ASCII to fix SyntaxError

Browse files
Files changed (1) hide show
  1. hearthnet/node.py +23 -23
hearthnet/node.py CHANGED
@@ -108,7 +108,7 @@ class HearthNode:
108
  # remote peers over the network (e.g. the public HF Space). The
109
  # in-process InMemoryNetwork still passes a shared InMemoryTransport.
110
  # CompositeTransport is a drop-in superset of HttpBusTransport that also
111
- # accepts pluggable delivery strategies (relay/WebRTC/tunnel) relay is
112
  # attached only on demand via join_relay(), keeping nodes local-first.
113
  if transport is None:
114
  from hearthnet.bus.transport import CompositeTransport
@@ -122,13 +122,13 @@ class HearthNode:
122
  self.chat = ChatFacade(self.bus)
123
  self.marketplace = MarketplaceFacade(self.bus)
124
 
125
- # Manual peer bridging (discovery.peer.add / discovery.peers) enables
126
  # cross-network peering where mDNS/UDP multicast cannot reach.
127
  from hearthnet.discovery.service import DiscoveryService
128
 
129
  self.bus.register_service(DiscoveryService(self.bus, self.peers))
130
 
131
- # mesh.join redeem an invite/relay code into all-to-all relay membership.
132
  from hearthnet.transport.mesh_service import MeshService
133
 
134
  self.bus.register_service(MeshService(self))
@@ -162,7 +162,7 @@ class HearthNode:
162
  ) -> dict[str, Any]:
163
  """Join a relay hub so this node meshes all-to-all with NAT-bound peers.
164
 
165
- Opt-in only a node stays purely local until this is called (e.g. from a
166
  redeemed invite or the ``mesh up`` launcher). Registers the relay roster's
167
  capabilities locally and attaches a :class:`RelayStrategy` to the bus
168
  transport so calls to those peers are delivered through the hub.
@@ -208,7 +208,7 @@ class HearthNode:
208
  # ------------------------------------------------------------------
209
 
210
  def install_demo_services(self, *, internet_llm: bool = False, corpus: str = "demo") -> None:
211
- """FOR TESTS ONLY †install echo-LLM + in-memory services (no disk I/O, fast).
212
 
213
  Production code should call install_services() which auto-discovers real backends.
214
  """
@@ -267,10 +267,10 @@ class HearthNode:
267
  """Install real services with auto-discovered LLM backends.
268
 
269
  Backend discovery order (local-first, no internet unless explicitly enabled):
270
- 1. OllamaBackend †if ollama is running on localhost
271
- 2. LlamaCppBackend †if llama.cpp HTTP server is running on localhost
272
- 3. HfLocalBackend †if transformers is installed (loads on first call)
273
- 4. _UnavailableBackend †fallback: returns a clear error, not a silent echo
274
 
275
  Also installs ModelDistributionService so peers can pull model weights.
276
  """
@@ -311,7 +311,7 @@ class HearthNode:
311
  # 4. NVIDIA Nemotron (cloud NIM or local; NVIDIA prize track)
312
  if os.getenv("NVIDIA_API_KEY"):
313
  nemotron = NemotronBackend(api_key_env="NVIDIA_API_KEY")
314
- backends.append(nemotron) # cloud no local check needed
315
  _log.info("Nemotron backend registered (NVIDIA_API_KEY set)")
316
  elif os.getenv("NEMOTRON_URL"):
317
  nemotron_local = NemotronBackend(
@@ -388,7 +388,7 @@ class HearthNode:
388
  """Register the real auxiliary services beyond the core set.
389
 
390
  Always (each degrades gracefully to an "unavailable" response when its
391
- optional backend/model is missing never a mock):
392
  M11 EmbeddingService embed.text (real semantic vectors when
393
  sentence-transformers present)
394
  M24 RerankService rerank.text
@@ -501,7 +501,7 @@ class HearthNode:
501
  data_dir: Path | str | None = None,
502
  gossip_interval: int = _GOSSIP_INTERVAL_SECONDS,
503
  ) -> None:
504
- """Start the node †wires all subsystems.
505
 
506
  Steps:
507
  1-2. Already done: node_id + bus created in __init__
@@ -530,22 +530,22 @@ class HearthNode:
530
 
531
  # Step 9: Event log + replay engine
532
  # If the caller already opened an EventLog and set node._event_log before
533
- # calling start() (e.g. app.py for HF Space), reuse it don't open a second DB.
534
  if self._event_log is None:
535
  try:
536
  from hearthnet.events import EventLog, ReplayEngine
537
 
538
  self._event_log = EventLog(
539
- data_dir_path / events.db, self.community_id, self.node_id
540
  )
541
  self._replay_engine = ReplayEngine(self._event_log)
542
- _log.debug(EventLog opened at %s, data_dir_path / events.db)
543
  except Exception as exc:
544
- _log.warning(EventLog init failed (non-fatal): %s, exc)
545
  else:
546
- _log.debug(EventLog already set, reusing existing instance)
547
 
548
- # â€â€ Step 3: Peer discovery (mDNS + UDP) â€â€â€â€â€â€â€â€â€â€â€â€â€â€â€â€â€â€â€â€â€â€â
549
  caps = [e.descriptor.name for e in self.bus.registry.all_local()]
550
  try:
551
  from hearthnet.discovery.mdns import MdnsAnnouncer, MdnsBrowser
@@ -572,13 +572,13 @@ class HearthNode:
572
  except Exception as exc:
573
  _log.warning("Discovery init failed (non-fatal): %s", exc)
574
 
575
- # â€â€ Step 8: Emergency detector â€â€â€â€â€â€â€â€â€â€â€â€â€â€â€â€â€â€â€â€â€â€â€â€â€â€â€â€â€â€â€â
576
  try:
577
  await self.detector.start()
578
  except Exception as exc:
579
  _log.warning("Emergency detector start failed (non-fatal): %s", exc)
580
 
581
- # â€â€ Step 10: HTTP server (X01) + WebSocket pubsub (X06) â€â€â€â€â€â€â
582
  try:
583
  from hearthnet.events.sync import SyncServer
584
  from hearthnet.transport.server import HttpServer
@@ -603,7 +603,7 @@ class HearthNode:
603
  except Exception as exc:
604
  _log.warning("HTTP server start failed (non-fatal): %s", exc)
605
 
606
- # â€â€ Gossip sync loop (X02) â€â€â€â€â€â€â€â€â€â€â€â€â€â€â€â€â€â€â€â€â€â€â€â€â€â€â€â€â€â€â€â€â€â€â€â
607
  if self._event_log is not None:
608
  self._gossip_task = asyncio.create_task(
609
  self._gossip_loop(gossip_interval), name="gossip-sync"
@@ -827,7 +827,7 @@ class InMemoryNetwork:
827
 
828
 
829
  # ---------------------------------------------------------------------------
830
- # PeriodicTask generic async interval runner (M12 §5)
831
  # ---------------------------------------------------------------------------
832
 
833
 
@@ -856,7 +856,7 @@ class PeriodicTask:
856
 
857
 
858
  # ---------------------------------------------------------------------------
859
- # ManifestPublisher republishes node manifest to mDNS + UDP (M12 §5)
860
  # ---------------------------------------------------------------------------
861
 
862
  _MANIFEST_REPUBLISH_INTERVAL_SECONDS = 300 # 5 minutes default
 
108
  # remote peers over the network (e.g. the public HF Space). The
109
  # in-process InMemoryNetwork still passes a shared InMemoryTransport.
110
  # CompositeTransport is a drop-in superset of HttpBusTransport that also
111
+ # accepts pluggable delivery strategies (relay/WebRTC/tunnel) -- relay is
112
  # attached only on demand via join_relay(), keeping nodes local-first.
113
  if transport is None:
114
  from hearthnet.bus.transport import CompositeTransport
 
122
  self.chat = ChatFacade(self.bus)
123
  self.marketplace = MarketplaceFacade(self.bus)
124
 
125
+ # Manual peer bridging (discovery.peer.add / discovery.peers) -- enables
126
  # cross-network peering where mDNS/UDP multicast cannot reach.
127
  from hearthnet.discovery.service import DiscoveryService
128
 
129
  self.bus.register_service(DiscoveryService(self.bus, self.peers))
130
 
131
+ # mesh.join -- redeem an invite/relay code into all-to-all relay membership.
132
  from hearthnet.transport.mesh_service import MeshService
133
 
134
  self.bus.register_service(MeshService(self))
 
162
  ) -> dict[str, Any]:
163
  """Join a relay hub so this node meshes all-to-all with NAT-bound peers.
164
 
165
+ Opt-in only -- a node stays purely local until this is called (e.g. from a
166
  redeemed invite or the ``mesh up`` launcher). Registers the relay roster's
167
  capabilities locally and attaches a :class:`RelayStrategy` to the bus
168
  transport so calls to those peers are delivered through the hub.
 
208
  # ------------------------------------------------------------------
209
 
210
  def install_demo_services(self, *, internet_llm: bool = False, corpus: str = "demo") -> None:
211
+ """FOR TESTS ONLY â€" install echo-LLM + in-memory services (no disk I/O, fast).
212
 
213
  Production code should call install_services() which auto-discovers real backends.
214
  """
 
267
  """Install real services with auto-discovered LLM backends.
268
 
269
  Backend discovery order (local-first, no internet unless explicitly enabled):
270
+ 1. OllamaBackend â€" if ollama is running on localhost
271
+ 2. LlamaCppBackend â€" if llama.cpp HTTP server is running on localhost
272
+ 3. HfLocalBackend â€" if transformers is installed (loads on first call)
273
+ 4. _UnavailableBackend â€" fallback: returns a clear error, not a silent echo
274
 
275
  Also installs ModelDistributionService so peers can pull model weights.
276
  """
 
311
  # 4. NVIDIA Nemotron (cloud NIM or local; NVIDIA prize track)
312
  if os.getenv("NVIDIA_API_KEY"):
313
  nemotron = NemotronBackend(api_key_env="NVIDIA_API_KEY")
314
+ backends.append(nemotron) # cloud -- no local check needed
315
  _log.info("Nemotron backend registered (NVIDIA_API_KEY set)")
316
  elif os.getenv("NEMOTRON_URL"):
317
  nemotron_local = NemotronBackend(
 
388
  """Register the real auxiliary services beyond the core set.
389
 
390
  Always (each degrades gracefully to an "unavailable" response when its
391
+ optional backend/model is missing -- never a mock):
392
  M11 EmbeddingService embed.text (real semantic vectors when
393
  sentence-transformers present)
394
  M24 RerankService rerank.text
 
501
  data_dir: Path | str | None = None,
502
  gossip_interval: int = _GOSSIP_INTERVAL_SECONDS,
503
  ) -> None:
504
+ """Start the node â€" wires all subsystems.
505
 
506
  Steps:
507
  1-2. Already done: node_id + bus created in __init__
 
530
 
531
  # Step 9: Event log + replay engine
532
  # If the caller already opened an EventLog and set node._event_log before
533
+ # calling start() (e.g. app.py for HF Space), reuse it -- don't open a second DB.
534
  if self._event_log is None:
535
  try:
536
  from hearthnet.events import EventLog, ReplayEngine
537
 
538
  self._event_log = EventLog(
539
+ data_dir_path / "events.db", self.community_id, self.node_id
540
  )
541
  self._replay_engine = ReplayEngine(self._event_log)
542
+ _log.debug("EventLog opened at %s", data_dir_path / "events.db")
543
  except Exception as exc:
544
+ _log.warning("EventLog init failed (non-fatal): %s", exc)
545
  else:
546
+ _log.debug("EventLog already set, reusing existing instance")
547
 
548
+ # â"€â"€ Step 3: Peer discovery (mDNS + UDP) â"€â"€â"€â"€â"€â"€â"€â"€â"€â"€â"€â"€â"€â"€â"€â"€â"€â"€â"€â"€â"€â"€â"
549
  caps = [e.descriptor.name for e in self.bus.registry.all_local()]
550
  try:
551
  from hearthnet.discovery.mdns import MdnsAnnouncer, MdnsBrowser
 
572
  except Exception as exc:
573
  _log.warning("Discovery init failed (non-fatal): %s", exc)
574
 
575
+ # â"€â"€ Step 8: Emergency detector â"€â"€â"€â"€â"€â"€â"€â"€â"€â"€â"€â"€â"€â"€â"€â"€â"€â"€â"€â"€â"€â"€â"€â"€â"€â"€â"€â"€â"€â"€â"€â"
576
  try:
577
  await self.detector.start()
578
  except Exception as exc:
579
  _log.warning("Emergency detector start failed (non-fatal): %s", exc)
580
 
581
+ # â"€â"€ Step 10: HTTP server (X01) + WebSocket pubsub (X06) â"€â"€â"€â"€â"€â"€â"
582
  try:
583
  from hearthnet.events.sync import SyncServer
584
  from hearthnet.transport.server import HttpServer
 
603
  except Exception as exc:
604
  _log.warning("HTTP server start failed (non-fatal): %s", exc)
605
 
606
+ # â"€â"€ Gossip sync loop (X02) â"€â"€â"€â"€â"€â"€â"€â"€â"€â"€â"€â"€â"€â"€â"€â"€â"€â"€â"€â"€â"€â"€â"€â"€â"€â"€â"€â"€â"€â"€â"€â"€â"€â"€â"€â"
607
  if self._event_log is not None:
608
  self._gossip_task = asyncio.create_task(
609
  self._gossip_loop(gossip_interval), name="gossip-sync"
 
827
 
828
 
829
  # ---------------------------------------------------------------------------
830
+ # PeriodicTask -- generic async interval runner (M12 §5)
831
  # ---------------------------------------------------------------------------
832
 
833
 
 
856
 
857
 
858
  # ---------------------------------------------------------------------------
859
+ # ManifestPublisher -- republishes node manifest to mDNS + UDP (M12 §5)
860
  # ---------------------------------------------------------------------------
861
 
862
  _MANIFEST_REPUBLISH_INTERVAL_SECONDS = 300 # 5 minutes default