meshcode 2.10.94__tar.gz → 2.10.95__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 (207) hide show
  1. {meshcode-2.10.94 → meshcode-2.10.95}/PKG-INFO +1 -1
  2. meshcode-2.10.95/meshcode/__init__.py +82 -0
  3. {meshcode-2.10.94 → meshcode-2.10.95}/meshcode/meshcode_mcp/backend.py +92 -16
  4. {meshcode-2.10.94 → meshcode-2.10.95}/meshcode/meshcode_mcp/server.py +52 -19
  5. {meshcode-2.10.94 → meshcode-2.10.95}/meshcode.egg-info/PKG-INFO +1 -1
  6. meshcode-2.10.95/meshcode.egg-info/PKG-INFO 2 +446 -0
  7. meshcode-2.10.95/meshcode.egg-info/SOURCES.txt +204 -0
  8. meshcode-2.10.95/meshcode.egg-info/dependency_links.txt +1 -0
  9. meshcode-2.10.95/meshcode.egg-info/entry_points.txt +3 -0
  10. meshcode-2.10.95/meshcode.egg-info/requires.txt +5 -0
  11. meshcode-2.10.95/meshcode.egg-info/top_level.txt +4 -0
  12. {meshcode-2.10.94 → meshcode-2.10.95}/pyproject.toml +1 -1
  13. meshcode-2.10.94/meshcode/__init__.py +0 -82
  14. {meshcode-2.10.94 → meshcode-2.10.95}/README.md +0 -0
  15. {meshcode-2.10.94 → meshcode-2.10.95}/meshcode/ascii_art.py +0 -0
  16. {meshcode-2.10.94 → meshcode-2.10.95}/meshcode/cli.py +0 -0
  17. {meshcode-2.10.94 → meshcode-2.10.95}/meshcode/comms_v4.py +0 -0
  18. {meshcode-2.10.94 → meshcode-2.10.95}/meshcode/compat.py +0 -0
  19. {meshcode-2.10.94 → meshcode-2.10.95}/meshcode/error_hints.py +0 -0
  20. {meshcode-2.10.94 → meshcode-2.10.95}/meshcode/exceptions.py +0 -0
  21. {meshcode-2.10.94 → meshcode-2.10.95}/meshcode/invites.py +0 -0
  22. {meshcode-2.10.94 → meshcode-2.10.95}/meshcode/launcher.py +0 -0
  23. {meshcode-2.10.94 → meshcode-2.10.95}/meshcode/launcher_install.py +0 -0
  24. {meshcode-2.10.94 → meshcode-2.10.95}/meshcode/meshcode_mcp/__init__.py +0 -0
  25. {meshcode-2.10.94 → meshcode-2.10.95}/meshcode/meshcode_mcp/__main__.py +0 -0
  26. {meshcode-2.10.94 → meshcode-2.10.95}/meshcode/meshcode_mcp/realtime.py +0 -0
  27. {meshcode-2.10.94 → meshcode-2.10.95}/meshcode/meshcode_mcp/test_backend.py +0 -0
  28. {meshcode-2.10.94 → meshcode-2.10.95}/meshcode/meshcode_mcp/test_realtime.py +0 -0
  29. {meshcode-2.10.94 → meshcode-2.10.95}/meshcode/meshcode_mcp/test_server_wrapper.py +0 -0
  30. {meshcode-2.10.94 → meshcode-2.10.95}/meshcode/preferences.py +0 -0
  31. {meshcode-2.10.94 → meshcode-2.10.95}/meshcode/protocol_v2.py +0 -0
  32. {meshcode-2.10.94 → meshcode-2.10.95}/meshcode/quickstart.py +0 -0
  33. {meshcode-2.10.94 → meshcode-2.10.95}/meshcode/run_agent.py +0 -0
  34. {meshcode-2.10.94 → meshcode-2.10.95}/meshcode/secrets.py +0 -0
  35. {meshcode-2.10.94 → meshcode-2.10.95}/meshcode/self_update.py +0 -0
  36. {meshcode-2.10.94 → meshcode-2.10.95}/meshcode/setup_clients.py +0 -0
  37. {meshcode-2.10.94 → meshcode-2.10.95}/meshcode/supervisor.py +0 -0
  38. {meshcode-2.10.94 → meshcode-2.10.95}/meshcode/upload.py +0 -0
  39. {meshcode-2.10.94 → meshcode-2.10.95}/meshcode-backend-wt/comms_v4.py +0 -0
  40. {meshcode-2.10.94 → meshcode-2.10.95}/meshcode-backend-wt/meshcode/__init__.py +0 -0
  41. {meshcode-2.10.94 → meshcode-2.10.95}/meshcode-backend-wt/meshcode/ascii_art.py +0 -0
  42. {meshcode-2.10.94 → meshcode-2.10.95}/meshcode-backend-wt/meshcode/cli.py +0 -0
  43. {meshcode-2.10.94 → meshcode-2.10.95}/meshcode-backend-wt/meshcode/comms_v4.py +0 -0
  44. {meshcode-2.10.94 → meshcode-2.10.95}/meshcode-backend-wt/meshcode/compat.py +0 -0
  45. {meshcode-2.10.94 → meshcode-2.10.95}/meshcode-backend-wt/meshcode/error_hints.py +0 -0
  46. {meshcode-2.10.94 → meshcode-2.10.95}/meshcode-backend-wt/meshcode/exceptions.py +0 -0
  47. {meshcode-2.10.94 → meshcode-2.10.95}/meshcode-backend-wt/meshcode/invites.py +0 -0
  48. {meshcode-2.10.94 → meshcode-2.10.95}/meshcode-backend-wt/meshcode/launcher.py +0 -0
  49. {meshcode-2.10.94 → meshcode-2.10.95}/meshcode-backend-wt/meshcode/launcher_install.py +0 -0
  50. {meshcode-2.10.94 → meshcode-2.10.95}/meshcode-backend-wt/meshcode/meshcode_mcp/__init__.py +0 -0
  51. {meshcode-2.10.94 → meshcode-2.10.95}/meshcode-backend-wt/meshcode/meshcode_mcp/__main__.py +0 -0
  52. {meshcode-2.10.94 → meshcode-2.10.95}/meshcode-backend-wt/meshcode/meshcode_mcp/backend.py +0 -0
  53. {meshcode-2.10.94 → meshcode-2.10.95}/meshcode-backend-wt/meshcode/meshcode_mcp/realtime.py +0 -0
  54. {meshcode-2.10.94 → meshcode-2.10.95}/meshcode-backend-wt/meshcode/meshcode_mcp/server.py +0 -0
  55. {meshcode-2.10.94 → meshcode-2.10.95}/meshcode-backend-wt/meshcode/meshcode_mcp/test_backend.py +0 -0
  56. {meshcode-2.10.94 → meshcode-2.10.95}/meshcode-backend-wt/meshcode/meshcode_mcp/test_realtime.py +0 -0
  57. {meshcode-2.10.94 → meshcode-2.10.95}/meshcode-backend-wt/meshcode/meshcode_mcp/test_server_wrapper.py +0 -0
  58. {meshcode-2.10.94 → meshcode-2.10.95}/meshcode-backend-wt/meshcode/preferences.py +0 -0
  59. {meshcode-2.10.94 → meshcode-2.10.95}/meshcode-backend-wt/meshcode/protocol_v2.py +0 -0
  60. {meshcode-2.10.94 → meshcode-2.10.95}/meshcode-backend-wt/meshcode/quickstart.py +0 -0
  61. {meshcode-2.10.94 → meshcode-2.10.95}/meshcode-backend-wt/meshcode/run_agent.py +0 -0
  62. {meshcode-2.10.94 → meshcode-2.10.95}/meshcode-backend-wt/meshcode/secrets.py +0 -0
  63. {meshcode-2.10.94 → meshcode-2.10.95}/meshcode-backend-wt/meshcode/self_update.py +0 -0
  64. {meshcode-2.10.94 → meshcode-2.10.95}/meshcode-backend-wt/meshcode/setup_clients.py +0 -0
  65. {meshcode-2.10.94 → meshcode-2.10.95}/meshcode-backend-wt/meshcode/supervisor.py +0 -0
  66. {meshcode-2.10.94 → meshcode-2.10.95}/meshcode-backend-wt/meshcode/upload.py +0 -0
  67. {meshcode-2.10.94 → meshcode-2.10.95}/meshcode-backend-wt/scripts/sentinel.py +0 -0
  68. {meshcode-2.10.94 → meshcode-2.10.95}/meshcode-backend-wt/tests/test_core.py +0 -0
  69. {meshcode-2.10.94 → meshcode-2.10.95}/meshcode-backend-wt/tests/test_cross_agent_messaging.py +0 -0
  70. {meshcode-2.10.94 → meshcode-2.10.95}/meshcode-backend-wt/tests/test_esc_deaf_state.py +0 -0
  71. {meshcode-2.10.94 → meshcode-2.10.95}/meshcode-backend-wt/tests/test_exceptions.py +0 -0
  72. {meshcode-2.10.94 → meshcode-2.10.95}/meshcode-backend-wt/tests/test_mark_read_batch.py +0 -0
  73. {meshcode-2.10.94 → meshcode-2.10.95}/meshcode-backend-wt/tests/test_migration_integrity.py +0 -0
  74. {meshcode-2.10.94 → meshcode-2.10.95}/meshcode-backend-wt/tests/test_realtime_event_freshness.py +0 -0
  75. {meshcode-2.10.94 → meshcode-2.10.95}/meshcode-backend-wt/tests/test_rls_cross_tenant.py +0 -0
  76. {meshcode-2.10.94 → meshcode-2.10.95}/meshcode-backend-wt/tests/test_rpc_migrations.py +0 -0
  77. {meshcode-2.10.94 → meshcode-2.10.95}/meshcode-backend-wt/tests/test_security_regressions.py +0 -0
  78. {meshcode-2.10.94 → meshcode-2.10.95}/meshcode-backend-wt/tests/test_sentinel.py +0 -0
  79. {meshcode-2.10.94 → meshcode-2.10.95}/meshcode-backend-wt/tests/test_status_enum_coverage.py +0 -0
  80. {meshcode-2.10.94 → meshcode-2.10.95}/meshcode-noun-wt/build/lib/meshcode/__init__.py +0 -0
  81. {meshcode-2.10.94 → meshcode-2.10.95}/meshcode-noun-wt/build/lib/meshcode/ascii_art.py +0 -0
  82. {meshcode-2.10.94 → meshcode-2.10.95}/meshcode-noun-wt/build/lib/meshcode/cli.py +0 -0
  83. {meshcode-2.10.94 → meshcode-2.10.95}/meshcode-noun-wt/build/lib/meshcode/comms_v4.py +0 -0
  84. {meshcode-2.10.94 → meshcode-2.10.95}/meshcode-noun-wt/build/lib/meshcode/compat.py +0 -0
  85. {meshcode-2.10.94 → meshcode-2.10.95}/meshcode-noun-wt/build/lib/meshcode/error_hints.py +0 -0
  86. {meshcode-2.10.94 → meshcode-2.10.95}/meshcode-noun-wt/build/lib/meshcode/exceptions.py +0 -0
  87. {meshcode-2.10.94 → meshcode-2.10.95}/meshcode-noun-wt/build/lib/meshcode/invites.py +0 -0
  88. {meshcode-2.10.94 → meshcode-2.10.95}/meshcode-noun-wt/build/lib/meshcode/launcher.py +0 -0
  89. {meshcode-2.10.94 → meshcode-2.10.95}/meshcode-noun-wt/build/lib/meshcode/launcher_install.py +0 -0
  90. {meshcode-2.10.94 → meshcode-2.10.95}/meshcode-noun-wt/build/lib/meshcode/meshcode_mcp/__init__.py +0 -0
  91. {meshcode-2.10.94 → meshcode-2.10.95}/meshcode-noun-wt/build/lib/meshcode/meshcode_mcp/__main__.py +0 -0
  92. {meshcode-2.10.94 → meshcode-2.10.95}/meshcode-noun-wt/build/lib/meshcode/meshcode_mcp/backend.py +0 -0
  93. {meshcode-2.10.94 → meshcode-2.10.95}/meshcode-noun-wt/build/lib/meshcode/meshcode_mcp/realtime.py +0 -0
  94. {meshcode-2.10.94 → meshcode-2.10.95}/meshcode-noun-wt/build/lib/meshcode/meshcode_mcp/server.py +0 -0
  95. {meshcode-2.10.94 → meshcode-2.10.95}/meshcode-noun-wt/build/lib/meshcode/meshcode_mcp/test_backend.py +0 -0
  96. {meshcode-2.10.94 → meshcode-2.10.95}/meshcode-noun-wt/build/lib/meshcode/meshcode_mcp/test_realtime.py +0 -0
  97. {meshcode-2.10.94 → meshcode-2.10.95}/meshcode-noun-wt/build/lib/meshcode/meshcode_mcp/test_server_wrapper.py +0 -0
  98. {meshcode-2.10.94 → meshcode-2.10.95}/meshcode-noun-wt/build/lib/meshcode/preferences.py +0 -0
  99. {meshcode-2.10.94 → meshcode-2.10.95}/meshcode-noun-wt/build/lib/meshcode/protocol_v2.py +0 -0
  100. {meshcode-2.10.94 → meshcode-2.10.95}/meshcode-noun-wt/build/lib/meshcode/quickstart.py +0 -0
  101. {meshcode-2.10.94 → meshcode-2.10.95}/meshcode-noun-wt/build/lib/meshcode/run_agent.py +0 -0
  102. {meshcode-2.10.94 → meshcode-2.10.95}/meshcode-noun-wt/build/lib/meshcode/secrets.py +0 -0
  103. {meshcode-2.10.94 → meshcode-2.10.95}/meshcode-noun-wt/build/lib/meshcode/self_update.py +0 -0
  104. {meshcode-2.10.94 → meshcode-2.10.95}/meshcode-noun-wt/build/lib/meshcode/setup_clients.py +0 -0
  105. {meshcode-2.10.94 → meshcode-2.10.95}/meshcode-noun-wt/build/lib/meshcode/supervisor.py +0 -0
  106. {meshcode-2.10.94 → meshcode-2.10.95}/meshcode-noun-wt/build/lib/meshcode/upload.py +0 -0
  107. {meshcode-2.10.94 → meshcode-2.10.95}/meshcode-noun-wt/comms_v4.py +0 -0
  108. {meshcode-2.10.94 → meshcode-2.10.95}/meshcode-noun-wt/meshcode/__init__.py +0 -0
  109. {meshcode-2.10.94 → meshcode-2.10.95}/meshcode-noun-wt/meshcode/ascii_art.py +0 -0
  110. {meshcode-2.10.94 → meshcode-2.10.95}/meshcode-noun-wt/meshcode/cli.py +0 -0
  111. {meshcode-2.10.94 → meshcode-2.10.95}/meshcode-noun-wt/meshcode/comms_v4.py +0 -0
  112. {meshcode-2.10.94 → meshcode-2.10.95}/meshcode-noun-wt/meshcode/compat.py +0 -0
  113. {meshcode-2.10.94 → meshcode-2.10.95}/meshcode-noun-wt/meshcode/error_hints.py +0 -0
  114. {meshcode-2.10.94 → meshcode-2.10.95}/meshcode-noun-wt/meshcode/exceptions.py +0 -0
  115. {meshcode-2.10.94 → meshcode-2.10.95}/meshcode-noun-wt/meshcode/invites.py +0 -0
  116. {meshcode-2.10.94 → meshcode-2.10.95}/meshcode-noun-wt/meshcode/launcher.py +0 -0
  117. {meshcode-2.10.94 → meshcode-2.10.95}/meshcode-noun-wt/meshcode/launcher_install.py +0 -0
  118. {meshcode-2.10.94 → meshcode-2.10.95}/meshcode-noun-wt/meshcode/meshcode_mcp/__init__.py +0 -0
  119. {meshcode-2.10.94 → meshcode-2.10.95}/meshcode-noun-wt/meshcode/meshcode_mcp/__main__.py +0 -0
  120. {meshcode-2.10.94 → meshcode-2.10.95}/meshcode-noun-wt/meshcode/meshcode_mcp/backend.py +0 -0
  121. {meshcode-2.10.94 → meshcode-2.10.95}/meshcode-noun-wt/meshcode/meshcode_mcp/realtime.py +0 -0
  122. {meshcode-2.10.94 → meshcode-2.10.95}/meshcode-noun-wt/meshcode/meshcode_mcp/server.py +0 -0
  123. {meshcode-2.10.94 → meshcode-2.10.95}/meshcode-noun-wt/meshcode/meshcode_mcp/test_backend.py +0 -0
  124. {meshcode-2.10.94 → meshcode-2.10.95}/meshcode-noun-wt/meshcode/meshcode_mcp/test_realtime.py +0 -0
  125. {meshcode-2.10.94 → meshcode-2.10.95}/meshcode-noun-wt/meshcode/meshcode_mcp/test_server_wrapper.py +0 -0
  126. {meshcode-2.10.94 → meshcode-2.10.95}/meshcode-noun-wt/meshcode/preferences.py +0 -0
  127. {meshcode-2.10.94 → meshcode-2.10.95}/meshcode-noun-wt/meshcode/protocol_v2.py +0 -0
  128. {meshcode-2.10.94 → meshcode-2.10.95}/meshcode-noun-wt/meshcode/quickstart.py +0 -0
  129. {meshcode-2.10.94 → meshcode-2.10.95}/meshcode-noun-wt/meshcode/run_agent.py +0 -0
  130. {meshcode-2.10.94 → meshcode-2.10.95}/meshcode-noun-wt/meshcode/secrets.py +0 -0
  131. {meshcode-2.10.94 → meshcode-2.10.95}/meshcode-noun-wt/meshcode/self_update.py +0 -0
  132. {meshcode-2.10.94 → meshcode-2.10.95}/meshcode-noun-wt/meshcode/setup_clients.py +0 -0
  133. {meshcode-2.10.94 → meshcode-2.10.95}/meshcode-noun-wt/meshcode/supervisor.py +0 -0
  134. {meshcode-2.10.94 → meshcode-2.10.95}/meshcode-noun-wt/meshcode/upload.py +0 -0
  135. {meshcode-2.10.94 → meshcode-2.10.95}/meshcode-noun-wt/scripts/sentinel.py +0 -0
  136. {meshcode-2.10.94 → meshcode-2.10.95}/meshcode-noun-wt/tests/test_core.py +0 -0
  137. {meshcode-2.10.94 → meshcode-2.10.95}/meshcode-noun-wt/tests/test_cross_agent_messaging.py +0 -0
  138. {meshcode-2.10.94 → meshcode-2.10.95}/meshcode-noun-wt/tests/test_esc_deaf_state.py +0 -0
  139. {meshcode-2.10.94 → meshcode-2.10.95}/meshcode-noun-wt/tests/test_exceptions.py +0 -0
  140. {meshcode-2.10.94 → meshcode-2.10.95}/meshcode-noun-wt/tests/test_mark_read_batch.py +0 -0
  141. {meshcode-2.10.94 → meshcode-2.10.95}/meshcode-noun-wt/tests/test_migration_integrity.py +0 -0
  142. {meshcode-2.10.94 → meshcode-2.10.95}/meshcode-noun-wt/tests/test_realtime_event_freshness.py +0 -0
  143. {meshcode-2.10.94 → meshcode-2.10.95}/meshcode-noun-wt/tests/test_rls_cross_tenant.py +0 -0
  144. {meshcode-2.10.94 → meshcode-2.10.95}/meshcode-noun-wt/tests/test_rpc_migrations.py +0 -0
  145. {meshcode-2.10.94 → meshcode-2.10.95}/meshcode-noun-wt/tests/test_security_regressions.py +0 -0
  146. {meshcode-2.10.94 → meshcode-2.10.95}/meshcode-noun-wt/tests/test_sentinel.py +0 -0
  147. {meshcode-2.10.94 → meshcode-2.10.95}/meshcode-noun-wt/tests/test_status_enum_coverage.py +0 -0
  148. {meshcode-2.10.94 → meshcode-2.10.95}/meshcode-tasks-wt/comms_v4.py +0 -0
  149. {meshcode-2.10.94 → meshcode-2.10.95}/meshcode-tasks-wt/meshcode/__init__.py +0 -0
  150. {meshcode-2.10.94 → meshcode-2.10.95}/meshcode-tasks-wt/meshcode/ascii_art.py +0 -0
  151. {meshcode-2.10.94 → meshcode-2.10.95}/meshcode-tasks-wt/meshcode/cli.py +0 -0
  152. {meshcode-2.10.94 → meshcode-2.10.95}/meshcode-tasks-wt/meshcode/comms_v4.py +0 -0
  153. {meshcode-2.10.94 → meshcode-2.10.95}/meshcode-tasks-wt/meshcode/compat.py +0 -0
  154. {meshcode-2.10.94 → meshcode-2.10.95}/meshcode-tasks-wt/meshcode/error_hints.py +0 -0
  155. {meshcode-2.10.94 → meshcode-2.10.95}/meshcode-tasks-wt/meshcode/exceptions.py +0 -0
  156. {meshcode-2.10.94 → meshcode-2.10.95}/meshcode-tasks-wt/meshcode/invites.py +0 -0
  157. {meshcode-2.10.94 → meshcode-2.10.95}/meshcode-tasks-wt/meshcode/launcher.py +0 -0
  158. {meshcode-2.10.94 → meshcode-2.10.95}/meshcode-tasks-wt/meshcode/launcher_install.py +0 -0
  159. {meshcode-2.10.94 → meshcode-2.10.95}/meshcode-tasks-wt/meshcode/meshcode_mcp/__init__.py +0 -0
  160. {meshcode-2.10.94 → meshcode-2.10.95}/meshcode-tasks-wt/meshcode/meshcode_mcp/__main__.py +0 -0
  161. {meshcode-2.10.94 → meshcode-2.10.95}/meshcode-tasks-wt/meshcode/meshcode_mcp/backend.py +0 -0
  162. {meshcode-2.10.94 → meshcode-2.10.95}/meshcode-tasks-wt/meshcode/meshcode_mcp/realtime.py +0 -0
  163. {meshcode-2.10.94 → meshcode-2.10.95}/meshcode-tasks-wt/meshcode/meshcode_mcp/server.py +0 -0
  164. {meshcode-2.10.94 → meshcode-2.10.95}/meshcode-tasks-wt/meshcode/meshcode_mcp/test_backend.py +0 -0
  165. {meshcode-2.10.94 → meshcode-2.10.95}/meshcode-tasks-wt/meshcode/meshcode_mcp/test_realtime.py +0 -0
  166. {meshcode-2.10.94 → meshcode-2.10.95}/meshcode-tasks-wt/meshcode/meshcode_mcp/test_server_wrapper.py +0 -0
  167. {meshcode-2.10.94 → meshcode-2.10.95}/meshcode-tasks-wt/meshcode/preferences.py +0 -0
  168. {meshcode-2.10.94 → meshcode-2.10.95}/meshcode-tasks-wt/meshcode/protocol_v2.py +0 -0
  169. {meshcode-2.10.94 → meshcode-2.10.95}/meshcode-tasks-wt/meshcode/quickstart.py +0 -0
  170. {meshcode-2.10.94 → meshcode-2.10.95}/meshcode-tasks-wt/meshcode/run_agent.py +0 -0
  171. {meshcode-2.10.94 → meshcode-2.10.95}/meshcode-tasks-wt/meshcode/secrets.py +0 -0
  172. {meshcode-2.10.94 → meshcode-2.10.95}/meshcode-tasks-wt/meshcode/self_update.py +0 -0
  173. {meshcode-2.10.94 → meshcode-2.10.95}/meshcode-tasks-wt/meshcode/setup_clients.py +0 -0
  174. {meshcode-2.10.94 → meshcode-2.10.95}/meshcode-tasks-wt/meshcode/supervisor.py +0 -0
  175. {meshcode-2.10.94 → meshcode-2.10.95}/meshcode-tasks-wt/meshcode/upload.py +0 -0
  176. {meshcode-2.10.94 → meshcode-2.10.95}/meshcode-tasks-wt/scripts/sentinel.py +0 -0
  177. {meshcode-2.10.94 → meshcode-2.10.95}/meshcode-tasks-wt/tests/test_core.py +0 -0
  178. {meshcode-2.10.94 → meshcode-2.10.95}/meshcode-tasks-wt/tests/test_cross_agent_messaging.py +0 -0
  179. {meshcode-2.10.94 → meshcode-2.10.95}/meshcode-tasks-wt/tests/test_esc_deaf_state.py +0 -0
  180. {meshcode-2.10.94 → meshcode-2.10.95}/meshcode-tasks-wt/tests/test_exceptions.py +0 -0
  181. {meshcode-2.10.94 → meshcode-2.10.95}/meshcode-tasks-wt/tests/test_mark_read_batch.py +0 -0
  182. {meshcode-2.10.94 → meshcode-2.10.95}/meshcode-tasks-wt/tests/test_migration_integrity.py +0 -0
  183. {meshcode-2.10.94 → meshcode-2.10.95}/meshcode-tasks-wt/tests/test_realtime_event_freshness.py +0 -0
  184. {meshcode-2.10.94 → meshcode-2.10.95}/meshcode-tasks-wt/tests/test_rls_cross_tenant.py +0 -0
  185. {meshcode-2.10.94 → meshcode-2.10.95}/meshcode-tasks-wt/tests/test_rpc_migrations.py +0 -0
  186. {meshcode-2.10.94 → meshcode-2.10.95}/meshcode-tasks-wt/tests/test_security_regressions.py +0 -0
  187. {meshcode-2.10.94 → meshcode-2.10.95}/meshcode-tasks-wt/tests/test_sentinel.py +0 -0
  188. {meshcode-2.10.94 → meshcode-2.10.95}/meshcode-tasks-wt/tests/test_status_enum_coverage.py +0 -0
  189. /meshcode-2.10.94/meshcode.egg-info/SOURCES.txt → /meshcode-2.10.95/meshcode.egg-info/SOURCES 2.txt +0 -0
  190. /meshcode-2.10.94/meshcode.egg-info/dependency_links.txt → /meshcode-2.10.95/meshcode.egg-info/dependency_links 2.txt +0 -0
  191. /meshcode-2.10.94/meshcode.egg-info/entry_points.txt → /meshcode-2.10.95/meshcode.egg-info/entry_points 2.txt +0 -0
  192. /meshcode-2.10.94/meshcode.egg-info/requires.txt → /meshcode-2.10.95/meshcode.egg-info/requires 2.txt +0 -0
  193. /meshcode-2.10.94/meshcode.egg-info/top_level.txt → /meshcode-2.10.95/meshcode.egg-info/top_level 2.txt +0 -0
  194. {meshcode-2.10.94 → meshcode-2.10.95}/setup.cfg +0 -0
  195. {meshcode-2.10.94 → meshcode-2.10.95}/tests/test_auto_update_hardening.py +0 -0
  196. {meshcode-2.10.94 → meshcode-2.10.95}/tests/test_core.py +0 -0
  197. {meshcode-2.10.94 → meshcode-2.10.95}/tests/test_cross_agent_messaging.py +0 -0
  198. {meshcode-2.10.94 → meshcode-2.10.95}/tests/test_esc_deaf_state.py +0 -0
  199. {meshcode-2.10.94 → meshcode-2.10.95}/tests/test_exceptions.py +0 -0
  200. {meshcode-2.10.94 → meshcode-2.10.95}/tests/test_mark_read_batch.py +0 -0
  201. {meshcode-2.10.94 → meshcode-2.10.95}/tests/test_migration_integrity.py +0 -0
  202. {meshcode-2.10.94 → meshcode-2.10.95}/tests/test_realtime_event_freshness.py +0 -0
  203. {meshcode-2.10.94 → meshcode-2.10.95}/tests/test_rls_cross_tenant.py +0 -0
  204. {meshcode-2.10.94 → meshcode-2.10.95}/tests/test_rpc_migrations.py +0 -0
  205. {meshcode-2.10.94 → meshcode-2.10.95}/tests/test_security_regressions.py +0 -0
  206. {meshcode-2.10.94 → meshcode-2.10.95}/tests/test_sentinel.py +0 -0
  207. {meshcode-2.10.94 → meshcode-2.10.95}/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.94
3
+ Version: 2.10.95
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,82 @@
1
+ """MeshCode — Real-time communication between AI agents."""
2
+ __version__ = "2.10.95"
3
+
4
+ # Exception hierarchy — eagerly imported (lightweight, no deps)
5
+ from meshcode.exceptions import ( # noqa: F401
6
+ MeshCodeError,
7
+ AuthError,
8
+ RPCError,
9
+ MeshCodeTimeoutError,
10
+ MeshCodeConnectionError,
11
+ )
12
+
13
+ # Public API — lazy imports to avoid heavy deps at import time
14
+ def __getattr__(name):
15
+ if name == "backend":
16
+ from meshcode.meshcode_mcp import backend
17
+ return backend
18
+ if name in _BACKEND_EXPORTS:
19
+ from meshcode.meshcode_mcp import backend
20
+ return getattr(backend, name)
21
+ if name in _SECRETS_EXPORTS:
22
+ from meshcode import secrets
23
+ return getattr(secrets, name)
24
+ raise AttributeError(f"module 'meshcode' has no attribute {name!r}")
25
+
26
+
27
+ # Backend: core messaging & agent management
28
+ _BACKEND_EXPORTS = {
29
+ "send_message",
30
+ "read_inbox",
31
+ "count_pending",
32
+ "get_board",
33
+ "heartbeat",
34
+ "set_status",
35
+ "register_agent",
36
+ "get_project_id",
37
+ "sb_rpc",
38
+ "task_create",
39
+ "task_list",
40
+ "encrypt_payload",
41
+ "decrypt_payload",
42
+ }
43
+
44
+ # Secrets: credential management
45
+ _SECRETS_EXPORTS = {
46
+ "get_api_key",
47
+ "set_api_key",
48
+ "list_profiles",
49
+ }
50
+
51
+ __all__ = [
52
+ "__version__",
53
+ "backend",
54
+ # Exceptions
55
+ "MeshCodeError",
56
+ "AuthError",
57
+ "RPCError",
58
+ "MeshCodeTimeoutError",
59
+ "MeshCodeConnectionError",
60
+ # Messaging
61
+ "send_message",
62
+ "read_inbox",
63
+ "count_pending",
64
+ # Agent management
65
+ "register_agent",
66
+ "get_project_id",
67
+ "get_board",
68
+ "heartbeat",
69
+ "set_status",
70
+ # Tasks
71
+ "task_create",
72
+ "task_list",
73
+ # Low-level
74
+ "sb_rpc",
75
+ # Encryption
76
+ "encrypt_payload",
77
+ "decrypt_payload",
78
+ # Credentials
79
+ "get_api_key",
80
+ "set_api_key",
81
+ "list_profiles",
82
+ ]
@@ -826,14 +826,29 @@ def read_inbox(project_id: str, agent: str, mark_read: bool = True, api_key: Opt
826
826
  for m in messages:
827
827
  p = m.get("payload")
828
828
  if isinstance(p, dict) and "_encrypted" in p:
829
- if mesh_key is None:
830
- mesh_key = get_mesh_key(api_key, project_id)
831
- if mesh_key:
832
- msg_aad = p.get("_aad", project_id)
833
- decrypted = decrypt_payload(p["_encrypted"], mesh_key, aad=msg_aad)
834
- if decrypted is not None:
835
- m["payload"] = decrypted
836
- m["_was_encrypted"] = True
829
+ msg_aad = p.get("_aad", project_id)
830
+ from_project_marker = p.get("_from_project")
831
+ decrypted = None
832
+ # Cross-mesh: payload tagged with sender's project.
833
+ # Fetch per-link shared key (NOT local mesh key).
834
+ if from_project_marker and from_project_marker != project_id:
835
+ link_key = get_link_shared_key(api_key, project_id, from_project_marker)
836
+ if link_key:
837
+ decrypted = decrypt_payload(p["_encrypted"], link_key, aad=msg_aad)
838
+ # Decrypt fail → key rotation; refetch once.
839
+ if decrypted is None:
840
+ link_key = get_link_shared_key(api_key, project_id, from_project_marker, bypass_cache=True)
841
+ if link_key:
842
+ decrypted = decrypt_payload(p["_encrypted"], link_key, aad=msg_aad)
843
+ # In-mesh OR no _from_project marker (legacy): local key.
844
+ if decrypted is None:
845
+ if mesh_key is None:
846
+ mesh_key = get_mesh_key(api_key, project_id)
847
+ if mesh_key:
848
+ decrypted = decrypt_payload(p["_encrypted"], mesh_key, aad=msg_aad)
849
+ if decrypted is not None:
850
+ m["payload"] = decrypted
851
+ m["_was_encrypted"] = True
837
852
  if mark_read and messages:
838
853
  import datetime as _dt
839
854
  now = _dt.datetime.now(_dt.timezone.utc)
@@ -872,14 +887,25 @@ def read_inbox(project_id: str, agent: str, mark_read: bool = True, api_key: Opt
872
887
  for m in messages:
873
888
  p = m.get("payload")
874
889
  if isinstance(p, dict) and "_encrypted" in p:
875
- if mesh_key is None:
876
- mesh_key = get_mesh_key(api_key, project_id)
877
- if mesh_key:
878
- msg_aad = p.get("_aad", project_id)
879
- decrypted = decrypt_payload(p["_encrypted"], mesh_key, aad=msg_aad)
880
- if decrypted is not None:
881
- m["payload"] = decrypted
882
- m["_was_encrypted"] = True
890
+ msg_aad = p.get("_aad", project_id)
891
+ from_project_marker = p.get("_from_project")
892
+ decrypted = None
893
+ if from_project_marker and from_project_marker != project_id:
894
+ link_key = get_link_shared_key(api_key, project_id, from_project_marker)
895
+ if link_key:
896
+ decrypted = decrypt_payload(p["_encrypted"], link_key, aad=msg_aad)
897
+ if decrypted is None:
898
+ link_key = get_link_shared_key(api_key, project_id, from_project_marker, bypass_cache=True)
899
+ if link_key:
900
+ decrypted = decrypt_payload(p["_encrypted"], link_key, aad=msg_aad)
901
+ if decrypted is None:
902
+ if mesh_key is None:
903
+ mesh_key = get_mesh_key(api_key, project_id)
904
+ if mesh_key:
905
+ decrypted = decrypt_payload(p["_encrypted"], mesh_key, aad=msg_aad)
906
+ if decrypted is not None:
907
+ m["payload"] = decrypted
908
+ m["_was_encrypted"] = True
883
909
  if mark_read and messages:
884
910
  for m in messages:
885
911
  marked = False
@@ -983,6 +1009,56 @@ def get_mesh_key(api_key: str, project_id: str) -> Optional[str]:
983
1009
  return None
984
1010
 
985
1011
 
1012
+ # Per-link shared key cache (cross-mesh encrypted msgs). Keyed by
1013
+ # (my_project, other_project) tuple. Populated on demand when an encrypted
1014
+ # cross-mesh message arrives. Cache invalidates on decrypt failure (rotation).
1015
+ _link_key_cache: Dict[tuple, tuple] = {} # (my_proj, other_proj) -> (hex_key, expiry_ts)
1016
+ _LINK_KEY_CACHE_TTL = 600
1017
+ _LINK_KEY_CACHE_MAX = 64
1018
+
1019
+
1020
+ def get_link_shared_key(api_key: str, my_project: str, other_project: str,
1021
+ bypass_cache: bool = False) -> Optional[str]:
1022
+ """Retrieve the per-link symmetric encryption key (hex-encoded AES-256).
1023
+
1024
+ Used for cross-mesh encrypted messages — backend `mc_get_link_shared_key`
1025
+ returns a key SHARED by both ends of the link, so encrypt-on-sender +
1026
+ decrypt-on-recipient roundtrips cleanly. `my_project` and `other_project`
1027
+ accept either project name OR project_id; the RPC resolves both.
1028
+
1029
+ Set `bypass_cache=True` after a decrypt failure to handle key rotation
1030
+ (`mc_rotate_link_shared_key`).
1031
+ """
1032
+ cache_key = (my_project, other_project)
1033
+ if not bypass_cache:
1034
+ entry = _link_key_cache.get(cache_key)
1035
+ if entry and entry[1] > _time.time():
1036
+ return entry[0]
1037
+ _link_key_cache.pop(cache_key, None)
1038
+ result = sb_rpc("mc_get_link_shared_key", {
1039
+ "p_api_key": api_key,
1040
+ "p_my_project": my_project,
1041
+ "p_other_project": other_project,
1042
+ })
1043
+ if isinstance(result, dict) and result.get("ok"):
1044
+ try:
1045
+ import base64 as _b64
1046
+ hex_key = _b64.b64decode(result["shared_encryption_key_b64"]).hex()
1047
+ except Exception:
1048
+ return None
1049
+ if len(_link_key_cache) >= _LINK_KEY_CACHE_MAX:
1050
+ now = _time.time()
1051
+ expired = [k for k, v in _link_key_cache.items() if v[1] <= now]
1052
+ for k in expired:
1053
+ del _link_key_cache[k]
1054
+ if len(_link_key_cache) >= _LINK_KEY_CACHE_MAX:
1055
+ oldest = min(_link_key_cache, key=lambda k: _link_key_cache[k][1])
1056
+ del _link_key_cache[oldest]
1057
+ _link_key_cache[cache_key] = (hex_key, _time.time() + _LINK_KEY_CACHE_TTL)
1058
+ return hex_key
1059
+ return None
1060
+
1061
+
986
1062
  def encrypt_payload(payload: Dict, hex_key: str, aad: Optional[str] = None) -> str:
987
1063
  """Encrypt a JSON payload using AES-256-GCM with optional AAD.
988
1064
 
@@ -2006,23 +2006,36 @@ def meshcode_send(to: str, message: Any, in_reply_to: Optional[str] = None,
2006
2006
  return {"error": "sensitive messages must use encrypted=True for cross-mesh"}
2007
2007
  api_key = _get_api_key()
2008
2008
 
2009
- # Bridge re-encryption: encrypt payload with the TARGET mesh key so
2010
- # the receiving agent decrypts normally. Uses mc_get_cross_mesh_key
2011
- # RPC which validates the link exists before returning the key.
2009
+ # Cross-mesh encryption: per-link symmetric AES-256-GCM key (backend
2010
+ # commit cc6a988 / mig 2026-05-04). Old `mc_get_cross_mesh_key`
2011
+ # returned target's per-mesh key, which empirically failed to decrypt
2012
+ # on recipient (incident 2026-05-04 chief@mesh-dev). New
2013
+ # `mc_get_link_shared_key` returns a key SHARED by sender + recipient
2014
+ # via the link record — both sides resolve to the same bytes, so
2015
+ # encryption roundtrips cleanly. Tag payload with _from_project so the
2016
+ # recipient knows to fetch the link key (not its local mesh key) on
2017
+ # decrypt.
2012
2018
  if encrypted:
2013
- key_result = be.sb_rpc("mc_get_cross_mesh_key", {
2019
+ key_result = be.sb_rpc("mc_get_link_shared_key", {
2014
2020
  "p_api_key": api_key,
2015
- "p_source_project": PROJECT_NAME,
2016
- "p_target_project": target_meshwork,
2017
- "p_agent_name": AGENT_NAME,
2021
+ "p_my_project": PROJECT_NAME,
2022
+ "p_other_project": target_meshwork,
2018
2023
  })
2019
2024
  if not isinstance(key_result, dict) or not key_result.get("ok"):
2020
- err = key_result.get("error", "unknown") if isinstance(key_result, dict) else "RPC failed"
2025
+ err = key_result.get("error_code") or key_result.get("error", "unknown") if isinstance(key_result, dict) else "RPC failed"
2021
2026
  return {"error": f"cross-mesh encryption failed: {err}"}
2022
- tgt_key = key_result["key"]
2027
+ link_key_b64 = key_result["shared_encryption_key_b64"]
2028
+ link_id = key_result.get("link_id", "")
2023
2029
  tgt_project_id = key_result.get("target_project_id", "")
2024
- encrypted_data = be.encrypt_payload(payload, tgt_key, aad=tgt_project_id)
2025
- payload = {"_encrypted": encrypted_data, "_aad": tgt_project_id}
2030
+ import base64 as _b64
2031
+ link_key_hex = _b64.b64decode(link_key_b64).hex()
2032
+ encrypted_data = be.encrypt_payload(payload, link_key_hex, aad=link_id or tgt_project_id)
2033
+ payload = {
2034
+ "_encrypted": encrypted_data,
2035
+ "_aad": link_id or tgt_project_id,
2036
+ "_from_project": PROJECT_NAME,
2037
+ "_link_id": link_id,
2038
+ }
2026
2039
 
2027
2040
  result = be.sb_rpc("mc_send_cross_mesh", {
2028
2041
  "p_api_key": api_key,
@@ -2688,20 +2701,40 @@ def _mark_realtime_msgs_read_in_db(messages: List[Dict[str, Any]]) -> None:
2688
2701
  async def _meshcode_wait_inner(actual_timeout: int, include_acks: bool) -> Dict[str, Any]:
2689
2702
 
2690
2703
  def _return_from_buffered(buffered: List[Dict[str, Any]]) -> Optional[Dict[str, Any]]:
2691
- # Auto-decrypt encrypted payloads
2704
+ # Auto-decrypt encrypted payloads. Cross-mesh msgs carry _from_project
2705
+ # marker → use per-link shared key. In-mesh → local mesh key.
2692
2706
  _mesh_key = None
2707
+ _api_key = _get_api_key()
2693
2708
  for msg in buffered:
2694
2709
  p = msg.get("payload")
2695
2710
  if isinstance(p, dict) and "_encrypted" in p:
2696
- if _mesh_key is None:
2711
+ _msg_aad = p.get("_aad", PROJECT_NAME)
2712
+ _from_proj = p.get("_from_project")
2713
+ _decrypted = None
2714
+ if _from_proj and _from_proj != PROJECT_NAME:
2697
2715
  try:
2698
- _mesh_key = be.get_mesh_key(_get_api_key(), _PROJECT_ID) or ""
2716
+ _link_key = be.get_link_shared_key(_api_key, PROJECT_NAME, _from_proj)
2717
+ if _link_key:
2718
+ _decrypted = be.decrypt_payload(p["_encrypted"], _link_key, aad=_msg_aad)
2719
+ if _decrypted is None:
2720
+ _link_key = be.get_link_shared_key(_api_key, PROJECT_NAME, _from_proj, bypass_cache=True)
2721
+ if _link_key:
2722
+ _decrypted = be.decrypt_payload(p["_encrypted"], _link_key, aad=_msg_aad)
2699
2723
  except Exception:
2700
- _mesh_key = ""
2701
- if _mesh_key:
2702
- decrypted = be.decrypt_payload(p["_encrypted"], _mesh_key)
2703
- if decrypted is not None:
2704
- msg["payload"] = decrypted
2724
+ pass
2725
+ if _decrypted is None:
2726
+ if _mesh_key is None:
2727
+ try:
2728
+ _mesh_key = be.get_mesh_key(_api_key, _PROJECT_ID) or ""
2729
+ except Exception:
2730
+ _mesh_key = ""
2731
+ if _mesh_key:
2732
+ try:
2733
+ _decrypted = be.decrypt_payload(p["_encrypted"], _mesh_key, aad=_msg_aad)
2734
+ except Exception:
2735
+ _decrypted = None
2736
+ if _decrypted is not None:
2737
+ msg["payload"] = _decrypted
2705
2738
  deduped = _filter_and_mark(buffered)
2706
2739
  if not deduped:
2707
2740
  return None
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.4
2
2
  Name: meshcode
3
- Version: 2.10.94
3
+ Version: 2.10.95
4
4
  Summary: Real-time communication between AI agents — Supabase-backed CLI
5
5
  Author-email: MeshCode <hello@meshcode.io>
6
6
  License: MIT