conductor-remote 1.34.3 → 1.34.4
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.
package/dist/index.html
CHANGED
|
@@ -13,7 +13,7 @@
|
|
|
13
13
|
<title>Conductor Remote</title>
|
|
14
14
|
<!-- Runs before the module bundle so it can catch a stale shell that fails to boot. -->
|
|
15
15
|
<script src="/self-heal.js"></script>
|
|
16
|
-
<script type="module" crossorigin src="/assets/index-
|
|
16
|
+
<script type="module" crossorigin src="/assets/index-CUGYKt7R.js"></script>
|
|
17
17
|
<link rel="stylesheet" crossorigin href="/assets/index--7Dp2aq8.css">
|
|
18
18
|
<link rel="manifest" href="/manifest.webmanifest"></head>
|
|
19
19
|
<body>
|
package/dist/sw.js
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
if(!self.define){let e,s={};const i=(i,n)=>(i=new URL(i+".js",n).href,s[i]||new Promise(s=>{if("document"in self){const e=document.createElement("script");e.src=i,e.onload=s,document.head.appendChild(e)}else e=i,importScripts(i),s()}).then(()=>{let e=s[i];if(!e)throw new Error(`Module ${i} didn’t register its module`);return e}));self.define=(n,r)=>{const o=e||("document"in self?document.currentScript.src:"")||location.href;if(s[o])return;let l={};const
|
|
1
|
+
if(!self.define){let e,s={};const i=(i,n)=>(i=new URL(i+".js",n).href,s[i]||new Promise(s=>{if("document"in self){const e=document.createElement("script");e.src=i,e.onload=s,document.head.appendChild(e)}else e=i,importScripts(i),s()}).then(()=>{let e=s[i];if(!e)throw new Error(`Module ${i} didn’t register its module`);return e}));self.define=(n,r)=>{const o=e||("document"in self?document.currentScript.src:"")||location.href;if(s[o])return;let l={};const t=e=>i(e,o),c={module:{uri:o},exports:l,require:t};s[o]=Promise.all(n.map(e=>c[e]||t(e))).then(e=>(r(...e),l))}}define(["./workbox-9c191d2f"],function(e){"use strict";importScripts("/push-sw.js"),self.addEventListener("message",e=>{e.data&&"SKIP_WAITING"===e.data.type&&self.skipWaiting()}),e.clientsClaim(),e.precacheAndRoute([{url:"self-heal.js",revision:"49bd63adb25a09341f8d2610e8bd3c76"},{url:"push-sw.js",revision:"890f6a70e97d144f4d025254e90892a1"},{url:"index.html",revision:"aa7c74f617001021bcfa69ef22c8a2b4"},{url:"assets/workbox-window.prod.es5-BBnX5xw4.js",revision:null},{url:"assets/index-CUGYKt7R.js",revision:null},{url:"assets/index--7Dp2aq8.css",revision:null},{url:"apple-touch-icon.png",revision:"2b9301416b880d45d4bb655f2600d1f2"},{url:"icon-192.png",revision:"c5e01ac58768627e18ee7b8b6a9239ef"},{url:"icon-512.png",revision:"a40638c55e310312457a621c9a0002c8"},{url:"icon-maskable-512.png",revision:"a40638c55e310312457a621c9a0002c8"},{url:"icon.svg",revision:"c1aee186821798733dd477e69a0ef243"},{url:"manifest.webmanifest",revision:"cf88fbc5755108a7fe0616fa160a8a15"}],{}),e.cleanupOutdatedCaches(),e.registerRoute(new e.NavigationRoute(e.createHandlerBoundToURL("/index.html"),{denylist:[/^\/api\//]}))});
|
|
@@ -73,10 +73,17 @@ on windowProbe()
|
|
|
73
73
|
-- count is -1 when macOS refused the read at all. Everything that wants to
|
|
74
74
|
-- know about windows goes through here, because "returned 0" and "refused to
|
|
75
75
|
-- answer" are different facts and only this handler still has both.
|
|
76
|
+
-- The timeout is load-bearing: a wedged Conductor (seen live after a restart
|
|
77
|
+
-- collided with a relaunch) answers deep links but hangs every AX read, and
|
|
78
|
+
-- without a cap this call blocks until the node-side ceiling kills the whole
|
|
79
|
+
-- run as "took too long" — 28s of silence instead of a named cause. 6s turns
|
|
80
|
+
-- that into error -1712, which refusalReason maps to words.
|
|
76
81
|
try
|
|
77
|
-
|
|
78
|
-
|
|
79
|
-
|
|
82
|
+
with timeout of 6 seconds
|
|
83
|
+
tell application "System Events" to tell process "Conductor"
|
|
84
|
+
set winCount to (count of windows)
|
|
85
|
+
end tell
|
|
86
|
+
end timeout
|
|
80
87
|
return {winCount, 0, ""}
|
|
81
88
|
on error errText number errNum
|
|
82
89
|
return {-1, errNum, errText}
|
|
@@ -99,6 +106,7 @@ on refusalReason(probe)
|
|
|
99
106
|
set errText to item 3 of probe
|
|
100
107
|
if errText contains "assistive access" then return "the relay is not trusted for Accessibility - grant it to the node binary running the relay in System Settings > Privacy & Security > Accessibility, then restart the relay (upgrading node silently revokes it). macOS said: " & errText
|
|
101
108
|
if errNum is -1743 or errText contains "Not authorized" then return "macOS blocked the relay from controlling the UI - grant Automation permission to the node binary running the relay in System Settings > Privacy & Security > Automation. macOS said: " & errText
|
|
109
|
+
if errNum is -1712 then return "Conductor stopped answering UI reads (the Accessibility query timed out) - the app looks wedged even though it may still process deep links. Force-quit Conductor on your Mac and open it again; if it repeats with a healthy Conductor, System Events is stuck - run: killall 'System Events'"
|
|
102
110
|
return ""
|
|
103
111
|
end refusalReason
|
|
104
112
|
|
|
@@ -143,14 +151,50 @@ on menuTitles()
|
|
|
143
151
|
end try
|
|
144
152
|
end menuTitles
|
|
145
153
|
|
|
154
|
+
on serverWindowCount()
|
|
155
|
+
-- Second opinion from the window server, because the Accessibility tree only
|
|
156
|
+
-- shows windows on the *current* Space: a full-screen Conductor (which owns its
|
|
157
|
+
-- own Space) or a Mac sitting at the lock screen reads as "no window" from AX
|
|
158
|
+
-- while the window very much exists — and acting on the AX answer alone once
|
|
159
|
+
-- quit a Conductor whose window the user had left open all along.
|
|
160
|
+
-- CGWindowListCopyWindowInfo(kCGWindowListOptionAll) sees every Space; owner
|
|
161
|
+
-- name and layer are readable without the Screen Recording grant (only window
|
|
162
|
+
-- *titles* are gated). Layer 0 keeps it to real windows. -1 = the probe itself
|
|
163
|
+
-- failed, which callers must treat as "no opinion", never as "no window".
|
|
164
|
+
set jxa to "ObjC.import('CoreGraphics'); const w = ObjC.deepUnwrap($.CFBridgingRelease($.CGWindowListCopyWindowInfo(0, 0))) || []; w.filter(x => x.kCGWindowOwnerName === 'Conductor' && x.kCGWindowLayer === 0).length"
|
|
165
|
+
try
|
|
166
|
+
return (do shell script "osascript -l JavaScript -e " & quoted form of jxa) as integer
|
|
167
|
+
on error
|
|
168
|
+
return -1
|
|
169
|
+
end try
|
|
170
|
+
end serverWindowCount
|
|
171
|
+
|
|
172
|
+
on screenLocked()
|
|
173
|
+
-- "locked" / "unlocked" / "unknown". CGSessionCopyCurrentDictionary carries
|
|
174
|
+
-- CGSSessionScreenIsLocked = 1 while the lock screen is up and omits the key
|
|
175
|
+
-- entirely when it is not — same stdlib JXA channel as serverWindowCount.
|
|
176
|
+
-- This matters because the lock screen is the product's home ground: sends
|
|
177
|
+
-- come from a phone precisely when nobody is at the Mac, so "is the lock up"
|
|
178
|
+
-- is the difference between a state a restart can fix and one it provably
|
|
179
|
+
-- makes worse (see the restart gate in activateConductor).
|
|
180
|
+
set jxa to "ObjC.import('CoreGraphics'); const d = ObjC.deepUnwrap($.CFBridgingRelease($.CGSessionCopyCurrentDictionary())) || {}; d.CGSSessionScreenIsLocked ? 'locked' : 'unlocked'"
|
|
181
|
+
try
|
|
182
|
+
return do shell script "osascript -l JavaScript -e " & quoted form of jxa
|
|
183
|
+
on error
|
|
184
|
+
return "unknown"
|
|
185
|
+
end try
|
|
186
|
+
end screenLocked
|
|
187
|
+
|
|
146
188
|
on windowEvidence()
|
|
147
189
|
-- Zero windows is a dead end without knowing what the AX tree *does* show, and
|
|
148
190
|
-- guessing the next thing to press has already cost a round trip (there is no
|
|
149
191
|
-- "New Window" item — Conductor is single-window). So the error carries the
|
|
150
|
-
-- evidence instead: who macOS thinks Conductor is,
|
|
192
|
+
-- evidence instead: who macOS thinks Conductor is, what its menus offer, how
|
|
193
|
+
-- many windows the window server counts across all Spaces (AX only sees the
|
|
194
|
+
-- current one), and whether the lock screen is up.
|
|
151
195
|
set procs to my processWindowCounts()
|
|
152
196
|
set titles to my menuTitles()
|
|
153
|
-
set ev to ""
|
|
197
|
+
set ev to " [window server: " & my serverWindowCount() & "; screen: " & my screenLocked() & "]"
|
|
154
198
|
if (count of procs) > 0 then set ev to ev & " [processes: " & my joinList(procs, ", ") & "]"
|
|
155
199
|
if (count of titles) > 0 then set ev to ev & " [menus: " & my joinList(titles, ", ") & "]"
|
|
156
200
|
return ev
|
|
@@ -282,6 +326,22 @@ on activateConductor()
|
|
|
282
326
|
-- used to drop it, which made a repeating no-window failure undebuggable
|
|
283
327
|
-- from the log alone.
|
|
284
328
|
set ev to my windowEvidence()
|
|
329
|
+
set lockState to my screenLocked()
|
|
330
|
+
-- AX saying "no window" is not the same as there being no window: full
|
|
331
|
+
-- screen on another Space and the lock screen both hide a live window from
|
|
332
|
+
-- AX, and restarting then destroys a window the user left open (measured
|
|
333
|
+
-- live: exactly that loop wedged Conductor for a whole evening). Only the
|
|
334
|
+
-- window server can tell the difference, so a window it CAN see blocks the
|
|
335
|
+
-- restart — this is a human's problem, said in words, not the relay's.
|
|
336
|
+
if my serverWindowCount() > 0 then
|
|
337
|
+
if lockState is "locked" then error "The Mac is locked - Conductor's window is open behind the lock screen, where the relay can't reach it. Unlock the Mac and send again." & ev
|
|
338
|
+
error "Conductor's window exists but is not reachable - it is probably full screen on another Space. Take Conductor out of full screen, then send again." & ev
|
|
339
|
+
end if
|
|
340
|
+
-- No window anywhere and the lock screen up: don't restart. Every relaunch
|
|
341
|
+
-- fired behind the lock screen in the live incident came up windowless, and
|
|
342
|
+
-- the last one came up wedged — answering deep links, hanging every AX
|
|
343
|
+
-- read. A restart here is not a lever, it is how the wreckage happened.
|
|
344
|
+
if lockState is "locked" then error "The Mac is locked and Conductor has no window. Relaunching behind the lock screen is what leaves it wedged, so the relay won't - unlock the Mac and send again." & ev
|
|
285
345
|
set restartError to my restartConductor()
|
|
286
346
|
if restartError is not "" then error restartError & ev
|
|
287
347
|
error "Conductor was running with no window and ignored both reopen and a Dock click, so the relay restarted it. Give it a few seconds and send again." & ev
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "conductor-remote",
|
|
3
|
-
"version": "1.34.
|
|
3
|
+
"version": "1.34.4",
|
|
4
4
|
"type": "module",
|
|
5
5
|
"packageManager": "yarn@4.15.0",
|
|
6
6
|
"description": "Phone control panel for local Conductor agents. Reads ride SQLite + git; prompts ride Conductor's own dispatch path.",
|