conductor-remote 1.39.0 → 1.40.0
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/assets/index-BhYD1Ar2.js +42 -0
- package/dist/index.html +1 -1
- package/dist/push-sw.js +32 -7
- package/dist/sw.js +1 -1
- package/dist-node/src/notify.js +14 -3
- package/dist-node/src/server.js +2 -2
- package/package.json +1 -1
- package/dist/assets/index-CHhZJBVH.js +0 -42
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-BhYD1Ar2.js"></script>
|
|
17
17
|
<link rel="stylesheet" crossorigin href="/assets/index-UopM0hHW.css">
|
|
18
18
|
<link rel="manifest" href="/manifest.webmanifest"></head>
|
|
19
19
|
<body>
|
package/dist/push-sw.js
CHANGED
|
@@ -13,6 +13,25 @@
|
|
|
13
13
|
// 2. **A tap focuses the existing window** rather than navigating it. The app is a
|
|
14
14
|
// token-gated SPA; `openWindow` on a live client would remount the whole thing and
|
|
15
15
|
// throw away in-progress composer text, so we focus and post a route instead.
|
|
16
|
+
// 3. **The route is also parked in Cache Storage**, because on iOS neither of the two
|
|
17
|
+
// direct routes survives. A backgrounded home-screen web app is resumed on whatever
|
|
18
|
+
// screen it was left on — `openWindow`'s path is ignored, and a `postMessage` to a
|
|
19
|
+
// frozen page is dropped (WebKit, reported from iOS 17.1 through 18.x and still
|
|
20
|
+
// open). The cache outlives both, so the app reads its target when it comes back to
|
|
21
|
+
// the front; see `usePushRouting` in web/src/hooks.ts.
|
|
22
|
+
|
|
23
|
+
/** One entry, overwritten per tap: only the newest tap can still be waiting to land. */
|
|
24
|
+
const ROUTE_CACHE = 'push-route'
|
|
25
|
+
const ROUTE_KEY = '/__push-route'
|
|
26
|
+
|
|
27
|
+
async function parkRoute(url) {
|
|
28
|
+
try {
|
|
29
|
+
const cache = await caches.open(ROUTE_CACHE)
|
|
30
|
+
await cache.put(ROUTE_KEY, new Response(JSON.stringify({ url, ts: Date.now() })))
|
|
31
|
+
} catch {
|
|
32
|
+
// Storage refused it (quota, a private window). The two direct routes below still stand.
|
|
33
|
+
}
|
|
34
|
+
}
|
|
16
35
|
|
|
17
36
|
self.addEventListener('push', event => {
|
|
18
37
|
const fallback = { title: 'Conductor Remote', body: 'Something changed in a workspace.', url: '/', tag: 'conductor' }
|
|
@@ -28,8 +47,9 @@ self.addEventListener('push', event => {
|
|
|
28
47
|
event.waitUntil(
|
|
29
48
|
self.registration.showNotification(data.title, {
|
|
30
49
|
body: data.body,
|
|
31
|
-
// Tagged per
|
|
32
|
-
// instead of stacking
|
|
50
|
+
// Tagged per chat by the relay: a chatty agent replaces its own notification
|
|
51
|
+
// instead of stacking, while a sibling chat keeps its own (they open different
|
|
52
|
+
// screens). `renotify` keeps the replacement audible.
|
|
33
53
|
tag: data.tag,
|
|
34
54
|
renotify: true,
|
|
35
55
|
icon: '/icon-192.png',
|
|
@@ -45,18 +65,23 @@ self.addEventListener('notificationclick', event => {
|
|
|
45
65
|
const url = (event.notification.data && event.notification.data.url) || '/'
|
|
46
66
|
event.waitUntil(
|
|
47
67
|
(async () => {
|
|
68
|
+
// Park first. Everything below can succeed and still leave the phone on the wrong
|
|
69
|
+
// screen, and this is the copy the app reads when it wakes up.
|
|
70
|
+
await parkRoute(url)
|
|
48
71
|
const clients = await self.clients.matchAll({ type: 'window', includeUncontrolled: true })
|
|
49
72
|
for (const client of clients) {
|
|
50
73
|
if (new URL(client.url).origin !== self.location.origin) continue
|
|
74
|
+
// Handled in web/src/hooks.ts (usePushRouting) — an in-app route change, so the
|
|
75
|
+
// token gate and React state survive the tap. Posted before the focus, since a
|
|
76
|
+
// refused focus is no reason to skip a message the page may well receive.
|
|
77
|
+
client.postMessage({ type: 'push-navigate', url })
|
|
51
78
|
try {
|
|
52
79
|
await client.focus()
|
|
53
|
-
// Handled in web/src/hooks.ts (usePushRouting) — an in-app route change,
|
|
54
|
-
// so the token gate and React state survive the tap.
|
|
55
|
-
client.postMessage({ type: 'push-navigate', url })
|
|
56
|
-
return
|
|
57
80
|
} catch {
|
|
58
|
-
// focus() can be refused (no user activation on some platforms)
|
|
81
|
+
// focus() can be refused (no user activation on some platforms); on iOS the
|
|
82
|
+
// system foregrounds the web app on the tap regardless.
|
|
59
83
|
}
|
|
84
|
+
return
|
|
60
85
|
}
|
|
61
86
|
await self.clients.openWindow(url)
|
|
62
87
|
})()
|
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 c=e=>i(e,o),t={module:{uri:o},exports:l,require:c};s[o]=Promise.all(n.map(e=>t[e]||c(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:"e1e682e2e5e88fa03b7808ae9db8e098"},{url:"index.html",revision:"1dca8269fa4358508f3ca90f0c216cdb"},{url:"assets/workbox-window.prod.es5-BBnX5xw4.js",revision:null},{url:"assets/index-UopM0hHW.css",revision:null},{url:"assets/index-BhYD1Ar2.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\//]}))});
|
package/dist-node/src/notify.js
CHANGED
|
@@ -218,6 +218,15 @@ export async function notifyDevice(id, message) {
|
|
|
218
218
|
export function deviceCount() {
|
|
219
219
|
return load().devices.length;
|
|
220
220
|
}
|
|
221
|
+
/**
|
|
222
|
+
* Where a tapped notification lands. The chat id rides along because the phone
|
|
223
|
+
* otherwise picks the tab itself (Conductor's active session, else the first one)
|
|
224
|
+
* — and on a multi-chat workspace that is rarely the chat that just finished.
|
|
225
|
+
* Kept here so the notifier and the parked-prompt queue can't drift apart.
|
|
226
|
+
*/
|
|
227
|
+
export function chatRoute(workspaceId, sessionId) {
|
|
228
|
+
return `/w/${workspaceId}?session=${encodeURIComponent(sessionId)}`;
|
|
229
|
+
}
|
|
221
230
|
/** Collapse a transcript entry to one lock-screen line: no code fences, no blank runs. */
|
|
222
231
|
function oneLine(text) {
|
|
223
232
|
return clip(text
|
|
@@ -287,9 +296,11 @@ async function fire(reads, sessionId, kind, state) {
|
|
|
287
296
|
const sent = await notifyAll({
|
|
288
297
|
title: state.repoName ? `${where} — ${state.repoName}` : where,
|
|
289
298
|
body,
|
|
290
|
-
// Per
|
|
291
|
-
|
|
292
|
-
|
|
299
|
+
// Per chat, so a chatty agent replaces its own notification instead of stacking —
|
|
300
|
+
// and two chats in one workspace stay separately tappable, since each now lands
|
|
301
|
+
// somewhere different.
|
|
302
|
+
tag: sessionId,
|
|
303
|
+
url: chatRoute(state.workspaceId, sessionId),
|
|
293
304
|
kind,
|
|
294
305
|
ts: Date.now()
|
|
295
306
|
});
|
package/dist-node/src/server.js
CHANGED
|
@@ -12,7 +12,7 @@ import { workspaceDiff } from "./git.js";
|
|
|
12
12
|
import { installLogCapture, isManaged, LOG_FILE_NAMES, logFiles, processStartedAt, recentLogs, redactSecrets, tailLogFile } from "./logbuf.js";
|
|
13
13
|
import { mergePr } from "./merge.js";
|
|
14
14
|
import { armNoSleep, disarmNoSleep, MAX_SECONDS as NOSLEEP_MAX_SECONDS, nosleepState, watchNoSleepExpiry } from "./nosleep.js";
|
|
15
|
-
import { notifyAll, notifyDevice, pushConfig, startNotifier, subscribeDevice, unsubscribeDevice } from "./notify.js";
|
|
15
|
+
import { chatRoute, notifyAll, notifyDevice, pushConfig, startNotifier, subscribeDevice, unsubscribeDevice } from "./notify.js";
|
|
16
16
|
import { ParkedPromptQueue } from "./parked.js";
|
|
17
17
|
import { attachPrStatus } from "./pr.js";
|
|
18
18
|
import { Reads } from "./reads.js";
|
|
@@ -288,7 +288,7 @@ const parkedPrompts = new ParkedPromptQueue(path.join(stateDir(), 'parked-prompt
|
|
|
288
288
|
body: error ? `Parked prompt failed: ${error}` : `Sent after unlock: ${preview}`,
|
|
289
289
|
// Per chat, so a second parked prompt replaces the first's notification.
|
|
290
290
|
tag: `parked-${entry.sessionId}`,
|
|
291
|
-
url:
|
|
291
|
+
url: chatRoute(entry.workspaceId, entry.sessionId),
|
|
292
292
|
kind: error ? 'error' : 'done',
|
|
293
293
|
ts: Date.now()
|
|
294
294
|
});
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "conductor-remote",
|
|
3
|
-
"version": "1.
|
|
3
|
+
"version": "1.40.0",
|
|
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.",
|