omnius 1.0.898 → 1.0.899
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 +2 -2
- package/dist/library.js +1 -1
- package/dist/omnius-tray-install.cjs +112 -0
- package/dist/postinstall-daemon.cjs +54 -4
- package/dist/update-worker-runtime.js +62012 -58969
- package/docs/DISCOVERY.json +257 -0
- package/docs/DISCOVERY.md +3 -0
- package/docs/getting-started/install.md +20 -0
- package/docs/guides/system-tray.md +4 -0
- package/docs/guides/telegram.md +10 -0
- package/npm-shrinkwrap.json +68 -68
- package/package.json +1 -1
package/dist/index.js
CHANGED
|
@@ -1,4 +1,4 @@
|
|
|
1
1
|
[diffend] Oversized file quarantined before diffing.
|
|
2
2
|
name: package/dist/index.js
|
|
3
|
-
size:
|
|
4
|
-
sha256:
|
|
3
|
+
size: 39003716 bytes
|
|
4
|
+
sha256: b6edef747f657c5b2a3d457343f93a79c376d250cf0aaffa2e59e7666d232f24
|
package/dist/library.js
CHANGED
|
@@ -374916,7 +374916,7 @@ function classifyFailureKind(text14, args) {
|
|
|
374916
374916
|
if (/\[PROPOSAL_MODE_REQUIRED\]|proposal\/copy-on-write mode|proposal mode only|copy-on-write patch proposal/i.test(text14)) {
|
|
374917
374917
|
return "proposal_mode_required";
|
|
374918
374918
|
}
|
|
374919
|
-
if (/\[COMPLETION BLOCKED
|
|
374919
|
+
if (/\[COMPLETION BLOCKED|\bCompletion blocked:|Resolution gate HELD|held by todo verification|\[MISSION COMPLETION CONTRACT|Backward-pass critique requested changes|completion gate|task_complete held/i.test(text14)) {
|
|
374920
374920
|
return "completion_hold";
|
|
374921
374921
|
}
|
|
374922
374922
|
if (/\[MUTATION_SCOPE_CONFLICT\]|mutation scope conflict|outside this worker's owned|coordinator-owned|already owns overlapping scope|artifact lease/i.test(text14)) {
|
|
@@ -0,0 +1,112 @@
|
|
|
1
|
+
#!/usr/bin/env node
|
|
2
|
+
"use strict";
|
|
3
|
+
|
|
4
|
+
// Shared by the package installer and explicit daemon service installation.
|
|
5
|
+
const fs = require("node:fs");
|
|
6
|
+
const path = require("node:path");
|
|
7
|
+
const os = require("node:os");
|
|
8
|
+
const cp = require("node:child_process");
|
|
9
|
+
const { randomUUID } = require("node:crypto");
|
|
10
|
+
|
|
11
|
+
function safe(value) {
|
|
12
|
+
if (typeof value !== "string" || !value || /[\r\n\0]/.test(value)) throw new Error("Invalid tray installation path");
|
|
13
|
+
return value;
|
|
14
|
+
}
|
|
15
|
+
const unitQuote = value => '"' + safe(value).replace(/\\/g, "\\\\").replace(/"/g, '\\"').replace(/%/g, "%%") + '"';
|
|
16
|
+
const desktopQuote = value => '"' + safe(value).replace(/\\/g, "\\\\").replace(/"/g, '\\"').replace(/%/g, "%%").replace(/[$`]/g, "\\$&") + '"';
|
|
17
|
+
|
|
18
|
+
function trayCompanionContents(options) {
|
|
19
|
+
const endpoint = `http://127.0.0.1:${options.port || 11435}`;
|
|
20
|
+
const argv = [options.nodePath, options.entrypoint, "tray", "run", "--endpoint", endpoint];
|
|
21
|
+
const unit = [
|
|
22
|
+
"[Unit]", "Description=Omnius desktop indicator", "PartOf=graphical-session.target",
|
|
23
|
+
"After=graphical-session.target", "StartLimitIntervalSec=60", "StartLimitBurst=5", "",
|
|
24
|
+
"[Service]", "Type=simple", `WorkingDirectory=${safe(options.homeDir).replace(/%/g, "%%")}`,
|
|
25
|
+
`Environment=${unitQuote(`OMNIUS_HOME=${options.dataDir || path.join(options.homeDir, ".omnius")}`)}`,
|
|
26
|
+
`ExecStart=${argv.map(value => unitQuote(value).replace(/\$/g, () => "$$")).join(" ")}`, "Restart=on-failure", "RestartSec=5",
|
|
27
|
+
"TimeoutStopSec=10", "", "[Install]", "WantedBy=graphical-session.target", "",
|
|
28
|
+
].join("\n");
|
|
29
|
+
const launch = options.userSystemd
|
|
30
|
+
? ["/usr/bin/systemctl", "--user", "start", "omnius-tray.service"] : argv;
|
|
31
|
+
const desktop = [
|
|
32
|
+
"[Desktop Entry]", "Type=Application", "Version=1.0", "Name=Omnius",
|
|
33
|
+
"Comment=Omnius daemon and Telegram workspace controls", `Exec=${launch.map(desktopQuote).join(" ")}`,
|
|
34
|
+
"Terminal=false", "X-GNOME-Autostart-enabled=true", "StartupNotify=false", "",
|
|
35
|
+
].join("\n");
|
|
36
|
+
return { unit, desktop };
|
|
37
|
+
}
|
|
38
|
+
|
|
39
|
+
function installTrayCompanion(options = {}) {
|
|
40
|
+
if ((options.platform || process.platform) !== "linux") return { installed: false, started: false, reason: "platform" };
|
|
41
|
+
const run = options.run || ((command, args) => cp.execFileSync(command, args, { encoding: "utf8", timeout: 10000, stdio: ["ignore", "pipe", "pipe"] }));
|
|
42
|
+
const homeDir = path.resolve(safe(options.homeDir || os.homedir()));
|
|
43
|
+
const userName = options.userName || process.env.SUDO_USER || os.userInfo().username;
|
|
44
|
+
const uid = Number(options.uid ?? run("id", ["-u", userName]).trim());
|
|
45
|
+
const gid = Number(options.gid ?? run("id", ["-g", userName]).trim());
|
|
46
|
+
if (!Number.isSafeInteger(uid) || uid < 0 || !Number.isSafeInteger(gid) || gid < 0) throw new Error("Invalid tray owner");
|
|
47
|
+
const opts = { ...options, nodePath: safe(options.nodePath || process.execPath),
|
|
48
|
+
entrypoint: safe(options.entrypoint || path.join(__dirname, "..", "dist", "launcher.cjs")), homeDir };
|
|
49
|
+
if (!Number.isInteger(opts.port ?? 11435) || (opts.port ?? 11435) < 1 || (opts.port ?? 11435) > 65535) throw new Error("Invalid tray port");
|
|
50
|
+
// A root package installation must never write through desktop-owner paths
|
|
51
|
+
// with root privileges. Let the owner create their own companion artifacts.
|
|
52
|
+
if (process.getuid?.() === 0 && uid !== 0 && !options.run) {
|
|
53
|
+
const args = ["-u", userName, "--", "env", `HOME=${homeDir}`, `USER=${userName}`, `LOGNAME=${userName}`,
|
|
54
|
+
`XDG_RUNTIME_DIR=/run/user/${uid}`, `DBUS_SESSION_BUS_ADDRESS=unix:path=/run/user/${uid}/bus`,
|
|
55
|
+
opts.nodePath, __filename, "--node", opts.nodePath, "--entrypoint", opts.entrypoint,
|
|
56
|
+
"--home", homeDir, "--user", userName, "--port", String(opts.port || 11435),
|
|
57
|
+
...(opts.dataDir ? ["--data-dir", opts.dataDir] : []), ...(options.start === false ? ["--no-start"] : [])];
|
|
58
|
+
return JSON.parse(run("runuser", args));
|
|
59
|
+
}
|
|
60
|
+
const asUser = args => {
|
|
61
|
+
const currentUid = typeof process.getuid === "function" ? process.getuid() : uid;
|
|
62
|
+
if (currentUid === uid) return run("systemctl", ["--user", ...args]);
|
|
63
|
+
if (currentUid !== 0) throw new Error("Tray installation must run as its desktop owner or root");
|
|
64
|
+
return run("runuser", ["-u", userName, "--", "env", `XDG_RUNTIME_DIR=/run/user/${uid}`,
|
|
65
|
+
`DBUS_SESSION_BUS_ADDRESS=unix:path=/run/user/${uid}/bus`, "systemctl", "--user", ...args]);
|
|
66
|
+
};
|
|
67
|
+
let environment = "", userSystemd = false;
|
|
68
|
+
try { environment = asUser(["show-environment"]); userSystemd = true; } catch { /* XDG autostart also supports non-systemd desktops. */ }
|
|
69
|
+
const { unit, desktop } = trayCompanionContents({ ...opts, userSystemd });
|
|
70
|
+
const unitFile = path.join(homeDir, ".config", "systemd", "user", "omnius-tray.service");
|
|
71
|
+
const desktopFile = path.join(homeDir, ".config", "autostart", "omnius-tray.desktop");
|
|
72
|
+
for (const [file, content] of [[unitFile, unit], [desktopFile, desktop]]) {
|
|
73
|
+
const directory = path.dirname(file), missing = [];
|
|
74
|
+
for (let dir = directory; !fs.existsSync(dir); dir = path.dirname(dir)) missing.push(dir);
|
|
75
|
+
fs.mkdirSync(directory, { recursive: true, mode: 0o700 });
|
|
76
|
+
for (const dir of missing) if (process.getuid?.() === 0) fs.chownSync(dir, uid, gid);
|
|
77
|
+
const temporary = `${file}.${randomUUID()}.tmp`;
|
|
78
|
+
try {
|
|
79
|
+
fs.writeFileSync(temporary, content, { mode: 0o600, flag: "wx" });
|
|
80
|
+
if (process.getuid?.() === 0) fs.chownSync(temporary, uid, gid);
|
|
81
|
+
fs.renameSync(temporary, file);
|
|
82
|
+
} finally { try { fs.unlinkSync(temporary); } catch {} }
|
|
83
|
+
}
|
|
84
|
+
let started = false;
|
|
85
|
+
if (userSystemd) {
|
|
86
|
+
asUser(["daemon-reload"]);
|
|
87
|
+
asUser(["enable", "omnius-tray.service"]);
|
|
88
|
+
const graphical = /^(?:DISPLAY|WAYLAND_DISPLAY)=.+$/m.test(environment);
|
|
89
|
+
if (graphical && options.start !== false) {
|
|
90
|
+
// An upgrade may have replaced the running helper's executable/assets.
|
|
91
|
+
// Reattach the indicator to the completed installation immediately.
|
|
92
|
+
asUser(["restart", "omnius-tray.service"]);
|
|
93
|
+
started = true;
|
|
94
|
+
}
|
|
95
|
+
}
|
|
96
|
+
return { installed: true, started, unitFile, desktopFile, userSystemd };
|
|
97
|
+
}
|
|
98
|
+
|
|
99
|
+
module.exports = { trayCompanionContents, installTrayCompanion };
|
|
100
|
+
if (require.main === module) {
|
|
101
|
+
const args = process.argv.slice(2), values = {};
|
|
102
|
+
const keys = { "--node": "nodePath", "--entrypoint": "entrypoint", "--home": "homeDir", "--user": "userName", "--data-dir": "dataDir", "--port": "port" };
|
|
103
|
+
try {
|
|
104
|
+
for (let i = 0; i < args.length; i++) {
|
|
105
|
+
if (args[i] === "--no-start") { values.start = false; continue; }
|
|
106
|
+
const key = keys[args[i]];
|
|
107
|
+
if (!key || !args[i + 1]) throw new Error("Invalid tray installer argument");
|
|
108
|
+
values[key] = key === "port" ? Number(args[++i]) : args[++i];
|
|
109
|
+
}
|
|
110
|
+
process.stdout.write(JSON.stringify(installTrayCompanion(values)) + "\n");
|
|
111
|
+
} catch (error) { process.stderr.write(`Omnius tray installation failed: ${error.message}\n`); process.exitCode = 1; }
|
|
112
|
+
}
|
|
@@ -519,6 +519,10 @@ function effectiveUser() {
|
|
|
519
519
|
if (!IS_WIN && process.getuid && process.getuid() === 0) {
|
|
520
520
|
var sudoUser = process.env.SUDO_USER;
|
|
521
521
|
if (sudoUser) return sudoUser;
|
|
522
|
+
if (IS_LINUX) {
|
|
523
|
+
var unitUser = runCapture("systemctl show " + SERVICE_LABEL + ".service --property=User --value").trim();
|
|
524
|
+
if (/^[a-zA-Z_][a-zA-Z0-9_.-]*\$?$/.test(unitUser) && unitUser !== "root") return unitUser;
|
|
525
|
+
}
|
|
522
526
|
return null; // Running as bare root — skip per-user service install
|
|
523
527
|
}
|
|
524
528
|
return process.env.USER || process.env.LOGNAME || os.userInfo().username;
|
|
@@ -683,12 +687,43 @@ function cleanNexus() {
|
|
|
683
687
|
|
|
684
688
|
// ─── Linux: systemd user unit ───────────────────────────────────────────────
|
|
685
689
|
|
|
690
|
+
function hasSystemDaemonUnit() {
|
|
691
|
+
if (!IS_LINUX) return false;
|
|
692
|
+
return runCapture("systemctl show " + SERVICE_LABEL + ".service --property=LoadState --value").trim() === "loaded";
|
|
693
|
+
}
|
|
694
|
+
|
|
695
|
+
function installDesktopCompanion(nodeBin, omniusScript, user) {
|
|
696
|
+
if (!user) return;
|
|
697
|
+
var helper = path.join(__dirname, "omnius-tray-install.cjs");
|
|
698
|
+
if (!fs.existsSync(helper)) {
|
|
699
|
+
warn("Desktop tray companion installer is missing from this package.");
|
|
700
|
+
return;
|
|
701
|
+
}
|
|
702
|
+
try {
|
|
703
|
+
var userHome = HOME;
|
|
704
|
+
if (IS_LINUX) {
|
|
705
|
+
var entry = cp.execFileSync("getent", ["passwd", user], { encoding: "utf8", stdio: ["ignore", "pipe", "ignore"], timeout: 5000 }).trim().split(":");
|
|
706
|
+
if (entry[0] === user && entry[5]) userHome = entry[5];
|
|
707
|
+
}
|
|
708
|
+
cp.execFileSync(nodeBin, [helper, "--node", nodeBin, "--entrypoint", omniusScript,
|
|
709
|
+
"--home", userHome, "--user", user, "--data-dir", path.join(userHome, ".omnius"), "--port", String(PORT)],
|
|
710
|
+
{ stdio: "pipe", timeout: 20000 });
|
|
711
|
+
log("Updated the daemon's desktop tray companion (headless hosts need no tray).");
|
|
712
|
+
} catch (e) {
|
|
713
|
+
warn("Desktop tray companion setup failed: " + (e && e.message));
|
|
714
|
+
}
|
|
715
|
+
}
|
|
716
|
+
|
|
686
717
|
function installSystemd(nodeBin, omniusScript, user) {
|
|
687
718
|
if (!IS_LINUX) return false;
|
|
688
719
|
if (!hasCmd("systemctl")) {
|
|
689
720
|
warn("systemctl not found — skipping systemd install.");
|
|
690
721
|
return false;
|
|
691
722
|
}
|
|
723
|
+
if (hasSystemDaemonUnit()) {
|
|
724
|
+
log("Native system daemon unit is installed; preserving its launcher and sole service ownership.");
|
|
725
|
+
return true;
|
|
726
|
+
}
|
|
692
727
|
|
|
693
728
|
var userHome = user === process.env.USER ? HOME : path.join("/home", user);
|
|
694
729
|
try {
|
|
@@ -740,6 +775,9 @@ function installSystemd(nodeBin, omniusScript, user) {
|
|
|
740
775
|
"Environment=OMNIUS_DAEMON=1",
|
|
741
776
|
"Environment=OMNIUS_PORT=" + PORT,
|
|
742
777
|
"Environment=NODE_ENV=production",
|
|
778
|
+
"Environment=HOME=" + userHome,
|
|
779
|
+
"Environment=OMNIUS_HOME=" + path.join(userHome, ".omnius"),
|
|
780
|
+
"WorkingDirectory=" + userHome,
|
|
743
781
|
// Keep this user-relative so a unit written during a root/global install
|
|
744
782
|
// still loads the owning user's overrides after the existing unit is
|
|
745
783
|
// rewritten on update.
|
|
@@ -751,6 +789,9 @@ function installSystemd(nodeBin, omniusScript, user) {
|
|
|
751
789
|
// Pair with StartLimitIntervalSec to prevent thrash loops.
|
|
752
790
|
"Restart=always",
|
|
753
791
|
"RestartSec=3",
|
|
792
|
+
"KillSignal=SIGTERM",
|
|
793
|
+
"KillMode=process",
|
|
794
|
+
"TimeoutStopSec=120",
|
|
754
795
|
"StandardOutput=append:" + path.join(logDir, "daemon.log"),
|
|
755
796
|
"StandardError=append:" + path.join(logDir, "daemon.err.log"),
|
|
756
797
|
"",
|
|
@@ -1094,9 +1135,11 @@ function main() {
|
|
|
1094
1135
|
if (!ensureCoreCommandAvailable()) return fatalExit(1);
|
|
1095
1136
|
|
|
1096
1137
|
// The coordinated worker already owns service handoff and verifies the
|
|
1097
|
-
// replacement package/runtime.
|
|
1098
|
-
//
|
|
1138
|
+
// replacement package/runtime. Skip model/native provisioning here; keep
|
|
1139
|
+
// the shared desktop companion registered to the newly installed package.
|
|
1099
1140
|
if (process.env.OMNIUS_UPDATE_COORDINATED === "1") {
|
|
1141
|
+
var companionEntrypoint = resolveOmniusBinary();
|
|
1142
|
+
if (companionEntrypoint) installDesktopCompanion(resolveNodeBinary(), companionEntrypoint, effectiveUser());
|
|
1100
1143
|
log("Coordinated update owns daemon restart and exact-version verification.");
|
|
1101
1144
|
return safeExit(0);
|
|
1102
1145
|
}
|
|
@@ -1123,6 +1166,8 @@ function main() {
|
|
|
1123
1166
|
|
|
1124
1167
|
if (process.env.OMNIUS_SKIP_DAEMON_INSTALL === "1") {
|
|
1125
1168
|
log("OMNIUS_SKIP_DAEMON_INSTALL=1 — skipping daemon service install.");
|
|
1169
|
+
var skippedDaemonEntrypoint = resolveOmniusBinary();
|
|
1170
|
+
if (skippedDaemonEntrypoint) installDesktopCompanion(resolveNodeBinary(), skippedDaemonEntrypoint, effectiveUser());
|
|
1126
1171
|
return safeExit(0);
|
|
1127
1172
|
}
|
|
1128
1173
|
|
|
@@ -1133,6 +1178,10 @@ function main() {
|
|
|
1133
1178
|
// the new service-managed daemon fails to bind port 11435 and the user
|
|
1134
1179
|
// ends up running stale in-memory code from the previous version.
|
|
1135
1180
|
progress(6, INSTALL_STEPS, "Clearing daemon port");
|
|
1181
|
+
if (hasSystemDaemonUnit()) {
|
|
1182
|
+
log("Native system service owns daemon restart; skipping standalone process signals.");
|
|
1183
|
+
return runMainAfterKill();
|
|
1184
|
+
}
|
|
1136
1185
|
stopAttestedDaemonPortHolder(PORT, function (killedCount) {
|
|
1137
1186
|
if (killedCount > 0) {
|
|
1138
1187
|
log("Killed " + killedCount + " stale daemon process(es) holding port " + PORT + ".");
|
|
@@ -1172,8 +1221,8 @@ function runMainAfterKill() {
|
|
|
1172
1221
|
if (!user) {
|
|
1173
1222
|
warn("Running as bare root with no SUDO_USER — skipping per-user service install.");
|
|
1174
1223
|
warn("Re-run as your user, or run: OMNIUS_SKIP_DAEMON_INSTALL=0 npm i -g omnius");
|
|
1175
|
-
//
|
|
1176
|
-
|
|
1224
|
+
// An unidentified desktop/service owner must never become a competing
|
|
1225
|
+
// root daemon merely because npm itself is running as administrator.
|
|
1177
1226
|
return safeExit(0);
|
|
1178
1227
|
}
|
|
1179
1228
|
|
|
@@ -1192,6 +1241,7 @@ function runMainAfterKill() {
|
|
|
1192
1241
|
// Fallback: spawn a detached child so at least the port is live NOW.
|
|
1193
1242
|
spawnDetached(nodeBin, omniusScript);
|
|
1194
1243
|
}
|
|
1244
|
+
installDesktopCompanion(nodeBin, omniusScript, user);
|
|
1195
1245
|
|
|
1196
1246
|
// Wait up to 15s for /health to come up, but don't fail npm install.
|
|
1197
1247
|
progress(8, INSTALL_STEPS, "Verifying daemon health");
|