meshcode 2.10.26__tar.gz → 2.10.28__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 (32) hide show
  1. {meshcode-2.10.26 → meshcode-2.10.28}/PKG-INFO +1 -1
  2. {meshcode-2.10.26 → meshcode-2.10.28}/meshcode/__init__.py +1 -1
  3. {meshcode-2.10.26 → meshcode-2.10.28}/meshcode/meshcode_mcp/server.py +45 -20
  4. {meshcode-2.10.26 → meshcode-2.10.28}/meshcode.egg-info/PKG-INFO +1 -1
  5. {meshcode-2.10.26 → meshcode-2.10.28}/pyproject.toml +1 -1
  6. {meshcode-2.10.26 → meshcode-2.10.28}/README.md +0 -0
  7. {meshcode-2.10.26 → meshcode-2.10.28}/meshcode/ascii_art.py +0 -0
  8. {meshcode-2.10.26 → meshcode-2.10.28}/meshcode/cli.py +0 -0
  9. {meshcode-2.10.26 → meshcode-2.10.28}/meshcode/comms_v4.py +0 -0
  10. {meshcode-2.10.26 → meshcode-2.10.28}/meshcode/invites.py +0 -0
  11. {meshcode-2.10.26 → meshcode-2.10.28}/meshcode/launcher.py +0 -0
  12. {meshcode-2.10.26 → meshcode-2.10.28}/meshcode/launcher_install.py +0 -0
  13. {meshcode-2.10.26 → meshcode-2.10.28}/meshcode/meshcode_mcp/__init__.py +0 -0
  14. {meshcode-2.10.26 → meshcode-2.10.28}/meshcode/meshcode_mcp/__main__.py +0 -0
  15. {meshcode-2.10.26 → meshcode-2.10.28}/meshcode/meshcode_mcp/backend.py +0 -0
  16. {meshcode-2.10.26 → meshcode-2.10.28}/meshcode/meshcode_mcp/realtime.py +0 -0
  17. {meshcode-2.10.26 → meshcode-2.10.28}/meshcode/meshcode_mcp/test_backend.py +0 -0
  18. {meshcode-2.10.26 → meshcode-2.10.28}/meshcode/meshcode_mcp/test_realtime.py +0 -0
  19. {meshcode-2.10.26 → meshcode-2.10.28}/meshcode/meshcode_mcp/test_server_wrapper.py +0 -0
  20. {meshcode-2.10.26 → meshcode-2.10.28}/meshcode/preferences.py +0 -0
  21. {meshcode-2.10.26 → meshcode-2.10.28}/meshcode/protocol_v2.py +0 -0
  22. {meshcode-2.10.26 → meshcode-2.10.28}/meshcode/run_agent.py +0 -0
  23. {meshcode-2.10.26 → meshcode-2.10.28}/meshcode/secrets.py +0 -0
  24. {meshcode-2.10.26 → meshcode-2.10.28}/meshcode/self_update.py +0 -0
  25. {meshcode-2.10.26 → meshcode-2.10.28}/meshcode/setup_clients.py +0 -0
  26. {meshcode-2.10.26 → meshcode-2.10.28}/meshcode.egg-info/SOURCES.txt +0 -0
  27. {meshcode-2.10.26 → meshcode-2.10.28}/meshcode.egg-info/dependency_links.txt +0 -0
  28. {meshcode-2.10.26 → meshcode-2.10.28}/meshcode.egg-info/entry_points.txt +0 -0
  29. {meshcode-2.10.26 → meshcode-2.10.28}/meshcode.egg-info/requires.txt +0 -0
  30. {meshcode-2.10.26 → meshcode-2.10.28}/meshcode.egg-info/top_level.txt +0 -0
  31. {meshcode-2.10.26 → meshcode-2.10.28}/setup.cfg +0 -0
  32. {meshcode-2.10.26 → meshcode-2.10.28}/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.26
3
+ Version: 2.10.28
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,2 +1,2 @@
1
1
  """MeshCode — Real-time communication between AI agents."""
2
- __version__ = "2.10.26"
2
+ __version__ = "2.10.28"
@@ -105,8 +105,12 @@ _SEEN_MSG_CAP = 1000
105
105
  # DEFAULT: ON. Disable with MESHCODE_AUTO_WAKE=0 if you don't want it.
106
106
  # ============================================================
107
107
  _IN_WAIT = False # True while meshcode_wait is blocking
108
- # Default ONopt-out via MESHCODE_AUTO_WAKE=0/false/no
109
- _AUTO_WAKE = os.environ.get("MESHCODE_AUTO_WAKE", "1").lower() not in ("0", "false", "no")
108
+ # Default OFF as of 2.10.27 the AppleScript/PowerShell keystroke injection
109
+ # wrote nudge text directly into the user's terminal, which corrupts stdin on
110
+ # terminals that don't interpret ANSI, interrupts the user mid-typing, and
111
+ # duplicates what the dashboard already surfaces. Opt-in with
112
+ # MESHCODE_AUTO_WAKE=1 for users who want the legacy behavior.
113
+ _AUTO_WAKE = os.environ.get("MESHCODE_AUTO_WAKE", "0").lower() in ("1", "true", "yes")
110
114
 
111
115
 
112
116
  def _try_auto_wake(from_agent: str, preview: str) -> None:
@@ -2807,24 +2811,45 @@ def run_server():
2807
2811
  # accidental stdout writes from corrupting the MCP protocol.
2808
2812
  sys.stdout = _REAL_STDOUT
2809
2813
 
2810
- # Claude Code cancels tool calls on ESC via TWO parallel channels:
2811
- # (1) JSON-RPC `notifications/cancelled` over stdin (the correct path)
2812
- # (2) SIGINT to the stdio subprocess (a destructive side-channel)
2813
- # anyio's asyncio backend installs its own SIGINT handler inside
2814
- # Runner.run() only if the current handler is `default_int_handler`
2815
- # (see anyio/_backends/_asyncio.py ~L197-210). That handler cancels the
2816
- # *main task* which for a stdio server IS the whole server run —
2817
- # tearing the event loop down and killing the subprocess. Setting
2818
- # SIG_IGN before mcp.run() trips anyio's guard, so it leaves SIGINT
2819
- # alone; the kernel drops the signal; only the notifications/cancelled
2820
- # path remains, which cancels just the in-flight tool call as intended.
2821
- # SIGTERM is deliberately untouched so Claude Code can still force-shut
2822
- # the server on session end. stdin EOF remains the normal exit path.
2814
+ # Claude Code cancels tool calls on ESC via multiple side channels that
2815
+ # are destructive to the stdio subprocess. 2.10.26's SIG_IGN-on-SIGINT
2816
+ # fix was incomplete in the wild (2.10.27 field test died anyway), so we
2817
+ # widen the net: ignore every signal Claude Code is known to send on
2818
+ # cancellation and log any that arrive so we can see what actually fires.
2819
+ #
2820
+ # SIGINT kernel default: terminate. asyncio Runner also installs a
2821
+ # cancel-main-task handler, but only if the current handler is
2822
+ # default_int_handler; SIG_IGN here trips that guard.
2823
+ # SIGTERM kernel default: terminate. Some Claude Code versions send
2824
+ # this after SIGINT if the subprocess didn't exit fast enough.
2825
+ # SIGHUP — kernel default: terminate. Sent when the controlling tty
2826
+ # detaches or the parent process restructures its session.
2827
+ # SIGPIPE — kernel default: terminate. Fires when Claude Code closes its
2828
+ # side of stdout while we're mid-write. Ignoring makes the
2829
+ # write fail with EPIPE instead of killing us.
2830
+ #
2831
+ # SIGKILL and SIGSTOP cannot be caught — that is how the process is
2832
+ # meant to be forcibly stopped (`kill -9 <pid>` still works). stdin EOF
2833
+ # is untouched and remains the clean-shutdown signal for session end.
2823
2834
  import signal
2824
- try:
2825
- signal.signal(signal.SIGINT, signal.SIG_IGN)
2826
- except (ValueError, OSError):
2827
- # Non-main thread or platform that can't install handlers — harmless.
2828
- pass
2835
+ def _diag_ignore(signum, frame): # pragma: no cover - signal handler
2836
+ try:
2837
+ name = signal.Signals(signum).name
2838
+ except Exception:
2839
+ name = f"signal-{signum}"
2840
+ try:
2841
+ sys.stderr.write(f"[meshcode-mcp] received {name} ({signum}); ignored to keep MCP alive during tool cancellation\n")
2842
+ sys.stderr.flush()
2843
+ except Exception:
2844
+ pass
2845
+ for _sig_name in ("SIGINT", "SIGTERM", "SIGHUP", "SIGPIPE"):
2846
+ _sig = getattr(signal, _sig_name, None)
2847
+ if _sig is None:
2848
+ continue
2849
+ try:
2850
+ signal.signal(_sig, _diag_ignore)
2851
+ except (ValueError, OSError):
2852
+ # Non-main thread or Windows doesn't expose the signal — harmless.
2853
+ pass
2829
2854
 
2830
2855
  mcp.run()
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.4
2
2
  Name: meshcode
3
- Version: 2.10.26
3
+ Version: 2.10.28
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.10.26"
7
+ version = "2.10.28"
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