conductor-remote 1.27.1 → 1.27.3

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-CzXmawS-.js"></script>
16
+ <script type="module" crossorigin src="/assets/index-DodAVrF-.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 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:"8c56dd890245566422e09621b1f83cd2"},{url:"assets/workbox-window.prod.es5-BBnX5xw4.js",revision:null},{url:"assets/index-DnE5ulTu.css",revision:null},{url:"assets/index-CzXmawS-.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\//]}))});
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\//]}))});
@@ -67,11 +67,112 @@ 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.
72
+ try
73
+ tell application "System Events" to tell process "Conductor"
74
+ return (count of windows) > 0
75
+ end tell
76
+ on error
77
+ return false
78
+ end try
79
+ end hasWindow
80
+
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)"
94
+ return ""
95
+ end scriptingBlocked
96
+
97
+ on conductorRunning()
98
+ try
99
+ tell application "System Events" to return (exists process "Conductor")
100
+ on error
101
+ return false
102
+ end try
103
+ end conductorRunning
104
+
105
+ on requireWindow()
106
+ -- 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"
113
+ end requireWindow
114
+
115
+ on waitForWindow(attempts)
116
+ -- "reopen" is the dock-click event — that is what recreates a closed window;
117
+ -- "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.
119
+ repeat with attempt from 1 to attempts
120
+ if my hasWindow() then return true
121
+ if attempt is 2 or attempt is 8 or attempt is 20 then
122
+ try
123
+ tell application "Conductor" to reopen
124
+ tell application "Conductor" to activate
125
+ end try
126
+ end if
127
+ delay 0.25
128
+ end repeat
129
+ return false
130
+ end waitForWindow
131
+
132
+ on activateConductor()
133
+ -- Conductor keeps running with every window closed (standard macOS: the red
134
+ -- button doesn't quit), and it may not be running at all. Both used to surface
135
+ -- as "Can't get window 1 of process Conductor. Invalid index." from whichever
136
+ -- handler happened to run first. So: launch-or-front it ("activate" starts it
137
+ -- when it isn't running), wait for a real window, then say what actually went
138
+ -- 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()
144
+ try
145
+ tell application "Conductor" to activate
146
+ on error errText
147
+ error "couldn't bring Conductor to the front: " & errText
148
+ end try
149
+ delay 0.4
150
+ -- Patience sized to what we're waiting for. A running app only has to redraw a
151
+ -- window (~4s is plenty, and the caller's osascript timeout still needs room
152
+ -- for the send itself). A cold launch is a whole app start, so it gets ~9s —
153
+ -- still inside the 20s script budget once the send's own delays are counted.
154
+ -- Anything slower fails with the message above and finds a warm app on retry.
155
+ set patience to 16
156
+ if not wasRunning then set patience to 36
157
+ if my waitForWindow(patience) then return
158
+ my requireWindow()
159
+ end activateConductor
160
+
161
+ on webArea()
162
+ -- The webview root: the window, then four nested containers. Guarded, or a
163
+ -- window that closed mid-run reappears as an "Invalid index" from a caller
164
+ -- that has nothing to do with windows.
165
+ my requireWindow()
166
+ tell application "System Events" to tell process "Conductor"
167
+ return UI element 1 of UI element 1 of UI element 1 of UI element 1 of window 1
168
+ end tell
169
+ end webArea
170
+
70
171
  on sidebarLinks()
71
172
  -- The sidebar rows are AXLinks named "<repo> <title> +adds -dels". They live
72
173
  -- two levels under the web area; collect them wherever they are at that depth.
174
+ set wa to my webArea()
73
175
  tell application "System Events" to tell process "Conductor"
74
- set wa to UI element 1 of UI element 1 of UI element 1 of UI element 1 of window 1
75
176
  set out to {}
76
177
  repeat with a in (UI elements of wa)
77
178
  try
@@ -156,6 +257,7 @@ on tabGroups()
156
257
  -- Level-order search, returning every tab group at the shallowest depth that
157
258
  -- has one (the chat strip and the terminal strip are siblings). Bounded: the
158
259
  -- pane sits ~5 levels down, and we must never descend into the transcript.
260
+ my requireWindow()
159
261
  tell application "System Events" to tell process "Conductor"
160
262
  set level to {window 1}
161
263
  set depth to 0
@@ -483,8 +585,8 @@ on setModel(wanted)
483
585
  -- otherwise also match "Sonnet 4.6 1M"), which must fail rather than guess.
484
586
  set chosen to missing value
485
587
  set loose to {}
588
+ set wa to my webArea()
486
589
  tell application "System Events" to tell process "Conductor"
487
- set wa to UI element 1 of UI element 1 of UI element 1 of UI element 1 of window 1
488
590
  repeat with m in (UI elements of wa whose role is "AXMenu")
489
591
  repeat with mi in (UI elements of m whose role is "AXMenuItem")
490
592
  set label to my firstLine(my tabLabel(mi))
@@ -529,8 +631,8 @@ on listModels()
529
631
  end tell
530
632
  delay 1.0
531
633
  set labels to {}
634
+ set wa to my webArea()
532
635
  tell application "System Events" to tell process "Conductor"
533
- set wa to UI element 1 of UI element 1 of UI element 1 of UI element 1 of window 1
534
636
  repeat with m in (UI elements of wa whose role is "AXMenu")
535
637
  repeat with mi in (UI elements of m whose role is "AXMenuItem")
536
638
  set end of labels to my firstLine(my tabLabel(mi))
@@ -592,6 +694,11 @@ function targetEnv(target) {
592
694
  /** osascript echoes the whole failing script back; keep just the reason for the phone. */
593
695
  function osaError(err) {
594
696
  const raw = err instanceof Error ? err.message : String(err);
697
+ // A timeout kill carries no execution error at all — its first line is
698
+ // "Command failed: osascript -e" plus the whole script, which is useless here.
699
+ if (err && typeof err === 'object' && 'killed' in err && err.killed) {
700
+ return 'Conductor took too long to respond';
701
+ }
595
702
  return raw.match(/execution error: (.+?) \(-?\d+\)/)?.[1] ?? raw.split('\n')[0];
596
703
  }
597
704
  /**
@@ -617,8 +724,7 @@ export class AppleScriptActuator {
617
724
  const script = `
618
725
  ${SELECT_CHAT_TAB_HANDLERS}
619
726
 
620
- tell application "Conductor" to activate
621
- delay 0.4
727
+ my activateConductor()
622
728
  my focusWorkspace()
623
729
  my selectChatTab()
624
730
  set promptText to my normalizeNewlines(do shell script "cat" & " " & quoted form of (system attribute "RELAY_PROMPT_FILE"))
@@ -680,8 +786,7 @@ export async function setAgentOptions(target, opts) {
680
786
  const script = `
681
787
  ${SELECT_CHAT_TAB_HANDLERS}
682
788
 
683
- tell application "Conductor" to activate
684
- delay 0.4
789
+ my activateConductor()
685
790
  my focusWorkspace()
686
791
  my selectChatTab()
687
792
  my applyAgentOptions()
@@ -709,8 +814,7 @@ export async function listAgentModels(target) {
709
814
  const script = `
710
815
  ${SELECT_CHAT_TAB_HANDLERS}
711
816
 
712
- tell application "Conductor" to activate
713
- delay 0.4
817
+ my activateConductor()
714
818
  my focusWorkspace()
715
819
  my selectChatTab()
716
820
  return my listModels()`.trim();
@@ -781,8 +885,7 @@ export async function newChat(workspace) {
781
885
  const script = `
782
886
  ${SELECT_CHAT_TAB_HANDLERS}
783
887
 
784
- tell application "Conductor" to activate
785
- delay 0.4
888
+ my activateConductor()
786
889
  my focusWorkspace()
787
890
  tell application "System Events"
788
891
  keystroke "t" using {command down}
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "conductor-remote",
3
- "version": "1.27.1",
3
+ "version": "1.27.3",
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.",