remote-pi-app 0.7.1

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 (159) hide show
  1. package/LICENSE +21 -0
  2. package/README.md +675 -0
  3. package/dist/actions/handlers.d.ts +138 -0
  4. package/dist/actions/handlers.js +189 -0
  5. package/dist/actions/handlers.js.map +1 -0
  6. package/dist/actions/registry.d.ts +39 -0
  7. package/dist/actions/registry.js +58 -0
  8. package/dist/actions/registry.js.map +1 -0
  9. package/dist/bin/supervisord.d.ts +2 -0
  10. package/dist/bin/supervisord.js +86 -0
  11. package/dist/bin/supervisord.js.map +1 -0
  12. package/dist/config.d.ts +62 -0
  13. package/dist/config.js +115 -0
  14. package/dist/config.js.map +1 -0
  15. package/dist/daemon/client.d.ts +20 -0
  16. package/dist/daemon/client.js +131 -0
  17. package/dist/daemon/client.js.map +1 -0
  18. package/dist/daemon/control_protocol.d.ts +176 -0
  19. package/dist/daemon/control_protocol.js +63 -0
  20. package/dist/daemon/control_protocol.js.map +1 -0
  21. package/dist/daemon/cron_log.d.ts +45 -0
  22. package/dist/daemon/cron_log.js +72 -0
  23. package/dist/daemon/cron_log.js.map +1 -0
  24. package/dist/daemon/cron_registry.d.ts +80 -0
  25. package/dist/daemon/cron_registry.js +194 -0
  26. package/dist/daemon/cron_registry.js.map +1 -0
  27. package/dist/daemon/id.d.ts +24 -0
  28. package/dist/daemon/id.js +36 -0
  29. package/dist/daemon/id.js.map +1 -0
  30. package/dist/daemon/install.d.ts +170 -0
  31. package/dist/daemon/install.js +547 -0
  32. package/dist/daemon/install.js.map +1 -0
  33. package/dist/daemon/registry.d.ts +63 -0
  34. package/dist/daemon/registry.js +153 -0
  35. package/dist/daemon/registry.js.map +1 -0
  36. package/dist/daemon/rpc_child.d.ts +194 -0
  37. package/dist/daemon/rpc_child.js +389 -0
  38. package/dist/daemon/rpc_child.js.map +1 -0
  39. package/dist/daemon/supervisor.d.ts +93 -0
  40. package/dist/daemon/supervisor.js +596 -0
  41. package/dist/daemon/supervisor.js.map +1 -0
  42. package/dist/extension_ui_bridge.d.ts +26 -0
  43. package/dist/extension_ui_bridge.js +341 -0
  44. package/dist/extension_ui_bridge.js.map +1 -0
  45. package/dist/index.d.ts +213 -0
  46. package/dist/index.js +5090 -0
  47. package/dist/index.js.map +1 -0
  48. package/dist/mcp/mesh_result.d.ts +10 -0
  49. package/dist/mcp/mesh_result.js +42 -0
  50. package/dist/mcp/mesh_result.js.map +1 -0
  51. package/dist/mcp/mesh_server.d.ts +16 -0
  52. package/dist/mcp/mesh_server.js +327 -0
  53. package/dist/mcp/mesh_server.js.map +1 -0
  54. package/dist/mesh/canonical.d.ts +30 -0
  55. package/dist/mesh/canonical.js +61 -0
  56. package/dist/mesh/canonical.js.map +1 -0
  57. package/dist/mesh/client.d.ts +18 -0
  58. package/dist/mesh/client.js +125 -0
  59. package/dist/mesh/client.js.map +1 -0
  60. package/dist/mesh/encoding.d.ts +38 -0
  61. package/dist/mesh/encoding.js +216 -0
  62. package/dist/mesh/encoding.js.map +1 -0
  63. package/dist/mesh/self_revoke.d.ts +73 -0
  64. package/dist/mesh/self_revoke.js +401 -0
  65. package/dist/mesh/self_revoke.js.map +1 -0
  66. package/dist/mesh/siblings.d.ts +49 -0
  67. package/dist/mesh/siblings.js +159 -0
  68. package/dist/mesh/siblings.js.map +1 -0
  69. package/dist/mesh/types.d.ts +34 -0
  70. package/dist/mesh/types.js +11 -0
  71. package/dist/mesh/types.js.map +1 -0
  72. package/dist/mesh/verify.d.ts +17 -0
  73. package/dist/mesh/verify.js +86 -0
  74. package/dist/mesh/verify.js.map +1 -0
  75. package/dist/pairing/crypto.d.ts +8 -0
  76. package/dist/pairing/crypto.js +22 -0
  77. package/dist/pairing/crypto.js.map +1 -0
  78. package/dist/pairing/qr.d.ts +59 -0
  79. package/dist/pairing/qr.js +125 -0
  80. package/dist/pairing/qr.js.map +1 -0
  81. package/dist/pairing/storage.d.ts +120 -0
  82. package/dist/pairing/storage.js +604 -0
  83. package/dist/pairing/storage.js.map +1 -0
  84. package/dist/protocol/codec.d.ts +7 -0
  85. package/dist/protocol/codec.js +53 -0
  86. package/dist/protocol/codec.js.map +1 -0
  87. package/dist/protocol/types.d.ts +432 -0
  88. package/dist/protocol/types.js +2 -0
  89. package/dist/protocol/types.js.map +1 -0
  90. package/dist/rooms.d.ts +29 -0
  91. package/dist/rooms.js +57 -0
  92. package/dist/rooms.js.map +1 -0
  93. package/dist/session/bridge.d.ts +37 -0
  94. package/dist/session/bridge.js +130 -0
  95. package/dist/session/bridge.js.map +1 -0
  96. package/dist/session/broker.d.ts +189 -0
  97. package/dist/session/broker.js +507 -0
  98. package/dist/session/broker.js.map +1 -0
  99. package/dist/session/broker_remote.d.ts +74 -0
  100. package/dist/session/broker_remote.js +583 -0
  101. package/dist/session/broker_remote.js.map +1 -0
  102. package/dist/session/cwd_lock.d.ts +33 -0
  103. package/dist/session/cwd_lock.js +126 -0
  104. package/dist/session/cwd_lock.js.map +1 -0
  105. package/dist/session/envelope.d.ts +33 -0
  106. package/dist/session/envelope.js +117 -0
  107. package/dist/session/envelope.js.map +1 -0
  108. package/dist/session/global_config.d.ts +33 -0
  109. package/dist/session/global_config.js +73 -0
  110. package/dist/session/global_config.js.map +1 -0
  111. package/dist/session/ipc.d.ts +27 -0
  112. package/dist/session/ipc.js +22 -0
  113. package/dist/session/ipc.js.map +1 -0
  114. package/dist/session/leader_election.d.ts +32 -0
  115. package/dist/session/leader_election.js +106 -0
  116. package/dist/session/leader_election.js.map +1 -0
  117. package/dist/session/local_config.d.ts +55 -0
  118. package/dist/session/local_config.js +157 -0
  119. package/dist/session/local_config.js.map +1 -0
  120. package/dist/session/mesh_node.d.ts +116 -0
  121. package/dist/session/mesh_node.js +573 -0
  122. package/dist/session/mesh_node.js.map +1 -0
  123. package/dist/session/peer.d.ts +139 -0
  124. package/dist/session/peer.js +451 -0
  125. package/dist/session/peer.js.map +1 -0
  126. package/dist/session/peer_inventory.d.ts +13 -0
  127. package/dist/session/peer_inventory.js +48 -0
  128. package/dist/session/peer_inventory.js.map +1 -0
  129. package/dist/session/peer_limits.d.ts +9 -0
  130. package/dist/session/peer_limits.js +21 -0
  131. package/dist/session/peer_limits.js.map +1 -0
  132. package/dist/session/setup_wizard.d.ts +39 -0
  133. package/dist/session/setup_wizard.js +63 -0
  134. package/dist/session/setup_wizard.js.map +1 -0
  135. package/dist/session/tools.d.ts +24 -0
  136. package/dist/session/tools.js +252 -0
  137. package/dist/session/tools.js.map +1 -0
  138. package/dist/session/wizard.d.ts +13 -0
  139. package/dist/session/wizard.js +20 -0
  140. package/dist/session/wizard.js.map +1 -0
  141. package/dist/transport/peer_channel.d.ts +37 -0
  142. package/dist/transport/peer_channel.js +98 -0
  143. package/dist/transport/peer_channel.js.map +1 -0
  144. package/dist/transport/pi_forward_client.d.ts +29 -0
  145. package/dist/transport/pi_forward_client.js +62 -0
  146. package/dist/transport/pi_forward_client.js.map +1 -0
  147. package/dist/transport/relay_client.d.ts +91 -0
  148. package/dist/transport/relay_client.js +206 -0
  149. package/dist/transport/relay_client.js.map +1 -0
  150. package/dist/ui/footer.d.ts +32 -0
  151. package/dist/ui/footer.js +34 -0
  152. package/dist/ui/footer.js.map +1 -0
  153. package/docs/daemon.md +289 -0
  154. package/package.json +90 -0
  155. package/service-templates/launchd.plist.template +35 -0
  156. package/service-templates/systemd.service.template +19 -0
  157. package/service-templates/task-launcher.vbs.template +10 -0
  158. package/service-templates/task-scheduler.xml.template +38 -0
  159. package/skills/agent-network/SKILL.md +310 -0
@@ -0,0 +1,547 @@
1
+ import { execFileSync } from "node:child_process";
2
+ import { chmodSync, existsSync, lstatSync, mkdirSync, readFileSync, readlinkSync, symlinkSync, unlinkSync, writeFileSync } from "node:fs";
3
+ import { delimiter } from "node:path";
4
+ import { homedir, platform, tmpdir, userInfo } from "node:os";
5
+ import { dirname, join, resolve } from "node:path";
6
+ import { fileURLToPath } from "node:url";
7
+ export function detectPlatform() {
8
+ switch (platform()) {
9
+ case "darwin": return "macos";
10
+ case "linux": return "linux";
11
+ case "win32": return "windows";
12
+ default: return "unsupported";
13
+ }
14
+ }
15
+ // ── Path resolution ────────────────────────────────────────────────────────
16
+ /**
17
+ * Absolute path to the supervisor's compiled entry. We resolve from
18
+ * `import.meta.url` (this file's location) since wherever the daemon
19
+ * module lives, `bin/supervisord.js` is a sibling of `daemon/` under
20
+ * `dist/`.
21
+ *
22
+ * After build: `dist/daemon/install.js` → `dist/bin/supervisord.js`.
23
+ * In dev (`tsx`): same path resolution still lands inside `src/`, which
24
+ * isn't directly runnable by `node` — dev install isn't expected.
25
+ */
26
+ export function findSupervisorScript() {
27
+ const here = fileURLToPath(import.meta.url); // dist/daemon/install.js
28
+ const daemonDir = dirname(here); // dist/daemon
29
+ const distRoot = dirname(daemonDir); // dist
30
+ return resolve(distRoot, "bin/supervisord.js");
31
+ }
32
+ /**
33
+ * Absolute path to the extension's CLI entry (`dist/index.js`). This is
34
+ * the file we symlink to `~/.local/bin/remote-pi` so the user can run
35
+ * `remote-pi <subcommand>` from any shell after installing the extension
36
+ * through Pi (`pi install npm:remote-pi`).
37
+ *
38
+ * Same resolution strategy as `findSupervisorScript`: from
39
+ * `dist/daemon/install.js` → `dist/index.js`.
40
+ */
41
+ export function findRemotePiScript() {
42
+ const here = fileURLToPath(import.meta.url); // dist/daemon/install.js
43
+ const daemonDir = dirname(here); // dist/daemon
44
+ const distRoot = dirname(daemonDir); // dist
45
+ return resolve(distRoot, "index.js");
46
+ }
47
+ export function findNodeBinary() {
48
+ // `process.execPath` is always absolute and points at the current Node
49
+ // binary. Embedding it in the service unit means the user gets the
50
+ // exact same Node version they invoked `remote-pi install` with — no
51
+ // PATH ambiguity at boot time.
52
+ return process.execPath;
53
+ }
54
+ export function findTemplate(name) {
55
+ // Templates ship next to the compiled `dist/` (via `files` in package.json).
56
+ // From `dist/daemon/install.js` go up two levels and into
57
+ // `service-templates/`. In the published npm tarball the layout is the
58
+ // same — `service-templates/` is sibling to `dist/`.
59
+ const here = fileURLToPath(import.meta.url); // dist/daemon/install.js
60
+ const pkgRoot = resolve(dirname(dirname(dirname(here)))); // package root
61
+ const file = name === "systemd" ? "systemd.service.template" :
62
+ name === "launchd" ? "launchd.plist.template" :
63
+ name === "vbs-launcher" ? "task-launcher.vbs.template" :
64
+ "task-scheduler.xml.template";
65
+ return resolve(pkgRoot, "service-templates", file);
66
+ }
67
+ // ── Service paths ──────────────────────────────────────────────────────────
68
+ export function systemdUnitPath() {
69
+ return join(homedir(), ".config", "systemd", "user", "remote-pi-supervisord.service");
70
+ }
71
+ export function launchdPlistPath() {
72
+ return join(homedir(), "Library", "LaunchAgents", "dev.remotepi.supervisord.plist");
73
+ }
74
+ export const LAUNCHD_LABEL = "dev.remotepi.supervisord";
75
+ /** systemd --user unit name (with `.service`) for the supervisor. */
76
+ export const SYSTEMD_UNIT = "remote-pi-supervisord.service";
77
+ /** Windows Task Scheduler task name (plan/40). */
78
+ export const WINDOWS_TASK_NAME = "RemotePiSupervisor";
79
+ /** Path of the rendered Task Scheduler XML (input to `schtasks /Create /XML`). */
80
+ export function taskXmlPath() {
81
+ return join(homedir(), ".pi", "remote", "RemotePiSupervisor.xml");
82
+ }
83
+ /**
84
+ * Path of the rendered VBScript launcher the Task Scheduler action invokes
85
+ * via `wscript.exe` (plan/40, Windows). Launching node through this hidden
86
+ * wrapper is what keeps the supervisor from flashing a console window.
87
+ */
88
+ export function vbsLauncherPath() {
89
+ return join(homedir(), ".pi", "remote", "RemotePiSupervisorLauncher.vbs");
90
+ }
91
+ /**
92
+ * Combined stdout/stderr log for the Windows supervisor. The Task Scheduler
93
+ * launches it hidden via wscript, so without this redirect its output (and the
94
+ * forwarded daemon-child stderr) would vanish — mirrors launchd/systemd, which
95
+ * already log to `~/.pi/remote/supervisord.log`.
96
+ */
97
+ export function supervisordLogPath() {
98
+ return join(homedir(), ".pi", "remote", "supervisord.log");
99
+ }
100
+ export function defaultRenderVars() {
101
+ return {
102
+ node: findNodeBinary(),
103
+ supervisor: findSupervisorScript(),
104
+ home: homedir(),
105
+ user: userInfo().username,
106
+ path: process.env["PATH"] ?? "/usr/local/bin:/usr/bin:/bin",
107
+ vbs: vbsLauncherPath(),
108
+ logPath: supervisordLogPath(),
109
+ };
110
+ }
111
+ /** Replace `{NODE}` / `{SUPERVISOR}` / `{USER}` / `{HOME}` / `{PATH}` / `{VBS}` / `{LOG}`. */
112
+ export function renderTemplate(template, vars) {
113
+ return template
114
+ .replace(/\{NODE\}/g, vars.node)
115
+ .replace(/\{SUPERVISOR\}/g, vars.supervisor)
116
+ .replace(/\{USER\}/g, vars.user)
117
+ .replace(/\{HOME\}/g, vars.home)
118
+ .replace(/\{PATH\}/g, vars.path)
119
+ .replace(/\{VBS\}/g, vars.vbs)
120
+ .replace(/\{LOG\}/g, vars.logPath);
121
+ }
122
+ /**
123
+ * Writes the unit/plist, runs the platform's activation command. Throws
124
+ * on unsupported OS or when the supervisor script isn't found.
125
+ *
126
+ * Idempotent: re-running re-writes the unit (paths could have changed)
127
+ * and re-activates via the platform tool's idempotent flag.
128
+ */
129
+ export function installService(vars = defaultRenderVars()) {
130
+ const plat = detectPlatform();
131
+ const log = [];
132
+ if (plat === "unsupported") {
133
+ throw new Error(`unsupported platform: ${platform()}. Only macOS, Linux, and Windows.`);
134
+ }
135
+ // Sanity: supervisor script must exist on disk.
136
+ if (!existsSync(vars.supervisor)) {
137
+ throw new Error(`supervisor script not found at ${vars.supervisor}. ` +
138
+ "Run `pnpm build` (dev) or `npm install -g remote-pi` (prod) first.");
139
+ }
140
+ const templateName = plat === "macos" ? "launchd" : plat === "linux" ? "systemd" : "taskscheduler";
141
+ const templatePath = findTemplate(templateName);
142
+ if (!existsSync(templatePath)) {
143
+ throw new Error(`service template missing: ${templatePath}`);
144
+ }
145
+ const tpl = readFileSync(templatePath, "utf8");
146
+ const rendered = renderTemplate(tpl, vars);
147
+ const unitPath = plat === "macos" ? launchdPlistPath() : plat === "linux" ? systemdUnitPath() : taskXmlPath();
148
+ mkdirSync(dirname(unitPath), { recursive: true });
149
+ if (plat === "windows") {
150
+ // `schtasks /Create /XML` requires UTF-16LE + BOM. A UTF-8 file fails with
151
+ // "(1,40)::ERROR: unable to switch the encoding" — the bytes must match the
152
+ // template's `encoding="UTF-16"` declaration. (plan/40 risk #5.)
153
+ const bom = Buffer.from([0xff, 0xfe]); // UTF-16LE byte-order mark
154
+ writeFileSync(unitPath, Buffer.concat([bom, Buffer.from(rendered, "utf16le")]));
155
+ }
156
+ else {
157
+ writeFileSync(unitPath, rendered); // launchd/systemd → UTF-8
158
+ }
159
+ log.push(`wrote ${unitPath}`);
160
+ if (plat === "macos") {
161
+ // Unload first in case a stale entry exists from a prior install —
162
+ // `launchctl bootstrap` errors out otherwise. `bootout` is the modern
163
+ // API; `unload` is the legacy fallback. Either may fail silently.
164
+ const uid = userInfo().uid;
165
+ _tryExec("launchctl", ["bootout", `gui/${uid}`, unitPath], log);
166
+ _tryExec("launchctl", ["unload", unitPath], log);
167
+ _exec("launchctl", ["bootstrap", `gui/${uid}`, unitPath], log);
168
+ log.push(`activated via launchctl bootstrap gui/${uid}`);
169
+ }
170
+ else if (plat === "linux") {
171
+ _exec("systemctl", ["--user", "daemon-reload"], log);
172
+ _exec("systemctl", ["--user", "enable", "--now", "remote-pi-supervisord.service"], log);
173
+ log.push("activated via systemctl --user enable --now");
174
+ }
175
+ else {
176
+ // windows — Task Scheduler (plan/40). The action runs `wscript.exe
177
+ // <launcher.vbs>` (not node directly) so the supervisor starts hidden,
178
+ // with no console window. Render + write that launcher first.
179
+ const vbsTpl = findTemplate("vbs-launcher");
180
+ if (!existsSync(vbsTpl))
181
+ throw new Error(`vbs launcher template missing: ${vbsTpl}`);
182
+ const vbsPath = vars.vbs;
183
+ writeFileSync(vbsPath, renderTemplate(readFileSync(vbsTpl, "utf8"), vars));
184
+ log.push(`wrote ${vbsPath}`);
185
+ // Only `schtasks /Create` modifies the root task store → that single op
186
+ // needs admin (elevate it via UAC). `/End` (stop a prior instance) and
187
+ // `/Run` (start it) act on a task we already own and work un-elevated — the
188
+ // very ops `remote-pi restart-supervisor` runs without elevation. Keeping
189
+ // them un-elevated narrows the admin surface to the one operation that
190
+ // truly requires it.
191
+ _tryExec("schtasks", ["/End", "/TN", WINDOWS_TASK_NAME], log);
192
+ _execElevatedWindows([
193
+ `schtasks /Create /XML "${unitPath}" /TN ${WINDOWS_TASK_NAME} /F`,
194
+ ], log);
195
+ _exec("schtasks", ["/Run", "/TN", WINDOWS_TASK_NAME], log);
196
+ log.push(`activated via schtasks /Create (elevated) + /Run (${WINDOWS_TASK_NAME})`);
197
+ }
198
+ return { platform: plat, unitPath, log };
199
+ }
200
+ export function uninstallService() {
201
+ const plat = detectPlatform();
202
+ const log = [];
203
+ if (plat === "unsupported") {
204
+ throw new Error(`unsupported platform: ${platform()}. Only macOS, Linux, and Windows.`);
205
+ }
206
+ const unitPath = plat === "macos" ? launchdPlistPath() : plat === "linux" ? systemdUnitPath() : taskXmlPath();
207
+ if (plat === "macos") {
208
+ const uid = userInfo().uid;
209
+ _tryExec("launchctl", ["bootout", `gui/${uid}`, unitPath], log);
210
+ _tryExec("launchctl", ["unload", unitPath], log);
211
+ log.push("deactivated via launchctl bootout");
212
+ }
213
+ else if (plat === "linux") {
214
+ _tryExec("systemctl", ["--user", "disable", "--now", "remote-pi-supervisord.service"], log);
215
+ log.push("deactivated via systemctl --user disable --now");
216
+ }
217
+ else {
218
+ // windows — Task Scheduler (plan/40): stop + delete the task. Only
219
+ // `/Delete` modifies the root task store → that's the op that needs admin.
220
+ // `/End` stops the running task and works un-elevated (own task), like
221
+ // restart-supervisor. `exit /b 0` keeps uninstall best-effort: a missing
222
+ // task (already removed) is success, not an error.
223
+ _tryExec("schtasks", ["/End", "/TN", WINDOWS_TASK_NAME], log);
224
+ _execElevatedWindows([
225
+ `schtasks /Delete /TN ${WINDOWS_TASK_NAME} /F`,
226
+ `exit /b 0`,
227
+ ], log);
228
+ log.push(`deactivated via elevated schtasks /Delete (${WINDOWS_TASK_NAME})`);
229
+ }
230
+ let removed = false;
231
+ if (existsSync(unitPath)) {
232
+ try {
233
+ unlinkSync(unitPath);
234
+ removed = true;
235
+ log.push(`removed ${unitPath}`);
236
+ }
237
+ catch (e) {
238
+ log.push(`failed to remove ${unitPath}: ${String(e)}`);
239
+ }
240
+ }
241
+ // Windows: also drop the hidden VBScript launcher we wrote alongside the XML.
242
+ if (plat === "windows") {
243
+ const vbsPath = vbsLauncherPath();
244
+ if (existsSync(vbsPath)) {
245
+ try {
246
+ unlinkSync(vbsPath);
247
+ log.push(`removed ${vbsPath}`);
248
+ }
249
+ catch (e) {
250
+ log.push(`failed to remove ${vbsPath}: ${String(e)}`);
251
+ }
252
+ }
253
+ }
254
+ if (plat === "linux") {
255
+ _tryExec("systemctl", ["--user", "daemon-reload"], log);
256
+ }
257
+ // Hint about the label for users that want to verify manually.
258
+ if (plat === "macos")
259
+ log.push(`(label: ${LAUNCHD_LABEL})`);
260
+ return { platform: plat, unitPath, removed, log };
261
+ }
262
+ // ── Internals ──────────────────────────────────────────────────────────────
263
+ function _exec(cmd, args, log) {
264
+ try {
265
+ const out = execFileSync(cmd, args, { encoding: "utf8", stdio: ["ignore", "pipe", "pipe"] });
266
+ if (out.trim())
267
+ log.push(`$ ${cmd} ${args.join(" ")}\n${out.trim()}`);
268
+ else
269
+ log.push(`$ ${cmd} ${args.join(" ")}`);
270
+ }
271
+ catch (e) {
272
+ const err = e;
273
+ const stderr = typeof err.stderr === "string" ? err.stderr : err.stderr?.toString() ?? "";
274
+ throw new Error(`\`${cmd} ${args.join(" ")}\` exited ${err.status ?? "?"}\n${stderr.trim() || err.message}`);
275
+ }
276
+ }
277
+ /** Like _exec but swallows errors — used for cleanup steps where failure
278
+ * is expected (e.g., "unload" before "load" when nothing was loaded). */
279
+ function _tryExec(cmd, args, log) {
280
+ try {
281
+ _exec(cmd, args, log);
282
+ }
283
+ catch { /* expected, suppress */ }
284
+ }
285
+ // ── Windows elevation (plan/40) ────────────────────────────────────────────
286
+ //
287
+ // `schtasks /Create` and `/Delete` register/remove the task in the root folder,
288
+ // which requires administrator rights. We can't elevate the current Node
289
+ // process, so we render the schtasks sequence into a temp `.cmd`, run it
290
+ // through an elevated `cmd.exe` via PowerShell `Start-Process -Verb RunAs`
291
+ // (one UAC prompt), and read the output back from a log file the script
292
+ // redirects into.
293
+ /**
294
+ * Build the batch script run elevated. Each command line redirects its output
295
+ * to `logFile` so the (separate, elevated) process's output can be read back by
296
+ * the parent. Control-flow lines (`if`/`exit`/`rem`/`@`) run bare — redirecting
297
+ * them would swallow the exit code. Pure + exported for tests.
298
+ */
299
+ export function buildElevatedCmd(lines, logFile) {
300
+ const redirect = ` >> "${logFile}" 2>&1`;
301
+ const body = lines.map((ln) => /^\s*(if|exit|rem|@)/i.test(ln) ? ln : ln + redirect);
302
+ return ["@echo off", ...body].join("\r\n") + "\r\n";
303
+ }
304
+ function _readIfExists(p) {
305
+ try {
306
+ return readFileSync(p, "utf8");
307
+ }
308
+ catch {
309
+ return "";
310
+ }
311
+ }
312
+ /**
313
+ * Run a schtasks command sequence elevated (UAC). Throws a clear error when the
314
+ * prompt is declined or the task operation fails (`Start-Process -Verb RunAs`
315
+ * throws → PowerShell exits non-zero → `execFileSync` throws). Captured schtasks
316
+ * output is appended to `log` either way.
317
+ */
318
+ function _execElevatedWindows(lines, log) {
319
+ const base = join(tmpdir(), `remote-pi-elevate-${process.pid}`);
320
+ const cmdPath = `${base}.cmd`;
321
+ const logFile = `${base}.log`;
322
+ writeFileSync(cmdPath, buildElevatedCmd(lines, logFile));
323
+ try {
324
+ unlinkSync(logFile);
325
+ }
326
+ catch { /* none yet */ }
327
+ let thrown = null;
328
+ try {
329
+ execFileSync("powershell", [
330
+ "-NoProfile", "-NonInteractive", "-Command",
331
+ `$p = Start-Process -FilePath cmd.exe -ArgumentList '/c','"${cmdPath}"' ` +
332
+ "-Verb RunAs -Wait -PassThru -WindowStyle Hidden; exit $p.ExitCode",
333
+ ], { stdio: ["ignore", "pipe", "pipe"] });
334
+ }
335
+ catch (e) {
336
+ thrown = e;
337
+ }
338
+ const out = _readIfExists(logFile).trim();
339
+ if (out)
340
+ log.push(out);
341
+ try {
342
+ unlinkSync(cmdPath);
343
+ }
344
+ catch { /* best-effort */ }
345
+ try {
346
+ unlinkSync(logFile);
347
+ }
348
+ catch { /* best-effort */ }
349
+ if (thrown) {
350
+ throw new Error("administrator privileges required — the UAC prompt was declined or the " +
351
+ "schtasks operation failed. Run the command again and accept the Windows " +
352
+ `elevation prompt.${out ? `\n${out}` : ""}`);
353
+ }
354
+ }
355
+ export function userLocalBinDir(home = homedir()) {
356
+ return join(home, ".local", "bin");
357
+ }
358
+ /**
359
+ * Check whether `dir` is on `process.env.PATH`. Tolerates trailing
360
+ * slashes and relative entries (which we treat as not matching — `~/.local/bin`
361
+ * is always absolute on our end).
362
+ */
363
+ export function isOnPath(dir, envPath = process.env["PATH"] ?? "") {
364
+ const target = dir.replace(/\/+$/, "");
365
+ return envPath.split(delimiter).some((entry) => entry.replace(/\/+$/, "") === target);
366
+ }
367
+ /**
368
+ * Create (or refresh) the `remote-pi` + `pi-supervisord` symlinks in
369
+ * `~/.local/bin/`. Idempotent — replaces stale links pointing at old
370
+ * extension paths (Pi can reinstall the extension to a different hash dir
371
+ * on upgrades, so this MUST overwrite).
372
+ *
373
+ * Returns `onPath: false` when `~/.local/bin` isn't in the user's `$PATH`.
374
+ * The caller is responsible for surfacing the shell-rc instruction —
375
+ * we don't edit the user's shell config files automatically.
376
+ */
377
+ export function linkCliBinaries(home = homedir(), paths = {}, opts = {}) {
378
+ const binDir = userLocalBinDir(home);
379
+ // Windows (plan/40): no POSIX symlinks. Installing via Pi (`pi install
380
+ // npm:remote-pi`) never reaches PATH, so write real `.cmd` shims into
381
+ // `~/.local/bin` and add that dir to the user's PATH (HKCU — no admin).
382
+ if (platform() === "win32") {
383
+ return _linkCliBinariesWindows(home, binDir, paths, opts);
384
+ }
385
+ const log = [];
386
+ mkdirSync(binDir, { recursive: true });
387
+ log.push(`ensured ${binDir}`);
388
+ const remotePi = paths.remotePi ?? findRemotePiScript();
389
+ const supervisord = paths.supervisord ?? findSupervisorScript();
390
+ if (!existsSync(remotePi)) {
391
+ throw new Error(`remote-pi script not found at ${remotePi}. ` +
392
+ "Run `pnpm build` (dev) or reinstall the extension.");
393
+ }
394
+ if (!existsSync(supervisord)) {
395
+ throw new Error(`supervisor script not found at ${supervisord}. ` +
396
+ "Run `pnpm build` (dev) or reinstall the extension.");
397
+ }
398
+ // tsc strips the executable bit on its outputs; the shebang at the top
399
+ // of dist/index.js means the file IS a valid interpreter target once
400
+ // chmod +x is applied. Same for supervisord.js (no shebang — we rely
401
+ // on `node` resolving via the symlink at exec time).
402
+ try {
403
+ chmodSync(remotePi, 0o755);
404
+ }
405
+ catch { /* best-effort */ }
406
+ try {
407
+ chmodSync(supervisord, 0o755);
408
+ }
409
+ catch { /* best-effort */ }
410
+ const links = [
411
+ { name: "remote-pi", path: join(binDir, "remote-pi"), target: remotePi },
412
+ { name: "pi-supervisord", path: join(binDir, "pi-supervisord"), target: supervisord },
413
+ ];
414
+ for (const link of links) {
415
+ _replaceSymlink(link.path, link.target, log);
416
+ }
417
+ const onPath = isOnPath(binDir);
418
+ if (!onPath) {
419
+ log.push(`WARNING: ${binDir} is not on $PATH. ` +
420
+ `Add this line to your shell rc (~/.zshrc, ~/.bashrc, etc.): ` +
421
+ `export PATH="$HOME/.local/bin:$PATH"`);
422
+ }
423
+ return { binDir, links, onPath, log };
424
+ }
425
+ /**
426
+ * Windows variant of `linkCliBinaries`: writes `remote-pi.cmd` +
427
+ * `pi-supervisord.cmd` shims into `~/.local/bin` and ensures that dir is on the
428
+ * user's PATH (User scope — no admin). `opts.node` overrides the node binary
429
+ * (tests); `opts.mutatePath === false` skips the real PATH mutation (tests).
430
+ */
431
+ function _linkCliBinariesWindows(home, binDir, paths, opts) {
432
+ void home;
433
+ const log = [];
434
+ mkdirSync(binDir, { recursive: true });
435
+ log.push(`ensured ${binDir}`);
436
+ const node = opts.node ?? findNodeBinary();
437
+ const remotePi = paths.remotePi ?? findRemotePiScript();
438
+ const supervisord = paths.supervisord ?? findSupervisorScript();
439
+ if (!existsSync(remotePi)) {
440
+ throw new Error(`remote-pi script not found at ${remotePi}. ` +
441
+ "Run `pnpm build` (dev) or reinstall the extension.");
442
+ }
443
+ if (!existsSync(supervisord)) {
444
+ throw new Error(`supervisor script not found at ${supervisord}. ` +
445
+ "Run `pnpm build` (dev) or reinstall the extension.");
446
+ }
447
+ const links = [
448
+ { name: "remote-pi.cmd", path: join(binDir, "remote-pi.cmd"), target: remotePi },
449
+ { name: "pi-supervisord.cmd", path: join(binDir, "pi-supervisord.cmd"), target: supervisord },
450
+ ];
451
+ for (const link of links) {
452
+ writeFileSync(link.path, buildCmdShim(node, link.target));
453
+ log.push(`wrote ${link.path}`);
454
+ }
455
+ const onPath = isOnPath(binDir);
456
+ if (!onPath && opts.mutatePath !== false) {
457
+ try {
458
+ _addUserPath(binDir);
459
+ log.push(`added ${binDir} to your user PATH — open a NEW terminal for \`remote-pi\` to resolve.`);
460
+ }
461
+ catch (e) {
462
+ log.push(`WARNING: ${binDir} is not on PATH and auto-add failed (${String(e)}). ` +
463
+ `Add it manually: setx PATH "%PATH%;${binDir}"`);
464
+ }
465
+ }
466
+ return { binDir, links, onPath, log };
467
+ }
468
+ /** A Windows `.cmd` shim that forwards all args to `node "<target>"`. Pure. */
469
+ export function buildCmdShim(node, target) {
470
+ return `@echo off\r\n"${node}" "${target}" %*\r\n`;
471
+ }
472
+ /**
473
+ * Append `dir` to the User-scope PATH via PowerShell (HKCU\Environment — no
474
+ * admin). Idempotent: skips when `dir` is already an exact PATH segment. Single-
475
+ * quoted PS literal (backslashes are literal in PS single quotes) with embedded
476
+ * `'` doubled.
477
+ */
478
+ function _addUserPath(dir) {
479
+ const lit = `'${dir.replace(/'/g, "''")}'`;
480
+ execFileSync("powershell", [
481
+ "-NoProfile", "-NonInteractive", "-Command",
482
+ `$d = ${lit}; ` +
483
+ "$p = [Environment]::GetEnvironmentVariable('Path','User'); " +
484
+ "if (-not $p) { $p = '' }; " +
485
+ "$parts = $p.Split(';') | Where-Object { $_ -ne '' }; " +
486
+ "if ($parts -notcontains $d) { " +
487
+ "[Environment]::SetEnvironmentVariable('Path', (($parts + $d) -join ';'), 'User') }",
488
+ ], { stdio: ["ignore", "pipe", "pipe"] });
489
+ }
490
+ export function unlinkCliBinaries(home = homedir()) {
491
+ const binDir = userLocalBinDir(home);
492
+ const log = [];
493
+ // Windows shims are `.cmd` files (linkCliBinaries writes those); POSIX uses
494
+ // extensionless symlinks. Match what was actually created on this platform.
495
+ const names = platform() === "win32"
496
+ ? ["remote-pi.cmd", "pi-supervisord.cmd"]
497
+ : ["remote-pi", "pi-supervisord"];
498
+ const removed = [];
499
+ for (const name of names) {
500
+ const path = join(binDir, name);
501
+ let existed = false;
502
+ try {
503
+ // lstatSync (not stat) so a symlink targeting a deleted file still
504
+ // resolves — we want to remove the LINK itself, not chase it.
505
+ lstatSync(path);
506
+ existed = true;
507
+ }
508
+ catch { /* not present */ }
509
+ if (existed) {
510
+ try {
511
+ unlinkSync(path);
512
+ log.push(`removed ${path}`);
513
+ }
514
+ catch (e) {
515
+ log.push(`failed to remove ${path}: ${String(e)}`);
516
+ existed = false;
517
+ }
518
+ }
519
+ removed.push({ name, path, existed });
520
+ }
521
+ return { binDir, removed, log };
522
+ }
523
+ /**
524
+ * Atomic-ish symlink replace. Idiomatic recipe — `symlinkSync` errors
525
+ * with `EEXIST` if the path is already a symlink/file, so we remove
526
+ * first. Race window between unlink and symlink is irrelevant for a
527
+ * single-user install command (no concurrent writers).
528
+ */
529
+ function _replaceSymlink(linkPath, target, log) {
530
+ let existing = null;
531
+ try {
532
+ existing = readlinkSync(linkPath);
533
+ }
534
+ catch { /* not a symlink, or doesn't exist */ }
535
+ if (existing === target) {
536
+ log.push(`symlink ${linkPath} → ${target} (unchanged)`);
537
+ return;
538
+ }
539
+ // Either it doesn't exist, or it points elsewhere. Remove + recreate.
540
+ try {
541
+ unlinkSync(linkPath);
542
+ }
543
+ catch { /* fine if absent */ }
544
+ symlinkSync(target, linkPath);
545
+ log.push(`symlink ${linkPath} → ${target}`);
546
+ }
547
+ //# sourceMappingURL=install.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"install.js","sourceRoot":"","sources":["../../src/daemon/install.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,63 @@
1
+ export interface DaemonEntry {
2
+ /** Absolute realpath of the cwd this daemon manages. */
3
+ cwd: string;
4
+ /**
5
+ * Display name (mesh `agent_name`). Persisted here because the supervisor
6
+ * now injects the daemon's config via `REMOTE_PI_DIRECT_CONFIG` at spawn
7
+ * instead of reading a per-cwd `.pi/remote-pi/config.json`. Legacy entries
8
+ * (cwd only) fall back to `defaultAgentName(cwd)`.
9
+ */
10
+ name?: string;
11
+ }
12
+ export interface DaemonRegistry {
13
+ daemons: DaemonEntry[];
14
+ }
15
+ /**
16
+ * Normalizes a user-provided path: expands `~`/`~/...`, resolves relative
17
+ * components against `process.cwd()`, and runs `realpath` to canonicalize
18
+ * symlinks. Throws if the resulting path doesn't exist on disk.
19
+ *
20
+ * `/remote-pi create` always stores normalized paths so two registrations
21
+ * of the same logical folder via different aliases produce a single entry.
22
+ */
23
+ export declare function normalizeCwd(input: string): string;
24
+ /** Reads the registry, returning an empty one when the file is absent. */
25
+ export declare function loadRegistry(): DaemonRegistry;
26
+ export declare function saveRegistry(reg: DaemonRegistry): void;
27
+ /**
28
+ * Adds a daemon entry. Refuses duplicates (same normalized cwd already
29
+ * present). Returns the derived id + normalized cwd so the caller can
30
+ * report it back to the user.
31
+ */
32
+ export declare function addDaemon(rawCwd: string, name?: string): {
33
+ id: string;
34
+ cwd: string;
35
+ name: string;
36
+ };
37
+ /**
38
+ * Removes the daemon entry whose derived id matches `id`. Returns the
39
+ * removed cwd (if any). Does NOT touch the cwd's local config — `create`
40
+ * the same cwd later restores the registration idempotently.
41
+ */
42
+ export declare function removeDaemon(id: string): {
43
+ removed: boolean;
44
+ cwd?: string;
45
+ };
46
+ /** Snapshot of all registered daemons with derived ids. Order matches the
47
+ * file's insertion order — first-registered first. */
48
+ export declare function listDaemons(): Array<{
49
+ id: string;
50
+ cwd: string;
51
+ name: string;
52
+ }>;
53
+ /**
54
+ * One-shot migration: backfill `name` (folder-derived) into legacy entries
55
+ * that predate the name field, persisting the change to `daemons.json`.
56
+ * Idempotent — writes only when something was missing. Returns how many
57
+ * entries were backfilled. The supervisor runs this on start.
58
+ */
59
+ export declare function migrateRegistryNames(): number;
60
+ /** Test/diag-only: returns the on-disk path. Exported so tests can poke
61
+ * at it (e.g. tmpdir override is done via env, but for now the path is
62
+ * hardcoded to ~/.pi/remote/daemons.json). */
63
+ export declare function registryPath(): string;