meshcode 2.11.88__tar.gz → 2.11.90__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.11.88 → meshcode-2.11.90}/PKG-INFO +1 -1
- {meshcode-2.11.88 → meshcode-2.11.90}/meshcode/__init__.py +1 -1
- {meshcode-2.11.88 → meshcode-2.11.90}/meshcode/hostd.py +47 -6
- {meshcode-2.11.88 → meshcode-2.11.90}/meshcode.egg-info/PKG-INFO +1 -1
- {meshcode-2.11.88 → meshcode-2.11.90}/pyproject.toml +1 -1
- {meshcode-2.11.88 → meshcode-2.11.90}/README.md +0 -0
- {meshcode-2.11.88 → meshcode-2.11.90}/meshcode/__main__.py +0 -0
- {meshcode-2.11.88 → meshcode-2.11.90}/meshcode/_session_handoff_template.py +0 -0
- {meshcode-2.11.88 → meshcode-2.11.90}/meshcode/_stop_hook_template.py +0 -0
- {meshcode-2.11.88 → meshcode-2.11.90}/meshcode/ascii_art.py +0 -0
- {meshcode-2.11.88 → meshcode-2.11.90}/meshcode/atomic_push.py +0 -0
- {meshcode-2.11.88 → meshcode-2.11.90}/meshcode/claude_update.py +0 -0
- {meshcode-2.11.88 → meshcode-2.11.90}/meshcode/cli.py +0 -0
- {meshcode-2.11.88 → meshcode-2.11.90}/meshcode/comms_v4.py +0 -0
- {meshcode-2.11.88 → meshcode-2.11.90}/meshcode/compat.py +0 -0
- {meshcode-2.11.88 → meshcode-2.11.90}/meshcode/daemon.py +0 -0
- {meshcode-2.11.88 → meshcode-2.11.90}/meshcode/date_parse.py +0 -0
- {meshcode-2.11.88 → meshcode-2.11.90}/meshcode/doctor.py +0 -0
- {meshcode-2.11.88 → meshcode-2.11.90}/meshcode/error_hints.py +0 -0
- {meshcode-2.11.88 → meshcode-2.11.90}/meshcode/exceptions.py +0 -0
- {meshcode-2.11.88 → meshcode-2.11.90}/meshcode/invites.py +0 -0
- {meshcode-2.11.88 → meshcode-2.11.90}/meshcode/launcher.py +0 -0
- {meshcode-2.11.88 → meshcode-2.11.90}/meshcode/launcher_install.py +0 -0
- {meshcode-2.11.88 → meshcode-2.11.90}/meshcode/meshcode_mcp/__init__.py +0 -0
- {meshcode-2.11.88 → meshcode-2.11.90}/meshcode/meshcode_mcp/__main__.py +0 -0
- {meshcode-2.11.88 → meshcode-2.11.90}/meshcode/meshcode_mcp/backend.py +0 -0
- {meshcode-2.11.88 → meshcode-2.11.90}/meshcode/meshcode_mcp/realtime.py +0 -0
- {meshcode-2.11.88 → meshcode-2.11.90}/meshcode/meshcode_mcp/server.py +0 -0
- {meshcode-2.11.88 → meshcode-2.11.90}/meshcode/meshcode_mcp/sleep_signals.py +0 -0
- {meshcode-2.11.88 → meshcode-2.11.90}/meshcode/meshcode_mcp/test_backend.py +0 -0
- {meshcode-2.11.88 → meshcode-2.11.90}/meshcode/meshcode_mcp/test_boot_timing.py +0 -0
- {meshcode-2.11.88 → meshcode-2.11.90}/meshcode/meshcode_mcp/test_install_guard.py +0 -0
- {meshcode-2.11.88 → meshcode-2.11.90}/meshcode/meshcode_mcp/test_prefs_claude_version.py +0 -0
- {meshcode-2.11.88 → meshcode-2.11.90}/meshcode/meshcode_mcp/test_realtime.py +0 -0
- {meshcode-2.11.88 → meshcode-2.11.90}/meshcode/meshcode_mcp/test_server_wrapper.py +0 -0
- {meshcode-2.11.88 → meshcode-2.11.90}/meshcode/preferences.py +0 -0
- {meshcode-2.11.88 → meshcode-2.11.90}/meshcode/protocol_handler.py +0 -0
- {meshcode-2.11.88 → meshcode-2.11.90}/meshcode/protocol_v2.py +0 -0
- {meshcode-2.11.88 → meshcode-2.11.90}/meshcode/quickstart.py +0 -0
- {meshcode-2.11.88 → meshcode-2.11.90}/meshcode/rpc_allowlist.py +0 -0
- {meshcode-2.11.88 → meshcode-2.11.90}/meshcode/run_agent.py +0 -0
- {meshcode-2.11.88 → meshcode-2.11.90}/meshcode/scripts/check_secrets.py +0 -0
- {meshcode-2.11.88 → meshcode-2.11.90}/meshcode/scripts/race_rate_harness.py +0 -0
- {meshcode-2.11.88 → meshcode-2.11.90}/meshcode/secrets.py +0 -0
- {meshcode-2.11.88 → meshcode-2.11.90}/meshcode/self_update.py +0 -0
- {meshcode-2.11.88 → meshcode-2.11.90}/meshcode/setup_clients.py +0 -0
- {meshcode-2.11.88 → meshcode-2.11.90}/meshcode/supervisor.py +0 -0
- {meshcode-2.11.88 → meshcode-2.11.90}/meshcode/up.py +0 -0
- {meshcode-2.11.88 → meshcode-2.11.90}/meshcode/upload.py +0 -0
- {meshcode-2.11.88 → meshcode-2.11.90}/meshcode.egg-info/SOURCES.txt +0 -0
- {meshcode-2.11.88 → meshcode-2.11.90}/meshcode.egg-info/dependency_links.txt +0 -0
- {meshcode-2.11.88 → meshcode-2.11.90}/meshcode.egg-info/entry_points.txt +0 -0
- {meshcode-2.11.88 → meshcode-2.11.90}/meshcode.egg-info/requires.txt +0 -0
- {meshcode-2.11.88 → meshcode-2.11.90}/meshcode.egg-info/top_level.txt +0 -0
- {meshcode-2.11.88 → meshcode-2.11.90}/setup.cfg +0 -0
- {meshcode-2.11.88 → meshcode-2.11.90}/tests/test_auto_update_hardening.py +0 -0
- {meshcode-2.11.88 → meshcode-2.11.90}/tests/test_autonomous_closegap_1.py +0 -0
- {meshcode-2.11.88 → meshcode-2.11.90}/tests/test_autonomous_closegap_2.py +0 -0
- {meshcode-2.11.88 → meshcode-2.11.90}/tests/test_autonomous_closegap_3.py +0 -0
- {meshcode-2.11.88 → meshcode-2.11.90}/tests/test_autonomous_prompt_inject.py +0 -0
- {meshcode-2.11.88 → meshcode-2.11.90}/tests/test_boot_bug_regression.py +0 -0
- {meshcode-2.11.88 → meshcode-2.11.90}/tests/test_color_truecolor.py +0 -0
- {meshcode-2.11.88 → meshcode-2.11.90}/tests/test_core.py +0 -0
- {meshcode-2.11.88 → meshcode-2.11.90}/tests/test_cross_agent_messaging.py +0 -0
- {meshcode-2.11.88 → meshcode-2.11.90}/tests/test_date_parse.py +0 -0
- {meshcode-2.11.88 → meshcode-2.11.90}/tests/test_doctor.py +0 -0
- {meshcode-2.11.88 → meshcode-2.11.90}/tests/test_epistemic_v1_python_sdk.py +0 -0
- {meshcode-2.11.88 → meshcode-2.11.90}/tests/test_epistemic_v1_stop_conditions.py +0 -0
- {meshcode-2.11.88 → meshcode-2.11.90}/tests/test_esc_deaf_state.py +0 -0
- {meshcode-2.11.88 → meshcode-2.11.90}/tests/test_exceptions.py +0 -0
- {meshcode-2.11.88 → meshcode-2.11.90}/tests/test_file_upload.py +0 -0
- {meshcode-2.11.88 → meshcode-2.11.90}/tests/test_init_device_code.py +0 -0
- {meshcode-2.11.88 → meshcode-2.11.90}/tests/test_install_guard.py +0 -0
- {meshcode-2.11.88 → meshcode-2.11.90}/tests/test_lease_sigterm_release.py +0 -0
- {meshcode-2.11.88 → meshcode-2.11.90}/tests/test_mark_read_batch.py +0 -0
- {meshcode-2.11.88 → meshcode-2.11.90}/tests/test_marketplace_ratings.py +0 -0
- {meshcode-2.11.88 → meshcode-2.11.90}/tests/test_migration_integrity.py +0 -0
- {meshcode-2.11.88 → meshcode-2.11.90}/tests/test_realtime_event_freshness.py +0 -0
- {meshcode-2.11.88 → meshcode-2.11.90}/tests/test_rls_cross_tenant.py +0 -0
- {meshcode-2.11.88 → meshcode-2.11.90}/tests/test_rpc_grants.py +0 -0
- {meshcode-2.11.88 → meshcode-2.11.90}/tests/test_rpc_migrations.py +0 -0
- {meshcode-2.11.88 → meshcode-2.11.90}/tests/test_run_agent_dry_run.py +0 -0
- {meshcode-2.11.88 → meshcode-2.11.90}/tests/test_run_agent_no_server_import.py +0 -0
- {meshcode-2.11.88 → meshcode-2.11.90}/tests/test_security_regressions.py +0 -0
- {meshcode-2.11.88 → meshcode-2.11.90}/tests/test_self_update_user_site.py +0 -0
- {meshcode-2.11.88 → meshcode-2.11.90}/tests/test_sentinel.py +0 -0
- {meshcode-2.11.88 → meshcode-2.11.90}/tests/test_setup_path.py +0 -0
- {meshcode-2.11.88 → meshcode-2.11.90}/tests/test_sleep_signals.py +0 -0
- {meshcode-2.11.88 → meshcode-2.11.90}/tests/test_status_enum_coverage.py +0 -0
- {meshcode-2.11.88 → meshcode-2.11.90}/tests/test_stay_on_loop_hook.py +0 -0
- {meshcode-2.11.88 → meshcode-2.11.90}/tests/test_wait_open_tasks_contradiction.py +0 -0
|
@@ -881,28 +881,58 @@ def _hostd_bootstrap_if_needed(ttl_sec: int = 3600, verbose: bool = False) -> bo
|
|
|
881
881
|
return ok
|
|
882
882
|
|
|
883
883
|
|
|
884
|
+
def _running_daemon_is_stale() -> bool:
|
|
885
|
+
"""ca947d7f: True ONLY if hostd_state.json records a running_version that is STRICTLY older
|
|
886
|
+
than the on-disk installed version. Absent / unknown / equal / newer -> False (FAIL-SAFE:
|
|
887
|
+
never bounce a healthy or ambiguous daemon on the login-critical path — commander's safety
|
|
888
|
+
condition). NOTE: a daemon predating the running_version stamp (<2.11.90) wrote no marker, so
|
|
889
|
+
this returns False for it — that one-time transition still needs a manual restart; this guards
|
|
890
|
+
FUTURE transitions as defense-in-depth (the daemon's own self-reexec is the primary path)."""
|
|
891
|
+
try:
|
|
892
|
+
rv = (_load_state() or {}).get("running_version")
|
|
893
|
+
if not rv:
|
|
894
|
+
return False
|
|
895
|
+
import importlib.metadata as _ilmd
|
|
896
|
+
ondisk = _ilmd.version("meshcode")
|
|
897
|
+
from meshcode import self_update as _su
|
|
898
|
+
return bool(_su._is_newer(ondisk, rv))
|
|
899
|
+
except Exception:
|
|
900
|
+
return False
|
|
901
|
+
|
|
902
|
+
|
|
884
903
|
def _hostd_bootstrap(verbose: bool = False) -> bool:
|
|
885
904
|
"""Idempotent auto-install + start of hostd (task f12b9d36) — called from `meshcode login`
|
|
886
905
|
so onboarding is just `pip install meshcode` + `meshcode login` (no manual `hostd install`).
|
|
887
|
-
If the OS job already exists, just ensure it's running (don't bounce a live daemon)
|
|
888
|
-
|
|
906
|
+
If the OS job already exists, just ensure it's running (don't bounce a live daemon) UNLESS the
|
|
907
|
+
running daemon is provably STALE (ca947d7f), in which case force-restart it so Stop's kill
|
|
908
|
+
sweep + launch fixes land. Best-effort: NEVER raises — login must not fail on a hiccup."""
|
|
889
909
|
import platform
|
|
890
910
|
try:
|
|
911
|
+
force = _running_daemon_is_stale() # bounce ONLY a provably-stale daemon
|
|
912
|
+
if force:
|
|
913
|
+
_log(f"hostd bootstrap: running daemon is STALE vs on-disk -> force-restart")
|
|
891
914
|
sysname = platform.system()
|
|
892
915
|
if sysname == "Darwin":
|
|
893
916
|
if not _hostd_plist_path().exists():
|
|
894
917
|
_hostd_install() # writes plist + launchctl load
|
|
895
918
|
try:
|
|
896
919
|
uid = str(os.getuid())
|
|
897
|
-
|
|
898
|
-
|
|
920
|
+
# `kickstart -k` restarts a running job; plain `kickstart` only starts if down.
|
|
921
|
+
args = ["launchctl", "kickstart", f"gui/{uid}/{_HOSTD_PLIST_LABEL}"]
|
|
922
|
+
if force:
|
|
923
|
+
args.insert(2, "-k")
|
|
924
|
+
subprocess.run(args, capture_output=True, text=True)
|
|
899
925
|
except Exception:
|
|
900
926
|
pass
|
|
901
927
|
elif sysname == "Windows":
|
|
902
928
|
q = subprocess.run(["schtasks", "/Query", "/TN", _HOSTD_TASK_NAME],
|
|
903
929
|
capture_output=True, text=True)
|
|
904
930
|
if q.returncode == 0:
|
|
905
|
-
|
|
931
|
+
if force:
|
|
932
|
+
# stale -> stop the running instance, then start fresh on the new wheel.
|
|
933
|
+
subprocess.run(["schtasks", "/End", "/TN", _HOSTD_TASK_NAME],
|
|
934
|
+
capture_output=True, text=True)
|
|
935
|
+
# task exists -> ensure running (IgnoreNew => harmless if already up; no double-spawn)
|
|
906
936
|
subprocess.run(["schtasks", "/Run", "/TN", _HOSTD_TASK_NAME],
|
|
907
937
|
capture_output=True, text=True)
|
|
908
938
|
else:
|
|
@@ -910,6 +940,10 @@ def _hostd_bootstrap(verbose: bool = False) -> bool:
|
|
|
910
940
|
_hostd_install_windows()
|
|
911
941
|
else: # Linux + others
|
|
912
942
|
if shutil.which("systemctl"):
|
|
943
|
+
if force:
|
|
944
|
+
subprocess.run(["systemctl", "--user", "restart", _HOSTD_SYSTEMD_UNIT],
|
|
945
|
+
capture_output=True, text=True)
|
|
946
|
+
return True
|
|
913
947
|
act = subprocess.run(["systemctl", "--user", "is-active", _HOSTD_SYSTEMD_UNIT],
|
|
914
948
|
capture_output=True, text=True)
|
|
915
949
|
if act.stdout.strip() == "active":
|
|
@@ -1024,7 +1058,14 @@ def cmd_hostd(args: list) -> int:
|
|
|
1024
1058
|
_log(f"registered host {host_id} in mc_host_config")
|
|
1025
1059
|
else:
|
|
1026
1060
|
_log(f"WARN: host registration failed (dashboard may not list this host): {_reg}")
|
|
1027
|
-
_log(f"hostd starting — host_id={host_id} interval={POLL_INTERVAL_SEC}s stale={STALE_SECONDS}s")
|
|
1061
|
+
_log(f"hostd starting — host_id={host_id} interval={POLL_INTERVAL_SEC}s stale={STALE_SECONDS}s v{_RUNNING_VERSION}")
|
|
1062
|
+
# ca947d7f: stamp the version THIS daemon is running into hostd_state.json so
|
|
1063
|
+
# `meshcode login` (_hostd_bootstrap) can detect a STALE running daemon and force-
|
|
1064
|
+
# restart it (the one-time transition onto a self-reexec-capable build). Best-effort.
|
|
1065
|
+
try:
|
|
1066
|
+
_st = _load_state(); _st["running_version"] = _RUNNING_VERSION; _save_state(_st)
|
|
1067
|
+
except Exception:
|
|
1068
|
+
pass
|
|
1028
1069
|
# uptime-since-spawn (core's suggestion): if the daemon dies <2min, the last alive log +
|
|
1029
1070
|
# the uptime stamped on the FATAL line reveal the <2min pattern for RC.
|
|
1030
1071
|
_spawn_mono = time.monotonic()
|
|
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
|
|
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
|
|
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
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|