meshcode 2.11.152__tar.gz → 2.11.153__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 (107) hide show
  1. {meshcode-2.11.152 → meshcode-2.11.153}/PKG-INFO +1 -1
  2. {meshcode-2.11.152 → meshcode-2.11.153}/meshcode/__init__.py +1 -1
  3. {meshcode-2.11.152 → meshcode-2.11.153}/meshcode/protocol_handler.py +60 -27
  4. {meshcode-2.11.152 → meshcode-2.11.153}/meshcode.egg-info/PKG-INFO +1 -1
  5. {meshcode-2.11.152 → meshcode-2.11.153}/pyproject.toml +1 -1
  6. {meshcode-2.11.152 → meshcode-2.11.153}/README.md +0 -0
  7. {meshcode-2.11.152 → meshcode-2.11.153}/meshcode/__main__.py +0 -0
  8. {meshcode-2.11.152 → meshcode-2.11.153}/meshcode/_session_handoff_template.py +0 -0
  9. {meshcode-2.11.152 → meshcode-2.11.153}/meshcode/_stop_hook_template.py +0 -0
  10. {meshcode-2.11.152 → meshcode-2.11.153}/meshcode/ascii_art.py +0 -0
  11. {meshcode-2.11.152 → meshcode-2.11.153}/meshcode/atomic_push.py +0 -0
  12. {meshcode-2.11.152 → meshcode-2.11.153}/meshcode/claude_update.py +0 -0
  13. {meshcode-2.11.152 → meshcode-2.11.153}/meshcode/cli.py +0 -0
  14. {meshcode-2.11.152 → meshcode-2.11.153}/meshcode/comms_v4.py +0 -0
  15. {meshcode-2.11.152 → meshcode-2.11.153}/meshcode/compat.py +0 -0
  16. {meshcode-2.11.152 → meshcode-2.11.153}/meshcode/daemon.py +0 -0
  17. {meshcode-2.11.152 → meshcode-2.11.153}/meshcode/date_parse.py +0 -0
  18. {meshcode-2.11.152 → meshcode-2.11.153}/meshcode/doctor.py +0 -0
  19. {meshcode-2.11.152 → meshcode-2.11.153}/meshcode/error_hints.py +0 -0
  20. {meshcode-2.11.152 → meshcode-2.11.153}/meshcode/exceptions.py +0 -0
  21. {meshcode-2.11.152 → meshcode-2.11.153}/meshcode/helper_visuals.py +0 -0
  22. {meshcode-2.11.152 → meshcode-2.11.153}/meshcode/hooks/__init__.py +0 -0
  23. {meshcode-2.11.152 → meshcode-2.11.153}/meshcode/hooks/repo_path_lock.py +0 -0
  24. {meshcode-2.11.152 → meshcode-2.11.153}/meshcode/hostd.py +0 -0
  25. {meshcode-2.11.152 → meshcode-2.11.153}/meshcode/invites.py +0 -0
  26. {meshcode-2.11.152 → meshcode-2.11.153}/meshcode/launcher.py +0 -0
  27. {meshcode-2.11.152 → meshcode-2.11.153}/meshcode/launcher_install.py +0 -0
  28. {meshcode-2.11.152 → meshcode-2.11.153}/meshcode/meshcode_mcp/__init__.py +0 -0
  29. {meshcode-2.11.152 → meshcode-2.11.153}/meshcode/meshcode_mcp/__main__.py +0 -0
  30. {meshcode-2.11.152 → meshcode-2.11.153}/meshcode/meshcode_mcp/backend.py +0 -0
  31. {meshcode-2.11.152 → meshcode-2.11.153}/meshcode/meshcode_mcp/realtime.py +0 -0
  32. {meshcode-2.11.152 → meshcode-2.11.153}/meshcode/meshcode_mcp/server.py +0 -0
  33. {meshcode-2.11.152 → meshcode-2.11.153}/meshcode/meshcode_mcp/sleep_signals.py +0 -0
  34. {meshcode-2.11.152 → meshcode-2.11.153}/meshcode/meshcode_mcp/swarm.py +0 -0
  35. {meshcode-2.11.152 → meshcode-2.11.153}/meshcode/meshcode_mcp/test_backend.py +0 -0
  36. {meshcode-2.11.152 → meshcode-2.11.153}/meshcode/meshcode_mcp/test_boot_timing.py +0 -0
  37. {meshcode-2.11.152 → meshcode-2.11.153}/meshcode/meshcode_mcp/test_install_guard.py +0 -0
  38. {meshcode-2.11.152 → meshcode-2.11.153}/meshcode/meshcode_mcp/test_prefs_claude_version.py +0 -0
  39. {meshcode-2.11.152 → meshcode-2.11.153}/meshcode/meshcode_mcp/test_realtime.py +0 -0
  40. {meshcode-2.11.152 → meshcode-2.11.153}/meshcode/meshcode_mcp/test_server_wrapper.py +0 -0
  41. {meshcode-2.11.152 → meshcode-2.11.153}/meshcode/meshcode_mcp/test_swarm.py +0 -0
  42. {meshcode-2.11.152 → meshcode-2.11.153}/meshcode/preferences.py +0 -0
  43. {meshcode-2.11.152 → meshcode-2.11.153}/meshcode/protocol_v2.py +0 -0
  44. {meshcode-2.11.152 → meshcode-2.11.153}/meshcode/quickstart.py +0 -0
  45. {meshcode-2.11.152 → meshcode-2.11.153}/meshcode/rpc_allowlist.py +0 -0
  46. {meshcode-2.11.152 → meshcode-2.11.153}/meshcode/run_agent.py +0 -0
  47. {meshcode-2.11.152 → meshcode-2.11.153}/meshcode/scripts/check_secrets.py +0 -0
  48. {meshcode-2.11.152 → meshcode-2.11.153}/meshcode/scripts/race_rate_harness.py +0 -0
  49. {meshcode-2.11.152 → meshcode-2.11.153}/meshcode/secrets.py +0 -0
  50. {meshcode-2.11.152 → meshcode-2.11.153}/meshcode/self_update.py +0 -0
  51. {meshcode-2.11.152 → meshcode-2.11.153}/meshcode/setup_clients.py +0 -0
  52. {meshcode-2.11.152 → meshcode-2.11.153}/meshcode/supervisor.py +0 -0
  53. {meshcode-2.11.152 → meshcode-2.11.153}/meshcode/up.py +0 -0
  54. {meshcode-2.11.152 → meshcode-2.11.153}/meshcode/upload.py +0 -0
  55. {meshcode-2.11.152 → meshcode-2.11.153}/meshcode.egg-info/SOURCES.txt +0 -0
  56. {meshcode-2.11.152 → meshcode-2.11.153}/meshcode.egg-info/dependency_links.txt +0 -0
  57. {meshcode-2.11.152 → meshcode-2.11.153}/meshcode.egg-info/entry_points.txt +0 -0
  58. {meshcode-2.11.152 → meshcode-2.11.153}/meshcode.egg-info/requires.txt +0 -0
  59. {meshcode-2.11.152 → meshcode-2.11.153}/meshcode.egg-info/top_level.txt +0 -0
  60. {meshcode-2.11.152 → meshcode-2.11.153}/setup.cfg +0 -0
  61. {meshcode-2.11.152 → meshcode-2.11.153}/tests/test_auto_update_hardening.py +0 -0
  62. {meshcode-2.11.152 → meshcode-2.11.153}/tests/test_autonomous_closegap_1.py +0 -0
  63. {meshcode-2.11.152 → meshcode-2.11.153}/tests/test_autonomous_closegap_2.py +0 -0
  64. {meshcode-2.11.152 → meshcode-2.11.153}/tests/test_autonomous_closegap_3.py +0 -0
  65. {meshcode-2.11.152 → meshcode-2.11.153}/tests/test_autonomous_prompt_inject.py +0 -0
  66. {meshcode-2.11.152 → meshcode-2.11.153}/tests/test_boot_bug_regression.py +0 -0
  67. {meshcode-2.11.152 → meshcode-2.11.153}/tests/test_color_truecolor.py +0 -0
  68. {meshcode-2.11.152 → meshcode-2.11.153}/tests/test_core.py +0 -0
  69. {meshcode-2.11.152 → meshcode-2.11.153}/tests/test_cross_agent_messaging.py +0 -0
  70. {meshcode-2.11.152 → meshcode-2.11.153}/tests/test_date_parse.py +0 -0
  71. {meshcode-2.11.152 → meshcode-2.11.153}/tests/test_doctor.py +0 -0
  72. {meshcode-2.11.152 → meshcode-2.11.153}/tests/test_epistemic_v1_python_sdk.py +0 -0
  73. {meshcode-2.11.152 → meshcode-2.11.153}/tests/test_epistemic_v1_stop_conditions.py +0 -0
  74. {meshcode-2.11.152 → meshcode-2.11.153}/tests/test_esc_deaf_state.py +0 -0
  75. {meshcode-2.11.152 → meshcode-2.11.153}/tests/test_exceptions.py +0 -0
  76. {meshcode-2.11.152 → meshcode-2.11.153}/tests/test_file_upload.py +0 -0
  77. {meshcode-2.11.152 → meshcode-2.11.153}/tests/test_helper_visuals.py +0 -0
  78. {meshcode-2.11.152 → meshcode-2.11.153}/tests/test_hostd_launch_pinned_env.py +0 -0
  79. {meshcode-2.11.152 → meshcode-2.11.153}/tests/test_hostd_serve_discovery_split.py +0 -0
  80. {meshcode-2.11.152 → meshcode-2.11.153}/tests/test_hostd_zombie_sessions.py +0 -0
  81. {meshcode-2.11.152 → meshcode-2.11.153}/tests/test_init_device_code.py +0 -0
  82. {meshcode-2.11.152 → meshcode-2.11.153}/tests/test_install_guard.py +0 -0
  83. {meshcode-2.11.152 → meshcode-2.11.153}/tests/test_lease_sigterm_release.py +0 -0
  84. {meshcode-2.11.152 → meshcode-2.11.153}/tests/test_live_mesh_guard.py +0 -0
  85. {meshcode-2.11.152 → meshcode-2.11.153}/tests/test_mark_read_batch.py +0 -0
  86. {meshcode-2.11.152 → meshcode-2.11.153}/tests/test_marketplace_ratings.py +0 -0
  87. {meshcode-2.11.152 → meshcode-2.11.153}/tests/test_migration_integrity.py +0 -0
  88. {meshcode-2.11.152 → meshcode-2.11.153}/tests/test_pretrust_claude.py +0 -0
  89. {meshcode-2.11.152 → meshcode-2.11.153}/tests/test_realtime_event_freshness.py +0 -0
  90. {meshcode-2.11.152 → meshcode-2.11.153}/tests/test_rls_cross_tenant.py +0 -0
  91. {meshcode-2.11.152 → meshcode-2.11.153}/tests/test_rpc_grants.py +0 -0
  92. {meshcode-2.11.152 → meshcode-2.11.153}/tests/test_rpc_migrations.py +0 -0
  93. {meshcode-2.11.152 → meshcode-2.11.153}/tests/test_run_agent_dry_run.py +0 -0
  94. {meshcode-2.11.152 → meshcode-2.11.153}/tests/test_run_agent_no_server_import.py +0 -0
  95. {meshcode-2.11.152 → meshcode-2.11.153}/tests/test_security_regressions.py +0 -0
  96. {meshcode-2.11.152 → meshcode-2.11.153}/tests/test_self_update_user_site.py +0 -0
  97. {meshcode-2.11.152 → meshcode-2.11.153}/tests/test_sentinel.py +0 -0
  98. {meshcode-2.11.152 → meshcode-2.11.153}/tests/test_session_replay_gate.py +0 -0
  99. {meshcode-2.11.152 → meshcode-2.11.153}/tests/test_setup_path.py +0 -0
  100. {meshcode-2.11.152 → meshcode-2.11.153}/tests/test_sleep_signals.py +0 -0
  101. {meshcode-2.11.152 → meshcode-2.11.153}/tests/test_status_enum_coverage.py +0 -0
  102. {meshcode-2.11.152 → meshcode-2.11.153}/tests/test_stay_on_loop_hook.py +0 -0
  103. {meshcode-2.11.152 → meshcode-2.11.153}/tests/test_stop_ghost_terminal.py +0 -0
  104. {meshcode-2.11.152 → meshcode-2.11.153}/tests/test_swarm_events.py +0 -0
  105. {meshcode-2.11.152 → meshcode-2.11.153}/tests/test_task_progress.py +0 -0
  106. {meshcode-2.11.152 → meshcode-2.11.153}/tests/test_terminal_lifecycle.py +0 -0
  107. {meshcode-2.11.152 → meshcode-2.11.153}/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.152
3
+ Version: 2.11.153
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.152"
2
+ __version__ = "2.11.153"
3
3
 
4
4
  # Exception hierarchy — eagerly imported (lightweight, no deps)
5
5
  from meshcode.exceptions import ( # noqa: F401
@@ -272,30 +272,53 @@ def _tmux(tmux: str, *args: str) -> subprocess.CompletedProcess:
272
272
  return subprocess.run([tmux, *args], capture_output=True, text=True, timeout=15)
273
273
 
274
274
 
275
- def _fleet_wrap(cmd: str) -> str:
275
+ def _fleet_wrap(cmd: str, tmux: str = "tmux") -> str:
276
276
  """Shell line for an agent inside its tmux window.
277
277
 
278
- Drop the LAST `exec ` (same trick as the .command launcher) so the shell
279
- survives the agent's exit and can translate rc 143 (SIGTERM = hostd
280
- stop/ghost-kill, task 91201315: that's the job FINISHING) to 0 otherwise
281
- `remain-on-exit failed` would keep a dead pane for every plain Stop.
282
-
283
- CLOSE-TAB=STOP (task 4df5a126, Samuel 68b1c17b: "cierro su terminal y
284
- ya"): export MESHCODE_CLOSE_STOP_SIGHUP=1 so the MCP server's gated POSIX
285
- close=stop handler (b6da0d54, default OFF) arms INSIDE fleet tabs only.
286
- In a tmux pane SIGHUP is unambiguous only kill-window / kill-session /
287
- tmux-server death close the pty (a window-close of the shared Terminal
288
- just DETACHES; ESC never closes the pty) so the false-stop risk that
289
- kept the flag off for plain windows (task dfa17461) does not exist here.
290
- Right-click a tab -> Kill => SIGHUP => agent flips desired_state=stopped
291
- server-side and exits clean: offline, NO hostd ghost-respawn (mig 494
292
- coherent). A real crash never runs the handler => crash-respawn intact."""
278
+ RAII / opener-owns-teardown (Samuel P0 'vergo de terminales' professional
279
+ supervisor pattern, NOT a patch): this wrapper OWNS its tmux window and an
280
+ EXIT+signal trap closes THAT window whenever the agent process diesclean
281
+ stop, recycle-exit, OR crash so a dead pane never lingers and accumulates
282
+ (459 spawns vs 0 closes / 18 days -> ~50 stale tabs). It self-targets via
283
+ $TMUX_PANE, so it can only EVER close its OWN window — never a live sibling's
284
+ (the 'never close a live agent' guardrail is structural here: the trap fires
285
+ only when THIS agent already exited). Replaces the old
286
+ `remain-on-exit=failed keeps the dead pane for debugging` behavior, which was
287
+ the accumulation source. rc 143 (SIGTERM = clean hostd stop, task 91201315)
288
+ and clean exits close silently; a crash rc is logged to stderr first.
289
+
290
+ Kill-switch env MESHCODE_FLEET_WINDOW_CLOSE: `0`/`off` restores the old
291
+ keep-dead-tab-for-debugging behavior; `dry`/`dryrun` logs intent without
292
+ closing.
293
+
294
+ Drops the LAST `exec ` (same trick as the .command launcher) so the shell
295
+ SURVIVES the agent's exit and the trap can run. CLOSE-TAB=STOP (task
296
+ 4df5a126, Samuel 68b1c17b): export MESHCODE_CLOSE_STOP_SIGHUP=1 so the MCP
297
+ server's gated POSIX close=stop handler arms INSIDE fleet tabs (right-click
298
+ tab -> Kill => SIGHUP => agent flips desired_state=stopped + exits clean, no
299
+ hostd ghost-respawn). A real crash still respawns (hostd, DB-driven) —
300
+ closing the crashed tab just means the respawn opens a fresh one."""
293
301
  if "exec " in cmd:
294
302
  head, _, tail = cmd.rpartition("exec ")
295
303
  cmd = head + tail
296
- return (f'export MESHCODE_CLOSE_STOP_SIGHUP=1; '
297
- f'{cmd}; MC_RC=$?; if [ "$MC_RC" = "143" ]; then exit 0; fi; '
298
- f'echo "[meshcode] agent exited rc=$MC_RC — tab kept for debugging"; exit $MC_RC')
304
+ tq = shlex.quote(tmux)
305
+ return (
306
+ 'export MESHCODE_CLOSE_STOP_SIGHUP=1; '
307
+ # RAII teardown: close OUR OWN tmux window on ANY exit/signal. $TMUX_PANE
308
+ # is set by tmux for the pane we run in, so kill-window can only ever hit
309
+ # THIS window. Disarm traps first (avoid double-run via the EXIT trap).
310
+ '_mc_close() { _rc=$?; trap - EXIT INT TERM HUP; '
311
+ 'case "${MESHCODE_FLEET_WINDOW_CLOSE:-}" in '
312
+ '0|off|false|no) exit "$_rc";; '
313
+ 'dry|dryrun|dry-run) echo "[meshcode] DRY-RUN: would close own tab (rc=$_rc)" >&2; exit "$_rc";; '
314
+ 'esac; '
315
+ '{ [ "$_rc" != "0" ] && [ "$_rc" != "143" ]; } && '
316
+ 'echo "[meshcode] agent exited rc=$_rc — closing tab (1 agent = 1 terminal)" >&2; '
317
+ f'{tq} kill-window -t "${{TMUX_PANE:-}}" 2>/dev/null; '
318
+ 'exit "$_rc"; }; '
319
+ 'trap _mc_close EXIT INT TERM HUP; '
320
+ f'{cmd}'
321
+ )
299
322
 
300
323
 
301
324
  def _fleet_attach_macos(tmux: str) -> tuple[bool, str]:
@@ -360,7 +383,7 @@ def _spawn_fleet_tab(cmd: str) -> tuple[bool, str]:
360
383
  if not tmux:
361
384
  return False, "tmux not installed (brew install tmux -> tabbed fleet window)"
362
385
  label = _fleet_tab_name(cmd)
363
- wrapped = _fleet_wrap(cmd)
386
+ wrapped = _fleet_wrap(cmd, tmux)
364
387
  try:
365
388
  fresh_session = _tmux(tmux, "has-session", "-t", f"={_FLEET_SESSION}").returncode != 0
366
389
  win_id = ""
@@ -684,10 +707,20 @@ def _write_fleet_native_agent(cmd: str) -> Path:
684
707
  "disown",
685
708
  run_line,
686
709
  "MC_RC=$?",
687
- # clean exit (0, or 143 = hostd stop sweep): close ONLY this tab.
688
- # Crash: keep tab + scrollback (debugging > clean window).
689
- 'if { [ "$MC_RC" = "0" ] || [ "$MC_RC" = "143" ]; } && [ -n "$MC_TTY" ]; then',
690
- " /usr/bin/osascript"
710
+ # RAII / opener-owns-teardown (Samuel P0 'vergo de terminales'
711
+ # professional pattern): close OUR OWN native tab on ANY exit clean
712
+ # stop, recycle-exit, OR crash so a dead tab never accumulates (Ian's
713
+ # ~40 stale native tabs). The osascript self-targets by MC_TTY (closes
714
+ # ONLY the tab whose tty is ours) so a LIVE sibling is never touched.
715
+ # Replaces the old keep-crashed-tab-for-debugging behavior. Kill-switch
716
+ # MESHCODE_FLEET_WINDOW_CLOSE=0 restores it; =dry logs intent.
717
+ 'case "${MESHCODE_FLEET_WINDOW_CLOSE:-}" in',
718
+ ' 0|off|false|no) { [ "$MC_RC" != "0" ] && [ "$MC_RC" != "143" ]; } && echo "[meshcode] agent exited rc=$MC_RC — tab kept (close disabled)" ;;',
719
+ ' dry|dryrun|dry-run) echo "[meshcode] DRY-RUN: would close own tab (rc=$MC_RC)" ;;',
720
+ ' *)',
721
+ ' { [ "$MC_RC" != "0" ] && [ "$MC_RC" != "143" ]; } && echo "[meshcode] agent exited rc=$MC_RC — closing tab (1 agent = 1 terminal)"',
722
+ ' if [ -n "$MC_TTY" ]; then',
723
+ " /usr/bin/osascript"
691
724
  " -e 'on run argv'"
692
725
  " -e 'tell application \"Terminal\"'"
693
726
  " -e 'repeat with w in windows'"
@@ -699,9 +732,9 @@ def _write_fleet_native_agent(cmd: str) -> Path:
699
732
  " -e 'end repeat'"
700
733
  " -e 'end tell'"
701
734
  " -e 'end run' \"$MC_TTY\" >/dev/null 2>&1",
702
- "else",
703
- ' echo "[meshcode] agent exited rc=$MC_RC — tab kept for debugging"',
704
- "fi",
735
+ ' fi',
736
+ ' ;;',
737
+ 'esac',
705
738
  ]
706
739
  p["dir"].mkdir(parents=True, exist_ok=True)
707
740
  script_path.write_text("\n".join(lines) + "\n", encoding="utf-8")
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.4
2
2
  Name: meshcode
3
- Version: 2.11.152
3
+ Version: 2.11.153
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.152"
7
+ version = "2.11.153"
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