meshcode 2.10.65__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.65 → meshcode-2.10.66}/PKG-INFO +1 -1
  2. {meshcode-2.10.65 → meshcode-2.10.66}/meshcode/__init__.py +1 -1
  3. {meshcode-2.10.65 → meshcode-2.10.66}/meshcode/comms_v4.py +69 -8
  4. {meshcode-2.10.65 → meshcode-2.10.66}/meshcode.egg-info/PKG-INFO +1 -1
  5. {meshcode-2.10.65 → meshcode-2.10.66}/pyproject.toml +1 -1
  6. {meshcode-2.10.65 → meshcode-2.10.66}/README.md +0 -0
  7. {meshcode-2.10.65 → meshcode-2.10.66}/meshcode/ascii_art.py +0 -0
  8. {meshcode-2.10.65 → meshcode-2.10.66}/meshcode/cli.py +0 -0
  9. {meshcode-2.10.65 → meshcode-2.10.66}/meshcode/compat.py +0 -0
  10. {meshcode-2.10.65 → meshcode-2.10.66}/meshcode/error_hints.py +0 -0
  11. {meshcode-2.10.65 → meshcode-2.10.66}/meshcode/exceptions.py +0 -0
  12. {meshcode-2.10.65 → meshcode-2.10.66}/meshcode/invites.py +0 -0
  13. {meshcode-2.10.65 → meshcode-2.10.66}/meshcode/launcher.py +0 -0
  14. {meshcode-2.10.65 → meshcode-2.10.66}/meshcode/launcher_install.py +0 -0
  15. {meshcode-2.10.65 → meshcode-2.10.66}/meshcode/meshcode_mcp/__init__.py +0 -0
  16. {meshcode-2.10.65 → meshcode-2.10.66}/meshcode/meshcode_mcp/__main__.py +0 -0
  17. {meshcode-2.10.65 → meshcode-2.10.66}/meshcode/meshcode_mcp/backend.py +0 -0
  18. {meshcode-2.10.65 → meshcode-2.10.66}/meshcode/meshcode_mcp/realtime.py +0 -0
  19. {meshcode-2.10.65 → meshcode-2.10.66}/meshcode/meshcode_mcp/server.py +0 -0
  20. {meshcode-2.10.65 → meshcode-2.10.66}/meshcode/meshcode_mcp/test_backend.py +0 -0
  21. {meshcode-2.10.65 → meshcode-2.10.66}/meshcode/meshcode_mcp/test_realtime.py +0 -0
  22. {meshcode-2.10.65 → meshcode-2.10.66}/meshcode/meshcode_mcp/test_server_wrapper.py +0 -0
  23. {meshcode-2.10.65 → meshcode-2.10.66}/meshcode/preferences.py +0 -0
  24. {meshcode-2.10.65 → meshcode-2.10.66}/meshcode/protocol_v2.py +0 -0
  25. {meshcode-2.10.65 → meshcode-2.10.66}/meshcode/quickstart.py +0 -0
  26. {meshcode-2.10.65 → meshcode-2.10.66}/meshcode/run_agent.py +0 -0
  27. {meshcode-2.10.65 → meshcode-2.10.66}/meshcode/secrets.py +0 -0
  28. {meshcode-2.10.65 → meshcode-2.10.66}/meshcode/self_update.py +0 -0
  29. {meshcode-2.10.65 → meshcode-2.10.66}/meshcode/setup_clients.py +0 -0
  30. {meshcode-2.10.65 → meshcode-2.10.66}/meshcode/supervisor.py +0 -0
  31. {meshcode-2.10.65 → meshcode-2.10.66}/meshcode/upload.py +0 -0
  32. {meshcode-2.10.65 → meshcode-2.10.66}/meshcode.egg-info/SOURCES.txt +0 -0
  33. {meshcode-2.10.65 → meshcode-2.10.66}/meshcode.egg-info/dependency_links.txt +0 -0
  34. {meshcode-2.10.65 → meshcode-2.10.66}/meshcode.egg-info/entry_points.txt +0 -0
  35. {meshcode-2.10.65 → meshcode-2.10.66}/meshcode.egg-info/requires.txt +0 -0
  36. {meshcode-2.10.65 → meshcode-2.10.66}/meshcode.egg-info/top_level.txt +0 -0
  37. {meshcode-2.10.65 → meshcode-2.10.66}/setup.cfg +0 -0
  38. {meshcode-2.10.65 → meshcode-2.10.66}/tests/test_core.py +0 -0
  39. {meshcode-2.10.65 → meshcode-2.10.66}/tests/test_cross_agent_messaging.py +0 -0
  40. {meshcode-2.10.65 → meshcode-2.10.66}/tests/test_esc_deaf_state.py +0 -0
  41. {meshcode-2.10.65 → meshcode-2.10.66}/tests/test_exceptions.py +0 -0
  42. {meshcode-2.10.65 → meshcode-2.10.66}/tests/test_mark_read_batch.py +0 -0
  43. {meshcode-2.10.65 → meshcode-2.10.66}/tests/test_migration_integrity.py +0 -0
  44. {meshcode-2.10.65 → meshcode-2.10.66}/tests/test_realtime_event_freshness.py +0 -0
  45. {meshcode-2.10.65 → meshcode-2.10.66}/tests/test_rls_cross_tenant.py +0 -0
  46. {meshcode-2.10.65 → meshcode-2.10.66}/tests/test_rpc_migrations.py +0 -0
  47. {meshcode-2.10.65 → meshcode-2.10.66}/tests/test_security_regressions.py +0 -0
  48. {meshcode-2.10.65 → meshcode-2.10.66}/tests/test_sentinel.py +0 -0
  49. {meshcode-2.10.65 → 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.65
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.65"
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,14 +1464,36 @@ 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:
1486
+ status = a.get("status", "?")
1470
1487
  icon = {"online": "●", "working": "▶", "blocked": "■", "standby": "◆",
1471
1488
  "idle": "○", "done": "✓", "sleeping": "☾", "offline": "✗",
1472
- "waiting": "◎"}.get(a.get("status", ""), "?")
1473
- print(f" {icon} {a['name']:<14} {a.get('status','?'):<10} {a.get('task','')}")
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}")
1474
1497
 
1475
1498
  # Enhanced: show health + tasks + activity from dashboard summary
1476
1499
  if _ak:
@@ -2996,9 +3019,47 @@ if __name__ == "__main__":
2996
3019
  # name exists in multiple meshworks
2997
3020
  # meshcode run <agent> (backwards compat, same as go)
2998
3021
  if len(sys.argv) < 3:
2999
- print(f"Usage: meshcode {cmd} <agent> [--project <name>] [--editor claude|cursor|code]")
3000
- print(f" or: meshcode {cmd} <project>/<agent> (disambiguation)")
3001
- 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)
3002
3063
  agent_arg = sys.argv[2]
3003
3064
  # Parse project/agent syntax
3004
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.65
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.65"
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