meshcode 2.5.1__tar.gz → 2.5.3__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.5.1 → meshcode-2.5.3}/PKG-INFO +1 -1
- {meshcode-2.5.1 → meshcode-2.5.3}/meshcode/__init__.py +1 -1
- {meshcode-2.5.1 → meshcode-2.5.3}/meshcode/meshcode_mcp/server.py +108 -0
- {meshcode-2.5.1 → meshcode-2.5.3}/meshcode.egg-info/PKG-INFO +1 -1
- {meshcode-2.5.1 → meshcode-2.5.3}/pyproject.toml +1 -1
- {meshcode-2.5.1 → meshcode-2.5.3}/README.md +0 -0
- {meshcode-2.5.1 → meshcode-2.5.3}/meshcode/cli.py +0 -0
- {meshcode-2.5.1 → meshcode-2.5.3}/meshcode/comms_v4.py +0 -0
- {meshcode-2.5.1 → meshcode-2.5.3}/meshcode/invites.py +0 -0
- {meshcode-2.5.1 → meshcode-2.5.3}/meshcode/launcher.py +0 -0
- {meshcode-2.5.1 → meshcode-2.5.3}/meshcode/launcher_install.py +0 -0
- {meshcode-2.5.1 → meshcode-2.5.3}/meshcode/meshcode_mcp/__init__.py +0 -0
- {meshcode-2.5.1 → meshcode-2.5.3}/meshcode/meshcode_mcp/__main__.py +0 -0
- {meshcode-2.5.1 → meshcode-2.5.3}/meshcode/meshcode_mcp/backend.py +0 -0
- {meshcode-2.5.1 → meshcode-2.5.3}/meshcode/meshcode_mcp/realtime.py +0 -0
- {meshcode-2.5.1 → meshcode-2.5.3}/meshcode/meshcode_mcp/test_backend.py +0 -0
- {meshcode-2.5.1 → meshcode-2.5.3}/meshcode/meshcode_mcp/test_realtime.py +0 -0
- {meshcode-2.5.1 → meshcode-2.5.3}/meshcode/meshcode_mcp/test_server_wrapper.py +0 -0
- {meshcode-2.5.1 → meshcode-2.5.3}/meshcode/preferences.py +0 -0
- {meshcode-2.5.1 → meshcode-2.5.3}/meshcode/protocol_v2.py +0 -0
- {meshcode-2.5.1 → meshcode-2.5.3}/meshcode/run_agent.py +0 -0
- {meshcode-2.5.1 → meshcode-2.5.3}/meshcode/secrets.py +0 -0
- {meshcode-2.5.1 → meshcode-2.5.3}/meshcode/self_update.py +0 -0
- {meshcode-2.5.1 → meshcode-2.5.3}/meshcode/setup_clients.py +0 -0
- {meshcode-2.5.1 → meshcode-2.5.3}/meshcode.egg-info/SOURCES.txt +0 -0
- {meshcode-2.5.1 → meshcode-2.5.3}/meshcode.egg-info/dependency_links.txt +0 -0
- {meshcode-2.5.1 → meshcode-2.5.3}/meshcode.egg-info/entry_points.txt +0 -0
- {meshcode-2.5.1 → meshcode-2.5.3}/meshcode.egg-info/requires.txt +0 -0
- {meshcode-2.5.1 → meshcode-2.5.3}/meshcode.egg-info/top_level.txt +0 -0
- {meshcode-2.5.1 → meshcode-2.5.3}/setup.cfg +0 -0
- {meshcode-2.5.1 → meshcode-2.5.3}/tests/test_status_enum_coverage.py +0 -0
|
@@ -1,2 +1,2 @@
|
|
|
1
1
|
"""MeshCode — Real-time communication between AI agents."""
|
|
2
|
-
__version__ = "2.5.
|
|
2
|
+
__version__ = "2.5.3"
|
|
@@ -452,6 +452,27 @@ def _working_to_online() -> None:
|
|
|
452
452
|
_set_state("online", "")
|
|
453
453
|
|
|
454
454
|
|
|
455
|
+
def _auto_learn_error(tool_name: str, error: Exception, args_keys: list) -> None:
|
|
456
|
+
"""Auto-save failed tool calls to agent memory for self-improvement."""
|
|
457
|
+
try:
|
|
458
|
+
import datetime as _dt
|
|
459
|
+
key = f"error_{tool_name}_{_dt.date.today().isoformat()}"
|
|
460
|
+
be.sb_rpc("mc_memory_set", {
|
|
461
|
+
"p_api_key": _get_api_key(),
|
|
462
|
+
"p_project_id": _PROJECT_ID,
|
|
463
|
+
"p_agent_name": AGENT_NAME,
|
|
464
|
+
"p_key": key,
|
|
465
|
+
"p_value": {
|
|
466
|
+
"tool": tool_name,
|
|
467
|
+
"error": str(error)[:200],
|
|
468
|
+
"args_keys": args_keys,
|
|
469
|
+
"timestamp": _dt.datetime.utcnow().isoformat(),
|
|
470
|
+
},
|
|
471
|
+
})
|
|
472
|
+
except Exception:
|
|
473
|
+
pass # Never let error-learning itself cause failures
|
|
474
|
+
|
|
475
|
+
|
|
455
476
|
def with_working_status(func):
|
|
456
477
|
name = func.__name__
|
|
457
478
|
skip = (name == "meshcode_wait")
|
|
@@ -465,6 +486,10 @@ def with_working_status(func):
|
|
|
465
486
|
_record_event_bg("tool_call", {"tool": name, "args_keys": list(kwargs.keys())})
|
|
466
487
|
try:
|
|
467
488
|
return await func(*args, **kwargs)
|
|
489
|
+
except Exception as e:
|
|
490
|
+
if not skip:
|
|
491
|
+
_auto_learn_error(name, e, list(kwargs.keys()))
|
|
492
|
+
raise
|
|
468
493
|
finally:
|
|
469
494
|
if not skip:
|
|
470
495
|
global _last_tool_at
|
|
@@ -482,6 +507,10 @@ def with_working_status(func):
|
|
|
482
507
|
_record_event_bg("tool_call", {"tool": name, "args_keys": list(kwargs.keys())})
|
|
483
508
|
try:
|
|
484
509
|
return func(*args, **kwargs)
|
|
510
|
+
except Exception as e:
|
|
511
|
+
if not skip:
|
|
512
|
+
_auto_learn_error(name, e, list(kwargs.keys()))
|
|
513
|
+
raise
|
|
485
514
|
finally:
|
|
486
515
|
if not skip:
|
|
487
516
|
global _last_tool_at
|
|
@@ -579,6 +608,65 @@ if not _acquire_lease():
|
|
|
579
608
|
sys.exit(2)
|
|
580
609
|
|
|
581
610
|
|
|
611
|
+
def _boot_diagnostic() -> None:
|
|
612
|
+
"""Run non-fatal boot health checks. Print clear warnings on failure."""
|
|
613
|
+
checks_passed = 0
|
|
614
|
+
checks_total = 4
|
|
615
|
+
api_key = _get_api_key()
|
|
616
|
+
|
|
617
|
+
# Check 1: API reachable
|
|
618
|
+
try:
|
|
619
|
+
be.sb_select("mc_projects", f"id=eq.{_PROJECT_ID}", limit=1)
|
|
620
|
+
checks_passed += 1
|
|
621
|
+
except Exception as e:
|
|
622
|
+
print(f"[meshcode] BOOT CHECK FAILED: Supabase API unreachable ({e}). Fix: check network/VPN.", file=sys.stderr)
|
|
623
|
+
|
|
624
|
+
# Check 2: Lease valid
|
|
625
|
+
try:
|
|
626
|
+
r = be.sb_select("mc_agents", f"project_id=eq.{_PROJECT_ID}&name=eq.{AGENT_NAME}", limit=1)
|
|
627
|
+
if r and isinstance(r, list) and len(r) > 0:
|
|
628
|
+
agent = r[0]
|
|
629
|
+
if agent.get("instance_id") == _INSTANCE_ID:
|
|
630
|
+
checks_passed += 1
|
|
631
|
+
else:
|
|
632
|
+
print(f"[meshcode] BOOT CHECK FAILED: Lease mismatch — expected {_INSTANCE_ID}, got {agent.get('instance_id')}. Fix: restart agent.", file=sys.stderr)
|
|
633
|
+
else:
|
|
634
|
+
print(f"[meshcode] BOOT CHECK FAILED: Agent '{AGENT_NAME}' not found in project. Fix: register agent first.", file=sys.stderr)
|
|
635
|
+
except Exception as e:
|
|
636
|
+
print(f"[meshcode] BOOT CHECK FAILED: Could not verify lease ({e}).", file=sys.stderr)
|
|
637
|
+
|
|
638
|
+
# Check 3: Heartbeat recent
|
|
639
|
+
try:
|
|
640
|
+
if r and isinstance(r, list) and len(r) > 0:
|
|
641
|
+
hb = agent.get("last_heartbeat")
|
|
642
|
+
if hb:
|
|
643
|
+
checks_passed += 1
|
|
644
|
+
else:
|
|
645
|
+
print(f"[meshcode] BOOT CHECK WARNING: No heartbeat recorded yet.", file=sys.stderr)
|
|
646
|
+
else:
|
|
647
|
+
checks_passed += 1 # skip if no agent data
|
|
648
|
+
except Exception:
|
|
649
|
+
checks_passed += 1 # skip on error
|
|
650
|
+
|
|
651
|
+
# Check 4: Version tracking
|
|
652
|
+
try:
|
|
653
|
+
from meshcode import __version__
|
|
654
|
+
be.sb_update("mc_agents",
|
|
655
|
+
f"project_id=eq.{_PROJECT_ID}&name=eq.{AGENT_NAME}",
|
|
656
|
+
{"mc_version": __version__})
|
|
657
|
+
checks_passed += 1
|
|
658
|
+
except Exception:
|
|
659
|
+
checks_passed += 1 # non-critical
|
|
660
|
+
|
|
661
|
+
if checks_passed == checks_total:
|
|
662
|
+
print(f"[meshcode] All boot checks passed ({checks_passed}/{checks_total}).", file=sys.stderr)
|
|
663
|
+
else:
|
|
664
|
+
print(f"[meshcode] Boot checks: {checks_passed}/{checks_total} passed. Agent starting anyway.", file=sys.stderr)
|
|
665
|
+
|
|
666
|
+
|
|
667
|
+
_boot_diagnostic()
|
|
668
|
+
|
|
669
|
+
|
|
582
670
|
def _release_lease() -> None:
|
|
583
671
|
api_key = _get_api_key()
|
|
584
672
|
if not api_key:
|
|
@@ -970,6 +1058,26 @@ async def lifespan(_app):
|
|
|
970
1058
|
yield {"realtime": _REALTIME}
|
|
971
1059
|
finally:
|
|
972
1060
|
_record_event_bg("shutdown", {"agent": AGENT_NAME, "session_id": _SESSION_ID})
|
|
1061
|
+
# Auto-save session summary to agent memory before shutdown
|
|
1062
|
+
try:
|
|
1063
|
+
import datetime as _dt
|
|
1064
|
+
api_key = _get_api_key()
|
|
1065
|
+
if api_key:
|
|
1066
|
+
be.sb_rpc("mc_memory_set", {
|
|
1067
|
+
"p_api_key": api_key,
|
|
1068
|
+
"p_project_id": _PROJECT_ID,
|
|
1069
|
+
"p_agent_name": AGENT_NAME,
|
|
1070
|
+
"p_key": f"session_retro_{_dt.date.today().isoformat()}",
|
|
1071
|
+
"p_value": {
|
|
1072
|
+
"session_id": _SESSION_ID,
|
|
1073
|
+
"agent": AGENT_NAME,
|
|
1074
|
+
"shutdown_at": _dt.datetime.utcnow().isoformat(),
|
|
1075
|
+
"instance_id": _INSTANCE_ID,
|
|
1076
|
+
"auto_generated": True,
|
|
1077
|
+
},
|
|
1078
|
+
})
|
|
1079
|
+
except Exception:
|
|
1080
|
+
pass # Never block shutdown
|
|
973
1081
|
log.info("lifespan shutdown — stopping heartbeat + realtime + releasing lease")
|
|
974
1082
|
_heartbeat_stop.set()
|
|
975
1083
|
hb_thread.join(timeout=5)
|
|
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
|