meshcode 2.11.1__tar.gz → 2.11.3__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 (208) hide show
  1. {meshcode-2.11.1 → meshcode-2.11.3}/PKG-INFO +1 -1
  2. {meshcode-2.11.1 → meshcode-2.11.3}/meshcode/__init__.py +1 -1
  3. {meshcode-2.11.1 → meshcode-2.11.3}/meshcode/_stop_hook_template.py +49 -40
  4. {meshcode-2.11.1 → meshcode-2.11.3}/meshcode/meshcode_mcp/server.py +68 -54
  5. {meshcode-2.11.1 → meshcode-2.11.3}/meshcode.egg-info/PKG-INFO +1 -1
  6. {meshcode-2.11.1 → meshcode-2.11.3}/pyproject.toml +1 -1
  7. {meshcode-2.11.1 → meshcode-2.11.3}/README.md +0 -0
  8. {meshcode-2.11.1 → meshcode-2.11.3}/meshcode/ascii_art.py +0 -0
  9. {meshcode-2.11.1 → meshcode-2.11.3}/meshcode/cli.py +0 -0
  10. {meshcode-2.11.1 → meshcode-2.11.3}/meshcode/comms_v4.py +0 -0
  11. {meshcode-2.11.1 → meshcode-2.11.3}/meshcode/compat.py +0 -0
  12. {meshcode-2.11.1 → meshcode-2.11.3}/meshcode/daemon.py +0 -0
  13. {meshcode-2.11.1 → meshcode-2.11.3}/meshcode/error_hints.py +0 -0
  14. {meshcode-2.11.1 → meshcode-2.11.3}/meshcode/exceptions.py +0 -0
  15. {meshcode-2.11.1 → meshcode-2.11.3}/meshcode/invites.py +0 -0
  16. {meshcode-2.11.1 → meshcode-2.11.3}/meshcode/launcher.py +0 -0
  17. {meshcode-2.11.1 → meshcode-2.11.3}/meshcode/launcher_install.py +0 -0
  18. {meshcode-2.11.1 → meshcode-2.11.3}/meshcode/meshcode_mcp/__init__.py +0 -0
  19. {meshcode-2.11.1 → meshcode-2.11.3}/meshcode/meshcode_mcp/__main__.py +0 -0
  20. {meshcode-2.11.1 → meshcode-2.11.3}/meshcode/meshcode_mcp/backend.py +0 -0
  21. {meshcode-2.11.1 → meshcode-2.11.3}/meshcode/meshcode_mcp/realtime.py +0 -0
  22. {meshcode-2.11.1 → meshcode-2.11.3}/meshcode/meshcode_mcp/test_backend.py +0 -0
  23. {meshcode-2.11.1 → meshcode-2.11.3}/meshcode/meshcode_mcp/test_realtime.py +0 -0
  24. {meshcode-2.11.1 → meshcode-2.11.3}/meshcode/meshcode_mcp/test_server_wrapper.py +0 -0
  25. {meshcode-2.11.1 → meshcode-2.11.3}/meshcode/preferences.py +0 -0
  26. {meshcode-2.11.1 → meshcode-2.11.3}/meshcode/protocol_handler.py +0 -0
  27. {meshcode-2.11.1 → meshcode-2.11.3}/meshcode/protocol_v2.py +0 -0
  28. {meshcode-2.11.1 → meshcode-2.11.3}/meshcode/quickstart.py +0 -0
  29. {meshcode-2.11.1 → meshcode-2.11.3}/meshcode/run_agent.py +0 -0
  30. {meshcode-2.11.1 → meshcode-2.11.3}/meshcode/scripts/check_secrets.py +0 -0
  31. {meshcode-2.11.1 → meshcode-2.11.3}/meshcode/scripts/race_rate_harness.py +0 -0
  32. {meshcode-2.11.1 → meshcode-2.11.3}/meshcode/secrets.py +0 -0
  33. {meshcode-2.11.1 → meshcode-2.11.3}/meshcode/self_update.py +0 -0
  34. {meshcode-2.11.1 → meshcode-2.11.3}/meshcode/setup_clients.py +0 -0
  35. {meshcode-2.11.1 → meshcode-2.11.3}/meshcode/supervisor.py +0 -0
  36. {meshcode-2.11.1 → meshcode-2.11.3}/meshcode/upload.py +0 -0
  37. {meshcode-2.11.1 → meshcode-2.11.3}/meshcode-backend-wt/comms_v4.py +0 -0
  38. {meshcode-2.11.1 → meshcode-2.11.3}/meshcode-backend-wt/meshcode/__init__.py +0 -0
  39. {meshcode-2.11.1 → meshcode-2.11.3}/meshcode-backend-wt/meshcode/ascii_art.py +0 -0
  40. {meshcode-2.11.1 → meshcode-2.11.3}/meshcode-backend-wt/meshcode/cli.py +0 -0
  41. {meshcode-2.11.1 → meshcode-2.11.3}/meshcode-backend-wt/meshcode/comms_v4.py +0 -0
  42. {meshcode-2.11.1 → meshcode-2.11.3}/meshcode-backend-wt/meshcode/compat.py +0 -0
  43. {meshcode-2.11.1 → meshcode-2.11.3}/meshcode-backend-wt/meshcode/error_hints.py +0 -0
  44. {meshcode-2.11.1 → meshcode-2.11.3}/meshcode-backend-wt/meshcode/exceptions.py +0 -0
  45. {meshcode-2.11.1 → meshcode-2.11.3}/meshcode-backend-wt/meshcode/invites.py +0 -0
  46. {meshcode-2.11.1 → meshcode-2.11.3}/meshcode-backend-wt/meshcode/launcher.py +0 -0
  47. {meshcode-2.11.1 → meshcode-2.11.3}/meshcode-backend-wt/meshcode/launcher_install.py +0 -0
  48. {meshcode-2.11.1 → meshcode-2.11.3}/meshcode-backend-wt/meshcode/meshcode_mcp/__init__.py +0 -0
  49. {meshcode-2.11.1 → meshcode-2.11.3}/meshcode-backend-wt/meshcode/meshcode_mcp/__main__.py +0 -0
  50. {meshcode-2.11.1 → meshcode-2.11.3}/meshcode-backend-wt/meshcode/meshcode_mcp/backend.py +0 -0
  51. {meshcode-2.11.1 → meshcode-2.11.3}/meshcode-backend-wt/meshcode/meshcode_mcp/realtime.py +0 -0
  52. {meshcode-2.11.1 → meshcode-2.11.3}/meshcode-backend-wt/meshcode/meshcode_mcp/server.py +0 -0
  53. {meshcode-2.11.1 → meshcode-2.11.3}/meshcode-backend-wt/meshcode/meshcode_mcp/test_backend.py +0 -0
  54. {meshcode-2.11.1 → meshcode-2.11.3}/meshcode-backend-wt/meshcode/meshcode_mcp/test_realtime.py +0 -0
  55. {meshcode-2.11.1 → meshcode-2.11.3}/meshcode-backend-wt/meshcode/meshcode_mcp/test_server_wrapper.py +0 -0
  56. {meshcode-2.11.1 → meshcode-2.11.3}/meshcode-backend-wt/meshcode/preferences.py +0 -0
  57. {meshcode-2.11.1 → meshcode-2.11.3}/meshcode-backend-wt/meshcode/protocol_v2.py +0 -0
  58. {meshcode-2.11.1 → meshcode-2.11.3}/meshcode-backend-wt/meshcode/quickstart.py +0 -0
  59. {meshcode-2.11.1 → meshcode-2.11.3}/meshcode-backend-wt/meshcode/run_agent.py +0 -0
  60. {meshcode-2.11.1 → meshcode-2.11.3}/meshcode-backend-wt/meshcode/secrets.py +0 -0
  61. {meshcode-2.11.1 → meshcode-2.11.3}/meshcode-backend-wt/meshcode/self_update.py +0 -0
  62. {meshcode-2.11.1 → meshcode-2.11.3}/meshcode-backend-wt/meshcode/setup_clients.py +0 -0
  63. {meshcode-2.11.1 → meshcode-2.11.3}/meshcode-backend-wt/meshcode/supervisor.py +0 -0
  64. {meshcode-2.11.1 → meshcode-2.11.3}/meshcode-backend-wt/meshcode/upload.py +0 -0
  65. {meshcode-2.11.1 → meshcode-2.11.3}/meshcode-backend-wt/scripts/sentinel.py +0 -0
  66. {meshcode-2.11.1 → meshcode-2.11.3}/meshcode-backend-wt/tests/test_core.py +0 -0
  67. {meshcode-2.11.1 → meshcode-2.11.3}/meshcode-backend-wt/tests/test_cross_agent_messaging.py +0 -0
  68. {meshcode-2.11.1 → meshcode-2.11.3}/meshcode-backend-wt/tests/test_esc_deaf_state.py +0 -0
  69. {meshcode-2.11.1 → meshcode-2.11.3}/meshcode-backend-wt/tests/test_exceptions.py +0 -0
  70. {meshcode-2.11.1 → meshcode-2.11.3}/meshcode-backend-wt/tests/test_mark_read_batch.py +0 -0
  71. {meshcode-2.11.1 → meshcode-2.11.3}/meshcode-backend-wt/tests/test_migration_integrity.py +0 -0
  72. {meshcode-2.11.1 → meshcode-2.11.3}/meshcode-backend-wt/tests/test_realtime_event_freshness.py +0 -0
  73. {meshcode-2.11.1 → meshcode-2.11.3}/meshcode-backend-wt/tests/test_rls_cross_tenant.py +0 -0
  74. {meshcode-2.11.1 → meshcode-2.11.3}/meshcode-backend-wt/tests/test_rpc_migrations.py +0 -0
  75. {meshcode-2.11.1 → meshcode-2.11.3}/meshcode-backend-wt/tests/test_security_regressions.py +0 -0
  76. {meshcode-2.11.1 → meshcode-2.11.3}/meshcode-backend-wt/tests/test_sentinel.py +0 -0
  77. {meshcode-2.11.1 → meshcode-2.11.3}/meshcode-backend-wt/tests/test_status_enum_coverage.py +0 -0
  78. {meshcode-2.11.1 → meshcode-2.11.3}/meshcode-noun-wt/build/lib/meshcode/__init__.py +0 -0
  79. {meshcode-2.11.1 → meshcode-2.11.3}/meshcode-noun-wt/build/lib/meshcode/ascii_art.py +0 -0
  80. {meshcode-2.11.1 → meshcode-2.11.3}/meshcode-noun-wt/build/lib/meshcode/cli.py +0 -0
  81. {meshcode-2.11.1 → meshcode-2.11.3}/meshcode-noun-wt/build/lib/meshcode/comms_v4.py +0 -0
  82. {meshcode-2.11.1 → meshcode-2.11.3}/meshcode-noun-wt/build/lib/meshcode/compat.py +0 -0
  83. {meshcode-2.11.1 → meshcode-2.11.3}/meshcode-noun-wt/build/lib/meshcode/error_hints.py +0 -0
  84. {meshcode-2.11.1 → meshcode-2.11.3}/meshcode-noun-wt/build/lib/meshcode/exceptions.py +0 -0
  85. {meshcode-2.11.1 → meshcode-2.11.3}/meshcode-noun-wt/build/lib/meshcode/invites.py +0 -0
  86. {meshcode-2.11.1 → meshcode-2.11.3}/meshcode-noun-wt/build/lib/meshcode/launcher.py +0 -0
  87. {meshcode-2.11.1 → meshcode-2.11.3}/meshcode-noun-wt/build/lib/meshcode/launcher_install.py +0 -0
  88. {meshcode-2.11.1 → meshcode-2.11.3}/meshcode-noun-wt/build/lib/meshcode/meshcode_mcp/__init__.py +0 -0
  89. {meshcode-2.11.1 → meshcode-2.11.3}/meshcode-noun-wt/build/lib/meshcode/meshcode_mcp/__main__.py +0 -0
  90. {meshcode-2.11.1 → meshcode-2.11.3}/meshcode-noun-wt/build/lib/meshcode/meshcode_mcp/backend.py +0 -0
  91. {meshcode-2.11.1 → meshcode-2.11.3}/meshcode-noun-wt/build/lib/meshcode/meshcode_mcp/realtime.py +0 -0
  92. {meshcode-2.11.1 → meshcode-2.11.3}/meshcode-noun-wt/build/lib/meshcode/meshcode_mcp/server.py +0 -0
  93. {meshcode-2.11.1 → meshcode-2.11.3}/meshcode-noun-wt/build/lib/meshcode/meshcode_mcp/test_backend.py +0 -0
  94. {meshcode-2.11.1 → meshcode-2.11.3}/meshcode-noun-wt/build/lib/meshcode/meshcode_mcp/test_realtime.py +0 -0
  95. {meshcode-2.11.1 → meshcode-2.11.3}/meshcode-noun-wt/build/lib/meshcode/meshcode_mcp/test_server_wrapper.py +0 -0
  96. {meshcode-2.11.1 → meshcode-2.11.3}/meshcode-noun-wt/build/lib/meshcode/preferences.py +0 -0
  97. {meshcode-2.11.1 → meshcode-2.11.3}/meshcode-noun-wt/build/lib/meshcode/protocol_v2.py +0 -0
  98. {meshcode-2.11.1 → meshcode-2.11.3}/meshcode-noun-wt/build/lib/meshcode/quickstart.py +0 -0
  99. {meshcode-2.11.1 → meshcode-2.11.3}/meshcode-noun-wt/build/lib/meshcode/run_agent.py +0 -0
  100. {meshcode-2.11.1 → meshcode-2.11.3}/meshcode-noun-wt/build/lib/meshcode/secrets.py +0 -0
  101. {meshcode-2.11.1 → meshcode-2.11.3}/meshcode-noun-wt/build/lib/meshcode/self_update.py +0 -0
  102. {meshcode-2.11.1 → meshcode-2.11.3}/meshcode-noun-wt/build/lib/meshcode/setup_clients.py +0 -0
  103. {meshcode-2.11.1 → meshcode-2.11.3}/meshcode-noun-wt/build/lib/meshcode/supervisor.py +0 -0
  104. {meshcode-2.11.1 → meshcode-2.11.3}/meshcode-noun-wt/build/lib/meshcode/upload.py +0 -0
  105. {meshcode-2.11.1 → meshcode-2.11.3}/meshcode-noun-wt/comms_v4.py +0 -0
  106. {meshcode-2.11.1 → meshcode-2.11.3}/meshcode-noun-wt/meshcode/__init__.py +0 -0
  107. {meshcode-2.11.1 → meshcode-2.11.3}/meshcode-noun-wt/meshcode/ascii_art.py +0 -0
  108. {meshcode-2.11.1 → meshcode-2.11.3}/meshcode-noun-wt/meshcode/cli.py +0 -0
  109. {meshcode-2.11.1 → meshcode-2.11.3}/meshcode-noun-wt/meshcode/comms_v4.py +0 -0
  110. {meshcode-2.11.1 → meshcode-2.11.3}/meshcode-noun-wt/meshcode/compat.py +0 -0
  111. {meshcode-2.11.1 → meshcode-2.11.3}/meshcode-noun-wt/meshcode/error_hints.py +0 -0
  112. {meshcode-2.11.1 → meshcode-2.11.3}/meshcode-noun-wt/meshcode/exceptions.py +0 -0
  113. {meshcode-2.11.1 → meshcode-2.11.3}/meshcode-noun-wt/meshcode/invites.py +0 -0
  114. {meshcode-2.11.1 → meshcode-2.11.3}/meshcode-noun-wt/meshcode/launcher.py +0 -0
  115. {meshcode-2.11.1 → meshcode-2.11.3}/meshcode-noun-wt/meshcode/launcher_install.py +0 -0
  116. {meshcode-2.11.1 → meshcode-2.11.3}/meshcode-noun-wt/meshcode/meshcode_mcp/__init__.py +0 -0
  117. {meshcode-2.11.1 → meshcode-2.11.3}/meshcode-noun-wt/meshcode/meshcode_mcp/__main__.py +0 -0
  118. {meshcode-2.11.1 → meshcode-2.11.3}/meshcode-noun-wt/meshcode/meshcode_mcp/backend.py +0 -0
  119. {meshcode-2.11.1 → meshcode-2.11.3}/meshcode-noun-wt/meshcode/meshcode_mcp/realtime.py +0 -0
  120. {meshcode-2.11.1 → meshcode-2.11.3}/meshcode-noun-wt/meshcode/meshcode_mcp/server.py +0 -0
  121. {meshcode-2.11.1 → meshcode-2.11.3}/meshcode-noun-wt/meshcode/meshcode_mcp/test_backend.py +0 -0
  122. {meshcode-2.11.1 → meshcode-2.11.3}/meshcode-noun-wt/meshcode/meshcode_mcp/test_realtime.py +0 -0
  123. {meshcode-2.11.1 → meshcode-2.11.3}/meshcode-noun-wt/meshcode/meshcode_mcp/test_server_wrapper.py +0 -0
  124. {meshcode-2.11.1 → meshcode-2.11.3}/meshcode-noun-wt/meshcode/preferences.py +0 -0
  125. {meshcode-2.11.1 → meshcode-2.11.3}/meshcode-noun-wt/meshcode/protocol_v2.py +0 -0
  126. {meshcode-2.11.1 → meshcode-2.11.3}/meshcode-noun-wt/meshcode/quickstart.py +0 -0
  127. {meshcode-2.11.1 → meshcode-2.11.3}/meshcode-noun-wt/meshcode/run_agent.py +0 -0
  128. {meshcode-2.11.1 → meshcode-2.11.3}/meshcode-noun-wt/meshcode/secrets.py +0 -0
  129. {meshcode-2.11.1 → meshcode-2.11.3}/meshcode-noun-wt/meshcode/self_update.py +0 -0
  130. {meshcode-2.11.1 → meshcode-2.11.3}/meshcode-noun-wt/meshcode/setup_clients.py +0 -0
  131. {meshcode-2.11.1 → meshcode-2.11.3}/meshcode-noun-wt/meshcode/supervisor.py +0 -0
  132. {meshcode-2.11.1 → meshcode-2.11.3}/meshcode-noun-wt/meshcode/upload.py +0 -0
  133. {meshcode-2.11.1 → meshcode-2.11.3}/meshcode-noun-wt/scripts/sentinel.py +0 -0
  134. {meshcode-2.11.1 → meshcode-2.11.3}/meshcode-noun-wt/tests/test_core.py +0 -0
  135. {meshcode-2.11.1 → meshcode-2.11.3}/meshcode-noun-wt/tests/test_cross_agent_messaging.py +0 -0
  136. {meshcode-2.11.1 → meshcode-2.11.3}/meshcode-noun-wt/tests/test_esc_deaf_state.py +0 -0
  137. {meshcode-2.11.1 → meshcode-2.11.3}/meshcode-noun-wt/tests/test_exceptions.py +0 -0
  138. {meshcode-2.11.1 → meshcode-2.11.3}/meshcode-noun-wt/tests/test_mark_read_batch.py +0 -0
  139. {meshcode-2.11.1 → meshcode-2.11.3}/meshcode-noun-wt/tests/test_migration_integrity.py +0 -0
  140. {meshcode-2.11.1 → meshcode-2.11.3}/meshcode-noun-wt/tests/test_realtime_event_freshness.py +0 -0
  141. {meshcode-2.11.1 → meshcode-2.11.3}/meshcode-noun-wt/tests/test_rls_cross_tenant.py +0 -0
  142. {meshcode-2.11.1 → meshcode-2.11.3}/meshcode-noun-wt/tests/test_rpc_migrations.py +0 -0
  143. {meshcode-2.11.1 → meshcode-2.11.3}/meshcode-noun-wt/tests/test_security_regressions.py +0 -0
  144. {meshcode-2.11.1 → meshcode-2.11.3}/meshcode-noun-wt/tests/test_sentinel.py +0 -0
  145. {meshcode-2.11.1 → meshcode-2.11.3}/meshcode-noun-wt/tests/test_status_enum_coverage.py +0 -0
  146. {meshcode-2.11.1 → meshcode-2.11.3}/meshcode-tasks-wt/comms_v4.py +0 -0
  147. {meshcode-2.11.1 → meshcode-2.11.3}/meshcode-tasks-wt/meshcode/__init__.py +0 -0
  148. {meshcode-2.11.1 → meshcode-2.11.3}/meshcode-tasks-wt/meshcode/ascii_art.py +0 -0
  149. {meshcode-2.11.1 → meshcode-2.11.3}/meshcode-tasks-wt/meshcode/cli.py +0 -0
  150. {meshcode-2.11.1 → meshcode-2.11.3}/meshcode-tasks-wt/meshcode/comms_v4.py +0 -0
  151. {meshcode-2.11.1 → meshcode-2.11.3}/meshcode-tasks-wt/meshcode/compat.py +0 -0
  152. {meshcode-2.11.1 → meshcode-2.11.3}/meshcode-tasks-wt/meshcode/error_hints.py +0 -0
  153. {meshcode-2.11.1 → meshcode-2.11.3}/meshcode-tasks-wt/meshcode/exceptions.py +0 -0
  154. {meshcode-2.11.1 → meshcode-2.11.3}/meshcode-tasks-wt/meshcode/invites.py +0 -0
  155. {meshcode-2.11.1 → meshcode-2.11.3}/meshcode-tasks-wt/meshcode/launcher.py +0 -0
  156. {meshcode-2.11.1 → meshcode-2.11.3}/meshcode-tasks-wt/meshcode/launcher_install.py +0 -0
  157. {meshcode-2.11.1 → meshcode-2.11.3}/meshcode-tasks-wt/meshcode/meshcode_mcp/__init__.py +0 -0
  158. {meshcode-2.11.1 → meshcode-2.11.3}/meshcode-tasks-wt/meshcode/meshcode_mcp/__main__.py +0 -0
  159. {meshcode-2.11.1 → meshcode-2.11.3}/meshcode-tasks-wt/meshcode/meshcode_mcp/backend.py +0 -0
  160. {meshcode-2.11.1 → meshcode-2.11.3}/meshcode-tasks-wt/meshcode/meshcode_mcp/realtime.py +0 -0
  161. {meshcode-2.11.1 → meshcode-2.11.3}/meshcode-tasks-wt/meshcode/meshcode_mcp/server.py +0 -0
  162. {meshcode-2.11.1 → meshcode-2.11.3}/meshcode-tasks-wt/meshcode/meshcode_mcp/test_backend.py +0 -0
  163. {meshcode-2.11.1 → meshcode-2.11.3}/meshcode-tasks-wt/meshcode/meshcode_mcp/test_realtime.py +0 -0
  164. {meshcode-2.11.1 → meshcode-2.11.3}/meshcode-tasks-wt/meshcode/meshcode_mcp/test_server_wrapper.py +0 -0
  165. {meshcode-2.11.1 → meshcode-2.11.3}/meshcode-tasks-wt/meshcode/preferences.py +0 -0
  166. {meshcode-2.11.1 → meshcode-2.11.3}/meshcode-tasks-wt/meshcode/protocol_v2.py +0 -0
  167. {meshcode-2.11.1 → meshcode-2.11.3}/meshcode-tasks-wt/meshcode/quickstart.py +0 -0
  168. {meshcode-2.11.1 → meshcode-2.11.3}/meshcode-tasks-wt/meshcode/run_agent.py +0 -0
  169. {meshcode-2.11.1 → meshcode-2.11.3}/meshcode-tasks-wt/meshcode/secrets.py +0 -0
  170. {meshcode-2.11.1 → meshcode-2.11.3}/meshcode-tasks-wt/meshcode/self_update.py +0 -0
  171. {meshcode-2.11.1 → meshcode-2.11.3}/meshcode-tasks-wt/meshcode/setup_clients.py +0 -0
  172. {meshcode-2.11.1 → meshcode-2.11.3}/meshcode-tasks-wt/meshcode/supervisor.py +0 -0
  173. {meshcode-2.11.1 → meshcode-2.11.3}/meshcode-tasks-wt/meshcode/upload.py +0 -0
  174. {meshcode-2.11.1 → meshcode-2.11.3}/meshcode-tasks-wt/scripts/sentinel.py +0 -0
  175. {meshcode-2.11.1 → meshcode-2.11.3}/meshcode-tasks-wt/tests/test_core.py +0 -0
  176. {meshcode-2.11.1 → meshcode-2.11.3}/meshcode-tasks-wt/tests/test_cross_agent_messaging.py +0 -0
  177. {meshcode-2.11.1 → meshcode-2.11.3}/meshcode-tasks-wt/tests/test_esc_deaf_state.py +0 -0
  178. {meshcode-2.11.1 → meshcode-2.11.3}/meshcode-tasks-wt/tests/test_exceptions.py +0 -0
  179. {meshcode-2.11.1 → meshcode-2.11.3}/meshcode-tasks-wt/tests/test_mark_read_batch.py +0 -0
  180. {meshcode-2.11.1 → meshcode-2.11.3}/meshcode-tasks-wt/tests/test_migration_integrity.py +0 -0
  181. {meshcode-2.11.1 → meshcode-2.11.3}/meshcode-tasks-wt/tests/test_realtime_event_freshness.py +0 -0
  182. {meshcode-2.11.1 → meshcode-2.11.3}/meshcode-tasks-wt/tests/test_rls_cross_tenant.py +0 -0
  183. {meshcode-2.11.1 → meshcode-2.11.3}/meshcode-tasks-wt/tests/test_rpc_migrations.py +0 -0
  184. {meshcode-2.11.1 → meshcode-2.11.3}/meshcode-tasks-wt/tests/test_security_regressions.py +0 -0
  185. {meshcode-2.11.1 → meshcode-2.11.3}/meshcode-tasks-wt/tests/test_sentinel.py +0 -0
  186. {meshcode-2.11.1 → meshcode-2.11.3}/meshcode-tasks-wt/tests/test_status_enum_coverage.py +0 -0
  187. {meshcode-2.11.1 → meshcode-2.11.3}/meshcode.egg-info/SOURCES.txt +0 -0
  188. {meshcode-2.11.1 → meshcode-2.11.3}/meshcode.egg-info/dependency_links.txt +0 -0
  189. {meshcode-2.11.1 → meshcode-2.11.3}/meshcode.egg-info/entry_points.txt +0 -0
  190. {meshcode-2.11.1 → meshcode-2.11.3}/meshcode.egg-info/requires.txt +0 -0
  191. {meshcode-2.11.1 → meshcode-2.11.3}/meshcode.egg-info/top_level.txt +0 -0
  192. {meshcode-2.11.1 → meshcode-2.11.3}/setup.cfg +0 -0
  193. {meshcode-2.11.1 → meshcode-2.11.3}/tests/test_auto_update_hardening.py +0 -0
  194. {meshcode-2.11.1 → meshcode-2.11.3}/tests/test_core.py +0 -0
  195. {meshcode-2.11.1 → meshcode-2.11.3}/tests/test_cross_agent_messaging.py +0 -0
  196. {meshcode-2.11.1 → meshcode-2.11.3}/tests/test_esc_deaf_state.py +0 -0
  197. {meshcode-2.11.1 → meshcode-2.11.3}/tests/test_exceptions.py +0 -0
  198. {meshcode-2.11.1 → meshcode-2.11.3}/tests/test_lease_sigterm_release.py +0 -0
  199. {meshcode-2.11.1 → meshcode-2.11.3}/tests/test_mark_read_batch.py +0 -0
  200. {meshcode-2.11.1 → meshcode-2.11.3}/tests/test_migration_integrity.py +0 -0
  201. {meshcode-2.11.1 → meshcode-2.11.3}/tests/test_realtime_event_freshness.py +0 -0
  202. {meshcode-2.11.1 → meshcode-2.11.3}/tests/test_rls_cross_tenant.py +0 -0
  203. {meshcode-2.11.1 → meshcode-2.11.3}/tests/test_rpc_migrations.py +0 -0
  204. {meshcode-2.11.1 → meshcode-2.11.3}/tests/test_security_regressions.py +0 -0
  205. {meshcode-2.11.1 → meshcode-2.11.3}/tests/test_sentinel.py +0 -0
  206. {meshcode-2.11.1 → meshcode-2.11.3}/tests/test_status_enum_coverage.py +0 -0
  207. {meshcode-2.11.1 → meshcode-2.11.3}/tests/test_stay_on_loop_hook.py +0 -0
  208. {meshcode-2.11.1 → meshcode-2.11.3}/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.1
3
+ Version: 2.11.3
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.1"
2
+ __version__ = "2.11.3"
3
3
 
4
4
  # Exception hierarchy — eagerly imported (lightweight, no deps)
5
5
  from meshcode.exceptions import ( # noqa: F401
@@ -353,52 +353,61 @@ def _mcp_unreachable_recently(transcript_path, lookback_records=_UNREACHABLE_LOO
353
353
 
354
354
 
355
355
  def _latest_deferred_listing_lacks_meshcode(transcript_path, lookback_records=_UNREACHABLE_LOOKBACK):
356
- """Find the most recent <system-reminder> that enumerates deferred
357
- tools. If it lists mcp__ entries (proving the listing format is
358
- canonical) but ZERO meshcode_* entries, the meshcode MCP server is
359
- not registered for this session. Release.
360
-
361
- Note: the listing is delivered as user-role content, often inside a
362
- <system-reminder>...</system-reminder> block but sometimes plain.
363
- We match on the marker substrings rather than tag parsing.
356
+ """Detect "meshcode MCP never loaded this session" by inspecting the
357
+ structured deferred-tools attachments Claude Code writes to the
358
+ transcript jsonl. Records of the form:
359
+
360
+ {"type": "attachment",
361
+ "attachment": {"type": "deferred_tools_delta",
362
+ "addedNames": ["mcp__claude_ai_Gmail__...", ...]}}
363
+
364
+ accumulate over the session — meshcode tools land as
365
+ `mcp__meshcode-<server>__<tool>` once the server registers. If we
366
+ walk every delta and find ZERO meshcode entries (but DID find OTHER
367
+ mcp__ entries, confirming Claude Code is recording deltas at all),
368
+ the meshcode MCP server is missing for this session → release.
369
+
370
+ Replaces the previous text-marker scan ("the following deferred tools
371
+ are now available") — Claude Code never writes that rendered text
372
+ into the transcript; only the structured attachment. The old scan
373
+ therefore never fired, trapping agents whose MCP server failed at
374
+ boot in an infinite stay-on-loop. Confirmed via bob@justforfun
375
+ cross-mesh repro (2026-05-14) + Samuel mesh-commander launch.
364
376
  """
365
377
  try:
366
- records = []
378
+ seen_other_mcp = False
379
+ seen_meshcode = False
380
+ record_count = 0
367
381
  with transcript_path.open() as f:
368
382
  for line in f:
369
383
  try:
370
- records.append(json.loads(line))
384
+ rec = json.loads(line)
371
385
  except json.JSONDecodeError:
372
386
  continue
373
- tail = records[-lookback_records:] if lookback_records else records
374
- for rec in reversed(tail):
375
- if rec.get("role") != "user":
376
- continue
377
- content = rec.get("content")
378
- blocks = content if isinstance(content, list) else [content] if isinstance(content, dict) else [content]
379
- for block in blocks:
380
- if isinstance(block, str):
381
- text = block
382
- elif isinstance(block, dict):
383
- if block.get("type") == "tool_result":
384
- # tool_result blocks aren't system-reminders; skip
385
- continue
386
- text = str(block.get("text", "") or block.get("content", "") or "")
387
- else:
387
+ record_count += 1
388
+ att = rec.get("attachment") if isinstance(rec, dict) else None
389
+ if not isinstance(att, dict):
388
390
  continue
389
- lower = text.lower()
390
- if not any(m in lower for m in _DEFERRED_LISTING_MARKERS):
391
+ if att.get("type") != "deferred_tools_delta":
391
392
  continue
392
- # Found a listing. Check if it enumerates real tools.
393
- has_mcp = "mcp__" in lower
394
- has_meshcode = "meshcode_" in lower
395
- if has_mcp and not has_meshcode:
396
- return True
397
- # First listing that contains meshcode_ is enough to
398
- # confirm MCP IS registered stop searching backwards.
399
- if has_meshcode:
400
- return False
401
- return False
393
+ names = att.get("addedNames") or []
394
+ if not isinstance(names, list):
395
+ continue
396
+ for n in names:
397
+ if not isinstance(n, str):
398
+ continue
399
+ # meshcode tools are namespaced under their server name:
400
+ # `mcp__meshcode-<server>__<tool>`. Substring check covers
401
+ # all variants (self-improve, justforfun, mesh-dev, etc.).
402
+ if "meshcode-" in n and "__meshcode_" in n:
403
+ seen_meshcode = True
404
+ elif n.startswith("mcp__"):
405
+ seen_other_mcp = True
406
+ # Release only when we have evidence Claude Code IS recording deltas
407
+ # (other mcp__ tools present) but no meshcode_* entries appeared.
408
+ # Without the seen_other_mcp guard we'd false-positive on transcripts
409
+ # that simply haven't reached any deferred-tools delta yet.
410
+ return bool(seen_other_mcp and not seen_meshcode)
402
411
  except (OSError, FileNotFoundError):
403
412
  return False
404
413
 
@@ -467,7 +476,7 @@ def main():
467
476
  # session traces can show why the loop released without a user
468
477
  # release keyword. Released without printing a block decision.
469
478
  try:
470
- sys.stderr.write("[stay_on_loop] release: mcp_unreachable\n")
479
+ sys.stderr.write("[stay_on_loop] release: mcp_unreachable\\n")
471
480
  sys.stderr.flush()
472
481
  except Exception:
473
482
  pass
@@ -475,7 +484,7 @@ def main():
475
484
 
476
485
  if transcript_path and _latest_deferred_listing_lacks_meshcode(transcript_path):
477
486
  try:
478
- sys.stderr.write("[stay_on_loop] release: mcp_not_registered (deferred listing has no meshcode_*)\n")
487
+ sys.stderr.write("[stay_on_loop] release: mcp_not_registered (deferred listing has no meshcode_*)\\n")
479
488
  sys.stderr.flush()
480
489
  except Exception:
481
490
  pass
@@ -483,7 +492,7 @@ def main():
483
492
 
484
493
  if transcript_path and _user_explicitly_reports_mcp_failure(transcript_path):
485
494
  try:
486
- sys.stderr.write("[stay_on_loop] release: user_reported_mcp_failure\n")
495
+ sys.stderr.write("[stay_on_loop] release: user_reported_mcp_failure\\n")
487
496
  sys.stderr.flush()
488
497
  except Exception:
489
498
  pass
@@ -501,17 +501,22 @@ def _filter_and_mark(messages: List[Dict[str, Any]]) -> List[Dict[str, Any]]:
501
501
 
502
502
  _SLEEP_PAYLOAD_TYPES = {"sleep", "go_to_sleep", "shutdown", "got_done", "done",
503
503
  "exit", "stop", "kill", "terminate"}
504
- # Spanish + English markers (es-MX hot path per SDK-S6.1). Matched as
505
- # substrings, lowercased before compare. Keep exclusive enough to not
506
- # false-positive on casual chatter (e.g. "no quiero dormir" still matches
507
- # accepted tradeoff for user-control reliability).
504
+ # Multi-word imperative markers ONLY. Single Spanish verbs like "salir" /
505
+ # "terminar" / "duerme" were too loose and caught idiomatic prose like
506
+ # "terminaron sus tasks" or "no puedo salir" (msg cfbd36b0 2026-05-14 alexa +
507
+ # commander incidents feedback_done_signal_false_positive_idiomatic
508
+ # precedent). The parser now requires a directive-shaped phrase: a verb
509
+ # combined with a temporal/object qualifier ("ahora" / "todos" / "to sleep")
510
+ # so describing an event in prose can't trip must_exit.
508
511
  _SLEEP_TEXT_MARKERS = (
509
- # English
512
+ # English directives
510
513
  "go to sleep", "all sleep now", "sleep now", "got_done", "go_done",
511
514
  "shut down", "shutdown", "stop now", "exit now",
512
- # Spanish (es-MX, sammybenu's primary)
513
- "a dormir", "todos a dormir", "duerme", "duerman", "dormir ahora",
514
- "salir", "terminar", "para la sesion", "exit y duerme",
515
+ # Spanish directives (es-MX, sammybenu's primary). All require either a
516
+ # leading "a"/"todos" or a trailing "ahora" so plain conjugations
517
+ # ("salir", "terminar", "duerme") in body prose don't trigger.
518
+ "a dormir", "todos a dormir", "duerme ahora", "duerman ahora",
519
+ "dormir ahora", "para la sesion", "exit y duerme",
515
520
  )
516
521
 
517
522
 
@@ -2305,12 +2310,10 @@ def meshcode_send(to: Union[str, List[str]], message: Any, in_reply_to: Optional
2305
2310
  to = recipients[0]
2306
2311
  if isinstance(message, str):
2307
2312
  # Auto-wrap strings into dict. Reject very long content; suggest
2308
- # task_create for >4000 chars so receiver context isn't blown.
2309
- # Cap raised from 2000 4000 (R3-CONV-1, 2026-05-05) — round-2/3
2310
- # task reports kept hitting the old cap and required forced
2311
- # downsizing or task_create fallback.
2312
- if len(message) > 4000:
2313
- return {"error": f"message too long ({len(message)} chars). Use meshcode_task_create for long content, or split into multiple messages. Max ~4000 chars."}
2313
+ # task_create for >8000 chars. Cap raised 4000 8000 (mig 303,
2314
+ # 2026-05-14) Samuel hit the old cap on consolidations.
2315
+ if len(message) > 8000:
2316
+ return {"error": f"message too long ({len(message)} chars). Use meshcode_task_create for long content, or split into multiple messages. Max ~8000 chars."}
2314
2317
  payload: Dict[str, Any] = {"text": message}
2315
2318
  elif isinstance(message, dict):
2316
2319
  payload = message
@@ -2328,13 +2331,10 @@ def meshcode_send(to: Union[str, List[str]], message: Any, in_reply_to: Optional
2328
2331
  payload["text"] = _synth if len(_synth) <= 280 else _synth[:279] + "…"
2329
2332
 
2330
2333
  # Enforce message size limit — long content belongs in task descriptions.
2331
- # Cap raised 20004000 (R3-CONV-1, 2026-05-05). Above 2000 chars the
2332
- # error message hints at task_create so callers learn the convention,
2333
- # but the hard cap is at 4000 so structured JSON reports don't get
2334
- # forcibly trimmed mid-payload.
2334
+ # Cap raised 40008000 chars in line with mig 303 (16KB DB cap).
2335
2335
  _payload_len = len(_json.dumps(payload, default=str))
2336
- if _payload_len > 4000:
2337
- return {"error": f"message too large ({_payload_len} chars). Use meshcode_task_create for long content. Messages must be structured JSON <4000 chars."}
2336
+ if _payload_len > 8000:
2337
+ return {"error": f"message too large ({_payload_len} chars). Use meshcode_task_create for long content. Messages must be structured JSON <8000 chars."}
2338
2338
 
2339
2339
  # Typed-catalog soft validation (BE-S4.2.sdk / mig 233): if caller
2340
2340
  # passes type=, fetch the schema and check required fields. NEVER
@@ -2671,6 +2671,13 @@ def meshcode_download_file(file_id: str) -> Dict[str, Any]:
2671
2671
  Returns file content for text/JSON files, or saves to temp file and
2672
2672
  returns the path for images (Claude can view image files directly).
2673
2673
 
2674
+ Download strategy:
2675
+ 1. mc_get_file_download RPC returns metadata + (when GUC is configured
2676
+ on the backend) a short-lived signed_url. If signed_url present,
2677
+ fetch it WITHOUT auth headers — works for any agent without
2678
+ per-client service_role secret distribution. Closes 235e85b6 PATH B.
2679
+ 2. Fallback: legacy service_role/anon/public path on the storage_path.
2680
+
2674
2681
  Args:
2675
2682
  file_id: UUID of the file (from message payload's file.file_id).
2676
2683
  """
@@ -2682,23 +2689,55 @@ def meshcode_download_file(file_id: str) -> Dict[str, Any]:
2682
2689
  if not api_key:
2683
2690
  return {"error": "no api key", "error_code": "auth_failed"}
2684
2691
 
2685
- # Step 1: Get file metadata via RPC
2692
+ def _consume(content: bytes, mime_type: str, file_name: str) -> Dict[str, Any]:
2693
+ if mime_type.startswith("text/") or mime_type == "application/json":
2694
+ try:
2695
+ text = content.decode("utf-8")
2696
+ if mime_type == "application/json":
2697
+ return {"ok": True, "file_name": file_name, "mime_type": mime_type,
2698
+ "content": json.loads(text)}
2699
+ return {"ok": True, "file_name": file_name, "mime_type": mime_type,
2700
+ "content": text[:50000]}
2701
+ except Exception:
2702
+ pass
2703
+ suffix = "." + file_name.rsplit(".", 1)[-1] if "." in file_name else ""
2704
+ tmp = tempfile.NamedTemporaryFile(delete=False, suffix=suffix, prefix="meshcode_")
2705
+ tmp.write(content)
2706
+ tmp.close()
2707
+ return {
2708
+ "ok": True,
2709
+ "file_name": file_name,
2710
+ "mime_type": mime_type,
2711
+ "size_bytes": len(content),
2712
+ "local_path": tmp.name,
2713
+ "note": "File saved to local_path. For images, use Read tool to view.",
2714
+ }
2715
+
2686
2716
  file_info = be.sb_rpc("mc_get_file_download", {
2687
2717
  "p_api_key": api_key,
2688
2718
  "p_file_id": file_id,
2689
2719
  })
2690
2720
  if not file_info or not file_info.get("ok"):
2691
- return {"error": file_info.get("error", "file not found"), "error_code": "not_found"}
2721
+ return {"error": (file_info or {}).get("error", "file not found"), "error_code": "not_found"}
2692
2722
 
2693
2723
  storage_path = file_info["storage_path"]
2694
2724
  bucket = file_info.get("bucket", "meshcode-files")
2695
2725
  mime_type = file_info.get("mime_type", "application/octet-stream")
2696
2726
  file_name = file_info.get("file_name", "download")
2727
+ signed_url = file_info.get("signed_url")
2697
2728
 
2698
- # Step 2: Download from Supabase Storage.
2699
- # The bucket is private, so the publishable/anon key returns 404. We try
2700
- # the keys in order: service_role (if user opted in) → anon → public-bucket
2701
- # fallback. Most setups need service_role for cross-agent file access.
2729
+ # Strategy 1: signed_url (no auth headers, no client service_role needed)
2730
+ if signed_url:
2731
+ try:
2732
+ with _req.urlopen(_req.Request(signed_url), timeout=30) as resp:
2733
+ content = resp.read()
2734
+ return _consume(content, mime_type, file_name)
2735
+ except _uerr.HTTPError:
2736
+ pass # fall through to legacy path
2737
+ except Exception:
2738
+ pass
2739
+
2740
+ # Strategy 2: legacy service_role/anon/public on storage_path
2702
2741
  sb_url = os.environ.get("SUPABASE_URL", be._sb_url if hasattr(be, '_sb_url') else "")
2703
2742
  anon_key = os.environ.get("SUPABASE_KEY", be._sb_key if hasattr(be, '_sb_key') else "")
2704
2743
  service_key = os.environ.get("MESHCODE_SUPABASE_SERVICE_KEY", "")
@@ -2732,7 +2771,7 @@ def meshcode_download_file(file_id: str) -> Dict[str, Any]:
2732
2771
 
2733
2772
  last_err = None
2734
2773
  content = None
2735
- tried_labels = []
2774
+ tried_labels: List[str] = ["signed_url"] if signed_url else []
2736
2775
  for label, _url, _key in attempts:
2737
2776
  tried_labels.append(label)
2738
2777
  try:
@@ -2750,35 +2789,10 @@ def meshcode_download_file(file_id: str) -> Dict[str, Any]:
2750
2789
  "error_code": "download_error",
2751
2790
  "tried": tried_labels,
2752
2791
  "storage_path": storage_path,
2753
- "hint": "set MESHCODE_SUPABASE_SERVICE_KEY in the MCP server env to enable service_role downloads (private bucket)" if not service_key else None,
2792
+ "hint": "ask commander to apply backend GUC app.settings.service_role_key + supabase_url so the RPC can mint signed URLs" if not signed_url else None,
2754
2793
  }
2755
2794
 
2756
- # Step 3: Return content based on type
2757
- if mime_type.startswith("text/") or mime_type == "application/json":
2758
- try:
2759
- text = content.decode("utf-8")
2760
- if mime_type == "application/json":
2761
- return {"ok": True, "file_name": file_name, "mime_type": mime_type,
2762
- "content": json.loads(text)}
2763
- return {"ok": True, "file_name": file_name, "mime_type": mime_type,
2764
- "content": text[:50000]} # cap at 50k chars
2765
- except Exception:
2766
- pass
2767
-
2768
- # For images and binary: save to temp file, return path
2769
- suffix = "." + file_name.rsplit(".", 1)[-1] if "." in file_name else ""
2770
- tmp = tempfile.NamedTemporaryFile(delete=False, suffix=suffix, prefix="meshcode_")
2771
- tmp.write(content)
2772
- tmp.close()
2773
-
2774
- return {
2775
- "ok": True,
2776
- "file_name": file_name,
2777
- "mime_type": mime_type,
2778
- "size_bytes": len(content),
2779
- "local_path": tmp.name,
2780
- "note": "File saved to local_path. For images, use Read tool to view.",
2781
- }
2795
+ return _consume(content, mime_type, file_name)
2782
2796
 
2783
2797
 
2784
2798
  def _detect_global_done(messages: List[Dict[str, Any]]) -> Optional[Dict[str, Any]]:
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.4
2
2
  Name: meshcode
3
- Version: 2.11.1
3
+ Version: 2.11.3
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.1"
7
+ version = "2.11.3"
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
File without changes
File without changes
File without changes