Preserve macOS app permissions via dynamic launcher, .env workspace path, and session/audio tools
This commit is contained in:
@@ -0,0 +1,56 @@
|
||||
#!/usr/bin/env python3
|
||||
"""Inspect or switch VoiceAgent's live input/output device through its local UI API."""
|
||||
|
||||
import argparse
|
||||
import json
|
||||
import sys
|
||||
from urllib.error import HTTPError, URLError
|
||||
from urllib.request import Request, urlopen
|
||||
|
||||
BASE_URL = "http://127.0.0.1:8888"
|
||||
|
||||
|
||||
def request(path, method="GET", payload=None):
|
||||
data = json.dumps(payload).encode() if payload is not None else None
|
||||
req = Request(BASE_URL + path, data=data, method=method)
|
||||
if data is not None:
|
||||
req.add_header("Content-Type", "application/json")
|
||||
try:
|
||||
with urlopen(req, timeout=5) as response:
|
||||
return json.load(response)
|
||||
except HTTPError as exc:
|
||||
try:
|
||||
message = json.load(exc)
|
||||
except Exception:
|
||||
message = {"error": exc.read().decode("utf-8", "replace")}
|
||||
raise RuntimeError(message.get("error", str(exc))) from exc
|
||||
except URLError as exc:
|
||||
raise RuntimeError(f"VoiceAgent is not reachable at {BASE_URL}: {exc.reason}") from exc
|
||||
|
||||
|
||||
def main() -> int:
|
||||
parser = argparse.ArgumentParser(description=__doc__)
|
||||
commands = parser.add_subparsers(dest="command", required=True)
|
||||
commands.add_parser("list", help="List selectable input/output devices.")
|
||||
select = commands.add_parser("set", help="Switch one live route or follow the macOS default.")
|
||||
select.add_argument("direction", choices=("input", "output"))
|
||||
select.add_argument("device", help="Unique device-name substring, PortAudio index, or 'default'.")
|
||||
args = parser.parse_args()
|
||||
try:
|
||||
if args.command == "list":
|
||||
result = request("/api/audio-devices")
|
||||
for device in result["devices"]:
|
||||
kinds = "/".join(kind for kind in ("input" if device["input"] else "", "output" if device["output"] else "") if kind)
|
||||
print(f"[{device['id']}] {device['name']} ({kinds})")
|
||||
else:
|
||||
result = request("/api/audio-device", "POST", {"direction": args.direction, "device": args.device})
|
||||
mode = "following macOS default" if result["following_default"] else f"pinned to [{result['device']}]"
|
||||
print(f"{args.direction} changed to {result['name']} ({mode})")
|
||||
return 0
|
||||
except (KeyError, RuntimeError) as exc:
|
||||
print(f"audio-tool: {exc}", file=sys.stderr)
|
||||
return 1
|
||||
|
||||
|
||||
if __name__ == "__main__":
|
||||
raise SystemExit(main())
|
||||
Reference in New Issue
Block a user