omnius 1.0.604 → 1.0.605
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.js +156 -29
- package/dist/update-worker.js +294690 -0
- package/npm-shrinkwrap.json +2 -2
- package/package.json +1 -1
package/dist/index.js
CHANGED
|
@@ -363,6 +363,7 @@ __export(update_service_exports, {
|
|
|
363
363
|
UpdateInProgressError: () => UpdateInProgressError,
|
|
364
364
|
assertExactUpdateTarget: () => assertExactUpdateTarget,
|
|
365
365
|
inspectGlobalOmniusInstall: () => inspectGlobalOmniusInstall,
|
|
366
|
+
readReconciledUpdateState: () => readReconciledUpdateState,
|
|
366
367
|
readUpdateLogTail: () => readUpdateLogTail,
|
|
367
368
|
readUpdateState: () => readUpdateState,
|
|
368
369
|
releaseUpdateLock: () => releaseUpdateLock,
|
|
@@ -373,6 +374,7 @@ __export(update_service_exports, {
|
|
|
373
374
|
updateStateFileIsPrivate: () => updateStateFileIsPrivate,
|
|
374
375
|
updateStateIsFreshRunning: () => updateStateIsFreshRunning,
|
|
375
376
|
updateStatusSnapshot: () => updateStatusSnapshot,
|
|
377
|
+
waitForUpdateTransaction: () => waitForUpdateTransaction,
|
|
376
378
|
writeUpdateState: () => writeUpdateState
|
|
377
379
|
});
|
|
378
380
|
import { spawn, spawnSync } from "node:child_process";
|
|
@@ -613,6 +615,68 @@ function transition(current, patch, paths) {
|
|
|
613
615
|
function permissionRemediation(evidence) {
|
|
614
616
|
return /EACCES|EPERM|permission denied/i.test(evidence) ? "The discovered npm global prefix is not writable. Configure a user-owned npm prefix or rerun the explicit update from a privileged terminal; Omnius never silently elevates." : void 0;
|
|
615
617
|
}
|
|
618
|
+
function installGlobalPackageStreaming(input) {
|
|
619
|
+
return new Promise((resolve87) => {
|
|
620
|
+
const stderrTail = [];
|
|
621
|
+
let settled = false;
|
|
622
|
+
let timedOut = false;
|
|
623
|
+
const finish = (exitCode, error) => {
|
|
624
|
+
if (settled) return;
|
|
625
|
+
settled = true;
|
|
626
|
+
clearTimeout(timer);
|
|
627
|
+
resolve87({ exitCode, ...error ? { error } : {} });
|
|
628
|
+
};
|
|
629
|
+
const child = spawn(
|
|
630
|
+
input.npmPath,
|
|
631
|
+
[
|
|
632
|
+
"install",
|
|
633
|
+
"-g",
|
|
634
|
+
`omnius@${input.targetVersion}`,
|
|
635
|
+
"--prefer-online",
|
|
636
|
+
"--no-audit",
|
|
637
|
+
"--no-fund",
|
|
638
|
+
"--no-progress"
|
|
639
|
+
],
|
|
640
|
+
{
|
|
641
|
+
env: input.env,
|
|
642
|
+
stdio: ["ignore", "pipe", "pipe"],
|
|
643
|
+
windowsHide: true
|
|
644
|
+
}
|
|
645
|
+
);
|
|
646
|
+
child.stdout?.on("data", (chunk) => {
|
|
647
|
+
process.stdout.write(chunk);
|
|
648
|
+
});
|
|
649
|
+
child.stderr?.on("data", (chunk) => {
|
|
650
|
+
const text2 = String(chunk);
|
|
651
|
+
process.stderr.write(text2);
|
|
652
|
+
stderrTail.push(text2);
|
|
653
|
+
while (stderrTail.join("").length > 8e3 && stderrTail.length > 1) stderrTail.shift();
|
|
654
|
+
});
|
|
655
|
+
child.once("error", (error) => finish(-1, error.message));
|
|
656
|
+
child.once("close", (code8, signal) => {
|
|
657
|
+
const exitCode = code8 ?? -1;
|
|
658
|
+
const evidence = stderrTail.join("").trim();
|
|
659
|
+
finish(
|
|
660
|
+
exitCode,
|
|
661
|
+
exitCode === 0 ? void 0 : timedOut ? "npm install timed out after 5 minutes" : evidence || `npm install exited with ${signal ? `signal ${signal}` : `code ${exitCode}`}`
|
|
662
|
+
);
|
|
663
|
+
});
|
|
664
|
+
const timer = setTimeout(() => {
|
|
665
|
+
timedOut = true;
|
|
666
|
+
try {
|
|
667
|
+
child.kill("SIGTERM");
|
|
668
|
+
} catch {
|
|
669
|
+
}
|
|
670
|
+
const forceTimer = setTimeout(() => {
|
|
671
|
+
try {
|
|
672
|
+
child.kill("SIGKILL");
|
|
673
|
+
} catch {
|
|
674
|
+
}
|
|
675
|
+
}, 2500);
|
|
676
|
+
forceTimer.unref?.();
|
|
677
|
+
}, 5 * 6e4);
|
|
678
|
+
});
|
|
679
|
+
}
|
|
616
680
|
async function runVerifiedUpdateTransaction(initial, dependencies, paths = resolveUpdatePaths()) {
|
|
617
681
|
let state = initial;
|
|
618
682
|
const target = assertExactUpdateTarget(initial.target_version);
|
|
@@ -632,27 +696,7 @@ async function runVerifiedUpdateTransaction(initial, dependencies, paths = resol
|
|
|
632
696
|
npm_path: npmPath,
|
|
633
697
|
...prefixProbe.status === 0 && prefixProbe.stdout.trim() ? { npm_prefix: prefixProbe.stdout.trim() } : {}
|
|
634
698
|
}, paths);
|
|
635
|
-
const installer = dependencies.install ??
|
|
636
|
-
const result = runSync(
|
|
637
|
-
command,
|
|
638
|
-
[
|
|
639
|
-
"install",
|
|
640
|
-
"-g",
|
|
641
|
-
`omnius@${targetVersion}`,
|
|
642
|
-
"--prefer-online",
|
|
643
|
-
"--no-audit",
|
|
644
|
-
"--no-fund",
|
|
645
|
-
"--no-progress"
|
|
646
|
-
],
|
|
647
|
-
{ env: childEnv, timeout: 5 * 6e4 }
|
|
648
|
-
);
|
|
649
|
-
if (result.stdout) process.stdout.write(result.stdout);
|
|
650
|
-
if (result.stderr) process.stderr.write(result.stderr);
|
|
651
|
-
return {
|
|
652
|
-
exitCode: result.status ?? -1,
|
|
653
|
-
...result.error || result.status !== 0 ? { error: result.error?.message || result.stderr.trim() || `npm install exited with code ${result.status ?? -1}` } : {}
|
|
654
|
-
};
|
|
655
|
-
});
|
|
699
|
+
const installer = dependencies.install ?? installGlobalPackageStreaming;
|
|
656
700
|
const installResult = await installer({ npmPath, targetVersion: target, env: env2 });
|
|
657
701
|
state = transition(state, { installer_exit_code: installResult.exitCode }, paths);
|
|
658
702
|
if (installResult.exitCode !== 0) {
|
|
@@ -721,6 +765,13 @@ function startDetachedGlobalUpdate(input, paths = resolveUpdatePaths()) {
|
|
|
721
765
|
const operationId = randomUUID();
|
|
722
766
|
const lockFd = acquireUpdateLock(operationId, paths);
|
|
723
767
|
closeSync(lockFd);
|
|
768
|
+
const workerPath = fileURLToPath(new URL("./update-worker.js", import.meta.url));
|
|
769
|
+
if (!existsSync2(workerPath)) {
|
|
770
|
+
releaseUpdateLock(paths, operationId);
|
|
771
|
+
throw new Error(
|
|
772
|
+
`The coordinated update worker is missing at ${workerPath}. Reinstall Omnius from a package that ships dist/update-worker.js.`
|
|
773
|
+
);
|
|
774
|
+
}
|
|
724
775
|
const now2 = (/* @__PURE__ */ new Date()).toISOString();
|
|
725
776
|
let state = {
|
|
726
777
|
schema_version: 1,
|
|
@@ -737,10 +788,15 @@ function startDetachedGlobalUpdate(input, paths = resolveUpdatePaths()) {
|
|
|
737
788
|
tray_restarted: false
|
|
738
789
|
};
|
|
739
790
|
writeUpdateState(state, paths);
|
|
740
|
-
const workerPath = fileURLToPath(new URL("./update-worker.js", import.meta.url));
|
|
741
791
|
rotateUpdateLog(paths);
|
|
742
792
|
const logFd = openSync(paths.logFile, "a", 384);
|
|
743
793
|
try {
|
|
794
|
+
writeSync(
|
|
795
|
+
logFd,
|
|
796
|
+
`
|
|
797
|
+
[omnius update ${operationId}] ${input.fromVersion} -> ${targetVersion} ${now2}
|
|
798
|
+
`
|
|
799
|
+
);
|
|
744
800
|
const child = spawn(
|
|
745
801
|
process.execPath,
|
|
746
802
|
[
|
|
@@ -805,6 +861,32 @@ function updateStatusSnapshot(paths = resolveUpdatePaths()) {
|
|
|
805
861
|
log_tail: readUpdateLogTail(paths)
|
|
806
862
|
};
|
|
807
863
|
}
|
|
864
|
+
function readReconciledUpdateState(paths = resolveUpdatePaths()) {
|
|
865
|
+
const snapshot = updateStatusSnapshot(paths).state;
|
|
866
|
+
return snapshot.status === "idle" ? null : snapshot;
|
|
867
|
+
}
|
|
868
|
+
async function waitForUpdateTransaction(operationId, options2 = {}, paths = resolveUpdatePaths()) {
|
|
869
|
+
const pollIntervalMs = Math.max(25, options2.pollIntervalMs ?? 300);
|
|
870
|
+
const timeoutMs = Math.max(pollIntervalMs, options2.timeoutMs ?? 10 * 6e4);
|
|
871
|
+
const deadline = Date.now() + timeoutMs;
|
|
872
|
+
while (Date.now() <= deadline) {
|
|
873
|
+
const snapshot = updateStatusSnapshot(paths);
|
|
874
|
+
if (snapshot.state.status !== "idle") {
|
|
875
|
+
if (snapshot.state.operation_id !== operationId) {
|
|
876
|
+
throw new Error(
|
|
877
|
+
`Update operation changed from ${operationId} to ${snapshot.state.operation_id}`
|
|
878
|
+
);
|
|
879
|
+
}
|
|
880
|
+
options2.onProgress?.({
|
|
881
|
+
state: snapshot.state,
|
|
882
|
+
log_tail: snapshot.log_tail
|
|
883
|
+
});
|
|
884
|
+
if (snapshot.state.status !== "running") return snapshot.state;
|
|
885
|
+
}
|
|
886
|
+
await new Promise((resolve87) => setTimeout(resolve87, pollIntervalMs));
|
|
887
|
+
}
|
|
888
|
+
throw new Error(`Update operation ${operationId} did not finish within ${timeoutMs}ms`);
|
|
889
|
+
}
|
|
808
890
|
function updateStateIsFreshRunning(state) {
|
|
809
891
|
if (!state || state.status !== "running") return false;
|
|
810
892
|
if (isPidAlive(state.pid)) return true;
|
|
@@ -679731,7 +679813,7 @@ async function runTrayForeground(explicitEndpoint) {
|
|
|
679731
679813
|
let updateView = trayUpdatePresentation(
|
|
679732
679814
|
health.version,
|
|
679733
679815
|
availableUpdate?.latestVersion,
|
|
679734
|
-
|
|
679816
|
+
readReconciledUpdateState()
|
|
679735
679817
|
);
|
|
679736
679818
|
const menuState = menuForHealth(health, endpoint, registered, updateView);
|
|
679737
679819
|
const SysTray = await loadSysTray();
|
|
@@ -679773,7 +679855,7 @@ async function runTrayForeground(explicitEndpoint) {
|
|
|
679773
679855
|
updateView = trayUpdatePresentation(
|
|
679774
679856
|
health.version,
|
|
679775
679857
|
availableUpdate?.latestVersion,
|
|
679776
|
-
|
|
679858
|
+
readReconciledUpdateState()
|
|
679777
679859
|
);
|
|
679778
679860
|
menuState.updateItem.title = updateView.title;
|
|
679779
679861
|
menuState.updateItem.tooltip = updateView.tooltip;
|
|
@@ -679842,7 +679924,7 @@ async function runTrayForeground(explicitEndpoint) {
|
|
|
679842
679924
|
endpoint,
|
|
679843
679925
|
trayWasRunning: true
|
|
679844
679926
|
});
|
|
679845
|
-
updateView = trayUpdatePresentation(currentVersion, targetVersion,
|
|
679927
|
+
updateView = trayUpdatePresentation(currentVersion, targetVersion, readReconciledUpdateState());
|
|
679846
679928
|
if (updateView.enabled) {
|
|
679847
679929
|
updateView = {
|
|
679848
679930
|
title: `Updating to v${targetVersion} — starting`,
|
|
@@ -679879,7 +679961,7 @@ async function runTrayForeground(explicitEndpoint) {
|
|
|
679879
679961
|
updateView = trayUpdatePresentation(
|
|
679880
679962
|
currentVersion,
|
|
679881
679963
|
availableUpdate?.latestVersion,
|
|
679882
|
-
|
|
679964
|
+
readReconciledUpdateState()
|
|
679883
679965
|
);
|
|
679884
679966
|
menuState.updateItem.title = updateView.title;
|
|
679885
679967
|
menuState.updateItem.tooltip = updateView.tooltip;
|
|
@@ -747939,8 +748021,12 @@ async function handleUpdate(subcommand, ctx3) {
|
|
|
747939
748021
|
renderInfo(`Omnius v${currentVersion} is already up to date.`);
|
|
747940
748022
|
return;
|
|
747941
748023
|
}
|
|
748024
|
+
const updateOverlay = startInstallOverlay(info.latestVersion);
|
|
748025
|
+
updateOverlay.setPhase("Preparing");
|
|
748026
|
+
updateOverlay.setProgress(0, 6);
|
|
748027
|
+
updateOverlay.setStatus("starting coordinated global update");
|
|
747942
748028
|
try {
|
|
747943
|
-
const [{ startDetachedGlobalUpdate: startDetachedGlobalUpdate2 }, { getTrayStatus: getTrayStatus2 }] = await Promise.all([
|
|
748029
|
+
const [{ startDetachedGlobalUpdate: startDetachedGlobalUpdate2, waitForUpdateTransaction: waitForUpdateTransaction2 }, { getTrayStatus: getTrayStatus2 }] = await Promise.all([
|
|
747944
748030
|
Promise.resolve().then(() => (init_update_service(), update_service_exports)),
|
|
747945
748031
|
Promise.resolve().then(() => (init_tray(), tray_exports))
|
|
747946
748032
|
]);
|
|
@@ -747951,11 +748037,52 @@ async function handleUpdate(subcommand, ctx3) {
|
|
|
747951
748037
|
endpoint: trayStatus.endpoint,
|
|
747952
748038
|
trayWasRunning: trayStatus.running
|
|
747953
748039
|
});
|
|
748040
|
+
const phasePresentation = {
|
|
748041
|
+
queued: { label: "Preparing", progress: 0, status: "update worker queued" },
|
|
748042
|
+
installing: { label: "Package", progress: 1, status: `installing omnius@${info.latestVersion}` },
|
|
748043
|
+
package_verified: { label: "Verification", progress: 2, status: "global package and executable verified" },
|
|
748044
|
+
daemon_restarting: { label: "Daemon", progress: 3, status: "restarting shared daemon" },
|
|
748045
|
+
runtime_verified: { label: "Runtime", progress: 4, status: "daemon version and package hash verified" },
|
|
748046
|
+
tray_restarting: { label: "Indicator", progress: 5, status: "restarting system indicator" },
|
|
748047
|
+
completed: { label: "Complete", progress: 6, status: "global runtime update verified" },
|
|
748048
|
+
failed: { label: "Failed", progress: 6, status: "update verification failed" }
|
|
748049
|
+
};
|
|
748050
|
+
const marker = `[omnius update ${started.state.operation_id}]`;
|
|
748051
|
+
const terminal = await waitForUpdateTransaction2(
|
|
748052
|
+
started.state.operation_id,
|
|
748053
|
+
{
|
|
748054
|
+
pollIntervalMs: 250,
|
|
748055
|
+
timeoutMs: 10 * 6e4,
|
|
748056
|
+
onProgress(snapshot) {
|
|
748057
|
+
const view = phasePresentation[snapshot.state.phase];
|
|
748058
|
+
updateOverlay.setPhase(view.label);
|
|
748059
|
+
updateOverlay.setProgress(view.progress, 6);
|
|
748060
|
+
const operationLog = snapshot.log_tail.includes(marker) ? snapshot.log_tail.slice(snapshot.log_tail.lastIndexOf(marker) + marker.length) : snapshot.log_tail;
|
|
748061
|
+
const liveLine = operationLog.replace(/\x1B\][^\x07]*(?:\x07|\x1B\\)/g, "").replace(/\x1B\[[0-?]*[ -/]*[@-~]/g, "").split(/\r?\n/).map((line) => line.trim()).filter((line) => line && !/^npm notice/i.test(line)).at(-1);
|
|
748062
|
+
updateOverlay.setStatus((liveLine || view.status).slice(0, 100));
|
|
748063
|
+
}
|
|
748064
|
+
}
|
|
748065
|
+
);
|
|
748066
|
+
if (terminal.status === "failed") {
|
|
748067
|
+
updateOverlay.dismiss();
|
|
748068
|
+
renderError(`Update to v${info.latestVersion} failed: ${terminal.error || "unknown error"}`);
|
|
748069
|
+
if (terminal.remediation) renderWarning(terminal.remediation);
|
|
748070
|
+
return;
|
|
748071
|
+
}
|
|
748072
|
+
updateOverlay.stop("Package, daemon, and indicator verified");
|
|
748073
|
+
await new Promise((resolve87) => setTimeout(resolve87, 1e3));
|
|
748074
|
+
updateOverlay.dismiss();
|
|
747954
748075
|
renderInfo(
|
|
747955
|
-
`
|
|
748076
|
+
`Updated Omnius v${currentVersion} → v${terminal.installed_version ?? info.latestVersion}; daemon v${terminal.daemon_version ?? info.latestVersion}${terminal.tray_was_running ? ", indicator restarted" : ""}.`
|
|
747956
748077
|
);
|
|
748078
|
+
ctx3.contextSave?.();
|
|
748079
|
+
ctx3.savePendingTaskState?.();
|
|
748080
|
+
if (ctx3.hasActiveTask?.()) ctx3.abortActiveTask?.();
|
|
748081
|
+
ctx3.killEphemeral?.({ preserveInfrastructure: true });
|
|
748082
|
+
process.exit(120);
|
|
747957
748083
|
} catch (error) {
|
|
747958
|
-
|
|
748084
|
+
updateOverlay.dismiss();
|
|
748085
|
+
renderError(`Update failed: ${error instanceof Error ? error.message : String(error)}`);
|
|
747959
748086
|
}
|
|
747960
748087
|
return;
|
|
747961
748088
|
}
|