meshcode 2.11.69__tar.gz → 2.11.70__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.69 → meshcode-2.11.70}/PKG-INFO +1 -1
- {meshcode-2.11.69 → meshcode-2.11.70}/meshcode/__init__.py +1 -1
- {meshcode-2.11.69 → meshcode-2.11.70}/meshcode/hostd.py +23 -12
- {meshcode-2.11.69 → meshcode-2.11.70}/meshcode/protocol_handler.py +28 -4
- {meshcode-2.11.69 → meshcode-2.11.70}/meshcode.egg-info/PKG-INFO +1 -1
- {meshcode-2.11.69 → meshcode-2.11.70}/pyproject.toml +1 -1
- {meshcode-2.11.69 → meshcode-2.11.70}/README.md +0 -0
- {meshcode-2.11.69 → meshcode-2.11.70}/meshcode/__main__.py +0 -0
- {meshcode-2.11.69 → meshcode-2.11.70}/meshcode/_stop_hook_template.py +0 -0
- {meshcode-2.11.69 → meshcode-2.11.70}/meshcode/ascii_art.py +0 -0
- {meshcode-2.11.69 → meshcode-2.11.70}/meshcode/atomic_push.py +0 -0
- {meshcode-2.11.69 → meshcode-2.11.70}/meshcode/claude_update.py +0 -0
- {meshcode-2.11.69 → meshcode-2.11.70}/meshcode/cli.py +0 -0
- {meshcode-2.11.69 → meshcode-2.11.70}/meshcode/comms_v4.py +0 -0
- {meshcode-2.11.69 → meshcode-2.11.70}/meshcode/compat.py +0 -0
- {meshcode-2.11.69 → meshcode-2.11.70}/meshcode/daemon.py +0 -0
- {meshcode-2.11.69 → meshcode-2.11.70}/meshcode/date_parse.py +0 -0
- {meshcode-2.11.69 → meshcode-2.11.70}/meshcode/doctor.py +0 -0
- {meshcode-2.11.69 → meshcode-2.11.70}/meshcode/error_hints.py +0 -0
- {meshcode-2.11.69 → meshcode-2.11.70}/meshcode/exceptions.py +0 -0
- {meshcode-2.11.69 → meshcode-2.11.70}/meshcode/invites.py +0 -0
- {meshcode-2.11.69 → meshcode-2.11.70}/meshcode/launcher.py +0 -0
- {meshcode-2.11.69 → meshcode-2.11.70}/meshcode/launcher_install.py +0 -0
- {meshcode-2.11.69 → meshcode-2.11.70}/meshcode/meshcode_mcp/__init__.py +0 -0
- {meshcode-2.11.69 → meshcode-2.11.70}/meshcode/meshcode_mcp/__main__.py +0 -0
- {meshcode-2.11.69 → meshcode-2.11.70}/meshcode/meshcode_mcp/backend.py +0 -0
- {meshcode-2.11.69 → meshcode-2.11.70}/meshcode/meshcode_mcp/realtime.py +0 -0
- {meshcode-2.11.69 → meshcode-2.11.70}/meshcode/meshcode_mcp/server.py +0 -0
- {meshcode-2.11.69 → meshcode-2.11.70}/meshcode/meshcode_mcp/sleep_signals.py +0 -0
- {meshcode-2.11.69 → meshcode-2.11.70}/meshcode/meshcode_mcp/test_backend.py +0 -0
- {meshcode-2.11.69 → meshcode-2.11.70}/meshcode/meshcode_mcp/test_boot_timing.py +0 -0
- {meshcode-2.11.69 → meshcode-2.11.70}/meshcode/meshcode_mcp/test_install_guard.py +0 -0
- {meshcode-2.11.69 → meshcode-2.11.70}/meshcode/meshcode_mcp/test_prefs_claude_version.py +0 -0
- {meshcode-2.11.69 → meshcode-2.11.70}/meshcode/meshcode_mcp/test_realtime.py +0 -0
- {meshcode-2.11.69 → meshcode-2.11.70}/meshcode/meshcode_mcp/test_server_wrapper.py +0 -0
- {meshcode-2.11.69 → meshcode-2.11.70}/meshcode/preferences.py +0 -0
- {meshcode-2.11.69 → meshcode-2.11.70}/meshcode/protocol_v2.py +0 -0
- {meshcode-2.11.69 → meshcode-2.11.70}/meshcode/quickstart.py +0 -0
- {meshcode-2.11.69 → meshcode-2.11.70}/meshcode/rpc_allowlist.py +0 -0
- {meshcode-2.11.69 → meshcode-2.11.70}/meshcode/run_agent.py +0 -0
- {meshcode-2.11.69 → meshcode-2.11.70}/meshcode/scripts/check_secrets.py +0 -0
- {meshcode-2.11.69 → meshcode-2.11.70}/meshcode/scripts/race_rate_harness.py +0 -0
- {meshcode-2.11.69 → meshcode-2.11.70}/meshcode/secrets.py +0 -0
- {meshcode-2.11.69 → meshcode-2.11.70}/meshcode/self_update.py +0 -0
- {meshcode-2.11.69 → meshcode-2.11.70}/meshcode/setup_clients.py +0 -0
- {meshcode-2.11.69 → meshcode-2.11.70}/meshcode/supervisor.py +0 -0
- {meshcode-2.11.69 → meshcode-2.11.70}/meshcode/up.py +0 -0
- {meshcode-2.11.69 → meshcode-2.11.70}/meshcode/upload.py +0 -0
- {meshcode-2.11.69 → meshcode-2.11.70}/meshcode.egg-info/SOURCES.txt +0 -0
- {meshcode-2.11.69 → meshcode-2.11.70}/meshcode.egg-info/dependency_links.txt +0 -0
- {meshcode-2.11.69 → meshcode-2.11.70}/meshcode.egg-info/entry_points.txt +0 -0
- {meshcode-2.11.69 → meshcode-2.11.70}/meshcode.egg-info/requires.txt +0 -0
- {meshcode-2.11.69 → meshcode-2.11.70}/meshcode.egg-info/top_level.txt +0 -0
- {meshcode-2.11.69 → meshcode-2.11.70}/setup.cfg +0 -0
- {meshcode-2.11.69 → meshcode-2.11.70}/tests/test_auto_update_hardening.py +0 -0
- {meshcode-2.11.69 → meshcode-2.11.70}/tests/test_autonomous_closegap_1.py +0 -0
- {meshcode-2.11.69 → meshcode-2.11.70}/tests/test_autonomous_closegap_2.py +0 -0
- {meshcode-2.11.69 → meshcode-2.11.70}/tests/test_autonomous_closegap_3.py +0 -0
- {meshcode-2.11.69 → meshcode-2.11.70}/tests/test_autonomous_prompt_inject.py +0 -0
- {meshcode-2.11.69 → meshcode-2.11.70}/tests/test_boot_bug_regression.py +0 -0
- {meshcode-2.11.69 → meshcode-2.11.70}/tests/test_color_truecolor.py +0 -0
- {meshcode-2.11.69 → meshcode-2.11.70}/tests/test_core.py +0 -0
- {meshcode-2.11.69 → meshcode-2.11.70}/tests/test_cross_agent_messaging.py +0 -0
- {meshcode-2.11.69 → meshcode-2.11.70}/tests/test_date_parse.py +0 -0
- {meshcode-2.11.69 → meshcode-2.11.70}/tests/test_doctor.py +0 -0
- {meshcode-2.11.69 → meshcode-2.11.70}/tests/test_epistemic_v1_python_sdk.py +0 -0
- {meshcode-2.11.69 → meshcode-2.11.70}/tests/test_epistemic_v1_stop_conditions.py +0 -0
- {meshcode-2.11.69 → meshcode-2.11.70}/tests/test_esc_deaf_state.py +0 -0
- {meshcode-2.11.69 → meshcode-2.11.70}/tests/test_exceptions.py +0 -0
- {meshcode-2.11.69 → meshcode-2.11.70}/tests/test_file_upload.py +0 -0
- {meshcode-2.11.69 → meshcode-2.11.70}/tests/test_init_device_code.py +0 -0
- {meshcode-2.11.69 → meshcode-2.11.70}/tests/test_install_guard.py +0 -0
- {meshcode-2.11.69 → meshcode-2.11.70}/tests/test_lease_sigterm_release.py +0 -0
- {meshcode-2.11.69 → meshcode-2.11.70}/tests/test_mark_read_batch.py +0 -0
- {meshcode-2.11.69 → meshcode-2.11.70}/tests/test_marketplace_ratings.py +0 -0
- {meshcode-2.11.69 → meshcode-2.11.70}/tests/test_migration_integrity.py +0 -0
- {meshcode-2.11.69 → meshcode-2.11.70}/tests/test_realtime_event_freshness.py +0 -0
- {meshcode-2.11.69 → meshcode-2.11.70}/tests/test_rls_cross_tenant.py +0 -0
- {meshcode-2.11.69 → meshcode-2.11.70}/tests/test_rpc_grants.py +0 -0
- {meshcode-2.11.69 → meshcode-2.11.70}/tests/test_rpc_migrations.py +0 -0
- {meshcode-2.11.69 → meshcode-2.11.70}/tests/test_run_agent_dry_run.py +0 -0
- {meshcode-2.11.69 → meshcode-2.11.70}/tests/test_run_agent_no_server_import.py +0 -0
- {meshcode-2.11.69 → meshcode-2.11.70}/tests/test_security_regressions.py +0 -0
- {meshcode-2.11.69 → meshcode-2.11.70}/tests/test_self_update_user_site.py +0 -0
- {meshcode-2.11.69 → meshcode-2.11.70}/tests/test_sentinel.py +0 -0
- {meshcode-2.11.69 → meshcode-2.11.70}/tests/test_setup_path.py +0 -0
- {meshcode-2.11.69 → meshcode-2.11.70}/tests/test_sleep_signals.py +0 -0
- {meshcode-2.11.69 → meshcode-2.11.70}/tests/test_status_enum_coverage.py +0 -0
- {meshcode-2.11.69 → meshcode-2.11.70}/tests/test_stay_on_loop_hook.py +0 -0
- {meshcode-2.11.69 → meshcode-2.11.70}/tests/test_wait_open_tasks_contradiction.py +0 -0
|
@@ -34,6 +34,7 @@ from __future__ import annotations
|
|
|
34
34
|
|
|
35
35
|
import json
|
|
36
36
|
import os
|
|
37
|
+
import shlex
|
|
37
38
|
import subprocess
|
|
38
39
|
import sys
|
|
39
40
|
import time
|
|
@@ -183,20 +184,30 @@ def _meshcode_bin() -> str:
|
|
|
183
184
|
|
|
184
185
|
|
|
185
186
|
def _spawn_agent(project: str, agent: str) -> bool:
|
|
186
|
-
"""Relaunch `meshcode run <project>/<agent>`
|
|
187
|
+
"""Relaunch `meshcode run <project>/<agent>` in a VISIBLE terminal window.
|
|
188
|
+
|
|
189
|
+
Samuel must SEE the terminal open — a headless background process is NOT the
|
|
190
|
+
feature (the old code did subprocess.Popen(...DEVNULL) = no window). We delegate
|
|
191
|
+
to protocol_handler._spawn_terminal, the canonical visible spawner (macOS:
|
|
192
|
+
osascript-if-Automation-granted else `open` a .command wrapper, no TCC needed;
|
|
193
|
+
Linux/Windows: native terminals). On failure we WARN loudly and return False —
|
|
194
|
+
we NEVER silently fall back to a headless process, so the gap stays visible.
|
|
195
|
+
"""
|
|
187
196
|
target = f"{project}/{agent}"
|
|
188
|
-
env
|
|
189
|
-
#
|
|
190
|
-
|
|
191
|
-
|
|
192
|
-
env["MESHCODE_NO_AUTO_UPDATE"] = env.get("MESHCODE_NO_AUTO_UPDATE", "1")
|
|
197
|
+
# env hygiene (item1 RC): a stale CLAUDECODE aborts `meshcode run` (exit2).
|
|
198
|
+
# Prefix the shell command so the spawned terminal starts with a clean env.
|
|
199
|
+
cmd = (f"unset CLAUDECODE CLAUDE_CODE_SESSION; export MESHCODE_NO_AUTO_UPDATE=1; "
|
|
200
|
+
f"exec {shlex.quote(_meshcode_bin())} run {shlex.quote(target)}")
|
|
193
201
|
try:
|
|
194
|
-
|
|
195
|
-
|
|
196
|
-
|
|
197
|
-
|
|
198
|
-
|
|
199
|
-
|
|
202
|
+
from meshcode import protocol_handler as _ph
|
|
203
|
+
ok, info = _ph._spawn_terminal(cmd)
|
|
204
|
+
if ok:
|
|
205
|
+
_log(f"spawned {target} in visible terminal ({info})")
|
|
206
|
+
return True
|
|
207
|
+
_log(f"WARN: visible spawn {target} FAILED ({info}) — agent NOT launched. "
|
|
208
|
+
f"macOS: grant Terminal Automation (System Settings > Privacy & Security "
|
|
209
|
+
f"> Automation), or ensure `open` works. NOT falling back to headless.")
|
|
210
|
+
return False
|
|
200
211
|
except Exception as e:
|
|
201
212
|
_log(f"WARN: spawn {target} failed: {e}")
|
|
202
213
|
return False
|
|
@@ -44,7 +44,15 @@ def _detect_macos_terminal() -> str:
|
|
|
44
44
|
|
|
45
45
|
|
|
46
46
|
def _spawn_terminal_macos(cmd: str) -> tuple[bool, str]:
|
|
47
|
-
"""Spawn `cmd` in a new Terminal/iTerm window (detached).
|
|
47
|
+
"""Spawn `cmd` in a new VISIBLE Terminal/iTerm window (detached).
|
|
48
|
+
|
|
49
|
+
Primary: osascript ('do script') — opens a window in the running Terminal/iTerm
|
|
50
|
+
but REQUIRES the macOS Automation permission. If the user hasn't granted it,
|
|
51
|
+
osascript fails. Fallback: a temp .command file launched via `open`, which opens
|
|
52
|
+
a visible Terminal window WITHOUT Automation (it just opens the app with a
|
|
53
|
+
document). So the spawn is ALWAYS a visible terminal, never a silent headless
|
|
54
|
+
background process (LAUNCH-1 spawn-visible gap).
|
|
55
|
+
"""
|
|
48
56
|
term = _detect_macos_terminal()
|
|
49
57
|
# AppleScript escaping: backslash + double-quote
|
|
50
58
|
safe = cmd.replace("\\", "\\\\").replace('"', '\\"')
|
|
@@ -59,9 +67,25 @@ def _spawn_terminal_macos(cmd: str) -> tuple[bool, str]:
|
|
|
59
67
|
script = f'tell application "Terminal" to do script "{safe}"\n'
|
|
60
68
|
r = subprocess.run(["osascript", "-e", script],
|
|
61
69
|
capture_output=True, text=True)
|
|
62
|
-
if r.returncode
|
|
63
|
-
return
|
|
64
|
-
|
|
70
|
+
if r.returncode == 0:
|
|
71
|
+
return True, term
|
|
72
|
+
osa_err = (r.stderr or "osascript failed").strip()
|
|
73
|
+
# Fallback: a .command launcher opened via `open` — no Automation permission needed.
|
|
74
|
+
try:
|
|
75
|
+
import tempfile
|
|
76
|
+
fd, path = tempfile.mkstemp(suffix=".command", prefix="meshcode-launch-")
|
|
77
|
+
with os.fdopen(fd, "w") as f:
|
|
78
|
+
f.write("#!/bin/bash\n")
|
|
79
|
+
f.write(cmd + "\n")
|
|
80
|
+
f.write('rm -f "$0"\n') # self-clean the temp launcher on exit
|
|
81
|
+
os.chmod(path, 0o755)
|
|
82
|
+
r2 = subprocess.run(["open", path], capture_output=True, text=True)
|
|
83
|
+
if r2.returncode == 0:
|
|
84
|
+
return True, "terminal(open-fallback)"
|
|
85
|
+
return False, (f"osascript failed ({osa_err}); "
|
|
86
|
+
f"open fallback failed ({(r2.stderr or '').strip()})")
|
|
87
|
+
except Exception as e:
|
|
88
|
+
return False, f"osascript failed ({osa_err}); open fallback exception: {e}"
|
|
65
89
|
|
|
66
90
|
|
|
67
91
|
def _spawn_terminal_linux(cmd: str) -> tuple[bool, str]:
|
|
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
|