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.
- {meshcode-2.10.65 → meshcode-2.10.66}/PKG-INFO +1 -1
- {meshcode-2.10.65 → meshcode-2.10.66}/meshcode/__init__.py +1 -1
- {meshcode-2.10.65 → meshcode-2.10.66}/meshcode/comms_v4.py +69 -8
- {meshcode-2.10.65 → meshcode-2.10.66}/meshcode.egg-info/PKG-INFO +1 -1
- {meshcode-2.10.65 → meshcode-2.10.66}/pyproject.toml +1 -1
- {meshcode-2.10.65 → meshcode-2.10.66}/README.md +0 -0
- {meshcode-2.10.65 → meshcode-2.10.66}/meshcode/ascii_art.py +0 -0
- {meshcode-2.10.65 → meshcode-2.10.66}/meshcode/cli.py +0 -0
- {meshcode-2.10.65 → meshcode-2.10.66}/meshcode/compat.py +0 -0
- {meshcode-2.10.65 → meshcode-2.10.66}/meshcode/error_hints.py +0 -0
- {meshcode-2.10.65 → meshcode-2.10.66}/meshcode/exceptions.py +0 -0
- {meshcode-2.10.65 → meshcode-2.10.66}/meshcode/invites.py +0 -0
- {meshcode-2.10.65 → meshcode-2.10.66}/meshcode/launcher.py +0 -0
- {meshcode-2.10.65 → meshcode-2.10.66}/meshcode/launcher_install.py +0 -0
- {meshcode-2.10.65 → meshcode-2.10.66}/meshcode/meshcode_mcp/__init__.py +0 -0
- {meshcode-2.10.65 → meshcode-2.10.66}/meshcode/meshcode_mcp/__main__.py +0 -0
- {meshcode-2.10.65 → meshcode-2.10.66}/meshcode/meshcode_mcp/backend.py +0 -0
- {meshcode-2.10.65 → meshcode-2.10.66}/meshcode/meshcode_mcp/realtime.py +0 -0
- {meshcode-2.10.65 → meshcode-2.10.66}/meshcode/meshcode_mcp/server.py +0 -0
- {meshcode-2.10.65 → meshcode-2.10.66}/meshcode/meshcode_mcp/test_backend.py +0 -0
- {meshcode-2.10.65 → meshcode-2.10.66}/meshcode/meshcode_mcp/test_realtime.py +0 -0
- {meshcode-2.10.65 → meshcode-2.10.66}/meshcode/meshcode_mcp/test_server_wrapper.py +0 -0
- {meshcode-2.10.65 → meshcode-2.10.66}/meshcode/preferences.py +0 -0
- {meshcode-2.10.65 → meshcode-2.10.66}/meshcode/protocol_v2.py +0 -0
- {meshcode-2.10.65 → meshcode-2.10.66}/meshcode/quickstart.py +0 -0
- {meshcode-2.10.65 → meshcode-2.10.66}/meshcode/run_agent.py +0 -0
- {meshcode-2.10.65 → meshcode-2.10.66}/meshcode/secrets.py +0 -0
- {meshcode-2.10.65 → meshcode-2.10.66}/meshcode/self_update.py +0 -0
- {meshcode-2.10.65 → meshcode-2.10.66}/meshcode/setup_clients.py +0 -0
- {meshcode-2.10.65 → meshcode-2.10.66}/meshcode/supervisor.py +0 -0
- {meshcode-2.10.65 → meshcode-2.10.66}/meshcode/upload.py +0 -0
- {meshcode-2.10.65 → meshcode-2.10.66}/meshcode.egg-info/SOURCES.txt +0 -0
- {meshcode-2.10.65 → meshcode-2.10.66}/meshcode.egg-info/dependency_links.txt +0 -0
- {meshcode-2.10.65 → meshcode-2.10.66}/meshcode.egg-info/entry_points.txt +0 -0
- {meshcode-2.10.65 → meshcode-2.10.66}/meshcode.egg-info/requires.txt +0 -0
- {meshcode-2.10.65 → meshcode-2.10.66}/meshcode.egg-info/top_level.txt +0 -0
- {meshcode-2.10.65 → meshcode-2.10.66}/setup.cfg +0 -0
- {meshcode-2.10.65 → meshcode-2.10.66}/tests/test_core.py +0 -0
- {meshcode-2.10.65 → meshcode-2.10.66}/tests/test_cross_agent_messaging.py +0 -0
- {meshcode-2.10.65 → meshcode-2.10.66}/tests/test_esc_deaf_state.py +0 -0
- {meshcode-2.10.65 → meshcode-2.10.66}/tests/test_exceptions.py +0 -0
- {meshcode-2.10.65 → meshcode-2.10.66}/tests/test_mark_read_batch.py +0 -0
- {meshcode-2.10.65 → meshcode-2.10.66}/tests/test_migration_integrity.py +0 -0
- {meshcode-2.10.65 → meshcode-2.10.66}/tests/test_realtime_event_freshness.py +0 -0
- {meshcode-2.10.65 → meshcode-2.10.66}/tests/test_rls_cross_tenant.py +0 -0
- {meshcode-2.10.65 → meshcode-2.10.66}/tests/test_rpc_migrations.py +0 -0
- {meshcode-2.10.65 → meshcode-2.10.66}/tests/test_security_regressions.py +0 -0
- {meshcode-2.10.65 → meshcode-2.10.66}/tests/test_sentinel.py +0 -0
- {meshcode-2.10.65 → meshcode-2.10.66}/tests/test_status_enum_coverage.py +0 -0
|
@@ -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"[
|
|
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("
|
|
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("
|
|
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(
|
|
1473
|
-
|
|
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
|
-
|
|
3000
|
-
|
|
3001
|
-
|
|
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("/"):
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|