meshcode 1.9.0__tar.gz → 2.0.0__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 (29) hide show
  1. {meshcode-1.9.0 → meshcode-2.0.0}/PKG-INFO +1 -1
  2. {meshcode-1.9.0 → meshcode-2.0.0}/meshcode/__init__.py +1 -1
  3. {meshcode-1.9.0 → meshcode-2.0.0}/meshcode/comms_v4.py +23 -0
  4. {meshcode-1.9.0 → meshcode-2.0.0}/meshcode/meshcode_mcp/server.py +155 -1
  5. {meshcode-1.9.0 → meshcode-2.0.0}/meshcode.egg-info/PKG-INFO +1 -1
  6. {meshcode-1.9.0 → meshcode-2.0.0}/pyproject.toml +1 -1
  7. {meshcode-1.9.0 → meshcode-2.0.0}/README.md +0 -0
  8. {meshcode-1.9.0 → meshcode-2.0.0}/meshcode/cli.py +0 -0
  9. {meshcode-1.9.0 → meshcode-2.0.0}/meshcode/invites.py +0 -0
  10. {meshcode-1.9.0 → meshcode-2.0.0}/meshcode/launcher.py +0 -0
  11. {meshcode-1.9.0 → meshcode-2.0.0}/meshcode/launcher_install.py +0 -0
  12. {meshcode-1.9.0 → meshcode-2.0.0}/meshcode/meshcode_mcp/__init__.py +0 -0
  13. {meshcode-1.9.0 → meshcode-2.0.0}/meshcode/meshcode_mcp/__main__.py +0 -0
  14. {meshcode-1.9.0 → meshcode-2.0.0}/meshcode/meshcode_mcp/backend.py +0 -0
  15. {meshcode-1.9.0 → meshcode-2.0.0}/meshcode/meshcode_mcp/realtime.py +0 -0
  16. {meshcode-1.9.0 → meshcode-2.0.0}/meshcode/meshcode_mcp/test_backend.py +0 -0
  17. {meshcode-1.9.0 → meshcode-2.0.0}/meshcode/meshcode_mcp/test_realtime.py +0 -0
  18. {meshcode-1.9.0 → meshcode-2.0.0}/meshcode/preferences.py +0 -0
  19. {meshcode-1.9.0 → meshcode-2.0.0}/meshcode/protocol_v2.py +0 -0
  20. {meshcode-1.9.0 → meshcode-2.0.0}/meshcode/run_agent.py +0 -0
  21. {meshcode-1.9.0 → meshcode-2.0.0}/meshcode/secrets.py +0 -0
  22. {meshcode-1.9.0 → meshcode-2.0.0}/meshcode/self_update.py +0 -0
  23. {meshcode-1.9.0 → meshcode-2.0.0}/meshcode/setup_clients.py +0 -0
  24. {meshcode-1.9.0 → meshcode-2.0.0}/meshcode.egg-info/SOURCES.txt +0 -0
  25. {meshcode-1.9.0 → meshcode-2.0.0}/meshcode.egg-info/dependency_links.txt +0 -0
  26. {meshcode-1.9.0 → meshcode-2.0.0}/meshcode.egg-info/entry_points.txt +0 -0
  27. {meshcode-1.9.0 → meshcode-2.0.0}/meshcode.egg-info/requires.txt +0 -0
  28. {meshcode-1.9.0 → meshcode-2.0.0}/meshcode.egg-info/top_level.txt +0 -0
  29. {meshcode-1.9.0 → meshcode-2.0.0}/setup.cfg +0 -0
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.4
2
2
  Name: meshcode
3
- Version: 1.9.0
3
+ Version: 2.0.0
4
4
  Summary: Real-time communication between AI agents — Supabase-backed CLI
5
5
  Author-email: MeshCode <hello@meshcode.io>
6
6
  License: MIT
@@ -1,2 +1,2 @@
1
1
  """MeshCode — Real-time communication between AI agents."""
2
- __version__ = "1.9.0"
2
+ __version__ = "2.0.0"
@@ -171,6 +171,7 @@ def sb_rpc(fn_name, params):
171
171
  raw = resp.read().decode()
172
172
  return json.loads(raw) if raw.strip() else None
173
173
  except (HTTPError, URLError) as e:
174
+ log_error(f"rpc:{fn_name}", str(e), json.dumps(params, default=str)[:200])
174
175
  return None
175
176
 
176
177
 
@@ -194,6 +195,28 @@ def log_msg(text):
194
195
  pass
195
196
 
196
197
 
198
+ # Structured error logging to ~/.meshcode/error.log (rotating, max 1MB)
199
+ _ERROR_LOG = Path.home() / ".meshcode" / "error.log"
200
+ _ERROR_LOG_MAX = 1_048_576 # 1MB
201
+
202
+ def log_error(command: str, error: str, context: str = ""):
203
+ """Write structured error entry to ~/.meshcode/error.log with rotation."""
204
+ try:
205
+ _ERROR_LOG.parent.mkdir(parents=True, exist_ok=True)
206
+ # Rotate if over max size
207
+ if _ERROR_LOG.exists() and _ERROR_LOG.stat().st_size > _ERROR_LOG_MAX:
208
+ rotated = _ERROR_LOG.with_suffix(".log.old")
209
+ _ERROR_LOG.rename(rotated)
210
+ entry = json.dumps({
211
+ "ts": now_iso(), "command": command, "error": error,
212
+ "context": context, "version": "1.9.0"
213
+ }, default=str)
214
+ with open(_ERROR_LOG, "a") as f:
215
+ f.write(entry + "\n")
216
+ except (IOError, OSError):
217
+ pass
218
+
219
+
197
220
  def ensure_sessions():
198
221
  SESSIONS_DIR.mkdir(parents=True, exist_ok=True)
199
222
 
@@ -446,7 +446,16 @@ meshcode_expand_link(). No sensitive msgs cross-mesh.
446
446
 
447
447
  MEMORY: meshcode_remember(key, value) persists across sessions.
448
448
  meshcode_recall(key?) retrieves. meshcode_forget(key) deletes.
449
- Auto-remember: mistakes, feedback, patterns, preferences after each task.
449
+ Auto-remember after each task: mistakes, feedback, patterns, preferences.
450
+ Save reusable code patterns as template_* keys for instant recall.
451
+
452
+ SCRATCHPAD: meshcode_scratchpad_set/get for shared meshwork-level context
453
+ (decisions, conventions, architecture notes). All agents can read/write.
454
+
455
+ ACCOUNT MANAGEMENT: you can create meshworks (meshcode_create_meshwork),
456
+ add agents (meshcode_add_agent), edit roles/prompts (meshcode_edit_agent),
457
+ and edit other agents' memory (meshcode_edit_memory). Always tell the user
458
+ what CLI command to run next (e.g. "meshcode run backend in a new terminal").
450
459
 
451
460
  Setup help → README.md or https://meshcode.io/docs
452
461
  """
@@ -920,6 +929,42 @@ def meshcode_task_complete(task_id: str, summary: str = "") -> Dict[str, Any]:
920
929
  return be.task_complete(api_key, _PROJECT_ID, task_id, AGENT_NAME, summary=summary)
921
930
 
922
931
 
932
+ @mcp.tool()
933
+ @with_working_status
934
+ def meshcode_task_approve(task_id: str) -> Dict[str, Any]:
935
+ """Approve a task in review. Only the reviewer can approve.
936
+
937
+ Args:
938
+ task_id: Task UUID to approve.
939
+ """
940
+ api_key = _get_api_key()
941
+ return be.sb_rpc("mc_task_approve", {
942
+ "p_api_key": api_key,
943
+ "p_project_id": _PROJECT_ID,
944
+ "p_task_id": task_id,
945
+ "p_approving_agent": AGENT_NAME,
946
+ })
947
+
948
+
949
+ @mcp.tool()
950
+ @with_working_status
951
+ def meshcode_task_reject(task_id: str, feedback: str = "") -> Dict[str, Any]:
952
+ """Reject a task in review — sends it back to in_progress with feedback.
953
+
954
+ Args:
955
+ task_id: Task UUID to reject.
956
+ feedback: Why it was rejected.
957
+ """
958
+ api_key = _get_api_key()
959
+ return be.sb_rpc("mc_task_reject", {
960
+ "p_api_key": api_key,
961
+ "p_project_id": _PROJECT_ID,
962
+ "p_task_id": task_id,
963
+ "p_rejecting_agent": AGENT_NAME,
964
+ "p_feedback": feedback,
965
+ })
966
+
967
+
923
968
  # ----------------- MESH LINK TOOLS -----------------
924
969
 
925
970
  @mcp.tool()
@@ -990,6 +1035,115 @@ def meshcode_expand_link(link_id: str, agents: str) -> Dict[str, Any]:
990
1035
  })
991
1036
 
992
1037
 
1038
+ # ----------------- ACCOUNT MANAGEMENT TOOLS -----------------
1039
+
1040
+ @mcp.tool()
1041
+ @with_working_status
1042
+ def meshcode_create_meshwork(name: str) -> Dict[str, Any]:
1043
+ """Create a new meshwork for the current user. Tell them to run 'meshcode setup <name> <agent>' next.
1044
+
1045
+ Args:
1046
+ name: Meshwork name (lowercase, hyphens ok).
1047
+ """
1048
+ api_key = _get_api_key()
1049
+ result = be.sb_rpc("mc_create_meshwork_by_api_key", {
1050
+ "p_api_key": api_key, "p_name": name,
1051
+ })
1052
+ if isinstance(result, dict) and result.get("ok"):
1053
+ return {**result, "next_step": f"Run: meshcode setup {name} <agent-name>"}
1054
+ return result or {"error": "failed to create meshwork"}
1055
+
1056
+
1057
+ @mcp.tool()
1058
+ @with_working_status
1059
+ def meshcode_add_agent(name: str, role: str = "") -> Dict[str, Any]:
1060
+ """Add an agent to the current meshwork. Tell user to run 'meshcode setup <project> <name>' then 'meshcode run <name>'.
1061
+
1062
+ Args:
1063
+ name: Agent name.
1064
+ role: Agent role description.
1065
+ """
1066
+ result = be.register_agent(PROJECT_NAME, name, role or "MCP-connected agent")
1067
+ if isinstance(result, dict) and not result.get("error"):
1068
+ return {"ok": True, "agent": name, "next_step": f"Run: meshcode setup {PROJECT_NAME} {name} && meshcode run {name}"}
1069
+ return result or {"error": "failed to add agent"}
1070
+
1071
+
1072
+ @mcp.tool()
1073
+ @with_working_status
1074
+ def meshcode_edit_agent(name: str, role: Optional[str] = None, launch_prompt: Optional[str] = None) -> Dict[str, Any]:
1075
+ """Update an agent's role or launch prompt.
1076
+
1077
+ Args:
1078
+ name: Agent name to edit.
1079
+ role: New role description.
1080
+ launch_prompt: New launch prompt (injected into agent's system context).
1081
+ """
1082
+ return be.sb_rpc("mc_agent_update_profile", {
1083
+ "p_project_id": _PROJECT_ID,
1084
+ "p_agent_name": name,
1085
+ "p_color": None,
1086
+ "p_display_name": None,
1087
+ "p_role_description": role,
1088
+ "p_launch_prompt": launch_prompt,
1089
+ }) or {"error": "failed to update agent"}
1090
+
1091
+
1092
+ @mcp.tool()
1093
+ @with_working_status
1094
+ def meshcode_edit_memory(agent_name: str, key: str, value: Any) -> Dict[str, Any]:
1095
+ """Edit another agent's memory (for commanders coordinating the team).
1096
+
1097
+ Args:
1098
+ agent_name: Target agent whose memory to edit.
1099
+ key: Memory key.
1100
+ value: New value.
1101
+ """
1102
+ api_key = _get_api_key()
1103
+ json_value = value if isinstance(value, (dict, list)) else {"_raw": value}
1104
+ return be.sb_rpc("mc_memory_set", {
1105
+ "p_api_key": api_key,
1106
+ "p_agent_name": agent_name,
1107
+ "p_key": key,
1108
+ "p_value": json_value,
1109
+ }) or {"error": "failed to edit memory"}
1110
+
1111
+
1112
+ # ----------------- SCRATCHPAD TOOLS -----------------
1113
+
1114
+ @mcp.tool()
1115
+ @with_working_status
1116
+ def meshcode_scratchpad_set(key: str, value: Any) -> Dict[str, Any]:
1117
+ """Write to shared scratchpad (all agents in this meshwork can read/write).
1118
+
1119
+ Args:
1120
+ key: Key name (e.g. "architecture_decisions", "conventions").
1121
+ value: Any JSON-serializable value.
1122
+ """
1123
+ api_key = _get_api_key()
1124
+ json_value = value if isinstance(value, (dict, list)) else {"_raw": value}
1125
+ return be.sb_rpc("mc_scratchpad_set", {
1126
+ "p_api_key": api_key,
1127
+ "p_key": key,
1128
+ "p_value": json_value,
1129
+ })
1130
+
1131
+
1132
+ @mcp.tool()
1133
+ @with_working_status
1134
+ def meshcode_scratchpad_get(key: Optional[str] = None) -> Dict[str, Any]:
1135
+ """Read from shared scratchpad. Omit key to list all entries.
1136
+
1137
+ Args:
1138
+ key: Specific key, or omit for all entries.
1139
+ """
1140
+ api_key = _get_api_key()
1141
+ if key:
1142
+ return be.sb_rpc("mc_scratchpad_get", {"p_api_key": api_key, "p_key": key})
1143
+ else:
1144
+ return be.sb_rpc("mc_scratchpad_list", {"p_api_key": api_key})
1145
+
1146
+
993
1147
  # ----------------- OBSIDIAN SYNC HELPER -----------------
994
1148
 
995
1149
  def _sync_to_obsidian(key: str, value: Any) -> None:
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.4
2
2
  Name: meshcode
3
- Version: 1.9.0
3
+ Version: 2.0.0
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 = "1.9.0"
7
+ version = "2.0.0"
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