The -1712 "AppleEvent timed out" on m3ultra was not the screen lock (2236a96 is wrong).
The user TCC db says it plainly:
m3ultra: /bin/sh -> com.google.Chrome auth_value=0 DENIED
(no row at all for /bin/sh -> com.brave.Browser)
ultra: /bin/sh -> com.brave.Browser auth_value=2 allowed
The launchd job IS `/bin/sh -c exec launch.sh`, so that one row kills it, and a DENIED
Automation grant surfaces as a ~2-minute hang then -1712, never a clean -1743. The
`sshd-keygen-wrapper -> {finder,systemevents,Brave,Chrome} = 0` rows are why AppleEvents
also failed from ssh on BOTH Macs — which is what made the lock look causal.
Two corrections to my own reasoning:
* `name`/`version`/`running` of an application are answered from the app bundle WITHOUT
sending an AppleEvent, so "app-level AE works, window-level hangs" was never evidence.
* the lock guard could wrongly stop a working rig (a locked screen was never shown to
break a granted AppleEvent). Removed the gate.
launch.sh now attempts the AppleScript and, only on failure, reads the TCC row for
(/bin/sh -> this browser's bundle id) and prints which of the three states it is:
denied / allowed-but-unresponsive / never-prompted.
Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
87 lines
3.9 KiB
Bash
Executable File
87 lines
3.9 KiB
Bash
Executable File
#!/bin/bash
|
|
# One-command Flow rinse launcher (macOS). Not headless — Brave must be logged in —
|
|
# but fully unattended once the tab is open and Auto-start is ticked in the popup.
|
|
#
|
|
# ./launch.sh https://labs.google/fx/tools/flow/project/XXXXXXXX
|
|
# FLOW_URL=... ./launch.sh
|
|
#
|
|
# Does three things: start the queue server if it's down, keep the Mac awake, and
|
|
# open OR focus a single Flow tab in Brave (never spawns duplicates).
|
|
#
|
|
# Scheduled every 10 min via launchd for self-healing (see install.sh).
|
|
# NOTE: launchd can't execute scripts inside ~/Documents (macOS TCC blocks it),
|
|
# so the agent runs a COPY at "~/Library/Application Support/flowrinse/" —
|
|
# after editing this file or local_server_example.py, re-run ./install.sh to resync.
|
|
|
|
set -e
|
|
DIR="$(cd "$(dirname "$0")" && pwd)"
|
|
URL="${1:-$FLOW_URL}"
|
|
if [ -z "$URL" ]; then
|
|
echo "Usage: ./launch.sh <flow_project_url> (or set FLOW_URL)"
|
|
exit 1
|
|
fi
|
|
|
|
# 1. queue server on 8017 (nc check avoids consuming a task via /next-task)
|
|
if ! nc -z localhost 8017 2>/dev/null; then
|
|
( cd "$DIR" && caffeinate -s python3 -B local_server_example.py >/tmp/flowrinse.log 2>&1 & )
|
|
echo "started queue server + caffeinate (log: /tmp/flowrinse.log)"
|
|
sleep 1
|
|
else
|
|
echo "queue server already up on 8017"
|
|
fi
|
|
|
|
# 2. open or focus ONE Flow tab (reuses an existing one so it can't double-run).
|
|
# Only `activate` (steal system focus) when opening fresh — on the 10-min launchd
|
|
# tick an existing tab is re-selected inside the browser without yanking you out of
|
|
# whatever you're doing. Selecting the tab also keeps Memory Saver from discarding it.
|
|
#
|
|
# Must name the browser the EXTENSION is loaded into. ultra = Brave, m3ultra = Chrome.
|
|
BROWSER="${FLOW_BROWSER:-Brave Browser}"
|
|
|
|
# `open location` hands the URL to the DEFAULT browser (Brave here) — never to $BROWSER.
|
|
# Make the tab inside the target app instead. Timeout so a wedged app can't hold the job:
|
|
# an Automation denial surfaces as a ~2min hang then -1712, NOT as a clean -1743.
|
|
if out=$(osascript <<OSA 2>&1
|
|
with timeout of 30 seconds
|
|
tell application "$BROWSER"
|
|
set found to false
|
|
repeat with w in windows
|
|
set i to 0
|
|
repeat with t in tabs of w
|
|
set i to i + 1
|
|
if (URL of t) contains "tools/flow/project" then
|
|
set active tab index of w to i
|
|
set index of w to 1
|
|
set found to true
|
|
end if
|
|
end repeat
|
|
end repeat
|
|
if not found then
|
|
activate
|
|
if (count of windows) = 0 then make new window
|
|
tell window 1 to make new tab with properties {URL:"$URL"}
|
|
end if
|
|
end tell
|
|
end timeout
|
|
OSA
|
|
); then
|
|
echo "$BROWSER focused on Flow. With Auto-start ticked, the rinse begins on load."
|
|
else
|
|
# Don't guess. The TCC row for (this launchd job's /bin/sh) -> (this browser) says which it is.
|
|
echo "cannot drive $BROWSER: $out"
|
|
BUNDLE=$(osascript -e "id of app \"$BROWSER\"" 2>/dev/null) # no AppleEvent — reads the bundle
|
|
DB="$HOME/Library/Application Support/com.apple.TCC/TCC.db"
|
|
AUTH=$(sqlite3 "$DB" "select auth_value from access where service='kTCCServiceAppleEvents'
|
|
and client='/bin/sh' and indirect_object_identifier='$BUNDLE';" 2>/dev/null)
|
|
case "$AUTH" in
|
|
0) echo " → Automation is DENIED for /bin/sh -> $BUNDLE (someone clicked Don't Allow)." \
|
|
"Fix: System Settings > Privacy & Security > Automation > sh > enable \"$BROWSER\"." ;;
|
|
2) echo " → Automation is ALLOWED, so $BROWSER itself is not answering AppleEvents." \
|
|
"Screen locked? $(ioreg -n Root -d1 -r | tr -d ' ' | grep -q '"CGSSessionScreenIsLocked"=Yes' \
|
|
&& echo yes || echo no). Try quitting and reopening $BROWSER." ;;
|
|
*) echo " → No Automation grant yet for /bin/sh -> $BUNDLE: a consent dialog is waiting on" \
|
|
"$(hostname -s)'s screen. Unlock it and click Allow." ;;
|
|
esac
|
|
exit 0 # not an error — the 10-min tick retries once a human fixes it
|
|
fi
|