meshcode 2.11.157__tar.gz → 2.11.159__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.157 → meshcode-2.11.159}/PKG-INFO +1 -1
- {meshcode-2.11.157 → meshcode-2.11.159}/meshcode/__init__.py +1 -1
- {meshcode-2.11.157 → meshcode-2.11.159}/meshcode/__main__.py +1 -1
- {meshcode-2.11.157 → meshcode-2.11.159}/meshcode/_session_handoff_template.py +16 -70
- {meshcode-2.11.157 → meshcode-2.11.159}/meshcode/comms_v4.py +17 -21
- {meshcode-2.11.157 → meshcode-2.11.159}/meshcode/hostd.py +195 -440
- {meshcode-2.11.157 → meshcode-2.11.159}/meshcode/meshcode_mcp/backend.py +2 -2
- {meshcode-2.11.157 → meshcode-2.11.159}/meshcode/meshcode_mcp/realtime.py +0 -11
- {meshcode-2.11.157 → meshcode-2.11.159}/meshcode/meshcode_mcp/server.py +45 -316
- {meshcode-2.11.157 → meshcode-2.11.159}/meshcode/meshcode_mcp/sleep_signals.py +1 -45
- {meshcode-2.11.157 → meshcode-2.11.159}/meshcode/protocol_handler.py +31 -45
- {meshcode-2.11.157 → meshcode-2.11.159}/meshcode/run_agent.py +11 -29
- {meshcode-2.11.157 → meshcode-2.11.159}/meshcode/self_update.py +3 -3
- {meshcode-2.11.157 → meshcode-2.11.159}/meshcode/setup_clients.py +4 -69
- {meshcode-2.11.157 → meshcode-2.11.159}/meshcode/up.py +4 -31
- {meshcode-2.11.157 → meshcode-2.11.159}/meshcode.egg-info/PKG-INFO +1 -1
- {meshcode-2.11.157 → meshcode-2.11.159}/meshcode.egg-info/SOURCES.txt +1 -5
- {meshcode-2.11.157 → meshcode-2.11.159}/pyproject.toml +1 -1
- {meshcode-2.11.157 → meshcode-2.11.159}/tests/test_fleet_reaper.py +1 -1
- {meshcode-2.11.157 → meshcode-2.11.159}/tests/test_hostd_zombie_sessions.py +2 -2
- meshcode-2.11.159/tests/test_no_appleevents_on_sweep.py +81 -0
- meshcode-2.11.157/meshcode/helper_visuals.py +0 -142
- meshcode-2.11.157/meshcode/meshcode_mcp/swarm.py +0 -472
- meshcode-2.11.157/meshcode/meshcode_mcp/test_swarm.py +0 -469
- meshcode-2.11.157/tests/test_helper_visuals.py +0 -214
- meshcode-2.11.157/tests/test_swarm_events.py +0 -115
- {meshcode-2.11.157 → meshcode-2.11.159}/README.md +0 -0
- {meshcode-2.11.157 → meshcode-2.11.159}/meshcode/_launch_smoke.py +0 -0
- {meshcode-2.11.157 → meshcode-2.11.159}/meshcode/_stop_hook_template.py +0 -0
- {meshcode-2.11.157 → meshcode-2.11.159}/meshcode/_update_guard.py +0 -0
- {meshcode-2.11.157 → meshcode-2.11.159}/meshcode/ascii_art.py +0 -0
- {meshcode-2.11.157 → meshcode-2.11.159}/meshcode/atomic_push.py +0 -0
- {meshcode-2.11.157 → meshcode-2.11.159}/meshcode/claude_update.py +0 -0
- {meshcode-2.11.157 → meshcode-2.11.159}/meshcode/cli.py +0 -0
- {meshcode-2.11.157 → meshcode-2.11.159}/meshcode/compat.py +0 -0
- {meshcode-2.11.157 → meshcode-2.11.159}/meshcode/daemon.py +0 -0
- {meshcode-2.11.157 → meshcode-2.11.159}/meshcode/date_parse.py +0 -0
- {meshcode-2.11.157 → meshcode-2.11.159}/meshcode/doctor.py +0 -0
- {meshcode-2.11.157 → meshcode-2.11.159}/meshcode/error_hints.py +0 -0
- {meshcode-2.11.157 → meshcode-2.11.159}/meshcode/exceptions.py +0 -0
- {meshcode-2.11.157 → meshcode-2.11.159}/meshcode/hooks/__init__.py +0 -0
- {meshcode-2.11.157 → meshcode-2.11.159}/meshcode/hooks/push_guard.py +0 -0
- {meshcode-2.11.157 → meshcode-2.11.159}/meshcode/hooks/repo_path_lock.py +0 -0
- {meshcode-2.11.157 → meshcode-2.11.159}/meshcode/invites.py +0 -0
- {meshcode-2.11.157 → meshcode-2.11.159}/meshcode/launcher.py +0 -0
- {meshcode-2.11.157 → meshcode-2.11.159}/meshcode/launcher_install.py +0 -0
- {meshcode-2.11.157 → meshcode-2.11.159}/meshcode/meshcode_mcp/__init__.py +0 -0
- {meshcode-2.11.157 → meshcode-2.11.159}/meshcode/meshcode_mcp/__main__.py +0 -0
- {meshcode-2.11.157 → meshcode-2.11.159}/meshcode/meshcode_mcp/test_backend.py +0 -0
- {meshcode-2.11.157 → meshcode-2.11.159}/meshcode/meshcode_mcp/test_boot_timing.py +0 -0
- {meshcode-2.11.157 → meshcode-2.11.159}/meshcode/meshcode_mcp/test_install_guard.py +0 -0
- {meshcode-2.11.157 → meshcode-2.11.159}/meshcode/meshcode_mcp/test_prefs_claude_version.py +0 -0
- {meshcode-2.11.157 → meshcode-2.11.159}/meshcode/meshcode_mcp/test_realtime.py +0 -0
- {meshcode-2.11.157 → meshcode-2.11.159}/meshcode/meshcode_mcp/test_server_wrapper.py +0 -0
- {meshcode-2.11.157 → meshcode-2.11.159}/meshcode/preferences.py +0 -0
- {meshcode-2.11.157 → meshcode-2.11.159}/meshcode/protocol_v2.py +0 -0
- {meshcode-2.11.157 → meshcode-2.11.159}/meshcode/quickstart.py +0 -0
- {meshcode-2.11.157 → meshcode-2.11.159}/meshcode/rpc_allowlist.py +0 -0
- {meshcode-2.11.157 → meshcode-2.11.159}/meshcode/scripts/check_secrets.py +0 -0
- {meshcode-2.11.157 → meshcode-2.11.159}/meshcode/scripts/race_rate_harness.py +0 -0
- {meshcode-2.11.157 → meshcode-2.11.159}/meshcode/secrets.py +0 -0
- {meshcode-2.11.157 → meshcode-2.11.159}/meshcode/supervisor.py +0 -0
- {meshcode-2.11.157 → meshcode-2.11.159}/meshcode/upload.py +0 -0
- {meshcode-2.11.157 → meshcode-2.11.159}/meshcode.egg-info/dependency_links.txt +0 -0
- {meshcode-2.11.157 → meshcode-2.11.159}/meshcode.egg-info/entry_points.txt +0 -0
- {meshcode-2.11.157 → meshcode-2.11.159}/meshcode.egg-info/requires.txt +0 -0
- {meshcode-2.11.157 → meshcode-2.11.159}/meshcode.egg-info/top_level.txt +0 -0
- {meshcode-2.11.157 → meshcode-2.11.159}/setup.cfg +0 -0
- {meshcode-2.11.157 → meshcode-2.11.159}/tests/test_auto_update_hardening.py +0 -0
- {meshcode-2.11.157 → meshcode-2.11.159}/tests/test_autonomous_closegap_1.py +0 -0
- {meshcode-2.11.157 → meshcode-2.11.159}/tests/test_autonomous_closegap_2.py +0 -0
- {meshcode-2.11.157 → meshcode-2.11.159}/tests/test_autonomous_closegap_3.py +0 -0
- {meshcode-2.11.157 → meshcode-2.11.159}/tests/test_autonomous_prompt_inject.py +0 -0
- {meshcode-2.11.157 → meshcode-2.11.159}/tests/test_boot_bug_regression.py +0 -0
- {meshcode-2.11.157 → meshcode-2.11.159}/tests/test_color_truecolor.py +0 -0
- {meshcode-2.11.157 → meshcode-2.11.159}/tests/test_core.py +0 -0
- {meshcode-2.11.157 → meshcode-2.11.159}/tests/test_cross_agent_messaging.py +0 -0
- {meshcode-2.11.157 → meshcode-2.11.159}/tests/test_date_parse.py +0 -0
- {meshcode-2.11.157 → meshcode-2.11.159}/tests/test_doctor.py +0 -0
- {meshcode-2.11.157 → meshcode-2.11.159}/tests/test_ensure_boot_env_urgent_wake.py +0 -0
- {meshcode-2.11.157 → meshcode-2.11.159}/tests/test_epistemic_v1_python_sdk.py +0 -0
- {meshcode-2.11.157 → meshcode-2.11.159}/tests/test_epistemic_v1_stop_conditions.py +0 -0
- {meshcode-2.11.157 → meshcode-2.11.159}/tests/test_esc_deaf_state.py +0 -0
- {meshcode-2.11.157 → meshcode-2.11.159}/tests/test_exceptions.py +0 -0
- {meshcode-2.11.157 → meshcode-2.11.159}/tests/test_file_upload.py +0 -0
- {meshcode-2.11.157 → meshcode-2.11.159}/tests/test_hostd_launch_pinned_env.py +0 -0
- {meshcode-2.11.157 → meshcode-2.11.159}/tests/test_hostd_serve_discovery_split.py +0 -0
- {meshcode-2.11.157 → meshcode-2.11.159}/tests/test_init_device_code.py +0 -0
- {meshcode-2.11.157 → meshcode-2.11.159}/tests/test_install_guard.py +0 -0
- {meshcode-2.11.157 → meshcode-2.11.159}/tests/test_launch_smoke.py +0 -0
- {meshcode-2.11.157 → meshcode-2.11.159}/tests/test_lease_sigterm_release.py +0 -0
- {meshcode-2.11.157 → meshcode-2.11.159}/tests/test_live_mesh_guard.py +0 -0
- {meshcode-2.11.157 → meshcode-2.11.159}/tests/test_mark_read_batch.py +0 -0
- {meshcode-2.11.157 → meshcode-2.11.159}/tests/test_marketplace_ratings.py +0 -0
- {meshcode-2.11.157 → meshcode-2.11.159}/tests/test_migration_integrity.py +0 -0
- {meshcode-2.11.157 → meshcode-2.11.159}/tests/test_preflight_hb_gate.py +0 -0
- {meshcode-2.11.157 → meshcode-2.11.159}/tests/test_pretrust_claude.py +0 -0
- {meshcode-2.11.157 → meshcode-2.11.159}/tests/test_push_guard.py +0 -0
- {meshcode-2.11.157 → meshcode-2.11.159}/tests/test_realtime_event_freshness.py +0 -0
- {meshcode-2.11.157 → meshcode-2.11.159}/tests/test_replica_base_workspace_fallback.py +0 -0
- {meshcode-2.11.157 → meshcode-2.11.159}/tests/test_replica_boot_protocol_unconditional.py +0 -0
- {meshcode-2.11.157 → meshcode-2.11.159}/tests/test_rls_cross_tenant.py +0 -0
- {meshcode-2.11.157 → meshcode-2.11.159}/tests/test_rm_guard.py +0 -0
- {meshcode-2.11.157 → meshcode-2.11.159}/tests/test_rpc_grants.py +0 -0
- {meshcode-2.11.157 → meshcode-2.11.159}/tests/test_rpc_migrations.py +0 -0
- {meshcode-2.11.157 → meshcode-2.11.159}/tests/test_run_agent_dry_run.py +0 -0
- {meshcode-2.11.157 → meshcode-2.11.159}/tests/test_run_agent_no_server_import.py +0 -0
- {meshcode-2.11.157 → meshcode-2.11.159}/tests/test_security_regressions.py +0 -0
- {meshcode-2.11.157 → meshcode-2.11.159}/tests/test_self_update_user_site.py +0 -0
- {meshcode-2.11.157 → meshcode-2.11.159}/tests/test_sentinel.py +0 -0
- {meshcode-2.11.157 → meshcode-2.11.159}/tests/test_session_replay_gate.py +0 -0
- {meshcode-2.11.157 → meshcode-2.11.159}/tests/test_setup_path.py +0 -0
- {meshcode-2.11.157 → meshcode-2.11.159}/tests/test_sleep_signals.py +0 -0
- {meshcode-2.11.157 → meshcode-2.11.159}/tests/test_status_enum_coverage.py +0 -0
- {meshcode-2.11.157 → meshcode-2.11.159}/tests/test_stay_on_loop_hook.py +0 -0
- {meshcode-2.11.157 → meshcode-2.11.159}/tests/test_stop_ghost_terminal.py +0 -0
- {meshcode-2.11.157 → meshcode-2.11.159}/tests/test_task_progress.py +0 -0
- {meshcode-2.11.157 → meshcode-2.11.159}/tests/test_terminal_lifecycle.py +0 -0
- {meshcode-2.11.157 → meshcode-2.11.159}/tests/test_up_launch_cmd.py +0 -0
- {meshcode-2.11.157 → meshcode-2.11.159}/tests/test_update_guard.py +0 -0
- {meshcode-2.11.157 → meshcode-2.11.159}/tests/test_urgent_wake_tmux.py +0 -0
- {meshcode-2.11.157 → meshcode-2.11.159}/tests/test_wait_open_tasks_contradiction.py +0 -0
|
@@ -13,7 +13,7 @@ def main():
|
|
|
13
13
|
# (comms_v4), not just setup-path. hostd spawns agents via `python -m meshcode run <target>`
|
|
14
14
|
# (so a bg pip can replace the .exe) — that MUST route to the `run` dispatch, NOT fall through
|
|
15
15
|
# to the PATH-help error. Previously only setup-path dispatched, so every `python -m meshcode
|
|
16
|
-
# run` died with the misleading "meshcode not on PATH" message (qa/
|
|
16
|
+
# run` died with the misleading "meshcode not on PATH" message (qa/respawn boots).
|
|
17
17
|
if len(sys.argv) > 1:
|
|
18
18
|
# runpy imports + executes comms_v4 as __main__; do NOT pre-import it here (a prior
|
|
19
19
|
# `import meshcode.comms_v4` triggers a runpy "found in sys.modules" double-exec warning).
|
|
@@ -1,12 +1,12 @@
|
|
|
1
1
|
"""Session-handoff hook templates — single source of truth for the
|
|
2
2
|
PreCompact (write) + SessionStart (read) hooks.
|
|
3
3
|
|
|
4
|
-
|
|
5
|
-
|
|
6
|
-
|
|
7
|
-
|
|
8
|
-
|
|
9
|
-
|
|
4
|
+
SESSION HANDOFF (task bcd157a9, backend2): when a session ends or compacts at
|
|
5
|
+
high context — either by Claude Code's in-place autocompact or by a manual
|
|
6
|
+
relaunch — the IN-FLIGHT working context (which task I was mid-executing, what
|
|
7
|
+
I just edited/decided this session) is lost. meshcode_boot restores mesh state
|
|
8
|
+
(tasks, inbox, memory) authoritatively, but NOT the conversational thread.
|
|
9
|
+
These two hooks bridge that gap:
|
|
10
10
|
|
|
11
11
|
* PreCompact -> session_handoff_write.py: dump a compact snapshot of the
|
|
12
12
|
recent transcript tail to .claude/handoff.json BEFORE the context is
|
|
@@ -18,11 +18,8 @@ conversational thread. These two hooks bridge that gap:
|
|
|
18
18
|
|
|
19
19
|
Stored as string constants (same pattern as _stop_hook_template.py) so
|
|
20
20
|
`meshcode patch-hooks` can backfill existing workspaces without a full
|
|
21
|
-
re-scaffold.
|
|
22
|
-
|
|
23
|
-
and is intentionally NOT in these scripts — handoff preservation is decoupled
|
|
24
|
-
from whatever causes the restart, so it works for autocompact, clean recycle,
|
|
25
|
-
crash-respawn, or a manual relaunch alike.
|
|
21
|
+
re-scaffold. Handoff preservation is decoupled from whatever causes the
|
|
22
|
+
restart, so it works for autocompact, crash-respawn, or a manual relaunch alike.
|
|
26
23
|
"""
|
|
27
24
|
|
|
28
25
|
# Shared constants kept in sync between the two bodies.
|
|
@@ -33,9 +30,9 @@ _HANDOFF_MAX_AGE_S = 24 * 3600 # ignore stale handoffs on read
|
|
|
33
30
|
|
|
34
31
|
HANDOFF_WRITE_BODY = '''#!/usr/bin/env python3
|
|
35
32
|
"""PreCompact hook: snapshot the recent transcript tail to .claude/handoff.json
|
|
36
|
-
so a fresh post-
|
|
33
|
+
so a fresh post-restart session can resume the in-flight thread.
|
|
37
34
|
|
|
38
|
-
|
|
35
|
+
SESSION HANDOFF (task bcd157a9). Pure local file I/O — never touches the
|
|
39
36
|
network, never imports meshcode, never blocks. Any failure is swallowed and the
|
|
40
37
|
hook exits 0 so it can NEVER stall or break a Claude Code compaction/exit.
|
|
41
38
|
|
|
@@ -113,61 +110,13 @@ def _extract_tail(transcript_path: str):
|
|
|
113
110
|
return rows[-MAX_TURNS:]
|
|
114
111
|
|
|
115
112
|
|
|
116
|
-
def _request_recycle_if_marked(project_dir) -> None:
|
|
117
|
-
"""CTX-CLOSE-RELAUNCH (task 400fc536): commander-tier sessions ask the
|
|
118
|
-
server to recycle (close+relaunch fresh) at the next task-edge, right after
|
|
119
|
-
the handoff is snapshotted. Gated by the scaffold-baked
|
|
120
|
-
.claude/meshcode_hook_ctx.json recycle_on_compact flag (commander-only v1).
|
|
121
|
-
|
|
122
|
-
Best-effort in every dimension: missing marker/flag, missing creds, import
|
|
123
|
-
failure, network error -> silently skip. handoff.json is already written, so
|
|
124
|
-
a context-recycle still relaunches WITH context; and the actual exit is the
|
|
125
|
-
server's call (mc_consume_recycle at a task boundary), never this hook.
|
|
126
|
-
"""
|
|
127
|
-
try:
|
|
128
|
-
ctx_path = project_dir / ".claude" / "meshcode_hook_ctx.json"
|
|
129
|
-
if not ctx_path.exists():
|
|
130
|
-
return
|
|
131
|
-
if not json.loads(ctx_path.read_text(encoding="utf-8")).get("recycle_on_compact"):
|
|
132
|
-
return # non-commander -> in-place autocompact, no recycle
|
|
133
|
-
mcp = json.loads((project_dir / ".mcp.json").read_text(encoding="utf-8"))
|
|
134
|
-
env = (next(iter((mcp.get("mcpServers") or {}).values()), {}) or {}).get("env", {}) or {}
|
|
135
|
-
url = env.get("SUPABASE_URL"); key = env.get("SUPABASE_KEY")
|
|
136
|
-
pid = env.get("MESHCODE_PROJECT_ID"); agent = env.get("MESHCODE_AGENT")
|
|
137
|
-
if not (url and key and pid and agent):
|
|
138
|
-
return
|
|
139
|
-
api_key = os.environ.get("MESHCODE_API_KEY")
|
|
140
|
-
if not api_key:
|
|
141
|
-
try:
|
|
142
|
-
import importlib
|
|
143
|
-
api_key = importlib.import_module("meshcode.secrets").get_api_key(
|
|
144
|
-
profile=env.get("MESHCODE_KEYCHAIN_PROFILE") or "default")
|
|
145
|
-
except Exception:
|
|
146
|
-
api_key = None
|
|
147
|
-
if not api_key:
|
|
148
|
-
return
|
|
149
|
-
import urllib.request as _u
|
|
150
|
-
body = json.dumps({
|
|
151
|
-
"p_api_key": api_key, "p_project_id": pid,
|
|
152
|
-
"p_agent_name": agent, "p_allow_busy": True, # flag-now; exit deferred to wait-loop
|
|
153
|
-
}).encode("utf-8")
|
|
154
|
-
req = _u.Request(
|
|
155
|
-
url.rstrip("/") + "/rest/v1/rpc/mc_request_recycle",
|
|
156
|
-
data=body, method="POST",
|
|
157
|
-
headers={"apikey": key, "Authorization": "Bearer " + key,
|
|
158
|
-
"Content-Type": "application/json"})
|
|
159
|
-
_u.urlopen(req, timeout=5).read() # best-effort; ignore result per backend contract
|
|
160
|
-
except Exception as e: # noqa: BLE001 — never block compaction
|
|
161
|
-
sys.stderr.write(f"[session_handoff_write] recycle-request skipped: {e}\\n")
|
|
162
|
-
|
|
163
|
-
|
|
164
113
|
def _persist_handoff_to_memory(project_dir, handoff) -> None:
|
|
165
114
|
"""L6 M6.1 (task 84c426d4, 2.11.114): mirror the handoff into
|
|
166
115
|
mc_agent_memory key='session_handoff' so the server-side boot
|
|
167
116
|
continuity_capsule (mig 456) can surface it on the NEXT session even
|
|
168
117
|
when the local handoff.json is gone (new host, wiped workspace).
|
|
169
|
-
|
|
170
|
-
|
|
118
|
+
Best-effort creds pattern — any failure silently skips; handoff.json
|
|
119
|
+
already covers the local path.
|
|
171
120
|
"""
|
|
172
121
|
try:
|
|
173
122
|
mcp = json.loads((project_dir / ".mcp.json").read_text(encoding="utf-8"))
|
|
@@ -305,9 +254,6 @@ def main() -> int:
|
|
|
305
254
|
_persist_handoff_to_memory(_project_dir(), handoff)
|
|
306
255
|
# py-half 4aee4739: dedicated handoff capsule -> mc_boot continuity_capsule.last_handoff.
|
|
307
256
|
_send_session_handoff_capsule(_project_dir(), handoff)
|
|
308
|
-
# CTX-CLOSE-RELAUNCH (task 400fc536): now that the thread is snapshotted,
|
|
309
|
-
# commander-tier sessions ask the server to recycle at the next task-edge.
|
|
310
|
-
_request_recycle_if_marked(_project_dir())
|
|
311
257
|
return 0
|
|
312
258
|
|
|
313
259
|
|
|
@@ -321,10 +267,10 @@ if __name__ == "__main__":
|
|
|
321
267
|
|
|
322
268
|
HANDOFF_READ_BODY = '''#!/usr/bin/env python3
|
|
323
269
|
"""SessionStart hook: if a handoff snapshot exists, inject it as
|
|
324
|
-
additionalContext so a freshly-
|
|
270
|
+
additionalContext so a freshly-relaunched session resumes the in-flight thread,
|
|
325
271
|
then archive it so it is injected exactly once.
|
|
326
272
|
|
|
327
|
-
|
|
273
|
+
SESSION HANDOFF (task bcd157a9). Pure local file I/O — no network, no
|
|
328
274
|
meshcode import, never blocks. meshcode_boot remains authoritative for mesh
|
|
329
275
|
state; this only restores the conversational thread.
|
|
330
276
|
|
|
@@ -360,9 +306,9 @@ def _render(handoff: dict) -> str:
|
|
|
360
306
|
if not turns:
|
|
361
307
|
return ""
|
|
362
308
|
lines = [
|
|
363
|
-
"## Recovered session handoff
|
|
309
|
+
"## Recovered session handoff",
|
|
364
310
|
"",
|
|
365
|
-
"Your previous session
|
|
311
|
+
"Your previous session ended or compacted at high context. meshcode_boot has "
|
|
366
312
|
"the authoritative mesh state (tasks/inbox/memory); the thread tail "
|
|
367
313
|
"below is the in-flight context that boot does not restore. Use it to "
|
|
368
314
|
"resume what you were mid-doing, then run the normal boot loop.",
|
|
@@ -2509,7 +2509,7 @@ AGENT CONTROL:
|
|
|
2509
2509
|
disconnect <proj> <name> Graceful disconnect
|
|
2510
2510
|
whoami Show logged-in identity
|
|
2511
2511
|
|
|
2512
|
-
|
|
2512
|
+
REPLICAS (agent clones):
|
|
2513
2513
|
replicate <agent> --count N [--no-launch] Clone agent into <agent>-1..N (launches by default)
|
|
2514
2514
|
replica-power <group_id> running|stopped Stop/Start a whole replica group [--restart]
|
|
2515
2515
|
profile [agent] Show/set agent profile
|
|
@@ -2540,16 +2540,14 @@ Run `meshcode <command> --help` for help on a specific command.
|
|
|
2540
2540
|
|
|
2541
2541
|
# Per-subcommand help texts
|
|
2542
2542
|
SUBCOMMAND_HELP = {
|
|
2543
|
-
"up": """meshcode up <project> [--agents a,b] [--
|
|
2543
|
+
"up": """meshcode up <project> [--agents a,b] [--visible]
|
|
2544
2544
|
|
|
2545
2545
|
Launch-All: opens a visible terminal for each agent in the project and
|
|
2546
2546
|
registers them as hostd-managed (so the watchdog daemon auto-relaunches
|
|
2547
|
-
|
|
2547
|
+
them if they crash). The fast way to bring a whole team online at once.
|
|
2548
2548
|
|
|
2549
2549
|
meshcode up myproject launch every agent in the roster
|
|
2550
2550
|
meshcode up myproject --agents a,b launch only a and b
|
|
2551
|
-
meshcode up myproject --recycle 80 set context-% recycle policy
|
|
2552
|
-
meshcode up myproject --recycle 12h set uptime recycle policy
|
|
2553
2551
|
|
|
2554
2552
|
Roster comes from the cloud (exact names). Pair with `meshcode hostd
|
|
2555
2553
|
install` so the launched team stays alive across crashes.
|
|
@@ -2557,18 +2555,16 @@ install` so the launched team stays alive across crashes.
|
|
|
2557
2555
|
"hostd": """meshcode hostd run|status|install|uninstall
|
|
2558
2556
|
|
|
2559
2557
|
Host-side watchdog daemon: auto-relaunches dead/stale managed agents
|
|
2560
|
-
(respawn)
|
|
2561
|
-
|
|
2562
|
-
only); hostd polls the cloud for heartbeat staleness + recycle triggers.
|
|
2558
|
+
(respawn). Complements supervisor.py (launchd KeepAlive = process-exit
|
|
2559
|
+
only); hostd polls the cloud for heartbeat staleness.
|
|
2563
2560
|
|
|
2564
2561
|
meshcode hostd run run the poll loop in the foreground
|
|
2565
2562
|
meshcode hostd status show agents this host would respawn (JSON)
|
|
2566
2563
|
meshcode hostd install install the launchd agent (auto-start, KeepAlive)
|
|
2567
2564
|
meshcode hostd uninstall remove the launchd agent
|
|
2568
2565
|
|
|
2569
|
-
Agents are managed via mc_host_set_agents (desired_state=running)
|
|
2570
|
-
|
|
2571
|
-
button (meshcode://) kickstarts it.
|
|
2566
|
+
Agents are managed via mc_host_set_agents (desired_state=running).
|
|
2567
|
+
NOT autostart-login; the Launch button (meshcode://) kickstarts it.
|
|
2572
2568
|
""",
|
|
2573
2569
|
"init": """meshcode init
|
|
2574
2570
|
|
|
@@ -3404,9 +3400,9 @@ if __name__ == "__main__":
|
|
|
3404
3400
|
# rows get desired_state='running' so hostd auto-spawns them as persistent
|
|
3405
3401
|
# terminals within ~one sweep; --no-launch creates them dormant (Start later
|
|
3406
3402
|
# from the dashboard or `meshcode replica-power <group> running`). The shared
|
|
3407
|
-
# replica_group_id (
|
|
3408
|
-
# while per-replica desired_state still allows killing one
|
|
3409
|
-
# Backend for task 069b5550.
|
|
3403
|
+
# replica_group_id (stored in the swarm_id column) lets the whole group be
|
|
3404
|
+
# powered as a unit while per-replica desired_state still allows killing one
|
|
3405
|
+
# without the group. Backend for task 069b5550.
|
|
3410
3406
|
_ak = _load_api_key_for_cli()
|
|
3411
3407
|
base = pos[0] if len(pos) > 0 else flags.get("agent", "")
|
|
3412
3408
|
proj = flags.get("project")
|
|
@@ -3424,9 +3420,9 @@ if __name__ == "__main__":
|
|
|
3424
3420
|
print("[meshcode] ERROR: --count must be an integer in 1..16")
|
|
3425
3421
|
sys.exit(1)
|
|
3426
3422
|
desired = None if flags.get("no-launch") else "running"
|
|
3427
|
-
# p_mode (task 986947b5): copilotos = shared
|
|
3428
|
-
# independientes = distinct
|
|
3429
|
-
# (Samuel's canonical spec). DB mig586 honors it on both overloads.
|
|
3423
|
+
# p_mode (task 986947b5): copilotos = one shared replica group (coordinate
|
|
3424
|
+
# together) | independientes = a distinct group per replica (isolated).
|
|
3425
|
+
# Default copilotos (Samuel's canonical spec). DB mig586 honors it on both overloads.
|
|
3430
3426
|
mode = str(flags.get("mode", "copilotos")).lower()
|
|
3431
3427
|
if mode not in ("copilotos", "independientes"):
|
|
3432
3428
|
print("[meshcode] ERROR: --mode must be 'copilotos' (shared/coordinate) or "
|
|
@@ -3475,9 +3471,9 @@ if __name__ == "__main__":
|
|
|
3475
3471
|
# meshcode replica-power <group_id> running|stopped [--restart]
|
|
3476
3472
|
#
|
|
3477
3473
|
# Sets desired_state for EVERY agent sharing replica_group_id (Stop/Start the
|
|
3478
|
-
# whole
|
|
3474
|
+
# whole replica group as a unit). CLI/agent path = mc_replica_group_power_as_agent
|
|
3479
3475
|
# (DB mig 20260616_573); the FE buttons call mc_replica_group_power (auth.uid,
|
|
3480
|
-
# no api_key in the browser). --restart
|
|
3476
|
+
# no api_key in the browser). --restart relaunches the group's terminals on power-on.
|
|
3481
3477
|
# Backend for task 069b5550 (FE Stop/Start/Launch route through here).
|
|
3482
3478
|
_ak = _load_api_key_for_cli()
|
|
3483
3479
|
group = pos[0] if len(pos) > 0 else flags.get("group", "")
|
|
@@ -4097,14 +4093,14 @@ if __name__ == "__main__":
|
|
|
4097
4093
|
print(f"Usage: meshcode supervisor [start|stop|status|--simple] <project> <agent>")
|
|
4098
4094
|
|
|
4099
4095
|
elif cmd == "hostd":
|
|
4100
|
-
# meshcode hostd run|status — local respawn
|
|
4096
|
+
# meshcode hostd run|status — local respawn watchdog daemon
|
|
4101
4097
|
# (auto-relaunch of stale/dead managed agents; mesh-core incident fix).
|
|
4102
4098
|
import importlib
|
|
4103
4099
|
_hostd = importlib.import_module("meshcode.hostd")
|
|
4104
4100
|
sys.exit(_hostd.cmd_hostd(pos))
|
|
4105
4101
|
|
|
4106
4102
|
elif cmd == "up":
|
|
4107
|
-
# meshcode up <project> [--agents a,b]
|
|
4103
|
+
# meshcode up <project> [--agents a,b] — Launch-All:
|
|
4108
4104
|
# opens a visible terminal per agent + registers them as hostd-managed.
|
|
4109
4105
|
import importlib
|
|
4110
4106
|
_up = importlib.import_module("meshcode.up")
|