meshcode 2.11.107__tar.gz → 2.11.108__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 (257) hide show
  1. {meshcode-2.11.107 → meshcode-2.11.108}/PKG-INFO +1 -1
  2. {meshcode-2.11.107 → meshcode-2.11.108}/meshcode/__init__.py +1 -1
  3. {meshcode-2.11.107 → meshcode-2.11.108}/meshcode/hostd.py +78 -0
  4. {meshcode-2.11.107 → meshcode-2.11.108}/meshcode/meshcode_mcp/server.py +2 -0
  5. {meshcode-2.11.107 → meshcode-2.11.108}/meshcode/protocol_handler.py +141 -0
  6. {meshcode-2.11.107 → meshcode-2.11.108}/meshcode/run_agent.py +15 -0
  7. {meshcode-2.11.107 → meshcode-2.11.108}/meshcode/setup_clients.py +5 -0
  8. {meshcode-2.11.107 → meshcode-2.11.108}/meshcode.egg-info/PKG-INFO +1 -1
  9. meshcode-2.11.108/meshcode.egg-info/SOURCES.txt +97 -0
  10. meshcode-2.11.108/meshcode.egg-info/top_level.txt +1 -0
  11. {meshcode-2.11.107 → meshcode-2.11.108}/pyproject.toml +2 -2
  12. {meshcode-2.11.107 → meshcode-2.11.108}/tests/test_wait_open_tasks_contradiction.py +3 -2
  13. meshcode-2.11.107/meshcode/cli.py +0 -42
  14. meshcode-2.11.107/meshcode/compat.py +0 -174
  15. meshcode-2.11.107/meshcode/error_hints.py +0 -74
  16. meshcode-2.11.107/meshcode/exceptions.py +0 -52
  17. meshcode-2.11.107/meshcode/invites.py +0 -406
  18. meshcode-2.11.107/meshcode/launcher.py +0 -353
  19. meshcode-2.11.107/meshcode/launcher_install.py +0 -414
  20. meshcode-2.11.107/meshcode/meshcode_mcp/__init__.py +0 -22
  21. meshcode-2.11.107/meshcode/meshcode_mcp/__main__.py +0 -62
  22. meshcode-2.11.107/meshcode/meshcode_mcp/test_backend.py +0 -86
  23. meshcode-2.11.107/meshcode/meshcode_mcp/test_realtime.py +0 -95
  24. meshcode-2.11.107/meshcode/meshcode_mcp/test_server_wrapper.py +0 -117
  25. meshcode-2.11.107/meshcode/preferences.py +0 -260
  26. meshcode-2.11.107/meshcode/protocol_v2.py +0 -129
  27. meshcode-2.11.107/meshcode/secrets.py +0 -365
  28. meshcode-2.11.107/meshcode/supervisor.py +0 -186
  29. meshcode-2.11.107/meshcode/upload.py +0 -125
  30. meshcode-2.11.107/meshcode-backend-wt/comms_v4.py +0 -1941
  31. meshcode-2.11.107/meshcode-backend-wt/meshcode/__init__.py +0 -82
  32. meshcode-2.11.107/meshcode-backend-wt/meshcode/ascii_art.py +0 -638
  33. meshcode-2.11.107/meshcode-backend-wt/meshcode/comms_v4.py +0 -3563
  34. meshcode-2.11.107/meshcode-backend-wt/meshcode/meshcode_mcp/backend.py +0 -1261
  35. meshcode-2.11.107/meshcode-backend-wt/meshcode/meshcode_mcp/realtime.py +0 -460
  36. meshcode-2.11.107/meshcode-backend-wt/meshcode/meshcode_mcp/server.py +0 -4117
  37. meshcode-2.11.107/meshcode-backend-wt/meshcode/quickstart.py +0 -148
  38. meshcode-2.11.107/meshcode-backend-wt/meshcode/run_agent.py +0 -958
  39. meshcode-2.11.107/meshcode-backend-wt/meshcode/self_update.py +0 -345
  40. meshcode-2.11.107/meshcode-backend-wt/meshcode/setup_clients.py +0 -926
  41. meshcode-2.11.107/meshcode-backend-wt/scripts/sentinel.py +0 -257
  42. meshcode-2.11.107/meshcode-backend-wt/tests/test_rpc_migrations.py +0 -387
  43. meshcode-2.11.107/meshcode-noun-wt/build/lib/meshcode/__init__.py +0 -82
  44. meshcode-2.11.107/meshcode-noun-wt/build/lib/meshcode/ascii_art.py +0 -638
  45. meshcode-2.11.107/meshcode-noun-wt/build/lib/meshcode/cli.py +0 -42
  46. meshcode-2.11.107/meshcode-noun-wt/build/lib/meshcode/comms_v4.py +0 -3563
  47. meshcode-2.11.107/meshcode-noun-wt/build/lib/meshcode/compat.py +0 -174
  48. meshcode-2.11.107/meshcode-noun-wt/build/lib/meshcode/error_hints.py +0 -74
  49. meshcode-2.11.107/meshcode-noun-wt/build/lib/meshcode/exceptions.py +0 -52
  50. meshcode-2.11.107/meshcode-noun-wt/build/lib/meshcode/invites.py +0 -406
  51. meshcode-2.11.107/meshcode-noun-wt/build/lib/meshcode/launcher.py +0 -353
  52. meshcode-2.11.107/meshcode-noun-wt/build/lib/meshcode/launcher_install.py +0 -414
  53. meshcode-2.11.107/meshcode-noun-wt/build/lib/meshcode/meshcode_mcp/__init__.py +0 -22
  54. meshcode-2.11.107/meshcode-noun-wt/build/lib/meshcode/meshcode_mcp/__main__.py +0 -62
  55. meshcode-2.11.107/meshcode-noun-wt/build/lib/meshcode/meshcode_mcp/backend.py +0 -1261
  56. meshcode-2.11.107/meshcode-noun-wt/build/lib/meshcode/meshcode_mcp/realtime.py +0 -460
  57. meshcode-2.11.107/meshcode-noun-wt/build/lib/meshcode/meshcode_mcp/server.py +0 -4117
  58. meshcode-2.11.107/meshcode-noun-wt/build/lib/meshcode/meshcode_mcp/test_backend.py +0 -86
  59. meshcode-2.11.107/meshcode-noun-wt/build/lib/meshcode/meshcode_mcp/test_realtime.py +0 -95
  60. meshcode-2.11.107/meshcode-noun-wt/build/lib/meshcode/meshcode_mcp/test_server_wrapper.py +0 -117
  61. meshcode-2.11.107/meshcode-noun-wt/build/lib/meshcode/preferences.py +0 -260
  62. meshcode-2.11.107/meshcode-noun-wt/build/lib/meshcode/protocol_v2.py +0 -129
  63. meshcode-2.11.107/meshcode-noun-wt/build/lib/meshcode/quickstart.py +0 -148
  64. meshcode-2.11.107/meshcode-noun-wt/build/lib/meshcode/run_agent.py +0 -958
  65. meshcode-2.11.107/meshcode-noun-wt/build/lib/meshcode/secrets.py +0 -365
  66. meshcode-2.11.107/meshcode-noun-wt/build/lib/meshcode/self_update.py +0 -345
  67. meshcode-2.11.107/meshcode-noun-wt/build/lib/meshcode/setup_clients.py +0 -926
  68. meshcode-2.11.107/meshcode-noun-wt/build/lib/meshcode/supervisor.py +0 -186
  69. meshcode-2.11.107/meshcode-noun-wt/build/lib/meshcode/upload.py +0 -125
  70. meshcode-2.11.107/meshcode-noun-wt/comms_v4.py +0 -1941
  71. meshcode-2.11.107/meshcode-noun-wt/meshcode/__init__.py +0 -82
  72. meshcode-2.11.107/meshcode-noun-wt/meshcode/ascii_art.py +0 -638
  73. meshcode-2.11.107/meshcode-noun-wt/meshcode/cli.py +0 -42
  74. meshcode-2.11.107/meshcode-noun-wt/meshcode/comms_v4.py +0 -3563
  75. meshcode-2.11.107/meshcode-noun-wt/meshcode/compat.py +0 -174
  76. meshcode-2.11.107/meshcode-noun-wt/meshcode/error_hints.py +0 -74
  77. meshcode-2.11.107/meshcode-noun-wt/meshcode/exceptions.py +0 -52
  78. meshcode-2.11.107/meshcode-noun-wt/meshcode/invites.py +0 -406
  79. meshcode-2.11.107/meshcode-noun-wt/meshcode/launcher.py +0 -353
  80. meshcode-2.11.107/meshcode-noun-wt/meshcode/launcher_install.py +0 -414
  81. meshcode-2.11.107/meshcode-noun-wt/meshcode/meshcode_mcp/__init__.py +0 -22
  82. meshcode-2.11.107/meshcode-noun-wt/meshcode/meshcode_mcp/__main__.py +0 -62
  83. meshcode-2.11.107/meshcode-noun-wt/meshcode/meshcode_mcp/backend.py +0 -1261
  84. meshcode-2.11.107/meshcode-noun-wt/meshcode/meshcode_mcp/realtime.py +0 -460
  85. meshcode-2.11.107/meshcode-noun-wt/meshcode/meshcode_mcp/server.py +0 -4117
  86. meshcode-2.11.107/meshcode-noun-wt/meshcode/meshcode_mcp/test_backend.py +0 -86
  87. meshcode-2.11.107/meshcode-noun-wt/meshcode/meshcode_mcp/test_realtime.py +0 -95
  88. meshcode-2.11.107/meshcode-noun-wt/meshcode/meshcode_mcp/test_server_wrapper.py +0 -117
  89. meshcode-2.11.107/meshcode-noun-wt/meshcode/preferences.py +0 -260
  90. meshcode-2.11.107/meshcode-noun-wt/meshcode/protocol_v2.py +0 -129
  91. meshcode-2.11.107/meshcode-noun-wt/meshcode/quickstart.py +0 -148
  92. meshcode-2.11.107/meshcode-noun-wt/meshcode/run_agent.py +0 -958
  93. meshcode-2.11.107/meshcode-noun-wt/meshcode/secrets.py +0 -365
  94. meshcode-2.11.107/meshcode-noun-wt/meshcode/self_update.py +0 -345
  95. meshcode-2.11.107/meshcode-noun-wt/meshcode/setup_clients.py +0 -926
  96. meshcode-2.11.107/meshcode-noun-wt/meshcode/supervisor.py +0 -186
  97. meshcode-2.11.107/meshcode-noun-wt/meshcode/upload.py +0 -125
  98. meshcode-2.11.107/meshcode-noun-wt/scripts/sentinel.py +0 -257
  99. meshcode-2.11.107/meshcode-noun-wt/tests/test_core.py +0 -216
  100. meshcode-2.11.107/meshcode-noun-wt/tests/test_cross_agent_messaging.py +0 -366
  101. meshcode-2.11.107/meshcode-noun-wt/tests/test_esc_deaf_state.py +0 -361
  102. meshcode-2.11.107/meshcode-noun-wt/tests/test_exceptions.py +0 -107
  103. meshcode-2.11.107/meshcode-noun-wt/tests/test_mark_read_batch.py +0 -200
  104. meshcode-2.11.107/meshcode-noun-wt/tests/test_migration_integrity.py +0 -176
  105. meshcode-2.11.107/meshcode-noun-wt/tests/test_realtime_event_freshness.py +0 -236
  106. meshcode-2.11.107/meshcode-noun-wt/tests/test_rls_cross_tenant.py +0 -255
  107. meshcode-2.11.107/meshcode-noun-wt/tests/test_rpc_migrations.py +0 -387
  108. meshcode-2.11.107/meshcode-noun-wt/tests/test_security_regressions.py +0 -171
  109. meshcode-2.11.107/meshcode-noun-wt/tests/test_sentinel.py +0 -148
  110. meshcode-2.11.107/meshcode-noun-wt/tests/test_status_enum_coverage.py +0 -231
  111. meshcode-2.11.107/meshcode-tasks-wt/comms_v4.py +0 -1941
  112. meshcode-2.11.107/meshcode-tasks-wt/meshcode/__init__.py +0 -82
  113. meshcode-2.11.107/meshcode-tasks-wt/meshcode/ascii_art.py +0 -638
  114. meshcode-2.11.107/meshcode-tasks-wt/meshcode/cli.py +0 -42
  115. meshcode-2.11.107/meshcode-tasks-wt/meshcode/comms_v4.py +0 -3563
  116. meshcode-2.11.107/meshcode-tasks-wt/meshcode/compat.py +0 -174
  117. meshcode-2.11.107/meshcode-tasks-wt/meshcode/error_hints.py +0 -74
  118. meshcode-2.11.107/meshcode-tasks-wt/meshcode/exceptions.py +0 -52
  119. meshcode-2.11.107/meshcode-tasks-wt/meshcode/invites.py +0 -406
  120. meshcode-2.11.107/meshcode-tasks-wt/meshcode/launcher.py +0 -353
  121. meshcode-2.11.107/meshcode-tasks-wt/meshcode/launcher_install.py +0 -414
  122. meshcode-2.11.107/meshcode-tasks-wt/meshcode/meshcode_mcp/__init__.py +0 -22
  123. meshcode-2.11.107/meshcode-tasks-wt/meshcode/meshcode_mcp/__main__.py +0 -62
  124. meshcode-2.11.107/meshcode-tasks-wt/meshcode/meshcode_mcp/backend.py +0 -1261
  125. meshcode-2.11.107/meshcode-tasks-wt/meshcode/meshcode_mcp/realtime.py +0 -460
  126. meshcode-2.11.107/meshcode-tasks-wt/meshcode/meshcode_mcp/server.py +0 -4117
  127. meshcode-2.11.107/meshcode-tasks-wt/meshcode/meshcode_mcp/test_backend.py +0 -86
  128. meshcode-2.11.107/meshcode-tasks-wt/meshcode/meshcode_mcp/test_realtime.py +0 -95
  129. meshcode-2.11.107/meshcode-tasks-wt/meshcode/meshcode_mcp/test_server_wrapper.py +0 -117
  130. meshcode-2.11.107/meshcode-tasks-wt/meshcode/preferences.py +0 -260
  131. meshcode-2.11.107/meshcode-tasks-wt/meshcode/protocol_v2.py +0 -129
  132. meshcode-2.11.107/meshcode-tasks-wt/meshcode/quickstart.py +0 -148
  133. meshcode-2.11.107/meshcode-tasks-wt/meshcode/run_agent.py +0 -958
  134. meshcode-2.11.107/meshcode-tasks-wt/meshcode/secrets.py +0 -365
  135. meshcode-2.11.107/meshcode-tasks-wt/meshcode/self_update.py +0 -345
  136. meshcode-2.11.107/meshcode-tasks-wt/meshcode/setup_clients.py +0 -926
  137. meshcode-2.11.107/meshcode-tasks-wt/meshcode/supervisor.py +0 -186
  138. meshcode-2.11.107/meshcode-tasks-wt/meshcode/upload.py +0 -125
  139. meshcode-2.11.107/meshcode-tasks-wt/scripts/sentinel.py +0 -257
  140. meshcode-2.11.107/meshcode-tasks-wt/tests/test_core.py +0 -216
  141. meshcode-2.11.107/meshcode-tasks-wt/tests/test_cross_agent_messaging.py +0 -366
  142. meshcode-2.11.107/meshcode-tasks-wt/tests/test_esc_deaf_state.py +0 -361
  143. meshcode-2.11.107/meshcode-tasks-wt/tests/test_exceptions.py +0 -107
  144. meshcode-2.11.107/meshcode-tasks-wt/tests/test_mark_read_batch.py +0 -200
  145. meshcode-2.11.107/meshcode-tasks-wt/tests/test_migration_integrity.py +0 -176
  146. meshcode-2.11.107/meshcode-tasks-wt/tests/test_realtime_event_freshness.py +0 -236
  147. meshcode-2.11.107/meshcode-tasks-wt/tests/test_rls_cross_tenant.py +0 -255
  148. meshcode-2.11.107/meshcode-tasks-wt/tests/test_rpc_migrations.py +0 -387
  149. meshcode-2.11.107/meshcode-tasks-wt/tests/test_security_regressions.py +0 -171
  150. meshcode-2.11.107/meshcode-tasks-wt/tests/test_sentinel.py +0 -148
  151. meshcode-2.11.107/meshcode-tasks-wt/tests/test_status_enum_coverage.py +0 -231
  152. meshcode-2.11.107/meshcode.egg-info/PKG-INFO 2 +0 -460
  153. meshcode-2.11.107/meshcode.egg-info/SOURCES 2.txt +0 -239
  154. meshcode-2.11.107/meshcode.egg-info/SOURCES.txt +0 -253
  155. meshcode-2.11.107/meshcode.egg-info/dependency_links 2.txt +0 -1
  156. meshcode-2.11.107/meshcode.egg-info/entry_points 2.txt +0 -3
  157. meshcode-2.11.107/meshcode.egg-info/requires 2.txt +0 -13
  158. meshcode-2.11.107/meshcode.egg-info/top_level 2.txt +0 -4
  159. meshcode-2.11.107/meshcode.egg-info/top_level.txt +0 -4
  160. meshcode-2.11.107/tests/test_core.py +0 -216
  161. meshcode-2.11.107/tests/test_cross_agent_messaging.py +0 -366
  162. meshcode-2.11.107/tests/test_esc_deaf_state.py +0 -361
  163. meshcode-2.11.107/tests/test_exceptions.py +0 -107
  164. meshcode-2.11.107/tests/test_mark_read_batch.py +0 -200
  165. meshcode-2.11.107/tests/test_migration_integrity.py +0 -176
  166. meshcode-2.11.107/tests/test_realtime_event_freshness.py +0 -236
  167. meshcode-2.11.107/tests/test_rls_cross_tenant.py +0 -255
  168. meshcode-2.11.107/tests/test_security_regressions.py +0 -171
  169. meshcode-2.11.107/tests/test_sentinel.py +0 -148
  170. meshcode-2.11.107/tests/test_status_enum_coverage.py +0 -231
  171. {meshcode-2.11.107 → meshcode-2.11.108}/README.md +0 -0
  172. {meshcode-2.11.107 → meshcode-2.11.108}/meshcode/__main__.py +0 -0
  173. {meshcode-2.11.107 → meshcode-2.11.108}/meshcode/_session_handoff_template 2.py +0 -0
  174. {meshcode-2.11.107 → meshcode-2.11.108}/meshcode/_session_handoff_template 3.py +0 -0
  175. {meshcode-2.11.107 → meshcode-2.11.108}/meshcode/_session_handoff_template.py +0 -0
  176. {meshcode-2.11.107 → meshcode-2.11.108}/meshcode/_stop_hook_template.py +0 -0
  177. {meshcode-2.11.107 → meshcode-2.11.108}/meshcode/ascii_art.py +0 -0
  178. {meshcode-2.11.107 → meshcode-2.11.108}/meshcode/atomic_push.py +0 -0
  179. {meshcode-2.11.107 → meshcode-2.11.108}/meshcode/claude_update 2.py +0 -0
  180. {meshcode-2.11.107 → meshcode-2.11.108}/meshcode/claude_update 3.py +0 -0
  181. {meshcode-2.11.107 → meshcode-2.11.108}/meshcode/claude_update.py +0 -0
  182. {meshcode-2.11.107/meshcode-backend-wt → meshcode-2.11.108}/meshcode/cli.py +0 -0
  183. {meshcode-2.11.107 → meshcode-2.11.108}/meshcode/comms_v4.py +0 -0
  184. {meshcode-2.11.107/meshcode-backend-wt → meshcode-2.11.108}/meshcode/compat.py +0 -0
  185. {meshcode-2.11.107 → meshcode-2.11.108}/meshcode/daemon.py +0 -0
  186. {meshcode-2.11.107 → meshcode-2.11.108}/meshcode/date_parse.py +0 -0
  187. {meshcode-2.11.107 → meshcode-2.11.108}/meshcode/doctor.py +0 -0
  188. {meshcode-2.11.107/meshcode-backend-wt → meshcode-2.11.108}/meshcode/error_hints.py +0 -0
  189. {meshcode-2.11.107/meshcode-backend-wt → meshcode-2.11.108}/meshcode/exceptions.py +0 -0
  190. {meshcode-2.11.107 → meshcode-2.11.108}/meshcode/hostd 2.py +0 -0
  191. {meshcode-2.11.107/meshcode-backend-wt → meshcode-2.11.108}/meshcode/invites.py +0 -0
  192. {meshcode-2.11.107/meshcode-backend-wt → meshcode-2.11.108}/meshcode/launcher.py +0 -0
  193. {meshcode-2.11.107/meshcode-backend-wt → meshcode-2.11.108}/meshcode/launcher_install.py +0 -0
  194. {meshcode-2.11.107/meshcode-backend-wt → meshcode-2.11.108}/meshcode/meshcode_mcp/__init__.py +0 -0
  195. {meshcode-2.11.107/meshcode-backend-wt → meshcode-2.11.108}/meshcode/meshcode_mcp/__main__.py +0 -0
  196. {meshcode-2.11.107 → meshcode-2.11.108}/meshcode/meshcode_mcp/backend.py +0 -0
  197. {meshcode-2.11.107 → meshcode-2.11.108}/meshcode/meshcode_mcp/realtime.py +0 -0
  198. {meshcode-2.11.107 → meshcode-2.11.108}/meshcode/meshcode_mcp/sleep_signals.py +0 -0
  199. {meshcode-2.11.107/meshcode-backend-wt → meshcode-2.11.108}/meshcode/meshcode_mcp/test_backend.py +0 -0
  200. {meshcode-2.11.107 → meshcode-2.11.108}/meshcode/meshcode_mcp/test_boot_timing.py +0 -0
  201. {meshcode-2.11.107 → meshcode-2.11.108}/meshcode/meshcode_mcp/test_install_guard.py +0 -0
  202. {meshcode-2.11.107 → meshcode-2.11.108}/meshcode/meshcode_mcp/test_prefs_claude_version.py +0 -0
  203. {meshcode-2.11.107/meshcode-backend-wt → meshcode-2.11.108}/meshcode/meshcode_mcp/test_realtime.py +0 -0
  204. {meshcode-2.11.107/meshcode-backend-wt → meshcode-2.11.108}/meshcode/meshcode_mcp/test_server_wrapper.py +0 -0
  205. {meshcode-2.11.107/meshcode-backend-wt → meshcode-2.11.108}/meshcode/preferences.py +0 -0
  206. {meshcode-2.11.107/meshcode-backend-wt → meshcode-2.11.108}/meshcode/protocol_v2.py +0 -0
  207. {meshcode-2.11.107 → meshcode-2.11.108}/meshcode/quickstart.py +0 -0
  208. {meshcode-2.11.107 → meshcode-2.11.108}/meshcode/rpc_allowlist.py +0 -0
  209. {meshcode-2.11.107 → meshcode-2.11.108}/meshcode/scripts/check_secrets.py +0 -0
  210. {meshcode-2.11.107 → meshcode-2.11.108}/meshcode/scripts/race_rate_harness.py +0 -0
  211. {meshcode-2.11.107/meshcode-backend-wt → meshcode-2.11.108}/meshcode/secrets.py +0 -0
  212. {meshcode-2.11.107 → meshcode-2.11.108}/meshcode/self_update.py +0 -0
  213. {meshcode-2.11.107/meshcode-backend-wt → meshcode-2.11.108}/meshcode/supervisor.py +0 -0
  214. {meshcode-2.11.107 → meshcode-2.11.108}/meshcode/up 2.py +0 -0
  215. {meshcode-2.11.107 → meshcode-2.11.108}/meshcode/up.py +0 -0
  216. {meshcode-2.11.107/meshcode-backend-wt → meshcode-2.11.108}/meshcode/upload.py +0 -0
  217. {meshcode-2.11.107 → meshcode-2.11.108}/meshcode.egg-info/dependency_links.txt +0 -0
  218. {meshcode-2.11.107 → meshcode-2.11.108}/meshcode.egg-info/entry_points.txt +0 -0
  219. {meshcode-2.11.107 → meshcode-2.11.108}/meshcode.egg-info/requires.txt +0 -0
  220. {meshcode-2.11.107 → meshcode-2.11.108}/setup.cfg +0 -0
  221. {meshcode-2.11.107 → meshcode-2.11.108}/tests/test_auto_update_hardening.py +0 -0
  222. {meshcode-2.11.107 → meshcode-2.11.108}/tests/test_autonomous_closegap_1.py +0 -0
  223. {meshcode-2.11.107 → meshcode-2.11.108}/tests/test_autonomous_closegap_2.py +0 -0
  224. {meshcode-2.11.107 → meshcode-2.11.108}/tests/test_autonomous_closegap_3.py +0 -0
  225. {meshcode-2.11.107 → meshcode-2.11.108}/tests/test_autonomous_prompt_inject 2.py +0 -0
  226. {meshcode-2.11.107 → meshcode-2.11.108}/tests/test_autonomous_prompt_inject 3.py +0 -0
  227. {meshcode-2.11.107 → meshcode-2.11.108}/tests/test_autonomous_prompt_inject.py +0 -0
  228. {meshcode-2.11.107 → meshcode-2.11.108}/tests/test_boot_bug_regression.py +0 -0
  229. {meshcode-2.11.107 → meshcode-2.11.108}/tests/test_color_truecolor.py +0 -0
  230. {meshcode-2.11.107/meshcode-backend-wt → meshcode-2.11.108}/tests/test_core.py +0 -0
  231. {meshcode-2.11.107/meshcode-backend-wt → meshcode-2.11.108}/tests/test_cross_agent_messaging.py +0 -0
  232. {meshcode-2.11.107 → meshcode-2.11.108}/tests/test_date_parse.py +0 -0
  233. {meshcode-2.11.107 → meshcode-2.11.108}/tests/test_doctor.py +0 -0
  234. {meshcode-2.11.107 → meshcode-2.11.108}/tests/test_epistemic_v1_python_sdk.py +0 -0
  235. {meshcode-2.11.107 → meshcode-2.11.108}/tests/test_epistemic_v1_stop_conditions.py +0 -0
  236. {meshcode-2.11.107/meshcode-backend-wt → meshcode-2.11.108}/tests/test_esc_deaf_state.py +0 -0
  237. {meshcode-2.11.107/meshcode-backend-wt → meshcode-2.11.108}/tests/test_exceptions.py +0 -0
  238. {meshcode-2.11.107 → meshcode-2.11.108}/tests/test_file_upload.py +0 -0
  239. {meshcode-2.11.107 → meshcode-2.11.108}/tests/test_init_device_code.py +0 -0
  240. {meshcode-2.11.107 → meshcode-2.11.108}/tests/test_install_guard.py +0 -0
  241. {meshcode-2.11.107 → meshcode-2.11.108}/tests/test_lease_sigterm_release.py +0 -0
  242. {meshcode-2.11.107/meshcode-backend-wt → meshcode-2.11.108}/tests/test_mark_read_batch.py +0 -0
  243. {meshcode-2.11.107 → meshcode-2.11.108}/tests/test_marketplace_ratings.py +0 -0
  244. {meshcode-2.11.107/meshcode-backend-wt → meshcode-2.11.108}/tests/test_migration_integrity.py +0 -0
  245. {meshcode-2.11.107/meshcode-backend-wt → meshcode-2.11.108}/tests/test_realtime_event_freshness.py +0 -0
  246. {meshcode-2.11.107/meshcode-backend-wt → meshcode-2.11.108}/tests/test_rls_cross_tenant.py +0 -0
  247. {meshcode-2.11.107 → meshcode-2.11.108}/tests/test_rpc_grants.py +0 -0
  248. {meshcode-2.11.107 → meshcode-2.11.108}/tests/test_rpc_migrations.py +0 -0
  249. {meshcode-2.11.107 → meshcode-2.11.108}/tests/test_run_agent_dry_run.py +0 -0
  250. {meshcode-2.11.107 → meshcode-2.11.108}/tests/test_run_agent_no_server_import.py +0 -0
  251. {meshcode-2.11.107/meshcode-backend-wt → meshcode-2.11.108}/tests/test_security_regressions.py +0 -0
  252. {meshcode-2.11.107 → meshcode-2.11.108}/tests/test_self_update_user_site.py +0 -0
  253. {meshcode-2.11.107/meshcode-backend-wt → meshcode-2.11.108}/tests/test_sentinel.py +0 -0
  254. {meshcode-2.11.107 → meshcode-2.11.108}/tests/test_setup_path.py +0 -0
  255. {meshcode-2.11.107 → meshcode-2.11.108}/tests/test_sleep_signals.py +0 -0
  256. {meshcode-2.11.107/meshcode-backend-wt → meshcode-2.11.108}/tests/test_status_enum_coverage.py +0 -0
  257. {meshcode-2.11.107 → meshcode-2.11.108}/tests/test_stay_on_loop_hook.py +0 -0
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.4
2
2
  Name: meshcode
3
- Version: 2.11.107
3
+ Version: 2.11.108
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.107"
2
+ __version__ = "2.11.108"
3
3
 
4
4
  # Exception hierarchy — eagerly imported (lightweight, no deps)
5
5
  from meshcode.exceptions import ( # noqa: F401
@@ -503,6 +503,48 @@ def _do_respawns(api_key: str, host_id: str) -> int:
503
503
  # only guard; for crash respawns it's a harmless backstop (the server
504
504
  # rate-limit at mig404 is stricter and trips first).
505
505
  _target = f"{proj}/{agent}"
506
+ # CONVERGENCE GUARD (451d33a0) — recycle fast-path ONLY. Stops the env-mismatch
507
+ # recycle-RESPAWN storm the version-recycle guard can't see (see _recycle_blocked).
508
+ # Counts consecutive recycle-respawns of this target; at _RECYREC_MAX within the
509
+ # window it blocks relaunch + alerts once, instead of storming terminals forever.
510
+ if _is_recycle:
511
+ _rst = _load_state()
512
+ _rblk = _recycle_blocked(_rst, _target)
513
+ if _rblk:
514
+ _log(f"SKIP recycle-respawn {_target}: BLOCKED ({_rblk}) — non-converging recycle; "
515
+ f"holding relaunch (auto-retry after {_RECYREC_BLOCK_TTL_S}s or a manual Start).")
516
+ continue
517
+ _now = time.time()
518
+ _rrall = dict(_rst.get("recyrespawn") or {})
519
+ _rr = dict(_rrall.get(_target) or {})
520
+ if _rr.get("last_ts") and (_now - float(_rr["last_ts"])) <= _RECYREC_WINDOW_S:
521
+ _rr["count"] = int(_rr.get("count", 0)) + 1
522
+ else:
523
+ _rr = {"count": 1} # window elapsed (converged/idle) -> fresh count, clears any stale block
524
+ _rr["last_ts"] = _now
525
+ if _rr["count"] >= _RECYREC_MAX:
526
+ _rr["blocked_ts"] = _now
527
+ _rr["reason"] = "recycle_no_converge"
528
+ _rrall[_target] = _rr
529
+ _rst["recyrespawn"] = _rrall
530
+ _save_state(_rst)
531
+ _log(f"RECYCLE-STUCK {_target}: {_rr['count']} recycle-respawns in <={_RECYREC_WINDOW_S}s "
532
+ f"without converging — spawn env likely older than hostd; align it "
533
+ f"(e.g. ~/meshcode-env/bin/pip install -U meshcode==<disk>). BLOCKING recycle-respawns "
534
+ f"for {_RECYREC_BLOCK_TTL_S}s. [recycle_blocked_reason=recycle_no_converge]")
535
+ try: # stop the dashboard's eternal 'launching…' spinner (same pattern as the breaker)
536
+ _rpc("mc_resolve_launch", {
537
+ "p_api_key": api_key, "p_project_id": c.get("project_id"), "p_agent": agent,
538
+ "p_status": "failed", "p_reason": "recycle_no_converge",
539
+ "p_detail": "recycle keeps relaunching without converging — this agent's MCP env is "
540
+ "older than the host; align it (pip install -U meshcode==<host version>), "
541
+ "then Start again"})
542
+ except Exception:
543
+ pass
544
+ continue
545
+ _rrall[_target] = _rr
546
+ _rst["recyrespawn"] = _rrall
547
+ _save_state(_rst)
506
548
  _ok, _burst, _why = _spawn_rate_ok(_target)
507
549
  if not _ok:
508
550
  _log(f"SKIP {'recycle-' if _is_recycle else ''}respawn {_target}: rate-limited ({_why})")
@@ -591,6 +633,40 @@ def _save_state(st: dict) -> None:
591
633
  pass
592
634
 
593
635
 
636
+ # ------------------------------------------------------------------
637
+ # Recycle non-convergence guard (451d33a0). The env-mismatch storm is a recycle-
638
+ # RESPAWN loop (log: "RECYCLE-RESPAWN <agent> (stale 15-37s, count=0)" every
639
+ # ~15-37s) that the version-recycle guard in _do_version_recycles can NOT see —
640
+ # that guard sits on the version-recycle REQUEST path and its counter only
641
+ # advances on a successful mc_request_recycle, so when a recycle is already
642
+ # pending (requested=False) the counter stays 0 and never trips. This guard sits
643
+ # on the recycle fast-path itself: if a target recycle-respawns _RECYREC_MAX times
644
+ # within _RECYREC_WINDOW_S without converging, STOP relaunching it + alert once
645
+ # (env mismatch) instead of storming terminals forever. Self-heals — the block
646
+ # lifts after _RECYREC_BLOCK_TTL_S (one clean retry; re-blocks if it storms again),
647
+ # and the counter resets the moment the target stops re-qualifying (converged).
648
+ _RECYREC_MAX = _env_int("MESHCODE_RECYREC_MAX", 3, 2) # recycle-respawns before non-converge
649
+ _RECYREC_WINDOW_S = _env_int("MESHCODE_RECYREC_WINDOW_SEC", 120, 30) # consecutive-respawn counting window
650
+ _RECYREC_BLOCK_TTL_S = _env_int("MESHCODE_RECYREC_BLOCK_TTL_SEC", 600, 60) # block duration before a retry
651
+
652
+
653
+ def _recycle_blocked(st, target, now=None):
654
+ """Shared guard consulted by BOTH _do_respawns (skip the recycle fast-path)
655
+ and _do_version_recycles (don't version-recycle a non-converging target).
656
+ Returns a reason string while `target` is blocked, else None. The block
657
+ auto-expires after _RECYREC_BLOCK_TTL_S so a fixed env gets one clean retry."""
658
+ now = now if now is not None else time.time()
659
+ rec = (st.get("recyrespawn") or {}).get(target) or {}
660
+ bts = rec.get("blocked_ts")
661
+ if bts:
662
+ try:
663
+ if (now - float(bts)) < _RECYREC_BLOCK_TTL_S:
664
+ return rec.get("reason") or "recycle_no_converge"
665
+ except (TypeError, ValueError):
666
+ return None
667
+ return None
668
+
669
+
594
670
  def _spawn_rate_ok(target: str):
595
671
  """Anti-spam circuit breaker. Returns (ok, tripped_burst, reason).
596
672
 
@@ -1442,6 +1518,8 @@ def _do_version_recycles(api_key: str, host_id: str) -> int:
1442
1518
  proj, agent = a.get("project_name"), a.get("name")
1443
1519
  if not proj or not agent:
1444
1520
  continue
1521
+ if _recycle_blocked(st, f"{proj}/{agent}", now):
1522
+ continue # 451d33a0 unify: already blocked as a non-converging recycle — don't also version-recycle it
1445
1523
  key = f"verrec/{a.get('project_id')}/{agent}"
1446
1524
  if now - float(st.get(key, 0) or 0) < 1800:
1447
1525
  continue # rate-limit: <=1 version-recycle per agent / 30min (no recycle-storm)
@@ -1731,6 +1731,8 @@ def _build_instructions() -> str:
1731
1731
 
1732
1732
  RULES: MCP tools only. Tasks > messages. Messages <100 tokens (long → task). No empty acks, JSON only. Thread via in_reply_to. sensitive=True for secrets. Sync vs async: for turn-based/shared-state work (chess, lock-step, "who goes first"), use meshcode_call (sync RPC, 30s) — async meshcode_send crosses ~50%/turn between same-model agents and yields-pongs.
1733
1733
 
1734
+ REPLY TO HUMANS VIA THE MESH, NOT THE TERMINAL (product default, Samuel 2026-06-04): when you answer a human (sammybenu/Samuel/ian/fis), you MUST meshcode_send to the mesh. The human watches the DASHBOARD — your Claude Code terminal text and your thinking are INVISIBLE to them, so a terminal-only reply reads as silence ("¿por qué no me contestas?" even while you "answered"). meshcode_send is the ONLY channel they see. To humans write plain prose in THEIR language (Spanish for Samuel), never JSON; JSON-only is for agent↔agent.
1735
+
1734
1736
  CLOSE TASKS IMMEDIATELY (#2 rule, sammybenu 2026-05-22T21:06Z): every time you finish/ship/deliver work for a claimed task, call meshcode_task_complete BEFORE re-entering wait. NO "I'll close it after one more thing." NO leaving claimed tasks lingering in_progress while you do something else — that creates phantom in-progress on the dashboard and the human gets angry. If the work needs human review, set requires_approval=true at task_create OR call meshcode_task_complete (it routes to in_review if reviewer set). The mesh dashboard reflects mc_tasks.status in real-time; stale in_progress = lying to the human.
1735
1737
 
1736
1738
  WORK ASSIGNED TASKS IMMEDIATELY (#3 rule): when meshcode_wait returns pending_tasks or auto_started_task, your NEXT action MUST be to work that task. Do NOT re-enter wait, do NOT ask "what should I do" — the task description tells you. Sequence: read task description → execute the work → meshcode_task_complete → meshcode_wait (which surfaces the next task). One by one until the queue is empty.
@@ -17,15 +17,125 @@ from __future__ import annotations
17
17
  import json
18
18
  import os
19
19
  import platform
20
+ import re
20
21
  import shlex
21
22
  import shutil
22
23
  import subprocess
23
24
  import sys
25
+ import time
24
26
  import urllib.parse
25
27
  from pathlib import Path
26
28
  from typing import Iterable, Optional
27
29
 
28
30
 
31
+ # SECURITY (audit P1-4 RCE/DoS): agent names get interpolated into the platform
32
+ # shell / cmd.exe launch string below. shlex.quote is POSIX-only and does NOT
33
+ # neutralize cmd.exe metacharacters, so a name like `x" & calc & "` would break
34
+ # out of the quoting on Windows (cmd /k) and execute arbitrary code. Real agent
35
+ # names are always plain identifiers — hard-reject anything else at the boundary.
36
+ # Hardened allowlist (chief@mesh-dev spec):
37
+ # - first char [A-Za-z0-9_] -> NO leading dash, so `-rf` / `--version` can't be
38
+ # read as a flag/arg if the name ever reaches a bare positional (arg-injection)
39
+ # - then [A-Za-z0-9_-]{0,63} -> total length 1..64, capping the 300-char-name DoS
40
+ # - anchor with \Z, not $ -> in Python `$` also matches just before a trailing
41
+ # newline, so `name\n` would slip through `^...$`. \Z = absolute end of string.
42
+ _VALID_AGENT_NAME = re.compile(r"^[A-Za-z0-9_][A-Za-z0-9_-]{0,63}\Z")
43
+
44
+ # Launch-storm control (audit P1: each "Launch All" click spawns a terminal per
45
+ # agent UNCONDITIONALLY; repeat clicks storm the desktop with dup terminals).
46
+ # Two dedup layers + a hard cap:
47
+ # (1) heartbeat liveness — skip agents already running (best-effort, network)
48
+ # (2) local cooldown file — per-agent last-spawn ts; covers the spawn->first-
49
+ # heartbeat gap where (1) is blind, and absorbs rapid repeat-clicks. No
50
+ # network, so it is the always-on backstop.
51
+ _MAX_BATCH = 32 # hard cap: agents spawned / call
52
+ _LAUNCH_COOLDOWN_S = 30 # min seconds between same-agent spawns
53
+ _LIVE_HEARTBEAT_S = 20 # heartbeat age < this = agent live
54
+ _COOLDOWN_FILE = Path.home() / ".meshcode" / "launch_cooldown.json"
55
+
56
+
57
+ def is_valid_agent_name(name: str) -> bool:
58
+ """Shared allowlist gate — True iff `name` is a safe agent identifier.
59
+
60
+ Single source of truth for the launch path AND `meshcode run` (run_agent),
61
+ so the RCE/DoS boundary can't drift between callers.
62
+ """
63
+ return bool(name) and bool(_VALID_AGENT_NAME.match(name))
64
+
65
+
66
+ def _read_cooldowns() -> dict:
67
+ try:
68
+ return json.loads(_COOLDOWN_FILE.read_text(encoding="utf-8")) or {}
69
+ except Exception:
70
+ return {}
71
+
72
+
73
+ def _record_spawn(name: str, now: Optional[float] = None) -> None:
74
+ """Stamp `name`'s last-spawn ts in the cooldown file (best-effort, atomic)."""
75
+ try:
76
+ data = _read_cooldowns()
77
+ data[name] = now if now is not None else time.time()
78
+ _COOLDOWN_FILE.parent.mkdir(parents=True, exist_ok=True)
79
+ tmp = _COOLDOWN_FILE.with_suffix(".json.tmp")
80
+ tmp.write_text(json.dumps(data), encoding="utf-8")
81
+ tmp.replace(_COOLDOWN_FILE)
82
+ except Exception:
83
+ pass
84
+
85
+
86
+ def _in_cooldown(name: str, cooldowns: dict, now: float) -> bool:
87
+ try:
88
+ return (now - float(cooldowns.get(name, 0))) < _LAUNCH_COOLDOWN_S
89
+ except (TypeError, ValueError):
90
+ return False
91
+
92
+
93
+ def live_agent_names(names: Iterable[str], project: Optional[str] = None) -> set:
94
+ """Best-effort set of `names` whose mc_agents heartbeat is fresh (<20s).
95
+
96
+ Shared liveness primitive for the dedup lane (co-owned w/ chief@mesh-dev).
97
+ Network + creds required; ANY failure (offline, no api_key, project
98
+ unresolved, RPC error) returns an EMPTY set so a legitimate launch is never
99
+ blocked — the cooldown file is the always-on backstop. NB: the meshcode://
100
+ launch URL carries no project today, so resolution falls back to
101
+ MESHCODE_PROJECT env; pass `project` explicitly for reliable liveness.
102
+ """
103
+ wanted = {n for n in names if is_valid_agent_name(n)}
104
+ if not wanted:
105
+ return set()
106
+ try:
107
+ import importlib
108
+ cv = importlib.import_module("meshcode.comms_v4")
109
+ api_key = cv._load_api_key_for_cli()
110
+ proj = project or os.environ.get("MESHCODE_PROJECT")
111
+ if not api_key or not proj:
112
+ return set()
113
+ pid = cv.get_project_id(proj)
114
+ if not pid:
115
+ return set()
116
+ r = cv.sb_rpc("mc_get_agents", {"p_api_key": api_key, "p_project_id": pid,
117
+ "p_agent_name": None, "p_select": None,
118
+ "p_limit": None})
119
+ agents = (r or {}).get("agents") or []
120
+ from datetime import datetime, timezone
121
+ now = datetime.now(timezone.utc)
122
+ live = set()
123
+ for a in agents:
124
+ nm = a.get("name")
125
+ ts = a.get("last_heartbeat")
126
+ if nm not in wanted or not ts:
127
+ continue
128
+ try:
129
+ dt = datetime.fromisoformat(str(ts).replace("Z", "+00:00"))
130
+ if (now - dt).total_seconds() < _LIVE_HEARTBEAT_S:
131
+ live.add(nm)
132
+ except Exception:
133
+ continue
134
+ return live
135
+ except Exception:
136
+ return set()
137
+
138
+
29
139
  # ============================================================
30
140
  # Per-OS terminal spawn
31
141
  # ============================================================
@@ -165,7 +275,37 @@ def cmd_launch_batch(agent_names: Iterable[str]) -> int:
165
275
  # Resolve `meshcode` binary path (CLI wrapper installed by pip).
166
276
  mc_bin = shutil.which("meshcode") or "meshcode"
167
277
 
278
+ # RATE LIMIT: hard-cap the batch so a crafted `agents=` list can't spawn an
279
+ # unbounded number of terminals (DoS). Excess is reported, never launched.
280
+ if len(names) > _MAX_BATCH:
281
+ for name in names[_MAX_BATCH:]:
282
+ skipped.append({"agent": name, "reason": f"batch cap {_MAX_BATCH} exceeded"})
283
+ names = names[:_MAX_BATCH]
284
+
285
+ # DEDUP inputs computed ONCE for the whole batch: live set (heartbeat) +
286
+ # cooldown snapshot. `now` is shared so all spawns in this call stamp the
287
+ # same instant.
288
+ live = live_agent_names(names)
289
+ cooldowns = _read_cooldowns()
290
+ now = time.time()
291
+
168
292
  for name in names:
293
+ # SECURITY (audit P1-4 RCE/DoS): reject any name that isn't a plain agent
294
+ # identifier BEFORE it reaches the shell/cmd.exe launch string below.
295
+ if not is_valid_agent_name(name):
296
+ skipped.append({"agent": name,
297
+ "reason": "invalid agent name (allowlist ^[A-Za-z0-9_][A-Za-z0-9_-]{0,63}$)"})
298
+ continue
299
+ # DEDUP 1: agent already running (fresh heartbeat) -> don't double-spawn.
300
+ if name in live:
301
+ skipped.append({"agent": name, "reason": "already live (heartbeat <20s)"})
302
+ continue
303
+ # DEDUP 2: spawned within the cooldown window -> absorbs repeat-clicks and
304
+ # the spawn->first-heartbeat gap that layer 1 cannot see.
305
+ if _in_cooldown(name, cooldowns, now):
306
+ skipped.append({"agent": name,
307
+ "reason": f"cooldown {_LAUNCH_COOLDOWN_S}s (recently launched)"})
308
+ continue
169
309
  # PER-PLATFORM quoting (mesh-core FIX2): cmd.exe wants double-quotes, not POSIX shlex
170
310
  # single-quotes (cmd.exe passes single-quotes through literally -> file-not-found).
171
311
  if sys.platform == "win32":
@@ -175,6 +315,7 @@ def cmd_launch_batch(agent_names: Iterable[str]) -> int:
175
315
  ok, info = _spawn_terminal(cmd)
176
316
  if ok:
177
317
  launched.append(name)
318
+ _record_spawn(name, now)
178
319
  else:
179
320
  skipped.append({"agent": name, "reason": info})
180
321
 
@@ -695,6 +695,21 @@ def run(agent: str, project: Optional[str] = None, editor_override: Optional[str
695
695
  boot path flips mc_agents.autonomous_mode=true at register time.
696
696
  Task f248d98e Phase 1 (no-DDL subset).
697
697
  """
698
+ # SECURITY (audit P1-4): the agent name flows into workspace path lookups and
699
+ # a child editor/`claude` launch. Reject anything that isn't a plain agent
700
+ # identifier (esp. a leading dash, which a child tool could read as a flag) —
701
+ # belt-and-suspenders with the launch-batch allowlist (shared source of truth).
702
+ try:
703
+ from meshcode.protocol_handler import is_valid_agent_name as _ok_name
704
+ except Exception:
705
+ import re as _re
706
+ _ok_name = lambda n: bool(n) and bool(
707
+ _re.match(r"^[A-Za-z0-9_][A-Za-z0-9_-]{0,63}\Z", str(n)))
708
+ if not _ok_name(agent):
709
+ print(json.dumps({"ok": False, "error": f"invalid agent name: {agent!r}",
710
+ "error_code": "invalid_agent_name"}))
711
+ return 1
712
+
698
713
  # Propagate autonomous flag to the editor + MCP child via env var.
699
714
  if autonomous:
700
715
  os.environ["MESHCODE_AUTONOMOUS"] = "1"
@@ -1333,6 +1333,11 @@ If `meshcode_wait()` times out, call it again with a 2× longer timeout (cap 180
1333
1333
  - Tasks > messages. Use `meshcode_task_create / task_claim / task_complete`
1334
1334
  for trackable work. Keep messages <100 tokens (signals only).
1335
1335
  - No empty acks. JSON reports only.
1336
+ - **Reply to humans via the mesh, NOT the terminal** (product default): when you
1337
+ answer a human (Samuel/sammybenu/ian/fis), `meshcode_send` to the mesh. The
1338
+ human watches the DASHBOARD — your Claude Code terminal text + thinking are
1339
+ invisible to them, so a terminal-only reply reads as silence. Write plain prose
1340
+ in their language (Spanish for Samuel), never JSON — JSON is for agent↔agent.
1336
1341
  - Threading: pass `in_reply_to`.
1337
1342
  - Sync vs async: for turn-based or shared-state coordination (chess, single-writer
1338
1343
  doc, lock-step handoffs, "who goes first" decisions), prefer
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.4
2
2
  Name: meshcode
3
- Version: 2.11.107
3
+ Version: 2.11.108
4
4
  Summary: Real-time communication between AI agents — Supabase-backed CLI
5
5
  Author-email: MeshCode <hello@meshcode.io>
6
6
  License: MIT
@@ -0,0 +1,97 @@
1
+ README.md
2
+ pyproject.toml
3
+ meshcode/__init__.py
4
+ meshcode/__main__.py
5
+ meshcode/_session_handoff_template 2.py
6
+ meshcode/_session_handoff_template 3.py
7
+ meshcode/_session_handoff_template.py
8
+ meshcode/_stop_hook_template.py
9
+ meshcode/ascii_art.py
10
+ meshcode/atomic_push.py
11
+ meshcode/claude_update 2.py
12
+ meshcode/claude_update 3.py
13
+ meshcode/claude_update.py
14
+ meshcode/cli.py
15
+ meshcode/comms_v4.py
16
+ meshcode/compat.py
17
+ meshcode/daemon.py
18
+ meshcode/date_parse.py
19
+ meshcode/doctor.py
20
+ meshcode/error_hints.py
21
+ meshcode/exceptions.py
22
+ meshcode/hostd 2.py
23
+ meshcode/hostd.py
24
+ meshcode/invites.py
25
+ meshcode/launcher.py
26
+ meshcode/launcher_install.py
27
+ meshcode/preferences.py
28
+ meshcode/protocol_handler.py
29
+ meshcode/protocol_v2.py
30
+ meshcode/quickstart.py
31
+ meshcode/rpc_allowlist.py
32
+ meshcode/run_agent.py
33
+ meshcode/secrets.py
34
+ meshcode/self_update.py
35
+ meshcode/setup_clients.py
36
+ meshcode/supervisor.py
37
+ meshcode/up 2.py
38
+ meshcode/up.py
39
+ meshcode/upload.py
40
+ meshcode.egg-info/PKG-INFO
41
+ meshcode.egg-info/SOURCES.txt
42
+ meshcode.egg-info/dependency_links.txt
43
+ meshcode.egg-info/entry_points.txt
44
+ meshcode.egg-info/requires.txt
45
+ meshcode.egg-info/top_level.txt
46
+ meshcode/meshcode_mcp/__init__.py
47
+ meshcode/meshcode_mcp/__main__.py
48
+ meshcode/meshcode_mcp/backend.py
49
+ meshcode/meshcode_mcp/realtime.py
50
+ meshcode/meshcode_mcp/server.py
51
+ meshcode/meshcode_mcp/sleep_signals.py
52
+ meshcode/meshcode_mcp/test_backend.py
53
+ meshcode/meshcode_mcp/test_boot_timing.py
54
+ meshcode/meshcode_mcp/test_install_guard.py
55
+ meshcode/meshcode_mcp/test_prefs_claude_version.py
56
+ meshcode/meshcode_mcp/test_realtime.py
57
+ meshcode/meshcode_mcp/test_server_wrapper.py
58
+ meshcode/scripts/check_secrets.py
59
+ meshcode/scripts/race_rate_harness.py
60
+ tests/test_auto_update_hardening.py
61
+ tests/test_autonomous_closegap_1.py
62
+ tests/test_autonomous_closegap_2.py
63
+ tests/test_autonomous_closegap_3.py
64
+ tests/test_autonomous_prompt_inject 2.py
65
+ tests/test_autonomous_prompt_inject 3.py
66
+ tests/test_autonomous_prompt_inject.py
67
+ tests/test_boot_bug_regression.py
68
+ tests/test_color_truecolor.py
69
+ tests/test_core.py
70
+ tests/test_cross_agent_messaging.py
71
+ tests/test_date_parse.py
72
+ tests/test_doctor.py
73
+ tests/test_epistemic_v1_python_sdk.py
74
+ tests/test_epistemic_v1_stop_conditions.py
75
+ tests/test_esc_deaf_state.py
76
+ tests/test_exceptions.py
77
+ tests/test_file_upload.py
78
+ tests/test_init_device_code.py
79
+ tests/test_install_guard.py
80
+ tests/test_lease_sigterm_release.py
81
+ tests/test_mark_read_batch.py
82
+ tests/test_marketplace_ratings.py
83
+ tests/test_migration_integrity.py
84
+ tests/test_realtime_event_freshness.py
85
+ tests/test_rls_cross_tenant.py
86
+ tests/test_rpc_grants.py
87
+ tests/test_rpc_migrations.py
88
+ tests/test_run_agent_dry_run.py
89
+ tests/test_run_agent_no_server_import.py
90
+ tests/test_security_regressions.py
91
+ tests/test_self_update_user_site.py
92
+ tests/test_sentinel.py
93
+ tests/test_setup_path.py
94
+ tests/test_sleep_signals.py
95
+ tests/test_status_enum_coverage.py
96
+ tests/test_stay_on_loop_hook.py
97
+ tests/test_wait_open_tasks_contradiction.py
@@ -0,0 +1 @@
1
+ meshcode
@@ -4,7 +4,7 @@ build-backend = "setuptools.build_meta"
4
4
 
5
5
  [project]
6
6
  name = "meshcode"
7
- version = "2.11.107"
7
+ version = "2.11.108"
8
8
  description = "Real-time communication between AI agents — Supabase-backed CLI"
9
9
  readme = "README.md"
10
10
  license = {text = "MIT"}
@@ -47,7 +47,7 @@ testpaths = ["tests"]
47
47
  addopts = "--durations=10 --durations-min=0.5 -v --tb=short"
48
48
 
49
49
  [tool.setuptools.packages.find]
50
- include = ["meshcode*"]
50
+ include = ["meshcode", "meshcode.*"]
51
51
 
52
52
  [tool.setuptools.package-data]
53
53
  meshcode = ["comms_v4.py"]
@@ -74,8 +74,9 @@ class TestWaitContradictionFix(unittest.TestCase):
74
74
  # Look for the count_pending check inside meshcode_wait.
75
75
  wait_def_idx = self.source.find("async def meshcode_wait")
76
76
  self.assertGreater(wait_def_idx, 0)
77
- # 6000 chars covers the function body comfortably.
78
- wait_body = self.source[wait_def_idx:wait_def_idx + 6000]
77
+ # 8000 chars covers the function body comfortably (grew after the
78
+ # CHAT-DELIVERY-FIX which adds an unread-priority guard before task_pull).
79
+ wait_body = self.source[wait_def_idx:wait_def_idx + 8000]
79
80
  self.assertIn("count_pending", wait_body,
80
81
  "messages-block-wait path must still call count_pending")
81
82
  self.assertIn("read_inbox", wait_body,
@@ -1,42 +0,0 @@
1
- #!/usr/bin/env python3
2
- """MeshCode CLI entry point for pip install."""
3
- import sys
4
- import os
5
-
6
- # Force UTF-8 on stdout/stderr for Windows terminals (cp1252 default crashes
7
- # on emojis, em-dashes, and any non-ASCII output the CLI prints).
8
- # Python 3.7+ supports reconfigure(); older versions get a no-op.
9
- try:
10
- if hasattr(sys.stdout, "reconfigure"):
11
- sys.stdout.reconfigure(encoding="utf-8", errors="replace")
12
- if hasattr(sys.stderr, "reconfigure"):
13
- sys.stderr.reconfigure(encoding="utf-8", errors="replace")
14
- except Exception:
15
- pass
16
-
17
-
18
- def main():
19
- """Entry point that delegates to comms_v4.py within the package."""
20
- # Find comms_v4.py — first in package dir, then in repo root
21
- pkg_dir = os.path.dirname(os.path.abspath(__file__))
22
- repo_root = os.path.dirname(pkg_dir)
23
-
24
- for candidate in [
25
- os.path.join(pkg_dir, "comms_v4.py"),
26
- os.path.join(repo_root, "comms_v4.py"),
27
- ]:
28
- if os.path.exists(candidate):
29
- sys.argv[0] = candidate
30
- # Set __name__ and __file__ for the script
31
- globs = {"__name__": "__main__", "__file__": candidate}
32
- # Force UTF-8 on Windows (cp1252 default crashes on non-ASCII)
33
- with open(candidate, encoding="utf-8") as f:
34
- exec(compile(f.read(), candidate, "exec"), globs)
35
- return
36
-
37
- print("[meshcode] ERROR: comms_v4.py not found. Reinstall: pip install meshcode")
38
- sys.exit(1)
39
-
40
-
41
- if __name__ == "__main__":
42
- main()