meshcode 2.8.0__tar.gz → 2.8.2__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.8.0 → meshcode-2.8.2}/PKG-INFO +1 -1
- {meshcode-2.8.0 → meshcode-2.8.2}/meshcode/__init__.py +1 -1
- {meshcode-2.8.0 → meshcode-2.8.2}/meshcode/meshcode_mcp/server.py +52 -7
- {meshcode-2.8.0 → meshcode-2.8.2}/meshcode.egg-info/PKG-INFO +1 -1
- {meshcode-2.8.0 → meshcode-2.8.2}/pyproject.toml +1 -1
- {meshcode-2.8.0 → meshcode-2.8.2}/README.md +0 -0
- {meshcode-2.8.0 → meshcode-2.8.2}/meshcode/cli.py +0 -0
- {meshcode-2.8.0 → meshcode-2.8.2}/meshcode/comms_v4.py +0 -0
- {meshcode-2.8.0 → meshcode-2.8.2}/meshcode/invites.py +0 -0
- {meshcode-2.8.0 → meshcode-2.8.2}/meshcode/launcher.py +0 -0
- {meshcode-2.8.0 → meshcode-2.8.2}/meshcode/launcher_install.py +0 -0
- {meshcode-2.8.0 → meshcode-2.8.2}/meshcode/meshcode_mcp/__init__.py +0 -0
- {meshcode-2.8.0 → meshcode-2.8.2}/meshcode/meshcode_mcp/__main__.py +0 -0
- {meshcode-2.8.0 → meshcode-2.8.2}/meshcode/meshcode_mcp/backend.py +0 -0
- {meshcode-2.8.0 → meshcode-2.8.2}/meshcode/meshcode_mcp/realtime.py +0 -0
- {meshcode-2.8.0 → meshcode-2.8.2}/meshcode/meshcode_mcp/test_backend.py +0 -0
- {meshcode-2.8.0 → meshcode-2.8.2}/meshcode/meshcode_mcp/test_realtime.py +0 -0
- {meshcode-2.8.0 → meshcode-2.8.2}/meshcode/meshcode_mcp/test_server_wrapper.py +0 -0
- {meshcode-2.8.0 → meshcode-2.8.2}/meshcode/preferences.py +0 -0
- {meshcode-2.8.0 → meshcode-2.8.2}/meshcode/protocol_v2.py +0 -0
- {meshcode-2.8.0 → meshcode-2.8.2}/meshcode/run_agent.py +0 -0
- {meshcode-2.8.0 → meshcode-2.8.2}/meshcode/secrets.py +0 -0
- {meshcode-2.8.0 → meshcode-2.8.2}/meshcode/self_update.py +0 -0
- {meshcode-2.8.0 → meshcode-2.8.2}/meshcode/setup_clients.py +0 -0
- {meshcode-2.8.0 → meshcode-2.8.2}/meshcode.egg-info/SOURCES.txt +0 -0
- {meshcode-2.8.0 → meshcode-2.8.2}/meshcode.egg-info/dependency_links.txt +0 -0
- {meshcode-2.8.0 → meshcode-2.8.2}/meshcode.egg-info/entry_points.txt +0 -0
- {meshcode-2.8.0 → meshcode-2.8.2}/meshcode.egg-info/requires.txt +0 -0
- {meshcode-2.8.0 → meshcode-2.8.2}/meshcode.egg-info/top_level.txt +0 -0
- {meshcode-2.8.0 → meshcode-2.8.2}/setup.cfg +0 -0
- {meshcode-2.8.0 → meshcode-2.8.2}/tests/test_status_enum_coverage.py +0 -0
|
@@ -1,2 +1,2 @@
|
|
|
1
1
|
"""MeshCode — Real-time communication between AI agents."""
|
|
2
|
-
__version__ = "2.8.
|
|
2
|
+
__version__ = "2.8.2"
|
|
@@ -978,7 +978,7 @@ def _heartbeat_thread_fn():
|
|
|
978
978
|
elif _current_state == "online" and idle_secs > 30:
|
|
979
979
|
# Brief idle — show as idle, not sleeping yet
|
|
980
980
|
_set_state("idle", "idle")
|
|
981
|
-
elif _current_state == "idle" and idle_secs > 300 and parent_cpu < 2.0:
|
|
981
|
+
elif _current_state == "idle" and idle_secs > 300 and parent_cpu < 2.0 and not _STAY_AWAKE:
|
|
982
982
|
# Extended idle + no CPU activity → sleeping (5 min, not 90s)
|
|
983
983
|
_set_state("sleeping", "sleeping")
|
|
984
984
|
|
|
@@ -1274,6 +1274,7 @@ def _detect_global_done(messages: List[Dict[str, Any]]) -> Optional[Dict[str, An
|
|
|
1274
1274
|
# Auto-sleep: track consecutive idle timeouts to auto-sleep after threshold
|
|
1275
1275
|
_CONSECUTIVE_IDLE_SECONDS = 0
|
|
1276
1276
|
_AUTO_SLEEP_THRESHOLD = int(os.environ.get("MESHCODE_AUTO_SLEEP_SECONDS", "600")) # default 10min
|
|
1277
|
+
_STAY_AWAKE = False # Set by meshcode_set_status("online") — prevents auto-sleep
|
|
1277
1278
|
_LAST_SEEN_TS: Optional[str] = None # auto-persisted for message dedup
|
|
1278
1279
|
|
|
1279
1280
|
# Hydrate _LAST_SEEN_TS from mesh memory on boot so restarts skip old messages
|
|
@@ -1282,7 +1283,6 @@ try:
|
|
|
1282
1283
|
"p_api_key": _get_api_key(),
|
|
1283
1284
|
"p_agent_name": AGENT_NAME,
|
|
1284
1285
|
"p_key": "last_seen",
|
|
1285
|
-
"p_project_name": PROJECT_NAME,
|
|
1286
1286
|
})
|
|
1287
1287
|
if isinstance(_ls_result, dict) and _ls_result.get("ok"):
|
|
1288
1288
|
_ls_val = _ls_result.get("value")
|
|
@@ -1404,7 +1404,7 @@ async def meshcode_wait(timeout_seconds: int = 120, include_acks: bool = False)
|
|
|
1404
1404
|
break # Return so agent can work tasks
|
|
1405
1405
|
|
|
1406
1406
|
# Update status to sleeping after threshold, but keep looping
|
|
1407
|
-
if _AUTO_SLEEP_THRESHOLD > 0 and _CONSECUTIVE_IDLE_SECONDS >= _AUTO_SLEEP_THRESHOLD:
|
|
1407
|
+
if _AUTO_SLEEP_THRESHOLD > 0 and _CONSECUTIVE_IDLE_SECONDS >= _AUTO_SLEEP_THRESHOLD and not _STAY_AWAKE:
|
|
1408
1408
|
try:
|
|
1409
1409
|
api_key = _get_api_key()
|
|
1410
1410
|
if api_key:
|
|
@@ -1438,6 +1438,7 @@ async def meshcode_wait(timeout_seconds: int = 120, include_acks: bool = False)
|
|
|
1438
1438
|
"p_agent_name": AGENT_NAME,
|
|
1439
1439
|
"p_key": "last_seen",
|
|
1440
1440
|
"p_value": {"_raw": latest_ts},
|
|
1441
|
+
"p_tier": "critical",
|
|
1441
1442
|
"p_project_name": PROJECT_NAME,
|
|
1442
1443
|
})
|
|
1443
1444
|
except Exception:
|
|
@@ -1721,6 +1722,7 @@ def meshcode_set_status(status: str, task: str = "") -> Dict[str, Any]:
|
|
|
1721
1722
|
status: One of: working, idle, standby, blocked, done, online, sleeping.
|
|
1722
1723
|
task: Optional human-readable task description.
|
|
1723
1724
|
"""
|
|
1725
|
+
global _STAY_AWAKE
|
|
1724
1726
|
# PRODUCT RULE: Cannot sleep/idle/standby with open tasks. Work first.
|
|
1725
1727
|
if status in ("sleeping", "idle", "standby"):
|
|
1726
1728
|
pending_tasks = _get_pending_tasks_summary()
|
|
@@ -1730,6 +1732,12 @@ def meshcode_set_status(status: str, task: str = "") -> Dict[str, Any]:
|
|
|
1730
1732
|
"reason": f"Cannot set status '{status}' — you have {len(pending_tasks)} open tasks. Work them first.",
|
|
1731
1733
|
"pending_tasks": pending_tasks,
|
|
1732
1734
|
}
|
|
1735
|
+
# Setting online/working = stay awake (prevent auto-sleep)
|
|
1736
|
+
# Setting sleeping = allow auto-sleep again
|
|
1737
|
+
if status in ("online", "working"):
|
|
1738
|
+
_STAY_AWAKE = True
|
|
1739
|
+
elif status == "sleeping":
|
|
1740
|
+
_STAY_AWAKE = False
|
|
1733
1741
|
return be.set_status(_PROJECT_ID, AGENT_NAME, status, task, api_key=_get_api_key())
|
|
1734
1742
|
|
|
1735
1743
|
|
|
@@ -1798,9 +1806,29 @@ def meshcode_task_claim(task_id: str) -> Dict[str, Any]:
|
|
|
1798
1806
|
@mcp.tool()
|
|
1799
1807
|
@with_working_status
|
|
1800
1808
|
def meshcode_task_complete(task_id: str, summary: str = "") -> Dict[str, Any]:
|
|
1801
|
-
"""Complete a claimed task with summary."""
|
|
1809
|
+
"""Complete a claimed task with summary. Auto-remembers the task summary."""
|
|
1802
1810
|
api_key = _get_api_key()
|
|
1803
|
-
|
|
1811
|
+
result = be.task_complete(api_key, _PROJECT_ID, task_id, AGENT_NAME, summary=summary)
|
|
1812
|
+
# Auto-remember task completion for future context
|
|
1813
|
+
if isinstance(result, dict) and result.get("ok") and summary:
|
|
1814
|
+
try:
|
|
1815
|
+
import threading
|
|
1816
|
+
def _auto_remember():
|
|
1817
|
+
try:
|
|
1818
|
+
be.sb_rpc("mc_memory_set", {
|
|
1819
|
+
"p_api_key": api_key,
|
|
1820
|
+
"p_agent_name": AGENT_NAME,
|
|
1821
|
+
"p_key": f"task_{task_id[:8]}",
|
|
1822
|
+
"p_value": {"title": result.get("title", ""), "summary": summary, "completed": True},
|
|
1823
|
+
"p_tier": "episodic",
|
|
1824
|
+
"p_project_name": PROJECT_NAME,
|
|
1825
|
+
})
|
|
1826
|
+
except Exception:
|
|
1827
|
+
pass
|
|
1828
|
+
threading.Thread(target=_auto_remember, daemon=True).start()
|
|
1829
|
+
except Exception:
|
|
1830
|
+
pass
|
|
1831
|
+
return result
|
|
1804
1832
|
|
|
1805
1833
|
|
|
1806
1834
|
@mcp.tool()
|
|
@@ -2160,6 +2188,7 @@ def meshcode_remember(key: str, value: Any) -> Dict[str, Any]:
|
|
|
2160
2188
|
"p_agent_name": AGENT_NAME,
|
|
2161
2189
|
"p_key": key,
|
|
2162
2190
|
"p_value": json_value,
|
|
2191
|
+
"p_tier": "reference",
|
|
2163
2192
|
"p_project_name": PROJECT_NAME,
|
|
2164
2193
|
})
|
|
2165
2194
|
# Best-effort sync to Obsidian vault (if configured)
|
|
@@ -2185,16 +2214,33 @@ def meshcode_recall(key: Optional[str] = None) -> Dict[str, Any]:
|
|
|
2185
2214
|
"p_api_key": api_key,
|
|
2186
2215
|
"p_agent_name": AGENT_NAME,
|
|
2187
2216
|
"p_key": key,
|
|
2188
|
-
"p_project_name": PROJECT_NAME,
|
|
2189
2217
|
})
|
|
2190
2218
|
else:
|
|
2191
2219
|
return be.sb_rpc("mc_memory_list", {
|
|
2192
2220
|
"p_api_key": api_key,
|
|
2193
2221
|
"p_agent_name": AGENT_NAME,
|
|
2222
|
+
"p_tier": "critical",
|
|
2194
2223
|
"p_project_name": PROJECT_NAME,
|
|
2195
2224
|
})
|
|
2196
2225
|
|
|
2197
2226
|
|
|
2227
|
+
@mcp.tool()
|
|
2228
|
+
@with_working_status
|
|
2229
|
+
def meshcode_recall_keys() -> Dict[str, Any]:
|
|
2230
|
+
"""List memory keys only (no values). Cheap token cost for deciding what to recall."""
|
|
2231
|
+
api_key = _get_api_key()
|
|
2232
|
+
result = be.sb_rpc("mc_memory_list", {
|
|
2233
|
+
"p_api_key": api_key,
|
|
2234
|
+
"p_agent_name": AGENT_NAME,
|
|
2235
|
+
"p_tier": "reference",
|
|
2236
|
+
"p_project_name": PROJECT_NAME,
|
|
2237
|
+
})
|
|
2238
|
+
if isinstance(result, dict) and result.get("ok"):
|
|
2239
|
+
keys = [m.get("key") for m in result.get("memories", []) if m.get("key")]
|
|
2240
|
+
return {"ok": True, "keys": keys, "count": len(keys)}
|
|
2241
|
+
return result
|
|
2242
|
+
|
|
2243
|
+
|
|
2198
2244
|
@mcp.tool()
|
|
2199
2245
|
@with_working_status
|
|
2200
2246
|
def meshcode_forget(key: str) -> Dict[str, Any]:
|
|
@@ -2208,7 +2254,6 @@ def meshcode_forget(key: str) -> Dict[str, Any]:
|
|
|
2208
2254
|
"p_api_key": api_key,
|
|
2209
2255
|
"p_agent_name": AGENT_NAME,
|
|
2210
2256
|
"p_key": key,
|
|
2211
|
-
"p_project_name": PROJECT_NAME,
|
|
2212
2257
|
})
|
|
2213
2258
|
|
|
2214
2259
|
|
|
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
|