mirror of
https://github.com/saphid/frame-control.git
synced 2026-10-06 01:00:18 +02:00
Devices: the assistant's keep-awake and panel tools reach the chosen headset; a Mac view tunnel opened during a switch is dropped
Integration review findings: the scripts they run ssh'd to whatever 'frame' means in ~/.ssh/config. They now take FRAME_ALIAS and FRAME_SSH_OPTS from the server's route. Co-Authored-By: Claude Opus 5.5 (1M context) <noreply@anthropic.com>
This commit is contained in:
1 parent
08fbe730c6
commit
ffef4d897a
5 files changed
+39
-6
No files matched your search
+6
-1
@@ -1,7 +1,9 @@
|
||||
"""Agent actions and one-use human approvals. No model SDK or network calls here."""
|
||||
import hashlib
|
||||
import os
|
||||
from pathlib import Path
|
||||
import secrets
|
||||
import shlex
|
||||
import shutil
|
||||
import subprocess
|
||||
import threading
|
||||
@@ -129,7 +131,10 @@ def run_script(server, name, args):
|
||||
script = server.HERE.parent / 'scripts' / name
|
||||
if not script.exists() or not shutil.which('zsh') or server.LOCAL:
|
||||
raise ValueError(name + ' requires a computer with zsh and the matching script installed')
|
||||
result = subprocess.run(['zsh', str(script), *args], capture_output=True, text=True, timeout=60)
|
||||
# The headset the server is routed to, not whatever `frame` means in ~/.ssh/config.
|
||||
env = {**os.environ, 'FRAME_ALIAS': server.FRAME,
|
||||
'FRAME_SSH_OPTS': shlex.join(server.SSH[1:])}
|
||||
result = subprocess.run(['zsh', str(script), *args], capture_output=True, text=True, timeout=60, env=env)
|
||||
if result.returncode:
|
||||
raise ValueError(result.stderr.strip() or 'Script failed')
|
||||
return {'message': result.stdout.strip()}
|
||||
|
||||
+6
-2
@@ -262,12 +262,13 @@ class MacView:
|
||||
"""Tries the ports on one route; True once the tunnel answers. With self.lock held."""
|
||||
last = ""
|
||||
for port in ports:
|
||||
target = (self.frame, self.host_opts) # retarget() may change these meanwhile
|
||||
# `via` first: ssh keeps the first value of an option, so USB-C's HostName wins
|
||||
# while the headset's pinned identity (in host_opts) still checks it.
|
||||
proc = subprocess.Popen([*self.tunnel_ssh, "-o", "ControlPath=none", *via, *self.host_opts,
|
||||
proc = subprocess.Popen([*self.tunnel_ssh, "-o", "ControlPath=none", *via, *target[1],
|
||||
"-o", "ExitOnForwardFailure=yes",
|
||||
"-o", "ServerAliveInterval=5", "-o", "ServerAliveCountMax=3", "-N",
|
||||
"-R", f"127.0.0.1:{port}:127.0.0.1:{self.port}", self.frame],
|
||||
"-R", f"127.0.0.1:{port}:127.0.0.1:{self.port}", target[0]],
|
||||
stdin=subprocess.DEVNULL, stdout=subprocess.DEVNULL,
|
||||
stderr=subprocess.PIPE, text=True)
|
||||
# A taken port makes ssh exit once it's connected; a working
|
||||
@@ -280,6 +281,9 @@ class MacView:
|
||||
if self._probe(port):
|
||||
ok = True
|
||||
break
|
||||
if ok and target[0] != self.frame:
|
||||
ok = False # the app switched headset while this one connected: not its tunnel
|
||||
self._last_tunnel_error = "switched headset"
|
||||
if ok:
|
||||
self.tunnel, self.remote_port = proc, port
|
||||
self.track(proc)
|
||||
|
||||
Reference in new issue
Block a user