meshcode 2.11.152__tar.gz → 2.11.153__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.152 → meshcode-2.11.153}/PKG-INFO +1 -1
- {meshcode-2.11.152 → meshcode-2.11.153}/meshcode/__init__.py +1 -1
- {meshcode-2.11.152 → meshcode-2.11.153}/meshcode/protocol_handler.py +60 -27
- {meshcode-2.11.152 → meshcode-2.11.153}/meshcode.egg-info/PKG-INFO +1 -1
- {meshcode-2.11.152 → meshcode-2.11.153}/pyproject.toml +1 -1
- {meshcode-2.11.152 → meshcode-2.11.153}/README.md +0 -0
- {meshcode-2.11.152 → meshcode-2.11.153}/meshcode/__main__.py +0 -0
- {meshcode-2.11.152 → meshcode-2.11.153}/meshcode/_session_handoff_template.py +0 -0
- {meshcode-2.11.152 → meshcode-2.11.153}/meshcode/_stop_hook_template.py +0 -0
- {meshcode-2.11.152 → meshcode-2.11.153}/meshcode/ascii_art.py +0 -0
- {meshcode-2.11.152 → meshcode-2.11.153}/meshcode/atomic_push.py +0 -0
- {meshcode-2.11.152 → meshcode-2.11.153}/meshcode/claude_update.py +0 -0
- {meshcode-2.11.152 → meshcode-2.11.153}/meshcode/cli.py +0 -0
- {meshcode-2.11.152 → meshcode-2.11.153}/meshcode/comms_v4.py +0 -0
- {meshcode-2.11.152 → meshcode-2.11.153}/meshcode/compat.py +0 -0
- {meshcode-2.11.152 → meshcode-2.11.153}/meshcode/daemon.py +0 -0
- {meshcode-2.11.152 → meshcode-2.11.153}/meshcode/date_parse.py +0 -0
- {meshcode-2.11.152 → meshcode-2.11.153}/meshcode/doctor.py +0 -0
- {meshcode-2.11.152 → meshcode-2.11.153}/meshcode/error_hints.py +0 -0
- {meshcode-2.11.152 → meshcode-2.11.153}/meshcode/exceptions.py +0 -0
- {meshcode-2.11.152 → meshcode-2.11.153}/meshcode/helper_visuals.py +0 -0
- {meshcode-2.11.152 → meshcode-2.11.153}/meshcode/hooks/__init__.py +0 -0
- {meshcode-2.11.152 → meshcode-2.11.153}/meshcode/hooks/repo_path_lock.py +0 -0
- {meshcode-2.11.152 → meshcode-2.11.153}/meshcode/hostd.py +0 -0
- {meshcode-2.11.152 → meshcode-2.11.153}/meshcode/invites.py +0 -0
- {meshcode-2.11.152 → meshcode-2.11.153}/meshcode/launcher.py +0 -0
- {meshcode-2.11.152 → meshcode-2.11.153}/meshcode/launcher_install.py +0 -0
- {meshcode-2.11.152 → meshcode-2.11.153}/meshcode/meshcode_mcp/__init__.py +0 -0
- {meshcode-2.11.152 → meshcode-2.11.153}/meshcode/meshcode_mcp/__main__.py +0 -0
- {meshcode-2.11.152 → meshcode-2.11.153}/meshcode/meshcode_mcp/backend.py +0 -0
- {meshcode-2.11.152 → meshcode-2.11.153}/meshcode/meshcode_mcp/realtime.py +0 -0
- {meshcode-2.11.152 → meshcode-2.11.153}/meshcode/meshcode_mcp/server.py +0 -0
- {meshcode-2.11.152 → meshcode-2.11.153}/meshcode/meshcode_mcp/sleep_signals.py +0 -0
- {meshcode-2.11.152 → meshcode-2.11.153}/meshcode/meshcode_mcp/swarm.py +0 -0
- {meshcode-2.11.152 → meshcode-2.11.153}/meshcode/meshcode_mcp/test_backend.py +0 -0
- {meshcode-2.11.152 → meshcode-2.11.153}/meshcode/meshcode_mcp/test_boot_timing.py +0 -0
- {meshcode-2.11.152 → meshcode-2.11.153}/meshcode/meshcode_mcp/test_install_guard.py +0 -0
- {meshcode-2.11.152 → meshcode-2.11.153}/meshcode/meshcode_mcp/test_prefs_claude_version.py +0 -0
- {meshcode-2.11.152 → meshcode-2.11.153}/meshcode/meshcode_mcp/test_realtime.py +0 -0
- {meshcode-2.11.152 → meshcode-2.11.153}/meshcode/meshcode_mcp/test_server_wrapper.py +0 -0
- {meshcode-2.11.152 → meshcode-2.11.153}/meshcode/meshcode_mcp/test_swarm.py +0 -0
- {meshcode-2.11.152 → meshcode-2.11.153}/meshcode/preferences.py +0 -0
- {meshcode-2.11.152 → meshcode-2.11.153}/meshcode/protocol_v2.py +0 -0
- {meshcode-2.11.152 → meshcode-2.11.153}/meshcode/quickstart.py +0 -0
- {meshcode-2.11.152 → meshcode-2.11.153}/meshcode/rpc_allowlist.py +0 -0
- {meshcode-2.11.152 → meshcode-2.11.153}/meshcode/run_agent.py +0 -0
- {meshcode-2.11.152 → meshcode-2.11.153}/meshcode/scripts/check_secrets.py +0 -0
- {meshcode-2.11.152 → meshcode-2.11.153}/meshcode/scripts/race_rate_harness.py +0 -0
- {meshcode-2.11.152 → meshcode-2.11.153}/meshcode/secrets.py +0 -0
- {meshcode-2.11.152 → meshcode-2.11.153}/meshcode/self_update.py +0 -0
- {meshcode-2.11.152 → meshcode-2.11.153}/meshcode/setup_clients.py +0 -0
- {meshcode-2.11.152 → meshcode-2.11.153}/meshcode/supervisor.py +0 -0
- {meshcode-2.11.152 → meshcode-2.11.153}/meshcode/up.py +0 -0
- {meshcode-2.11.152 → meshcode-2.11.153}/meshcode/upload.py +0 -0
- {meshcode-2.11.152 → meshcode-2.11.153}/meshcode.egg-info/SOURCES.txt +0 -0
- {meshcode-2.11.152 → meshcode-2.11.153}/meshcode.egg-info/dependency_links.txt +0 -0
- {meshcode-2.11.152 → meshcode-2.11.153}/meshcode.egg-info/entry_points.txt +0 -0
- {meshcode-2.11.152 → meshcode-2.11.153}/meshcode.egg-info/requires.txt +0 -0
- {meshcode-2.11.152 → meshcode-2.11.153}/meshcode.egg-info/top_level.txt +0 -0
- {meshcode-2.11.152 → meshcode-2.11.153}/setup.cfg +0 -0
- {meshcode-2.11.152 → meshcode-2.11.153}/tests/test_auto_update_hardening.py +0 -0
- {meshcode-2.11.152 → meshcode-2.11.153}/tests/test_autonomous_closegap_1.py +0 -0
- {meshcode-2.11.152 → meshcode-2.11.153}/tests/test_autonomous_closegap_2.py +0 -0
- {meshcode-2.11.152 → meshcode-2.11.153}/tests/test_autonomous_closegap_3.py +0 -0
- {meshcode-2.11.152 → meshcode-2.11.153}/tests/test_autonomous_prompt_inject.py +0 -0
- {meshcode-2.11.152 → meshcode-2.11.153}/tests/test_boot_bug_regression.py +0 -0
- {meshcode-2.11.152 → meshcode-2.11.153}/tests/test_color_truecolor.py +0 -0
- {meshcode-2.11.152 → meshcode-2.11.153}/tests/test_core.py +0 -0
- {meshcode-2.11.152 → meshcode-2.11.153}/tests/test_cross_agent_messaging.py +0 -0
- {meshcode-2.11.152 → meshcode-2.11.153}/tests/test_date_parse.py +0 -0
- {meshcode-2.11.152 → meshcode-2.11.153}/tests/test_doctor.py +0 -0
- {meshcode-2.11.152 → meshcode-2.11.153}/tests/test_epistemic_v1_python_sdk.py +0 -0
- {meshcode-2.11.152 → meshcode-2.11.153}/tests/test_epistemic_v1_stop_conditions.py +0 -0
- {meshcode-2.11.152 → meshcode-2.11.153}/tests/test_esc_deaf_state.py +0 -0
- {meshcode-2.11.152 → meshcode-2.11.153}/tests/test_exceptions.py +0 -0
- {meshcode-2.11.152 → meshcode-2.11.153}/tests/test_file_upload.py +0 -0
- {meshcode-2.11.152 → meshcode-2.11.153}/tests/test_helper_visuals.py +0 -0
- {meshcode-2.11.152 → meshcode-2.11.153}/tests/test_hostd_launch_pinned_env.py +0 -0
- {meshcode-2.11.152 → meshcode-2.11.153}/tests/test_hostd_serve_discovery_split.py +0 -0
- {meshcode-2.11.152 → meshcode-2.11.153}/tests/test_hostd_zombie_sessions.py +0 -0
- {meshcode-2.11.152 → meshcode-2.11.153}/tests/test_init_device_code.py +0 -0
- {meshcode-2.11.152 → meshcode-2.11.153}/tests/test_install_guard.py +0 -0
- {meshcode-2.11.152 → meshcode-2.11.153}/tests/test_lease_sigterm_release.py +0 -0
- {meshcode-2.11.152 → meshcode-2.11.153}/tests/test_live_mesh_guard.py +0 -0
- {meshcode-2.11.152 → meshcode-2.11.153}/tests/test_mark_read_batch.py +0 -0
- {meshcode-2.11.152 → meshcode-2.11.153}/tests/test_marketplace_ratings.py +0 -0
- {meshcode-2.11.152 → meshcode-2.11.153}/tests/test_migration_integrity.py +0 -0
- {meshcode-2.11.152 → meshcode-2.11.153}/tests/test_pretrust_claude.py +0 -0
- {meshcode-2.11.152 → meshcode-2.11.153}/tests/test_realtime_event_freshness.py +0 -0
- {meshcode-2.11.152 → meshcode-2.11.153}/tests/test_rls_cross_tenant.py +0 -0
- {meshcode-2.11.152 → meshcode-2.11.153}/tests/test_rpc_grants.py +0 -0
- {meshcode-2.11.152 → meshcode-2.11.153}/tests/test_rpc_migrations.py +0 -0
- {meshcode-2.11.152 → meshcode-2.11.153}/tests/test_run_agent_dry_run.py +0 -0
- {meshcode-2.11.152 → meshcode-2.11.153}/tests/test_run_agent_no_server_import.py +0 -0
- {meshcode-2.11.152 → meshcode-2.11.153}/tests/test_security_regressions.py +0 -0
- {meshcode-2.11.152 → meshcode-2.11.153}/tests/test_self_update_user_site.py +0 -0
- {meshcode-2.11.152 → meshcode-2.11.153}/tests/test_sentinel.py +0 -0
- {meshcode-2.11.152 → meshcode-2.11.153}/tests/test_session_replay_gate.py +0 -0
- {meshcode-2.11.152 → meshcode-2.11.153}/tests/test_setup_path.py +0 -0
- {meshcode-2.11.152 → meshcode-2.11.153}/tests/test_sleep_signals.py +0 -0
- {meshcode-2.11.152 → meshcode-2.11.153}/tests/test_status_enum_coverage.py +0 -0
- {meshcode-2.11.152 → meshcode-2.11.153}/tests/test_stay_on_loop_hook.py +0 -0
- {meshcode-2.11.152 → meshcode-2.11.153}/tests/test_stop_ghost_terminal.py +0 -0
- {meshcode-2.11.152 → meshcode-2.11.153}/tests/test_swarm_events.py +0 -0
- {meshcode-2.11.152 → meshcode-2.11.153}/tests/test_task_progress.py +0 -0
- {meshcode-2.11.152 → meshcode-2.11.153}/tests/test_terminal_lifecycle.py +0 -0
- {meshcode-2.11.152 → meshcode-2.11.153}/tests/test_wait_open_tasks_contradiction.py +0 -0
|
@@ -272,30 +272,53 @@ def _tmux(tmux: str, *args: str) -> subprocess.CompletedProcess:
|
|
|
272
272
|
return subprocess.run([tmux, *args], capture_output=True, text=True, timeout=15)
|
|
273
273
|
|
|
274
274
|
|
|
275
|
-
def _fleet_wrap(cmd: str) -> str:
|
|
275
|
+
def _fleet_wrap(cmd: str, tmux: str = "tmux") -> str:
|
|
276
276
|
"""Shell line for an agent inside its tmux window.
|
|
277
277
|
|
|
278
|
-
|
|
279
|
-
|
|
280
|
-
|
|
281
|
-
|
|
282
|
-
|
|
283
|
-
|
|
284
|
-
|
|
285
|
-
|
|
286
|
-
|
|
287
|
-
|
|
288
|
-
|
|
289
|
-
|
|
290
|
-
|
|
291
|
-
|
|
292
|
-
|
|
278
|
+
RAII / opener-owns-teardown (Samuel P0 'vergo de terminales' — professional
|
|
279
|
+
supervisor pattern, NOT a patch): this wrapper OWNS its tmux window and an
|
|
280
|
+
EXIT+signal trap closes THAT window whenever the agent process dies — clean
|
|
281
|
+
stop, recycle-exit, OR crash — so a dead pane never lingers and accumulates
|
|
282
|
+
(459 spawns vs 0 closes / 18 days -> ~50 stale tabs). It self-targets via
|
|
283
|
+
$TMUX_PANE, so it can only EVER close its OWN window — never a live sibling's
|
|
284
|
+
(the 'never close a live agent' guardrail is structural here: the trap fires
|
|
285
|
+
only when THIS agent already exited). Replaces the old
|
|
286
|
+
`remain-on-exit=failed keeps the dead pane for debugging` behavior, which was
|
|
287
|
+
the accumulation source. rc 143 (SIGTERM = clean hostd stop, task 91201315)
|
|
288
|
+
and clean exits close silently; a crash rc is logged to stderr first.
|
|
289
|
+
|
|
290
|
+
Kill-switch env MESHCODE_FLEET_WINDOW_CLOSE: `0`/`off` restores the old
|
|
291
|
+
keep-dead-tab-for-debugging behavior; `dry`/`dryrun` logs intent without
|
|
292
|
+
closing.
|
|
293
|
+
|
|
294
|
+
Drops the LAST `exec ` (same trick as the .command launcher) so the shell
|
|
295
|
+
SURVIVES the agent's exit and the trap can run. CLOSE-TAB=STOP (task
|
|
296
|
+
4df5a126, Samuel 68b1c17b): export MESHCODE_CLOSE_STOP_SIGHUP=1 so the MCP
|
|
297
|
+
server's gated POSIX close=stop handler arms INSIDE fleet tabs (right-click
|
|
298
|
+
tab -> Kill => SIGHUP => agent flips desired_state=stopped + exits clean, no
|
|
299
|
+
hostd ghost-respawn). A real crash still respawns (hostd, DB-driven) —
|
|
300
|
+
closing the crashed tab just means the respawn opens a fresh one."""
|
|
293
301
|
if "exec " in cmd:
|
|
294
302
|
head, _, tail = cmd.rpartition("exec ")
|
|
295
303
|
cmd = head + tail
|
|
296
|
-
|
|
297
|
-
|
|
298
|
-
|
|
304
|
+
tq = shlex.quote(tmux)
|
|
305
|
+
return (
|
|
306
|
+
'export MESHCODE_CLOSE_STOP_SIGHUP=1; '
|
|
307
|
+
# RAII teardown: close OUR OWN tmux window on ANY exit/signal. $TMUX_PANE
|
|
308
|
+
# is set by tmux for the pane we run in, so kill-window can only ever hit
|
|
309
|
+
# THIS window. Disarm traps first (avoid double-run via the EXIT trap).
|
|
310
|
+
'_mc_close() { _rc=$?; trap - EXIT INT TERM HUP; '
|
|
311
|
+
'case "${MESHCODE_FLEET_WINDOW_CLOSE:-}" in '
|
|
312
|
+
'0|off|false|no) exit "$_rc";; '
|
|
313
|
+
'dry|dryrun|dry-run) echo "[meshcode] DRY-RUN: would close own tab (rc=$_rc)" >&2; exit "$_rc";; '
|
|
314
|
+
'esac; '
|
|
315
|
+
'{ [ "$_rc" != "0" ] && [ "$_rc" != "143" ]; } && '
|
|
316
|
+
'echo "[meshcode] agent exited rc=$_rc — closing tab (1 agent = 1 terminal)" >&2; '
|
|
317
|
+
f'{tq} kill-window -t "${{TMUX_PANE:-}}" 2>/dev/null; '
|
|
318
|
+
'exit "$_rc"; }; '
|
|
319
|
+
'trap _mc_close EXIT INT TERM HUP; '
|
|
320
|
+
f'{cmd}'
|
|
321
|
+
)
|
|
299
322
|
|
|
300
323
|
|
|
301
324
|
def _fleet_attach_macos(tmux: str) -> tuple[bool, str]:
|
|
@@ -360,7 +383,7 @@ def _spawn_fleet_tab(cmd: str) -> tuple[bool, str]:
|
|
|
360
383
|
if not tmux:
|
|
361
384
|
return False, "tmux not installed (brew install tmux -> tabbed fleet window)"
|
|
362
385
|
label = _fleet_tab_name(cmd)
|
|
363
|
-
wrapped = _fleet_wrap(cmd)
|
|
386
|
+
wrapped = _fleet_wrap(cmd, tmux)
|
|
364
387
|
try:
|
|
365
388
|
fresh_session = _tmux(tmux, "has-session", "-t", f"={_FLEET_SESSION}").returncode != 0
|
|
366
389
|
win_id = ""
|
|
@@ -684,10 +707,20 @@ def _write_fleet_native_agent(cmd: str) -> Path:
|
|
|
684
707
|
"disown",
|
|
685
708
|
run_line,
|
|
686
709
|
"MC_RC=$?",
|
|
687
|
-
#
|
|
688
|
-
#
|
|
689
|
-
|
|
690
|
-
|
|
710
|
+
# RAII / opener-owns-teardown (Samuel P0 'vergo de terminales' —
|
|
711
|
+
# professional pattern): close OUR OWN native tab on ANY exit — clean
|
|
712
|
+
# stop, recycle-exit, OR crash — so a dead tab never accumulates (Ian's
|
|
713
|
+
# ~40 stale native tabs). The osascript self-targets by MC_TTY (closes
|
|
714
|
+
# ONLY the tab whose tty is ours) so a LIVE sibling is never touched.
|
|
715
|
+
# Replaces the old keep-crashed-tab-for-debugging behavior. Kill-switch
|
|
716
|
+
# MESHCODE_FLEET_WINDOW_CLOSE=0 restores it; =dry logs intent.
|
|
717
|
+
'case "${MESHCODE_FLEET_WINDOW_CLOSE:-}" in',
|
|
718
|
+
' 0|off|false|no) { [ "$MC_RC" != "0" ] && [ "$MC_RC" != "143" ]; } && echo "[meshcode] agent exited rc=$MC_RC — tab kept (close disabled)" ;;',
|
|
719
|
+
' dry|dryrun|dry-run) echo "[meshcode] DRY-RUN: would close own tab (rc=$MC_RC)" ;;',
|
|
720
|
+
' *)',
|
|
721
|
+
' { [ "$MC_RC" != "0" ] && [ "$MC_RC" != "143" ]; } && echo "[meshcode] agent exited rc=$MC_RC — closing tab (1 agent = 1 terminal)"',
|
|
722
|
+
' if [ -n "$MC_TTY" ]; then',
|
|
723
|
+
" /usr/bin/osascript"
|
|
691
724
|
" -e 'on run argv'"
|
|
692
725
|
" -e 'tell application \"Terminal\"'"
|
|
693
726
|
" -e 'repeat with w in windows'"
|
|
@@ -699,9 +732,9 @@ def _write_fleet_native_agent(cmd: str) -> Path:
|
|
|
699
732
|
" -e 'end repeat'"
|
|
700
733
|
" -e 'end tell'"
|
|
701
734
|
" -e 'end run' \"$MC_TTY\" >/dev/null 2>&1",
|
|
702
|
-
|
|
703
|
-
'
|
|
704
|
-
|
|
735
|
+
' fi',
|
|
736
|
+
' ;;',
|
|
737
|
+
'esac',
|
|
705
738
|
]
|
|
706
739
|
p["dir"].mkdir(parents=True, exist_ok=True)
|
|
707
740
|
script_path.write_text("\n".join(lines) + "\n", encoding="utf-8")
|
|
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
|
|
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
|