meshcode 2.10.64__tar.gz → 2.10.66__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 (49) hide show
  1. {meshcode-2.10.64 → meshcode-2.10.66}/PKG-INFO +1 -1
  2. {meshcode-2.10.64 → meshcode-2.10.66}/meshcode/__init__.py +1 -1
  3. {meshcode-2.10.64 → meshcode-2.10.66}/meshcode/comms_v4.py +109 -11
  4. {meshcode-2.10.64 → meshcode-2.10.66}/meshcode.egg-info/PKG-INFO +1 -1
  5. {meshcode-2.10.64 → meshcode-2.10.66}/pyproject.toml +1 -1
  6. {meshcode-2.10.64 → meshcode-2.10.66}/README.md +0 -0
  7. {meshcode-2.10.64 → meshcode-2.10.66}/meshcode/ascii_art.py +0 -0
  8. {meshcode-2.10.64 → meshcode-2.10.66}/meshcode/cli.py +0 -0
  9. {meshcode-2.10.64 → meshcode-2.10.66}/meshcode/compat.py +0 -0
  10. {meshcode-2.10.64 → meshcode-2.10.66}/meshcode/error_hints.py +0 -0
  11. {meshcode-2.10.64 → meshcode-2.10.66}/meshcode/exceptions.py +0 -0
  12. {meshcode-2.10.64 → meshcode-2.10.66}/meshcode/invites.py +0 -0
  13. {meshcode-2.10.64 → meshcode-2.10.66}/meshcode/launcher.py +0 -0
  14. {meshcode-2.10.64 → meshcode-2.10.66}/meshcode/launcher_install.py +0 -0
  15. {meshcode-2.10.64 → meshcode-2.10.66}/meshcode/meshcode_mcp/__init__.py +0 -0
  16. {meshcode-2.10.64 → meshcode-2.10.66}/meshcode/meshcode_mcp/__main__.py +0 -0
  17. {meshcode-2.10.64 → meshcode-2.10.66}/meshcode/meshcode_mcp/backend.py +0 -0
  18. {meshcode-2.10.64 → meshcode-2.10.66}/meshcode/meshcode_mcp/realtime.py +0 -0
  19. {meshcode-2.10.64 → meshcode-2.10.66}/meshcode/meshcode_mcp/server.py +0 -0
  20. {meshcode-2.10.64 → meshcode-2.10.66}/meshcode/meshcode_mcp/test_backend.py +0 -0
  21. {meshcode-2.10.64 → meshcode-2.10.66}/meshcode/meshcode_mcp/test_realtime.py +0 -0
  22. {meshcode-2.10.64 → meshcode-2.10.66}/meshcode/meshcode_mcp/test_server_wrapper.py +0 -0
  23. {meshcode-2.10.64 → meshcode-2.10.66}/meshcode/preferences.py +0 -0
  24. {meshcode-2.10.64 → meshcode-2.10.66}/meshcode/protocol_v2.py +0 -0
  25. {meshcode-2.10.64 → meshcode-2.10.66}/meshcode/quickstart.py +0 -0
  26. {meshcode-2.10.64 → meshcode-2.10.66}/meshcode/run_agent.py +0 -0
  27. {meshcode-2.10.64 → meshcode-2.10.66}/meshcode/secrets.py +0 -0
  28. {meshcode-2.10.64 → meshcode-2.10.66}/meshcode/self_update.py +0 -0
  29. {meshcode-2.10.64 → meshcode-2.10.66}/meshcode/setup_clients.py +0 -0
  30. {meshcode-2.10.64 → meshcode-2.10.66}/meshcode/supervisor.py +0 -0
  31. {meshcode-2.10.64 → meshcode-2.10.66}/meshcode/upload.py +0 -0
  32. {meshcode-2.10.64 → meshcode-2.10.66}/meshcode.egg-info/SOURCES.txt +0 -0
  33. {meshcode-2.10.64 → meshcode-2.10.66}/meshcode.egg-info/dependency_links.txt +0 -0
  34. {meshcode-2.10.64 → meshcode-2.10.66}/meshcode.egg-info/entry_points.txt +0 -0
  35. {meshcode-2.10.64 → meshcode-2.10.66}/meshcode.egg-info/requires.txt +0 -0
  36. {meshcode-2.10.64 → meshcode-2.10.66}/meshcode.egg-info/top_level.txt +0 -0
  37. {meshcode-2.10.64 → meshcode-2.10.66}/setup.cfg +0 -0
  38. {meshcode-2.10.64 → meshcode-2.10.66}/tests/test_core.py +0 -0
  39. {meshcode-2.10.64 → meshcode-2.10.66}/tests/test_cross_agent_messaging.py +0 -0
  40. {meshcode-2.10.64 → meshcode-2.10.66}/tests/test_esc_deaf_state.py +0 -0
  41. {meshcode-2.10.64 → meshcode-2.10.66}/tests/test_exceptions.py +0 -0
  42. {meshcode-2.10.64 → meshcode-2.10.66}/tests/test_mark_read_batch.py +0 -0
  43. {meshcode-2.10.64 → meshcode-2.10.66}/tests/test_migration_integrity.py +0 -0
  44. {meshcode-2.10.64 → meshcode-2.10.66}/tests/test_realtime_event_freshness.py +0 -0
  45. {meshcode-2.10.64 → meshcode-2.10.66}/tests/test_rls_cross_tenant.py +0 -0
  46. {meshcode-2.10.64 → meshcode-2.10.66}/tests/test_rpc_migrations.py +0 -0
  47. {meshcode-2.10.64 → meshcode-2.10.66}/tests/test_security_regressions.py +0 -0
  48. {meshcode-2.10.64 → meshcode-2.10.66}/tests/test_sentinel.py +0 -0
  49. {meshcode-2.10.64 → meshcode-2.10.66}/tests/test_status_enum_coverage.py +0 -0
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.4
2
2
  Name: meshcode
3
- Version: 2.10.64
3
+ Version: 2.10.66
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,5 +1,5 @@
1
1
  """MeshCode — Real-time communication between AI agents."""
2
- __version__ = "2.10.64"
2
+ __version__ = "2.10.66"
3
3
 
4
4
  # Exception hierarchy — eagerly imported (lightweight, no deps)
5
5
  from meshcode.exceptions import ( # noqa: F401
@@ -1171,7 +1171,8 @@ def send_msg(project, from_agent, to_agent, content, msg_type="msg", compact=Fal
1171
1171
  if agents and agents[0].get("status") not in ("offline", "killed"):
1172
1172
  nudge_agent(project, to_agent, from_agent)
1173
1173
  else:
1174
- print(f"[{project}] ERROR: no se pudo enviar mensaje")
1174
+ print(f"[meshcode] ERROR: Could not send message to {project}")
1175
+ print(f"[meshcode] Fix: Check project name with: meshcode projects")
1175
1176
 
1176
1177
 
1177
1178
  def broadcast(project, from_agent, content, msg_type="broadcast"):
@@ -1200,7 +1201,7 @@ def read_messages(project, name, silent=False, send_acks=True):
1200
1201
  project_id = get_project_id(project)
1201
1202
  if not project_id:
1202
1203
  if not silent:
1203
- print("[EMPTY]")
1204
+ print("No new messages.")
1204
1205
  return []
1205
1206
 
1206
1207
  # Get unread messages
@@ -1210,7 +1211,7 @@ def read_messages(project, name, silent=False, send_acks=True):
1210
1211
 
1211
1212
  if not messages:
1212
1213
  if not silent:
1213
- print("[EMPTY]")
1214
+ print("No new messages.")
1214
1215
  return []
1215
1216
 
1216
1217
  # Mark all as read
@@ -1463,12 +1464,60 @@ def show_board(project):
1463
1464
  print(f"[{project}] No agents found")
1464
1465
  return
1465
1466
 
1467
+ def _human_time(ts_str):
1468
+ """Convert ISO timestamp to human-readable age."""
1469
+ if not ts_str:
1470
+ return ""
1471
+ try:
1472
+ from datetime import datetime, timezone
1473
+ dt = datetime.fromisoformat(ts_str.replace("Z", "+00:00"))
1474
+ age = (datetime.now(timezone.utc) - dt).total_seconds()
1475
+ if age < 60: return f"{int(age)}s ago"
1476
+ if age < 3600: return f"{int(age/60)}m ago"
1477
+ if age < 86400: return f"{int(age/3600)}h ago"
1478
+ return f"{int(age/86400)}d ago"
1479
+ except Exception:
1480
+ return ""
1481
+
1466
1482
  print(f"\n{'='*60}")
1467
1483
  print(f" {project.upper()} — Board")
1468
1484
  print(f"{'='*60}")
1469
1485
  for a in agents:
1470
- icon = {"online": "●", "working": "▶", "blocked": "■", "standby": "◆", "idle": "○", "done": "✓"}.get(a.get("status", ""), "?")
1471
- print(f" {icon} {a['name']:<14} {a.get('status','?'):<10} {a.get('task','')}")
1486
+ status = a.get("status", "?")
1487
+ icon = {"online": "●", "working": "▶", "blocked": "■", "standby": "◆",
1488
+ "idle": "○", "done": "✓", "sleeping": "☾", "offline": "✗",
1489
+ "waiting": "◎"}.get(status, "?")
1490
+ task = a.get("task", "")
1491
+ # Clean up noisy task text
1492
+ if task and "idle" in task.lower() and "s —" in task:
1493
+ task = "" # hide "idle 29720s — still listening"
1494
+ hb_age = _human_time(a.get("last_heartbeat"))
1495
+ hb_info = f" ({hb_age})" if hb_age and status in ("offline", "sleeping") else ""
1496
+ print(f" {icon} {a['name']:<14} {status:<10} {task[:40]}{hb_info}")
1497
+
1498
+ # Enhanced: show health + tasks + activity from dashboard summary
1499
+ if _ak:
1500
+ try:
1501
+ summary = sb_rpc("mc_get_dashboard_summary", {"p_api_key": _ak})
1502
+ if isinstance(summary, dict) and summary.get("ok"):
1503
+ h = summary.get("health", {})
1504
+ print(f"\n{'-'*60}")
1505
+ print(f" Health: {h.get('active_agents',0)}/{h.get('total_agents',0)} agents active"
1506
+ f" | {h.get('open_tasks',0)} open tasks"
1507
+ f" | {h.get('messages_today',0)} messages today")
1508
+ tasks = summary.get("tasks", [])
1509
+ if tasks:
1510
+ print(f"\n Open tasks:")
1511
+ for t in tasks[:5]:
1512
+ prio_icon = {"urgent": "!!", "high": "!", "normal": " ", "low": "."}.get(t.get("priority", ""), " ")
1513
+ print(f" [{prio_icon}] {t.get('title','')[:50]} ({t.get('assignee','?')})")
1514
+ activity = summary.get("activity", [])
1515
+ if activity:
1516
+ print(f"\n Recent activity:")
1517
+ for e in activity[:5]:
1518
+ print(f" {e.get('agent','?')}: {e.get('summary','')[:50]}")
1519
+ except Exception:
1520
+ pass
1472
1521
  print()
1473
1522
 
1474
1523
 
@@ -2040,11 +2089,11 @@ def cmd_doctor(flags, pos):
2040
2089
  else:
2041
2090
  fail("API key", "not found. Run: meshcode login <api_key>")
2042
2091
 
2043
- # 4c. MCP server import test
2092
+ # 4c. MCP server import test (lightweight — only test backend, not full server)
2044
2093
  try:
2045
2094
  import importlib
2046
- _mod = importlib.import_module("meshcode.meshcode_mcp.server")
2047
- ok("MCP server", "module imports cleanly")
2095
+ _mod = importlib.import_module("meshcode.meshcode_mcp.backend")
2096
+ ok("MCP server", "core module imports cleanly")
2048
2097
  except Exception as e:
2049
2098
  fail("MCP server", f"import error: {e}. Run: pip install --upgrade meshcode")
2050
2099
 
@@ -2576,6 +2625,17 @@ if __name__ == "__main__":
2576
2625
  pass
2577
2626
 
2578
2627
  if len(sys.argv) < 2:
2628
+ # First-run detection: no credentials = new user
2629
+ _config = Path.home() / ".meshcode"
2630
+ _has_creds = (_config / "profile_meta.json").exists() if _config.exists() else False
2631
+ if not _has_creds:
2632
+ print()
2633
+ print(" Welcome to MeshCode!")
2634
+ print(" First time? Run: meshcode quickstart")
2635
+ print(" Already have an API key? Run: meshcode login <api_key>")
2636
+ print(" Need help? Run: meshcode doctor")
2637
+ print()
2638
+ sys.exit(0)
2579
2639
  show_help()
2580
2640
  sys.exit(0)
2581
2641
 
@@ -2959,9 +3019,47 @@ if __name__ == "__main__":
2959
3019
  # name exists in multiple meshworks
2960
3020
  # meshcode run <agent> (backwards compat, same as go)
2961
3021
  if len(sys.argv) < 3:
2962
- print(f"Usage: meshcode {cmd} <agent> [--project <name>] [--editor claude|cursor|code]")
2963
- print(f" or: meshcode {cmd} <project>/<agent> (disambiguation)")
2964
- sys.exit(1)
3022
+ # Interactive agent selection
3023
+ _ak = _load_api_key_for_cli()
3024
+ if _ak:
3025
+ try:
3026
+ _projs = sb_rpc("mc_list_user_projects", {"p_api_key": _ak})
3027
+ _agents_list = []
3028
+ if isinstance(_projs, dict) and _projs.get("projects"):
3029
+ for _p in _projs["projects"]:
3030
+ for _a in (_p.get("agents") or []):
3031
+ _agents_list.append((_p["name"], _a.get("name", "?")))
3032
+ if _agents_list:
3033
+ print(f"\n Your agents:")
3034
+ for i, (pn, an) in enumerate(_agents_list, 1):
3035
+ print(f" {i}. {pn}/{an}")
3036
+ print()
3037
+ choice = input(" Which agent? (number or name): ").strip()
3038
+ if choice.isdigit() and 1 <= int(choice) <= len(_agents_list):
3039
+ pn, an = _agents_list[int(choice) - 1]
3040
+ sys.argv = [sys.argv[0], cmd, f"{pn}/{an}"] + sys.argv[2:]
3041
+ elif "/" in choice:
3042
+ sys.argv = [sys.argv[0], cmd, choice] + sys.argv[2:]
3043
+ else:
3044
+ # Try to find by name
3045
+ matches = [(pn, an) for pn, an in _agents_list if an == choice]
3046
+ if matches:
3047
+ pn, an = matches[0]
3048
+ sys.argv = [sys.argv[0], cmd, f"{pn}/{an}"] + sys.argv[2:]
3049
+ else:
3050
+ print(f" Agent '{choice}' not found.")
3051
+ sys.exit(1)
3052
+ else:
3053
+ print(f" No agents found. Run: meshcode quickstart")
3054
+ sys.exit(1)
3055
+ except Exception:
3056
+ print(f"Usage: meshcode {cmd} <agent> [--project <name>]")
3057
+ sys.exit(1)
3058
+ else:
3059
+ print(f"Usage: meshcode {cmd} <agent> [--project <name>] [--editor claude|cursor|code]")
3060
+ print(f" or: meshcode {cmd} <project>/<agent> (disambiguation)")
3061
+ print(f"\n Not logged in? Run: meshcode quickstart")
3062
+ sys.exit(1)
2965
3063
  agent_arg = sys.argv[2]
2966
3064
  # Parse project/agent syntax
2967
3065
  if "/" in agent_arg and not agent_arg.startswith("/"):
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.4
2
2
  Name: meshcode
3
- Version: 2.10.64
3
+ Version: 2.10.66
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.10.64"
7
+ version = "2.10.66"
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