meshcode 2.11.68__tar.gz → 2.11.70__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 (90) hide show
  1. {meshcode-2.11.68 → meshcode-2.11.70}/PKG-INFO +1 -1
  2. {meshcode-2.11.68 → meshcode-2.11.70}/meshcode/__init__.py +1 -1
  3. {meshcode-2.11.68 → meshcode-2.11.70}/meshcode/hostd.py +33 -13
  4. {meshcode-2.11.68 → meshcode-2.11.70}/meshcode/protocol_handler.py +28 -4
  5. {meshcode-2.11.68 → meshcode-2.11.70}/meshcode.egg-info/PKG-INFO +1 -1
  6. {meshcode-2.11.68 → meshcode-2.11.70}/pyproject.toml +1 -1
  7. {meshcode-2.11.68 → meshcode-2.11.70}/README.md +0 -0
  8. {meshcode-2.11.68 → meshcode-2.11.70}/meshcode/__main__.py +0 -0
  9. {meshcode-2.11.68 → meshcode-2.11.70}/meshcode/_stop_hook_template.py +0 -0
  10. {meshcode-2.11.68 → meshcode-2.11.70}/meshcode/ascii_art.py +0 -0
  11. {meshcode-2.11.68 → meshcode-2.11.70}/meshcode/atomic_push.py +0 -0
  12. {meshcode-2.11.68 → meshcode-2.11.70}/meshcode/claude_update.py +0 -0
  13. {meshcode-2.11.68 → meshcode-2.11.70}/meshcode/cli.py +0 -0
  14. {meshcode-2.11.68 → meshcode-2.11.70}/meshcode/comms_v4.py +0 -0
  15. {meshcode-2.11.68 → meshcode-2.11.70}/meshcode/compat.py +0 -0
  16. {meshcode-2.11.68 → meshcode-2.11.70}/meshcode/daemon.py +0 -0
  17. {meshcode-2.11.68 → meshcode-2.11.70}/meshcode/date_parse.py +0 -0
  18. {meshcode-2.11.68 → meshcode-2.11.70}/meshcode/doctor.py +0 -0
  19. {meshcode-2.11.68 → meshcode-2.11.70}/meshcode/error_hints.py +0 -0
  20. {meshcode-2.11.68 → meshcode-2.11.70}/meshcode/exceptions.py +0 -0
  21. {meshcode-2.11.68 → meshcode-2.11.70}/meshcode/invites.py +0 -0
  22. {meshcode-2.11.68 → meshcode-2.11.70}/meshcode/launcher.py +0 -0
  23. {meshcode-2.11.68 → meshcode-2.11.70}/meshcode/launcher_install.py +0 -0
  24. {meshcode-2.11.68 → meshcode-2.11.70}/meshcode/meshcode_mcp/__init__.py +0 -0
  25. {meshcode-2.11.68 → meshcode-2.11.70}/meshcode/meshcode_mcp/__main__.py +0 -0
  26. {meshcode-2.11.68 → meshcode-2.11.70}/meshcode/meshcode_mcp/backend.py +0 -0
  27. {meshcode-2.11.68 → meshcode-2.11.70}/meshcode/meshcode_mcp/realtime.py +0 -0
  28. {meshcode-2.11.68 → meshcode-2.11.70}/meshcode/meshcode_mcp/server.py +0 -0
  29. {meshcode-2.11.68 → meshcode-2.11.70}/meshcode/meshcode_mcp/sleep_signals.py +0 -0
  30. {meshcode-2.11.68 → meshcode-2.11.70}/meshcode/meshcode_mcp/test_backend.py +0 -0
  31. {meshcode-2.11.68 → meshcode-2.11.70}/meshcode/meshcode_mcp/test_boot_timing.py +0 -0
  32. {meshcode-2.11.68 → meshcode-2.11.70}/meshcode/meshcode_mcp/test_install_guard.py +0 -0
  33. {meshcode-2.11.68 → meshcode-2.11.70}/meshcode/meshcode_mcp/test_prefs_claude_version.py +0 -0
  34. {meshcode-2.11.68 → meshcode-2.11.70}/meshcode/meshcode_mcp/test_realtime.py +0 -0
  35. {meshcode-2.11.68 → meshcode-2.11.70}/meshcode/meshcode_mcp/test_server_wrapper.py +0 -0
  36. {meshcode-2.11.68 → meshcode-2.11.70}/meshcode/preferences.py +0 -0
  37. {meshcode-2.11.68 → meshcode-2.11.70}/meshcode/protocol_v2.py +0 -0
  38. {meshcode-2.11.68 → meshcode-2.11.70}/meshcode/quickstart.py +0 -0
  39. {meshcode-2.11.68 → meshcode-2.11.70}/meshcode/rpc_allowlist.py +0 -0
  40. {meshcode-2.11.68 → meshcode-2.11.70}/meshcode/run_agent.py +0 -0
  41. {meshcode-2.11.68 → meshcode-2.11.70}/meshcode/scripts/check_secrets.py +0 -0
  42. {meshcode-2.11.68 → meshcode-2.11.70}/meshcode/scripts/race_rate_harness.py +0 -0
  43. {meshcode-2.11.68 → meshcode-2.11.70}/meshcode/secrets.py +0 -0
  44. {meshcode-2.11.68 → meshcode-2.11.70}/meshcode/self_update.py +0 -0
  45. {meshcode-2.11.68 → meshcode-2.11.70}/meshcode/setup_clients.py +0 -0
  46. {meshcode-2.11.68 → meshcode-2.11.70}/meshcode/supervisor.py +0 -0
  47. {meshcode-2.11.68 → meshcode-2.11.70}/meshcode/up.py +0 -0
  48. {meshcode-2.11.68 → meshcode-2.11.70}/meshcode/upload.py +0 -0
  49. {meshcode-2.11.68 → meshcode-2.11.70}/meshcode.egg-info/SOURCES.txt +0 -0
  50. {meshcode-2.11.68 → meshcode-2.11.70}/meshcode.egg-info/dependency_links.txt +0 -0
  51. {meshcode-2.11.68 → meshcode-2.11.70}/meshcode.egg-info/entry_points.txt +0 -0
  52. {meshcode-2.11.68 → meshcode-2.11.70}/meshcode.egg-info/requires.txt +0 -0
  53. {meshcode-2.11.68 → meshcode-2.11.70}/meshcode.egg-info/top_level.txt +0 -0
  54. {meshcode-2.11.68 → meshcode-2.11.70}/setup.cfg +0 -0
  55. {meshcode-2.11.68 → meshcode-2.11.70}/tests/test_auto_update_hardening.py +0 -0
  56. {meshcode-2.11.68 → meshcode-2.11.70}/tests/test_autonomous_closegap_1.py +0 -0
  57. {meshcode-2.11.68 → meshcode-2.11.70}/tests/test_autonomous_closegap_2.py +0 -0
  58. {meshcode-2.11.68 → meshcode-2.11.70}/tests/test_autonomous_closegap_3.py +0 -0
  59. {meshcode-2.11.68 → meshcode-2.11.70}/tests/test_autonomous_prompt_inject.py +0 -0
  60. {meshcode-2.11.68 → meshcode-2.11.70}/tests/test_boot_bug_regression.py +0 -0
  61. {meshcode-2.11.68 → meshcode-2.11.70}/tests/test_color_truecolor.py +0 -0
  62. {meshcode-2.11.68 → meshcode-2.11.70}/tests/test_core.py +0 -0
  63. {meshcode-2.11.68 → meshcode-2.11.70}/tests/test_cross_agent_messaging.py +0 -0
  64. {meshcode-2.11.68 → meshcode-2.11.70}/tests/test_date_parse.py +0 -0
  65. {meshcode-2.11.68 → meshcode-2.11.70}/tests/test_doctor.py +0 -0
  66. {meshcode-2.11.68 → meshcode-2.11.70}/tests/test_epistemic_v1_python_sdk.py +0 -0
  67. {meshcode-2.11.68 → meshcode-2.11.70}/tests/test_epistemic_v1_stop_conditions.py +0 -0
  68. {meshcode-2.11.68 → meshcode-2.11.70}/tests/test_esc_deaf_state.py +0 -0
  69. {meshcode-2.11.68 → meshcode-2.11.70}/tests/test_exceptions.py +0 -0
  70. {meshcode-2.11.68 → meshcode-2.11.70}/tests/test_file_upload.py +0 -0
  71. {meshcode-2.11.68 → meshcode-2.11.70}/tests/test_init_device_code.py +0 -0
  72. {meshcode-2.11.68 → meshcode-2.11.70}/tests/test_install_guard.py +0 -0
  73. {meshcode-2.11.68 → meshcode-2.11.70}/tests/test_lease_sigterm_release.py +0 -0
  74. {meshcode-2.11.68 → meshcode-2.11.70}/tests/test_mark_read_batch.py +0 -0
  75. {meshcode-2.11.68 → meshcode-2.11.70}/tests/test_marketplace_ratings.py +0 -0
  76. {meshcode-2.11.68 → meshcode-2.11.70}/tests/test_migration_integrity.py +0 -0
  77. {meshcode-2.11.68 → meshcode-2.11.70}/tests/test_realtime_event_freshness.py +0 -0
  78. {meshcode-2.11.68 → meshcode-2.11.70}/tests/test_rls_cross_tenant.py +0 -0
  79. {meshcode-2.11.68 → meshcode-2.11.70}/tests/test_rpc_grants.py +0 -0
  80. {meshcode-2.11.68 → meshcode-2.11.70}/tests/test_rpc_migrations.py +0 -0
  81. {meshcode-2.11.68 → meshcode-2.11.70}/tests/test_run_agent_dry_run.py +0 -0
  82. {meshcode-2.11.68 → meshcode-2.11.70}/tests/test_run_agent_no_server_import.py +0 -0
  83. {meshcode-2.11.68 → meshcode-2.11.70}/tests/test_security_regressions.py +0 -0
  84. {meshcode-2.11.68 → meshcode-2.11.70}/tests/test_self_update_user_site.py +0 -0
  85. {meshcode-2.11.68 → meshcode-2.11.70}/tests/test_sentinel.py +0 -0
  86. {meshcode-2.11.68 → meshcode-2.11.70}/tests/test_setup_path.py +0 -0
  87. {meshcode-2.11.68 → meshcode-2.11.70}/tests/test_sleep_signals.py +0 -0
  88. {meshcode-2.11.68 → meshcode-2.11.70}/tests/test_status_enum_coverage.py +0 -0
  89. {meshcode-2.11.68 → meshcode-2.11.70}/tests/test_stay_on_loop_hook.py +0 -0
  90. {meshcode-2.11.68 → meshcode-2.11.70}/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.68
3
+ Version: 2.11.70
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.68"
2
+ __version__ = "2.11.70"
3
3
 
4
4
  # Exception hierarchy — eagerly imported (lightweight, no deps)
5
5
  from meshcode.exceptions import ( # noqa: F401
@@ -34,6 +34,7 @@ from __future__ import annotations
34
34
 
35
35
  import json
36
36
  import os
37
+ import shlex
37
38
  import subprocess
38
39
  import sys
39
40
  import time
@@ -183,20 +184,30 @@ def _meshcode_bin() -> str:
183
184
 
184
185
 
185
186
  def _spawn_agent(project: str, agent: str) -> bool:
186
- """Relaunch `meshcode run <project>/<agent>` detached + visible-friendly."""
187
+ """Relaunch `meshcode run <project>/<agent>` in a VISIBLE terminal window.
188
+
189
+ Samuel must SEE the terminal open — a headless background process is NOT the
190
+ feature (the old code did subprocess.Popen(...DEVNULL) = no window). We delegate
191
+ to protocol_handler._spawn_terminal, the canonical visible spawner (macOS:
192
+ osascript-if-Automation-granted else `open` a .command wrapper, no TCC needed;
193
+ Linux/Windows: native terminals). On failure we WARN loudly and return False —
194
+ we NEVER silently fall back to a headless process, so the gap stays visible.
195
+ """
187
196
  target = f"{project}/{agent}"
188
- env = dict(os.environ)
189
- # env hygiene (item1 RC): a stale CLAUDECODE aborts `meshcode run` (exit2)
190
- env.pop("CLAUDECODE", None)
191
- env.pop("CLAUDE_CODE_SESSION", None)
192
- env["MESHCODE_NO_AUTO_UPDATE"] = env.get("MESHCODE_NO_AUTO_UPDATE", "1")
197
+ # env hygiene (item1 RC): a stale CLAUDECODE aborts `meshcode run` (exit2).
198
+ # Prefix the shell command so the spawned terminal starts with a clean env.
199
+ cmd = (f"unset CLAUDECODE CLAUDE_CODE_SESSION; export MESHCODE_NO_AUTO_UPDATE=1; "
200
+ f"exec {shlex.quote(_meshcode_bin())} run {shlex.quote(target)}")
193
201
  try:
194
- subprocess.Popen(
195
- [_meshcode_bin(), "run", target],
196
- env=env, start_new_session=True,
197
- stdout=subprocess.DEVNULL, stderr=subprocess.DEVNULL,
198
- )
199
- return True
202
+ from meshcode import protocol_handler as _ph
203
+ ok, info = _ph._spawn_terminal(cmd)
204
+ if ok:
205
+ _log(f"spawned {target} in visible terminal ({info})")
206
+ return True
207
+ _log(f"WARN: visible spawn {target} FAILED ({info}) — agent NOT launched. "
208
+ f"macOS: grant Terminal Automation (System Settings > Privacy & Security "
209
+ f"> Automation), or ensure `open` works. NOT falling back to headless.")
210
+ return False
200
211
  except Exception as e:
201
212
  _log(f"WARN: spawn {target} failed: {e}")
202
213
  return False
@@ -413,8 +424,17 @@ def cmd_hostd(args: list) -> int:
413
424
 
414
425
  if sub == "run":
415
426
  if not api_key:
416
- _log("FATAL: no api key — set MESHCODE_API_KEY")
427
+ _log("FATAL: no api key — run `meshcode login` (key is read from the keychain)")
417
428
  return 1
429
+ # Register this host in mc_host_config so the dashboard can list it as a
430
+ # launch target (Path2 canonical: dashboard -> mc_host_set_agents ->
431
+ # mc_agents.desired_state='running' -> this daemon polls + spawns).
432
+ # mc_host_config_set upserts (host_id, owner_user_id) idempotently.
433
+ _reg = _rpc("mc_host_config_set", {"p_api_key": api_key, "p_host_id": host_id})
434
+ if _reg and _reg.get("ok"):
435
+ _log(f"registered host {host_id} in mc_host_config")
436
+ else:
437
+ _log(f"WARN: host registration failed (dashboard may not list this host): {_reg}")
418
438
  _log(f"hostd starting — host_id={host_id} interval={POLL_INTERVAL_SEC}s stale={STALE_SECONDS}s")
419
439
  while True:
420
440
  try:
@@ -44,7 +44,15 @@ def _detect_macos_terminal() -> str:
44
44
 
45
45
 
46
46
  def _spawn_terminal_macos(cmd: str) -> tuple[bool, str]:
47
- """Spawn `cmd` in a new Terminal/iTerm window (detached)."""
47
+ """Spawn `cmd` in a new VISIBLE Terminal/iTerm window (detached).
48
+
49
+ Primary: osascript ('do script') — opens a window in the running Terminal/iTerm
50
+ but REQUIRES the macOS Automation permission. If the user hasn't granted it,
51
+ osascript fails. Fallback: a temp .command file launched via `open`, which opens
52
+ a visible Terminal window WITHOUT Automation (it just opens the app with a
53
+ document). So the spawn is ALWAYS a visible terminal, never a silent headless
54
+ background process (LAUNCH-1 spawn-visible gap).
55
+ """
48
56
  term = _detect_macos_terminal()
49
57
  # AppleScript escaping: backslash + double-quote
50
58
  safe = cmd.replace("\\", "\\\\").replace('"', '\\"')
@@ -59,9 +67,25 @@ def _spawn_terminal_macos(cmd: str) -> tuple[bool, str]:
59
67
  script = f'tell application "Terminal" to do script "{safe}"\n'
60
68
  r = subprocess.run(["osascript", "-e", script],
61
69
  capture_output=True, text=True)
62
- if r.returncode != 0:
63
- return False, (r.stderr or "osascript failed").strip()
64
- return True, term
70
+ if r.returncode == 0:
71
+ return True, term
72
+ osa_err = (r.stderr or "osascript failed").strip()
73
+ # Fallback: a .command launcher opened via `open` — no Automation permission needed.
74
+ try:
75
+ import tempfile
76
+ fd, path = tempfile.mkstemp(suffix=".command", prefix="meshcode-launch-")
77
+ with os.fdopen(fd, "w") as f:
78
+ f.write("#!/bin/bash\n")
79
+ f.write(cmd + "\n")
80
+ f.write('rm -f "$0"\n') # self-clean the temp launcher on exit
81
+ os.chmod(path, 0o755)
82
+ r2 = subprocess.run(["open", path], capture_output=True, text=True)
83
+ if r2.returncode == 0:
84
+ return True, "terminal(open-fallback)"
85
+ return False, (f"osascript failed ({osa_err}); "
86
+ f"open fallback failed ({(r2.stderr or '').strip()})")
87
+ except Exception as e:
88
+ return False, f"osascript failed ({osa_err}); open fallback exception: {e}"
65
89
 
66
90
 
67
91
  def _spawn_terminal_linux(cmd: str) -> tuple[bool, str]:
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.4
2
2
  Name: meshcode
3
- Version: 2.11.68
3
+ Version: 2.11.70
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.11.68"
7
+ version = "2.11.70"
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
File without changes