meshcode 2.0.2__tar.gz → 2.0.4__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.
- {meshcode-2.0.2 → meshcode-2.0.4}/PKG-INFO +39 -8
- {meshcode-2.0.2 → meshcode-2.0.4}/README.md +38 -7
- {meshcode-2.0.2 → meshcode-2.0.4}/meshcode/__init__.py +1 -1
- {meshcode-2.0.2 → meshcode-2.0.4}/meshcode/meshcode_mcp/realtime.py +2 -1
- {meshcode-2.0.2 → meshcode-2.0.4}/meshcode/meshcode_mcp/server.py +83 -14
- {meshcode-2.0.2 → meshcode-2.0.4}/meshcode.egg-info/PKG-INFO +39 -8
- {meshcode-2.0.2 → meshcode-2.0.4}/pyproject.toml +1 -1
- {meshcode-2.0.2 → meshcode-2.0.4}/meshcode/cli.py +0 -0
- {meshcode-2.0.2 → meshcode-2.0.4}/meshcode/comms_v4.py +0 -0
- {meshcode-2.0.2 → meshcode-2.0.4}/meshcode/invites.py +0 -0
- {meshcode-2.0.2 → meshcode-2.0.4}/meshcode/launcher.py +0 -0
- {meshcode-2.0.2 → meshcode-2.0.4}/meshcode/launcher_install.py +0 -0
- {meshcode-2.0.2 → meshcode-2.0.4}/meshcode/meshcode_mcp/__init__.py +0 -0
- {meshcode-2.0.2 → meshcode-2.0.4}/meshcode/meshcode_mcp/__main__.py +0 -0
- {meshcode-2.0.2 → meshcode-2.0.4}/meshcode/meshcode_mcp/backend.py +0 -0
- {meshcode-2.0.2 → meshcode-2.0.4}/meshcode/meshcode_mcp/test_backend.py +0 -0
- {meshcode-2.0.2 → meshcode-2.0.4}/meshcode/meshcode_mcp/test_realtime.py +0 -0
- {meshcode-2.0.2 → meshcode-2.0.4}/meshcode/preferences.py +0 -0
- {meshcode-2.0.2 → meshcode-2.0.4}/meshcode/protocol_v2.py +0 -0
- {meshcode-2.0.2 → meshcode-2.0.4}/meshcode/run_agent.py +0 -0
- {meshcode-2.0.2 → meshcode-2.0.4}/meshcode/secrets.py +0 -0
- {meshcode-2.0.2 → meshcode-2.0.4}/meshcode/self_update.py +0 -0
- {meshcode-2.0.2 → meshcode-2.0.4}/meshcode/setup_clients.py +0 -0
- {meshcode-2.0.2 → meshcode-2.0.4}/meshcode.egg-info/SOURCES.txt +0 -0
- {meshcode-2.0.2 → meshcode-2.0.4}/meshcode.egg-info/dependency_links.txt +0 -0
- {meshcode-2.0.2 → meshcode-2.0.4}/meshcode.egg-info/entry_points.txt +0 -0
- {meshcode-2.0.2 → meshcode-2.0.4}/meshcode.egg-info/requires.txt +0 -0
- {meshcode-2.0.2 → meshcode-2.0.4}/meshcode.egg-info/top_level.txt +0 -0
- {meshcode-2.0.2 → meshcode-2.0.4}/setup.cfg +0 -0
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
Metadata-Version: 2.4
|
|
2
2
|
Name: meshcode
|
|
3
|
-
Version: 2.0.
|
|
3
|
+
Version: 2.0.4
|
|
4
4
|
Summary: Real-time communication between AI agents — Supabase-backed CLI
|
|
5
5
|
Author-email: MeshCode <hello@meshcode.io>
|
|
6
6
|
License: MIT
|
|
@@ -153,7 +153,9 @@ meshcode revoke-member my-project <user> # kick a member instantly
|
|
|
153
153
|
| `meshcode status` | `meshcode status` | Show the logged-in account and version. |
|
|
154
154
|
| `meshcode send` (legacy) | `meshcode send my-project a:b '{"need":"..."}'` | Pre-1.5 manual message send (MCP tools are preferred). |
|
|
155
155
|
| `meshcode read` (legacy) | `meshcode read my-project backend` | Pre-1.5 manual read. |
|
|
156
|
-
| `meshcode
|
|
156
|
+
| `meshcode projects` | `meshcode projects` | List all your meshworks and their agents. |
|
|
157
|
+
| `meshcode list` | `meshcode list` | Alias for `meshcode projects`. |
|
|
158
|
+
| `meshcode --version` | `meshcode --version` | Print current version. |
|
|
157
159
|
| `meshcode help` | `meshcode help` | Top-level help. Per-verb help: `meshcode <verb> --help`. |
|
|
158
160
|
|
|
159
161
|
---
|
|
@@ -251,10 +253,11 @@ pip install meshcode --upgrade
|
|
|
251
253
|
### Reconnect a single agent
|
|
252
254
|
|
|
253
255
|
```bash
|
|
254
|
-
meshcode
|
|
256
|
+
meshcode setup my-project agent-name # ensures workspace exists (safe to re-run)
|
|
257
|
+
meshcode run agent-name # opens your editor
|
|
255
258
|
```
|
|
256
259
|
|
|
257
|
-
|
|
260
|
+
Since v2.0.2, `meshcode run` **auto-recovers** if the workspace was deleted — it queries the server, recreates the workspace, and launches. So `meshcode run agent-name` alone is usually enough. The agent automatically:
|
|
258
261
|
1. Loads its persistent memories (`meshcode_recall()`)
|
|
259
262
|
2. Checks who else is online (`meshcode_status()`)
|
|
260
263
|
3. Picks up any open tasks (`meshcode_tasks()`)
|
|
@@ -326,21 +329,49 @@ If an agent is offline, the dashboard shows a **Reconnect** button on its card.
|
|
|
326
329
|
|
|
327
330
|
## Troubleshooting
|
|
328
331
|
|
|
329
|
-
**1. `
|
|
332
|
+
**1. `no workspace found for agent 'X'`**
|
|
333
|
+
Your local workspace was deleted or never created. Since v2.0.2, `meshcode run` auto-recovers by querying the server. If you're on an older version:
|
|
334
|
+
```bash
|
|
335
|
+
pip install meshcode --upgrade # get v2.0.2+
|
|
336
|
+
meshcode run agent-name # auto-recovers now
|
|
337
|
+
```
|
|
338
|
+
If auto-recovery fails (no API key stored), run setup manually:
|
|
339
|
+
```bash
|
|
340
|
+
meshcode setup my-project agent-name # recreates ~/meshcode/my-project-agent-name/
|
|
341
|
+
meshcode run agent-name
|
|
342
|
+
```
|
|
343
|
+
|
|
344
|
+
**2. `meshcode projects` shows no projects (but dashboard shows them)**
|
|
345
|
+
Before v2.0.2, the `projects` command used an unauthenticated query blocked by row-level security. Upgrade:
|
|
346
|
+
```bash
|
|
347
|
+
pip install meshcode --upgrade
|
|
348
|
+
meshcode projects # now uses your API key
|
|
349
|
+
```
|
|
350
|
+
|
|
351
|
+
**3. `No credentials found. Run meshcode login first.`**
|
|
330
352
|
You haven't stored a key yet. Grab your `mc_xxx` from https://meshcode.io/onboarding and run:
|
|
331
353
|
```bash
|
|
332
354
|
meshcode login mc_xxxxxxxxxxxx
|
|
333
355
|
```
|
|
334
356
|
|
|
335
|
-
**
|
|
357
|
+
**4. `agent already running in another window`**
|
|
336
358
|
MeshCode prevents split-brain — the same agent name can't be live in two editor windows. Close the other window, or use a different agent name.
|
|
337
359
|
|
|
338
|
-
**
|
|
360
|
+
**5. `scoped api key cannot access this project`**
|
|
339
361
|
You joined a meshwork via an invite, and you're now trying to use a different project. Scoped keys only work for the one mesh they were minted for. Run `meshcode members <correct-project>` to confirm which mesh you belong to.
|
|
340
362
|
|
|
341
|
-
**
|
|
363
|
+
**6. `meshcode: command not found`**
|
|
342
364
|
Either `pip install` didn't add to your PATH (check `which meshcode` and `python -m site --user-base`), or you have a stale pre-1.0.0 `~/bin/meshcode` shim shadowing the real binary — delete it.
|
|
343
365
|
|
|
366
|
+
**7. `could not resolve project 'X': project not found`**
|
|
367
|
+
Wrong project name. Since v2.0.2, `meshcode setup` will suggest your real projects when it can't find the one you typed. Check the exact name:
|
|
368
|
+
```bash
|
|
369
|
+
meshcode projects # lists all your meshworks
|
|
370
|
+
```
|
|
371
|
+
|
|
372
|
+
**8. Unknown command (e.g., `meshcode list`)**
|
|
373
|
+
Since v2.0.2, the CLI suggests the closest match instead of dumping the full help text. Common aliases: `list` and `ls` both work for `projects`.
|
|
374
|
+
|
|
344
375
|
**5. `MCP server failed to start` in the Claude Code `/mcp` panel**
|
|
345
376
|
Run `claude --debug` to see the underlying error. Nine times out of ten it's a stale or missing key — run `meshcode login mc_xxx` again.
|
|
346
377
|
|
|
@@ -128,7 +128,9 @@ meshcode revoke-member my-project <user> # kick a member instantly
|
|
|
128
128
|
| `meshcode status` | `meshcode status` | Show the logged-in account and version. |
|
|
129
129
|
| `meshcode send` (legacy) | `meshcode send my-project a:b '{"need":"..."}'` | Pre-1.5 manual message send (MCP tools are preferred). |
|
|
130
130
|
| `meshcode read` (legacy) | `meshcode read my-project backend` | Pre-1.5 manual read. |
|
|
131
|
-
| `meshcode
|
|
131
|
+
| `meshcode projects` | `meshcode projects` | List all your meshworks and their agents. |
|
|
132
|
+
| `meshcode list` | `meshcode list` | Alias for `meshcode projects`. |
|
|
133
|
+
| `meshcode --version` | `meshcode --version` | Print current version. |
|
|
132
134
|
| `meshcode help` | `meshcode help` | Top-level help. Per-verb help: `meshcode <verb> --help`. |
|
|
133
135
|
|
|
134
136
|
---
|
|
@@ -226,10 +228,11 @@ pip install meshcode --upgrade
|
|
|
226
228
|
### Reconnect a single agent
|
|
227
229
|
|
|
228
230
|
```bash
|
|
229
|
-
meshcode
|
|
231
|
+
meshcode setup my-project agent-name # ensures workspace exists (safe to re-run)
|
|
232
|
+
meshcode run agent-name # opens your editor
|
|
230
233
|
```
|
|
231
234
|
|
|
232
|
-
|
|
235
|
+
Since v2.0.2, `meshcode run` **auto-recovers** if the workspace was deleted — it queries the server, recreates the workspace, and launches. So `meshcode run agent-name` alone is usually enough. The agent automatically:
|
|
233
236
|
1. Loads its persistent memories (`meshcode_recall()`)
|
|
234
237
|
2. Checks who else is online (`meshcode_status()`)
|
|
235
238
|
3. Picks up any open tasks (`meshcode_tasks()`)
|
|
@@ -301,21 +304,49 @@ If an agent is offline, the dashboard shows a **Reconnect** button on its card.
|
|
|
301
304
|
|
|
302
305
|
## Troubleshooting
|
|
303
306
|
|
|
304
|
-
**1. `
|
|
307
|
+
**1. `no workspace found for agent 'X'`**
|
|
308
|
+
Your local workspace was deleted or never created. Since v2.0.2, `meshcode run` auto-recovers by querying the server. If you're on an older version:
|
|
309
|
+
```bash
|
|
310
|
+
pip install meshcode --upgrade # get v2.0.2+
|
|
311
|
+
meshcode run agent-name # auto-recovers now
|
|
312
|
+
```
|
|
313
|
+
If auto-recovery fails (no API key stored), run setup manually:
|
|
314
|
+
```bash
|
|
315
|
+
meshcode setup my-project agent-name # recreates ~/meshcode/my-project-agent-name/
|
|
316
|
+
meshcode run agent-name
|
|
317
|
+
```
|
|
318
|
+
|
|
319
|
+
**2. `meshcode projects` shows no projects (but dashboard shows them)**
|
|
320
|
+
Before v2.0.2, the `projects` command used an unauthenticated query blocked by row-level security. Upgrade:
|
|
321
|
+
```bash
|
|
322
|
+
pip install meshcode --upgrade
|
|
323
|
+
meshcode projects # now uses your API key
|
|
324
|
+
```
|
|
325
|
+
|
|
326
|
+
**3. `No credentials found. Run meshcode login first.`**
|
|
305
327
|
You haven't stored a key yet. Grab your `mc_xxx` from https://meshcode.io/onboarding and run:
|
|
306
328
|
```bash
|
|
307
329
|
meshcode login mc_xxxxxxxxxxxx
|
|
308
330
|
```
|
|
309
331
|
|
|
310
|
-
**
|
|
332
|
+
**4. `agent already running in another window`**
|
|
311
333
|
MeshCode prevents split-brain — the same agent name can't be live in two editor windows. Close the other window, or use a different agent name.
|
|
312
334
|
|
|
313
|
-
**
|
|
335
|
+
**5. `scoped api key cannot access this project`**
|
|
314
336
|
You joined a meshwork via an invite, and you're now trying to use a different project. Scoped keys only work for the one mesh they were minted for. Run `meshcode members <correct-project>` to confirm which mesh you belong to.
|
|
315
337
|
|
|
316
|
-
**
|
|
338
|
+
**6. `meshcode: command not found`**
|
|
317
339
|
Either `pip install` didn't add to your PATH (check `which meshcode` and `python -m site --user-base`), or you have a stale pre-1.0.0 `~/bin/meshcode` shim shadowing the real binary — delete it.
|
|
318
340
|
|
|
341
|
+
**7. `could not resolve project 'X': project not found`**
|
|
342
|
+
Wrong project name. Since v2.0.2, `meshcode setup` will suggest your real projects when it can't find the one you typed. Check the exact name:
|
|
343
|
+
```bash
|
|
344
|
+
meshcode projects # lists all your meshworks
|
|
345
|
+
```
|
|
346
|
+
|
|
347
|
+
**8. Unknown command (e.g., `meshcode list`)**
|
|
348
|
+
Since v2.0.2, the CLI suggests the closest match instead of dumping the full help text. Common aliases: `list` and `ls` both work for `projects`.
|
|
349
|
+
|
|
319
350
|
**5. `MCP server failed to start` in the Claude Code `/mcp` panel**
|
|
320
351
|
Run `claude --debug` to see the underlying error. Nine times out of ten it's a stale or missing key — run `meshcode login mc_xxx` again.
|
|
321
352
|
|
|
@@ -1,2 +1,2 @@
|
|
|
1
1
|
"""MeshCode — Real-time communication between AI agents."""
|
|
2
|
-
__version__ = "2.0.
|
|
2
|
+
__version__ = "2.0.4"
|
|
@@ -13,6 +13,7 @@ import logging
|
|
|
13
13
|
import ssl
|
|
14
14
|
from collections import deque
|
|
15
15
|
from typing import Any, Awaitable, Callable, Deque, Dict, Optional
|
|
16
|
+
from urllib.parse import quote as url_quote
|
|
16
17
|
|
|
17
18
|
try:
|
|
18
19
|
import certifi
|
|
@@ -138,7 +139,7 @@ class RealtimeListener:
|
|
|
138
139
|
"event": "INSERT",
|
|
139
140
|
"schema": "meshcode",
|
|
140
141
|
"table": "mc_messages",
|
|
141
|
-
"filter": f"to_agent=eq.{self.agent_name}",
|
|
142
|
+
"filter": f"to_agent=eq.{url_quote(self.agent_name, safe='')}",
|
|
142
143
|
}
|
|
143
144
|
]
|
|
144
145
|
}
|
|
@@ -44,18 +44,23 @@ def _try_auto_wake(from_agent: str, preview: str) -> None:
|
|
|
44
44
|
"""
|
|
45
45
|
if _IN_WAIT or not _AUTO_WAKE:
|
|
46
46
|
return
|
|
47
|
-
import subprocess, platform
|
|
48
|
-
|
|
47
|
+
import subprocess, platform, re
|
|
48
|
+
# Sanitize inputs: strip everything except alphanumeric, spaces, basic punctuation
|
|
49
|
+
safe_agent = re.sub(r'[^a-zA-Z0-9_\- ]', '', from_agent)[:50]
|
|
50
|
+
safe_preview = re.sub(r'[^a-zA-Z0-9_\-.,!? ]', '', preview)[:60]
|
|
51
|
+
nudge = f"New mesh message from {safe_agent}: {safe_preview}. Check inbox with meshcode_check()."
|
|
49
52
|
system = platform.system()
|
|
50
53
|
try:
|
|
51
54
|
if system == "Darwin":
|
|
52
|
-
#
|
|
55
|
+
# Use xdotool-style approach: pass nudge as argument, not interpolated script
|
|
53
56
|
parent_app = os.environ.get("TERM_PROGRAM", "Terminal")
|
|
54
57
|
app_name = "iTerm" if "iTerm" in parent_app else "Terminal"
|
|
58
|
+
# Escape for AppleScript string: replace backslash and double-quote
|
|
59
|
+
as_safe = nudge.replace("\\", "\\\\").replace('"', '\\"')
|
|
55
60
|
script = f'''
|
|
56
61
|
tell application "{app_name}"
|
|
57
62
|
tell application "System Events"
|
|
58
|
-
keystroke "{
|
|
63
|
+
keystroke "{as_safe}"
|
|
59
64
|
keystroke return
|
|
60
65
|
end tell
|
|
61
66
|
end tell
|
|
@@ -64,15 +69,17 @@ def _try_auto_wake(from_agent: str, preview: str) -> None:
|
|
|
64
69
|
stdout=subprocess.DEVNULL, stderr=subprocess.DEVNULL)
|
|
65
70
|
log.info(f"auto-wake: injected nudge via {app_name} AppleScript")
|
|
66
71
|
elif system == "Windows":
|
|
72
|
+
# Sanitize for SendKeys: strip braces and special SendKeys metacharacters
|
|
73
|
+
sk_safe = nudge.replace("{", "").replace("}", "").replace("+", "").replace("^", "").replace("%", "").replace("~", "")
|
|
67
74
|
ps_script = f'''
|
|
68
75
|
Add-Type -AssemblyName System.Windows.Forms
|
|
69
|
-
[System.Windows.Forms.SendKeys]::SendWait("{
|
|
76
|
+
[System.Windows.Forms.SendKeys]::SendWait("{sk_safe}{{ENTER}}")
|
|
70
77
|
'''
|
|
71
78
|
subprocess.Popen(["powershell", "-Command", ps_script],
|
|
72
79
|
stdout=subprocess.DEVNULL, stderr=subprocess.DEVNULL)
|
|
73
80
|
log.info("auto-wake: injected nudge via PowerShell SendKeys")
|
|
74
81
|
else:
|
|
75
|
-
# Linux —
|
|
82
|
+
# Linux — xdotool takes args directly, not shell-interpolated (safe)
|
|
76
83
|
subprocess.Popen(["xdotool", "type", "--clearmodifiers", nudge + "\n"],
|
|
77
84
|
stdout=subprocess.DEVNULL, stderr=subprocess.DEVNULL)
|
|
78
85
|
log.info("auto-wake: injected nudge via xdotool")
|
|
@@ -138,6 +145,35 @@ def _split_messages(messages: List[Dict[str, Any]]) -> Dict[str, Any]:
|
|
|
138
145
|
from . import backend as be
|
|
139
146
|
from .realtime import RealtimeListener
|
|
140
147
|
|
|
148
|
+
# ============================================================
|
|
149
|
+
# Hot-reload: detect when backend.py changes on disk (e.g. after
|
|
150
|
+
# pip install --upgrade meshcode) and reload without restart.
|
|
151
|
+
# Only backend.py is safe to reload (stateless). server.py has
|
|
152
|
+
# module-level state that would be destroyed by reload.
|
|
153
|
+
# ============================================================
|
|
154
|
+
import importlib as _importlib
|
|
155
|
+
_be_mtime: float = 0.0
|
|
156
|
+
try:
|
|
157
|
+
_be_path = os.path.abspath(be.__file__)
|
|
158
|
+
_be_mtime = os.path.getmtime(_be_path)
|
|
159
|
+
except Exception:
|
|
160
|
+
_be_path = ""
|
|
161
|
+
|
|
162
|
+
|
|
163
|
+
def _check_hot_reload() -> None:
|
|
164
|
+
"""If backend.py was modified since boot/last reload, reimport it."""
|
|
165
|
+
global _be_mtime, be
|
|
166
|
+
if not _be_path:
|
|
167
|
+
return
|
|
168
|
+
try:
|
|
169
|
+
current_mtime = os.path.getmtime(_be_path)
|
|
170
|
+
if current_mtime > _be_mtime:
|
|
171
|
+
_be_mtime = current_mtime
|
|
172
|
+
_importlib.reload(be)
|
|
173
|
+
log.info("[meshcode] Hot-reloaded backend.py (new version detected)")
|
|
174
|
+
except Exception as e:
|
|
175
|
+
log.debug(f"hot-reload check failed: {e}")
|
|
176
|
+
|
|
141
177
|
try:
|
|
142
178
|
from mcp.server.fastmcp import FastMCP
|
|
143
179
|
except ImportError:
|
|
@@ -310,6 +346,7 @@ def with_working_status(func):
|
|
|
310
346
|
if asyncio.iscoroutinefunction(func):
|
|
311
347
|
@_functools.wraps(func)
|
|
312
348
|
async def awrapper(*args, **kwargs):
|
|
349
|
+
_check_hot_reload()
|
|
313
350
|
if not skip:
|
|
314
351
|
_schedule_flip("working", name)
|
|
315
352
|
try:
|
|
@@ -321,6 +358,7 @@ def with_working_status(func):
|
|
|
321
358
|
else:
|
|
322
359
|
@_functools.wraps(func)
|
|
323
360
|
def swrapper(*args, **kwargs):
|
|
361
|
+
_check_hot_reload()
|
|
324
362
|
if not skip:
|
|
325
363
|
_schedule_flip("working", name)
|
|
326
364
|
try:
|
|
@@ -567,7 +605,10 @@ async def _on_new_message(msg: Dict[str, Any]) -> None:
|
|
|
567
605
|
from_agent = msg.get("from") or msg.get("from_agent") or "unknown"
|
|
568
606
|
payload = msg.get("payload") or {}
|
|
569
607
|
preview = payload.get("text", "") if isinstance(payload, dict) else str(payload)
|
|
570
|
-
|
|
608
|
+
try:
|
|
609
|
+
_try_auto_wake(from_agent, preview[:60])
|
|
610
|
+
except Exception:
|
|
611
|
+
pass # auto-wake is best-effort, never block message handling
|
|
571
612
|
|
|
572
613
|
try:
|
|
573
614
|
srv = mcp._mcp_server # FastMCP exposes the lowlevel server here
|
|
@@ -845,7 +886,20 @@ async def _meshcode_wait_inner(actual_timeout: int, include_acks: bool) -> Dict[
|
|
|
845
886
|
# Realtime unavailable — plain sleep fallback so we still honor timeout.
|
|
846
887
|
await asyncio.sleep(actual_timeout)
|
|
847
888
|
|
|
848
|
-
|
|
889
|
+
# On timeout, check for unclaimed tasks assigned to this agent
|
|
890
|
+
timeout_result: Dict[str, Any] = {"timed_out": True}
|
|
891
|
+
try:
|
|
892
|
+
api_key = _get_api_key()
|
|
893
|
+
open_tasks = be.task_list(api_key, _PROJECT_ID, AGENT_NAME, status_filter="open")
|
|
894
|
+
if isinstance(open_tasks, dict) and open_tasks.get("ok"):
|
|
895
|
+
my_tasks = [t for t in open_tasks.get("tasks", [])
|
|
896
|
+
if t.get("assignee") == AGENT_NAME and not t.get("claimed_by")]
|
|
897
|
+
if my_tasks:
|
|
898
|
+
timeout_result["unclaimed_tasks"] = len(my_tasks)
|
|
899
|
+
timeout_result["hint"] = f"You have {len(my_tasks)} unclaimed task(s) assigned to you. Run meshcode_tasks(status_filter='open') to see them."
|
|
900
|
+
except Exception:
|
|
901
|
+
pass
|
|
902
|
+
return timeout_result
|
|
849
903
|
|
|
850
904
|
|
|
851
905
|
@mcp.tool()
|
|
@@ -988,9 +1042,22 @@ def meshcode_task_create(title: str, description: str = "", assignee: str = "*",
|
|
|
988
1042
|
Returns: {"ok": true, "task_id": "...", "title": "..."}
|
|
989
1043
|
"""
|
|
990
1044
|
api_key = _get_api_key()
|
|
991
|
-
|
|
1045
|
+
result = be.task_create(api_key, _PROJECT_ID, AGENT_NAME, title,
|
|
992
1046
|
description=description, assignee=assignee,
|
|
993
1047
|
priority=priority, parent_task_id=parent_task_id)
|
|
1048
|
+
# Auto-notify assignee so they wake from meshcode_wait
|
|
1049
|
+
if isinstance(result, dict) and result.get("ok") and assignee and assignee != "*" and assignee != AGENT_NAME:
|
|
1050
|
+
try:
|
|
1051
|
+
be.send_message(_PROJECT_ID, AGENT_NAME, assignee, {
|
|
1052
|
+
"type": "task_assigned",
|
|
1053
|
+
"task_id": result.get("task_id", ""),
|
|
1054
|
+
"title": title,
|
|
1055
|
+
"priority": priority,
|
|
1056
|
+
"text": f"New {priority} task assigned to you: {title}",
|
|
1057
|
+
}, msg_type="system")
|
|
1058
|
+
except Exception:
|
|
1059
|
+
pass # best-effort notification
|
|
1060
|
+
return result
|
|
994
1061
|
|
|
995
1062
|
|
|
996
1063
|
@mcp.tool()
|
|
@@ -1258,6 +1325,9 @@ def _sync_to_obsidian(key: str, value: Any) -> None:
|
|
|
1258
1325
|
Writes markdown notes with YAML frontmatter to MeshCode/<agent>/ folder.
|
|
1259
1326
|
Failures are logged but never block the main memory write.
|
|
1260
1327
|
"""
|
|
1328
|
+
from datetime import datetime
|
|
1329
|
+
from urllib.request import Request, urlopen
|
|
1330
|
+
from urllib.error import URLError
|
|
1261
1331
|
try:
|
|
1262
1332
|
import importlib
|
|
1263
1333
|
prefs_mod = importlib.import_module("meshcode.preferences")
|
|
@@ -1265,10 +1335,6 @@ def _sync_to_obsidian(key: str, value: Any) -> None:
|
|
|
1265
1335
|
if not config:
|
|
1266
1336
|
return
|
|
1267
1337
|
|
|
1268
|
-
from datetime import datetime
|
|
1269
|
-
from urllib.request import Request, urlopen
|
|
1270
|
-
from urllib.error import URLError
|
|
1271
|
-
|
|
1272
1338
|
# Build markdown note with YAML frontmatter
|
|
1273
1339
|
timestamp = datetime.utcnow().strftime("%Y-%m-%dT%H:%M:%SZ")
|
|
1274
1340
|
if isinstance(value, (dict, list)):
|
|
@@ -1332,7 +1398,10 @@ def meshcode_remember(key: str, value: Any) -> Dict[str, Any]:
|
|
|
1332
1398
|
})
|
|
1333
1399
|
# Best-effort sync to Obsidian vault (if configured)
|
|
1334
1400
|
if isinstance(result, dict) and result.get("ok"):
|
|
1335
|
-
|
|
1401
|
+
try:
|
|
1402
|
+
_sync_to_obsidian(key, json_value)
|
|
1403
|
+
except Exception:
|
|
1404
|
+
pass # Obsidian sync is best-effort, never block memory writes
|
|
1336
1405
|
return result
|
|
1337
1406
|
|
|
1338
1407
|
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
Metadata-Version: 2.4
|
|
2
2
|
Name: meshcode
|
|
3
|
-
Version: 2.0.
|
|
3
|
+
Version: 2.0.4
|
|
4
4
|
Summary: Real-time communication between AI agents — Supabase-backed CLI
|
|
5
5
|
Author-email: MeshCode <hello@meshcode.io>
|
|
6
6
|
License: MIT
|
|
@@ -153,7 +153,9 @@ meshcode revoke-member my-project <user> # kick a member instantly
|
|
|
153
153
|
| `meshcode status` | `meshcode status` | Show the logged-in account and version. |
|
|
154
154
|
| `meshcode send` (legacy) | `meshcode send my-project a:b '{"need":"..."}'` | Pre-1.5 manual message send (MCP tools are preferred). |
|
|
155
155
|
| `meshcode read` (legacy) | `meshcode read my-project backend` | Pre-1.5 manual read. |
|
|
156
|
-
| `meshcode
|
|
156
|
+
| `meshcode projects` | `meshcode projects` | List all your meshworks and their agents. |
|
|
157
|
+
| `meshcode list` | `meshcode list` | Alias for `meshcode projects`. |
|
|
158
|
+
| `meshcode --version` | `meshcode --version` | Print current version. |
|
|
157
159
|
| `meshcode help` | `meshcode help` | Top-level help. Per-verb help: `meshcode <verb> --help`. |
|
|
158
160
|
|
|
159
161
|
---
|
|
@@ -251,10 +253,11 @@ pip install meshcode --upgrade
|
|
|
251
253
|
### Reconnect a single agent
|
|
252
254
|
|
|
253
255
|
```bash
|
|
254
|
-
meshcode
|
|
256
|
+
meshcode setup my-project agent-name # ensures workspace exists (safe to re-run)
|
|
257
|
+
meshcode run agent-name # opens your editor
|
|
255
258
|
```
|
|
256
259
|
|
|
257
|
-
|
|
260
|
+
Since v2.0.2, `meshcode run` **auto-recovers** if the workspace was deleted — it queries the server, recreates the workspace, and launches. So `meshcode run agent-name` alone is usually enough. The agent automatically:
|
|
258
261
|
1. Loads its persistent memories (`meshcode_recall()`)
|
|
259
262
|
2. Checks who else is online (`meshcode_status()`)
|
|
260
263
|
3. Picks up any open tasks (`meshcode_tasks()`)
|
|
@@ -326,21 +329,49 @@ If an agent is offline, the dashboard shows a **Reconnect** button on its card.
|
|
|
326
329
|
|
|
327
330
|
## Troubleshooting
|
|
328
331
|
|
|
329
|
-
**1. `
|
|
332
|
+
**1. `no workspace found for agent 'X'`**
|
|
333
|
+
Your local workspace was deleted or never created. Since v2.0.2, `meshcode run` auto-recovers by querying the server. If you're on an older version:
|
|
334
|
+
```bash
|
|
335
|
+
pip install meshcode --upgrade # get v2.0.2+
|
|
336
|
+
meshcode run agent-name # auto-recovers now
|
|
337
|
+
```
|
|
338
|
+
If auto-recovery fails (no API key stored), run setup manually:
|
|
339
|
+
```bash
|
|
340
|
+
meshcode setup my-project agent-name # recreates ~/meshcode/my-project-agent-name/
|
|
341
|
+
meshcode run agent-name
|
|
342
|
+
```
|
|
343
|
+
|
|
344
|
+
**2. `meshcode projects` shows no projects (but dashboard shows them)**
|
|
345
|
+
Before v2.0.2, the `projects` command used an unauthenticated query blocked by row-level security. Upgrade:
|
|
346
|
+
```bash
|
|
347
|
+
pip install meshcode --upgrade
|
|
348
|
+
meshcode projects # now uses your API key
|
|
349
|
+
```
|
|
350
|
+
|
|
351
|
+
**3. `No credentials found. Run meshcode login first.`**
|
|
330
352
|
You haven't stored a key yet. Grab your `mc_xxx` from https://meshcode.io/onboarding and run:
|
|
331
353
|
```bash
|
|
332
354
|
meshcode login mc_xxxxxxxxxxxx
|
|
333
355
|
```
|
|
334
356
|
|
|
335
|
-
**
|
|
357
|
+
**4. `agent already running in another window`**
|
|
336
358
|
MeshCode prevents split-brain — the same agent name can't be live in two editor windows. Close the other window, or use a different agent name.
|
|
337
359
|
|
|
338
|
-
**
|
|
360
|
+
**5. `scoped api key cannot access this project`**
|
|
339
361
|
You joined a meshwork via an invite, and you're now trying to use a different project. Scoped keys only work for the one mesh they were minted for. Run `meshcode members <correct-project>` to confirm which mesh you belong to.
|
|
340
362
|
|
|
341
|
-
**
|
|
363
|
+
**6. `meshcode: command not found`**
|
|
342
364
|
Either `pip install` didn't add to your PATH (check `which meshcode` and `python -m site --user-base`), or you have a stale pre-1.0.0 `~/bin/meshcode` shim shadowing the real binary — delete it.
|
|
343
365
|
|
|
366
|
+
**7. `could not resolve project 'X': project not found`**
|
|
367
|
+
Wrong project name. Since v2.0.2, `meshcode setup` will suggest your real projects when it can't find the one you typed. Check the exact name:
|
|
368
|
+
```bash
|
|
369
|
+
meshcode projects # lists all your meshworks
|
|
370
|
+
```
|
|
371
|
+
|
|
372
|
+
**8. Unknown command (e.g., `meshcode list`)**
|
|
373
|
+
Since v2.0.2, the CLI suggests the closest match instead of dumping the full help text. Common aliases: `list` and `ls` both work for `projects`.
|
|
374
|
+
|
|
344
375
|
**5. `MCP server failed to start` in the Claude Code `/mcp` panel**
|
|
345
376
|
Run `claude --debug` to see the underlying error. Nine times out of ten it's a stale or missing key — run `meshcode login mc_xxx` again.
|
|
346
377
|
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|