meshcode 2.6.4__tar.gz → 2.6.6__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.6.4 → meshcode-2.6.6}/PKG-INFO +1 -1
- {meshcode-2.6.4 → meshcode-2.6.6}/meshcode/__init__.py +1 -1
- {meshcode-2.6.4 → meshcode-2.6.6}/meshcode/meshcode_mcp/server.py +37 -7
- {meshcode-2.6.4 → meshcode-2.6.6}/meshcode.egg-info/PKG-INFO +1 -1
- {meshcode-2.6.4 → meshcode-2.6.6}/pyproject.toml +1 -1
- {meshcode-2.6.4 → meshcode-2.6.6}/README.md +0 -0
- {meshcode-2.6.4 → meshcode-2.6.6}/meshcode/cli.py +0 -0
- {meshcode-2.6.4 → meshcode-2.6.6}/meshcode/comms_v4.py +0 -0
- {meshcode-2.6.4 → meshcode-2.6.6}/meshcode/invites.py +0 -0
- {meshcode-2.6.4 → meshcode-2.6.6}/meshcode/launcher.py +0 -0
- {meshcode-2.6.4 → meshcode-2.6.6}/meshcode/launcher_install.py +0 -0
- {meshcode-2.6.4 → meshcode-2.6.6}/meshcode/meshcode_mcp/__init__.py +0 -0
- {meshcode-2.6.4 → meshcode-2.6.6}/meshcode/meshcode_mcp/__main__.py +0 -0
- {meshcode-2.6.4 → meshcode-2.6.6}/meshcode/meshcode_mcp/backend.py +0 -0
- {meshcode-2.6.4 → meshcode-2.6.6}/meshcode/meshcode_mcp/realtime.py +0 -0
- {meshcode-2.6.4 → meshcode-2.6.6}/meshcode/meshcode_mcp/test_backend.py +0 -0
- {meshcode-2.6.4 → meshcode-2.6.6}/meshcode/meshcode_mcp/test_realtime.py +0 -0
- {meshcode-2.6.4 → meshcode-2.6.6}/meshcode/meshcode_mcp/test_server_wrapper.py +0 -0
- {meshcode-2.6.4 → meshcode-2.6.6}/meshcode/preferences.py +0 -0
- {meshcode-2.6.4 → meshcode-2.6.6}/meshcode/protocol_v2.py +0 -0
- {meshcode-2.6.4 → meshcode-2.6.6}/meshcode/run_agent.py +0 -0
- {meshcode-2.6.4 → meshcode-2.6.6}/meshcode/secrets.py +0 -0
- {meshcode-2.6.4 → meshcode-2.6.6}/meshcode/self_update.py +0 -0
- {meshcode-2.6.4 → meshcode-2.6.6}/meshcode/setup_clients.py +0 -0
- {meshcode-2.6.4 → meshcode-2.6.6}/meshcode.egg-info/SOURCES.txt +0 -0
- {meshcode-2.6.4 → meshcode-2.6.6}/meshcode.egg-info/dependency_links.txt +0 -0
- {meshcode-2.6.4 → meshcode-2.6.6}/meshcode.egg-info/entry_points.txt +0 -0
- {meshcode-2.6.4 → meshcode-2.6.6}/meshcode.egg-info/requires.txt +0 -0
- {meshcode-2.6.4 → meshcode-2.6.6}/meshcode.egg-info/top_level.txt +0 -0
- {meshcode-2.6.4 → meshcode-2.6.6}/setup.cfg +0 -0
- {meshcode-2.6.4 → meshcode-2.6.6}/tests/test_status_enum_coverage.py +0 -0
|
@@ -1,2 +1,2 @@
|
|
|
1
1
|
"""MeshCode — Real-time communication between AI agents."""
|
|
2
|
-
__version__ = "2.6.
|
|
2
|
+
__version__ = "2.6.6"
|
|
@@ -746,7 +746,7 @@ RULES:
|
|
|
746
746
|
|
|
747
747
|
SESSION START (do these IMMEDIATELY — don't wait for user input):
|
|
748
748
|
1. meshcode_set_status(status="online", task="ready")
|
|
749
|
-
2. meshcode_check() — read
|
|
749
|
+
2. meshcode_check() — read NEW messages only (last_seen is auto-restored from mesh memory on boot, old messages are skipped automatically)
|
|
750
750
|
3. meshcode_tasks() — check for assigned/pending tasks and claim any unclaimed ones
|
|
751
751
|
4. meshcode_auto_wake() — scan meshwork health, create tasks for issues found
|
|
752
752
|
5. meshcode_status() — see who's online
|
|
@@ -1124,8 +1124,8 @@ except Exception:
|
|
|
1124
1124
|
@mcp.tool()
|
|
1125
1125
|
@with_working_status
|
|
1126
1126
|
def meshcode_send(to: str, message: Any, in_reply_to: Optional[str] = None,
|
|
1127
|
-
sensitive: bool = False, encrypted: bool =
|
|
1128
|
-
"""Send message. Use "agent@meshwork" for cross-mesh. sensitive=True hides from exports.
|
|
1127
|
+
sensitive: bool = False, encrypted: bool = False) -> Dict[str, Any]:
|
|
1128
|
+
"""Send message. Use "agent@meshwork" for cross-mesh. sensitive=True hides from exports. Pass encrypted=True for secrets/credentials (AES-256-GCM)."""
|
|
1129
1129
|
if isinstance(message, str):
|
|
1130
1130
|
# Auto-wrap strings but warn if too long — prefer structured JSON
|
|
1131
1131
|
if len(message) > 400:
|
|
@@ -1291,6 +1291,25 @@ _CONSECUTIVE_IDLE_SECONDS = 0
|
|
|
1291
1291
|
_AUTO_SLEEP_THRESHOLD = int(os.environ.get("MESHCODE_AUTO_SLEEP_SECONDS", "600")) # default 10min
|
|
1292
1292
|
_LAST_SEEN_TS: Optional[str] = None # auto-persisted for message dedup
|
|
1293
1293
|
|
|
1294
|
+
# Hydrate _LAST_SEEN_TS from mesh memory on boot so restarts skip old messages
|
|
1295
|
+
try:
|
|
1296
|
+
_ls_result = be.sb_rpc("mc_memory_get", {
|
|
1297
|
+
"p_api_key": _get_api_key(),
|
|
1298
|
+
"p_agent_name": AGENT_NAME,
|
|
1299
|
+
"p_key": "last_seen",
|
|
1300
|
+
"p_project_name": PROJECT_NAME,
|
|
1301
|
+
})
|
|
1302
|
+
if isinstance(_ls_result, dict) and _ls_result.get("ok"):
|
|
1303
|
+
_ls_val = _ls_result.get("value")
|
|
1304
|
+
if isinstance(_ls_val, dict) and _ls_val.get("_raw"):
|
|
1305
|
+
_LAST_SEEN_TS = str(_ls_val["_raw"])
|
|
1306
|
+
elif isinstance(_ls_val, str):
|
|
1307
|
+
_LAST_SEEN_TS = _ls_val
|
|
1308
|
+
if _LAST_SEEN_TS:
|
|
1309
|
+
print(f"[meshcode] Restored last_seen={_LAST_SEEN_TS} from mesh memory.", file=sys.stderr)
|
|
1310
|
+
except Exception as _e:
|
|
1311
|
+
print(f"[meshcode] Could not restore last_seen: {_e}", file=sys.stderr)
|
|
1312
|
+
|
|
1294
1313
|
|
|
1295
1314
|
def _get_pending_tasks_summary() -> Optional[List[Dict[str, str]]]:
|
|
1296
1315
|
"""Fetch open/in_progress tasks assigned to this agent. Returns compact list or None."""
|
|
@@ -1306,7 +1325,7 @@ def _get_pending_tasks_summary() -> Optional[List[Dict[str, str]]]:
|
|
|
1306
1325
|
{"id": t["id"][:8], "title": t["title"][:80], "priority": t.get("priority", "normal"), "status": t["status"]}
|
|
1307
1326
|
for t in tasks
|
|
1308
1327
|
if t.get("status") in ("open", "in_progress")
|
|
1309
|
-
and (t.get("
|
|
1328
|
+
and (t.get("assignee") in (AGENT_NAME, "*", None) or t.get("claimed_by") == AGENT_NAME)
|
|
1310
1329
|
]
|
|
1311
1330
|
return pending if pending else None
|
|
1312
1331
|
except Exception:
|
|
@@ -1321,7 +1340,7 @@ async def meshcode_wait(timeout_seconds: int = 120, include_acks: bool = False)
|
|
|
1321
1340
|
Args:
|
|
1322
1341
|
timeout_seconds: Max wait time in seconds (default 120, hard cap 120).
|
|
1323
1342
|
"""
|
|
1324
|
-
global _IN_WAIT, _CONSECUTIVE_IDLE_SECONDS
|
|
1343
|
+
global _IN_WAIT, _CONSECUTIVE_IDLE_SECONDS, _LAST_SEEN_TS
|
|
1325
1344
|
|
|
1326
1345
|
# PRODUCT RULE 1: If agent has open tasks, refuse to wait. Work first.
|
|
1327
1346
|
pending_tasks = _get_pending_tasks_summary()
|
|
@@ -1397,13 +1416,23 @@ async def meshcode_wait(timeout_seconds: int = 120, include_acks: bool = False)
|
|
|
1397
1416
|
if pending_tasks:
|
|
1398
1417
|
result["pending_tasks"] = pending_tasks
|
|
1399
1418
|
# Track last seen timestamp for message dedup
|
|
1400
|
-
global _LAST_SEEN_TS
|
|
1401
1419
|
if result.get("got_message"):
|
|
1402
1420
|
msgs = result.get("messages", [])
|
|
1403
1421
|
if msgs:
|
|
1404
1422
|
latest_ts = max((m.get("ts", "") for m in msgs), default="")
|
|
1405
1423
|
if latest_ts:
|
|
1406
1424
|
_LAST_SEEN_TS = latest_ts
|
|
1425
|
+
# Persist to mesh memory so next session resumes here
|
|
1426
|
+
try:
|
|
1427
|
+
be.sb_rpc("mc_memory_set", {
|
|
1428
|
+
"p_api_key": _get_api_key(),
|
|
1429
|
+
"p_agent_name": AGENT_NAME,
|
|
1430
|
+
"p_key": "last_seen",
|
|
1431
|
+
"p_value": {"_raw": latest_ts},
|
|
1432
|
+
"p_project_name": PROJECT_NAME,
|
|
1433
|
+
})
|
|
1434
|
+
except Exception:
|
|
1435
|
+
pass # best-effort, never block wait loop
|
|
1407
1436
|
return result
|
|
1408
1437
|
finally:
|
|
1409
1438
|
_IN_WAIT = False
|
|
@@ -1570,6 +1599,7 @@ def meshcode_check(include_acks: bool = False, since: Optional[str] = None) -> D
|
|
|
1570
1599
|
since: ISO-8601 timestamp. Only return messages newer than this.
|
|
1571
1600
|
Use meshcode_remember("last_seen", ts) to persist across sessions.
|
|
1572
1601
|
"""
|
|
1602
|
+
global _LAST_SEEN_TS
|
|
1573
1603
|
pending = be.count_pending(_PROJECT_ID, AGENT_NAME, api_key=_get_api_key())
|
|
1574
1604
|
# Peek at realtime buffer WITHOUT draining — check is non-destructive
|
|
1575
1605
|
realtime_buffered = _REALTIME.peek() if _REALTIME else []
|
|
@@ -1805,7 +1835,7 @@ def meshcode_auto_wake() -> Dict[str, Any]:
|
|
|
1805
1835
|
task_result = be.task_list(api_key, _PROJECT_ID, AGENT_NAME, status_filter="open")
|
|
1806
1836
|
if isinstance(task_result, dict) and task_result.get("ok"):
|
|
1807
1837
|
open_tasks = task_result.get("tasks", [])
|
|
1808
|
-
unassigned = [t for t in open_tasks if not t.get("
|
|
1838
|
+
unassigned = [t for t in open_tasks if not t.get("assignee") or t.get("assignee") == "*"]
|
|
1809
1839
|
if len(unassigned) > 3:
|
|
1810
1840
|
suggestions.append({
|
|
1811
1841
|
"title": f"Task backlog: {len(unassigned)} unassigned open tasks",
|
|
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
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|