meshcode 2.0.3__tar.gz → 2.0.4__tar.gz

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.
Files changed (29) hide show
  1. {meshcode-2.0.3 → meshcode-2.0.4}/PKG-INFO +1 -1
  2. {meshcode-2.0.3 → meshcode-2.0.4}/meshcode/__init__.py +1 -1
  3. {meshcode-2.0.3 → meshcode-2.0.4}/meshcode/meshcode_mcp/server.py +67 -4
  4. {meshcode-2.0.3 → meshcode-2.0.4}/meshcode.egg-info/PKG-INFO +1 -1
  5. {meshcode-2.0.3 → meshcode-2.0.4}/pyproject.toml +1 -1
  6. {meshcode-2.0.3 → meshcode-2.0.4}/README.md +0 -0
  7. {meshcode-2.0.3 → meshcode-2.0.4}/meshcode/cli.py +0 -0
  8. {meshcode-2.0.3 → meshcode-2.0.4}/meshcode/comms_v4.py +0 -0
  9. {meshcode-2.0.3 → meshcode-2.0.4}/meshcode/invites.py +0 -0
  10. {meshcode-2.0.3 → meshcode-2.0.4}/meshcode/launcher.py +0 -0
  11. {meshcode-2.0.3 → meshcode-2.0.4}/meshcode/launcher_install.py +0 -0
  12. {meshcode-2.0.3 → meshcode-2.0.4}/meshcode/meshcode_mcp/__init__.py +0 -0
  13. {meshcode-2.0.3 → meshcode-2.0.4}/meshcode/meshcode_mcp/__main__.py +0 -0
  14. {meshcode-2.0.3 → meshcode-2.0.4}/meshcode/meshcode_mcp/backend.py +0 -0
  15. {meshcode-2.0.3 → meshcode-2.0.4}/meshcode/meshcode_mcp/realtime.py +0 -0
  16. {meshcode-2.0.3 → meshcode-2.0.4}/meshcode/meshcode_mcp/test_backend.py +0 -0
  17. {meshcode-2.0.3 → meshcode-2.0.4}/meshcode/meshcode_mcp/test_realtime.py +0 -0
  18. {meshcode-2.0.3 → meshcode-2.0.4}/meshcode/preferences.py +0 -0
  19. {meshcode-2.0.3 → meshcode-2.0.4}/meshcode/protocol_v2.py +0 -0
  20. {meshcode-2.0.3 → meshcode-2.0.4}/meshcode/run_agent.py +0 -0
  21. {meshcode-2.0.3 → meshcode-2.0.4}/meshcode/secrets.py +0 -0
  22. {meshcode-2.0.3 → meshcode-2.0.4}/meshcode/self_update.py +0 -0
  23. {meshcode-2.0.3 → meshcode-2.0.4}/meshcode/setup_clients.py +0 -0
  24. {meshcode-2.0.3 → meshcode-2.0.4}/meshcode.egg-info/SOURCES.txt +0 -0
  25. {meshcode-2.0.3 → meshcode-2.0.4}/meshcode.egg-info/dependency_links.txt +0 -0
  26. {meshcode-2.0.3 → meshcode-2.0.4}/meshcode.egg-info/entry_points.txt +0 -0
  27. {meshcode-2.0.3 → meshcode-2.0.4}/meshcode.egg-info/requires.txt +0 -0
  28. {meshcode-2.0.3 → meshcode-2.0.4}/meshcode.egg-info/top_level.txt +0 -0
  29. {meshcode-2.0.3 → meshcode-2.0.4}/setup.cfg +0 -0
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.4
2
2
  Name: meshcode
3
- Version: 2.0.3
3
+ Version: 2.0.4
4
4
  Summary: Real-time communication between AI agents — Supabase-backed CLI
5
5
  Author-email: MeshCode <hello@meshcode.io>
6
6
  License: MIT
@@ -1,2 +1,2 @@
1
1
  """MeshCode — Real-time communication between AI agents."""
2
- __version__ = "2.0.3"
2
+ __version__ = "2.0.4"
@@ -145,6 +145,35 @@ def _split_messages(messages: List[Dict[str, Any]]) -> Dict[str, Any]:
145
145
  from . import backend as be
146
146
  from .realtime import RealtimeListener
147
147
 
148
+ # ============================================================
149
+ # Hot-reload: detect when backend.py changes on disk (e.g. after
150
+ # pip install --upgrade meshcode) and reload without restart.
151
+ # Only backend.py is safe to reload (stateless). server.py has
152
+ # module-level state that would be destroyed by reload.
153
+ # ============================================================
154
+ import importlib as _importlib
155
+ _be_mtime: float = 0.0
156
+ try:
157
+ _be_path = os.path.abspath(be.__file__)
158
+ _be_mtime = os.path.getmtime(_be_path)
159
+ except Exception:
160
+ _be_path = ""
161
+
162
+
163
+ def _check_hot_reload() -> None:
164
+ """If backend.py was modified since boot/last reload, reimport it."""
165
+ global _be_mtime, be
166
+ if not _be_path:
167
+ return
168
+ try:
169
+ current_mtime = os.path.getmtime(_be_path)
170
+ if current_mtime > _be_mtime:
171
+ _be_mtime = current_mtime
172
+ _importlib.reload(be)
173
+ log.info("[meshcode] Hot-reloaded backend.py (new version detected)")
174
+ except Exception as e:
175
+ log.debug(f"hot-reload check failed: {e}")
176
+
148
177
  try:
149
178
  from mcp.server.fastmcp import FastMCP
150
179
  except ImportError:
@@ -317,6 +346,7 @@ def with_working_status(func):
317
346
  if asyncio.iscoroutinefunction(func):
318
347
  @_functools.wraps(func)
319
348
  async def awrapper(*args, **kwargs):
349
+ _check_hot_reload()
320
350
  if not skip:
321
351
  _schedule_flip("working", name)
322
352
  try:
@@ -328,6 +358,7 @@ def with_working_status(func):
328
358
  else:
329
359
  @_functools.wraps(func)
330
360
  def swrapper(*args, **kwargs):
361
+ _check_hot_reload()
331
362
  if not skip:
332
363
  _schedule_flip("working", name)
333
364
  try:
@@ -574,7 +605,10 @@ async def _on_new_message(msg: Dict[str, Any]) -> None:
574
605
  from_agent = msg.get("from") or msg.get("from_agent") or "unknown"
575
606
  payload = msg.get("payload") or {}
576
607
  preview = payload.get("text", "") if isinstance(payload, dict) else str(payload)
577
- _try_auto_wake(from_agent, preview[:60])
608
+ try:
609
+ _try_auto_wake(from_agent, preview[:60])
610
+ except Exception:
611
+ pass # auto-wake is best-effort, never block message handling
578
612
 
579
613
  try:
580
614
  srv = mcp._mcp_server # FastMCP exposes the lowlevel server here
@@ -852,7 +886,20 @@ async def _meshcode_wait_inner(actual_timeout: int, include_acks: bool) -> Dict[
852
886
  # Realtime unavailable — plain sleep fallback so we still honor timeout.
853
887
  await asyncio.sleep(actual_timeout)
854
888
 
855
- return {"timed_out": True}
889
+ # On timeout, check for unclaimed tasks assigned to this agent
890
+ timeout_result: Dict[str, Any] = {"timed_out": True}
891
+ try:
892
+ api_key = _get_api_key()
893
+ open_tasks = be.task_list(api_key, _PROJECT_ID, AGENT_NAME, status_filter="open")
894
+ if isinstance(open_tasks, dict) and open_tasks.get("ok"):
895
+ my_tasks = [t for t in open_tasks.get("tasks", [])
896
+ if t.get("assignee") == AGENT_NAME and not t.get("claimed_by")]
897
+ if my_tasks:
898
+ timeout_result["unclaimed_tasks"] = len(my_tasks)
899
+ timeout_result["hint"] = f"You have {len(my_tasks)} unclaimed task(s) assigned to you. Run meshcode_tasks(status_filter='open') to see them."
900
+ except Exception:
901
+ pass
902
+ return timeout_result
856
903
 
857
904
 
858
905
  @mcp.tool()
@@ -995,9 +1042,22 @@ def meshcode_task_create(title: str, description: str = "", assignee: str = "*",
995
1042
  Returns: {"ok": true, "task_id": "...", "title": "..."}
996
1043
  """
997
1044
  api_key = _get_api_key()
998
- return be.task_create(api_key, _PROJECT_ID, AGENT_NAME, title,
1045
+ result = be.task_create(api_key, _PROJECT_ID, AGENT_NAME, title,
999
1046
  description=description, assignee=assignee,
1000
1047
  priority=priority, parent_task_id=parent_task_id)
1048
+ # Auto-notify assignee so they wake from meshcode_wait
1049
+ if isinstance(result, dict) and result.get("ok") and assignee and assignee != "*" and assignee != AGENT_NAME:
1050
+ try:
1051
+ be.send_message(_PROJECT_ID, AGENT_NAME, assignee, {
1052
+ "type": "task_assigned",
1053
+ "task_id": result.get("task_id", ""),
1054
+ "title": title,
1055
+ "priority": priority,
1056
+ "text": f"New {priority} task assigned to you: {title}",
1057
+ }, msg_type="system")
1058
+ except Exception:
1059
+ pass # best-effort notification
1060
+ return result
1001
1061
 
1002
1062
 
1003
1063
  @mcp.tool()
@@ -1338,7 +1398,10 @@ def meshcode_remember(key: str, value: Any) -> Dict[str, Any]:
1338
1398
  })
1339
1399
  # Best-effort sync to Obsidian vault (if configured)
1340
1400
  if isinstance(result, dict) and result.get("ok"):
1341
- _sync_to_obsidian(key, json_value)
1401
+ try:
1402
+ _sync_to_obsidian(key, json_value)
1403
+ except Exception:
1404
+ pass # Obsidian sync is best-effort, never block memory writes
1342
1405
  return result
1343
1406
 
1344
1407
 
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.4
2
2
  Name: meshcode
3
- Version: 2.0.3
3
+ Version: 2.0.4
4
4
  Summary: Real-time communication between AI agents — Supabase-backed CLI
5
5
  Author-email: MeshCode <hello@meshcode.io>
6
6
  License: MIT
@@ -4,7 +4,7 @@ build-backend = "setuptools.build_meta"
4
4
 
5
5
  [project]
6
6
  name = "meshcode"
7
- version = "2.0.3"
7
+ version = "2.0.4"
8
8
  description = "Real-time communication between AI agents — Supabase-backed CLI"
9
9
  readme = "README.md"
10
10
  license = {text = "MIT"}
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes