conductor-remote 1.27.3 → 1.27.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-DodAVrF-.js"></script>
16
+ <script type="module" crossorigin src="/assets/index-DgCZgSTk.js"></script>
17
17
  <link rel="stylesheet" crossorigin href="/assets/index-DnE5ulTu.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,i={};const n=(n,s)=>(n=new URL(n+".js",s).href,i[n]||new Promise(i=>{if("document"in self){const e=document.createElement("script");e.src=n,e.onload=i,document.head.appendChild(e)}else e=n,importScripts(n),i()}).then(()=>{let e=i[n];if(!e)throw new Error(`Module ${n} didn’t register its module`);return e}));self.define=(s,r)=>{const o=e||("document"in self?document.currentScript.src:"")||location.href;if(i[o])return;let c={};const l=e=>n(e,o),t={module:{uri:o},exports:c,require:l};i[o]=Promise.all(s.map(e=>t[e]||l(e))).then(e=>(r(...e),c))}}define(["./workbox-9c191d2f"],function(e){"use strict";self.addEventListener("message",e=>{e.data&&"SKIP_WAITING"===e.data.type&&self.skipWaiting()}),e.clientsClaim(),e.precacheAndRoute([{url:"self-heal.js",revision:"49bd63adb25a09341f8d2610e8bd3c76"},{url:"index.html",revision:"0d9b7c2e83c2d2ac18a82c2accca260a"},{url:"assets/workbox-window.prod.es5-BBnX5xw4.js",revision:null},{url:"assets/index-DodAVrF-.js",revision:null},{url:"assets/index-DnE5ulTu.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\//]}))});
1
+ if(!self.define){let e,i={};const n=(n,s)=>(n=new URL(n+".js",s).href,i[n]||new Promise(i=>{if("document"in self){const e=document.createElement("script");e.src=n,e.onload=i,document.head.appendChild(e)}else e=n,importScripts(n),i()}).then(()=>{let e=i[n];if(!e)throw new Error(`Module ${n} didn’t register its module`);return e}));self.define=(s,r)=>{const o=e||("document"in self?document.currentScript.src:"")||location.href;if(i[o])return;let l={};const c=e=>n(e,o),t={module:{uri:o},exports:l,require:c};i[o]=Promise.all(s.map(e=>t[e]||c(e))).then(e=>(r(...e),l))}}define(["./workbox-9c191d2f"],function(e){"use strict";self.addEventListener("message",e=>{e.data&&"SKIP_WAITING"===e.data.type&&self.skipWaiting()}),e.clientsClaim(),e.precacheAndRoute([{url:"self-heal.js",revision:"49bd63adb25a09341f8d2610e8bd3c76"},{url:"index.html",revision:"83ffcb8926c341d0bda6b343b1649bf7"},{url:"assets/workbox-window.prod.es5-BBnX5xw4.js",revision:null},{url:"assets/index-DnE5ulTu.css",revision:null},{url:"assets/index-DgCZgSTk.js",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\//]}))});
@@ -67,32 +67,39 @@ on splitLines(s)
67
67
  return parts
68
68
  end splitLines
69
69
 
70
- on hasWindow()
71
- -- Also false when the process itself is gone: "tell process" errors there.
70
+ on windowProbe()
71
+ -- One read, three outcomes, none of them guessed: {count, errNum, errText}.
72
+ -- count is -1 when macOS refused the read at all. Everything that wants to
73
+ -- know about windows goes through here, because "returned 0" and "refused to
74
+ -- answer" are different facts and only this handler still has both.
72
75
  try
73
76
  tell application "System Events" to tell process "Conductor"
74
- return (count of windows) > 0
77
+ set winCount to (count of windows)
75
78
  end tell
76
- on error
77
- return false
79
+ return {winCount, 0, ""}
80
+ on error errText number errNum
81
+ return {-1, errNum, errText}
78
82
  end try
83
+ end windowProbe
84
+
85
+ on hasWindow()
86
+ -- Also false when the process is gone or macOS refused: callers that only
87
+ -- need a boolean keep getting one. windowFailure() is what tells them why.
88
+ return (item 1 of my windowProbe()) > 0
79
89
  end hasWindow
80
90
 
81
- on scriptingBlocked()
82
- -- hasWindow() cannot tell "no window" from "macOS refused us" it swallows
83
- -- every error so without this a missing permission reads as "no open
84
- -- window" and sends the user off to open a window that is already open.
85
- -- These are the two separate grants the write path needs: Automation (may we
86
- -- talk to System Events at all) and Accessibility (may we read the UI tree).
87
- -- Returns "" when both are in place.
88
- try
89
- tell application "System Events" to set axTrusted to (UI elements enabled)
90
- on error errText number errNum
91
- return "macOS blocked the relay from controlling the UI (" & errNum & ") - grant Automation permission to the node binary running the relay in System Settings > Privacy & Security > Automation. " & errText
92
- end try
93
- if not axTrusted 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)"
91
+ on refusalReason(probe)
92
+ -- macOS's own words, matched on the error it actually returned rather than on
93
+ -- a capability flag we hope is accurate. "UI elements enabled" was the earlier
94
+ -- attempt at this and is not trustworthy it can report true for a process
95
+ -- that is not itself trusted, and then the refusal reappears downstream as
96
+ -- "no open window". These strings are the two grants the write path needs.
97
+ set errNum to item 2 of probe
98
+ set errText to item 3 of probe
99
+ 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
100
+ 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
94
101
  return ""
95
- end scriptingBlocked
102
+ end refusalReason
96
103
 
97
104
  on conductorRunning()
98
105
  try
@@ -102,20 +109,51 @@ on conductorRunning()
102
109
  end try
103
110
  end conductorRunning
104
111
 
105
- on requireWindow()
112
+ on windowFailure()
113
+ -- "" when a window is there; otherwise why not, in words the phone can act on.
106
114
  -- ASCII on purpose: these reach the phone, and osascript decodes -e by the
107
- -- caller's locale, which a LaunchAgent doesn't set.
108
- if my hasWindow() then return
109
- set blocked to my scriptingBlocked()
110
- if blocked is not "" then error blocked
111
- if not (my conductorRunning()) then error "Conductor is not running - the relay started it, but it did not come up in time. Try again in a few seconds."
112
- error "Conductor has no open window - open it on your Mac and try again"
115
+ -- caller's locale, which a LaunchAgent doesn't set. The last branch carries
116
+ -- the raw error number and text on purpose — an unrecognised refusal must
117
+ -- arrive as itself, not as the most plausible-sounding of the known causes.
118
+ set probe to my windowProbe()
119
+ set winCount to item 1 of probe
120
+ if winCount > 0 then return ""
121
+ if winCount is 0 then return "Conductor has no open window - open it on your Mac and try again"
122
+ set refusal to my refusalReason(probe)
123
+ if refusal is not "" then return refusal
124
+ if not (my conductorRunning()) then return "Conductor is not running - the relay started it, but it did not come up in time. Try again in a few seconds."
125
+ return "couldn't read Conductor's windows (" & (item 2 of probe) & "): " & (item 3 of probe)
126
+ end windowFailure
127
+
128
+ on requireWindow()
129
+ set reason to my windowFailure()
130
+ if reason is not "" then error reason
113
131
  end requireWindow
114
132
 
133
+ on openNewWindow()
134
+ -- Last resort when "reopen" draws nothing: press the app's own New Window.
135
+ -- Exact match only — "New Workspace" is a different command and would create a
136
+ -- workspace nobody asked for — so an app without that item fails closed and
137
+ -- silent, leaving windowFailure() to report the honest "no open window".
138
+ try
139
+ tell application "System Events" to tell process "Conductor"
140
+ repeat with topMenu in (menu bar items of menu bar 1)
141
+ try
142
+ click (first menu item of menu 1 of topMenu whose name is "New Window")
143
+ return true
144
+ end try
145
+ end repeat
146
+ end tell
147
+ end try
148
+ return false
149
+ end openNewWindow
150
+
115
151
  on waitForWindow(attempts)
116
152
  -- "reopen" is the dock-click event — that is what recreates a closed window;
117
153
  -- "activate" on its own does not. Nudge a few times across the wait: a cold
118
- -- launch can reach "process exists" long before it draws anything.
154
+ -- launch can reach "process exists" long before it draws anything. If reopen
155
+ -- has drawn nothing by ~3s, the app isn't answering that event at all, so
156
+ -- escalate to its own menu item rather than repeating what already failed.
119
157
  repeat with attempt from 1 to attempts
120
158
  if my hasWindow() then return true
121
159
  if attempt is 2 or attempt is 8 or attempt is 20 then
@@ -124,6 +162,7 @@ on waitForWindow(attempts)
124
162
  tell application "Conductor" to activate
125
163
  end try
126
164
  end if
165
+ if attempt is 12 or attempt is 28 then my openNewWindow()
127
166
  delay 0.25
128
167
  end repeat
129
168
  return false
@@ -136,11 +175,13 @@ on activateConductor()
136
175
  -- handler happened to run first. So: launch-or-front it ("activate" starts it
137
176
  -- when it isn't running), wait for a real window, then say what actually went
138
177
  -- wrong in words the phone can act on.
139
- -- Permissions first: a blocked relay reads as "no process, no window" from
140
- -- every probe below, and waiting 9s to say the wrong thing helps nobody.
141
- set blocked to my scriptingBlocked()
142
- if blocked is not "" then error blocked
143
- set wasRunning to my conductorRunning()
178
+ -- Permissions first: a refusal reads as "no process, no window" from every
179
+ -- probe below, and waiting out the patience budget to say the wrong thing
180
+ -- helps nobody. A refusal is the one failure launching can't fix.
181
+ set firstProbe to my windowProbe()
182
+ set refusal to my refusalReason(firstProbe)
183
+ if refusal is not "" then error refusal
184
+ set wasRunning to (item 1 of firstProbe) >= 0
144
185
  try
145
186
  tell application "Conductor" to activate
146
187
  on error errText
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "conductor-remote",
3
- "version": "1.27.3",
3
+ "version": "1.27.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.",