meshcode 2.11.128__tar.gz → 2.11.131__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 (101) hide show
  1. {meshcode-2.11.128 → meshcode-2.11.131}/PKG-INFO +1 -1
  2. {meshcode-2.11.128 → meshcode-2.11.131}/meshcode/__init__.py +1 -1
  3. {meshcode-2.11.128 → meshcode-2.11.131}/meshcode/_session_handoff_template.py +71 -0
  4. {meshcode-2.11.128 → meshcode-2.11.131}/meshcode/hostd.py +586 -34
  5. {meshcode-2.11.128 → meshcode-2.11.131}/meshcode/meshcode_mcp/backend.py +11 -0
  6. {meshcode-2.11.128 → meshcode-2.11.131}/meshcode/meshcode_mcp/server.py +93 -22
  7. {meshcode-2.11.128 → meshcode-2.11.131}/meshcode/meshcode_mcp/swarm.py +93 -38
  8. {meshcode-2.11.128 → meshcode-2.11.131}/meshcode/meshcode_mcp/test_swarm.py +118 -38
  9. {meshcode-2.11.128 → meshcode-2.11.131}/meshcode/protocol_handler.py +317 -16
  10. {meshcode-2.11.128 → meshcode-2.11.131}/meshcode/run_agent.py +18 -2
  11. {meshcode-2.11.128 → meshcode-2.11.131}/meshcode/secrets.py +51 -11
  12. {meshcode-2.11.128 → meshcode-2.11.131}/meshcode/setup_clients.py +14 -6
  13. {meshcode-2.11.128 → meshcode-2.11.131}/meshcode/up.py +2 -1
  14. {meshcode-2.11.128 → meshcode-2.11.131}/meshcode.egg-info/PKG-INFO +1 -1
  15. {meshcode-2.11.128 → meshcode-2.11.131}/meshcode.egg-info/SOURCES.txt +3 -0
  16. {meshcode-2.11.128 → meshcode-2.11.131}/pyproject.toml +1 -1
  17. meshcode-2.11.131/tests/test_hostd_zombie_sessions.py +431 -0
  18. meshcode-2.11.131/tests/test_session_replay_gate.py +153 -0
  19. {meshcode-2.11.128 → meshcode-2.11.131}/tests/test_stop_ghost_terminal.py +13 -3
  20. meshcode-2.11.131/tests/test_terminal_lifecycle.py +118 -0
  21. {meshcode-2.11.128 → meshcode-2.11.131}/README.md +0 -0
  22. {meshcode-2.11.128 → meshcode-2.11.131}/meshcode/__main__.py +0 -0
  23. {meshcode-2.11.128 → meshcode-2.11.131}/meshcode/_stop_hook_template.py +0 -0
  24. {meshcode-2.11.128 → meshcode-2.11.131}/meshcode/ascii_art.py +0 -0
  25. {meshcode-2.11.128 → meshcode-2.11.131}/meshcode/atomic_push.py +0 -0
  26. {meshcode-2.11.128 → meshcode-2.11.131}/meshcode/claude_update.py +0 -0
  27. {meshcode-2.11.128 → meshcode-2.11.131}/meshcode/cli.py +0 -0
  28. {meshcode-2.11.128 → meshcode-2.11.131}/meshcode/comms_v4.py +0 -0
  29. {meshcode-2.11.128 → meshcode-2.11.131}/meshcode/compat.py +0 -0
  30. {meshcode-2.11.128 → meshcode-2.11.131}/meshcode/daemon.py +0 -0
  31. {meshcode-2.11.128 → meshcode-2.11.131}/meshcode/date_parse.py +0 -0
  32. {meshcode-2.11.128 → meshcode-2.11.131}/meshcode/doctor.py +0 -0
  33. {meshcode-2.11.128 → meshcode-2.11.131}/meshcode/error_hints.py +0 -0
  34. {meshcode-2.11.128 → meshcode-2.11.131}/meshcode/exceptions.py +0 -0
  35. {meshcode-2.11.128 → meshcode-2.11.131}/meshcode/hooks/__init__.py +0 -0
  36. {meshcode-2.11.128 → meshcode-2.11.131}/meshcode/hooks/repo_path_lock.py +0 -0
  37. {meshcode-2.11.128 → meshcode-2.11.131}/meshcode/invites.py +0 -0
  38. {meshcode-2.11.128 → meshcode-2.11.131}/meshcode/launcher.py +0 -0
  39. {meshcode-2.11.128 → meshcode-2.11.131}/meshcode/launcher_install.py +0 -0
  40. {meshcode-2.11.128 → meshcode-2.11.131}/meshcode/meshcode_mcp/__init__.py +0 -0
  41. {meshcode-2.11.128 → meshcode-2.11.131}/meshcode/meshcode_mcp/__main__.py +0 -0
  42. {meshcode-2.11.128 → meshcode-2.11.131}/meshcode/meshcode_mcp/realtime.py +0 -0
  43. {meshcode-2.11.128 → meshcode-2.11.131}/meshcode/meshcode_mcp/sleep_signals.py +0 -0
  44. {meshcode-2.11.128 → meshcode-2.11.131}/meshcode/meshcode_mcp/test_backend.py +0 -0
  45. {meshcode-2.11.128 → meshcode-2.11.131}/meshcode/meshcode_mcp/test_boot_timing.py +0 -0
  46. {meshcode-2.11.128 → meshcode-2.11.131}/meshcode/meshcode_mcp/test_install_guard.py +0 -0
  47. {meshcode-2.11.128 → meshcode-2.11.131}/meshcode/meshcode_mcp/test_prefs_claude_version.py +0 -0
  48. {meshcode-2.11.128 → meshcode-2.11.131}/meshcode/meshcode_mcp/test_realtime.py +0 -0
  49. {meshcode-2.11.128 → meshcode-2.11.131}/meshcode/meshcode_mcp/test_server_wrapper.py +0 -0
  50. {meshcode-2.11.128 → meshcode-2.11.131}/meshcode/preferences.py +0 -0
  51. {meshcode-2.11.128 → meshcode-2.11.131}/meshcode/protocol_v2.py +0 -0
  52. {meshcode-2.11.128 → meshcode-2.11.131}/meshcode/quickstart.py +0 -0
  53. {meshcode-2.11.128 → meshcode-2.11.131}/meshcode/rpc_allowlist.py +0 -0
  54. {meshcode-2.11.128 → meshcode-2.11.131}/meshcode/scripts/check_secrets.py +0 -0
  55. {meshcode-2.11.128 → meshcode-2.11.131}/meshcode/scripts/race_rate_harness.py +0 -0
  56. {meshcode-2.11.128 → meshcode-2.11.131}/meshcode/self_update.py +0 -0
  57. {meshcode-2.11.128 → meshcode-2.11.131}/meshcode/supervisor.py +0 -0
  58. {meshcode-2.11.128 → meshcode-2.11.131}/meshcode/upload.py +0 -0
  59. {meshcode-2.11.128 → meshcode-2.11.131}/meshcode.egg-info/dependency_links.txt +0 -0
  60. {meshcode-2.11.128 → meshcode-2.11.131}/meshcode.egg-info/entry_points.txt +0 -0
  61. {meshcode-2.11.128 → meshcode-2.11.131}/meshcode.egg-info/requires.txt +0 -0
  62. {meshcode-2.11.128 → meshcode-2.11.131}/meshcode.egg-info/top_level.txt +0 -0
  63. {meshcode-2.11.128 → meshcode-2.11.131}/setup.cfg +0 -0
  64. {meshcode-2.11.128 → meshcode-2.11.131}/tests/test_auto_update_hardening.py +0 -0
  65. {meshcode-2.11.128 → meshcode-2.11.131}/tests/test_autonomous_closegap_1.py +0 -0
  66. {meshcode-2.11.128 → meshcode-2.11.131}/tests/test_autonomous_closegap_2.py +0 -0
  67. {meshcode-2.11.128 → meshcode-2.11.131}/tests/test_autonomous_closegap_3.py +0 -0
  68. {meshcode-2.11.128 → meshcode-2.11.131}/tests/test_autonomous_prompt_inject.py +0 -0
  69. {meshcode-2.11.128 → meshcode-2.11.131}/tests/test_boot_bug_regression.py +0 -0
  70. {meshcode-2.11.128 → meshcode-2.11.131}/tests/test_color_truecolor.py +0 -0
  71. {meshcode-2.11.128 → meshcode-2.11.131}/tests/test_core.py +0 -0
  72. {meshcode-2.11.128 → meshcode-2.11.131}/tests/test_cross_agent_messaging.py +0 -0
  73. {meshcode-2.11.128 → meshcode-2.11.131}/tests/test_date_parse.py +0 -0
  74. {meshcode-2.11.128 → meshcode-2.11.131}/tests/test_doctor.py +0 -0
  75. {meshcode-2.11.128 → meshcode-2.11.131}/tests/test_epistemic_v1_python_sdk.py +0 -0
  76. {meshcode-2.11.128 → meshcode-2.11.131}/tests/test_epistemic_v1_stop_conditions.py +0 -0
  77. {meshcode-2.11.128 → meshcode-2.11.131}/tests/test_esc_deaf_state.py +0 -0
  78. {meshcode-2.11.128 → meshcode-2.11.131}/tests/test_exceptions.py +0 -0
  79. {meshcode-2.11.128 → meshcode-2.11.131}/tests/test_file_upload.py +0 -0
  80. {meshcode-2.11.128 → meshcode-2.11.131}/tests/test_init_device_code.py +0 -0
  81. {meshcode-2.11.128 → meshcode-2.11.131}/tests/test_install_guard.py +0 -0
  82. {meshcode-2.11.128 → meshcode-2.11.131}/tests/test_lease_sigterm_release.py +0 -0
  83. {meshcode-2.11.128 → meshcode-2.11.131}/tests/test_live_mesh_guard.py +0 -0
  84. {meshcode-2.11.128 → meshcode-2.11.131}/tests/test_mark_read_batch.py +0 -0
  85. {meshcode-2.11.128 → meshcode-2.11.131}/tests/test_marketplace_ratings.py +0 -0
  86. {meshcode-2.11.128 → meshcode-2.11.131}/tests/test_migration_integrity.py +0 -0
  87. {meshcode-2.11.128 → meshcode-2.11.131}/tests/test_realtime_event_freshness.py +0 -0
  88. {meshcode-2.11.128 → meshcode-2.11.131}/tests/test_rls_cross_tenant.py +0 -0
  89. {meshcode-2.11.128 → meshcode-2.11.131}/tests/test_rpc_grants.py +0 -0
  90. {meshcode-2.11.128 → meshcode-2.11.131}/tests/test_rpc_migrations.py +0 -0
  91. {meshcode-2.11.128 → meshcode-2.11.131}/tests/test_run_agent_dry_run.py +0 -0
  92. {meshcode-2.11.128 → meshcode-2.11.131}/tests/test_run_agent_no_server_import.py +0 -0
  93. {meshcode-2.11.128 → meshcode-2.11.131}/tests/test_security_regressions.py +0 -0
  94. {meshcode-2.11.128 → meshcode-2.11.131}/tests/test_self_update_user_site.py +0 -0
  95. {meshcode-2.11.128 → meshcode-2.11.131}/tests/test_sentinel.py +0 -0
  96. {meshcode-2.11.128 → meshcode-2.11.131}/tests/test_setup_path.py +0 -0
  97. {meshcode-2.11.128 → meshcode-2.11.131}/tests/test_sleep_signals.py +0 -0
  98. {meshcode-2.11.128 → meshcode-2.11.131}/tests/test_status_enum_coverage.py +0 -0
  99. {meshcode-2.11.128 → meshcode-2.11.131}/tests/test_stay_on_loop_hook.py +0 -0
  100. {meshcode-2.11.128 → meshcode-2.11.131}/tests/test_swarm_events.py +0 -0
  101. {meshcode-2.11.128 → meshcode-2.11.131}/tests/test_wait_open_tasks_contradiction.py +0 -0
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.4
2
2
  Name: meshcode
3
- Version: 2.11.128
3
+ Version: 2.11.131
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.11.128"
2
+ __version__ = "2.11.131"
3
3
 
4
4
  # Exception hierarchy — eagerly imported (lightweight, no deps)
5
5
  from meshcode.exceptions import ( # noqa: F401
@@ -208,6 +208,75 @@ def _persist_handoff_to_memory(project_dir, handoff) -> None:
208
208
  sys.stderr.write(f"[session_handoff_write] memory-persist skipped: {e}\\n")
209
209
 
210
210
 
211
+ def _send_session_handoff_capsule(project_dir, handoff) -> None:
212
+ """py-half task 4aee4739 (66d10cec): push a MINI capsule to the dedicated
213
+ mc_set_session_handoff RPC (live in prod, api_key-auth) so the NEXT boot
214
+ surfaces it as continuity_capsule.last_handoff in mc_boot — even on a new
215
+ host or wiped workspace. Contract: ended_at ISO8601, last_task_ids (str8
216
+ list scraped from the transcript tail), last_msg_snippet, note (from the
217
+ cooperative .session-thread.json if the agent keeps one). Best-effort in
218
+ every dimension — the stop/compaction path NEVER blocks on this.
219
+ """
220
+ try:
221
+ mcp = json.loads((project_dir / ".mcp.json").read_text(encoding="utf-8"))
222
+ env = (next(iter((mcp.get("mcpServers") or {}).values()), {}) or {}).get("env", {}) or {}
223
+ url = env.get("SUPABASE_URL"); key = env.get("SUPABASE_KEY")
224
+ pid = env.get("MESHCODE_PROJECT_ID"); agent = env.get("MESHCODE_AGENT")
225
+ if not (url and key and pid and agent):
226
+ return
227
+ api_key = os.environ.get("MESHCODE_API_KEY")
228
+ if not api_key:
229
+ try:
230
+ import importlib
231
+ api_key = importlib.import_module("meshcode.secrets").get_api_key(
232
+ profile=env.get("MESHCODE_KEYCHAIN_PROFILE") or "default")
233
+ except Exception:
234
+ api_key = None
235
+ if not api_key:
236
+ return
237
+ import re as _re
238
+ from datetime import datetime, timezone
239
+ turns = handoff.get("turns") or []
240
+ tail_text = " ".join(t.get("text", "") for t in turns[-8:])
241
+ # task ids surface in transcripts as 8-hex prefixes (task_id short form);
242
+ # dedupe preserving order, cap 5 — a hint list, not an authority (boot
243
+ # task list stays authoritative).
244
+ seen = []
245
+ for m in _re.findall(r"\\b[0-9a-f]{8}\\b", tail_text):
246
+ if m not in seen:
247
+ seen.append(m)
248
+ note = ""
249
+ try:
250
+ thread = json.loads((project_dir / ".session-thread.json").read_text(encoding="utf-8"))
251
+ note = str(thread.get("hilo_de_pensamiento", ""))[:500]
252
+ except Exception:
253
+ pass
254
+ last_snip = ""
255
+ for t in reversed(turns):
256
+ if t.get("text"):
257
+ last_snip = str(t["text"])[:400]
258
+ break
259
+ capsule = {
260
+ "ended_at": datetime.now(timezone.utc).isoformat(),
261
+ "last_task_ids": seen[:5],
262
+ "last_msg_snippet": last_snip,
263
+ "note": note,
264
+ }
265
+ import urllib.request as _u
266
+ body = json.dumps({
267
+ "p_api_key": api_key, "p_project_id": pid,
268
+ "p_agent_name": agent, "p_capsule": capsule,
269
+ }).encode("utf-8")
270
+ req = _u.Request(
271
+ url.rstrip("/") + "/rest/v1/rpc/mc_set_session_handoff",
272
+ data=body, method="POST",
273
+ headers={"apikey": key, "Authorization": "Bearer " + key,
274
+ "Content-Type": "application/json"})
275
+ _u.urlopen(req, timeout=5).read()
276
+ except Exception as e: # noqa: BLE001 — never block stop/compaction
277
+ sys.stderr.write(f"[session_handoff_write] capsule skipped: {e}\\n")
278
+
279
+
211
280
  def main() -> int:
212
281
  try:
213
282
  raw = sys.stdin.read()
@@ -234,6 +303,8 @@ def main() -> int:
234
303
  sys.stderr.write(f"[session_handoff_write] skipped: {e}\\n")
235
304
  # L6 M6.1: mirror to server-side memory for the boot continuity capsule.
236
305
  _persist_handoff_to_memory(_project_dir(), handoff)
306
+ # py-half 4aee4739: dedicated handoff capsule -> mc_boot continuity_capsule.last_handoff.
307
+ _send_session_handoff_capsule(_project_dir(), handoff)
237
308
  # CTX-CLOSE-RELAUNCH (task 400fc536): now that the thread is snapshotted,
238
309
  # commander-tier sessions ask the server to recycle at the next task-edge.
239
310
  _request_recycle_if_marked(_project_dir())