pushary 1.9.136 → 1.9.138

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.
Files changed (109) hide show
  1. package/CHANGELOG.md +16 -0
  2. package/dist/{api-5H25QRNM.js → api-J4XJ7XWW.js} +9 -9
  3. package/dist/bin/pushary-audit.js +3 -3
  4. package/dist/bin/pushary-bell-hook.js +19 -19
  5. package/dist/bin/pushary-bell.js +7 -7
  6. package/dist/bin/pushary-claude.js +23 -23
  7. package/dist/bin/pushary-clean.js +34 -34
  8. package/dist/bin/pushary-codex-bridge.js +15 -15
  9. package/dist/bin/pushary-codex-hook.js +30 -30
  10. package/dist/bin/pushary-codex-session.js +6 -6
  11. package/dist/bin/pushary-codex.js +11 -11
  12. package/dist/bin/pushary-connect.js +23 -23
  13. package/dist/bin/pushary-daemon-supervisor.js +91 -12
  14. package/dist/bin/pushary-daemon.js +35 -35
  15. package/dist/bin/pushary-disconnect.js +23 -23
  16. package/dist/bin/pushary-display-hook.js +45 -24
  17. package/dist/bin/pushary-doctor.js +49 -45
  18. package/dist/bin/pushary-elicitation-hook.js +20 -20
  19. package/dist/bin/pushary-gemini-bridge.js +6 -6
  20. package/dist/bin/pushary-gemini-hook.js +23 -23
  21. package/dist/bin/pushary-hook.js +25 -25
  22. package/dist/bin/pushary-login.js +17 -17
  23. package/dist/bin/pushary-logout.js +21 -21
  24. package/dist/bin/pushary-mcp.js +11 -11
  25. package/dist/bin/pushary-mode.js +12 -12
  26. package/dist/bin/pushary-notification-hook.js +19 -19
  27. package/dist/bin/pushary-opencode-hook.js +22 -22
  28. package/dist/bin/pushary-permission-denied-hook.js +25 -25
  29. package/dist/bin/pushary-permission-hook.js +25 -25
  30. package/dist/bin/pushary-post-hook.js +20 -20
  31. package/dist/bin/pushary-prompt-hook.js +19 -19
  32. package/dist/bin/pushary-session-end-hook.js +19 -19
  33. package/dist/bin/pushary-session-start-hook.js +28 -28
  34. package/dist/bin/pushary-setup.js +54 -52
  35. package/dist/bin/pushary-status.js +27 -27
  36. package/dist/bin/pushary-stop-hook.js +19 -19
  37. package/dist/bin/pushary-stopfailure-hook.js +19 -19
  38. package/dist/bin/pushary-suggestions.js +12 -12
  39. package/dist/bin/pushary-transcript-register.js +9 -9
  40. package/dist/bin/pushary-transcripts.js +19 -19
  41. package/dist/bin/pushary-upgrade.js +37 -37
  42. package/dist/bin/pushary-wait.js +12 -12
  43. package/dist/bin/pushary.js +6 -6
  44. package/dist/{chunk-ICCM3DLT.js → chunk-33E75LIY.js} +1 -1
  45. package/dist/{chunk-IHAKBLW2.js → chunk-42BVIKPZ.js} +3 -3
  46. package/dist/{chunk-3QBI5C6P.js → chunk-52B2TQJM.js} +1 -1
  47. package/dist/{chunk-NZD6ISCL.js → chunk-5ZK4RHYR.js} +1 -1
  48. package/dist/{chunk-FAF5RDWT.js → chunk-6TK3DWSF.js} +293 -48
  49. package/dist/{chunk-DBIPNY7J.js → chunk-7WR3FDDX.js} +2 -2
  50. package/dist/{chunk-6SWFS4GU.js → chunk-AGVE7MXF.js} +2 -2
  51. package/dist/{chunk-43DT3QWZ.js → chunk-APTNHX63.js} +3 -3
  52. package/dist/{chunk-L2GADKFL.js → chunk-B3AZPYRU.js} +6 -6
  53. package/dist/chunk-B4UIRMOE.js +31 -0
  54. package/dist/{chunk-JZJ5CM6X.js → chunk-CBTXOWB3.js} +3 -3
  55. package/dist/{chunk-A7R43KOX.js → chunk-CULDO4UA.js} +2 -2
  56. package/dist/{chunk-YHX5YF77.js → chunk-DES272QQ.js} +3 -3
  57. package/dist/{chunk-WXUEOHYY.js → chunk-DK6CMXYI.js} +5 -5
  58. package/dist/{chunk-VV7WRIQT.js → chunk-DMZMPYLB.js} +2 -2
  59. package/dist/{chunk-WNT4JHK3.js → chunk-EHQCMJHI.js} +1 -1
  60. package/dist/{chunk-V7ZY7P2X.js → chunk-EJSU5YWO.js} +3 -3
  61. package/dist/{chunk-HKJLPVPZ.js → chunk-FJ7OESWX.js} +3 -3
  62. package/dist/{chunk-2R4OVJHS.js → chunk-FO5MHOBI.js} +4 -4
  63. package/dist/{chunk-NN43KGTN.js → chunk-FQ3ASV5L.js} +3 -3
  64. package/dist/{chunk-GS5FH3C2.js → chunk-FYLYAVQG.js} +2 -2
  65. package/dist/{chunk-2MVKT7KH.js → chunk-H5XLVJI7.js} +1 -1
  66. package/dist/{chunk-UP5QXEUU.js → chunk-HVRXBHX2.js} +2 -2
  67. package/dist/{chunk-VBWJ756P.js → chunk-ICQU3SNR.js} +3 -3
  68. package/dist/{chunk-2XDVEBHI.js → chunk-IDGWQY3J.js} +4 -4
  69. package/dist/{chunk-L7Q57R4J.js → chunk-JFGM6VSU.js} +3 -3
  70. package/dist/{chunk-RPFSVNH6.js → chunk-KN4YJ4QS.js} +2 -2
  71. package/dist/{chunk-Q2VV77IY.js → chunk-KXKE3SW3.js} +4 -4
  72. package/dist/{chunk-MQ3I5OIC.js → chunk-L3UV4LLL.js} +7 -7
  73. package/dist/{chunk-D7AAAD6W.js → chunk-LF3ZRLUQ.js} +8 -8
  74. package/dist/{chunk-YURIU333.js → chunk-LIUWN23V.js} +4 -4
  75. package/dist/{chunk-54TZGPZP.js → chunk-LIZEMDE4.js} +1 -1
  76. package/dist/{chunk-G73ACPR2.js → chunk-LPXHKIJC.js} +1 -1
  77. package/dist/{chunk-2E46RALI.js → chunk-NIBF37NU.js} +2 -2
  78. package/dist/{chunk-EJHD44ZN.js → chunk-NLJ2ILA7.js} +1 -1
  79. package/dist/{chunk-3HXOR6E5.js → chunk-NNDUDXOJ.js} +9 -9
  80. package/dist/{chunk-H2RE3IPK.js → chunk-NUG2A73X.js} +1 -1
  81. package/dist/{chunk-62GD26OE.js → chunk-O26H5X5M.js} +2 -2
  82. package/dist/{chunk-POV2TBFA.js → chunk-OAGYR5LI.js} +9 -9
  83. package/dist/{chunk-4T72AHIA.js → chunk-OXPYENHL.js} +1 -1
  84. package/dist/{chunk-EQZB5P6I.js → chunk-P6HLLS5J.js} +2 -2
  85. package/dist/{chunk-ZWLSXECG.js → chunk-P7YVVWTW.js} +1 -1
  86. package/dist/{chunk-TLK5YLIE.js → chunk-PNDL3OMR.js} +2 -2
  87. package/dist/{chunk-A4YOXS24.js → chunk-PPCZSOCL.js} +2 -2
  88. package/dist/{chunk-KLV2NQVT.js → chunk-S47AAQFT.js} +2 -2
  89. package/dist/{chunk-PHA6AFOR.js → chunk-SNMTACCY.js} +4 -4
  90. package/dist/{chunk-VO77WHK4.js → chunk-TJCUGBCZ.js} +5 -5
  91. package/dist/{chunk-R7KC57PC.js → chunk-TN5PGMH5.js} +1 -1
  92. package/dist/{chunk-O5T53LZ5.js → chunk-TXPXK5Q6.js} +10 -10
  93. package/dist/{chunk-ZWIJJYN3.js → chunk-VF4N6NHG.js} +3 -3
  94. package/dist/{chunk-HY4ATVCT.js → chunk-VQMGR32B.js} +1 -1
  95. package/dist/{chunk-LAWI6NQK.js → chunk-WHOFZB5W.js} +1 -1
  96. package/dist/{chunk-J42EAEX3.js → chunk-XR27HPYC.js} +2 -1
  97. package/dist/{codex-app-cards-switch-Z7TMF2OR.js → codex-app-cards-switch-R3MIDYFA.js} +6 -6
  98. package/dist/{codex-desktop-launch-HKXGKL3T.js → codex-desktop-launch-2YRIBVDK.js} +1 -1
  99. package/dist/{codex-session-launch-DTGH7ZKM.js → codex-session-launch-CTMTMGHU.js} +15 -15
  100. package/dist/{global-upgrade-5UAH5DCG.js → global-upgrade-NMTIVAJ3.js} +8 -8
  101. package/dist/{identity-UFJEWGEU.js → identity-3XKATUN2.js} +3 -3
  102. package/dist/{live-capabilities-BL3SHFWX.js → live-capabilities-MR35FXPF.js} +3 -3
  103. package/dist/paths-YA5ROXGC.js +2 -2
  104. package/dist/{reapply-OPQF4DPQ.js → reapply-LIBOIVBT.js} +23 -23
  105. package/dist/src/index.js +25 -25
  106. package/dist/{upgrade-lock-AZLOOGKV.js → upgrade-lock-LK4XD3HR.js} +3 -3
  107. package/package.json +1 -1
  108. package/dist/bin/pushary-daemon-supervisor.d.ts +0 -1
  109. package/dist/chunk-GACQSKNG.js +0 -75
@@ -1,6 +1,6 @@
1
1
  import {
2
2
  parseSseMessages
3
- } from "./chunk-WXUEOHYY.js";
3
+ } from "./chunk-DK6CMXYI.js";
4
4
  import {
5
5
  fetchAsCredential
6
6
  } from "./chunk-VVN3RPV6.js";
@@ -4,16 +4,16 @@ import {
4
4
  } from "./chunk-H6CL3T2S.js";
5
5
  import {
6
6
  getMachineId
7
- } from "./chunk-WNT4JHK3.js";
7
+ } from "./chunk-EHQCMJHI.js";
8
8
  import {
9
9
  readControlMode
10
10
  } from "./chunk-PNVTPEO5.js";
11
11
  import {
12
12
  pusharyDir
13
- } from "./chunk-R7KC57PC.js";
13
+ } from "./chunk-TN5PGMH5.js";
14
14
  import {
15
15
  resolveGlobalBinary
16
- } from "./chunk-GS5FH3C2.js";
16
+ } from "./chunk-FYLYAVQG.js";
17
17
  import {
18
18
  getApiKey
19
19
  } from "./chunk-IKBTG3OT.js";
@@ -34,9 +34,158 @@ import {
34
34
  isRecord
35
35
  } from "./chunk-DL67HX3D.js";
36
36
 
37
+ // src/daemon-entry-guard.ts
38
+ import { mkdirSync, readFileSync } from "fs";
39
+ import { basename, dirname, join } from "path";
40
+ var DAEMON_ENTRY_GUARD_SOURCE = [
41
+ "const { existsSync } = require('node:fs')",
42
+ "if (process.argv[1] && !existsSync(process.argv[1])) process.exit(0)",
43
+ ""
44
+ ].join("\n");
45
+ var DAEMON_ENTRY_GUARD_FILE = "daemon-entry-guard.cjs";
46
+ var NODE_EXECUTABLE = /^node(?:\.exe)?$/i;
47
+ var ENTRY_GUARD_PRELOAD_FLAG = "--require";
48
+ var UNGUARDED = { kind: "unguarded" };
49
+ var daemonEntryGuardPath = (stateDir) => join(stateDir, DAEMON_ENTRY_GUARD_FILE);
50
+ var entryGuardApplies = (platform, execPath) => platform === "darwin" && NODE_EXECUTABLE.test(basename(execPath));
51
+ var holdsDaemonEntryGuard = (path) => {
52
+ try {
53
+ return readFileSync(path, "utf8") === DAEMON_ENTRY_GUARD_SOURCE;
54
+ } catch {
55
+ return false;
56
+ }
57
+ };
58
+ var writeDaemonEntryGuardAt = (path) => {
59
+ if (holdsDaemonEntryGuard(path)) return { kind: "in-place" };
60
+ try {
61
+ mkdirSync(dirname(path), { recursive: true, mode: 448 });
62
+ writeFileAtomic(path, DAEMON_ENTRY_GUARD_SOURCE, 384);
63
+ return { kind: "in-place" };
64
+ } catch (error) {
65
+ return { kind: "failed", detail: error instanceof Error ? error.message : String(error) };
66
+ }
67
+ };
68
+ var writeDaemonEntryGuard = (input) => {
69
+ if (!entryGuardApplies(input.platform, input.execPath)) return UNGUARDED;
70
+ const path = daemonEntryGuardPath(input.stateDir);
71
+ const written = writeDaemonEntryGuardAt(path);
72
+ if (written.kind === "in-place") return { kind: "guarded", path };
73
+ input.warn(`[pushary] could not write ${path}, so the background service was installed without its uninstall guard: ${written.detail}
74
+ `);
75
+ return UNGUARDED;
76
+ };
77
+
78
+ // src/daemon-supervisor.ts
79
+ import { join as join2 } from "path";
80
+ var DAEMON_SUPERVISOR_SCRIPT = "pushary-daemon-supervisor.js";
81
+ var SUPERVISOR_LAUNCH_FLAG = "--launch";
82
+ var DAEMON_LOG_FILE = "daemon.log";
83
+ var DAEMON_ERROR_LOG_FILE = "daemon-error.log";
84
+ var supervisorTaskArguments = (daemonEntry, stateDir) => [daemonEntry, stateDir, SUPERVISOR_LAUNCH_FLAG];
85
+ var parseSupervisorInvocation = (args) => {
86
+ const launching = args.length > 1 && args[args.length - 1] === SUPERVISOR_LAUNCH_FLAG;
87
+ const [daemonEntry, stateDir] = launching ? args.slice(0, -1) : args;
88
+ if (!daemonEntry || daemonEntry === SUPERVISOR_LAUNCH_FLAG) return { kind: "missing-entry" };
89
+ return { kind: launching ? "launch" : "supervise", daemonEntry, stateDir: stateDir || null };
90
+ };
91
+
92
+ // src/diagnostics/service-runtime.ts
93
+ var unescapeXml = (value) => value.replaceAll("&quot;", '"').replaceAll("&apos;", "'").replaceAll("&lt;", "<").replaceAll("&gt;", ">").replaceAll("&amp;", "&");
94
+ var unquoteSystemdExecutable = (value) => value.replace(/\\(["\\])|%(%)/g, (_match, escaped, percent) => escaped ?? percent ?? "");
95
+ var unquoteSystemdArgument = (value) => value.replace(/\\(["\\])|%(%)|\$(\$)/g, (_match, escaped, percent, dollar) => escaped ?? percent ?? dollar ?? "");
96
+ var readServiceExecPath = (contents, platform) => {
97
+ if (platform === "darwin") {
98
+ const program = contents.match(/<key>ProgramArguments<\/key>\s*<array>\s*<string>([^<]*)<\/string>/)?.[1];
99
+ return program ? unescapeXml(program) : null;
100
+ }
101
+ if (platform === "linux") {
102
+ const exec = contents.match(/^ExecStart="((?:[^"\\]|\\.)*)"/m)?.[1];
103
+ return exec ? unquoteSystemdExecutable(exec) : null;
104
+ }
105
+ if (platform === "win32") {
106
+ const command = contents.match(/<Command>([^<]*)<\/Command>/)?.[1];
107
+ return command ? unescapeXml(command) : null;
108
+ }
109
+ return null;
110
+ };
111
+ var readLaunchdProgramArguments = (contents) => {
112
+ const array = contents.match(/<key>ProgramArguments<\/key>\s*<array>([\s\S]*?)<\/array>/)?.[1] ?? "";
113
+ return [...array.matchAll(/<string>([^<]*)<\/string>/g)].map((match) => unescapeXml(match[1] ?? ""));
114
+ };
115
+ var systemdExecStartArguments = (contents) => {
116
+ const line = contents.match(/^ExecStart=(.*)$/m)?.[1] ?? "";
117
+ return [...line.matchAll(/"((?:[^"\\]|\\.)*)"/g)].map((match, index) => (index === 0 ? unquoteSystemdExecutable : unquoteSystemdArgument)(match[1] ?? ""));
118
+ };
119
+ var windowsTaskArguments = (contents) => {
120
+ const args = unescapeXml(contents.match(/<Arguments>([^<]*)<\/Arguments>/)?.[1] ?? "");
121
+ return [...args.matchAll(/"([^"]*)"/g)].map((match) => match[1] ?? "");
122
+ };
123
+ var serviceArguments = (contents, platform) => {
124
+ if (platform === "darwin") return readLaunchdProgramArguments(contents);
125
+ if (platform === "linux") return systemdExecStartArguments(contents);
126
+ if (platform === "win32") return windowsTaskArguments(contents);
127
+ return [];
128
+ };
129
+ var namesTheSupervisor = (path) => path.split(/[\\/]/).at(-1) === DAEMON_SUPERVISOR_SCRIPT;
130
+ var windowsTaskDaemonEntry = (contents) => {
131
+ const [program, ...supervisorArguments] = windowsTaskArguments(contents);
132
+ if (program === void 0) return null;
133
+ if (!namesTheSupervisor(program)) return program;
134
+ const invocation = parseSupervisorInvocation(supervisorArguments);
135
+ return invocation.kind === "missing-entry" ? null : invocation.daemonEntry;
136
+ };
137
+ var readServiceDaemonEntry = (contents, platform) => platform === "win32" ? windowsTaskDaemonEntry(contents) : serviceArguments(contents, platform).at(-1) ?? null;
138
+ var readServiceEntryGuard = (contents, platform) => {
139
+ if (platform !== "darwin") return null;
140
+ const [, flag, guard] = readLaunchdProgramArguments(contents);
141
+ return flag === ENTRY_GUARD_PRELOAD_FLAG && guard !== void 0 ? guard : null;
142
+ };
143
+ var serviceStartFileChecks = (contents, platform, exists) => {
144
+ const checks = [];
145
+ const entry = readServiceDaemonEntry(contents, platform);
146
+ if (entry !== null) {
147
+ const present = exists(entry);
148
+ checks.push({
149
+ label: "Remote-control service entry",
150
+ passed: present,
151
+ detail: present ? entry : `${entry} is gone, so the background service starts nothing at login; run \`pushary daemon install\` from the Pushary install you use`
152
+ });
153
+ }
154
+ const guard = readServiceEntryGuard(contents, platform);
155
+ if (guard !== null && !exists(guard)) {
156
+ checks.push({
157
+ label: "Remote-control service start guard",
158
+ passed: false,
159
+ detail: `${guard} is gone, so the background service cannot start; run \`pushary daemon install\` to restore it`
160
+ });
161
+ }
162
+ return checks;
163
+ };
164
+ var MANAGER_SEGMENTS = [
165
+ [".nvm", "nvm"],
166
+ ["nvm", "nvm"],
167
+ ["fnm", "fnm"],
168
+ [".fnm", "fnm"],
169
+ [".volta", "volta"],
170
+ ["volta", "volta"],
171
+ [".asdf", "asdf"],
172
+ ["asdf", "asdf"],
173
+ ["Cellar", "homebrew"]
174
+ ];
175
+ var versionManagerOf = (execPath) => {
176
+ const segments = execPath.split(/[/\\]/);
177
+ for (const segment of segments) {
178
+ const hit = MANAGER_SEGMENTS.find(([name]) => name === segment);
179
+ if (hit) return hit[1];
180
+ }
181
+ return null;
182
+ };
183
+ var describeVersionManagerPin = (execPath, manager) => `The background service is pinned to ${execPath}, which ${manager} manages. Switching or upgrading Node strands it; run pushary daemon install afterwards.`;
184
+ var describeServiceNodeRisk = (manager) => manager === "homebrew" ? "a Homebrew version folder; brew upgrade strands the service, and `pushary daemon install` repins it to the stable link" : `managed by ${manager}; a version switch strands the service`;
185
+
37
186
  // src/daemon-lifecycle.ts
38
- import { dirname, join, win32 as win32Path } from "path";
39
- import { existsSync, mkdirSync, readFileSync, realpathSync, renameSync, statSync, unlinkSync, writeFileSync } from "fs";
187
+ import { dirname as dirname2, join as join3, win32 as win32Path } from "path";
188
+ import { existsSync, mkdirSync as mkdirSync2, readFileSync as readFileSync2, realpathSync, renameSync, statSync, unlinkSync, writeFileSync } from "fs";
40
189
  import { createHash, randomUUID } from "crypto";
41
190
  import { homedir, uptime, userInfo } from "os";
42
191
  import { execFileSync } from "child_process";
@@ -55,7 +204,7 @@ var remoteProofIsFresh = (timestamp, now) => {
55
204
  };
56
205
  var daemonHasRemoteProof = (status, now = Date.now()) => status.kind === "running" && remoteProofIsFresh(status.lastSuccessfulHeartbeatAt, now) && remoteProofIsFresh(status.lastSuccessfulControlAt, now);
57
206
  var readServiceDefinitionFile = (path) => {
58
- const bytes = readFileSync(path);
207
+ const bytes = readFileSync2(path);
59
208
  const encoding = bytes.length >= 2 && bytes[0] === 255 && bytes[1] === 254 ? "utf16le" : "utf-8";
60
209
  return { contents: bytes.toString(encoding), encoding };
61
210
  };
@@ -105,9 +254,9 @@ var daemonServiceManagerAvailable = (options = {}) => {
105
254
  }
106
255
  };
107
256
  var DAEMON_STATE_FILE = "daemon-state.json";
108
- var statePath = (dir) => join(dir, DAEMON_STATE_FILE);
109
- var lockPath = (dir) => join(dir, "daemon.lock");
110
- var targetPath = (dir) => join(dir, "daemon-target.json");
257
+ var statePath = (dir) => join3(dir, DAEMON_STATE_FILE);
258
+ var lockPath = (dir) => join3(dir, "daemon.lock");
259
+ var targetPath = (dir) => join3(dir, "daemon-target.json");
111
260
  var DAEMON_LEASE_RENEW_INTERVAL_MS = 3e4;
112
261
  var LOCAL_LEASE_TIMEOUT_MS = DAEMON_LEASE_RENEW_INTERVAL_MS * 3;
113
262
  var DAEMON_YIELD_CHECK_INTERVAL_MS = 2e3;
@@ -117,28 +266,56 @@ var buildDaemonLaunch = (input) => input.siblingEntry ? { command: input.execPat
117
266
  shell: needsShell(input.daemonBinary, input.platform ?? process.platform)
118
267
  };
119
268
  var xml = (value) => value.replaceAll("&", "&amp;").replaceAll("<", "&lt;").replaceAll(">", "&gt;").replaceAll('"', "&quot;").replaceAll("'", "&apos;");
120
- var systemdQuote = (value) => `"${value.replaceAll("%", "%%").replaceAll("\\", "\\\\").replaceAll('"', '\\"')}"`;
269
+ var WINDOWS_TASK_NAME = "Pushary Daemon";
270
+ var POWERSHELL_SINGLE_QUOTES = /['\u2018\u2019\u201A\u201B]/g;
271
+ var powershellLiteral = (value) => `'${value.replace(POWERSHELL_SINGLE_QUOTES, (quote) => quote + quote)}'`;
272
+ var WQL_LIKE_SPECIALS = /[[%_]/g;
273
+ var wqlLikeLiteral = (value) => value.replace(WQL_LIKE_SPECIALS, (special) => `[${special}]`);
274
+ var WINDOWS_TASK_LOOKUP = `$task = @(Get-ScheduledTask -ErrorAction Stop) | Where-Object { $_.TaskName -eq ${powershellLiteral(WINDOWS_TASK_NAME)} -and $_.TaskPath -eq '\\' } | Select-Object -First 1; if ($null -eq $task) { exit 3 }`;
275
+ var POWERSHELL_HOSTS = ["powershell.exe", "pwsh.exe"];
276
+ var withoutTrailingSeparators = (path) => path.replace(/[\\/]+$/, "");
277
+ var POWERSHELL_STOP_ON_ERROR = "$ErrorActionPreference = 'Stop'";
278
+ var powershellCommandLineContains = (text) => `$_.CommandLine.ToUpperInvariant().Contains(${powershellLiteral(text)}.ToUpperInvariant())`;
279
+ var powershellCommandLineEndsWithLaunchFlag = `$_.CommandLine.TrimEnd().TrimEnd([char]34).EndsWith(${powershellLiteral(SUPERVISOR_LAUNCH_FLAG)})`;
280
+ var windowsSupervisorProcesses = (stateDir) => [
281
+ `@(Get-CimInstance -ClassName Win32_Process -Filter ${powershellLiteral(`CommandLine LIKE '%${wqlLikeLiteral(DAEMON_SUPERVISOR_SCRIPT)}%'`)}`,
282
+ `| Where-Object { $_.ProcessId -ne $PID -and ${POWERSHELL_HOSTS.map((host) => `$_.Name -ne ${powershellLiteral(host)}`).join(" -and ")}`,
283
+ `-and $null -ne $_.CommandLine -and ${powershellCommandLineContains(withoutTrailingSeparators(stateDir))} })`
284
+ ].join(" ");
285
+ var windowsRunningSupervisors = (stateDir) => `@(${windowsSupervisorProcesses(stateDir)} | Where-Object { -not (${powershellCommandLineEndsWithLaunchFlag}) })`;
286
+ var taskArgument = (value) => `&quot;${xml(value)}&quot;`;
287
+ var systemdQuotedEnvironment = (value) => `"${value.replaceAll("%", "%%").replaceAll("\\", "\\\\").replaceAll('"', '\\"')}"`;
288
+ var escapeSystemdSpecifiers = (value) => value.replaceAll("%", "%%");
289
+ var systemdQuotedWord = (escaped) => `"${escaped.replaceAll("\\", "\\\\").replaceAll('"', '\\"')}"`;
290
+ var systemdExecutableWord = (value) => systemdQuotedWord(escapeSystemdSpecifiers(value));
291
+ var systemdArgumentWord = (value) => systemdQuotedWord(escapeSystemdSpecifiers(value).replaceAll("$", "$$$$"));
292
+ var systemdExecLine = (executable, args) => [systemdExecutableWord(executable), ...args.map(systemdArgumentWord)].join(" ");
293
+ var ENTRY_PRESENT_CHECK = "process.exit(require('node:fs').existsSync(process.argv[1]) ? 0 : 1)";
294
+ var guardedLaunchdProgram = (input) => {
295
+ const guard = input.entryGuard ?? UNGUARDED;
296
+ return guard.kind === "guarded" ? [input.execPath, ENTRY_GUARD_PRELOAD_FLAG, guard.path, input.daemonEntry] : [input.execPath, input.daemonEntry];
297
+ };
121
298
  var buildDaemonService = (input) => {
122
299
  if (input.platform === "darwin") {
123
300
  if (!Number.isInteger(input.uid) || input.uid < 0) return null;
124
301
  const label = "com.pushary.daemon";
125
302
  const domain = `gui/${input.uid}`;
126
303
  const target = `${domain}/${label}`;
127
- const definitionPath = join(input.homeDir, "Library", "LaunchAgents", `${label}.plist`);
304
+ const definitionPath = join3(input.homeDir, "Library", "LaunchAgents", `${label}.plist`);
128
305
  const contents = `<?xml version="1.0" encoding="UTF-8"?>
129
306
  <!DOCTYPE plist PUBLIC "-//Apple//DTD PLIST 1.0//EN" "http://www.apple.com/DTDs/PropertyList-1.0.dtd">
130
307
  <plist version="1.0">
131
308
  <dict>
132
309
  <key>Label</key><string>${label}</string>
133
310
  <key>ProgramArguments</key>
134
- <array><string>${xml(input.execPath)}</string><string>${xml(input.daemonEntry)}</string></array>
311
+ <array>${guardedLaunchdProgram(input).map((argument) => `<string>${xml(argument)}</string>`).join("")}</array>
135
312
  <key>WorkingDirectory</key><string>${xml(input.homeDir)}</string>
136
313
  <key>EnvironmentVariables</key><dict><key>PATH</key><string>${xml(input.pathEnv)}</string></dict>
137
314
  <key>RunAtLoad</key><true/>
138
315
  <key>KeepAlive</key><dict><key>SuccessfulExit</key><false/></dict>
139
316
  <key>ThrottleInterval</key><integer>10</integer>
140
- <key>StandardOutPath</key><string>${xml(join(input.stateDir, "daemon.log"))}</string>
141
- <key>StandardErrorPath</key><string>${xml(join(input.stateDir, "daemon-error.log"))}</string>
317
+ <key>StandardOutPath</key><string>${xml(join3(input.stateDir, DAEMON_LOG_FILE))}</string>
318
+ <key>StandardErrorPath</key><string>${xml(join3(input.stateDir, DAEMON_ERROR_LOG_FILE))}</string>
142
319
  </dict>
143
320
  </plist>
144
321
  `;
@@ -157,6 +334,8 @@ var buildDaemonService = (input) => {
157
334
  disable: [{ command: "launchctl", args: ["disable", target] }],
158
335
  canDisableWhenUnregistered: true,
159
336
  uninstall: [{ command: "launchctl", args: ["bootout", domain, definitionPath], ignoreFailure: true }],
337
+ platform: input.platform,
338
+ startGuardPath: daemonEntryGuardPath(input.stateDir),
160
339
  registrationProbe: {
161
340
  command: "launchctl",
162
341
  args: ["print", target],
@@ -177,15 +356,17 @@ var buildDaemonService = (input) => {
177
356
  }
178
357
  if (input.platform === "linux") {
179
358
  const unit = "pushary-daemon.service";
180
- const definitionPath = join(input.homeDir, ".config", "systemd", "user", unit);
359
+ const definitionPath = join3(input.homeDir, ".config", "systemd", "user", unit);
181
360
  const contents = `[Unit]
182
361
  Description=Pushary phone-to-agent daemon
183
362
  After=network-online.target
363
+ ConditionPathExists=${escapeSystemdSpecifiers(input.daemonEntry)}
184
364
 
185
365
  [Service]
186
366
  Type=simple
187
- ExecStart=${systemdQuote(input.execPath)} ${systemdQuote(input.daemonEntry)}
188
- Environment=${systemdQuote(`PATH=${input.pathEnv}`)}
367
+ ExecCondition=${systemdExecLine(input.execPath, ["-e", ENTRY_PRESENT_CHECK, input.daemonEntry])}
368
+ ExecStart=${systemdExecLine(input.execPath, [input.daemonEntry])}
369
+ Environment=${systemdQuotedEnvironment(`PATH=${input.pathEnv}`)}
189
370
  Restart=on-failure
190
371
  RestartSec=10
191
372
  KillMode=process
@@ -216,18 +397,20 @@ WantedBy=default.target
216
397
  args: ["--user", "is-active", unit],
217
398
  negativeOutputPattern: /^(?:inactive|failed|unknown|activating|deactivating)\s*$/m
218
399
  },
219
- reloadAfterUninstall: { command: "systemctl", args: ["--user", "daemon-reload"] }
400
+ reloadAfterUninstall: { command: "systemctl", args: ["--user", "daemon-reload"] },
401
+ platform: input.platform,
402
+ startGuardPath: null
220
403
  };
221
404
  }
222
405
  if (input.platform === "win32") {
223
- const taskName = "Pushary Daemon";
406
+ const taskName = WINDOWS_TASK_NAME;
224
407
  const username = process.env.USERNAME?.trim() || userInfo().username;
225
408
  const domain = process.env.USERDOMAIN?.trim();
226
409
  const userId = input.userId?.trim() || (domain ? `${domain}\\${username}` : username);
227
410
  const definitionPath = win32Path.join(input.stateDir, "pushary-daemon-task.xml");
228
- const supervisorPath = win32Path.join(win32Path.dirname(input.daemonEntry), "pushary-daemon-supervisor.js");
411
+ const supervisorPath = win32Path.join(win32Path.dirname(input.daemonEntry), DAEMON_SUPERVISOR_SCRIPT);
229
412
  const supervised = (input.entryExists ?? existsSync)(supervisorPath);
230
- const args = supervised ? `&quot;${xml(supervisorPath)}&quot; &quot;${xml(input.daemonEntry)}&quot;` : `&quot;${xml(input.daemonEntry)}&quot;`;
413
+ const args = supervised ? [supervisorPath, ...supervisorTaskArguments(input.daemonEntry, withoutTrailingSeparators(input.stateDir))].map(taskArgument).join(" ") : taskArgument(input.daemonEntry);
231
414
  const contents = `\uFEFF<?xml version="1.0" encoding="UTF-16"?>
232
415
  <Task version="1.4" xmlns="http://schemas.microsoft.com/windows/2004/02/mit/task">
233
416
  <RegistrationInfo><Description>Pushary phone-to-agent daemon</Description></RegistrationInfo>
@@ -250,25 +433,41 @@ WantedBy=default.target
250
433
  </Actions>
251
434
  </Task>
252
435
  `;
436
+ const stopTaskAndSupervisors = [
437
+ { command: "schtasks.exe", args: ["/End", "/TN", taskName], ignoreFailure: true },
438
+ {
439
+ command: "powershell.exe",
440
+ args: [
441
+ "-NoProfile",
442
+ "-NonInteractive",
443
+ "-Command",
444
+ `${POWERSHELL_STOP_ON_ERROR}; ${windowsSupervisorProcesses(input.stateDir)} | ForEach-Object { Stop-Process -Id $_.ProcessId -Force -ErrorAction SilentlyContinue }`
445
+ ],
446
+ ignoreFailure: true
447
+ }
448
+ ];
253
449
  return {
254
450
  definitionPath,
255
451
  contents,
256
452
  encoding: "utf16le",
257
453
  install: [
454
+ ...stopTaskAndSupervisors,
258
455
  { command: "schtasks.exe", args: ["/Create", "/TN", taskName, "/XML", definitionPath, "/F"] },
259
456
  { command: "schtasks.exe", args: ["/Run", "/TN", taskName] }
260
457
  ],
261
458
  start: [{ command: "schtasks.exe", args: ["/Run", "/TN", taskName] }],
262
- stop: [{ command: "schtasks.exe", args: ["/End", "/TN", taskName], ignoreFailure: true }],
459
+ stop: stopTaskAndSupervisors,
263
460
  disable: [{ command: "schtasks.exe", args: ["/Change", "/TN", taskName, "/Disable"] }],
264
461
  uninstall: [{ command: "schtasks.exe", args: ["/Delete", "/TN", taskName, "/F"], ignoreFailure: true }],
462
+ platform: input.platform,
463
+ startGuardPath: null,
265
464
  registrationProbe: {
266
465
  command: "powershell.exe",
267
466
  args: [
268
467
  "-NoProfile",
269
468
  "-NonInteractive",
270
469
  "-Command",
271
- "$task = @(Get-ScheduledTask -ErrorAction Stop) | Where-Object { $_.TaskName -eq 'Pushary Daemon' -and $_.TaskPath -eq '\\' } | Select-Object -First 1; if ($null -eq $task) { exit 3 }"
470
+ WINDOWS_TASK_LOOKUP
272
471
  ],
273
472
  negativeExitCodes: [3]
274
473
  },
@@ -278,7 +477,7 @@ WantedBy=default.target
278
477
  "-NoProfile",
279
478
  "-NonInteractive",
280
479
  "-Command",
281
- "$task = @(Get-ScheduledTask -ErrorAction Stop) | Where-Object { $_.TaskName -eq 'Pushary Daemon' -and $_.TaskPath -eq '\\' } | Select-Object -First 1; if ($null -eq $task) { exit 3 }; if ($null -eq $task.Settings -or $null -eq $task.Settings.Enabled) { exit 5 }; if (-not $task.Settings.Enabled) { exit 4 }"
480
+ `${WINDOWS_TASK_LOOKUP}; if ($null -eq $task.Settings -or $null -eq $task.Settings.Enabled) { exit 5 }; if (-not $task.Settings.Enabled) { exit 4 }`
282
481
  ],
283
482
  negativeExitCodes: [3, 4]
284
483
  },
@@ -288,7 +487,7 @@ WantedBy=default.target
288
487
  "-NoProfile",
289
488
  "-NonInteractive",
290
489
  "-Command",
291
- "$task = @(Get-ScheduledTask -ErrorAction Stop) | Where-Object { $_.TaskName -eq 'Pushary Daemon' -and $_.TaskPath -eq '\\' } | Select-Object -First 1; if ($null -eq $task) { exit 3 }; if ($task.State -ne 'Running') { exit 4 }"
490
+ `${POWERSHELL_STOP_ON_ERROR}; if (${windowsRunningSupervisors(input.stateDir)}.Count -gt 0) { exit 0 }; ${WINDOWS_TASK_LOOKUP}; if ($task.State -ne 'Running') { exit 4 }`
292
491
  ],
293
492
  negativeExitCodes: [3, 4]
294
493
  }
@@ -297,7 +496,7 @@ WantedBy=default.target
297
496
  return null;
298
497
  };
299
498
  var WINDOWS_DAEMON_ENTRY_SEGMENTS = ["dist", "bin", "pushary-daemon.js"];
300
- var readTextFile = (path) => readFileSync(path, "utf8");
499
+ var readTextFile = (path) => readFileSync2(path, "utf8");
301
500
  var windowsPackageDaemonEntries = (globalPrefix) => {
302
501
  const root = globalRootFor(globalPrefix, "win32");
303
502
  return CLI_PACKAGE_NAMES.map((name) => win32Path.join(globalPackageFolder(root, name, "win32"), ...WINDOWS_DAEMON_ENTRY_SEGMENTS));
@@ -316,7 +515,8 @@ var serviceNodeFor = (execPath, exists) => {
316
515
  const linked = homebrewLinkedNodeFor(execPath);
317
516
  return linked !== null && exists(linked) ? linked : execPath;
318
517
  };
319
- var resolveDaemonServiceDefinition = (options = {}) => {
518
+ var serviceExecPathFor = (options) => serviceNodeFor(options.execPath ?? process.execPath, options.entryExists ?? existsSync);
519
+ var resolveDaemonServiceInput = (options) => {
320
520
  const platform = options.platform ?? process.platform;
321
521
  const exists = options.entryExists ?? existsSync;
322
522
  const globalBinary = options.globalBinary ?? resolveGlobalBinary("pushary-daemon");
@@ -333,18 +533,22 @@ var resolveDaemonServiceDefinition = (options = {}) => {
333
533
  }
334
534
  }
335
535
  if (!daemonEntry || !exists(daemonEntry)) return null;
336
- const homeDir = options.homeDir ?? homedir();
337
- return buildDaemonService({
536
+ return {
338
537
  platform,
339
- homeDir,
538
+ homeDir: options.homeDir ?? homedir(),
340
539
  stateDir: options.stateDir ?? pusharyDir(),
341
- execPath: serviceNodeFor(options.execPath ?? process.execPath, exists),
540
+ execPath: serviceExecPathFor(options),
342
541
  daemonEntry,
343
542
  pathEnv: options.pathEnv ?? process.env.PATH ?? "",
344
543
  uid: options.uid ?? process.getuid?.(),
345
544
  entryExists: exists
346
- });
545
+ };
546
+ };
547
+ var resolveDaemonServiceDefinition = (options = {}) => {
548
+ const input = resolveDaemonServiceInput(options);
549
+ return input ? buildDaemonService(input) : null;
347
550
  };
551
+ var daemonEntryGuardPathFor = (options = {}) => entryGuardApplies(options.platform ?? process.platform, serviceExecPathFor(options)) ? daemonEntryGuardPath(options.stateDir ?? pusharyDir()) : null;
348
552
  var runDaemonServiceSteps = (steps, run) => {
349
553
  for (const step of steps) {
350
554
  try {
@@ -409,7 +613,17 @@ var manageDaemonService = (action, options = {}) => {
409
613
  if (action === "uninstall" && !daemonServiceManagerAvailable(options)) {
410
614
  return { kind: "failed", detail: "Native background-service manager is unavailable" };
411
615
  }
412
- return applyDaemonService(action, definition, { run: options.run });
616
+ const applied = applyDaemonService(action, definition, { run: options.run });
617
+ return action === "uninstall" && applied.kind === "ok" ? removeEntryGuardOf(definition) : applied;
618
+ };
619
+ var removeEntryGuardOf = (definition) => {
620
+ if (!definition.startGuardPath) return { kind: "ok" };
621
+ try {
622
+ safeUnlink(definition.startGuardPath);
623
+ return { kind: "ok" };
624
+ } catch (err) {
625
+ return { kind: "failed", detail: `the background service is removed, but its start guard ${definition.startGuardPath} could not be: ${err instanceof Error ? err.message : String(err)}` };
626
+ }
413
627
  };
414
628
  var nominalDaemonService = (options) => buildDaemonService({
415
629
  platform: options.platform ?? process.platform,
@@ -431,7 +645,7 @@ var readInstalledDaemonService = (options = {}) => {
431
645
  try {
432
646
  return {
433
647
  path: definition.definitionPath,
434
- contents: readFileSync(definition.definitionPath, definition.encoding ?? "utf-8")
648
+ contents: readFileSync2(definition.definitionPath, definition.encoding ?? "utf-8")
435
649
  };
436
650
  } catch {
437
651
  return null;
@@ -595,7 +809,7 @@ var acquireDaemonLease = (options = {}) => {
595
809
  const instanceId = randomUUID();
596
810
  const startedAt = new Date(now()).toISOString();
597
811
  const writeLock = () => {
598
- mkdirSync(dir, { recursive: true });
812
+ mkdirSync2(dir, { recursive: true });
599
813
  writeFileSync(lockPath(dir), JSON.stringify({ instanceId, pid }), { flag: "wx", mode: 384 });
600
814
  };
601
815
  try {
@@ -619,7 +833,7 @@ var acquireDaemonLease = (options = {}) => {
619
833
  if (owner && ownerIsFromThisBoot && (options.isProcessAlive ?? processIsAlive)(owner.pid)) {
620
834
  return { kind: "unavailable", detail: "daemon owner is still running or starting" };
621
835
  }
622
- const stale = join(dir, `daemon.lock.${instanceId}.stale`);
836
+ const stale = join3(dir, `daemon.lock.${instanceId}.stale`);
623
837
  let ownsReplacement = false;
624
838
  try {
625
839
  renameSync(lockPath(dir), stale);
@@ -763,8 +977,16 @@ var stopDaemonRunning = async (options = {}) => {
763
977
  safeUnlink(lockPath(dir));
764
978
  return { kind: "stopped" };
765
979
  };
980
+ var writeEntryGuardForService = (input, options) => writeDaemonEntryGuard({
981
+ stateDir: input.stateDir,
982
+ platform: input.platform,
983
+ execPath: input.execPath,
984
+ warn: options.warn ?? ((message) => {
985
+ process.stderr.write(message);
986
+ })
987
+ });
766
988
  var DAEMON_LOGIN_REASONS = ["key_rejected", "plan_inactive", "key_missing", "mac_signed_out"];
767
- var needsLoginPath = (dir) => join(dir, "daemon-needs-login.json");
989
+ var needsLoginPath = (dir) => join3(dir, "daemon-needs-login.json");
768
990
  var isLoginReason = (value) => DAEMON_LOGIN_REASONS.includes(value);
769
991
  var parseDaemonNeedsLogin = (value) => {
770
992
  if (typeof value !== "object" || value === null) return null;
@@ -804,7 +1026,7 @@ var DAEMON_LOGIN_BLOCK_DESCRIPTIONS = {
804
1026
  var describeDaemonLoginBlock = (record) => DAEMON_LOGIN_BLOCK_DESCRIPTIONS[record.reason](record.at);
805
1027
  var recoverDaemonAfterLogin = (options = {}) => {
806
1028
  const cleared = clearDaemonNeedsLogin(options);
807
- if (!cleared || readControlMode(join(options.dir ?? pusharyDir(), "config.json")) === "off" || !hasDaemonServiceDefinition(options)) {
1029
+ if (!cleared || readControlMode(join3(options.dir ?? pusharyDir(), "config.json")) === "off" || !hasDaemonServiceDefinition(options)) {
808
1030
  return { cleared, restarted: false, detail: null };
809
1031
  }
810
1032
  const started = manageDaemonService("start", options);
@@ -878,12 +1100,26 @@ var probeDaemonServiceState = (definition, run) => {
878
1100
  }
879
1101
  };
880
1102
  var previousEncoding = (snapshot) => snapshot.previousEncoding ?? "utf-8";
1103
+ var launchdEntryGuardArguments = (guard) => `<string>${xml(ENTRY_GUARD_PRELOAD_FLAG)}</string><string>${xml(guard)}</string>`;
1104
+ var restorableContents = (definition, contents) => {
1105
+ const guard = definition.startGuardPath;
1106
+ if (!guard || contents === null || readServiceEntryGuard(contents, definition.platform) !== guard) {
1107
+ return { kind: "ready", contents };
1108
+ }
1109
+ const written = writeDaemonEntryGuardAt(guard);
1110
+ if (written.kind === "in-place") return { kind: "ready", contents };
1111
+ const unguarded = contents.replace(launchdEntryGuardArguments(guard), "");
1112
+ return readServiceEntryGuard(unguarded, definition.platform) === null ? { kind: "ready", contents: unguarded } : { kind: "failed", detail: `could not write the start guard ${guard} the previous service names (${written.detail}), or restore that service without it` };
1113
+ };
881
1114
  var restoreDaemonServiceSnapshot = (definition, snapshot, run) => {
1115
+ const restorable = restorableContents(definition, snapshot.previousContents);
1116
+ if (restorable.kind !== "ready") return restorable;
1117
+ const previousContents = restorable.contents;
882
1118
  const removed = applyDaemonService("uninstall", definition, { run });
883
1119
  if (removed.kind !== "ok") return removed;
884
1120
  try {
885
- if (snapshot.previousContents === null) safeUnlink(definition.definitionPath);
886
- else writeFileAtomic(definition.definitionPath, snapshot.previousContents, 384, previousEncoding(snapshot));
1121
+ if (previousContents === null) safeUnlink(definition.definitionPath);
1122
+ else writeFileAtomic(definition.definitionPath, previousContents, 384, previousEncoding(snapshot));
887
1123
  } catch (err) {
888
1124
  return {
889
1125
  kind: "failed",
@@ -892,7 +1128,7 @@ var restoreDaemonServiceSnapshot = (definition, snapshot, run) => {
892
1128
  }
893
1129
  if (!snapshot.previousRegistered) {
894
1130
  const reload = definition.reloadAfterUninstall;
895
- if (snapshot.previousContents !== null && reload) {
1131
+ if (previousContents !== null && reload) {
896
1132
  try {
897
1133
  run(reload.command, reload.args);
898
1134
  } catch (err) {
@@ -917,12 +1153,12 @@ var restoreDaemonServiceSnapshot = (definition, snapshot, run) => {
917
1153
  }
918
1154
  return { kind: "ok" };
919
1155
  }
920
- if (snapshot.previousContents === null) {
1156
+ if (previousContents === null) {
921
1157
  return { kind: "failed", detail: "the previous registered service had no recoverable definition" };
922
1158
  }
923
1159
  const restored = applyDaemonService("install", {
924
1160
  ...definition,
925
- contents: snapshot.previousContents,
1161
+ contents: previousContents,
926
1162
  encoding: previousEncoding(snapshot)
927
1163
  }, { run });
928
1164
  if (restored.kind !== "ok") return restored;
@@ -971,19 +1207,22 @@ var recoverDaemonServiceTransaction = (definition, path, run) => {
971
1207
  return { kind: "ok" };
972
1208
  };
973
1209
  var replaceDaemonService = async (options = {}) => {
974
- const definition = resolveDaemonServiceDefinition(options);
975
- if (!definition) {
1210
+ const input = resolveDaemonServiceInput(options);
1211
+ const unguarded = input ? buildDaemonService(input) : null;
1212
+ if (!input || !unguarded) {
976
1213
  return {
977
1214
  kind: "unavailable",
978
1215
  detail: "Could not find the globally installed daemon entry. Run Pushary setup again."
979
1216
  };
980
1217
  }
981
1218
  const run = options.run ?? runDaemonServiceCommand;
982
- const transactionPath = join(options.stateDir ?? options.dir ?? pusharyDir(), "daemon-service-transaction.json");
983
- const recovered = recoverDaemonServiceTransaction(definition, transactionPath, run);
1219
+ const transactionPath = join3(options.stateDir ?? options.dir ?? pusharyDir(), "daemon-service-transaction.json");
1220
+ const recovered = recoverDaemonServiceTransaction(unguarded, transactionPath, run);
984
1221
  if (recovered.kind !== "ok") {
985
1222
  return { kind: "failed", detail: `Could not recover interrupted service replacement: ${recovered.detail}` };
986
1223
  }
1224
+ const definition = buildDaemonService({ ...input, entryGuard: writeEntryGuardForService(input, options) });
1225
+ if (!definition) return { kind: "unavailable", detail: "Could not build the daemon service definition for this platform." };
987
1226
  let previousContents = null;
988
1227
  let previousDefinitionEncoding = "utf-8";
989
1228
  try {
@@ -1088,7 +1327,7 @@ var replaceDaemonService = async (options = {}) => {
1088
1327
  var launchInstalledDaemon = (options) => {
1089
1328
  const entryExists = options.entryExists ?? existsSync;
1090
1329
  const argvEntry = process.argv[1];
1091
- const candidate = options.daemonEntry !== void 0 ? options.daemonEntry : argvEntry ? join(dirname(argvEntry), "pushary-daemon.js") : null;
1330
+ const candidate = options.daemonEntry !== void 0 ? options.daemonEntry : argvEntry ? join3(dirname2(argvEntry), "pushary-daemon.js") : null;
1092
1331
  const siblingEntry = candidate && entryExists(candidate) ? candidate : null;
1093
1332
  const platform = options.platform ?? process.platform;
1094
1333
  const daemonBinary = options.daemonBinary ?? resolveGlobalBinary("pushary-daemon") ?? (platform === "win32" ? "pushary-daemon.cmd" : "pushary-daemon");
@@ -1163,6 +1402,11 @@ var waitForDaemonRemoteProof = async (options = {}) => {
1163
1402
  };
1164
1403
 
1165
1404
  export {
1405
+ readServiceExecPath,
1406
+ serviceStartFileChecks,
1407
+ versionManagerOf,
1408
+ describeVersionManagerPin,
1409
+ describeServiceNodeRisk,
1166
1410
  daemonIsServing,
1167
1411
  daemonProcessIsThere,
1168
1412
  DAEMON_COLD_START_TIMEOUT_MS,
@@ -1172,6 +1416,7 @@ export {
1172
1416
  DAEMON_YIELD_CHECK_INTERVAL_MS,
1173
1417
  xml,
1174
1418
  serviceNodeFor,
1419
+ daemonEntryGuardPathFor,
1175
1420
  parseDaemonAction,
1176
1421
  manageDaemonService,
1177
1422
  hasDaemonServiceDefinition,
@@ -1,6 +1,6 @@
1
1
  import {
2
2
  realpath
3
- } from "./chunk-EJHD44ZN.js";
3
+ } from "./chunk-NLJ2ILA7.js";
4
4
  import {
5
5
  findNativeClaudeInstall
6
6
  } from "./chunk-CYTPQDQY.js";
@@ -13,7 +13,7 @@ import {
13
13
  resolvePackageVersionFromBinary,
14
14
  resolvePathBinary,
15
15
  resolvePathBinaryAsync
16
- } from "./chunk-GS5FH3C2.js";
16
+ } from "./chunk-FYLYAVQG.js";
17
17
  import {
18
18
  MANAGED_PROVIDERS
19
19
  } from "./chunk-DL67HX3D.js";
@@ -7,10 +7,10 @@ import {
7
7
  codexHome,
8
8
  codexHooksJsonIn,
9
9
  isPusharyCodexCommand
10
- } from "./chunk-R7KC57PC.js";
10
+ } from "./chunk-TN5PGMH5.js";
11
11
  import {
12
12
  resolvePathBinary
13
- } from "./chunk-GS5FH3C2.js";
13
+ } from "./chunk-FYLYAVQG.js";
14
14
  import {
15
15
  getPackageVersion
16
16
  } from "./chunk-WIIMW5YO.js";