thinkpool-pair 0.7.323 → 0.7.325
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/package.json +1 -1
- package/service.mjs +22 -7
package/package.json
CHANGED
package/service.mjs
CHANGED
|
@@ -62,6 +62,15 @@ const cacheWipe = (cacheRoot) => `rm -rf ${shq(path.join(cacheRoot, '_npx'))}/*
|
|
|
62
62
|
// deliberate (re-run install-service). `--auto-update` opts back into @latest tracking.
|
|
63
63
|
const VERSION = (() => { try { return JSON.parse(fs.readFileSync(new URL('./package.json', import.meta.url), 'utf8')).version } catch { return 'latest' } })()
|
|
64
64
|
|
|
65
|
+
// Connected account readiness is deliberately stronger than "the OS process is
|
|
66
|
+
// running": the supervisor must receive its own Supabase presence echo first.
|
|
67
|
+
// That echo has taken ~62s on a real Linux host, so the old 30s handoff window
|
|
68
|
+
// killed a healthy replacement and rolled back forever. Keep the external helper
|
|
69
|
+
// alive long enough for one slow Realtime generation plus five stable PID probes.
|
|
70
|
+
const SERVICE_PROOF_POLLS = 180
|
|
71
|
+
const SERVICE_PROOF_SLEEP_SECONDS = '0.5'
|
|
72
|
+
const SERVICE_CONFIRM_TIMEOUT_MS = 200_000
|
|
73
|
+
|
|
65
74
|
// Resolve the real npx next to the current node, so the service stays seamless:
|
|
66
75
|
// it runs `npx -y thinkpool-pair@latest …`, always picking up the newest publish
|
|
67
76
|
// with no re-install. Absolute path + injected PATH so it works under launchd /
|
|
@@ -219,7 +228,7 @@ StandardError=append:${log}
|
|
|
219
228
|
[Install]
|
|
220
229
|
WantedBy=default.target
|
|
221
230
|
`
|
|
222
|
-
return { file, content, logDir, post: ['systemctl --user daemon-reload', `systemctl --user enable ${label(room)}.service`, `systemctl --user restart ${label(room)}.service`], note: 'Enabled as a systemd --user service. Run `loginctl enable-linger $USER` once to keep it running after logout.' }
|
|
231
|
+
return { file, content, logDir, post: ['systemctl --user daemon-reload', `systemctl --user enable ${label(room)}.service`, `systemctl --user restart ${label(room)}.service`], expectedRuntime: runtimeEntry || verSpec, note: 'Enabled as a systemd --user service. Run `loginctl enable-linger $USER` once to keep it running after logout.' }
|
|
223
232
|
}
|
|
224
233
|
|
|
225
234
|
if (platform === 'win32') {
|
|
@@ -323,8 +332,11 @@ export function buildDarwinReloadHandoff({ targetLabel, targetFile, stagedFile,
|
|
|
323
332
|
'cp "$staged_file" "$target_file"',
|
|
324
333
|
'launchctl enable "$dom/$target" 2>/dev/null || true',
|
|
325
334
|
'for i in $(seq 1 30); do launchctl bootstrap "$dom" "$target_file" 2>/dev/null && break; sleep 0.3; done',
|
|
326
|
-
'
|
|
327
|
-
|
|
335
|
+
'printf "update_handoff_start target=%s version=%s timeout_s=90\\n" "$target" "$version"',
|
|
336
|
+
'for i in $(seq 1 ' + SERVICE_PROOF_POLLS + '); do snapshot="$(launchctl print "$dom/$target" 2>/dev/null || true)"; pid="$(printf "%s\\n" "$snapshot" | sed -n "s/^[[:space:]]*pid = \\([0-9][0-9]*\\)[[:space:]]*$/\\1/p" | head -1)"; ready_ok=1; if [ "$requires_ready" = 1 ]; then ready_ok=0; [ -f "$ready" ] && grep -F "\\"pid\\":$pid" "$ready" >/dev/null 2>&1 && grep -F "\\"version\\":\\"$version\\"" "$ready" >/dev/null 2>&1 && ready_ok=1; fi; if [ -n "$pid" ] && [ "$ready_ok" = 1 ] && printf "%s\\n" "$snapshot" | grep -F -- "$expected" >/dev/null && printf "%s\\n" "$snapshot" | grep -F "state = running" >/dev/null; then if [ "$pid" = "$live_pid" ]; then stable=$((stable+1)); else live_pid="$pid"; stable=1; fi; if [ "$stable" -ge 5 ]; then ok=1; break; fi; else live_pid=""; stable=0; fi; sleep ' + SERVICE_PROOF_SLEEP_SECONDS + '; done',
|
|
337
|
+
'if [ "$ok" != 1 ]; then ready_state=missing; [ -f "$ready" ] && ready_state=present; printf "update_handoff_verify_timeout target=%s version=%s last_pid=%s ready=%s\\n" "$target" "$version" "$live_pid" "$ready_state"; fi',
|
|
338
|
+
`if [ "$ok" = 1 ]; then printf '%s\\n' '${JSON.stringify({ ok: true, version: String(version), target: String(targetLabel) })}' > "$tmp"; else rollback=0; if [ "$had_previous" = 1 ]; then launchctl bootout "$dom/$target" 2>/dev/null || true; for i in $(seq 1 40); do launchctl print "$dom/$target" >/dev/null 2>&1 || break; sleep 0.2; done; if [ "$requires_ready" = 1 ]; then rm -f "$ready"; fi; cp "$backup_file" "$target_file"; launchctl enable "$dom/$target" 2>/dev/null || true; bootstrapped=0; for i in $(seq 1 30); do if launchctl bootstrap "$dom" "$target_file" 2>/dev/null; then bootstrapped=1; break; fi; sleep 0.3; done; if [ "$bootstrapped" = 1 ]; then rollback_pid=""; rollback_stable=0; for i in $(seq 1 ${SERVICE_PROOF_POLLS}); do snapshot="$(launchctl print "$dom/$target" 2>/dev/null || true)"; pid="$(printf "%s\\n" "$snapshot" | sed -n "s/^[[:space:]]*pid = \\([0-9][0-9]*\\)[[:space:]]*$/\\1/p" | head -1)"; ready_ok=1; if [ "$requires_ready" = 1 ]; then ready_ok=0; [ -f "$ready" ] && grep -F "\\"pid\\":$pid" "$ready" >/dev/null 2>&1 && ready_ok=1; fi; if [ -n "$pid" ] && [ "$ready_ok" = 1 ] && printf "%s\\n" "$snapshot" | grep -F "state = running" >/dev/null; then if [ "$pid" = "$rollback_pid" ]; then rollback_stable=$((rollback_stable+1)); else rollback_pid="$pid"; rollback_stable=1; fi; if [ "$rollback_stable" -ge 5 ]; then rollback=1; break; fi; else rollback_pid=""; rollback_stable=0; fi; sleep ${SERVICE_PROOF_SLEEP_SECONDS}; done; fi; else launchctl bootout "$dom/$target" 2>/dev/null || true; rm -f "$target_file"; fi; if [ "$rollback" = 1 ]; then printf '%s\\n' '${JSON.stringify({ ok: false, version: String(version), target: String(targetLabel), error: 'new runtime not confirmed within 90s; previous service restored and ready', rolledBack: true })}' > "$tmp"; else printf '%s\\n' '${JSON.stringify({ ok: false, version: String(version), target: String(targetLabel), error: 'new runtime not confirmed within 90s and ready rollback failed', rolledBack: false })}' > "$tmp"; fi; fi`,
|
|
339
|
+
'printf "update_handoff_complete target=%s version=%s ok=%s\\n" "$target" "$version" "$ok"',
|
|
328
340
|
'mv "$tmp" "$status"',
|
|
329
341
|
'rm -f "$staged_file" "$backup_file" "$helper_file"',
|
|
330
342
|
'launchctl bootout "$dom/$helper" >/dev/null 2>&1 || true',
|
|
@@ -380,8 +392,11 @@ export function buildLinuxReloadHandoff({ targetLabel, targetFile, stagedFile, e
|
|
|
380
392
|
'systemctl --user restart "$unit" >/dev/null 2>&1 || true',
|
|
381
393
|
'live_pid=""',
|
|
382
394
|
'stable=0',
|
|
383
|
-
'
|
|
384
|
-
|
|
395
|
+
'printf "update_handoff_start target=%s version=%s timeout_s=90\\n" "$target" "$version"',
|
|
396
|
+
'for i in $(seq 1 ' + SERVICE_PROOF_POLLS + '); do snapshot="$(systemctl --user show "$unit" --property=ActiveState --property=MainPID --property=ExecStart 2>/dev/null || true)"; pid="$(printf "%s\\n" "$snapshot" | sed -n "s/^MainPID=\\([1-9][0-9]*\\)$/\\1/p" | head -1)"; ready_ok=1; if [ "$requires_ready" = 1 ]; then ready_ok=0; [ -f "$ready" ] && grep -F "\\"pid\\":$pid" "$ready" >/dev/null 2>&1 && grep -F "\\"version\\":\\"$version\\"" "$ready" >/dev/null 2>&1 && ready_ok=1; fi; if [ -n "$pid" ] && [ "$ready_ok" = 1 ] && printf "%s\\n" "$snapshot" | grep -F "ActiveState=active" >/dev/null && printf "%s\\n" "$snapshot" | grep -F -- "$expected" >/dev/null; then if [ "$pid" = "$live_pid" ]; then stable=$((stable+1)); else live_pid="$pid"; stable=1; fi; if [ "$stable" -ge 5 ]; then ok=1; break; fi; else live_pid=""; stable=0; fi; sleep ' + SERVICE_PROOF_SLEEP_SECONDS + '; done',
|
|
397
|
+
'if [ "$ok" != 1 ]; then ready_state=missing; [ -f "$ready" ] && ready_state=present; printf "update_handoff_verify_timeout target=%s version=%s last_pid=%s ready=%s\\n" "$target" "$version" "$live_pid" "$ready_state"; fi',
|
|
398
|
+
`if [ "$ok" = 1 ]; then printf '%s\\n' '${JSON.stringify({ ok: true, version: String(version), target: String(targetLabel) })}' > "$tmp"; else rollback=0; if [ "$had_previous" = 1 ]; then systemctl --user stop "$unit" 2>/dev/null || true; if [ "$requires_ready" = 1 ]; then rm -f "$ready"; fi; cp "$backup_file" "$target_file"; systemctl --user daemon-reload; systemctl --user enable "$unit" >/dev/null 2>&1 || true; systemctl --user restart "$unit" >/dev/null 2>&1 || true; rollback_pid=""; rollback_stable=0; for i in $(seq 1 ${SERVICE_PROOF_POLLS}); do snapshot="$(systemctl --user show "$unit" --property=ActiveState --property=MainPID 2>/dev/null || true)"; pid="$(printf "%s\\n" "$snapshot" | sed -n "s/^MainPID=\\([1-9][0-9]*\\)$/\\1/p" | head -1)"; ready_ok=1; if [ "$requires_ready" = 1 ]; then ready_ok=0; [ -f "$ready" ] && grep -F "\\"pid\\":$pid" "$ready" >/dev/null 2>&1 && ready_ok=1; fi; if [ -n "$pid" ] && [ "$ready_ok" = 1 ] && printf "%s\\n" "$snapshot" | grep -F "ActiveState=active" >/dev/null; then if [ "$pid" = "$rollback_pid" ]; then rollback_stable=$((rollback_stable+1)); else rollback_pid="$pid"; rollback_stable=1; fi; if [ "$rollback_stable" -ge 5 ]; then rollback=1; break; fi; else rollback_pid=""; rollback_stable=0; fi; sleep ${SERVICE_PROOF_SLEEP_SECONDS}; done; else systemctl --user stop "$unit" 2>/dev/null || true; rm -f "$target_file"; systemctl --user daemon-reload; fi; if [ "$rollback" = 1 ]; then printf '%s\\n' '${JSON.stringify({ ok: false, version: String(version), target: String(targetLabel), error: 'new runtime not confirmed within 90s; previous service restored and ready', rolledBack: true })}' > "$tmp"; else printf '%s\\n' '${JSON.stringify({ ok: false, version: String(version), target: String(targetLabel), error: 'new runtime not confirmed within 90s and ready rollback failed', rolledBack: false })}' > "$tmp"; fi; fi`,
|
|
399
|
+
'printf "update_handoff_complete target=%s version=%s ok=%s\\n" "$target" "$version" "$ok"',
|
|
385
400
|
'mv "$tmp" "$status"',
|
|
386
401
|
'rm -f "$staged_file" "$backup_file"',
|
|
387
402
|
'exit "$((1-ok))"',
|
|
@@ -598,7 +613,7 @@ export async function installAndConfirmService(room, cmdArgs = [], {
|
|
|
598
613
|
},
|
|
599
614
|
now = Date.now,
|
|
600
615
|
sleep = (ms) => new Promise((resolve) => setTimeout(resolve, ms)),
|
|
601
|
-
timeoutMs =
|
|
616
|
+
timeoutMs = SERVICE_CONFIRM_TIMEOUT_MS,
|
|
602
617
|
pollMs = 250,
|
|
603
618
|
stderr = process.stderr,
|
|
604
619
|
} = {}) {
|
|
@@ -746,7 +761,7 @@ export async function updateAndConfirmService(room, {
|
|
|
746
761
|
},
|
|
747
762
|
now = Date.now,
|
|
748
763
|
sleep = (ms) => new Promise((resolve) => setTimeout(resolve, ms)),
|
|
749
|
-
timeoutMs =
|
|
764
|
+
timeoutMs = SERVICE_CONFIRM_TIMEOUT_MS,
|
|
750
765
|
pollMs = 250,
|
|
751
766
|
stderr = process.stderr,
|
|
752
767
|
} = {}) {
|