meshcode 2.10.53__tar.gz → 2.10.54__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.53 → meshcode-2.10.54}/PKG-INFO +1 -1
  2. {meshcode-2.10.53 → meshcode-2.10.54}/meshcode/__init__.py +1 -1
  3. {meshcode-2.10.53 → meshcode-2.10.54}/meshcode/meshcode_mcp/server.py +119 -4
  4. {meshcode-2.10.53 → meshcode-2.10.54}/meshcode.egg-info/PKG-INFO +1 -1
  5. {meshcode-2.10.53 → meshcode-2.10.54}/pyproject.toml +1 -1
  6. {meshcode-2.10.53 → meshcode-2.10.54}/README.md +0 -0
  7. {meshcode-2.10.53 → meshcode-2.10.54}/meshcode/ascii_art.py +0 -0
  8. {meshcode-2.10.53 → meshcode-2.10.54}/meshcode/cli.py +0 -0
  9. {meshcode-2.10.53 → meshcode-2.10.54}/meshcode/comms_v4.py +0 -0
  10. {meshcode-2.10.53 → meshcode-2.10.54}/meshcode/invites.py +0 -0
  11. {meshcode-2.10.53 → meshcode-2.10.54}/meshcode/launcher.py +0 -0
  12. {meshcode-2.10.53 → meshcode-2.10.54}/meshcode/launcher_install.py +0 -0
  13. {meshcode-2.10.53 → meshcode-2.10.54}/meshcode/meshcode_mcp/__init__.py +0 -0
  14. {meshcode-2.10.53 → meshcode-2.10.54}/meshcode/meshcode_mcp/__main__.py +0 -0
  15. {meshcode-2.10.53 → meshcode-2.10.54}/meshcode/meshcode_mcp/backend.py +0 -0
  16. {meshcode-2.10.53 → meshcode-2.10.54}/meshcode/meshcode_mcp/realtime.py +0 -0
  17. {meshcode-2.10.53 → meshcode-2.10.54}/meshcode/meshcode_mcp/test_backend.py +0 -0
  18. {meshcode-2.10.53 → meshcode-2.10.54}/meshcode/meshcode_mcp/test_realtime.py +0 -0
  19. {meshcode-2.10.53 → meshcode-2.10.54}/meshcode/meshcode_mcp/test_server_wrapper.py +0 -0
  20. {meshcode-2.10.53 → meshcode-2.10.54}/meshcode/preferences.py +0 -0
  21. {meshcode-2.10.53 → meshcode-2.10.54}/meshcode/protocol_v2.py +0 -0
  22. {meshcode-2.10.53 → meshcode-2.10.54}/meshcode/run_agent.py +0 -0
  23. {meshcode-2.10.53 → meshcode-2.10.54}/meshcode/secrets.py +0 -0
  24. {meshcode-2.10.53 → meshcode-2.10.54}/meshcode/self_update.py +0 -0
  25. {meshcode-2.10.53 → meshcode-2.10.54}/meshcode/setup_clients.py +0 -0
  26. {meshcode-2.10.53 → meshcode-2.10.54}/meshcode.egg-info/SOURCES.txt +0 -0
  27. {meshcode-2.10.53 → meshcode-2.10.54}/meshcode.egg-info/dependency_links.txt +0 -0
  28. {meshcode-2.10.53 → meshcode-2.10.54}/meshcode.egg-info/entry_points.txt +0 -0
  29. {meshcode-2.10.53 → meshcode-2.10.54}/meshcode.egg-info/requires.txt +0 -0
  30. {meshcode-2.10.53 → meshcode-2.10.54}/meshcode.egg-info/top_level.txt +0 -0
  31. {meshcode-2.10.53 → meshcode-2.10.54}/setup.cfg +0 -0
  32. {meshcode-2.10.53 → meshcode-2.10.54}/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.53
3
+ Version: 2.10.54
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.53"
2
+ __version__ = "2.10.54"
@@ -721,6 +721,52 @@ def with_working_status(func):
721
721
  # to prevent cascade through FastMCP into the event loop.
722
722
  # Return an error dict instead of propagating BaseException.
723
723
  log.debug(f"[meshcode] tool {name} cancelled by client (ESC)")
724
+ # 2.10.54 deaf-agent fix: for meshcode_wait specifically, the
725
+ # inner cancel handler already tries to drain pending messages.
726
+ # If we still got CancelledError here, the inner drain failed —
727
+ # do a last-ditch DB read so the LLM sees pending mail instead
728
+ # of a generic error and goes silent.
729
+ if name == "meshcode_wait":
730
+ try:
731
+ _t = asyncio.current_task()
732
+ if _t is not None and hasattr(_t, "uncancel"):
733
+ _t.uncancel()
734
+ except Exception:
735
+ pass
736
+ try:
737
+ _ak = _get_api_key()
738
+ if _ak:
739
+ _raw = be.read_inbox(
740
+ _PROJECT_ID, AGENT_NAME, mark_read=True, api_key=_ak
741
+ )
742
+ if _raw:
743
+ _msgs = [
744
+ {
745
+ "from": m["from_agent"],
746
+ "type": m.get("type", "msg"),
747
+ "ts": m.get("created_at"),
748
+ "payload": m.get("payload", {}),
749
+ "id": m.get("id"),
750
+ "parent_id": m.get("parent_msg_id"),
751
+ }
752
+ for m in _raw
753
+ ]
754
+ _filter_and_mark(_msgs)
755
+ _split = _split_messages(_msgs)
756
+ if _split["messages"] or _split["done_signals"]:
757
+ log.info(
758
+ f"[meshcode] wrapper-level cancel-drain rescued "
759
+ f"{_split['count']} messages"
760
+ )
761
+ return {
762
+ "got_message": True,
763
+ "cancelled_during_wait": True,
764
+ **_split,
765
+ }
766
+ except Exception as _final_err:
767
+ log.debug(
768
+ f"[meshcode] wrapper cancel-drain failed: {_final_err}"
769
+ )
724
770
  return {"error": "cancelled_by_client", "tool": name}
725
771
  except Exception as e:
726
772
  if not skip:
@@ -2120,10 +2166,79 @@ async def meshcode_wait(timeout_seconds: int = 20, include_acks: bool = False) -
2120
2166
  try:
2121
2167
  result = await _meshcode_wait_inner(actual_timeout=capped_timeout, include_acks=include_acks)
2122
2168
  except asyncio.CancelledError:
2123
- # Safety net: if CancelledError escapes _meshcode_wait_inner
2124
- # despite the inner shield, catch it here to prevent cascade.
2125
- log.debug("[meshcode] meshcode_wait outer loop caught CancelledError")
2126
- result = {"timed_out": True, "reason": "cancelled_by_client"}
2169
+ # 2.10.54 deaf-agent fix: when ESC fires during meshcode_wait,
2170
+ # Python keeps the task in cancelled state every subsequent
2171
+ # await re-raises CancelledError, even if we caught the first
2172
+ # one. That trapped us in a loop that eventually returned
2173
+ # `{"error": "cancelled_by_client"}` to the LLM, which never
2174
+ # saw the messages that arrived during the cancel window —
2175
+ # they sat in the queue/DB unread (the "deaf agents" bug).
2176
+ #
2177
+ # Fix: uncancel the current task so we can run a final drain
2178
+ # cycle without re-raising. Then aggressively pull from BOTH
2179
+ # the realtime buffer AND the DB and return whatever we find
2180
+ # to the LLM. If nothing is pending, return cancelled-timeout
2181
+ # cleanly so the LLM's wait loop continues normally.
2182
+ log.info("[meshcode] meshcode_wait caught CancelledError — uncancelling + final drain")
2183
+ try:
2184
+ _t = asyncio.current_task()
2185
+ if _t is not None and hasattr(_t, "uncancel"):
2186
+ _t.uncancel()
2187
+ except Exception:
2188
+ pass
2189
+
2190
+ _final_msgs: List[Dict[str, Any]] = []
2191
+ # 1) Drain realtime buffer (messages received during cancel window)
2192
+ if _REALTIME:
2193
+ try:
2194
+ _rt_buf = _REALTIME.drain()
2195
+ if _rt_buf:
2196
+ _final_msgs.extend(_rt_buf)
2197
+ except Exception as _drain_err:
2198
+ log.debug(f"[meshcode] cancel-drain realtime failed: {_drain_err}")
2199
+ # 2) Pull from DB (catches messages realtime missed)
2200
+ try:
2201
+ _api_key = _get_api_key()
2202
+ if _api_key:
2203
+ _db_unread = be.read_inbox(
2204
+ _PROJECT_ID, AGENT_NAME, mark_read=True, api_key=_api_key
2205
+ )
2206
+ if _db_unread:
2207
+ _final_msgs.extend([
2208
+ {
2209
+ "from": m["from_agent"],
2210
+ "type": m.get("type", "msg"),
2211
+ "ts": m.get("created_at"),
2212
+ "payload": m.get("payload", {}),
2213
+ "id": m.get("id"),
2214
+ "parent_id": m.get("parent_msg_id"),
2215
+ }
2216
+ for m in _db_unread
2217
+ ])
2218
+ except Exception as _db_err:
2219
+ log.debug(f"[meshcode] cancel-drain DB failed: {_db_err}")
2220
+
2221
+ if _final_msgs:
2222
+ # Dedupe + filter, then return as got_message so the LLM
2223
+ # processes them instead of seeing a generic cancel error.
2224
+ _filter_and_mark(_final_msgs)
2225
+ _split = _split_messages(_final_msgs)
2226
+ if not include_acks:
2227
+ _split["acks"] = []
2228
+ if _split["messages"] or _split["done_signals"]:
2229
+ log.info(
2230
+ f"[meshcode] cancel-drain rescued {_split['count']} pending "
2231
+ f"messages from going deaf"
2232
+ )
2233
+ result = {
2234
+ "got_message": True,
2235
+ "cancelled_during_wait": True,
2236
+ **_split,
2237
+ }
2238
+ else:
2239
+ result = {"timed_out": True, "reason": "cancelled_by_client"}
2240
+ else:
2241
+ result = {"timed_out": True, "reason": "cancelled_by_client"}
2127
2242
 
2128
2243
  if result.get("got_message"):
2129
2244
  # Real message arrived — return to agent for processing
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.4
2
2
  Name: meshcode
3
- Version: 2.10.53
3
+ Version: 2.10.54
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.53"
7
+ version = "2.10.54"
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