meshcode 2.10.62__tar.gz → 2.10.64__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.62 → meshcode-2.10.64}/PKG-INFO +1 -1
  2. {meshcode-2.10.62 → meshcode-2.10.64}/meshcode/__init__.py +1 -1
  3. {meshcode-2.10.62 → meshcode-2.10.64}/meshcode/comms_v4.py +30 -2
  4. {meshcode-2.10.62 → meshcode-2.10.64}/meshcode/meshcode_mcp/server.py +40 -5
  5. meshcode-2.10.64/meshcode/quickstart.py +148 -0
  6. {meshcode-2.10.62 → meshcode-2.10.64}/meshcode.egg-info/PKG-INFO +1 -1
  7. {meshcode-2.10.62 → meshcode-2.10.64}/meshcode.egg-info/SOURCES.txt +1 -0
  8. {meshcode-2.10.62 → meshcode-2.10.64}/pyproject.toml +1 -1
  9. {meshcode-2.10.62 → meshcode-2.10.64}/README.md +0 -0
  10. {meshcode-2.10.62 → meshcode-2.10.64}/meshcode/ascii_art.py +0 -0
  11. {meshcode-2.10.62 → meshcode-2.10.64}/meshcode/cli.py +0 -0
  12. {meshcode-2.10.62 → meshcode-2.10.64}/meshcode/compat.py +0 -0
  13. {meshcode-2.10.62 → meshcode-2.10.64}/meshcode/error_hints.py +0 -0
  14. {meshcode-2.10.62 → meshcode-2.10.64}/meshcode/exceptions.py +0 -0
  15. {meshcode-2.10.62 → meshcode-2.10.64}/meshcode/invites.py +0 -0
  16. {meshcode-2.10.62 → meshcode-2.10.64}/meshcode/launcher.py +0 -0
  17. {meshcode-2.10.62 → meshcode-2.10.64}/meshcode/launcher_install.py +0 -0
  18. {meshcode-2.10.62 → meshcode-2.10.64}/meshcode/meshcode_mcp/__init__.py +0 -0
  19. {meshcode-2.10.62 → meshcode-2.10.64}/meshcode/meshcode_mcp/__main__.py +0 -0
  20. {meshcode-2.10.62 → meshcode-2.10.64}/meshcode/meshcode_mcp/backend.py +0 -0
  21. {meshcode-2.10.62 → meshcode-2.10.64}/meshcode/meshcode_mcp/realtime.py +0 -0
  22. {meshcode-2.10.62 → meshcode-2.10.64}/meshcode/meshcode_mcp/test_backend.py +0 -0
  23. {meshcode-2.10.62 → meshcode-2.10.64}/meshcode/meshcode_mcp/test_realtime.py +0 -0
  24. {meshcode-2.10.62 → meshcode-2.10.64}/meshcode/meshcode_mcp/test_server_wrapper.py +0 -0
  25. {meshcode-2.10.62 → meshcode-2.10.64}/meshcode/preferences.py +0 -0
  26. {meshcode-2.10.62 → meshcode-2.10.64}/meshcode/protocol_v2.py +0 -0
  27. {meshcode-2.10.62 → meshcode-2.10.64}/meshcode/run_agent.py +0 -0
  28. {meshcode-2.10.62 → meshcode-2.10.64}/meshcode/secrets.py +0 -0
  29. {meshcode-2.10.62 → meshcode-2.10.64}/meshcode/self_update.py +0 -0
  30. {meshcode-2.10.62 → meshcode-2.10.64}/meshcode/setup_clients.py +0 -0
  31. {meshcode-2.10.62 → meshcode-2.10.64}/meshcode/supervisor.py +0 -0
  32. {meshcode-2.10.62 → meshcode-2.10.64}/meshcode/upload.py +0 -0
  33. {meshcode-2.10.62 → meshcode-2.10.64}/meshcode.egg-info/dependency_links.txt +0 -0
  34. {meshcode-2.10.62 → meshcode-2.10.64}/meshcode.egg-info/entry_points.txt +0 -0
  35. {meshcode-2.10.62 → meshcode-2.10.64}/meshcode.egg-info/requires.txt +0 -0
  36. {meshcode-2.10.62 → meshcode-2.10.64}/meshcode.egg-info/top_level.txt +0 -0
  37. {meshcode-2.10.62 → meshcode-2.10.64}/setup.cfg +0 -0
  38. {meshcode-2.10.62 → meshcode-2.10.64}/tests/test_core.py +0 -0
  39. {meshcode-2.10.62 → meshcode-2.10.64}/tests/test_cross_agent_messaging.py +0 -0
  40. {meshcode-2.10.62 → meshcode-2.10.64}/tests/test_esc_deaf_state.py +0 -0
  41. {meshcode-2.10.62 → meshcode-2.10.64}/tests/test_exceptions.py +0 -0
  42. {meshcode-2.10.62 → meshcode-2.10.64}/tests/test_mark_read_batch.py +0 -0
  43. {meshcode-2.10.62 → meshcode-2.10.64}/tests/test_migration_integrity.py +0 -0
  44. {meshcode-2.10.62 → meshcode-2.10.64}/tests/test_realtime_event_freshness.py +0 -0
  45. {meshcode-2.10.62 → meshcode-2.10.64}/tests/test_rls_cross_tenant.py +0 -0
  46. {meshcode-2.10.62 → meshcode-2.10.64}/tests/test_rpc_migrations.py +0 -0
  47. {meshcode-2.10.62 → meshcode-2.10.64}/tests/test_security_regressions.py +0 -0
  48. {meshcode-2.10.62 → meshcode-2.10.64}/tests/test_sentinel.py +0 -0
  49. {meshcode-2.10.62 → meshcode-2.10.64}/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.62
3
+ Version: 2.10.64
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.62"
2
+ __version__ = "2.10.64"
3
3
 
4
4
  # Exception hierarchy — eagerly imported (lightweight, no deps)
5
5
  from meshcode.exceptions import ( # noqa: F401
@@ -2024,8 +2024,31 @@ def cmd_doctor(flags, pos):
2024
2024
  except Exception as e:
2025
2025
  fail("Supabase API", f"unreachable: {e}")
2026
2026
 
2027
- # 5. Stale agents check (requires auth)
2027
+ # 4b. API key validity
2028
2028
  api_key = _load_api_key_for_cli()
2029
+ if api_key:
2030
+ try:
2031
+ result = sb_rpc("mc_validate_api_key", {"p_api_key": api_key})
2032
+ if isinstance(result, dict) and result.get("ok"):
2033
+ ok("API key", "valid")
2034
+ elif isinstance(result, dict) and result.get("error"):
2035
+ fail("API key", f"invalid: {result.get('error')}. Run: meshcode login <new_key>")
2036
+ else:
2037
+ ok("API key", "accepted (validation RPC may not exist)")
2038
+ except Exception:
2039
+ ok("API key", "present (could not validate)")
2040
+ else:
2041
+ fail("API key", "not found. Run: meshcode login <api_key>")
2042
+
2043
+ # 4c. MCP server import test
2044
+ try:
2045
+ import importlib
2046
+ _mod = importlib.import_module("meshcode.meshcode_mcp.server")
2047
+ ok("MCP server", "module imports cleanly")
2048
+ except Exception as e:
2049
+ fail("MCP server", f"import error: {e}. Run: pip install --upgrade meshcode")
2050
+
2051
+ # 5. Stale agents check (requires auth)
2029
2052
  if api_key:
2030
2053
  try:
2031
2054
  # Try listing all projects for this user
@@ -3314,6 +3337,11 @@ if __name__ == "__main__":
3314
3337
  elif cmd == "doctor":
3315
3338
  cmd_doctor(flags, pos)
3316
3339
 
3340
+ elif cmd == "quickstart":
3341
+ import importlib
3342
+ _qs = importlib.import_module("meshcode.quickstart")
3343
+ sys.exit(_qs.cmd_quickstart())
3344
+
3317
3345
  elif cmd == "launcher":
3318
3346
  # meshcode launcher {install|uninstall|start|stop|restart|status|logs|test}
3319
3347
  try:
@@ -3369,7 +3397,7 @@ if __name__ == "__main__":
3369
3397
  "setup", "run", "go", "invite", "join", "invites", "members",
3370
3398
  "revoke-invite", "revoke-member", "login", "prefs", "launcher",
3371
3399
  "help", "init", "doctor", "compat", "upgrade", "profile", "validate-sessions", "wake-headless",
3372
- "supervisor", "upload",
3400
+ "supervisor", "upload", "quickstart",
3373
3401
  ]
3374
3402
  # Simple fuzzy: prefix match + Levenshtein-like best match
3375
3403
  suggestions = [c for c in known_cmds if c.startswith(cmd)]
@@ -684,6 +684,33 @@ def _auto_learn_error(tool_name: str, error: Exception, args_keys: list) -> None
684
684
  pass # Never let error-learning itself cause failures
685
685
 
686
686
 
687
+ # ── Activity feed auto-logger ──────────────────────────────────
688
+ # Logs tool calls to mc_activity for the live dashboard feed.
689
+ # Background thread, fire-and-forget — never blocks tool execution.
690
+ _ACTIVITY_LOG_SKIP = {"meshcode_wait", "meshcode_check", "meshcode_set_status",
691
+ "meshcode_recall", "meshcode_recall_keys", "meshcode_recall_search",
692
+ "meshcode_health", "meshcode_status", "meshcode_debug_sleep"}
693
+
694
+ def _log_activity_bg(event_type: str, summary: str) -> None:
695
+ """Fire-and-forget activity logging in background thread."""
696
+ try:
697
+ import threading
698
+ def _do():
699
+ try:
700
+ api_key = _get_api_key()
701
+ if api_key:
702
+ be.sb_rpc("mc_log_activity", {
703
+ "p_api_key": api_key,
704
+ "p_event_type": event_type,
705
+ "p_summary": summary[:200],
706
+ })
707
+ except Exception:
708
+ pass
709
+ threading.Thread(target=_do, daemon=True).start()
710
+ except Exception:
711
+ pass
712
+
713
+
687
714
  def with_working_status(func):
688
715
  name = func.__name__
689
716
  skip = (name == "meshcode_wait")
@@ -700,11 +727,12 @@ def with_working_status(func):
700
727
  _est_tokens = sum(len(str(v)) for v in kwargs.values()) // 4
701
728
  _record_event_bg("tool_call", {"tool": name, "args_keys": list(kwargs.keys()), "estimated_tokens": _est_tokens})
702
729
  try:
703
- return await func(*args, **kwargs)
730
+ result = await func(*args, **kwargs)
731
+ # Auto-log to activity feed (skip noisy read-only tools)
732
+ if not skip and name not in _ACTIVITY_LOG_SKIP:
733
+ _log_activity_bg("tool_call", f"{AGENT_NAME}: {name}")
734
+ return result
704
735
  except asyncio.CancelledError:
705
- # ESC in Claude Code cancels the in-flight task. Catch here
706
- # to prevent cascade through FastMCP into the event loop.
707
- # Return an error dict instead of propagating BaseException.
708
736
  log.debug(f"[meshcode] tool {name} cancelled by client (ESC)")
709
737
  return {"error": "cancelled_by_client", "tool": name}
710
738
  except Exception as e:
@@ -728,7 +756,10 @@ def with_working_status(func):
728
756
  _est_tokens = sum(len(str(v)) for v in kwargs.values()) // 4
729
757
  _record_event_bg("tool_call", {"tool": name, "args_keys": list(kwargs.keys()), "estimated_tokens": _est_tokens})
730
758
  try:
731
- return func(*args, **kwargs)
759
+ result = func(*args, **kwargs)
760
+ if not skip and name not in _ACTIVITY_LOG_SKIP:
761
+ _log_activity_bg("tool_call", f"{AGENT_NAME}: {name}")
762
+ return result
732
763
  except Exception as e:
733
764
  if not skip:
734
765
  _auto_learn_error(name, e, list(kwargs.keys()))
@@ -1506,6 +1537,7 @@ async def lifespan(_app):
1506
1537
  be.sb_rpc("mc_heartbeat", {"p_project_id": _PROJECT_ID, "p_agent_name": AGENT_NAME, "p_version": _SDK_VERSION})
1507
1538
  be.set_status(_PROJECT_ID, AGENT_NAME, "idle", "MCP session active", api_key=_get_api_key())
1508
1539
  log.info(f"[meshcode] Agent {AGENT_NAME} online — initial heartbeat sent")
1540
+ _log_activity_bg("agent_online", f"{AGENT_NAME} came online")
1509
1541
  break
1510
1542
  except Exception as e:
1511
1543
  log.warning(f"initial heartbeat attempt {_attempt+1} failed: {e}")
@@ -2072,6 +2104,9 @@ async def meshcode_wait(timeout_seconds: int = 20, include_acks: bool = False) -
2072
2104
  # Real message arrived — return to agent for processing
2073
2105
  _set_state("online", "")
2074
2106
  _CONSECUTIVE_IDLE_SECONDS = 0
2107
+ _msg_count = len(result.get("messages", []))
2108
+ if _msg_count:
2109
+ _log_activity_bg("message_delivered", f"{AGENT_NAME} received {_msg_count} message(s)")
2075
2110
  break
2076
2111
 
2077
2112
  if result.get("timed_out"):
@@ -0,0 +1,148 @@
1
+ """MeshCode Quickstart Wizard — one command to go from zero to running agent.
2
+
3
+ Usage: meshcode quickstart
4
+
5
+ Flow:
6
+ 1. Ask for API key (or detect from config)
7
+ 2. Ask for project name (or create new)
8
+ 3. Ask for agent name + role
9
+ 4. Auto-run: register → setup → run
10
+ """
11
+ import sys
12
+ import os
13
+ import json
14
+ from pathlib import Path
15
+
16
+
17
+ def _input_with_default(prompt: str, default: str = "") -> str:
18
+ """Input with default value shown in brackets."""
19
+ if default:
20
+ raw = input(f"{prompt} [{default}]: ").strip()
21
+ return raw if raw else default
22
+ return input(f"{prompt}: ").strip()
23
+
24
+
25
+ def cmd_quickstart() -> int:
26
+ """Interactive quickstart wizard."""
27
+ print()
28
+ print(" ╔══════════════════════════════════════╗")
29
+ print(" ║ MeshCode Quickstart Wizard ║")
30
+ print(" ║ From zero to running agent in 60s ║")
31
+ print(" ╚══════════════════════════════════════╝")
32
+ print()
33
+
34
+ # Step 1: API key
35
+ config_dir = Path.home() / ".meshcode"
36
+ existing_key = None
37
+ try:
38
+ profile = config_dir / "profile_meta.json"
39
+ if profile.exists():
40
+ meta = json.loads(profile.read_text())
41
+ existing_key = meta.get("api_key")
42
+ email = meta.get("email", "unknown")
43
+ print(f" [+] Already logged in as {email}")
44
+ except Exception:
45
+ pass
46
+
47
+ if not existing_key:
48
+ print(" Step 1: Enter your API key")
49
+ print(" (Get one at meshcode.io/dashboard → Settings → API Keys)")
50
+ print()
51
+ api_key = input(" API key: ").strip()
52
+ if not api_key:
53
+ print(" [!] API key required. Get one at meshcode.io/dashboard")
54
+ return 1
55
+ # Login
56
+ try:
57
+ from meshcode.meshcode_mcp import backend as be
58
+ # Validate key
59
+ result = be.sb_rpc("mc_validate_api_key", {"p_api_key": api_key})
60
+ if isinstance(result, dict) and result.get("error"):
61
+ print(f" [x] Invalid API key: {result.get('error')}")
62
+ return 1
63
+ print(" [+] API key valid!")
64
+ # Save
65
+ config_dir.mkdir(parents=True, exist_ok=True)
66
+ (config_dir / "profile_meta.json").write_text(json.dumps({
67
+ "api_key": api_key,
68
+ "email": result.get("email", "unknown"),
69
+ }))
70
+ except Exception as e:
71
+ print(f" [x] Could not validate: {e}")
72
+ print(" Continuing anyway — key will be verified on run.")
73
+ config_dir.mkdir(parents=True, exist_ok=True)
74
+ (config_dir / "profile_meta.json").write_text(json.dumps({"api_key": api_key}))
75
+ else:
76
+ api_key = existing_key
77
+
78
+ print()
79
+
80
+ # Step 2: Project
81
+ print(" Step 2: Choose your meshwork (project)")
82
+ try:
83
+ from meshcode.meshcode_mcp import backend as be
84
+ projects = be.sb_rpc("mc_list_user_projects", {"p_api_key": api_key})
85
+ if isinstance(projects, dict) and projects.get("projects"):
86
+ proj_list = projects["projects"]
87
+ print(f" Your meshworks: {', '.join(p['name'] for p in proj_list[:5])}")
88
+ project = _input_with_default(" Meshwork name", proj_list[0]["name"])
89
+ else:
90
+ project = _input_with_default(" New meshwork name", "my-team")
91
+ except Exception:
92
+ project = _input_with_default(" Meshwork name", "my-team")
93
+
94
+ print()
95
+
96
+ # Step 3: Agent
97
+ print(" Step 3: Create your agent")
98
+ agent_name = _input_with_default(" Agent name", "assistant")
99
+ role = _input_with_default(" Agent role", "General-purpose AI assistant")
100
+
101
+ print()
102
+ print(f" Creating {agent_name} in {project}...")
103
+ print()
104
+
105
+ # Step 4: Setup + Run
106
+ try:
107
+ # Register agent
108
+ from meshcode.meshcode_mcp import backend as be
109
+ result = be.register_agent(project, agent_name, role, api_key=api_key)
110
+ if isinstance(result, dict) and result.get("error"):
111
+ if "already registered" in str(result.get("error", "")).lower():
112
+ print(f" [+] Agent {agent_name} already exists — reusing")
113
+ else:
114
+ print(f" [!] Registration: {result.get('error')}")
115
+ else:
116
+ print(f" [+] Agent {agent_name} registered!")
117
+ except Exception as e:
118
+ print(f" [!] Registration note: {e}")
119
+
120
+ # Run setup
121
+ print(f" [+] Setting up MCP connection...")
122
+ try:
123
+ import subprocess
124
+ subprocess.run(
125
+ [sys.executable, "-m", "meshcode", "setup", "claude", project, agent_name, role],
126
+ check=False
127
+ )
128
+ except Exception as e:
129
+ print(f" [!] Setup: {e}")
130
+
131
+ print()
132
+ print(" ╔══════════════════════════════════════╗")
133
+ print(f" ║ Agent '{agent_name}' is ready! ")
134
+ print(" ╚══════════════════════════════════════╝")
135
+ print()
136
+ print(" Next steps:")
137
+ print(f" 1. Open Claude Code and start chatting")
138
+ print(f" 2. Your agent will auto-connect via MCP")
139
+ print(f" 3. Or run manually: meshcode run {project} {agent_name}")
140
+ print()
141
+
142
+ # Ask if they want to run now
143
+ run_now = input(" Start agent now? [Y/n]: ").strip().lower()
144
+ if run_now in ("", "y", "yes"):
145
+ print(f"\n Starting {agent_name}...")
146
+ os.execvp(sys.executable, [sys.executable, "-m", "meshcode", "run", project, agent_name])
147
+
148
+ return 0
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.4
2
2
  Name: meshcode
3
- Version: 2.10.62
3
+ Version: 2.10.64
4
4
  Summary: Real-time communication between AI agents — Supabase-backed CLI
5
5
  Author-email: MeshCode <hello@meshcode.io>
6
6
  License: MIT
@@ -12,6 +12,7 @@ meshcode/launcher.py
12
12
  meshcode/launcher_install.py
13
13
  meshcode/preferences.py
14
14
  meshcode/protocol_v2.py
15
+ meshcode/quickstart.py
15
16
  meshcode/run_agent.py
16
17
  meshcode/secrets.py
17
18
  meshcode/self_update.py
@@ -4,7 +4,7 @@ build-backend = "setuptools.build_meta"
4
4
 
5
5
  [project]
6
6
  name = "meshcode"
7
- version = "2.10.62"
7
+ version = "2.10.64"
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